From c605f9762fec8fa9a77f12db87799492546ff257 Mon Sep 17 00:00:00 2001 From: Zhu Date: Thu, 18 Oct 2018 10:27:23 +0800 Subject: [PATCH] initial commit --- CommonAssemblyInfo.cs | 37 + CommonAssemblyInfo.cs.in | 37 + LICENSE | 425 + README | 48 + THANKYOU | 27 + THIRD_PARTY_README | 3605 ++++ TRADEMARK | 67 + awt/AssemblyInfo.cs | 41 + awt/AssemblyInfo.cs.in | 41 + awt/IKVM.AWT.WinForms.8.csproj | 161 + awt/IconFactory.cs | 683 + awt/ShellApi.cs | 562 + awt/awt.build | 95 + awt/composite.cs | 143 + awt/converter.cs | 402 + awt/fonts-0.95.cs | 557 + awt/graphics.cs | 2344 +++ awt/images.cs | 211 + awt/native.cs | 1038 + awt/printing.cs | 335 + awt/robot.cs | 404 + awt/theming.cs | 94 + awt/toolkit-0.95.cs | 5666 ++++++ bin-x64/README | 1 + bin-x86/README | 1 + bin/ikvm.exe.config | 7 + bin/ikvm.exe.manifest | 15 + bin/ikvmc.exe.config | 7 + bin/ikvmstub.exe.config | 7 + .../java/net/protocol/ikvmres/Handler.java | 329 + .../ikvm/extensions/ExtensionMethods.java | 565 + .../ikvm/internal/AssemblyClassLoader.java | 157 + classpath/ikvm/internal/CallerID.java | 139 + classpath/ikvm/internal/Formatter.java | 65 + classpath/ikvm/internal/JMath.java | 2661 +++ classpath/ikvm/internal/Library.java | 11 + .../ikvm/internal/LibraryVMInterface.java | 62 + classpath/ikvm/internal/MonoUtils.java | 52 + classpath/ikvm/internal/Util.java | 62 + classpath/ikvm/internal/WeakIdentityMap.java | 155 + classpath/ikvm/internal/__unspecified.java | 29 + classpath/ikvm/io/InputStreamWrapper.java | 239 + classpath/ikvm/lang/CIL.java | 55 + classpath/ikvm/lang/DllExport.java | 40 + classpath/ikvm/lang/Internal.java | 38 + classpath/ikvm/lang/IterableEnumerator.java | 69 + classpath/ikvm/lang/MapEnumerator.java | 70 + classpath/ikvm/lang/Property.java | 12 + .../runtime/AppDomainAssemblyClassLoader.java | 71 + .../runtime/ClassPathAssemblyClassLoader.java | 106 + classpath/ikvm/runtime/Delegates.java | 91 + .../ikvm/runtime/EnumerationWrapper.java | 55 + classpath/ikvm/runtime/Startup.java | 187 + classpath/ikvm/runtime/Util.java | 55 + .../util/concurrent/atomic/AtomicBoolean.java | 152 + .../util/concurrent/atomic/AtomicInteger.java | 314 + .../concurrent/atomic/AtomicIntegerArray.java | 315 + .../util/concurrent/atomic/AtomicLong.java | 322 + .../concurrent/atomic/AtomicLongArray.java | 314 + .../concurrent/atomic/AtomicReference.java | 225 + .../atomic/AtomicReferenceArray.java | 291 + .../util/concurrent/atomic/Striped64.java | 380 + classpath/sun/misc/Ref.java | 66 + ikvm.build | 122 + ikvm.include | 45 + ikvm/AssemblyInfo.cs | 33 + ikvm/ikvm.8.csproj | 94 + ikvm/ikvm.build | 44 + ikvm/starter.cs | 438 + ikvm9.sln | 77 + ikvmc.8.csproj | 161 + ikvmc/AotTypeWrapper.cs | 1296 ++ ikvmc/AssemblyInfo.cs | 32 + ikvmc/AssemblyResolver.cs | 474 + ikvmc/Compiler.cs | 1554 ++ ikvmc/CompilerClassLoader.cs | 4172 ++++ ikvmc/FakeTypes.cs | 118 + ikvmc/Proxy.cs | 457 + ikvmc/ikvmc.build | 88 + ikvmc/remapper.cs | 1833 ++ ikvmdoc/IKVMDoc.java | 847 + ikvmdoc/ikvmdoc.build | 45 + ikvmstub/AssemblyInfo.cs | 32 + ikvmstub/ikvmstub.8.csproj | 121 + ikvmstub/ikvmstub.build | 64 + ikvmstub/ikvmstub.cs | 615 + japi/japi-status.build | 75 + jvm/jvm.build | 62 + jvm/jvm.def | 5 + msbuild/AssemblyInfo.cs | 40 + msbuild/IKVM.MSBuild.Java.Targets | 31 + msbuild/IKVM.MSBuild.csproj | 52 + msbuild/JavaTask.cs | 532 + msbuild/msbuild.build | 43 + native/ikvm-native.rc | 30 + native/ikvm-native.rc.in | 30 + native/jni.c | 504 + native/jni.h | 406 + native/native.8.vcproj | 133 + native/native.9.vcproj | 132 + native/native.build | 76 + native/os.c | 100 + nuget/IKVM.nuspec.in | 16 + nuget/nupkg.build | 76 + openjdk/AssemblyInfo.java | 75 + openjdk/AssemblyInfo.java.in | 51 + openjdk/ExtensionAttribute.java | 39 + openjdk/FORKED | 108 + openjdk/GenerateSystemCore.cs | 44 + openjdk/MANIFEST.MF | 8 + openjdk/MANIFEST.MF.in | 8 + openjdk/allsources.lst | 16203 ++++++++++++++++ .../imageio/plugins/jpeg/JPEGImageReader.java | 145 + .../imageio/plugins/jpeg/JPEGImageWriter.java | 180 + .../sun/java/util/jar/pack/PackageReader.java | 2383 +++ openjdk/copyright.txt | 24 + openjdk/dependencies.txt | 151 + openjdk/exclude.lst | 6 + openjdk/gnu/java/awt/Buffers.java | 225 + .../gnu/java/awt/color/CieXyzConverter.java | 73 + .../java/awt/color/ClutProfileConverter.java | 152 + .../gnu/java/awt/color/ColorLookUpTable.java | 429 + .../java/awt/color/ColorSpaceConverter.java | 69 + .../java/awt/color/GrayProfileConverter.java | 137 + .../java/awt/color/GrayScaleConverter.java | 110 + openjdk/gnu/java/awt/color/ProfileHeader.java | 398 + .../java/awt/color/RgbProfileConverter.java | 244 + openjdk/gnu/java/awt/color/SrgbConverter.java | 152 + openjdk/gnu/java/awt/color/TagEntry.java | 121 + .../java/awt/color/ToneReproductionCurve.java | 177 + openjdk/gnu/java/util/EmptyEnumeration.java | 96 + .../security/action/GetPropertyAction.java | 89 + .../action/GetSecurityPropertyAction.java | 93 + .../security/action/SetAccessibleAction.java | 77 + .../com/sun/jmx/snmp/SnmpDataTypeEnums.java | 52 + .../rt/com/sun/jmx/snmp/SnmpDefinitions.java | 83 + .../icedtea/rt/com/sun/jmx/snmp/SnmpOid.java | 137 + .../rt/com/sun/jmx/snmp/SnmpOidRecord.java | 53 + .../rt/com/sun/jmx/snmp/SnmpOidTable.java | 53 + .../com/sun/jmx/snmp/SnmpOidTableSupport.java | 54 + .../rt/com/sun/jmx/snmp/SnmpParameters.java | 60 + .../rt/com/sun/jmx/snmp/SnmpPduPacket.java | 53 + .../icedtea/rt/com/sun/jmx/snmp/SnmpPeer.java | 73 + .../rt/com/sun/jmx/snmp/SnmpSession.java | 65 + .../rt/com/sun/jmx/snmp/SnmpTimeticks.java | 74 + .../rt/com/sun/jmx/snmp/SnmpVarBind.java | 74 + .../rt/com/sun/jmx/snmp/SnmpVarBindList.java | 82 + .../jmx/snmp/daemon/SnmpInformRequest.java | 42 + .../com/sun/jmx/snmp/daemon/SnmpSession.java | 66 + .../com/sun/media/sound/AbstractPlayer.java | 45 + .../sun/media/sound/AutoConnectSequencer.java | 50 + .../rt/com/sun/media/sound/DataPusher.java | 62 + .../sun/media/sound/DirectAudioDevice.java | 45 + .../sound/DirectAudioDeviceProvider.java | 45 + .../com/sun/media/sound/HeadspaceMixer.java | 44 + .../sun/media/sound/HeadspaceSoundbank.java | 45 + .../rt/com/sun/media/sound/JDK13Services.java | 50 + .../sun/media/sound/JavaSoundAudioClip.java | 68 + .../rt/com/sun/media/sound/MidiInDevice.java | 45 + .../sun/media/sound/MidiInDeviceProvider.java | 45 + .../rt/com/sun/media/sound/MidiOutDevice.java | 44 + .../media/sound/MidiOutDeviceProvider.java | 45 + .../rt/com/sun/media/sound/MidiUtils.java | 59 + .../rt/com/sun/media/sound/MixerClip.java | 44 + .../com/sun/media/sound/MixerMidiChannel.java | 45 + .../com/sun/media/sound/MixerSequencer.java | 45 + .../com/sun/media/sound/MixerSourceLine.java | 44 + .../rt/com/sun/media/sound/MixerSynth.java | 45 + .../rt/com/sun/media/sound/MixerThread.java | 44 + .../rt/com/sun/media/sound/Platform.java | 45 + .../rt/com/sun/media/sound/PortMixer.java | 45 + .../sun/media/sound/PortMixerProvider.java | 45 + .../media/sound/ReferenceCountingDevice.java | 57 + .../sun/media/sound/SimpleInputDevice.java | 44 + .../sound/SimpleInputDeviceProvider.java | 45 + .../rt/com/sun/media/sound/Toolkit.java | 50 + openjdk/ikvm/awt/IkvmToolkit.java | 48 + .../internal/AnnotationAttributeBase.java | 726 + openjdk/ikvm/internal/FieldReflectorBase.java | 35 + .../internal/InterlockedCompareAndSet.java | 37 + .../IntrinsicAtomicReferenceFieldUpdater.java | 62 + .../ikvm/internal/IntrinsicThreadLocal.java | 41 + openjdk/ikvm/internal/JNI.java | 114 + .../ikvm/internal/NotYetImplementedError.java | 37 + openjdk/ikvm/internal/Serialization.java | 47 + openjdk/ikvm/internal/Winsock.java | 982 + openjdk/java/awt/Font.java | 2640 +++ openjdk/java/awt/GraphicsConfiguration.java | 452 + openjdk/java/awt/Image.java | 354 + openjdk/java/awt/color/ICC_ColorSpace.java | 295 + openjdk/java/awt/image/AffineTransformOp.java | 608 + openjdk/java/awt/image/BandCombineOp.java | 218 + openjdk/java/awt/image/BufferedImage.java | 1811 ++ openjdk/java/awt/image/ColorConvertOp.java | 537 + openjdk/java/awt/image/ConvolveOp.java | 380 + openjdk/java/awt/image/DataBuffer.java | 562 + openjdk/java/awt/image/DataBufferByte.java | 288 + openjdk/java/awt/image/DataBufferDouble.java | 409 + openjdk/java/awt/image/DataBufferFloat.java | 412 + openjdk/java/awt/image/DataBufferInt.java | 286 + openjdk/java/awt/image/DataBufferShort.java | 285 + openjdk/java/awt/image/DataBufferUShort.java | 320 + openjdk/java/awt/image/IndexColorModel.java | 1528 ++ openjdk/java/awt/image/LookupOp.java | 307 + openjdk/java/awt/image/RescaleOp.java | 385 + openjdk/java/io/DefaultFileSystem.java | 35 + openjdk/java/io/FileDescriptor.java | 781 + openjdk/java/io/InteropObjectInputStream.java | 740 + .../java/io/InteropObjectOutputStream.java | 738 + openjdk/java/io/ObjectStreamClass.java | 2361 +++ openjdk/java/io/ObjectStreamField.java | 337 + openjdk/java/lang/Class.java | 3646 ++++ openjdk/java/lang/ClassLoader.java | 2240 +++ openjdk/java/lang/ClassLoaderHelper.java | 50 + .../java/lang/ClassSerializationProxy.java | 85 + openjdk/java/lang/Enum.java | 294 + openjdk/java/lang/LangHelper.java | 88 + openjdk/java/lang/ProcessImpl.java | 834 + openjdk/java/lang/PropertyConstants.java | 33 + openjdk/java/lang/PropertyConstants.java.in | 33 + openjdk/java/lang/Shutdown.java | 284 + openjdk/java/lang/StringHelper.java | 2727 +++ openjdk/java/lang/System.java | 1222 ++ openjdk/java/lang/Thread.java | 2593 +++ openjdk/java/lang/ThrowableHelper.java | 345 + openjdk/java/lang/VMSystemProperties.java | 469 + .../lang/invoke/LightWeightMethodHandle.java | 47 + .../lang/management/PlatformComponent.java | 408 + openjdk/java/lang/ref/Reference.java | 137 + openjdk/java/lang/ref/ReferenceQueue.java | 208 + openjdk/java/lang/ref/SoftReference.java | 133 + openjdk/java/lang/reflect/Constructor.java | 562 + openjdk/java/lang/reflect/Executable.java | 720 + openjdk/java/lang/reflect/Field.java | 1174 ++ openjdk/java/lang/reflect/Method.java | 630 + openjdk/java/lang/reflect/Proxy.java | 843 + .../net/DefaultDatagramSocketImplFactory.java | 151 + .../net/DualStackPlainDatagramSocketImpl.java | 335 + .../DualStackPlainDatagramSocketImpl_c.java | 489 + .../java/net/DualStackPlainSocketImpl.java | 361 + .../java/net/DualStackPlainSocketImpl_c.java | 491 + openjdk/java/net/PlainSocketImpl.java | 359 + openjdk/java/net/SocketUtil.java | 190 + .../net/TwoStacksPlainDatagramSocketImpl.java | 277 + .../TwoStacksPlainDatagramSocketImpl_c.java | 2466 +++ .../java/net/TwoStacksPlainSocketImpl.java | 285 + .../java/net/TwoStacksPlainSocketImpl_c.java | 1083 ++ openjdk/java/net/net_util_md.java | 889 + openjdk/java/nio/Bits.java | 850 + openjdk/java/security/AccessController.java | 960 + openjdk/java/security/ProtectionDomain.java | 532 + .../locks/AbstractQueuedSynchronizer.java | 2285 +++ .../util/concurrent/locks/LockSupport.java | 456 + openjdk/java/util/zip/Adler32.java | 212 + openjdk/java/util/zip/CRC32.java | 139 + openjdk/java/util/zip/ClassStubZipEntry.java | 98 + openjdk/java/util/zip/Deflater.java | 569 + openjdk/java/util/zip/DeflaterConstants.java | 78 + openjdk/java/util/zip/DeflaterEngine.java | 692 + openjdk/java/util/zip/DeflaterHuffman.java | 776 + openjdk/java/util/zip/DeflaterPending.java | 54 + openjdk/java/util/zip/Inflater.java | 727 + openjdk/java/util/zip/InflaterDynHeader.java | 203 + .../java/util/zip/InflaterHuffmanTree.java | 220 + openjdk/java/util/zip/OutputWindow.java | 178 + openjdk/java/util/zip/PendingBuffer.java | 200 + openjdk/java/util/zip/StreamManipulator.java | 216 + openjdk/java/util/zip/ZipEntry.java | 577 + openjdk/java/util/zip/ZipFile.java | 908 + openjdk/map.xml | 3153 +++ openjdk/openjdk.build | 465 + .../META-INF/services/java.sql.Driver | 1 + .../services/sun.java2d.pipe.RenderingEngine | 2 + openjdk/resources/nashorn/version.properties | 2 + .../resources/nashorn/version.properties.in | 2 + openjdk/response.txt | 1622 ++ openjdk/security.xml | 52 + openjdk/sun/awt/DebugSettings.java | 30 + openjdk/sun/awt/EmbeddedFrame.java | 544 + openjdk/sun/awt/IkvmDataTransferer.java | 566 + openjdk/sun/awt/Win32FontManager.java | 30 + openjdk/sun/awt/X11FontManager.java | 30 + .../sun/awt/image/ByteInterleavedRaster.java | 1331 ++ openjdk/sun/awt/image/GifImageDecoder.java | 38 + openjdk/sun/awt/image/IkvmImageDecoder.java | 150 + .../sun/awt/image/ImageRepresentation.java | 421 + openjdk/sun/awt/image/ImagingLib.java | 67 + .../awt/image/IntegerInterleavedRaster.java | 573 + openjdk/sun/awt/image/JPEGImageDecoder.java | 38 + openjdk/sun/awt/image/SunWritableRaster.java | 139 + openjdk/sun/awt/image/ToolkitImage.java | 325 + openjdk/sun/awt/shell/Win32ShellFolder2.java | 1160 ++ .../awt/shell/Win32ShellFolderManager2.java | 514 + openjdk/sun/awt/windows/WPrinterJob.java | 126 + openjdk/sun/font/CompositeFont.java | 152 + openjdk/sun/font/Font2D.java | 221 + openjdk/sun/font/FontManager.java | 415 + openjdk/sun/font/GlyphLayout.java | 76 + openjdk/sun/font/PhysicalFont.java | 299 + openjdk/sun/font/PhysicalStrike.java | 223 + openjdk/sun/font/StandardGlyphVector.java | 511 + openjdk/sun/font/StrikeCache.java | 317 + openjdk/sun/font/SunFontManager.java | 443 + openjdk/sun/font/TrueTypeFont.java | 44 + .../java2d/HeadlessGraphicsEnvironment.java | 168 + openjdk/sun/java2d/SunCompositeContext.java | 316 + openjdk/sun/java2d/SunGraphics2D.java | 130 + .../sun/java2d/SunGraphicsEnvironment.java | 106 + openjdk/sun/java2d/SurfaceData.java | 41 + openjdk/sun/java2d/cmm/lcms/LCMS.java | 180 + openjdk/sun/java2d/loops/TransformHelper.java | 27 + .../sun/java2d/pipe/ShapeSpanIterator.java | 82 + .../jdbc/odbc/JdbcOdbcCallableStatement.java | 662 + openjdk/sun/jdbc/odbc/JdbcOdbcConnection.java | 490 + .../sun/jdbc/odbc/JdbcOdbcDTResultSet.java | 287 + .../odbc/JdbcOdbcDTResultSetMetaData.java | 180 + .../jdbc/odbc/JdbcOdbcDatabaseMetaData.java | 1211 ++ openjdk/sun/jdbc/odbc/JdbcOdbcDriver.java | 111 + openjdk/sun/jdbc/odbc/JdbcOdbcObject.java | 650 + .../jdbc/odbc/JdbcOdbcPreparedStatement.java | 387 + openjdk/sun/jdbc/odbc/JdbcOdbcResultSet.java | 799 + .../jdbc/odbc/JdbcOdbcResultSetMetaData.java | 269 + openjdk/sun/jdbc/odbc/JdbcOdbcStatement.java | 386 + .../odbc/JdbcOdbcUpdateableResultSet.java | 165 + openjdk/sun/jdbc/odbc/JdbcOdbcUtils.java | 372 + .../management/ManagementFactoryHelper.java | 324 + openjdk/sun/management/VMManagementImpl.java | 291 + openjdk/sun/misc/FileURLMapper.java | 99 + openjdk/sun/misc/MiscHelper.java | 59 + openjdk/sun/misc/OSEnvironment.java | 32 + openjdk/sun/misc/SharedSecrets.java | 160 + openjdk/sun/misc/Unsafe.java | 1270 ++ openjdk/sun/misc/VM.java | 402 + openjdk/sun/misc/Version.java | 345 + .../net/dns/ResolverConfigurationImpl.java | 223 + openjdk/sun/net/sdp/SdpSupport.java | 55 + .../www/protocol/file/FileURLConnection.java | 238 + .../sun/net/www/protocol/file/Handler.java | 160 + .../sun/net/www/protocol/ikvmres/Handler.java | 29 + .../net/www/protocol/jar/JarFileFactory.java | 184 + openjdk/sun/nio/ch/DatagramChannelImpl.java | 1143 ++ .../sun/nio/ch/DefaultSelectorProvider.java | 55 + openjdk/sun/nio/ch/DotNetSelectorImpl.java | 324 + openjdk/sun/nio/ch/FileChannelImpl.java | 1145 ++ openjdk/sun/nio/ch/FileDispatcherImpl.java | 306 + openjdk/sun/nio/ch/FileKey.java | 57 + openjdk/sun/nio/ch/IOUtil.java | 178 + openjdk/sun/nio/ch/Iocp.java | 140 + openjdk/sun/nio/ch/NativeDispatcher.java | 64 + openjdk/sun/nio/ch/Net.java | 616 + openjdk/sun/nio/ch/SelectionKeyImpl.java | 118 + openjdk/sun/nio/ch/SocketDispatcher.java | 121 + openjdk/sun/nio/ch/SocketOptionRegistry.java | 86 + openjdk/sun/nio/ch/Util.java | 200 + .../WindowsAsynchronousFileChannelImpl.java | 687 + ...wsAsynchronousServerSocketChannelImpl.java | 320 + .../WindowsAsynchronousSocketChannelImpl.java | 842 + openjdk/sun/nio/cs/StandardCharsets.java | 715 + .../sun/nio/fs/DefaultFileSystemProvider.java | 35 + .../sun/nio/fs/DefaultFileTypeDetector.java | 41 + openjdk/sun/nio/fs/NetFileSystem.java | 498 + openjdk/sun/nio/fs/NetFileSystemProvider.java | 1467 ++ openjdk/sun/nio/fs/NetPath.java | 569 + openjdk/sun/nio/fs/UnixUriUtils.java | 228 + openjdk/sun/nio/fs/WindowsUriSupport.java | 167 + openjdk/sun/print/PrintPeer.java | 42 + openjdk/sun/print/UnixPrintServiceLookup.java | 33 + openjdk/sun/print/Win32PrintJob.java | 1126 ++ openjdk/sun/print/Win32PrintService.java | 920 + .../sun/print/Win32PrintServiceLookup.java | 264 + openjdk/sun/reflect/MethodAccessor.java | 40 + openjdk/sun/reflect/Reflection.java | 372 + openjdk/sun/reflect/ReflectionFactory.java | 318 + .../reflect/annotation/AnnotationType.java | 224 + .../jgss/wrapper/NativeGSSFactory.java | 75 + .../jgss/wrapper/SunNativeProvider.java | 40 + openjdk/swingawt.xml | 41 + openjdk/tools.rsp | 206 + reflect/AmbiguousMatchException.cs | 54 + reflect/Assembly.cs | 264 + reflect/AssemblyName.cs | 538 + reflect/BadImageFormatException.cs | 54 + reflect/Binder.cs | 403 + reflect/ConstructorInfo.cs | 239 + reflect/CustomAttributeData.cs | 1022 + reflect/CustomAttributeNamedArgument.cs | 81 + reflect/CustomAttributeTypedArgument.cs | 71 + reflect/CustomModifiers.cs | 357 + reflect/Emit/AssemblyBuilder.cs | 841 + reflect/Emit/ConstructorBuilder.cs | 143 + reflect/Emit/CustomAttributeBuilder.cs | 752 + reflect/Emit/CustomModifiersBuilder.cs | 75 + reflect/Emit/EnumBuilder.cs | 119 + reflect/Emit/Enums.cs | 129 + reflect/Emit/EventBuilder.cs | 280 + reflect/Emit/ExceptionHandler.cs | 121 + reflect/Emit/FieldBuilder.cs | 225 + reflect/Emit/ILGenerator.cs | 1150 ++ reflect/Emit/MethodBuilder.cs | 782 + reflect/Emit/ModuleBuilder.cs | 2019 ++ reflect/Emit/OpCode.cs | 288 + reflect/Emit/OpCodes.cs | 749 + reflect/Emit/ParameterBuilder.cs | 141 + reflect/Emit/PropertyBuilder.cs | 287 + reflect/Emit/SignatureHelper.cs | 317 + reflect/Emit/Tokens.cs | 271 + reflect/Emit/TypeBuilder.cs | 1208 ++ reflect/Enums.cs | 325 + reflect/EventInfo.cs | 252 + reflect/ExceptionHandlingClause.cs | 94 + reflect/FieldInfo.cs | 304 + reflect/FieldSignature.cs | 98 + reflect/Fusion.cs | 810 + reflect/GenericWrappers.cs | 694 + reflect/IKVM.Reflection.csproj | 148 + reflect/Impl/ITypeOwner.cs | 32 + reflect/Impl/MdbWriter.cs | 238 + reflect/Impl/PdbWriter.cs | 1193 ++ reflect/Impl/SymbolSupport.cs | 103 + reflect/InterfaceMapping.cs | 35 + reflect/LocalVariableInfo.cs | 73 + reflect/ManifestResourceInfo.cs | 113 + reflect/MarshalSpec.cs | 259 + reflect/MemberInfo.cs | 135 + reflect/Metadata/CliHeader.cs | 99 + reflect/Metadata/MetadataRW.cs | 101 + reflect/Metadata/Tables.cs | 2722 +++ reflect/MethodBase.cs | 168 + reflect/MethodBody.cs | 163 + reflect/MethodImplMap.cs | 36 + reflect/MethodInfo.cs | 392 + reflect/MethodSignature.cs | 505 + reflect/Missing.cs | 1254 ++ reflect/Module.cs | 726 + reflect/ParameterInfo.cs | 189 + reflect/ParameterModifier.cs | 45 + reflect/Projection.cs | 602 + reflect/Properties/AssemblyInfo.cs | 27 + reflect/PropertyInfo.cs | 355 + reflect/PropertySignature.cs | 186 + reflect/Reader/AssemblyReader.cs | 330 + reflect/Reader/Authenticode.cs | 185 + reflect/Reader/ByteReader.cs | 217 + reflect/Reader/EventInfoImpl.cs | 166 + reflect/Reader/Field.cs | 136 + reflect/Reader/GenericTypeParameter.cs | 380 + reflect/Reader/MetadataReader.cs | 406 + reflect/Reader/Method.cs | 394 + reflect/Reader/ModuleReader.cs | 1304 ++ reflect/Reader/PEReader.cs | 349 + reflect/Reader/PropertyInfoImpl.cs | 179 + reflect/Reader/ResourceModule.cs | 107 + reflect/Reader/TypeDefImpl.cs | 377 + reflect/Signature.cs | 596 + reflect/StandAloneMethodSig.cs | 130 + reflect/StrongNameKeyPair.cs | 140 + reflect/Type.cs | 3266 ++++ reflect/TypeInfo.cs | 163 + reflect/TypeNameParser.cs | 625 + reflect/Universe.cs | 1249 ++ reflect/Util.cs | 266 + reflect/Writer/ByteBuffer.cs | 352 + reflect/Writer/Heaps.cs | 395 + reflect/Writer/MetadataWriter.cs | 575 + reflect/Writer/ModuleWriter.cs | 463 + reflect/Writer/PEWriter.cs | 287 + reflect/Writer/ResourceSection.cs | 411 + reflect/Writer/TextSection.cs | 921 + reflect/Writer/VersionInfo.cs | 282 + reflect/coreclr.cs | 70 + reflect/reflect.build | 161 + runtime/AssemblyClassLoader.cs | 1347 ++ runtime/AssemblyInfo.cs | 57 + runtime/AssemblyInfo.cs.in | 57 + runtime/Assertions.cs | 177 + runtime/BigEndianBinaryReader.cs | 242 + runtime/Boxer.cs | 212 + runtime/ByteCode.cs | 815 + runtime/ByteCodeHelper.cs | 1265 ++ runtime/ClassFile.cs | 4005 ++++ runtime/ClassLoaderWrapper.cs | 1652 ++ runtime/CodeEmitter.cs | 3018 +++ runtime/CoreClasses.cs | 141 + runtime/DotNetTypeWrapper.cs | 2812 +++ runtime/Dummy.OpenJDK.Core.cs | 102 + runtime/DynamicClassLoader.cs | 603 + runtime/DynamicMethodUtils.cs | 92 + runtime/DynamicTypeWrapper.cs | 7390 +++++++ runtime/ExceptionHelper.cs | 918 + runtime/IKVM.Runtime.8.csproj | 203 + runtime/IKVM.Runtime.JNI.8.csproj | 84 + runtime/JavaException.cs | 233 + runtime/JniAssemblyInfo.cs | 34 + runtime/JniAssemblyInfo.cs.in | 34 + runtime/JniInterface.cs | 3790 ++++ runtime/JsrInliner.cs | 2062 ++ runtime/LambdaMetafactory.cs | 1030 + runtime/LocalVars.cs | 640 + runtime/MemberWrapper.cs | 2163 +++ runtime/MethodHandleUtil.cs | 209 + runtime/PassiveWeakDictionary.cs | 257 + runtime/ReflectUtil.cs | 279 + runtime/RuntimeHelperTypes.cs | 96 + runtime/Serialization.cs | 264 + runtime/TypeWrapper.cs | 5828 ++++++ runtime/Types.cs | 66 + runtime/atomic.cs | 158 + runtime/attributes.cs | 1010 + runtime/common.cs | 631 + runtime/compiler.cs | 4215 ++++ runtime/fdlibm/e_hypot.cs | 126 + runtime/fdlibm/e_pow.cs | 314 + runtime/fdlibm/e_rem_pio2.cs | 173 + runtime/fdlibm/fdlibm_h.cs | 70 + runtime/fdlibm/k_rem_pio2.cs | 319 + runtime/fdlibm/k_tan.cs | 158 + runtime/fdlibm/s_cbrt.cs | 89 + runtime/fdlibm/s_expm1.cs | 224 + runtime/fdlibm/s_floor.cs | 86 + runtime/fdlibm/s_log1p.cs | 177 + runtime/fdlibm/s_scalbn.cs | 70 + runtime/fdlibm/s_tan.cs | 84 + runtime/intrinsics.cs | 1278 ++ .../openjdk/NativeInvokerBytecodeGenerator.cs | 1029 + runtime/openjdk/java.io.cs | 1562 ++ runtime/openjdk/java.lang.cs | 1448 ++ runtime/openjdk/java.lang.invoke.cs | 1278 ++ runtime/openjdk/java.lang.reflect.cs | 808 + runtime/openjdk/java.net.SocketInputStream.cs | 216 + runtime/openjdk/java.net.cs | 732 + runtime/openjdk/java.nio.cs | 277 + runtime/openjdk/java.security.cs | 154 + runtime/openjdk/java.util.cs | 339 + runtime/openjdk/java.util.prefs.cs | 359 + runtime/openjdk/misc.cs | 635 + runtime/openjdk/sun.management.cs | 354 + runtime/openjdk/sun.misc.cs | 829 + runtime/openjdk/sun.nio.ch.cs | 1222 ++ runtime/openjdk/sun.reflect.cs | 2310 +++ runtime/openjdk/sun.security.krb5.cs | 354 + runtime/openjdk/sun.util.locale.provider.cs | 554 + runtime/profiler.cs | 121 + runtime/runtime.build | 227 + runtime/stubgen/ClassFileWriter.cs | 1104 ++ runtime/stubgen/SerialVersionUID.cs | 183 + runtime/stubgen/StubGenerator.cs | 894 + runtime/tracer.cs | 222 + runtime/verifier.cs | 4121 ++++ runtime/vfs.cs | 1033 + runtime/vm.cs | 499 + tools/SourceLicenseAnalyzer.cs | 217 + tools/depcheck.cs | 90 + tools/implib.cs | 230 + tools/pubkey.cs | 44 + tools/pubkey.txt | 1 + tools/tools.build | 64 + tools/updbaseaddresses.cs | 69 + tools/writeappconfig.cs | 48 + 558 files changed, 275726 insertions(+) create mode 100644 CommonAssemblyInfo.cs create mode 100644 CommonAssemblyInfo.cs.in create mode 100644 LICENSE create mode 100644 README create mode 100644 THANKYOU create mode 100644 THIRD_PARTY_README create mode 100644 TRADEMARK create mode 100644 awt/AssemblyInfo.cs create mode 100644 awt/AssemblyInfo.cs.in create mode 100644 awt/IKVM.AWT.WinForms.8.csproj create mode 100644 awt/IconFactory.cs create mode 100644 awt/ShellApi.cs create mode 100644 awt/awt.build create mode 100644 awt/composite.cs create mode 100644 awt/converter.cs create mode 100644 awt/fonts-0.95.cs create mode 100644 awt/graphics.cs create mode 100644 awt/images.cs create mode 100644 awt/native.cs create mode 100644 awt/printing.cs create mode 100644 awt/robot.cs create mode 100644 awt/theming.cs create mode 100644 awt/toolkit-0.95.cs create mode 100644 bin-x64/README create mode 100644 bin-x86/README create mode 100644 bin/ikvm.exe.config create mode 100644 bin/ikvm.exe.manifest create mode 100644 bin/ikvmc.exe.config create mode 100644 bin/ikvmstub.exe.config create mode 100644 classpath/gnu/java/net/protocol/ikvmres/Handler.java create mode 100644 classpath/ikvm/extensions/ExtensionMethods.java create mode 100644 classpath/ikvm/internal/AssemblyClassLoader.java create mode 100644 classpath/ikvm/internal/CallerID.java create mode 100644 classpath/ikvm/internal/Formatter.java create mode 100644 classpath/ikvm/internal/JMath.java create mode 100644 classpath/ikvm/internal/Library.java create mode 100644 classpath/ikvm/internal/LibraryVMInterface.java create mode 100644 classpath/ikvm/internal/MonoUtils.java create mode 100644 classpath/ikvm/internal/Util.java create mode 100644 classpath/ikvm/internal/WeakIdentityMap.java create mode 100644 classpath/ikvm/internal/__unspecified.java create mode 100644 classpath/ikvm/io/InputStreamWrapper.java create mode 100644 classpath/ikvm/lang/CIL.java create mode 100644 classpath/ikvm/lang/DllExport.java create mode 100644 classpath/ikvm/lang/Internal.java create mode 100644 classpath/ikvm/lang/IterableEnumerator.java create mode 100644 classpath/ikvm/lang/MapEnumerator.java create mode 100644 classpath/ikvm/lang/Property.java create mode 100644 classpath/ikvm/runtime/AppDomainAssemblyClassLoader.java create mode 100644 classpath/ikvm/runtime/ClassPathAssemblyClassLoader.java create mode 100644 classpath/ikvm/runtime/Delegates.java create mode 100644 classpath/ikvm/runtime/EnumerationWrapper.java create mode 100644 classpath/ikvm/runtime/Startup.java create mode 100644 classpath/ikvm/runtime/Util.java create mode 100644 classpath/java/util/concurrent/atomic/AtomicBoolean.java create mode 100644 classpath/java/util/concurrent/atomic/AtomicInteger.java create mode 100644 classpath/java/util/concurrent/atomic/AtomicIntegerArray.java create mode 100644 classpath/java/util/concurrent/atomic/AtomicLong.java create mode 100644 classpath/java/util/concurrent/atomic/AtomicLongArray.java create mode 100644 classpath/java/util/concurrent/atomic/AtomicReference.java create mode 100644 classpath/java/util/concurrent/atomic/AtomicReferenceArray.java create mode 100644 classpath/java/util/concurrent/atomic/Striped64.java create mode 100644 classpath/sun/misc/Ref.java create mode 100644 ikvm.build create mode 100644 ikvm.include create mode 100644 ikvm/AssemblyInfo.cs create mode 100644 ikvm/ikvm.8.csproj create mode 100644 ikvm/ikvm.build create mode 100644 ikvm/starter.cs create mode 100644 ikvm9.sln create mode 100644 ikvmc.8.csproj create mode 100644 ikvmc/AotTypeWrapper.cs create mode 100644 ikvmc/AssemblyInfo.cs create mode 100644 ikvmc/AssemblyResolver.cs create mode 100644 ikvmc/Compiler.cs create mode 100644 ikvmc/CompilerClassLoader.cs create mode 100644 ikvmc/FakeTypes.cs create mode 100644 ikvmc/Proxy.cs create mode 100644 ikvmc/ikvmc.build create mode 100644 ikvmc/remapper.cs create mode 100644 ikvmdoc/IKVMDoc.java create mode 100644 ikvmdoc/ikvmdoc.build create mode 100644 ikvmstub/AssemblyInfo.cs create mode 100644 ikvmstub/ikvmstub.8.csproj create mode 100644 ikvmstub/ikvmstub.build create mode 100644 ikvmstub/ikvmstub.cs create mode 100644 japi/japi-status.build create mode 100644 jvm/jvm.build create mode 100644 jvm/jvm.def create mode 100644 msbuild/AssemblyInfo.cs create mode 100644 msbuild/IKVM.MSBuild.Java.Targets create mode 100644 msbuild/IKVM.MSBuild.csproj create mode 100644 msbuild/JavaTask.cs create mode 100644 msbuild/msbuild.build create mode 100644 native/ikvm-native.rc create mode 100644 native/ikvm-native.rc.in create mode 100644 native/jni.c create mode 100644 native/jni.h create mode 100644 native/native.8.vcproj create mode 100644 native/native.9.vcproj create mode 100644 native/native.build create mode 100644 native/os.c create mode 100644 nuget/IKVM.nuspec.in create mode 100644 nuget/nupkg.build create mode 100644 openjdk/AssemblyInfo.java create mode 100644 openjdk/AssemblyInfo.java.in create mode 100644 openjdk/ExtensionAttribute.java create mode 100644 openjdk/FORKED create mode 100644 openjdk/GenerateSystemCore.cs create mode 100644 openjdk/MANIFEST.MF create mode 100644 openjdk/MANIFEST.MF.in create mode 100644 openjdk/allsources.lst create mode 100644 openjdk/com/sun/imageio/plugins/jpeg/JPEGImageReader.java create mode 100644 openjdk/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java create mode 100644 openjdk/com/sun/java/util/jar/pack/PackageReader.java create mode 100644 openjdk/copyright.txt create mode 100644 openjdk/dependencies.txt create mode 100644 openjdk/exclude.lst create mode 100644 openjdk/gnu/java/awt/Buffers.java create mode 100644 openjdk/gnu/java/awt/color/CieXyzConverter.java create mode 100644 openjdk/gnu/java/awt/color/ClutProfileConverter.java create mode 100644 openjdk/gnu/java/awt/color/ColorLookUpTable.java create mode 100644 openjdk/gnu/java/awt/color/ColorSpaceConverter.java create mode 100644 openjdk/gnu/java/awt/color/GrayProfileConverter.java create mode 100644 openjdk/gnu/java/awt/color/GrayScaleConverter.java create mode 100644 openjdk/gnu/java/awt/color/ProfileHeader.java create mode 100644 openjdk/gnu/java/awt/color/RgbProfileConverter.java create mode 100644 openjdk/gnu/java/awt/color/SrgbConverter.java create mode 100644 openjdk/gnu/java/awt/color/TagEntry.java create mode 100644 openjdk/gnu/java/awt/color/ToneReproductionCurve.java create mode 100644 openjdk/gnu/java/util/EmptyEnumeration.java create mode 100644 openjdk/icedtea/jce/gnu/java/security/action/GetPropertyAction.java create mode 100644 openjdk/icedtea/jce/gnu/java/security/action/GetSecurityPropertyAction.java create mode 100644 openjdk/icedtea/jce/gnu/java/security/action/SetAccessibleAction.java create mode 100644 openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpDataTypeEnums.java create mode 100644 openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpDefinitions.java create mode 100644 openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpOid.java create mode 100644 openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpOidRecord.java create mode 100644 openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpOidTable.java create mode 100644 openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpOidTableSupport.java create mode 100644 openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpParameters.java create mode 100644 openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpPduPacket.java create mode 100644 openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpPeer.java create mode 100644 openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpSession.java create mode 100644 openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpTimeticks.java create mode 100644 openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpVarBind.java create mode 100644 openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpVarBindList.java create mode 100644 openjdk/icedtea/rt/com/sun/jmx/snmp/daemon/SnmpInformRequest.java create mode 100644 openjdk/icedtea/rt/com/sun/jmx/snmp/daemon/SnmpSession.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/AbstractPlayer.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/AutoConnectSequencer.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/DataPusher.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/DirectAudioDevice.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/DirectAudioDeviceProvider.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/HeadspaceMixer.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/HeadspaceSoundbank.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/JDK13Services.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/JavaSoundAudioClip.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/MidiInDevice.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/MidiInDeviceProvider.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/MidiOutDevice.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/MidiOutDeviceProvider.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/MidiUtils.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/MixerClip.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/MixerMidiChannel.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/MixerSequencer.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/MixerSourceLine.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/MixerSynth.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/MixerThread.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/Platform.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/PortMixer.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/PortMixerProvider.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/ReferenceCountingDevice.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/SimpleInputDevice.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/SimpleInputDeviceProvider.java create mode 100644 openjdk/icedtea/rt/com/sun/media/sound/Toolkit.java create mode 100644 openjdk/ikvm/awt/IkvmToolkit.java create mode 100644 openjdk/ikvm/internal/AnnotationAttributeBase.java create mode 100644 openjdk/ikvm/internal/FieldReflectorBase.java create mode 100644 openjdk/ikvm/internal/InterlockedCompareAndSet.java create mode 100644 openjdk/ikvm/internal/IntrinsicAtomicReferenceFieldUpdater.java create mode 100644 openjdk/ikvm/internal/IntrinsicThreadLocal.java create mode 100644 openjdk/ikvm/internal/JNI.java create mode 100644 openjdk/ikvm/internal/NotYetImplementedError.java create mode 100644 openjdk/ikvm/internal/Serialization.java create mode 100644 openjdk/ikvm/internal/Winsock.java create mode 100644 openjdk/java/awt/Font.java create mode 100644 openjdk/java/awt/GraphicsConfiguration.java create mode 100644 openjdk/java/awt/Image.java create mode 100644 openjdk/java/awt/color/ICC_ColorSpace.java create mode 100644 openjdk/java/awt/image/AffineTransformOp.java create mode 100644 openjdk/java/awt/image/BandCombineOp.java create mode 100644 openjdk/java/awt/image/BufferedImage.java create mode 100644 openjdk/java/awt/image/ColorConvertOp.java create mode 100644 openjdk/java/awt/image/ConvolveOp.java create mode 100644 openjdk/java/awt/image/DataBuffer.java create mode 100644 openjdk/java/awt/image/DataBufferByte.java create mode 100644 openjdk/java/awt/image/DataBufferDouble.java create mode 100644 openjdk/java/awt/image/DataBufferFloat.java create mode 100644 openjdk/java/awt/image/DataBufferInt.java create mode 100644 openjdk/java/awt/image/DataBufferShort.java create mode 100644 openjdk/java/awt/image/DataBufferUShort.java create mode 100644 openjdk/java/awt/image/IndexColorModel.java create mode 100644 openjdk/java/awt/image/LookupOp.java create mode 100644 openjdk/java/awt/image/RescaleOp.java create mode 100644 openjdk/java/io/DefaultFileSystem.java create mode 100644 openjdk/java/io/FileDescriptor.java create mode 100644 openjdk/java/io/InteropObjectInputStream.java create mode 100644 openjdk/java/io/InteropObjectOutputStream.java create mode 100644 openjdk/java/io/ObjectStreamClass.java create mode 100644 openjdk/java/io/ObjectStreamField.java create mode 100644 openjdk/java/lang/Class.java create mode 100644 openjdk/java/lang/ClassLoader.java create mode 100644 openjdk/java/lang/ClassLoaderHelper.java create mode 100644 openjdk/java/lang/ClassSerializationProxy.java create mode 100644 openjdk/java/lang/Enum.java create mode 100644 openjdk/java/lang/LangHelper.java create mode 100644 openjdk/java/lang/ProcessImpl.java create mode 100644 openjdk/java/lang/PropertyConstants.java create mode 100644 openjdk/java/lang/PropertyConstants.java.in create mode 100644 openjdk/java/lang/Shutdown.java create mode 100644 openjdk/java/lang/StringHelper.java create mode 100644 openjdk/java/lang/System.java create mode 100644 openjdk/java/lang/Thread.java create mode 100644 openjdk/java/lang/ThrowableHelper.java create mode 100644 openjdk/java/lang/VMSystemProperties.java create mode 100644 openjdk/java/lang/invoke/LightWeightMethodHandle.java create mode 100644 openjdk/java/lang/management/PlatformComponent.java create mode 100644 openjdk/java/lang/ref/Reference.java create mode 100644 openjdk/java/lang/ref/ReferenceQueue.java create mode 100644 openjdk/java/lang/ref/SoftReference.java create mode 100644 openjdk/java/lang/reflect/Constructor.java create mode 100644 openjdk/java/lang/reflect/Executable.java create mode 100644 openjdk/java/lang/reflect/Field.java create mode 100644 openjdk/java/lang/reflect/Method.java create mode 100644 openjdk/java/lang/reflect/Proxy.java create mode 100644 openjdk/java/net/DefaultDatagramSocketImplFactory.java create mode 100644 openjdk/java/net/DualStackPlainDatagramSocketImpl.java create mode 100644 openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java create mode 100644 openjdk/java/net/DualStackPlainSocketImpl.java create mode 100644 openjdk/java/net/DualStackPlainSocketImpl_c.java create mode 100644 openjdk/java/net/PlainSocketImpl.java create mode 100644 openjdk/java/net/SocketUtil.java create mode 100644 openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java create mode 100644 openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java create mode 100644 openjdk/java/net/TwoStacksPlainSocketImpl.java create mode 100644 openjdk/java/net/TwoStacksPlainSocketImpl_c.java create mode 100644 openjdk/java/net/net_util_md.java create mode 100644 openjdk/java/nio/Bits.java create mode 100644 openjdk/java/security/AccessController.java create mode 100644 openjdk/java/security/ProtectionDomain.java create mode 100644 openjdk/java/util/concurrent/locks/AbstractQueuedSynchronizer.java create mode 100644 openjdk/java/util/concurrent/locks/LockSupport.java create mode 100644 openjdk/java/util/zip/Adler32.java create mode 100644 openjdk/java/util/zip/CRC32.java create mode 100644 openjdk/java/util/zip/ClassStubZipEntry.java create mode 100644 openjdk/java/util/zip/Deflater.java create mode 100644 openjdk/java/util/zip/DeflaterConstants.java create mode 100644 openjdk/java/util/zip/DeflaterEngine.java create mode 100644 openjdk/java/util/zip/DeflaterHuffman.java create mode 100644 openjdk/java/util/zip/DeflaterPending.java create mode 100644 openjdk/java/util/zip/Inflater.java create mode 100644 openjdk/java/util/zip/InflaterDynHeader.java create mode 100644 openjdk/java/util/zip/InflaterHuffmanTree.java create mode 100644 openjdk/java/util/zip/OutputWindow.java create mode 100644 openjdk/java/util/zip/PendingBuffer.java create mode 100644 openjdk/java/util/zip/StreamManipulator.java create mode 100644 openjdk/java/util/zip/ZipEntry.java create mode 100644 openjdk/java/util/zip/ZipFile.java create mode 100644 openjdk/map.xml create mode 100644 openjdk/openjdk.build create mode 100644 openjdk/resources/META-INF/services/java.sql.Driver create mode 100644 openjdk/resources/META-INF/services/sun.java2d.pipe.RenderingEngine create mode 100644 openjdk/resources/nashorn/version.properties create mode 100644 openjdk/resources/nashorn/version.properties.in create mode 100644 openjdk/response.txt create mode 100644 openjdk/security.xml create mode 100644 openjdk/sun/awt/DebugSettings.java create mode 100644 openjdk/sun/awt/EmbeddedFrame.java create mode 100644 openjdk/sun/awt/IkvmDataTransferer.java create mode 100644 openjdk/sun/awt/Win32FontManager.java create mode 100644 openjdk/sun/awt/X11FontManager.java create mode 100644 openjdk/sun/awt/image/ByteInterleavedRaster.java create mode 100644 openjdk/sun/awt/image/GifImageDecoder.java create mode 100644 openjdk/sun/awt/image/IkvmImageDecoder.java create mode 100644 openjdk/sun/awt/image/ImageRepresentation.java create mode 100644 openjdk/sun/awt/image/ImagingLib.java create mode 100644 openjdk/sun/awt/image/IntegerInterleavedRaster.java create mode 100644 openjdk/sun/awt/image/JPEGImageDecoder.java create mode 100644 openjdk/sun/awt/image/SunWritableRaster.java create mode 100644 openjdk/sun/awt/image/ToolkitImage.java create mode 100644 openjdk/sun/awt/shell/Win32ShellFolder2.java create mode 100644 openjdk/sun/awt/shell/Win32ShellFolderManager2.java create mode 100644 openjdk/sun/awt/windows/WPrinterJob.java create mode 100644 openjdk/sun/font/CompositeFont.java create mode 100644 openjdk/sun/font/Font2D.java create mode 100644 openjdk/sun/font/FontManager.java create mode 100644 openjdk/sun/font/GlyphLayout.java create mode 100644 openjdk/sun/font/PhysicalFont.java create mode 100644 openjdk/sun/font/PhysicalStrike.java create mode 100644 openjdk/sun/font/StandardGlyphVector.java create mode 100644 openjdk/sun/font/StrikeCache.java create mode 100644 openjdk/sun/font/SunFontManager.java create mode 100644 openjdk/sun/font/TrueTypeFont.java create mode 100644 openjdk/sun/java2d/HeadlessGraphicsEnvironment.java create mode 100644 openjdk/sun/java2d/SunCompositeContext.java create mode 100644 openjdk/sun/java2d/SunGraphics2D.java create mode 100644 openjdk/sun/java2d/SunGraphicsEnvironment.java create mode 100644 openjdk/sun/java2d/SurfaceData.java create mode 100644 openjdk/sun/java2d/cmm/lcms/LCMS.java create mode 100644 openjdk/sun/java2d/loops/TransformHelper.java create mode 100644 openjdk/sun/java2d/pipe/ShapeSpanIterator.java create mode 100644 openjdk/sun/jdbc/odbc/JdbcOdbcCallableStatement.java create mode 100644 openjdk/sun/jdbc/odbc/JdbcOdbcConnection.java create mode 100644 openjdk/sun/jdbc/odbc/JdbcOdbcDTResultSet.java create mode 100644 openjdk/sun/jdbc/odbc/JdbcOdbcDTResultSetMetaData.java create mode 100644 openjdk/sun/jdbc/odbc/JdbcOdbcDatabaseMetaData.java create mode 100644 openjdk/sun/jdbc/odbc/JdbcOdbcDriver.java create mode 100644 openjdk/sun/jdbc/odbc/JdbcOdbcObject.java create mode 100644 openjdk/sun/jdbc/odbc/JdbcOdbcPreparedStatement.java create mode 100644 openjdk/sun/jdbc/odbc/JdbcOdbcResultSet.java create mode 100644 openjdk/sun/jdbc/odbc/JdbcOdbcResultSetMetaData.java create mode 100644 openjdk/sun/jdbc/odbc/JdbcOdbcStatement.java create mode 100644 openjdk/sun/jdbc/odbc/JdbcOdbcUpdateableResultSet.java create mode 100644 openjdk/sun/jdbc/odbc/JdbcOdbcUtils.java create mode 100644 openjdk/sun/management/ManagementFactoryHelper.java create mode 100644 openjdk/sun/management/VMManagementImpl.java create mode 100644 openjdk/sun/misc/FileURLMapper.java create mode 100644 openjdk/sun/misc/MiscHelper.java create mode 100644 openjdk/sun/misc/OSEnvironment.java create mode 100644 openjdk/sun/misc/SharedSecrets.java create mode 100644 openjdk/sun/misc/Unsafe.java create mode 100644 openjdk/sun/misc/VM.java create mode 100644 openjdk/sun/misc/Version.java create mode 100644 openjdk/sun/net/dns/ResolverConfigurationImpl.java create mode 100644 openjdk/sun/net/sdp/SdpSupport.java create mode 100644 openjdk/sun/net/www/protocol/file/FileURLConnection.java create mode 100644 openjdk/sun/net/www/protocol/file/Handler.java create mode 100644 openjdk/sun/net/www/protocol/ikvmres/Handler.java create mode 100644 openjdk/sun/net/www/protocol/jar/JarFileFactory.java create mode 100644 openjdk/sun/nio/ch/DatagramChannelImpl.java create mode 100644 openjdk/sun/nio/ch/DefaultSelectorProvider.java create mode 100644 openjdk/sun/nio/ch/DotNetSelectorImpl.java create mode 100644 openjdk/sun/nio/ch/FileChannelImpl.java create mode 100644 openjdk/sun/nio/ch/FileDispatcherImpl.java create mode 100644 openjdk/sun/nio/ch/FileKey.java create mode 100644 openjdk/sun/nio/ch/IOUtil.java create mode 100644 openjdk/sun/nio/ch/Iocp.java create mode 100644 openjdk/sun/nio/ch/NativeDispatcher.java create mode 100644 openjdk/sun/nio/ch/Net.java create mode 100644 openjdk/sun/nio/ch/SelectionKeyImpl.java create mode 100644 openjdk/sun/nio/ch/SocketDispatcher.java create mode 100644 openjdk/sun/nio/ch/SocketOptionRegistry.java create mode 100644 openjdk/sun/nio/ch/Util.java create mode 100644 openjdk/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java create mode 100644 openjdk/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java create mode 100644 openjdk/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java create mode 100644 openjdk/sun/nio/cs/StandardCharsets.java create mode 100644 openjdk/sun/nio/fs/DefaultFileSystemProvider.java create mode 100644 openjdk/sun/nio/fs/DefaultFileTypeDetector.java create mode 100644 openjdk/sun/nio/fs/NetFileSystem.java create mode 100644 openjdk/sun/nio/fs/NetFileSystemProvider.java create mode 100644 openjdk/sun/nio/fs/NetPath.java create mode 100644 openjdk/sun/nio/fs/UnixUriUtils.java create mode 100644 openjdk/sun/nio/fs/WindowsUriSupport.java create mode 100644 openjdk/sun/print/PrintPeer.java create mode 100644 openjdk/sun/print/UnixPrintServiceLookup.java create mode 100644 openjdk/sun/print/Win32PrintJob.java create mode 100644 openjdk/sun/print/Win32PrintService.java create mode 100644 openjdk/sun/print/Win32PrintServiceLookup.java create mode 100644 openjdk/sun/reflect/MethodAccessor.java create mode 100644 openjdk/sun/reflect/Reflection.java create mode 100644 openjdk/sun/reflect/ReflectionFactory.java create mode 100644 openjdk/sun/reflect/annotation/AnnotationType.java create mode 100644 openjdk/sun/security/jgss/wrapper/NativeGSSFactory.java create mode 100644 openjdk/sun/security/jgss/wrapper/SunNativeProvider.java create mode 100644 openjdk/swingawt.xml create mode 100644 openjdk/tools.rsp create mode 100644 reflect/AmbiguousMatchException.cs create mode 100644 reflect/Assembly.cs create mode 100644 reflect/AssemblyName.cs create mode 100644 reflect/BadImageFormatException.cs create mode 100644 reflect/Binder.cs create mode 100644 reflect/ConstructorInfo.cs create mode 100644 reflect/CustomAttributeData.cs create mode 100644 reflect/CustomAttributeNamedArgument.cs create mode 100644 reflect/CustomAttributeTypedArgument.cs create mode 100644 reflect/CustomModifiers.cs create mode 100644 reflect/Emit/AssemblyBuilder.cs create mode 100644 reflect/Emit/ConstructorBuilder.cs create mode 100644 reflect/Emit/CustomAttributeBuilder.cs create mode 100644 reflect/Emit/CustomModifiersBuilder.cs create mode 100644 reflect/Emit/EnumBuilder.cs create mode 100644 reflect/Emit/Enums.cs create mode 100644 reflect/Emit/EventBuilder.cs create mode 100644 reflect/Emit/ExceptionHandler.cs create mode 100644 reflect/Emit/FieldBuilder.cs create mode 100644 reflect/Emit/ILGenerator.cs create mode 100644 reflect/Emit/MethodBuilder.cs create mode 100644 reflect/Emit/ModuleBuilder.cs create mode 100644 reflect/Emit/OpCode.cs create mode 100644 reflect/Emit/OpCodes.cs create mode 100644 reflect/Emit/ParameterBuilder.cs create mode 100644 reflect/Emit/PropertyBuilder.cs create mode 100644 reflect/Emit/SignatureHelper.cs create mode 100644 reflect/Emit/Tokens.cs create mode 100644 reflect/Emit/TypeBuilder.cs create mode 100644 reflect/Enums.cs create mode 100644 reflect/EventInfo.cs create mode 100644 reflect/ExceptionHandlingClause.cs create mode 100644 reflect/FieldInfo.cs create mode 100644 reflect/FieldSignature.cs create mode 100644 reflect/Fusion.cs create mode 100644 reflect/GenericWrappers.cs create mode 100644 reflect/IKVM.Reflection.csproj create mode 100644 reflect/Impl/ITypeOwner.cs create mode 100644 reflect/Impl/MdbWriter.cs create mode 100644 reflect/Impl/PdbWriter.cs create mode 100644 reflect/Impl/SymbolSupport.cs create mode 100644 reflect/InterfaceMapping.cs create mode 100644 reflect/LocalVariableInfo.cs create mode 100644 reflect/ManifestResourceInfo.cs create mode 100644 reflect/MarshalSpec.cs create mode 100644 reflect/MemberInfo.cs create mode 100644 reflect/Metadata/CliHeader.cs create mode 100644 reflect/Metadata/MetadataRW.cs create mode 100644 reflect/Metadata/Tables.cs create mode 100644 reflect/MethodBase.cs create mode 100644 reflect/MethodBody.cs create mode 100644 reflect/MethodImplMap.cs create mode 100644 reflect/MethodInfo.cs create mode 100644 reflect/MethodSignature.cs create mode 100644 reflect/Missing.cs create mode 100644 reflect/Module.cs create mode 100644 reflect/ParameterInfo.cs create mode 100644 reflect/ParameterModifier.cs create mode 100644 reflect/Projection.cs create mode 100644 reflect/Properties/AssemblyInfo.cs create mode 100644 reflect/PropertyInfo.cs create mode 100644 reflect/PropertySignature.cs create mode 100644 reflect/Reader/AssemblyReader.cs create mode 100644 reflect/Reader/Authenticode.cs create mode 100644 reflect/Reader/ByteReader.cs create mode 100644 reflect/Reader/EventInfoImpl.cs create mode 100644 reflect/Reader/Field.cs create mode 100644 reflect/Reader/GenericTypeParameter.cs create mode 100644 reflect/Reader/MetadataReader.cs create mode 100644 reflect/Reader/Method.cs create mode 100644 reflect/Reader/ModuleReader.cs create mode 100644 reflect/Reader/PEReader.cs create mode 100644 reflect/Reader/PropertyInfoImpl.cs create mode 100644 reflect/Reader/ResourceModule.cs create mode 100644 reflect/Reader/TypeDefImpl.cs create mode 100644 reflect/Signature.cs create mode 100644 reflect/StandAloneMethodSig.cs create mode 100644 reflect/StrongNameKeyPair.cs create mode 100644 reflect/Type.cs create mode 100644 reflect/TypeInfo.cs create mode 100644 reflect/TypeNameParser.cs create mode 100644 reflect/Universe.cs create mode 100644 reflect/Util.cs create mode 100644 reflect/Writer/ByteBuffer.cs create mode 100644 reflect/Writer/Heaps.cs create mode 100644 reflect/Writer/MetadataWriter.cs create mode 100644 reflect/Writer/ModuleWriter.cs create mode 100644 reflect/Writer/PEWriter.cs create mode 100644 reflect/Writer/ResourceSection.cs create mode 100644 reflect/Writer/TextSection.cs create mode 100644 reflect/Writer/VersionInfo.cs create mode 100644 reflect/coreclr.cs create mode 100644 reflect/reflect.build create mode 100644 runtime/AssemblyClassLoader.cs create mode 100644 runtime/AssemblyInfo.cs create mode 100644 runtime/AssemblyInfo.cs.in create mode 100644 runtime/Assertions.cs create mode 100644 runtime/BigEndianBinaryReader.cs create mode 100644 runtime/Boxer.cs create mode 100644 runtime/ByteCode.cs create mode 100644 runtime/ByteCodeHelper.cs create mode 100644 runtime/ClassFile.cs create mode 100644 runtime/ClassLoaderWrapper.cs create mode 100644 runtime/CodeEmitter.cs create mode 100644 runtime/CoreClasses.cs create mode 100644 runtime/DotNetTypeWrapper.cs create mode 100644 runtime/Dummy.OpenJDK.Core.cs create mode 100644 runtime/DynamicClassLoader.cs create mode 100644 runtime/DynamicMethodUtils.cs create mode 100644 runtime/DynamicTypeWrapper.cs create mode 100644 runtime/ExceptionHelper.cs create mode 100644 runtime/IKVM.Runtime.8.csproj create mode 100644 runtime/IKVM.Runtime.JNI.8.csproj create mode 100644 runtime/JavaException.cs create mode 100644 runtime/JniAssemblyInfo.cs create mode 100644 runtime/JniAssemblyInfo.cs.in create mode 100644 runtime/JniInterface.cs create mode 100644 runtime/JsrInliner.cs create mode 100644 runtime/LambdaMetafactory.cs create mode 100644 runtime/LocalVars.cs create mode 100644 runtime/MemberWrapper.cs create mode 100644 runtime/MethodHandleUtil.cs create mode 100644 runtime/PassiveWeakDictionary.cs create mode 100644 runtime/ReflectUtil.cs create mode 100644 runtime/RuntimeHelperTypes.cs create mode 100644 runtime/Serialization.cs create mode 100644 runtime/TypeWrapper.cs create mode 100644 runtime/Types.cs create mode 100644 runtime/atomic.cs create mode 100644 runtime/attributes.cs create mode 100644 runtime/common.cs create mode 100644 runtime/compiler.cs create mode 100644 runtime/fdlibm/e_hypot.cs create mode 100644 runtime/fdlibm/e_pow.cs create mode 100644 runtime/fdlibm/e_rem_pio2.cs create mode 100644 runtime/fdlibm/fdlibm_h.cs create mode 100644 runtime/fdlibm/k_rem_pio2.cs create mode 100644 runtime/fdlibm/k_tan.cs create mode 100644 runtime/fdlibm/s_cbrt.cs create mode 100644 runtime/fdlibm/s_expm1.cs create mode 100644 runtime/fdlibm/s_floor.cs create mode 100644 runtime/fdlibm/s_log1p.cs create mode 100644 runtime/fdlibm/s_scalbn.cs create mode 100644 runtime/fdlibm/s_tan.cs create mode 100644 runtime/intrinsics.cs create mode 100644 runtime/openjdk/NativeInvokerBytecodeGenerator.cs create mode 100644 runtime/openjdk/java.io.cs create mode 100644 runtime/openjdk/java.lang.cs create mode 100644 runtime/openjdk/java.lang.invoke.cs create mode 100644 runtime/openjdk/java.lang.reflect.cs create mode 100644 runtime/openjdk/java.net.SocketInputStream.cs create mode 100644 runtime/openjdk/java.net.cs create mode 100644 runtime/openjdk/java.nio.cs create mode 100644 runtime/openjdk/java.security.cs create mode 100644 runtime/openjdk/java.util.cs create mode 100644 runtime/openjdk/java.util.prefs.cs create mode 100644 runtime/openjdk/misc.cs create mode 100644 runtime/openjdk/sun.management.cs create mode 100644 runtime/openjdk/sun.misc.cs create mode 100644 runtime/openjdk/sun.nio.ch.cs create mode 100644 runtime/openjdk/sun.reflect.cs create mode 100644 runtime/openjdk/sun.security.krb5.cs create mode 100644 runtime/openjdk/sun.util.locale.provider.cs create mode 100644 runtime/profiler.cs create mode 100644 runtime/runtime.build create mode 100644 runtime/stubgen/ClassFileWriter.cs create mode 100644 runtime/stubgen/SerialVersionUID.cs create mode 100644 runtime/stubgen/StubGenerator.cs create mode 100644 runtime/tracer.cs create mode 100644 runtime/verifier.cs create mode 100644 runtime/vfs.cs create mode 100644 runtime/vm.cs create mode 100644 tools/SourceLicenseAnalyzer.cs create mode 100644 tools/depcheck.cs create mode 100644 tools/implib.cs create mode 100644 tools/pubkey.cs create mode 100644 tools/pubkey.txt create mode 100644 tools/tools.build create mode 100644 tools/updbaseaddresses.cs create mode 100644 tools/writeappconfig.cs diff --git a/CommonAssemblyInfo.cs b/CommonAssemblyInfo.cs new file mode 100644 index 0000000..b3c1ef1 --- /dev/null +++ b/CommonAssemblyInfo.cs @@ -0,0 +1,37 @@ +/* + Copyright (C) 2008 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System.Reflection; + +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Jeroen Frijters")] +[assembly: AssemblyProduct("IKVM.NET")] +[assembly: AssemblyCopyright("Copyright (C) 2002-2015 Jeroen Frijters")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: AssemblyVersion("8.1.5717.0")] + +#if SIGNCODE + #pragma warning disable 1699 + [assembly: AssemblyKeyName("ikvm-key")] +#endif diff --git a/CommonAssemblyInfo.cs.in b/CommonAssemblyInfo.cs.in new file mode 100644 index 0000000..b3c1ef1 --- /dev/null +++ b/CommonAssemblyInfo.cs.in @@ -0,0 +1,37 @@ +/* + Copyright (C) 2008 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System.Reflection; + +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Jeroen Frijters")] +[assembly: AssemblyProduct("IKVM.NET")] +[assembly: AssemblyCopyright("Copyright (C) 2002-2015 Jeroen Frijters")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: AssemblyVersion("8.1.5717.0")] + +#if SIGNCODE + #pragma warning disable 1699 + [assembly: AssemblyKeyName("ikvm-key")] +#endif diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0f1d17a --- /dev/null +++ b/LICENSE @@ -0,0 +1,425 @@ +IMPORTANT NOTICE + + Copyright (C) 1998-2014 Free Software Foundation, Inc. + Copyright (C) 1996-2014 Oracle and/or its affiliates + Copyright (C) 2002-2014 Jeroen Frijters + + Some files in this distribution are part of GNU Classpath or OpenJDK and + are licensed under the GNU General Public License (GPL) version 2 + with "Classpath" exception. This applies in particular to: + - IKVM.OpenJDK.*.dll + - some of the *.java files (see each file header for license) + + See http://www.gnu.org/software/classpath/ for information on the + GNU Classpath license and "Classpath" exception. + + See below for a full copy of the GPL license and the Sun version of the + "Classpath" exception. + +----------------------------------------------------------------------------- + + Copyright (C) 2002-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +----------------------------------------------------------------------------- + +The GNU General Public License (GPL) + +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Everyone is permitted to copy and distribute verbatim copies of this license +document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to share +and change it. By contrast, the GNU General Public License is intended to +guarantee your freedom to share and change free software--to make sure the +software is free for all its users. This General Public License applies to +most of the Free Software Foundation's software and to any other program whose +authors commit to using it. (Some other Free Software Foundation software is +covered by the GNU Library General Public License instead.) You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our +General Public Licenses are designed to make sure that you have the freedom to +distribute copies of free software (and charge for this service if you wish), +that you receive source code or can get it if you want it, that you can change +the software or use pieces of it in new free programs; and that you know you +can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny +you these rights or to ask you to surrender the rights. These restrictions +translate to certain responsibilities for you if you distribute copies of the +software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for +a fee, you must give the recipients all the rights that you have. You must +make sure that they, too, receive or can get the source code. And you must +show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) +offer you this license which gives you legal permission to copy, distribute +and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that +everyone understands that there is no warranty for this free software. If the +software is modified by someone else and passed on, we want its recipients to +know that what they have is not the original, so that any problems introduced +by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We +wish to avoid the danger that redistributors of a free program will +individually obtain patent licenses, in effect making the program proprietary. +To prevent this, we have made it clear that any patent must be licensed for +everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification +follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice +placed by the copyright holder saying it may be distributed under the terms of +this General Public License. The "Program", below, refers to any such program +or work, and a "work based on the Program" means either the Program or any +derivative work under copyright law: that is to say, a work containing the +Program or a portion of it, either verbatim or with modifications and/or +translated into another language. (Hereinafter, translation is included +without limitation in the term "modification".) Each licensee is addressed as +"you". + +Activities other than copying, distribution and modification are not covered by +this License; they are outside its scope. The act of running the Program is +not restricted, and the output from the Program is covered only if its contents +constitute a work based on the Program (independent of having been made by +running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as +you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this License +and to the absence of any warranty; and give any other recipients of the +Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may +at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus +forming a work based on the Program, and copy and distribute such modifications +or work under the terms of Section 1 above, provided that you also meet all of +these conditions: + + a) You must cause the modified files to carry prominent notices stating + that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in whole or + in part contains or is derived from the Program or any part thereof, to be + licensed as a whole at no charge to all third parties under the terms of + this License. + + c) If the modified program normally reads commands interactively when run, + you must cause it, when started running for such interactive use in the + most ordinary way, to print or display an announcement including an + appropriate copyright notice and a notice that there is no warranty (or + else, saying that you provide a warranty) and that users may redistribute + the program under these conditions, and telling the user how to view a copy + of this License. (Exception: if the Program itself is interactive but does + not normally print such an announcement, your work based on the Program is + not required to print an announcement.) + +These requirements apply to the modified work as a whole. If identifiable +sections of that work are not derived from the Program, and can be reasonably +considered independent and separate works in themselves, then this License, and +its terms, do not apply to those sections when you distribute them as separate +works. But when you distribute the same sections as part of a whole which is a +work based on the Program, the distribution of the whole must be on the terms +of this License, whose permissions for other licensees extend to the entire +whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your +rights to work written entirely by you; rather, the intent is to exercise the +right to control the distribution of derivative or collective works based on +the Program. + +In addition, mere aggregation of another work not based on the Program with the +Program (or with a work based on the Program) on a volume of a storage or +distribution medium does not bring the other work under the scope of this +License. + +3. You may copy and distribute the Program (or a work based on it, under +Section 2) in object code or executable form under the terms of Sections 1 and +2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable source + code, which must be distributed under the terms of Sections 1 and 2 above + on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three years, to + give any third party, for a charge no more than your cost of physically + performing source distribution, a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of Sections 1 + and 2 above on a medium customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer to + distribute corresponding source code. (This alternative is allowed only + for noncommercial distribution and only if you received the program in + object code or executable form with such an offer, in accord with + Subsection b above.) + +The source code for a work means the preferred form of the work for making +modifications to it. For an executable work, complete source code means all +the source code for all modules it contains, plus any associated interface +definition files, plus the scripts used to control compilation and installation +of the executable. However, as a special exception, the source code +distributed need not include anything that is normally distributed (in either +source or binary form) with the major components (compiler, kernel, and so on) +of the operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the source +code from the same place counts as distribution of the source code, even though +third parties are not compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as +expressly provided under this License. Any attempt otherwise to copy, modify, +sublicense or distribute the Program is void, and will automatically terminate +your rights under this License. However, parties who have received copies, or +rights, from you under this License will not have their licenses terminated so +long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. +However, nothing else grants you permission to modify or distribute the Program +or its derivative works. These actions are prohibited by law if you do not +accept this License. Therefore, by modifying or distributing the Program (or +any work based on the Program), you indicate your acceptance of this License to +do so, and all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), +the recipient automatically receives a license from the original licensor to +copy, distribute or modify the Program subject to these terms and conditions. +You may not impose any further restrictions on the recipients' exercise of the +rights granted herein. You are not responsible for enforcing compliance by +third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), conditions +are imposed on you (whether by court order, agreement or otherwise) that +contradict the conditions of this License, they do not excuse you from the +conditions of this License. If you cannot distribute so as to satisfy +simultaneously your obligations under this License and any other pertinent +obligations, then as a consequence you may not distribute the Program at all. +For example, if a patent license would not permit royalty-free redistribution +of the Program by all those who receive copies directly or indirectly through +you, then the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply and +the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or +other property right claims or to contest validity of any such claims; this +section has the sole purpose of protecting the integrity of the free software +distribution system, which is implemented by public license practices. Many +people have made generous contributions to the wide range of software +distributed through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing to +distribute software through any other system and a licensee cannot impose that +choice. + +This section is intended to make thoroughly clear what is believed to be a +consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain +countries either by patents or by copyrighted interfaces, the original +copyright holder who places the Program under this License may add an explicit +geographical distribution limitation excluding those countries, so that +distribution is permitted only in or among countries not thus excluded. In +such case, this License incorporates the limitation as if written in the body +of this License. + +9. The Free Software Foundation may publish revised and/or new versions of the +General Public License from time to time. Such new versions will be similar in +spirit to the present version, but may differ in detail to address new problems +or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any later +version", you have the option of following the terms and conditions either of +that version or of any later version published by the Free Software Foundation. +If the Program does not specify a version number of this License, you may +choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs +whose distribution conditions are different, write to the author to ask for +permission. For software which is copyrighted by the Free Software Foundation, +write to the Free Software Foundation; we sometimes make exceptions for this. +Our decision will be guided by the two goals of preserving the free status of +all derivatives of our free software and of promoting the sharing and reuse of +software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR +THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE +STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE +PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND +PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, +YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL +ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE +PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR +INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA +BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER +OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible +use to the public, the best way to achieve this is to make it free software +which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach +them to the start of each source file to most effectively convey the exclusion +of warranty; and each file should have at least the "copyright" line and a +pointer to where the full notice is found. + + One line to give the program's name and a brief idea of what it does. + + Copyright (C) + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program 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 for + more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when it +starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author Gnomovision comes + with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free + software, and you are welcome to redistribute it under certain conditions; + type 'show c' for details. + +The hypothetical commands 'show w' and 'show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may be +called something other than 'show w' and 'show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, +if any, to sign a "copyright disclaimer" for the program, if necessary. Here +is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + 'Gnomovision' (which makes passes at compilers) written by James Hacker. + + signature of Ty Coon, 1 April 1989 + + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General Public +License instead of this License. + + +"CLASSPATH" EXCEPTION TO THE GPL + +Certain source files distributed by Oracle America and/or its affiliates are +subject to the following clarification and special exception to the GPL, but +only where Oracle has expressly included in the particular source file's header +the words "Oracle designates this particular file as subject to the "Classpath" +exception as provided by Oracle in the LICENSE file that accompanied this code." + + Linking this library statically or dynamically with other modules is making + a combined work based on this library. Thus, the terms and conditions of + the GNU General Public License cover the whole combination. + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent modules, + and to copy and distribute the resulting executable under terms of your + choice, provided that you also meet, for each linked independent module, + the terms and conditions of the license of that module. An independent + module is a module which is not derived from or based on this library. If + you modify this library, you may extend this exception to your version of + the library, but you are not obligated to do so. If you do not wish to do + so, delete this exception statement from your version. + +----------------------------------------------------------------------------- + + ------------------------------------------------------------------------- + $Id: LICENSE,v 1.8 2014/05/19 12:43:29 jfrijters Exp $ + ------------------------------------------------------------------------- + Copyright (c) 1999 Visual Numerics Inc. All Rights Reserved. + + Permission to use, copy, modify, and distribute this software is freely + granted by Visual Numerics, Inc., provided that the copyright notice + above and the following warranty disclaimer are preserved in human + readable form. + + Because this software is licenses free of charge, it is provided + "AS IS", with NO WARRANTY. TO THE EXTENT PERMITTED BY LAW, VNI + DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO ITS PERFORMANCE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + VNI WILL NOT BE LIABLE FOR ANY DAMAGES WHATSOEVER ARISING OUT OF THE USE + OF OR INABILITY TO USE THIS SOFTWARE, INCLUDING BUT NOT LIMITED TO DIRECT, + INDIRECT, SPECIAL, CONSEQUENTIAL, PUNITIVE, AND EXEMPLARY DAMAGES, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + + This Java code is based on C code in the package fdlibm, + which can be obtained from www.netlib.org. + The original fdlibm C code contains the following notice. + + Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + + Developed at SunSoft, a Sun Microsystems, Inc. business. + Permission to use, copy, modify, and distribute this + software is freely granted, provided that this notice + is preserved. + +----------------------------------------------------------------------------- diff --git a/README b/README new file mode 100644 index 0000000..1a24412 --- /dev/null +++ b/README @@ -0,0 +1,48 @@ +IKVM.NET Build Instructions +--------------------------- + +This IKVM.NET source bundle requires OpenJDK 8u45 b14 sources (and build artifacts). + +They can be downloaded from the SourceForge IKVM project, or from: + +http://www.frijters.net/openjdk-8u45-b14-stripped.zip + +This file should be unzipped in the same directory as where the ikvm directory +(that contains this unzipped source bundle) lives. + +Download ICSharpCode.SharpZipLib.dll (from http://www.icsharpcode.net/opensource/sharpziplib/ +or from the ikvmbin-x.y.z.r.zip in the SourceForge IKVM project) and copy it to ikvm/bin. + +Add the bin directory of NAnt 0.85 and JDK 8 to the PATH. Java 8 is required to build +the Java class library. It is recommend to use the 64 bit version. + +From the ikvm directory run "nant". + +You now should have the built binaries in ikvm/bin. Note that this only builds the managed +binaries, to build the native binary see Native Build. + + +Native Build +------------ + +Windows: +Make sure you have Visual C++ 2008 installed. Open a Visual Studio 2008 Command Prompt. +From the ikvm directory run "nant native". + +Linux: +Make sure you have gcc installed. From the ikvm directory run "nant native". + + +Additional Information +---------------------- + +IKVM.Runtime.dll and the various IKVM.OpenJDK.*.dll assemblies mutually depend on each other. +This is accomplished by building IKVM.Runtime.dll in two passes. The first pass defines the +methods and types that the IKVM.OpenJDK.*.dll assemblies use, but generally with an empty +method body (look for #if FIRST_PASS in the IKVM.Runtime.dll sources). The second pass is +built after the IKVM.OpenJDK.*.dll assemblies have been built. + +The version number of the build is defined in ikvm/CommonAssemblyInfo.cs.in + +If you want to do a strong named build, make sure you have a key container installed named +"ikvm-key" and run the build with "nant signed". diff --git a/THANKYOU b/THANKYOU new file mode 100644 index 0000000..cba68c1 --- /dev/null +++ b/THANKYOU @@ -0,0 +1,27 @@ +The following people have made contributions (in any way shape or form) to the IKVM.NET project. + +Eyal Alaluf +Stuart Ballard +Volker Berlin +Miguel Alfredo Garcia Gutierrez +Kevin Grigorenko +Brian Heineman +Miguel de Icaza +Michael Kay +Chris Laffra +Nat Luengnaruemitchai +Alan Macek +Andy Malakov +M. David Peterson +Jonathan Pierce +KiYun Roe +Stephen Schaub +Jo Shields +Brian Sletten +Albert Strasheim +Dennis Ushakov +Zoltan Varga +Dawid Weiss +Mark Wielaard + +And, of course, all GNU Classpath, OpenJDK and Mono developers. diff --git a/THIRD_PARTY_README b/THIRD_PARTY_README new file mode 100644 index 0000000..a93b35b --- /dev/null +++ b/THIRD_PARTY_README @@ -0,0 +1,3605 @@ +DO NOT TRANSLATE OR LOCALIZE. +----------------------------- + +%% This notice is provided with respect to ASM Bytecode Manipulation +Framework v5.0, which may be included with JRE 8, and JDK 8, and +OpenJDK 8. + +--- begin of LICENSE --- + +Copyright (c) 2000-2011 France Télécom +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. + +--- end of LICENSE --- + +-------------------------------------------------------------------------------- + +%% This notice is provided with respect to BSDiff v4.3, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright 2003-2005 Colin Percival +All rights reserved + +Redistribution and use in source and binary forms, with or without +modification, are permitted providing 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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to CodeViewer 1.0, which may be +included with JDK 8. + +--- begin of LICENSE --- + +Copyright 1999 by CoolServlets.com. + +Any errors or suggested improvements to this class can be reported as +instructed on CoolServlets.com. We hope you enjoy this program... your +comments will encourage further development! This software is distributed +under the terms of the BSD License. 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. + +Neither name of CoolServlets.com 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 COOLSERVLETS.COM 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 AUTHOR 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." + + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Cryptix AES 3.2.0, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Cryptix General License + +Copyright (c) 1995-2005 The Cryptix Foundation Limited. +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 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. + +THIS SOFTWARE IS PROVIDED BY THE CRYPTIX FOUNDATION LIMITED 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 CRYPTIX FOUNDATION LIMITED 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. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to CUP Parser Generator for +Java 0.10k, which may be included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright 1996-1999 by Scott Hudson, Frank Flannery, C. Scott Ananian + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, provided +that the above copyright notice appear in all copies and that both the +copyright notice and this permission notice and warranty disclaimer appear in +supporting documentation, and that the names of the authors or their +employers not be used in advertising or publicity pertaining to distribution of +the software without specific, written prior permission. + +The authors and their employers disclaim all warranties with regard to +this software, including all implied warranties of merchantability and fitness. +In no event shall the authors or their employers be liable for any special, +indirect or consequential damages or any damages whatsoever resulting from +loss of use, data or profits, whether in an action of contract, negligence or +other tortious action, arising out of or in connection with the use or +performance of this software. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Document Object Model (DOM) Level 2 +& 3, which may be included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +W3C SOFTWARE NOTICE AND LICENSE + +http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 + +This work (and included software, documentation such as READMEs, or other +related items) is being provided by the copyright holders under the following +license. By obtaining, using and/or copying this work, you (the licensee) +agree that you have read, understood, and will comply with the following terms +and conditions. + +Permission to copy, modify, and distribute this software and its +documentation, with or without modification, for any purpose and without fee +or royalty is hereby granted, provided that you include the following on ALL +copies of the software and documentation or portions thereof, including +modifications: + + 1.The full text of this NOTICE in a location viewable to users of the + redistributed or derivative work. + + 2.Any pre-existing intellectual property disclaimers, notices, or terms and + conditions. If none exist, the W3C Software Short Notice should be included + (hypertext is preferred, text is permitted) within the body of any + redistributed or derivative code. + + 3.Notice of any changes or modifications to the files, including the date + changes were made. (We recommend you provide URIs to the location from + which the code is derived.) + +THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS +MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR +PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY +THIRD PARTY PATENTS,COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. + +COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL +OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR +DOCUMENTATION. The name and trademarks of copyright holders may NOT be used +in advertising or publicity pertaining to the software without specific, +written prior permission. Title to copyright in this software and any +associated documentation will at all times remain with copyright holders. + +____________________________________ + +This formulation of W3C's notice and license became active on December 31 +2002. This version removes the copyright ownership notice such that this +license can be used with materials other than those owned by the W3C, reflects +that ERCIM is now a host of the W3C, includes references to this specific +dated version of the license, and removes the ambiguous grant of "use". +Otherwise, this version is the same as the previous version and is written so +as to preserve the Free Software Foundation's assessment of GPL compatibility +and OSI's certification under the Open Source Definition. Please see our +Copyright FAQ for common questions about using materials from our site, +including specific terms and conditions for packages like libwww, Amaya, and +Jigsaw. Other questions about this notice can be directed to +site-policy@w3.org. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Dynalink v0.5, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright (c) 2009-2013, Attila Szegedi + +All rights reserved.Redistribution and use in source and binary forms, with or +without modification, are permitted provided that the following conditions are +met:* Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. * 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. * Neither the name of Attila +Szegedi 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 HOLDER 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 THEPOSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Elliptic Curve Cryptography, which +may be included with JRE 8, JDK 8, and OpenJDK 8. + +You are receiving a copy of the Elliptic Curve Cryptography library in source +form with the JDK 8 and OpenJDK 8 source distributions, and as object code in +the JRE 8 & JDK 8 runtimes. + +In the case of the JRE 8 & JDK 8 runtimes, the terms of the Oracle license do +NOT apply to the Elliptic Curve Cryptography library; it is licensed under the +following license, separately from Oracle's JDK & JRE. If you do not wish to +install the Elliptic Curve Cryptography library, you may delete the library +named libsunec.so (on Solaris and Linux systems) or sunec.dll (on Windows +systems) from the JRE bin directory reserved for native libraries. + + +--- begin of LICENSE --- + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to ECMAScript Language +Specification ECMA-262 Edition 5.1 which may be included with +JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright notice +Copyright © 2011 Ecma International +Ecma International +Rue du Rhone 114 +CH-1204 Geneva +Tel: +41 22 849 6000 +Fax: +41 22 849 6001 +Web: http://www.ecma-international.org + +This document and possible translations of it may be copied and furnished to +others, and derivative works that comment on or otherwise explain it or assist +in its implementation may be prepared, copied, published, and distributed, in +whole or in part, without restriction of any kind, provided that the above +copyright notice and this section are included on all such copies and derivative +works. However, this document itself may not be modified in any way, including +by removing the copyright notice or references to Ecma International, except as +needed for the purpose of developing any document or deliverable produced by +Ecma International (in which case the rules applied to copyrights must be +followed) or as required to translate it into languages other than English. The +limited permissions granted above are perpetual and will not be revoked by Ecma +International or its successors or assigns. This document and the information +contained herein is provided on an "AS IS" basis and ECMA INTERNATIONAL +DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY +WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY OWNERSHIP +RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE." Software License + +All Software contained in this document ("Software)" is protected by copyright +and is being made available under the "BSD License", included below. This +Software may be subject to third party rights (rights from parties other than +Ecma International), including patent rights, and no licenses under such third +party rights are granted under this license even if the third party concerned is +a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS +AVAILABLE AT http://www.ecma-international.org/memento/codeofconduct.htm FOR +INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO +IMPLEMENT ECMA INTERNATIONAL STANDARDS*. 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 authors nor Ecma International may be used to endorse +or promote products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "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 ECMA INTERNATIONAL 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. +--- end of LICENSE --- + +%% This notice is provided with respect to Dynalink library which is included +with the Nashorn technology. + +--- begin of LICENSE --- +Copyright (c) 2009-2013, Attila Szegedi + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* 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. +* Neither the name of the copyright holder nor the names of + 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 COPYRIGHT HOLDER +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. +--- end of LICENSE --- + +%% This notice is provided with respect to Joni library which is included +with the Nashorn technology. + +--- begin of LICENSE --- +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. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to FontConfig 2.5, which may be +included with JRE 8, JDK 8, and OpenJDK 8 source distributions on +Linux and Solaris. + +--- begin of LICENSE --- + +Copyright © 2001,2003 Keith Packard + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that the +above copyright notice appear in all copies and that both that copyright +notice and this permission notice appear in supporting documentation, and that +the name of Keith Packard not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior permission. +Keith Packard makes no representations about the suitability of this software +for any purpose. It is provided "as is" without express or implied warranty. + +KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL KEITH +PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY +DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to IAIK PKCS#11 Wrapper, +which may be included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +IAIK PKCS#11 Wrapper License + +Copyright (c) 2002 Graz University of Technology. 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. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: + + "This product includes software developed by IAIK of Graz University of + Technology." + + Alternately, this acknowledgment may appear in the software itself, if and + wherever such third-party acknowledgments normally appear. + +4. The names "Graz University of Technology" and "IAIK of Graz University of + Technology" must not be used to endorse or promote products derived from this + software without prior written permission. + +5. Products derived from this software may not be called "IAIK PKCS Wrapper", + nor may "IAIK" appear in their name, without prior written permission of + Graz University of Technology. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED 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 +LICENSOR 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. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to ICU4C 4.0.1 and ICU4J 4.4, which +may be included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright (c) 1995-2010 International Business Machines Corporation and others + +All rights reserved. + +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, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, +provided that the above copyright notice(s) and this permission notice appear +in all copies of the Software and that both the above copyright notice(s) and +this permission notice appear in supporting documentation. + +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 OF THIRD PARTY RIGHTS. IN +NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE +LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY +DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall not +be used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization of the copyright holder. +All trademarks and registered trademarks mentioned herein are the property of +their respective owners. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to IJG JPEG 6b, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +This software is copyright (C) 1991-1998, Thomas G. Lane. +All Rights Reserved except as specified below. + +Permission is hereby granted to use, copy, modify, and distribute this +software (or portions thereof) for any purpose, without fee, subject to these +conditions: +(1) If any part of the source code for this software is distributed, then this +README file must be included, with this copyright and no-warranty notice +unaltered; and any additions, deletions, or changes to the original files +must be clearly indicated in accompanying documentation. +(2) If only executable code is distributed, then the accompanying +documentation must state that "this software is based in part on the work of +the Independent JPEG Group". +(3) Permission for use of this software is granted only if the user accepts +full responsibility for any undesirable consequences; the authors accept +NO LIABILITY for damages of any kind. + +These conditions apply to any software derived from or based on the IJG code, +not just to the unmodified library. If you use our work, you ought to +acknowledge us. + +Permission is NOT granted for the use of any IJG author's name or company name +in advertising or publicity relating to this software or products derived from +it. This software may be referred to only as "the Independent JPEG Group's +software". + +We specifically permit and encourage the use of this software as the basis of +commercial products, provided that all warranty or liability claims are +assumed by the product vendor. + +--- end of LICENSE --- + +-------------------------------------------------------------------------------- + +%% This notice is provided with respect to Joni v1.1.9, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +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. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to JOpt-Simple v3.0, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + + Copyright (c) 2004-2009 Paul R. Holser, Jr. + + 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. + +--- end of LICENSE --- + +-------------------------------------------------------------------------------- + +%% This notice is provided with respect to JSON, which may be included +with JRE 8 & JDK 8. + +--- begin of LICENSE --- + +Copyright (c) 2002 JSON.org + +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 shall be used for Good, not Evil. + +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. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Kerberos functionality, which +which may be included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + + (C) Copyright IBM Corp. 1999 All Rights Reserved. + Copyright 1997 The Open Group Research Institute. All rights reserved. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Kerberos functionality from +FundsXpress, INC., which may be included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + + Copyright (C) 1998 by the FundsXpress, INC. + + All rights reserved. + + Export of this software from the United States of America may require + a specific license from the United States Government. It is the + responsibility of any person or organization contemplating export to + obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of FundsXpress. not be used in advertising or publicity pertaining + to distribution of the software without specific, written prior + permission. FundsXpress makes no representations about the suitability of + this software for any purpose. It is provided "as is" without express + or implied warranty. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Kronos OpenGL headers, which may be +included with JDK 8 and OpenJDK 8 source distributions. + +--- begin of LICENSE --- + + Copyright (c) 2007 The Khronos Group Inc. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and/or associated documentation files (the "Materials"), to + deal in the Materials without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Materials, and to permit persons to whom the Materials are + 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 Materials. + + THE MATERIALS ARE 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 MATERIALS OR THE USE OR OTHER DEALINGS IN THE + MATERIALS. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% Portions Copyright Eastman Kodak Company 1992 + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to libpng 1.5.4, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +This copy of the libpng notices is provided for your convenience. In case of +any discrepancy between this copy and the notices in the file png.h that is +included in the libpng distribution, the latter shall prevail. + +COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + +If you modify libpng you may insert additional notices immediately following +this sentence. + +This code is released under the libpng license. + +libpng versions 1.2.6, August 15, 2004, through 1.5.4, July 7, 2011, are +Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.2.5 +with the following individual added to the list of Contributing Authors + + Cosmin Truta + +libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are +Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.0.6 +with the following individuals added to the list of Contributing Authors + + Simon-Pierre Cadieux + Eric S. Raymond + Gilles Vollant + +and with the following additions to the disclaimer: + + There is no warranty against interference with your enjoyment of the + library or against infringement. There is no warranty that our + efforts or the library will fulfill any of your particular purposes + or needs. This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and effort is with + the user. + +libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are +Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-0.96, +with the following individuals added to the list of Contributing Authors: + + Tom Lane + Glenn Randers-Pehrson + Willem van Schaik + +libpng versions 0.89, June 1996, through 0.96, May 1997, are +Copyright (c) 1996, 1997 Andreas Dilger +Distributed according to the same disclaimer and license as libpng-0.88, +with the following individuals added to the list of Contributing Authors: + + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner + +libpng versions 0.5, May 1995, through 0.88, January 1996, are +Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. + +For the purposes of this copyright and license, "Contributing Authors" +is defined as the following set of individuals: + + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner + +The PNG Reference Library is supplied "AS IS". The Contributing Authors +and Group 42, Inc. disclaim all warranties, expressed or implied, +including, without limitation, the warranties of merchantability and of +fitness for any purpose. The Contributing Authors and Group 42, Inc. +assume no liability for direct, indirect, incidental, special, exemplary, +or consequential damages, which may result from the use of the PNG +Reference Library, even if advised of the possibility of such damage. + +Permission is hereby granted to use, copy, modify, and distribute this +source code, or portions hereof, for any purpose, without fee, subject +to the following restrictions: + +1. The origin of this source code must not be misrepresented. + +2. Altered versions must be plainly marked as such and must not + be misrepresented as being the original source. + +3. This Copyright notice may not be removed or altered from any + source or altered source distribution. + +The Contributing Authors and Group 42, Inc. specifically permit, without +fee, and encourage the use of this source code as a component to +supporting the PNG file format in commercial products. If you use this +source code in a product, acknowledgment is not required but would be +appreciated. + + +A "png_get_copyright" function is available, for convenient use in "about" +boxes and the like: + + printf("%s",png_get_copyright(NULL)); + +Also, the PNG logo (in PNG format, of course) is supplied in the +files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + +Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a +certification mark of the Open Source Initiative. + +Glenn Randers-Pehrson +glennrp at users.sourceforge.net +July 7, 2011 + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to libungif 4.1.3, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +The GIFLIB distribution is Copyright (c) 1997 Eric S. Raymond + +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. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Little CMS 2.4, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Little CMS +Copyright (c) 1998-2010 Marti Maria Saguer + +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. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% Lucida is a registered trademark or trademark of Bigelow & Holmes in the +U.S. and other countries. + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Mesa 3D Graphics Library v4.1, +which may be included with JRE 8, JDK 8, and OpenJDK 8 source distributions. + +--- begin of LICENSE --- + + Mesa 3-D graphics library + Version: 4.1 + + Copyright (C) 1999-2002 Brian Paul All Rights Reserved. + + 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 + BRIAN PAUL 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. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Mozilla Network Security +Services (NSS), which is supplied with the JDK test suite in the OpenJDK +source code repository. It is licensed under Mozilla Public License (MPL), +version 2.0. + +The NSS libraries are supplied in executable form, built from unmodified +NSS source code labeled with the "NSS_3.13.1_RTM" release tag. + +The NSS source code is available in the OpenJDK source code repository at: + jdk/test/sun/security/pkcs11/nss/src + +The NSS libraries are available in the OpenJDK source code repository at: + jdk/test/sun/security/pkcs11/nss/lib + +--- begin of LICENSE --- + +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to PC/SC Lite for Suse Linux v.1.1.1, +which may be included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. + +--- begin of LICENSE --- + +Copyright (c) 1999-2004 David Corcoran +Copyright (c) 1999-2004 Ludovic Rousseau +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. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + This product includes software developed by: + David Corcoran + http://www.linuxnet.com (MUSCLE) +4. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +Changes to this license can be made only by the copyright author with +explicit written consent. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to PorterStemmer v4, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +See: http://tartarus.org/~martin/PorterStemmer + +The software is completely free for any purpose, unless notes at the head of +the program text indicates otherwise (which is rare). In any case, the notes +about licensing are never more restrictive than the BSD License. + +In every case where the software is not written by me (Martin Porter), this +licensing arrangement has been endorsed by the contributor, and it is +therefore unnecessary to ask the contributor again to confirm it. + +I have not asked any contributors (or their employers, if they have them) for +proofs that they have the right to distribute their software in this way. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Relax NG Object/Parser v.20050510, +which may be included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright (c) Kohsuke Kawaguchi + +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. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to RelaxNGCC v1.12, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright (c) 2000-2003 Daisuke Okajima and Kohsuke Kawaguchi. +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. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: + + "This product includes software developed by Daisuke Okajima + and Kohsuke Kawaguchi (http://relaxngcc.sf.net/)." + +Alternately, this acknowledgment may appear in the software itself, if and +wherever such third-party acknowledgments normally appear. + +4. The names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission. For + written permission, please contact the copyright holders. + +5. Products derived from this software may not be called "RELAXNGCC", nor may + "RELAXNGCC" appear in their name, without prior written permission of the + copyright holders. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED 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 APACHE +SOFTWARE FOUNDATION OR ITS 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. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to SAX 2.0.1, which may be included +with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + + SAX is free! + + In fact, it's not possible to own a license to SAX, since it's been placed in + the public domain. + + No Warranty + + Because SAX is released to the public domain, there is no warranty for the + design or for the software implementation, to the extent permitted by + applicable law. Except when otherwise stated in writing the copyright holders + and/or other parties provide SAX "as is" without warranty of any kind, either + expressed or implied, including, but not limited to, the implied warranties + of merchantability and fitness for a particular purpose. The entire risk as + to the quality and performance of SAX is with you. Should SAX prove + defective, you assume the cost of all necessary servicing, repair or + correction. + + In no event unless required by applicable law or agreed to in writing will + any copyright holder, or any other party who may modify and/or redistribute + SAX, be liable to you for damages, including any general, special, incidental + or consequential damages arising out of the use or inability to use SAX + (including but not limited to loss of data or data being rendered inaccurate + or losses sustained by you or third parties or a failure of the SAX to + operate with any other programs), even if such holder or other party has been + advised of the possibility of such damages. + + Copyright Disclaimers + + This page includes statements to that effect by David Megginson, who would + have been able to claim copyright for the original work. SAX 1.0 + + Version 1.0 of the Simple API for XML (SAX), created collectively by the + membership of the XML-DEV mailing list, is hereby released into the public + domain. + + No one owns SAX: you may use it freely in both commercial and non-commercial + applications, bundle it with your software distribution, include it on a + CD-ROM, list the source code in a book, mirror the documentation at your own + web site, or use it in any other way you see fit. + + David Megginson, sax@megginson.com + 1998-05-11 + + SAX 2.0 + + I hereby abandon any property rights to SAX 2.0 (the Simple API for XML), and + release all of the SAX 2.0 source code, compiled code, and documentation + contained in this distribution into the Public Domain. SAX comes with NO + WARRANTY or guarantee of fitness for any purpose. + + David Megginson, david@megginson.com + 2000-05-05 + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to SoftFloat version 2b, which may be +included with JRE 8, JDK 8, and OpenJDK 8 on Linux/ARM. + +--- begin of LICENSE --- + +Use of any of this software is governed by the terms of the license below: + +SoftFloat was written by me, John R. Hauser. This work was made possible in +part by the International Computer Science Institute, located at Suite 600, +1947 Center Street, Berkeley, California 94704. Funding was partially +provided by the National Science Foundation under grant MIP-9311980. The +original version of this code was written as part of a project to build +a fixed-point vector processor in collaboration with the University of +California at Berkeley, overseen by Profs. Nelson Morgan and John Wawrzynek. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL +LOSSES, COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO +FURTHERMORE EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER +SCIENCE INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, +COSTS, OR OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE +SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, provided +that the minimal documentation requirements stated in the source code are +satisfied. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Sparkle 1.5, +which may be included with JRE 8 on Mac OS X. + +--- begin of LICENSE --- + +Copyright (c) 2012 Sparkle.org and Andy Matuschak + +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. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% Portions licensed from Taligent, Inc. + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Thai Dictionary, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright (C) 1982 The Royal Institute, Thai Royal Government. + +Copyright (C) 1998 National Electronics and Computer Technology Center, +National Science and Technology Development Agency, +Ministry of Science Technology and Environment, +Thai Royal Government. + +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. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Unicode 6.2.0 & CLDR 21.0.1 +which may be included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Unicode Terms of Use + +For the general privacy policy governing access to this site, see the Unicode +Privacy Policy. For trademark usage, see the Unicode® Consortium Name and +Trademark Usage Policy. + +A. Unicode Copyright. + 1. Copyright © 1991-2013 Unicode, Inc. All rights reserved. + + 2. Certain documents and files on this website contain a legend indicating + that "Modification is permitted." Any person is hereby authorized, + without fee, to modify such documents and files to create derivative + works conforming to the Unicode® Standard, subject to Terms and + Conditions herein. + + 3. Any person is hereby authorized, without fee, to view, use, reproduce, + and distribute all documents and files solely for informational + purposes in the creation of products supporting the Unicode Standard, + subject to the Terms and Conditions herein. + + 4. Further specifications of rights and restrictions pertaining to the use + of the particular set of data files known as the "Unicode Character + Database" can be found in Exhibit 1. + + 5. Each version of the Unicode Standard has further specifications of + rights and restrictions of use. For the book editions (Unicode 5.0 and + earlier), these are found on the back of the title page. The online + code charts carry specific restrictions. All other files, including + online documentation of the core specification for Unicode 6.0 and + later, are covered under these general Terms of Use. + + 6. No license is granted to "mirror" the Unicode website where a fee is + charged for access to the "mirror" site. + + 7. Modification is not permitted with respect to this document. All copies + of this document must be verbatim. + +B. Restricted Rights Legend. Any technical data or software which is licensed + to the United States of America, its agencies and/or instrumentalities + under this Agreement is commercial technical data or commercial computer + software developed exclusively at private expense as defined in FAR 2.101, + or DFARS 252.227-7014 (June 1995), as applicable. For technical data, use, + duplication, or disclosure by the Government is subject to restrictions as + set forth in DFARS 202.227-7015 Technical Data, Commercial and Items (Nov + 1995) and this Agreement. For Software, in accordance with FAR 12-212 or + DFARS 227-7202, as applicable, use, duplication or disclosure by the + Government is subject to the restrictions set forth in this Agreement. + +C. Warranties and Disclaimers. + 1. This publication and/or website may include technical or typographical + errors or other inaccuracies . Changes are periodically added to the + information herein; these changes will be incorporated in new editions + of the publication and/or website. Unicode may make improvements and/or + changes in the product(s) and/or program(s) described in this + publication and/or website at any time. + + 2. If this file has been purchased on magnetic or optical media from + Unicode, Inc. the sole and exclusive remedy for any claim will be + exchange of the defective media within ninety (90) days of original + purchase. + + 3. EXCEPT AS PROVIDED IN SECTION C.2, THIS PUBLICATION AND/OR SOFTWARE IS + PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND EITHER EXPRESS, IMPLIED, + OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. + UNICODE AND ITS LICENSORS ASSUME NO RESPONSIBILITY FOR ERRORS OR + OMISSIONS IN THIS PUBLICATION AND/OR SOFTWARE OR OTHER DOCUMENTS WHICH + ARE REFERENCED BY OR LINKED TO THIS PUBLICATION OR THE UNICODE WEBSITE. + +D. Waiver of Damages. In no event shall Unicode or its licensors be liable for + any special, incidental, indirect or consequential damages of any kind, or + any damages whatsoever, whether or not Unicode was advised of the + possibility of the damage, including, without limitation, those resulting + from the following: loss of use, data or profits, in connection with the + use, modification or distribution of this information or its derivatives. + +E.Trademarks & Logos. + 1. The Unicode Word Mark and the Unicode Logo are trademarks of Unicode, + Inc. “The Unicode Consortium” and “Unicode, Inc.” are trade names of + Unicode, Inc. Use of the information and materials found on this + website indicates your acknowledgement of Unicode, Inc.’s exclusive + worldwide rights in the Unicode Word Mark, the Unicode Logo, and the + Unicode trade names. + + 2. The Unicode Consortium Name and Trademark Usage Policy (“Trademark + Policy”) are incorporated herein by reference and you agree to abide by + the provisions of the Trademark Policy, which may be changed from time + to time in the sole discretion of Unicode, Inc. + + 3. All third party trademarks referenced herein are the property of their + respective owners. + +Miscellaneous. + 1. Jurisdiction and Venue. This server is operated from a location in the + State of California, United States of America. Unicode makes no + representation that the materials are appropriate for use in other + locations. If you access this server from other locations, you are + responsible for compliance with local laws. This Agreement, all use of + this site and any claims and damages resulting from use of this site are + governed solely by the laws of the State of California without regard to + any principles which would apply the laws of a different jurisdiction. + The user agrees that any disputes regarding this site shall be resolved + solely in the courts located in Santa Clara County, California. The user + agrees said courts have personal jurisdiction and agree to waive any + right to transfer the dispute to any other forum. + + 2. Modification by Unicode. Unicode shall have the right to modify this + Agreement at any time by posting it to this site. The user may not + assign any part of this Agreement without Unicode’s prior written + consent. + + 3. Taxes. The user agrees to pay any taxes arising from access to this + website or use of the information herein, except for those based on + Unicode’s net income. + + 4. Severability. If any provision of this Agreement is declared invalid or + unenforceable, the remaining provisions of this Agreement shall remain + in effect. + + 5. Entire Agreement. This Agreement constitutes the entire agreement + between the parties. + +EXHIBIT 1 +UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE + +Unicode Data Files include all data files under the directories +http://www.unicode.org/Public/, http://www.unicode.org/reports/, and +http://www.unicode.org/cldr/data/. Unicode Data Files do not include PDF +online code charts under the directory http://www.unicode.org/Public/. +Software includes any source code published in the Unicode Standard or under +the directories http://www.unicode.org/Public/, +http://www.unicode.org/reports/, and http://www.unicode.org/cldr/data/. + +NOTICE TO USER: Carefully read the following legal agreement. BY DOWNLOADING, +INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S DATA FILES ("DATA +FILES"), AND/OR SOFTWARE ("SOFTWARE"), YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO +BE BOUND BY, ALL OF THE TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT +AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR +SOFTWARE. + +COPYRIGHT AND PERMISSION NOTICE + +Copyright © 1991-2012 Unicode, Inc. All rights reserved. Distributed under the +Terms of Use in http://www.unicode.org/copyright.html. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the Unicode data files and any associated documentation (the "Data Files") +or Unicode software and any associated documentation (the "Software") to deal +in the Data Files or Software without restriction, including without +limitation the rights to use, copy, modify, merge, publish, distribute, and/or +sell copies of the Data Files or Software, and to permit persons to whom the +Data Files or Software are furnished to do so, provided that (a) the above +copyright notice(s) and this permission notice appear with all copies of the +Data Files or Software, (b) both the above copyright notice(s) and this +permission notice appear in associated documentation, and (c) there is clear +notice in each modified Data File or in the Software as well as in the +documentation associated with the Data File(s) or Software that the data or +software has been modified. + +THE DATA FILES AND SOFTWARE ARE 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 OF THIRD +PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN +THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE +DATA FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall not +be used in advertising or otherwise to promote the sale, use or other dealings +in these Data Files or Software without prior written authorization of the +copyright holder. + +Unicode and the Unicode logo are trademarks of Unicode, Inc. in the United +States and other countries. All third party trademarks referenced herein are +the property of their respective owners. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to UPX v3.01, which may be included +with JRE 8 on Windows. + +--- begin of LICENSE --- + +Use of any of this software is governed by the terms of the license below: + + + ooooo ooo ooooooooo. ooooooo ooooo + `888' `8' `888 `Y88. `8888 d8' + 888 8 888 .d88' Y888..8P + 888 8 888ooo88P' `8888' + 888 8 888 .8PY888. + `88. .8' 888 d8' `888b + `YbodP' o888o o888o o88888o + + + The Ultimate Packer for eXecutables + Copyright (c) 1996-2000 Markus Oberhumer & Laszlo Molnar + http://wildsau.idv.uni-linz.ac.at/mfx/upx.html + http://www.nexus.hu/upx + http://upx.tsx.org + + +PLEASE CAREFULLY READ THIS LICENSE AGREEMENT, ESPECIALLY IF YOU PLAN +TO MODIFY THE UPX SOURCE CODE OR USE A MODIFIED UPX VERSION. + + +ABSTRACT +======== + + UPX and UCL are copyrighted software distributed under the terms + of the GNU General Public License (hereinafter the "GPL"). + + The stub which is imbedded in each UPX compressed program is part + of UPX and UCL, and contains code that is under our copyright. The + terms of the GNU General Public License still apply as compressing + a program is a special form of linking with our stub. + + As a special exception we grant the free usage of UPX for all + executables, including commercial programs. + See below for details and restrictions. + + +COPYRIGHT +========= + + UPX and UCL are copyrighted software. All rights remain with the authors. + + UPX is Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer + UPX is Copyright (C) 1996-2000 Laszlo Molnar + + UCL is Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer + + +GNU GENERAL PUBLIC LICENSE +========================== + + UPX and the UCL library are free software; you can redistribute them + and/or modify them under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + UPX and UCL are distributed in the hope that they 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 for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + + +SPECIAL EXCEPTION FOR COMPRESSED EXECUTABLES +============================================ + + The stub which is imbedded in each UPX compressed program is part + of UPX and UCL, and contains code that is under our copyright. The + terms of the GNU General Public License still apply as compressing + a program is a special form of linking with our stub. + + Hereby Markus F.X.J. Oberhumer and Laszlo Molnar grant you special + permission to freely use and distribute all UPX compressed programs + (including commercial ones), subject to the following restrictions: + + 1. You must compress your program with a completely unmodified UPX + version; either with our precompiled version, or (at your option) + with a self compiled version of the unmodified UPX sources as + distributed by us. + 2. This also implies that the UPX stub must be completely unmodfied, i.e. + the stub imbedded in your compressed program must be byte-identical + to the stub that is produced by the official unmodified UPX version. + 3. The decompressor and any other code from the stub must exclusively get + used by the unmodified UPX stub for decompressing your program at + program startup. No portion of the stub may get read, copied, + called or otherwise get used or accessed by your program. + + +ANNOTATIONS +=========== + + - You can use a modified UPX version or modified UPX stub only for + programs that are compatible with the GNU General Public License. + + - We grant you special permission to freely use and distribute all UPX + compressed programs. But any modification of the UPX stub (such as, + but not limited to, removing our copyright string or making your + program non-decompressible) will immediately revoke your right to + use and distribute a UPX compressed program. + + - UPX is not a software protection tool; by requiring that you use + the unmodified UPX version for your proprietary programs we + make sure that any user can decompress your program. This protects + both you and your users as nobody can hide malicious code - + any program that cannot be decompressed is highly suspicious + by definition. + + - You can integrate all or part of UPX and UCL into projects that + are compatible with the GNU GPL, but obviously you cannot grant + any special exceptions beyond the GPL for our code in your project. + + - We want to actively support manufacturers of virus scanners and + similar security software. Please contact us if you would like to + incorporate parts of UPX or UCL into such a product. + + + +Markus F.X.J. Oberhumer Laszlo Molnar +markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu + +Linz, Austria, 25 Feb 2000 + +Additional License(s) + +The UPX license file is at http://upx.sourceforge.net/upx-license.html. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Xfree86-VidMode Extension 1.0, +which may be included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. + +--- begin of LICENSE --- + +Version 1.1 of XFree86 ProjectLicence. + +Copyright (C) 1994-2004 The XFree86 Project, Inc. All rights reserved. + +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, sublicence, 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: + + 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, and in the same place + and form as other copyright, license and disclaimer information. + + 3. The end-user documentation included with the redistribution, if any,must + include the following acknowledgment: "This product includes + software developed by The XFree86 Project, Inc (http://www.xfree86.org/) and + its contributors", in the same place and form as other third-party + acknowledgments. Alternately, this acknowledgment may appear in the software + itself, in the same form and location as other such third-party + acknowledgments. + + 4. Except as contained in this notice, the name of The XFree86 Project,Inc + shall not be used in advertising or otherwise to promote the sale, use + or other dealings in this Software without prior written authorization from + The XFree86 Project, Inc. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 XFREE86 PROJECT, INC OR ITS 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. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to X Window System 6.8.2, which may be +included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. + +--- begin of LICENSE --- + + Licenses +The X.Org Foundation March 2004 + +1. Introduction + +The X.org Foundation X Window System distribution is a compilation of code and +documentation from many sources. This document is intended primarily as a +guide to the licenses used in the distribution: you must check each file +and/or package for precise redistribution terms. None-the-less, this summary +may be useful to many users. No software incorporating the XFree86 1.1 license +has been incorporated. + +This document is based on the compilation from XFree86. + +2. XFree86 License + +XFree86 code without an explicit copyright is covered by the following +copyright/license: + +Copyright (C) 1994-2003 The XFree86 Project, Inc. All Rights Reserved. + +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 +XFREE86 PROJECT 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. + +Except as contained in this notice, the name of the XFree86 Project shall not +be used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the XFree86 Project. + +3. Other Licenses + +Portions of code are covered by the following licenses/copyrights. See +individual files for the copyright dates. + +3.1. X/MIT Copyrights + +3.1.1. X Consortium + +Copyright (C) X Consortium + +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 X +CONSORTIUM 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. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from the X Consortium. + +X Window System is a trademark of X Consortium, Inc. + +3.1.2. The Open Group + +Copyright The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that the +above copyright notice appear in all copies and that both that copyright +notice and this permission notice appear in supporting documentation. + +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 +OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from The Open Group. 3.2. +Berkeley-based copyrights: + +o +3.2.1. General + +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. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. 3.2.2. UCB/LBL + +Copyright (c) 1993 The Regents of the University of California. All rights +reserved. + +This software was developed by the Computer Systems Engineering group at +Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and contributed to +Berkeley. + +All advertising materials mentioning features or use of this software must +display the following acknowledgement: This product includes software +developed by the University of California, Lawrence Berkeley Laboratory. + +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. All advertising materials mentioning features or use of this software + must display the following acknowledgement: This product includes software + developed by the University of California, Berkeley and its contributors. + + 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. 3.2.3. The +NetBSD Foundation, Inc. + +Copyright (c) 2003 The NetBSD Foundation, Inc. All rights reserved. + +This code is derived from software contributed to The NetBSD Foundation by Ben +Collver + +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. All advertising materials mentioning features or use of this software + must display the following acknowledgement: This product includes software + developed by the NetBSD Foundation, Inc. and its contributors. + + 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. 3.2.4. Theodore +Ts'o. + +Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999. 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, + and the entire permission notice in its entirety, including the disclaimer + of warranties. + + 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. he name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE, ALL OF WHICH ARE HEREBY DISCLAIMED. IN NO +EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. 3.2.5. Theo de Raadt and Damien Miller + +Copyright (c) 1995,1999 Theo de Raadt. All rights reserved. Copyright (c) +2001-2002 Damien Miller. 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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. 3.2.6. Todd C. Miller + +Copyright (c) 1998 Todd C. Miller + +Permission to use, copy, modify, and distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright +notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 3.2.7. Thomas +Winischhofer + +Copyright (C) 2001-2004 Thomas Winischhofer + +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. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED 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 AUTHOR 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. 3.3. NVIDIA Corp + +Copyright (c) 1996 NVIDIA, Corp. All rights reserved. + +NOTICE TO USER: The source code is copyrighted under U.S. and international +laws. NVIDIA, Corp. of Sunnyvale, California owns the copyright and as design +patents pending on the design and interface of the NV chips. Users and +possessors of this source code are hereby granted a nonexclusive, royalty-free +copyright and design patent license to use this code in individual and +commercial software. + +Any use of this source code must include, in the user documentation and +internal comments to the code, notices to the end user as follows: + +Copyright (c) 1996 NVIDIA, Corp. NVIDIA design patents pending in the U.S. and +foreign countries. + +NVIDIA, CORP. MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE +CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED +WARRANTY OF ANY KIND. NVIDIA, CORP. DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA, CORP. BE LIABLE +FOR ANY SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY +DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. 3.4. GLX Public +License + +GLX PUBLIC LICENSE (Version 1.0 (2/11/99)) ("License") + +Subject to any third party claims, Silicon Graphics, Inc. ("SGI") hereby +grants permission to Recipient (defined below), under Recipient's copyrights +in the Original Software (defined below), to use, copy, modify, merge, +publish, distribute, sublicense and/or sell copies of Subject Software +(defined below), and to permit persons to whom the Subject Software is +furnished in accordance with this License to do the same, subject to all of +the following terms and conditions, which Recipient accepts by engaging in any +such use, copying, modifying, merging, publishing, distributing, sublicensing +or selling: + +1. Definitions. + + (a) "Original Software" means source code of computer software code which + is described in Exhibit A as Original Software. + + (b) "Modifications" means any addition to or deletion from the substance + or structure of either the Original Software or any previous + Modifications. When Subject Software is released as a series of files, a + Modification means (i) any addition to or deletion from the contents of a + file containing Original Software or previous Modifications and (ii) any + new file that contains any part of the Original Code or previous + Modifications. + + (c) "Subject Software" means the Original Software or Modifications or the + combination of the Original Software and Modifications, or portions of any + of the foregoing. + + (d) "Recipient" means an individual or a legal entity exercising rights + under, and complying with all of the terms of, this License. For legal + entities, "Recipient" includes any entity which controls, is controlled + by, or is under common control with Recipient. For purposes of this + definition, "control" of an entity means (a) the power, direct or + indirect, to direct or manage such entity, or (b) ownership of fifty + percent (50%) or more of the outstanding shares or beneficial ownership of + such entity. + +2. Redistribution of Source Code Subject to These Terms. Redistributions of +Subject Software in source code form must retain the notice set forth in +Exhibit A, below, in every file. A copy of this License must be included in +any documentation for such Subject Software where the recipients' rights +relating to Subject Software are described. Recipient may distribute the +source code version of Subject Software under a license of Recipient's choice, +which may contain terms different from this License, provided that (i) +Recipient is in compliance with the terms of this License, and (ii) the +license terms include this Section 2 and Sections 3, 4, 7, 8, 10, 12 and 13 of +this License, which terms may not be modified or superseded by any other terms +of such license. If Recipient distributes the source code version under a +different license Recipient must make it absolutely clear that any terms which +differ from this License are offered by Recipient alone, not by SGI. Recipient +hereby agrees to indemnify SGI for any liability incurred by SGI as a result +of any such terms Recipient offers. + +3. Redistribution in Executable Form. The notice set forth in Exhibit A must +be conspicuously included in any notice in an executable version of Subject +Software, related documentation or collateral in which Recipient describes the +user's rights relating to the Subject Software. Recipient may distribute the +executable version of Subject Software under a license of Recipient's choice, +which may contain terms different from this License, provided that (i) +Recipient is in compliance with the terms of this License, and (ii) the +license terms include this Section 3 and Sections 4, 7, 8, 10, 12 and 13 of +this License, which terms may not be modified or superseded by any other terms +of such license. If Recipient distributes the executable version under a +different license Recipient must make it absolutely clear that any terms which +differ from this License are offered by Recipient alone, not by SGI. Recipient +hereby agrees to indemnify SGI for any liability incurred by SGI as a result +of any such terms Recipient offers. + +4. Termination. This License and the rights granted hereunder will terminate +automatically if Recipient fails to comply with terms herein and fails to cure +such breach within 30 days of the breach. Any sublicense to the Subject +Software which is properly granted shall survive any termination of this +License absent termination by the terms of such sublicense. Provisions which, +by their nature, must remain in effect beyond the termination of this License +shall survive. + +5. No Trademark Rights. This License does not grant any rights to use any +trade name, trademark or service mark whatsoever. No trade name, trademark or +service mark of SGI may be used to endorse or promote products derived from +the Subject Software without prior written permission of SGI. + +6. No Other Rights. This License does not grant any rights with respect to the +OpenGL API or to any software or hardware implementation thereof or to any +other software whatsoever, nor shall any other rights or licenses not +expressly granted hereunder arise by implication, estoppel or otherwise with +respect to the Subject Software. Title to and ownership of the Original +Software at all times remains with SGI. All rights in the Original Software +not expressly granted under this License are reserved. + +7. Compliance with Laws; Non-Infringement. Recipient shall comply with all +applicable laws and regulations in connection with use and distribution of the +Subject Software, including but not limited to, all export and import control +laws and regulations of the U.S. government and other countries. Recipient may +not distribute Subject Software that (i) in any way infringes (directly or +contributorily) the rights (including patent, copyright, trade secret, +trademark or other intellectual property rights of any kind) of any other +person or entity or (ii) breaches any representation or warranty, express, +implied or statutory, which under any applicable law it might be deemed to +have been distributed. + +8. Claims of Infringement. If Recipient at any time has knowledge of any one +or more third party claims that reproduction, modification, use, distribution, +import or sale of Subject Software (including particular functionality or code +incorporated in Subject Software) infringes the third party's intellectual +property rights, Recipient must place in a well-identified web page bearing +the title "LEGAL" a description of each such claim and a description of the +party making each such claim in sufficient detail that a user of the Subject +Software will know whom to contact regarding the claim. Also, upon gaining +such knowledge of any such claim, Recipient must conspicuously include the URL +for such web page in the Exhibit A notice required under Sections 2 and 3, +above, and in the text of any related documentation, license agreement or +collateral in which Recipient describes end user's rights relating to the +Subject Software. If Recipient obtains such knowledge after it makes Subject +Software available to any other person or entity, Recipient shall take other +steps (such as notifying appropriate mailing lists or newsgroups) reasonably +calculated to inform those who received the Subject Software that new +knowledge has been obtained. + +9. DISCLAIMER OF WARRANTY. SUBJECT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, +WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT +LIMITATION, WARRANTIES THAT THE SUBJECT SOFTWARE IS FREE OF DEFECTS, +MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON- INFRINGING. SGI ASSUMES NO +RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE. SHOULD ANY SOFTWARE +PROVE DEFECTIVE IN ANY RESPECT, SGI ASSUMES NO COST OR LIABILITY FOR ANY +SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN +ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY SUBJECT SOFTWARE IS AUTHORIZED +HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +10. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, +WHETHER TORT (INCLUDING, WITHOUT LIMITATION, NEGLIGENCE OR STRICT LIABILITY), +CONTRACT, OR OTHERWISE, SHALL SGI OR ANY SGI LICENSOR BE LIABLE FOR ANY +DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY +CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK +STOPPAGE, LOSS OF DATA, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER +COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF +THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY +TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SGI's NEGLIGENCE TO +THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT +ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO +THAT EXCLUSION AND LIMITATION MAY NOT APPLY TO RECIPIENT. + +11. Indemnity. Recipient shall be solely responsible for damages arising, +directly or indirectly, out of its utilization of rights under this License. +Recipient will defend, indemnify and hold harmless Silicon Graphics, Inc. from +and against any loss, liability, damages, costs or expenses (including the +payment of reasonable attorneys fees) arising out of Recipient's use, +modification, reproduction and distribution of the Subject Software or out of +any representation or warranty made by Recipient. + +12. U.S. Government End Users. The Subject Software is a "commercial item" +consisting of "commercial computer software" as such terms are defined in +title 48 of the Code of Federal Regulations and all U.S. Government End Users +acquire only the rights set forth in this License and are subject to the terms +of this License. + +13. Miscellaneous. This License represents the complete agreement concerning +subject matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed so as to achieve as nearly as +possible the same economic effect as the original provision and the remainder +of this License will remain in effect. This License shall be governed by and +construed in accordance with the laws of the United States and the State of +California as applied to agreements entered into and to be performed entirely +within California between California residents. Any litigation relating to +this License shall be subject to the exclusive jurisdiction of the Federal +Courts of the Northern District of California (or, absent subject matter +jurisdiction in such courts, the courts of the State of California), with +venue lying exclusively in Santa Clara County, California, with the losing +party responsible for costs, including without limitation, court costs and +reasonable attorneys fees and expenses. The application of the United Nations +Convention on Contracts for the International Sale of Goods is expressly +excluded. Any law or regulation which provides that the language of a contract +shall be construed against the drafter shall not apply to this License. + +Exhibit A + +The contents of this file are subject to Sections 2, 3, 4, 7, 8, 10, 12 and 13 +of the GLX Public License Version 1.0 (the "License"). You may not use this +file except in compliance with those sections of the License. You may obtain a +copy of the License at Silicon Graphics, Inc., attn: Legal Services, 2011 N. +Shoreline Blvd., Mountain View, CA 94043 or at +http://www.sgi.com/software/opensource/glx/license.html. + +Software distributed under the License is distributed on an "AS IS" basis. ALL +WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED +WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR PURPOSE OR OF NON- +INFRINGEMENT. See the License for the specific language governing rights and +limitations under the License. + +The Original Software is GLX version 1.2 source code, released February, 1999. +The developer of the Original Software is Silicon Graphics, Inc. Those +portions of the Subject Software created by Silicon Graphics, Inc. are +Copyright (c) 1991-9 Silicon Graphics, Inc. All Rights Reserved. 3.5. CID +Font Code Public License + +CID FONT CODE PUBLIC LICENSE (Version 1.0 (3/31/99))("License") + +Subject to any applicable third party claims, Silicon Graphics, Inc. ("SGI") +hereby grants permission to Recipient (defined below), under SGI's copyrights +in the Original Software (defined below), to use, copy, modify, merge, +publish, distribute, sublicense and/or sell copies of Subject Software +(defined below) in both source code and executable form, and to permit persons +to whom the Subject Software is furnished in accordance with this License to +do the same, subject to all of the following terms and conditions, which +Recipient accepts by engaging in any such use, copying, modifying, merging, +publication, distributing, sublicensing or selling: + +1. Definitions. + + a. "Original Software" means source code of computer software code that is + described in Exhibit A as Original Software. + + b. "Modifications" means any addition to or deletion from the substance or + structure of either the Original Software or any previous Modifications. + When Subject Software is released as a series of files, a Modification + means (i) any addition to or deletion from the contents of a file + containing Original Software or previous Modifications and (ii) any new + file that contains any part of the Original Code or previous + Modifications. + + c. "Subject Software" means the Original Software or Modifications or the + combination of the Original Software and Modifications, or portions of any + of the foregoing. + + d. "Recipient" means an individual or a legal entity exercising rights + under the terms of this License. For legal entities, "Recipient" includes + any entity that controls, is controlled by, or is under common control + with Recipient. For purposes of this definition, "control" of an entity + means (i) the power, direct or indirect, to direct or manage such entity, + or (ii) ownership of fifty percent (50%) or more of the outstanding shares + or beneficial ownership of such entity. + + e. "Required Notice" means the notice set forth in Exhibit A to this + License. + + f. "Accompanying Technology" means any software or other technology that + is not a Modification and that is distributed or made publicly available + by Recipient with the Subject Software. Separate software files that do + not contain any Original Software or any previous Modification shall not + be deemed a Modification, even if such software files are aggregated as + part of a product, or in any medium of storage, with any file that does + contain Original Software or any previous Modification. + +2. License Terms. All distribution of the Subject Software must be made +subject to the terms of this License. A copy of this License and the Required +Notice must be included in any documentation for Subject Software where +Recipient's rights relating to Subject Software and/or any Accompanying +Technology are described. Distributions of Subject Software in source code +form must also include the Required Notice in every file distributed. In +addition, a ReadMe file entitled "Important Legal Notice" must be distributed +with each distribution of one or more files that incorporate Subject Software. +That file must be included with distributions made in both source code and +executable form. A copy of the License and the Required Notice must be +included in that file. Recipient may distribute Accompanying Technology under +a license of Recipient's choice, which may contain terms different from this +License, provided that (i) Recipient is in compliance with the terms of this +License, (ii) such other license terms do not modify or supersede the terms of +this License as applicable to the Subject Software, (iii) Recipient hereby +indemnifies SGI for any liability incurred by SGI as a result of the +distribution of Accompanying Technology or the use of other license terms. + +3. Termination. This License and the rights granted hereunder will terminate +automatically if Recipient fails to comply with terms herein and fails to cure +such breach within 30 days of the breach. Any sublicense to the Subject +Software that is properly granted shall survive any termination of this +License absent termination by the terms of such sublicense. Provisions which, +by their nature, must remain in effect beyond the termination of this License +shall survive. + +4. Trademark Rights. This License does not grant any rights to use any trade +name, trademark or service mark whatsoever. No trade name, trademark or +service mark of SGI may be used to endorse or promote products derived from or +incorporating any Subject Software without prior written permission of SGI. + +5. No Other Rights. No rights or licenses not expressly granted hereunder +shall arise by implication, estoppel or otherwise. Title to and ownership of +the Original Software at all times remains with SGI. All rights in the +Original Software not expressly granted under this License are reserved. + +6. Compliance with Laws; Non-Infringement. Recipient shall comply with all +applicable laws and regulations in connection with use and distribution of the +Subject Software, including but not limited to, all export and import control +laws and regulations of the U.S. government and other countries. Recipient may +not distribute Subject Software that (i) in any way infringes (directly or +contributorily) the rights (including patent, copyright, trade secret, +trademark or other intellectual property rights of any kind) of any other +person or entity, or (ii) breaches any representation or warranty, express, +implied or statutory, which under any applicable law it might be deemed to +have been distributed. + +7. Claims of Infringement. If Recipient at any time has knowledge of any one +or more third party claims that reproduction, modification, use, distribution, +import or sale of Subject Software (including particular functionality or code +incorporated in Subject Software) infringes the third party's intellectual +property rights, Recipient must place in a well-identified web page bearing +the title "LEGAL" a description of each such claim and a description of the +party making each such claim in sufficient detail that a user of the Subject +Software will know whom to contact regarding the claim. Also, upon gaining +such knowledge of any such claim, Recipient must conspicuously include the URL +for such web page in the Required Notice, and in the text of any related +documentation, license agreement or collateral in which Recipient describes +end user's rights relating to the Subject Software. If Recipient obtains such +knowledge after it makes Subject Software available to any other person or +entity, Recipient shall take other steps (such as notifying appropriate +mailing lists or newsgroups) reasonably calculated to provide such knowledge +to those who received the Subject Software. + +8. DISCLAIMER OF WARRANTY. SUBJECT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, +WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT +LIMITATION, WARRANTIES THAT THE SUBJECT SOFTWARE IS FREE OF DEFECTS, +MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. SGI ASSUMES NO +RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE. SHOULD ANY SOFTWARE +PROVE DEFECTIVE IN ANY RESPECT, SGI ASSUMES NO COST OR LIABILITY FOR ANY +SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN +ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY SUBJECT SOFTWARE IS AUTHORIZED +HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +9. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, +WHETHER TORT (INCLUDING, WITHOUT LIMITATION, NEGLIGENCE OR STRICT LIABILITY), +CONTRACT, OR OTHERWISE, SHALL SGI OR ANY SGI LICENSOR 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 SUBJECT SOFTWARE OR +THE USE OR OTHER DEALINGS IN THE SUBJECT SOFTWARE. SOME JURISDICTIONS DO NOT +ALLOW THE EXCLUSION OR LIMITATION OF CERTAIN DAMAGES, SO THIS EXCLUSION AND +LIMITATION MAY NOT APPLY TO RECIPIENT TO THE EXTENT SO DISALLOWED. + +10. Indemnity. Recipient shall be solely responsible for damages arising, +directly or indirectly, out of its utilization of rights under this License. +Recipient will defend, indemnify and hold SGI and its successors and assigns +harmless from and against any loss, liability, damages, costs or expenses +(including the payment of reasonable attorneys fees) arising out of +(Recipient's use, modification, reproduction and distribution of the Subject +Software or out of any representation or warranty made by Recipient. + +11. U.S. Government End Users. The Subject Software is a "commercial item" +consisting of "commercial computer software" as such terms are defined in +title 48 of the Code of Federal Regulations and all U.S. Government End Users +acquire only the rights set forth in this License and are subject to the terms +of this License. + +12. Miscellaneous. This License represents the complete agreement concerning +subject matter hereof. If any provision of this License is held to be +unenforceable by any judicial or administrative authority having proper +jurisdiction with respect thereto, such provision shall be reformed so as to +achieve as nearly as possible the same economic effect as the original +provision and the remainder of this License will remain in effect. This +License shall be governed by and construed in accordance with the laws of the +United States and the State of California as applied to agreements entered +into and to be performed entirely within California between California +residents. Any litigation relating to this License shall be subject to the +exclusive jurisdiction of the Federal Courts of the Northern District of +California (or, absent subject matter jurisdiction in such courts, the courts +of the State of California), with venue lying exclusively in Santa Clara +County, California, with the losing party responsible for costs, including +without limitation, court costs and reasonable attorneys fees and expenses. +The application of the United Nations Convention on Contracts for the +International Sale of Goods is expressly excluded. Any law or regulation that +provides that the language of a contract shall be construed against the +drafter shall not apply to this License. + +Exhibit A + +Copyright (c) 1994-1999 Silicon Graphics, Inc. + +The contents of this file are subject to the CID Font Code Public License +Version 1.0 (the "License"). You may not use this file except in compliance +with the License. You may obtain a copy of the License at Silicon Graphics, +Inc., attn: Legal Services, 2011 N. Shoreline Blvd., Mountain View, CA 94043 +or at http://www.sgi.com/software/opensource/cid/license.html + +Software distributed under the License is distributed on an "AS IS" basis. ALL +WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED +WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR PURPOSE OR OF +NON-INFRINGEMENT. See the License for the specific language governing rights +and limitations under the License. + +The Original Software (as defined in the License) is CID font code that was +developed by Silicon Graphics, Inc. Those portions of the Subject Software (as +defined in the License) that were created by Silicon Graphics, Inc. are +Copyright (c) 1994-1999 Silicon Graphics, Inc. All Rights Reserved. + +[NOTE: When using this text in connection with Subject Software delivered +solely in object code form, Recipient may replace the words "this file" with +"this software" in both the first and second sentences.] 3.6. Bitstream Vera +Fonts Copyright + +The fonts have a generous copyright, allowing derivative works (as long as +"Bitstream" or "Vera" are not in the names), and full redistribution (so long +as they are not *sold* by themselves). They can be be bundled, redistributed +and sold with any software. + +The fonts are distributed under the following copyright: + +Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a +trademark of Bitstream, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the fonts accompanying this license ("Fonts") and associated documentation +files (the "Font Software"), to reproduce and distribute the Font Software, +including without limitation the rights to use, copy, merge, publish, +distribute, and/or sell copies of the Font Software, and to permit persons to +whom the Font Software is furnished to do so, subject to the following +conditions: + +The above copyright and trademark notices and this permission notice shall be +included in all copies of one or more of the Font Software typefaces. + +The Font Software may be modified, altered, or added to, and in particular the +designs of glyphs or characters in the Fonts may be modified and additional +glyphs or characters may be added to the Fonts, only if the fonts are renamed +to names not containing either the words "Bitstream" or the word "Vera". + +This License becomes null and void to the extent applicable to Fonts or Font +Software that has been modified and is distributed under the "Bitstream Vera" +names. + +The Font Software may be sold as part of a larger software package but no copy +of one or more of the Font Software typefaces may be sold by itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, +TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, +SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO +USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. + +Except as contained in this notice, the names of Gnome, the Gnome Foundation, +and Bitstream Inc., shall not be used in advertising or otherwise to promote +the sale, use or other dealings in this Font Software without prior written +authorization from the Gnome Foundation or Bitstream Inc., respectively. For +further information, contact: fonts at gnome dot org. 3.7. Bigelow & Holmes +Inc and URW++ GmbH Luxi font license + +Luxi fonts copyright (c) 2001 by Bigelow & Holmes Inc. Luxi font instruction +code copyright (c) 2001 by URW++ GmbH. All Rights Reserved. Luxi is a +registered trademark of Bigelow & Holmes Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of these Fonts and associated documentation files (the "Font Software"), to +deal in the Font Software, including without limitation the rights to use, +copy, merge, publish, distribute, sublicense, and/or sell copies of the Font +Software, and to permit persons to whom the Font Software is furnished to do +so, subject to the following conditions: + +The above copyright and trademark notices and this permission notice shall be +included in all copies of one or more of the Font Software. + +The Font Software may not be modified, altered, or added to, and in particular +the designs of glyphs or characters in the Fonts may not be modified nor may +additional glyphs or characters be added to the Fonts. This License becomes +null and void when the Fonts or Font Software have been modified. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, +TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BIGELOW & HOLMES INC. OR URW++ +GMBH. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY +GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR +INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT +SOFTWARE. + +Except as contained in this notice, the names of Bigelow & Holmes Inc. and +URW++ GmbH. shall not be used in advertising or otherwise to promote the sale, +use or other dealings in this Font Software without prior written +authorization from Bigelow & Holmes Inc. and URW++ GmbH. + +For further information, contact: + +info@urwpp.de or design@bigelowandholmes.com + + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to zlib v1.2.5, which may be included +with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + + version 1.2.5, July 18th, 2005 + + Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to the following which may be +included with JRE 8, JDK 8, and OpenJDK 8, except where noted: + + Apache Commons Math 2.2 + Apache Derby 10.10.1.2 [included with JDK 8] + Apache Jakarta BCEL 5.2 + Apache Jakarta Regexp 1.4 + Apache Santuario XML Security for Java 1.5.4 + Apache Xalan-Java 2.7.1 + Apache Xerces Java 2.10.0 + Apache XML Resolver 1.1 + Dynalink 0.5 + + +--- begin of LICENSE --- + + 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. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + diff --git a/TRADEMARK b/TRADEMARK new file mode 100644 index 0000000..4f4a50b --- /dev/null +++ b/TRADEMARK @@ -0,0 +1,67 @@ +Version 1.2O, 2011/11/11 + +OpenJDK (the "Name") is a trademark of Oracle America, Inc. ("Oracle") +(the "Trademark Owner"). + +Trademark Owner publishes source code (the "Original Software") at +several World Wide Web locations (each a "Website"). These locations +include: + + http://download.java.net/openjdk/jdk6 + http://download.java.net/openjdk/jdk7 + http://download.java.net/openjdk/jdk8 + http://hg.openjdk.java.net/jdk6/jdk6 + http://hg.openjdk.java.net/jdk7/jdk7 + http://hg.openjdk.java.net/jdk8/jdk8 + +as well as any successor locations designated by Trademark Owner in +future revisions of this Notice. + +Each Website provides Original Software in two parts: A Java virtual +machine (the "Virtual Machine") and an API library and tools (the +"Library and Tools"). + +Trademark Owner permits any person obtaining a copy of this software +(the "Software") that is based on Original Software to use the Name in +the package names and version strings of the Software subject to the +following conditions: + + (1) The Software is a substantially complete implementation of the + OpenJDK development kit or runtime environment source code + retrieved from a single Website, and the vast majority of the + Software code is identical to that upstream Original Software, + except that: + + (a) Changes required to port Original Software to new operating + systems or hardware architectures are permitted, so long as + that work takes place in the context of an approved Project + hosted in the OpenJDK Community; and + + (b) A Virtual Machine from one Website may be combined with the + Library and Tools of another Website, so long as the vast + majority of the code in each is identical to the + corresponding upstream Virtual Machine or Library and Tools + component. + + (2) No permission is hereby granted to use the Name in any other + manner, unless such use constitutes "fair use", for example + "based on the OpenJDK source code" or "DistroXYZ's packaging of + the OpenJDK 6 code". + + (3) Trademark Owner makes no warranties of any kind respecting the + Name, and all representations and warranties, including any implied + warranty of merchantability, fitness for a particular purpose or + non-infringement are hereby disclaimed. + + (4) Finally, this notice and the following legend are included in all + copies of the Software or portions of it: + + Java and OpenJDK are trademarks or registered trademarks of + Oracle and/or its affiliates. + +Trademark Owner intends to revise this Notice as necessary in order to +meet the needs of the OpenJDK Community. Revisions to this notice will +be announced on the public mailing list announce at openjdk.java.net, to +which you may subscribe by visiting http://mail.openjdk.java.net. Please +send questions or comments about this Notice to the discuss list at the +same location. diff --git a/awt/AssemblyInfo.cs b/awt/AssemblyInfo.cs new file mode 100644 index 0000000..05a4049 --- /dev/null +++ b/awt/AssemblyInfo.cs @@ -0,0 +1,41 @@ +/* + Copyright (C) 2002-2010 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("IKVM.NET AWT Support")] +[assembly: AssemblyDescription("Winforms peers and 'native' code")] + +[assembly: System.Security.AllowPartiallyTrustedCallers] + +#if SIGNCODE +[assembly: InternalsVisibleTo("IKVM.OpenJDK.SwingAWT, PublicKey=0024000004800000940000000602000000240000525341310004000001000100DD6B140E5209CAE3D1C710030021EF589D0F00D05ACA8771101A7E99E10EE063E66040DF96E6F842F717BFC5B62D2EC2B62CEB0282E4649790DACB424DB29B68ADC7EAEAB0356FCE04702379F84400B8427EDBB33DAB8720B9F16A42E2CDB87F885EF413DBC4229F2BD157C9B8DC2CD14866DEC5F31C764BFB9394CC3C60E6C0")] +#else +[assembly: InternalsVisibleTo("IKVM.OpenJDK.SwingAWT")] +#endif diff --git a/awt/AssemblyInfo.cs.in b/awt/AssemblyInfo.cs.in new file mode 100644 index 0000000..a25f87d --- /dev/null +++ b/awt/AssemblyInfo.cs.in @@ -0,0 +1,41 @@ +/* + Copyright (C) 2002-2010 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("IKVM.NET AWT Support")] +[assembly: AssemblyDescription("Winforms peers and 'native' code")] + +[assembly: System.Security.AllowPartiallyTrustedCallers] + +#if SIGNCODE +[assembly: InternalsVisibleTo("IKVM.OpenJDK.SwingAWT, PublicKey=@PUBLICKEY@")] +#else +[assembly: InternalsVisibleTo("IKVM.OpenJDK.SwingAWT")] +#endif diff --git a/awt/IKVM.AWT.WinForms.8.csproj b/awt/IKVM.AWT.WinForms.8.csproj new file mode 100644 index 0000000..2947cd1 --- /dev/null +++ b/awt/IKVM.AWT.WinForms.8.csproj @@ -0,0 +1,161 @@ + + + Local + 9.0.30729 + 2.0 + {E00A0FA2-1FD7-4DD9-8C06-7202CE366102} + Debug + AnyCPU + + + + + IKVM.AWT.WinForms + + + JScript + Grid + IE50 + false + Library + awt + OnBuildSuccess + + + + + + + 2.0 + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + + + bin\Debug\ + false + 285212672 + false + + + TRACE;DEBUG;WHIDBEY + + + true + 4096 + false + 672,612 + false + false + false + false + 4 + full + prompt + + + + False + ..\bin\IKVM.OpenJDK.Core.dll + + + False + ..\bin\IKVM.OpenJDK.Media.dll + + + False + ..\bin\IKVM.OpenJDK.Misc.dll + + + False + ..\bin\IKVM.OpenJDK.SwingAWT.dll + + + False + ..\bin\IKVM.OpenJDK.Text.dll + + + System + + + + System.Drawing + + + System.Windows.Forms + + + + + + Code + + + Code + + + + Code + + + + Code + + + + Code + + + + + Code + + + + + Form + + + + + {F5C7B588-0403-4AF2-A4DE-5697DE21BC2C} + IKVM.Runtime.8 + + + + + False + .NET Framework 2.0 %28x86%29 + true + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + + + + + + + + \ No newline at end of file diff --git a/awt/IconFactory.cs b/awt/IconFactory.cs new file mode 100644 index 0000000..353ce08 --- /dev/null +++ b/awt/IconFactory.cs @@ -0,0 +1,683 @@ +/* + Copyright (C) 2012 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +namespace ikvm.awt +{ + + using java.awt.image; + using System.IO; + using System.Drawing; + + /// + /// Encodes images in ICO format. + /// + internal class IconFactory + { + + /// + /// Indicates that ICO data represents an icon (.ICO). + /// + private const int TYPE_ICON = 1; + + private BinaryWriter writer; + + /// + /// Creates a new instance of IconFactory + internal IconFactory() + { + } + + /// + /// Create a Icon from the given list of images + /// + /// list of images + /// + internal Icon CreateIcon(java.util.List images, Size size) + { + MemoryStream stream = new MemoryStream(); + Write(images, stream); + stream.Position = 0; + return new Icon(stream, size); + } + + /// + /// Encodes and writes multiple images without colour depth conversion. + /// + /// + /// the list of source images to be encoded + /// + /// the output to which the encoded image will be written + internal void Write(java.util.List images, System.IO.Stream stream) + { + writer = new BinaryWriter(stream); + + int count = images.size(); + + // file header 6 + WriteFileHeader(count, TYPE_ICON); + + // file offset where images start + int fileOffset = 6 + count * 16; + + // icon entries 16 * count + for (int i = 0; i < count; i++) + { + BufferedImage imgc = (BufferedImage)images.get(i); + fileOffset += WriteIconEntry(imgc, fileOffset); + } + + // images + for (int i = 0; i < count; i++) + { + BufferedImage imgc = (BufferedImage)images.get(i); + + // info header + WriteInfoHeader(imgc); + // color map + if (imgc.getColorModel().getPixelSize() <= 8) + { + IndexColorModel icm = (IndexColorModel)imgc.getColorModel(); + WriteColorMap(icm); + } + // xor bitmap + WriteXorBitmap(imgc); + // and bitmap + WriteAndBitmap(imgc); + + } + } + + /// + /// Writes the ICO file header for an ICO containing the given number of + /// images. + /// + /// + /// the number of images in the ICO + /// + /// TYPE_ICON + private void WriteFileHeader(int count, int type) + { + // reserved 2 + writer.Write((short)0); + // type 2 + writer.Write((short)type); + // count 2 + writer.Write((short)count); + } + + /// + /// Encodes the AND bitmap for the given image according the its + /// alpha channel (transparency) and writes it to the given output. + /// + /// + /// the image to encode as the AND bitmap. + private void WriteAndBitmap(BufferedImage img) + { + WritableRaster alpha = img.getAlphaRaster(); + + // indexed transparency (eg. GIF files) + if (img.getColorModel() is IndexColorModel && img.getColorModel().hasAlpha()) + { + int w = img.getWidth(); + int h = img.getHeight(); + + int bytesPerLine = GetBytesPerLine1(w); + + byte[] line = new byte[bytesPerLine]; + + IndexColorModel icm = (IndexColorModel)img.getColorModel(); + Raster raster = img.getRaster(); + + for (int y = h - 1; y >= 0; y--) + { + for (int x = 0; x < w; x++) + { + int bi = x / 8; + int i = x % 8; + // int a = alpha.getSample(x, y, 0); + int p = raster.getSample(x, y, 0); + int a = icm.getAlpha(p); + // invert bit since and mask is applied to xor mask + int b = ~a & 1; + line[bi] = SetBit(line[bi], i, b); + } + + writer.Write(line); + } + } + // no transparency + else if (alpha == null) + { + int h = img.getHeight(); + int w = img.getWidth(); + // calculate number of bytes per line, including 32-bit padding + int bytesPerLine = GetBytesPerLine1(w); + + byte[] line = new byte[bytesPerLine]; + for (int i = 0; i < bytesPerLine; i++) + { + line[i] = (byte)0; + } + + for (int y = h - 1; y >= 0; y--) + { + writer.Write(line); + } + } + // transparency (ARGB, etc. eg. PNG) + else + { + int w = img.getWidth(); + int h = img.getHeight(); + + int bytesPerLine = GetBytesPerLine1(w); + + byte[] line = new byte[bytesPerLine]; + + for (int y = h - 1; y >= 0; y--) + { + for (int x = 0; x < w; x++) + { + int bi = x / 8; + int i = x % 8; + int a = alpha.getSample(x, y, 0); + // invert bit since and mask is applied to xor mask + int b = ~a & 1; + line[bi] = SetBit(line[bi], i, b); + } + + writer.Write(line); + } + } + } + + private void WriteXorBitmap(BufferedImage img) + { + Raster raster = img.getRaster(); + switch (img.getColorModel().getPixelSize()) + { + case 1: + Write1(raster); + break; + case 4: + Write4(raster); + break; + case 8: + Write8(raster); + break; + case 24: + Write24(raster); + break; + case 32: + Raster alpha = img.getAlphaRaster(); + Write32(raster, alpha); + break; + } + } + + /// + /// Writes the InfoHeader structure to output + /// + /// + private void WriteInfoHeader(BufferedImage img) + { + // Size of InfoHeader structure = 40 + writer.Write(40); + // Width + writer.Write(img.getWidth()); + // Height + writer.Write(img.getHeight() * 2); + // Planes (=1) + writer.Write((short)1); + // Bit count + writer.Write((short)img.getColorModel().getPixelSize()); + // Compression + writer.Write(0); + // Image size - compressed size of image or 0 if Compression = 0 + writer.Write(0); + // horizontal resolution pixels/meter + writer.Write(0); + // vertical resolution pixels/meter + writer.Write(0); + // Colors used - number of colors actually used + writer.Write(0); + // Colors important - number of important colors 0 = all + writer.Write(0); + } + + /// + /// Writes the IconEntry structure to output + /// + private int WriteIconEntry(BufferedImage img, int fileOffset) + { + // Width 1 byte Cursor Width (16, 32 or 64) + int width = img.getWidth(); + writer.Write((byte)(width == 256 ? 0 : width)); + // Height 1 byte Cursor Height (16, 32 or 64 , most commonly = Width) + int height = img.getHeight(); + writer.Write((byte)(height == 256 ? 0 : height)); + // ColorCount 1 byte Number of Colors (2,16, 0=256) + short BitCount = (short)img.getColorModel().getPixelSize(); + int NumColors = 1 << (BitCount == 32 ? 24 : (int)BitCount); + byte ColorCount = (byte)(NumColors >= 256 ? 0 : NumColors); + writer.Write((byte)ColorCount); + // Reserved 1 byte =0 + writer.Write((byte)0); + // Planes 2 byte =1 + writer.Write((short)1); + // BitCount 2 byte bits per pixel (1, 4, 8) + writer.Write((short)BitCount); + // SizeInBytes 4 byte Size of (InfoHeader + ANDbitmap + XORbitmap) + int cmapSize = GetColorMapSize(BitCount); + int xorSize = GetBitmapSize(width, height, BitCount); + int andSize = GetBitmapSize(width, height, 1); + int size = 40 + cmapSize + xorSize + andSize; + writer.Write(size); + // FileOffset 4 byte FilePos, where InfoHeader starts + writer.Write(fileOffset); + return size; + } + + /// + /// Writes the colour map resulting from the source IndexColorModel. + /// + /// + /// the source IndexColorModel + private void WriteColorMap(IndexColorModel icm) + { + int mapSize = icm.getMapSize(); + for (int i = 0; i < mapSize; i++) + { + int rgb = icm.getRGB(i); + byte r = (byte)(rgb >> 16); + byte g = (byte)(rgb >> 8); + byte b = (byte)(rgb); + writer.Write(b); + writer.Write(g); + writer.Write(r); + writer.Write((byte)0); + } + } + + /// + /// Calculates the number of bytes per line required for the given width in + /// pixels, for a 1-bit bitmap. Lines are always padded to the next 4-byte + /// boundary. + /// + /// + /// the width in pixels + /// the number of bytes per line + private int GetBytesPerLine1(int width) + { + int ret = (int)width / 8; + if (ret % 4 != 0) + { + ret = (ret / 4 + 1) * 4; + } + return ret; + } + + /// + /// Calculates the number of bytes per line required for the given with in + /// pixels, for a 4-bit bitmap. Lines are always padded to the next 4-byte + /// boundary. + /// + /// + /// the width in pixels + /// the number of bytes per line + private int GetBytesPerLine4(int width) + { + int ret = (int)width / 2; + if (ret % 4 != 0) + { + ret = (ret / 4 + 1) * 4; + } + return ret; + } + + /// + /// Calculates the number of bytes per line required for the given with in + /// pixels, for a 8-bit bitmap. Lines are always padded to the next 4-byte + /// boundary. + /// + /// + /// the width in pixels + /// the number of bytes per line + private int GetBytesPerLine8(int width) + { + int ret = width; + if (ret % 4 != 0) + { + ret = (ret / 4 + 1) * 4; + } + return ret; + } + + /// + /// Calculates the number of bytes per line required for the given with in + /// pixels, for a 24-bit bitmap. Lines are always padded to the next 4-byte + /// boundary. + /// + /// + /// the width in pixels + /// the number of bytes per line + private int GetBytesPerLine24(int width) + { + int ret = width * 3; + if (ret % 4 != 0) + { + ret = (ret / 4 + 1) * 4; + } + return ret; + } + + /// + /// Calculates the size in bytes of a bitmap with the specified size and + /// colour depth. + /// + /// + /// the width in pixels + /// + /// the height in pixels + /// + /// the colour depth (bits per pixel) + /// the size of the bitmap in bytes + private int GetBitmapSize(int w, int h, int bpp) + { + int bytesPerLine = 0; + switch (bpp) + { + case 1: + bytesPerLine = GetBytesPerLine1(w); + break; + case 4: + bytesPerLine = GetBytesPerLine4(w); + break; + case 8: + bytesPerLine = GetBytesPerLine8(w); + break; + case 24: + bytesPerLine = GetBytesPerLine24(w); + break; + case 32: + bytesPerLine = w * 4; + break; + } + int ret = bytesPerLine * h; + return ret; + } + + /// + /// Encodes and writes raster data as a 1-bit bitmap. + /// + /// + /// the source raster data + private void Write1(Raster raster) + { + int bytesPerLine = GetBytesPerLine1(raster.getWidth()); + + byte[] line = new byte[bytesPerLine]; + + for (int y = raster.getHeight() - 1; y >= 0; y--) + { + for (int i = 0; i < bytesPerLine; i++) + { + line[i] = 0; + } + + for (int x = 0; x < raster.getWidth(); x++) + { + int bi = x / 8; + int i = x % 8; + int index = raster.getSample(x, y, 0); + line[bi] = SetBit(line[bi], i, index); + } + + writer.Write(line); + } + } + + /// + /// Encodes and writes raster data as a 4-bit bitmap. + /// + /// + /// the source raster data + private void Write4(Raster raster) + { + int width = raster.getWidth(); + int height = raster.getHeight(); + + // calculate bytes per line + int bytesPerLine = GetBytesPerLine4(width); + + // line buffer + byte[] line = new byte[bytesPerLine]; + + // encode and write lines + for (int y = height - 1; y >= 0; y--) + { + + // clear line buffer + for (int i = 0; i < bytesPerLine; i++) + { + line[i] = 0; + } + + // encode raster data for line + for (int x = 0; x < width; x++) + { + + // calculate buffer index + int bi = x / 2; + + // calculate nibble index (high order or low order) + int i = x % 2; + + // get color index + int index = raster.getSample(x, y, 0); + // set color index in buffer + line[bi] = SetNibble(line[bi], i, index); + } + + // write line data (padding bytes included) + writer.Write(line); + } + } + + /// + /// Encodes and writes raster data as an 8-bit bitmap. + /// + /// + /// the source raster data + private void Write8(Raster raster) + { + int width = raster.getWidth(); + int height = raster.getHeight(); + + // calculate bytes per line + int bytesPerLine = GetBytesPerLine8(width); + + // write lines + for (int y = height - 1; y >= 0; y--) + { + + // write raster data for each line + for (int x = 0; x < width; x++) + { + + // get color index for pixel + byte index = (byte)raster.getSample(x, y, 0); + + // write color index + writer.Write(index); + } + + // write padding bytes at end of line + for (int i = width; i < bytesPerLine; i++) + { + writer.Write((byte)0); + } + + } + } + + /// + /// Encodes and writes raster data as a 24-bit bitmap. + /// + /// + /// the source raster data + private void Write24(Raster raster) + { + int width = raster.getWidth(); + int height = raster.getHeight(); + + // calculate bytes per line + int bytesPerLine = GetBytesPerLine24(width); + + // write lines + for (int y = height - 1; y >= 0; y--) + { + + // write pixel data for each line + for (int x = 0; x < width; x++) + { + + // get RGB values for pixel + byte r = (byte)raster.getSample(x, y, 0); + byte g = (byte)raster.getSample(x, y, 1); + byte b = (byte)raster.getSample(x, y, 2); + + // write RGB values + writer.Write(b); + writer.Write(g); + writer.Write(r); + } + + // write padding bytes at end of line + for (int i = width * 3; i < bytesPerLine; i++) + { + writer.Write((byte)0); + } + } + } + + /// + /// Encodes and writes raster data, together with alpha (transparency) data, + /// as a 32-bit bitmap. + /// + /// + /// the source raster data + /// + /// the source alpha data + private void Write32(Raster raster, Raster alpha) + { + int width = raster.getWidth(); + int height = raster.getHeight(); + + // write lines + for (int y = height - 1; y >= 0; y--) + { + + // write pixel data for each line + for (int x = 0; x < width; x++) + { + + // get RGBA values + byte r = (byte)raster.getSample(x, y, 0); + byte g = (byte)raster.getSample(x, y, 1); + byte b = (byte)raster.getSample(x, y, 2); + byte a = (byte)alpha.getSample(x, y, 0); + + // write RGBA values + writer.Write(b); + writer.Write(g); + writer.Write(r); + writer.Write(a); + } + } + } + + /// + /// Sets a particular bit in a byte. + /// + /// + /// the source byte + /// + /// the index of the bit to set + /// + /// the value for the bit, which should be either 0 or + /// 1. + /// + /// resultant byte + private byte SetBit(byte bits, int index, int bit) + { + if (bit == 0) + { + bits &= (byte)~(1 << (7 - index)); + } + else + { + bits |= (byte)(1 << (7 - index)); + } + return bits; + } + + /// + /// Sets a particular nibble (4 bits) in a byte. + /// + /// + /// the source byte + /// + /// the index of the nibble to set + /// + /// value for the nibble, which should be in the range + /// 0x0..0xF. + private byte SetNibble(byte nibbles, int index, int nibble) + { + nibbles |= (byte)(nibble << ((1 - index) * 4)); + + return nibbles; + } + + /// + /// Calculates the size in bytes for a colour map with the specified bit + /// count. + /// + /// + /// the bit count, which represents the colour depth + /// the size of the colour map, in bytes if sBitCount is + /// less than or equal to 8, otherwise 0 as colour maps are + /// only used for bitmaps with a colour depth of 8 bits or less. + private int GetColorMapSize(short sBitCount) + { + int ret = 0; + if (sBitCount <= 8) + { + ret = (1 << sBitCount) * 4; + } + return ret; + } + + } +} diff --git a/awt/ShellApi.cs b/awt/ShellApi.cs new file mode 100644 index 0000000..446ada7 --- /dev/null +++ b/awt/ShellApi.cs @@ -0,0 +1,562 @@ +/* + Copyright (C) 2010 Karsten Heinrich (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.InteropServices; + +namespace awt +{ + public class ShellApi + { + + public static Guid GUID_ISHELLFOLDER = new Guid("{000214E6-0000-0000-C000-000000000046}"); + public static Guid GUID_ISHELLFOLDER2 = new Guid("{93F2F68C-1D1B-11d3-A30E-00C04F79ABD1}"); + + #region Windows API access by DLL + + /// + /// FreeMem for icon handles + /// + /// The icon handle; must not be in use. + /// + [DllImport("user32.dll")] + public static extern bool DestroyIcon(IntPtr hIcon); + + [DllImport("user32.dll")] + static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO piconinfo); + + [DllImport("shell32.dll")] + public static extern int FindExecutable(string lpFile, string lpDirectory, StringBuilder lpResult); + + /// + /// Returns the IShellFolder for the virtual desktop, which is the root any other folder. + /// See http://msdn.microsoft.com/en-us/library/bb762175%28VS.85%29.aspx + /// + [DllImport("shell32.dll")] + public static extern Int32 SHGetDesktopFolder(ref IShellFolder ppshf); + + /// + /// Returns informations aboud any filesystem object which can be addressed by a normal path. + /// See http://msdn.microsoft.com/en-us/library/bb762179%28VS.85%29.aspx + /// + [DllImport("shell32.dll")] + public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttribs, out SHFILEINFO psfi, uint cbFileInfo, SHGFI uFlags); + + + [DllImport("shell32.dll")] + public static extern IntPtr SHGetFileInfo(IntPtr pIDL, uint dwFileAttributes, out SHFILEINFO psfi, uint cbFileInfo, SHGFI uFlags); + + /// + /// Returns the pIDL for a special folder. + /// See http://msdn.microsoft.com/en-us/library/bb762203%28VS.85%29.aspx + /// + [DllImport("shell32.dll")] + public static extern Int32 SHGetSpecialFolderLocation(IntPtr hwndOwner, CSIDL nFolder, ref IntPtr ppidl); + + /// + /// Returns the path for a desktop-relative pIDL + /// See http://msdn.microsoft.com/en-us/library/bb762194%28VS.85%29.aspx + /// + [DllImport("shell32.dll")] + public static extern Boolean SHGetPathFromIDList(IntPtr pidl, StringBuilder pszPath); + + #endregion + + #region Flags and Enumerations + // see http://msdn.microsoft.com/en-us/library/bb762499(v=VS.85).aspx + + /// + /// Constants for IShellFolder.GetDisplayNameOf and IShellFolder.SetNameOf + /// + [Flags] + public enum SHGDN : uint + { + SHGDN_NORMAL = 0x0000, // Default + SHGDN_INFOLDER = 0x0001, // Displayed relative to a folder + SHGDN_FOREDITING = 0x1000, // for in-place editing + SHGDN_FORADDRESSBAR = 0x4000, + SHGDN_FORPARSING = 0x8000, // parsable by ParseDisplayName() + } + + /// + /// Filter constants for IShellFolder.EnumObjects + /// + [Flags] + public enum SHCONTF : uint + { + SHCONTF_CHECKING_FOR_CHILDREN = 0x00010,// >Win7. The calling application is checking for the existence of child items in the folder. + SHCONTF_FOLDERS = 0x0020, // Include folders + SHCONTF_NONFOLDERS = 0x0040, // Include non folders + SHCONTF_INCLUDEHIDDEN = 0x0080, // Show hidden items + SHCONTF_INIT_ON_FIRST_NEXT = 0x0100, // Allow EnumObject() to return before validating the enumeration + SHCONTF_NETPRINTERSRCH = 0x0200, // Hint that client is looking for printers + SHCONTF_SHAREABLE = 0x0400, // Hint that client is looking sharable resources + SHCONTF_STORAGE = 0x0800, // Include all items with accessible storage + SHCONTF_NAVIGATION_ENUM = 0x01000, // >Win7. Child folders should provide a navigation enumeration. + SHCONTF_FASTITEMS = 0x02000, // >Win7. The calling application is looking for resources that can be enumerated quickly. + SHCONTF_FLATLIST = 0x04000, // >Win7. Enumerate items as a simple list even if the folder itself is not structured in that way. + SHCONTF_ENABLE_ASYNC = 0x08000, // >Win7. The calling application is monitoring for change notifications. + SHCONTF_INCLUDESUPERHIDDEN = 0x10000 // >Win7. Include hidden system items in the enumeration. + } + + /// + /// Attributes of an IShellFolder object + /// + [Flags] + public enum SFGAOF : uint + { + SFGAO_CANCOPY = 0x1, // can be copied + SFGAO_CANMOVE = 0x2, // can be moved + SFGAO_CANLINK = 0x4, // can be linked + SFGAO_STORAGE = 0x00000008, // Supports BindToObject(IID_IStorage) + SFGAO_CANRENAME = 0x00000010, // can be renamed + SFGAO_CANDELETE = 0x00000020, // can be deleted + SFGAO_HASPROPSHEET = 0x00000040, // have property sheets + SFGAO_DROPTARGET = 0x00000100, // are drop target + SFGAO_CAPABILITYMASK = 0x00000177, + SFGAO_SYSTEM = 0x00001000, // >Win7, The specified items are system items. + SFGAO_ENCRYPTED = 0x00002000, // items are encrypted + SFGAO_ISSLOW = 0x00004000, // 'Slow' object + SFGAO_GHOSTED = 0x00008000, // Ghosted icon + SFGAO_LINK = 0x00010000, // Shortcut (link) + SFGAO_SHARE = 0x00020000, // Shared + SFGAO_READONLY = 0x00040000, // Read-only + SFGAO_HIDDEN = 0x00080000, // Hidden object + SFGAO_DISPLAYATTRMASK = 0x000FC000, // Do not use.(Docs of MSDN) + SFGAO_FILESYSANCESTOR = 0x10000000, // May contain children with SFGAO_FILESYSTEM + SFGAO_FOLDER = 0x20000000, // Support BindToObject(IID_IShellFolder) + SFGAO_FILESYSTEM = 0x40000000, // Is a win32 file system object (file/folder/root) + SFGAO_HASSUBFOLDER = 0x80000000, // May contain children with SFGAO_FOLDER + SFGAO_CONTENTSMASK = 0x80000000, // + SFGAO_VALIDATE = 0x01000000, // revalidate cached information + SFGAO_REMOVABLE = 0x02000000, // is a removeable media + SFGAO_COMPRESSED = 0x04000000, // is compressed + SFGAO_BROWSABLE = 0x08000000, // Supports IShellFolder, but only implements CreateViewObject() (non-folder view) + SFGAO_NONENUMERATED = 0x00100000, // is a non-enumerated object + SFGAO_NEWCONTENT = 0x00200000, // Should show bold in explorer tree + SFGAO_CANMONIKER = 0x00400000, // Not supported. + SFGAO_HASSTORAGE = 0x00400000, // Not supported. + SFGAO_STREAM = 0x00400000, // Supports BindToObject + SFGAO_STORAGEANCESTOR = 0x00800000, // May contain children with SFGAO_STORAGE or SFGAO_STREAM + SFGAO_STORAGECAPMASK = 0x70C50008, // For determining storage capabilities, ie for open/save semantics + } + + /// + /// Specifies the desired format of a STRRET structure + /// + [Flags] + public enum STRRET_TYPE : uint + { + STRRET_WSTR = 0, // The string is returned in the cStr + STRRET_OFFSET = 0x1, // The uOffset value indicates the number of bytes from the beginning of the IDL where the string is located. + STRRET_CSTR = 0x2, // The string is at the address specified by pOleStr + } + + /// + /// Flags for SHGetFileInfo, parameter uFlags; specifies the file information to retrieve. + /// See http://www.pinvoke.net/default.aspx/Constants/ShellAPI%20.html + /// + [Flags] + public enum SHGFI + { + SHGFI_LARGEICON = 0x000000000, + SHGFI_SMALLICON = 0x000000001, + SHGFI_OPENICON = 0x000000002, + SHGFI_SHELLICONSIZE = 0x000000004, + SHGFI_PIDL = 0x000000008, + SHGFI_USEFILEATTRIBUTES = 0x000000010, + SHGFI_ADDOVERLAYS = 0x000000020, + SHGFI_OVERLAYINDEX = 0x000000040, + SHGFI_ICON = 0x000000100, + SHGFI_DISPLAYNAME = 0x000000200, + SHGFI_TYPENAME = 0x000000400, + SHGFI_ATTRIBUTES = 0x000000800, + SHGFI_ICONLOCATION = 0x000001000, + SHGFI_EXETYPE = 0x000002000, + SHGFI_SYSICONINDEX = 0x000004000, + SHGFI_LINKOVERLAY = 0x000008000, + SHGFI_SELECTED = 0x000010000, + SHGFI_ATTR_SPECIFIED = 0x000020000, + } + + /// + /// Special folder constants + /// See http://msdn.microsoft.com/en-us/library/bb762494%28VS.85%29.aspx + /// + [Flags] + public enum CSIDL : int + { + CSIDL_DESKTOP = 0x0000, + CSIDL_INTERNET = 0x0001, + CSIDL_PROGRAMS = 0x0002, + CSIDL_CONTROLS = 0x0003, + CSIDL_PRINTERS = 0x0004, + CSIDL_PERSONAL = 0x0005, + CSIDL_FAVORITES = 0x0006, + CSIDL_STARTUP = 0x0007, + CSIDL_RECENT = 0x0008, + CSIDL_SENDTO = 0x0009, + CSIDL_BITBUCKET = 0x000a, + CSIDL_STARTMENU = 0x000b, + CSIDL_MYDOCUMENTS = 0x000c, + CSIDL_MYMUSIC = 0x000d, + CSIDL_MYVIDEO = 0x000e, + CSIDL_DESKTOPDIRECTORY = 0x0010, + CSIDL_DRIVES = 0x0011, + CSIDL_NETWORK = 0x0012, + CSIDL_NETHOOD = 0x0013, + CSIDL_FONTS = 0x0014, + CSIDL_TEMPLATES = 0x0015, + CSIDL_COMMON_STARTMENU = 0x0016, + CSIDL_COMMON_PROGRAMS = 0X0017, + CSIDL_COMMON_STARTUP = 0x0018, + CSIDL_COMMON_DESKTOPDIRECTORY = 0x0019, + CSIDL_APPDATA = 0x001A, + CSIDL_PRINTHOOD = 0x001b, + CSIDL_LOCAL_APPDATA = 0x001c, + CSIDL_ALTSTARTUP = 0x001d, + CSIDL_COMMON_ALTSTARTUP = 0x001e, + CSIDL_COMMON_FAVORITES = 0x001f, + CSIDL_INTERNET_CACHE = 0x0020, + CSIDL_COOKIES = 0x0021, + CSIDL_HISTORY = 0x0022, + CSIDL_COMMON_APPDATA = 0x0023, + CSIDL_WINDOWS = 0x0024, + CSIDL_SYSTEM = 0x0025, + CSIDL_PROGRAM_FILES = 0x0026, + CSIDL_MYPICTURES = 0x0027, + CSIDL_PROFILE = 0x0028, + CSIDL_SYSTEMX86 = 0x0029, + CSIDL_PROGRAM_FILESX86 = 0x002a, + CSIDL_PROGRAM_FILES_COMMON = 0x002b, + CSIDL_PROGRAM_FILES_COMMONX86 = 0x002c, + CSIDL_COMMON_TEMPLATES = 0x002d, + CSIDL_COMMON_DOCUMENTS = 0x002e, + CSIDL_COMMON_ADMINTOOLS = 0x002f, + CSIDL_ADMINTOOLS = 0x0030, + CSIDL_CONNECTIONS = 0x0031, + CSIDL_COMMON_MUSIC = 0x0035, + CSIDL_COMMON_PICTURES = 0x0036, + CSIDL_COMMON_VIDEO = 0x0037, + CSIDL_CDBURN_AREA = 0x003b + } + + /// + /// See http://msdn.microsoft.com/en-us/library/bb762538%28VS.85%29.aspx + /// + [Flags] + public enum SHCOLSTATE : uint + { + SHCOLSTATE_DEFAULT = 0x00000000, + SHCOLSTATE_TYPE_STR = 0x00000001, + SHCOLSTATE_TYPE_INT = 0x00000002, + SHCOLSTATE_TYPE_DATE = 0x00000003, + SHCOLSTATE_TYPEMASK = 0x0000000f, + SHCOLSTATE_ONBYDEFAULT = 0x00000010, + SHCOLSTATE_SLOW = 0x00000020, + SHCOLSTATE_EXTENDED = 0x00000040, + SHCOLSTATE_SECONDARYUI = 0x00000080, + SHCOLSTATE_HIDDEN = 0x00000100, + SHCOLSTATE_PREFER_VARCMP = 0x00000200, + SHCOLSTATE_PREFER_FMTCMP = 0x00000400, + SHCOLSTATE_NOSORTBYFOLDERNESS = 0x00000800, + SHCOLSTATE_VIEWONLY = 0x00010000, + SHCOLSTATE_BATCHREAD = 0x00020000, + SHCOLSTATE_NO_GROUPBY = 0x00040000, + SHCOLSTATE_FIXED_WIDTH = 0x00001000, + SHCOLSTATE_NODPISCALE = 0x00002000, + SHCOLSTATE_FIXED_RATIO = 0x00004000, + SHCOLSTATE_DISPLAYMASK = 0x0000F000, + } + + /// + /// Flags for IExtractIcon.GetIconLocation + /// See http://msdn.microsoft.com/en-us/library/bb761852%28VS.85%29.aspx + /// + [Flags] + public enum GIL : uint{ + GIL_OPENICON = 0x0001, + GIL_FORSHELL = 0x0002, + GIL_ASYNC = 0x0020, + GIL_DEFAULTICON = 0x0040, + GIL_FORSHORTCUT = 0x0080, + } + + #endregion + + #region Structs + + /// + /// File informations + /// See http://msdn.microsoft.com/en-us/library/bb759792%28VS.85%29.aspx + /// + public struct SHFILEINFO + { + public IntPtr hIcon; + public int iIcon; + public uint dwAttributes; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] + public string szDisplayName; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] + public string szTypeName; + } + + /// + /// Return value of IShellFolder interface methods + /// + [StructLayout(LayoutKind.Explicit, Size=264, CharSet = CharSet.Auto)] + public struct STRRET + { + [FieldOffset(0)] + public UInt32 uType; // type of storage + [FieldOffset(4)] + public IntPtr pOleStr; // pointer to the string + [FieldOffset(4)] + public UInt32 uOffset; // Offset into an IID list + [FieldOffset(4)] + public IntPtr cStr; // string buffer with the name + } + + [StructLayout(LayoutKind.Sequential)] + private struct ICONINFO + { + internal bool fIcon; + internal int xHotspot; + internal int yHotspot; + internal IntPtr hbmMask; + internal IntPtr hbmColor; + } + + [StructLayout(LayoutKind.Sequential)] + public struct SHELLDETAILS + { + public int fmt; + public int cxChar; + public STRRET str; + } + + #endregion + + #region ComImports + + /// + /// See http://msdn.microsoft.com/en-us/library/bb775075%28VS.85%29.aspx + /// + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("000214E6-0000-0000-C000-000000000046")] + public interface IShellFolder + { + [PreserveSig()] + uint ParseDisplayName( + IntPtr hwnd, + IntPtr pbc, + [In(), MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName, + out uint pchEaten, + out IntPtr ppidl, + ref uint pdwAttributes); + + [PreserveSig()] + uint EnumObjects( + IntPtr hwnd, + SHCONTF grfFlags, + out IEnumIDList ppenumIDList); + + [PreserveSig()] + uint BindToObject( + IntPtr pidl, + IntPtr pbc, + [In()] ref Guid riid, + out IShellFolder ppv); + + [PreserveSig()] + uint BindToStorage( + IntPtr pidl, + IntPtr pbc, + [In()] ref Guid riid, + [MarshalAs(UnmanagedType.Interface)] out object ppv); + + [PreserveSig()] + int CompareIDs( + int lParam, + IntPtr pidl1, + IntPtr pidl2); + + [PreserveSig()] + uint CreateViewObject( + IntPtr hwndOwner, + [In()] ref Guid riid, + [MarshalAs(UnmanagedType.Interface)] out object ppv); + + [PreserveSig()] + uint GetAttributesOf( + int cidl, + [In(), MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl, + [MarshalAs(UnmanagedType.LPArray)] + SFGAOF[] rgfInOut); + + [PreserveSig()] + uint GetUIObjectOf( + IntPtr hwndOwner, + int cidl, + [In(), MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl, + [In()] ref Guid riid, + IntPtr rgfReserved, + [MarshalAs(UnmanagedType.Interface)] out object ppv); + + [PreserveSig()] + uint GetDisplayNameOf( + IntPtr pidl, + SHGDN uFlags, + out STRRET pName); + + [PreserveSig()] + uint SetNameOf( + IntPtr hwnd, + IntPtr pidl, + [In(), MarshalAs(UnmanagedType.LPWStr)] string pszName, + SHGDN uFlags, + out IntPtr ppidlOut); + } + + /// + /// See http://msdn.microsoft.com/en-us/library/bb761277%28VS.85%29.aspx + /// + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("000214e5-0000-0000-c000-000000000046")] + public interface IShellIcon + { + [PreserveSig()] + int GetIconOf( + IntPtr pidl, + uint flags, + out int pIconIndex); + } + + /// + /// see http://msdn.microsoft.com/en-us/library/bb761854%28VS.85%29.aspx + /// + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("000214fa-0000-0000-c000-000000000046")] + public interface IExtractIcon + { + [PreserveSig()] + int GetIconLocation( + uint uFlags, + [Out, MarshalAs(UnmanagedType.LPWStr, SizeParamIndex = 2)] StringBuilder szIconFile, + int cchMax, + out int piIndex, + out uint pwFlags); + + [PreserveSig()] + int Extract( + [MarshalAs( UnmanagedType.LPWStr )] string pstFile, + uint nIconIndex, + out IntPtr phiconLarge, + out IntPtr phiconSmall, + uint nIconSize ); + } + /// + /// See http://msdn.microsoft.com/en-us/library/bb775055%28VS.85%29.aspx + /// + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("93F2F68C-1D1B-11d3-A30E-00C04F79ABD1")] + public interface IShellFolder2 : IShellFolder // Extends the capabilities of IShellFolder + { + + [PreserveSig()] + uint EnumSearches( + [MarshalAs(UnmanagedType.Interface)] out object ppEnum); + + [PreserveSig()] + uint GetDefaultColumn( + uint dwReserved, + out ulong pSort, + out ulong pDisplay); + + [PreserveSig()] + uint GetDefaultColumnState( + uint iColumn, + out uint pcsFlags); + + [PreserveSig()] + uint GetDefaultSearchGUID( + ref Guid guid); + + [PreserveSig()] + uint GetDetailsEx( + IntPtr pidl, + [In()] IntPtr pcsFlags, + out IntPtr pv); + + [PreserveSig()] + uint GetDetailsOf( + IntPtr pidl, + uint iColumn, + out SHELLDETAILS psd); + + [PreserveSig()] + uint MapColumnToSCID( + uint iColumn, + out IntPtr pscid); + } + + /// + /// See http://msdn.microsoft.com/en-us/library/bb761982%28VS.85%29.aspx + /// + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("000214F2-0000-0000-C000-000000000046")] + public interface IEnumIDList + { + [PreserveSig()] + uint Next( + uint celt, + out IntPtr rgelt, + out Int32 pceltFetched + ); + + [PreserveSig()] + uint Skip( + uint celt + ); + + [PreserveSig()] + uint Reset(); + + [PreserveSig()] + uint Clone( + out IEnumIDList ppenum + ); + } + + #endregion + } + +} diff --git a/awt/awt.build b/awt/awt.build new file mode 100644 index 0000000..93734c7 --- /dev/null +++ b/awt/awt.build @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awt/composite.cs b/awt/composite.cs new file mode 100644 index 0000000..72cb339 --- /dev/null +++ b/awt/composite.cs @@ -0,0 +1,143 @@ +/* + Copyright (C) 2010 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; + +namespace ikvm.awt { + + internal class CompositeHelper { + + private readonly ImageAttributes imageAttributes = new ImageAttributes(); + + /// + /// Create a default CompositeHelper. Is used from Create only. + /// + protected CompositeHelper() { + } + + internal static CompositeHelper Create(java.awt.Composite comp, Graphics graphics){ + if (comp is java.awt.AlphaComposite) { + java.awt.AlphaComposite alphaComp = (java.awt.AlphaComposite)comp; + float alpha = alphaComp.getAlpha(); + switch (alphaComp.getRule()) { + case java.awt.AlphaComposite.CLEAR: + graphics.CompositingMode = CompositingMode.SourceCopy; + return new ClearCompositeHelper(); + case java.awt.AlphaComposite.SRC: + graphics.CompositingMode = CompositingMode.SourceCopy; + break; + case java.awt.AlphaComposite.SRC_OVER: + graphics.CompositingMode = CompositingMode.SourceOver; + break; + case java.awt.AlphaComposite.DST: + graphics.CompositingMode = CompositingMode.SourceOver; + alpha = 0.0F; + break; + default: + graphics.CompositingMode = CompositingMode.SourceOver; + Console.Error.WriteLine("AlphaComposite with Rule " + alphaComp.getRule() + " not supported."); + break; + } + if (alpha == 1.0) { + return new CompositeHelper(); + } else { + return new AlphaCompositeHelper(alpha); + } + } else { + graphics.CompositingMode = CompositingMode.SourceOver; + Console.Error.WriteLine("Composite not supported: " + comp.GetType().FullName); + return new CompositeHelper(); + } + } + + internal virtual int GetArgb(java.awt.Color color) { + return color.getRGB(); + } + + internal virtual Color GetColor( java.awt.Color color ){ + return color == null ? Color.Empty : Color.FromArgb(GetArgb(color)); + } + + internal virtual int ToArgb(Color color) { + return color.ToArgb(); + } + + internal virtual java.awt.Color GetColor(Color color) { + return color == Color.Empty ? null : new java.awt.Color(ToArgb(color), true); + } + + /// + /// Get the ImageAttributes instance. Does not change it bcause it is not a copy. + /// + /// + internal virtual ImageAttributes GetImageAttributes(){ + return imageAttributes; + } + } + + internal sealed class AlphaCompositeHelper : CompositeHelper { + private readonly float alpha; + + /// + /// Create a AlphaCompositeHelper + /// + /// a value in the range from 0.0 to 1.0 + internal AlphaCompositeHelper(float alpha) { + this.alpha = alpha; + ColorMatrix matrix = new ColorMatrix(); + matrix.Matrix33 = alpha; + GetImageAttributes().SetColorMatrix(matrix); + } + + internal override int GetArgb(java.awt.Color color) { + uint argb = (uint)color.getRGB(); + uint newAlpha = (uint)((0xff000000 & argb) * alpha + 0x800000); + uint newArgb = (0xff000000 & newAlpha) | (0xffffff & argb); + return (int)newArgb; + } + + internal override int ToArgb(Color color) { + uint argb = (uint)color.ToArgb(); + uint newAlpha = (uint)((0xff000000 & argb) / alpha + 0x800000); + uint newArgb = (0xff000000 & newAlpha) | (0xffffff & argb); + return (int)newArgb; + } + } + + internal sealed class ClearCompositeHelper : CompositeHelper { + + internal ClearCompositeHelper() + { + ColorMatrix matrix = new ColorMatrix(); + matrix.Matrix00 = matrix.Matrix11 = matrix.Matrix22 = matrix.Matrix33 = 0.0F; + GetImageAttributes().SetColorMatrix(matrix); + } + + internal override int GetArgb(java.awt.Color color) { + return 0; + } + } +} diff --git a/awt/converter.cs b/awt/converter.cs new file mode 100644 index 0000000..7969978 --- /dev/null +++ b/awt/converter.cs @@ -0,0 +1,402 @@ +/* + Copyright (C) 2002, 2004, 2005, 2006, 2007 Jeroen Frijters + Copyright (C) 2006 Active Endpoints, Inc. + Copyright (C) 2006 - 2010 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +using System; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Text; +using System.Drawing.Imaging; +using System.IO; +using System.Runtime.InteropServices; +using System.Threading; +using System.Windows.Forms; +using System.ComponentModel; +using System.Reflection; +using System.Text; +using java.awt.datatransfer; +using java.awt.image; +using java.awt.peer; +using java.net; +using java.util; + +namespace ikvm.awt +{ + /// + /// This class has some static convertion methods from Java to C# objects + /// + class J2C + { + + internal static Color ConvertColor(java.awt.Color color) + { + return color == null ? Color.Empty : Color.FromArgb(color.getRGB()); + } + + internal static Bitmap ConvertImage(java.awt.Image img) + { + if (img is BufferedImage) + { + return ((BufferedImage)img).getBitmap(); + } + if (img is NetVolatileImage) + { + return ((NetVolatileImage)img).bitmap; + } + if (img is sun.awt.image.ToolkitImage) + { + sun.awt.image.ImageRepresentation ir = ((sun.awt.image.ToolkitImage)img).getImageRep(); + // start the production and wait if not produce the image + lock( ir ) { + ir.prepare(null); + while ( ir.getBufferedImage() == null ) { + ir.wait(); + } + } + return ir.getBufferedImage().getBitmap(); + } + if (img is NoImage) + { + return null; + } + Console.WriteLine(new System.Diagnostics.StackTrace()); + throw new NotImplementedException("Image class:" + img.GetType().FullName); + } + + internal static PointF ConvertPoint(java.awt.geom.Point2D point) + { + return new PointF((float)point.getX(), (float)point.getY()); + } + + internal static RectangleF ConvertRect(java.awt.geom.Rectangle2D rect) + { + return new RectangleF((float)rect.getX(), (float)rect.getY(), (float)rect.getWidth(), (float)rect.getHeight()); + } + + internal static Rectangle ConvertRect(java.awt.Rectangle rect) + { + return new Rectangle(rect.x, rect.y, rect.width, rect.height); + } + + /// + /// Create a rounded rectangle using lines and arcs + /// + /// upper left x coordinate + /// upper left y coordinate + /// width + /// height + /// the horizontal diameter of the arc at the four corners + /// the vertical diameter of the arc at the four corners + /// + internal static GraphicsPath ConvertRoundRect(int x, int y, int w, int h, int arcWidth, int arcHeight) + { + GraphicsPath gp = new GraphicsPath(); + bool drawArc = arcWidth > 0 && arcHeight > 0; + int a = arcWidth / 2; + int b = arcHeight / 2; + gp.AddLine(x + a, y, x + w - a, y); + if (drawArc) + { + gp.AddArc(x + w - arcWidth, y, arcWidth, arcHeight, 270, 90); //upper right arc + } + gp.AddLine(x + w, y + b, x + w, y + h - b); + if (drawArc) + { + gp.AddArc(x + w - arcWidth, y + h - arcHeight, arcWidth, arcHeight, 0, 90); //lower right arc + } + gp.AddLine(x + w - a, y + h, x + a, y + h); + if (drawArc) + { + gp.AddArc(x, y + h - arcHeight, arcWidth, arcHeight, 90, 90);//lower left arc + } + gp.AddLine(x, y + h - b, x, y + b); + if (drawArc) + { + gp.AddArc(x, y, arcWidth, arcHeight, 180, 90); //upper left arc + } + gp.CloseFigure(); + + return gp; + } + + internal static GraphicsPath ConvertShape(java.awt.Shape shape) + { + java.awt.geom.PathIterator iterator = shape.getPathIterator(null); + GraphicsPath gp = new GraphicsPath(); + gp.FillMode = (FillMode)iterator.getWindingRule(); + float[] coords = new float[6]; + float x = 0; + float y = 0; + while (!iterator.isDone()) + { + int type = iterator.currentSegment(coords); + switch (type) + { + case java.awt.geom.PathIterator.__Fields.SEG_MOVETO: + x = coords[0]; + y = coords[1]; + gp.StartFigure(); + break; + case java.awt.geom.PathIterator.__Fields.SEG_LINETO: + gp.AddLine(x, y, coords[0], coords[1]); + x = coords[0]; + y = coords[1]; + break; + case java.awt.geom.PathIterator.__Fields.SEG_QUADTO: + gp.AddBezier(x, y, coords[0], coords[1], coords[0], coords[1], coords[2], coords[3]); + x = coords[2]; + y = coords[3]; + break; + case java.awt.geom.PathIterator.__Fields.SEG_CUBICTO: + gp.AddBezier(x, y, coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]); + x = coords[4]; + y = coords[5]; + break; + case java.awt.geom.PathIterator.__Fields.SEG_CLOSE: + gp.CloseFigure(); + break; + } + iterator.next(); + } + return gp; + } + + internal static LineJoin ConvertLineJoin(int join) + { + switch (join) + { + case java.awt.BasicStroke.JOIN_MITER: + return LineJoin.Miter; + case java.awt.BasicStroke.JOIN_ROUND: + return LineJoin.Round; + case java.awt.BasicStroke.JOIN_BEVEL: + return LineJoin.Bevel; + default: + Console.WriteLine("Unknown line join type:" + join); + return LineJoin.Miter; + } + } + + internal static Matrix ConvertTransform(java.awt.geom.AffineTransform tx) + { + return new Matrix( + (float)tx.getScaleX(), + (float)tx.getShearY(), + (float)tx.getShearX(), + (float)tx.getScaleY(), + (float)tx.getTranslateX(), + (float)tx.getTranslateY()); + } + + internal static FontFamily CreateFontFamily(String name) + { + String name2 = name == null ? null : name.ToLower(); + switch (name2) + { + case "monospaced": + case "courier": + return FontFamily.GenericMonospace; + case "serif": + return FontFamily.GenericSerif; + case "sansserif": + case "dialog": + case "dialoginput": + case null: + case "default": + return FontFamily.GenericSansSerif; + default: + try + { + return new FontFamily(name); + } + catch (ArgumentException) + { + return FontFamily.GenericSansSerif; + } + } + } + + private static FontStyle ConvertFontStyle(int style) + { + FontStyle fs = FontStyle.Regular; + if ((style & java.awt.Font.BOLD) != 0) + { + fs |= FontStyle.Bold; + } + if ((style & java.awt.Font.ITALIC) != 0) + { + fs |= FontStyle.Italic; + } + return fs; + } + + internal static Font ConvertFont(String name, int style, float size) + { + if (size <= 0) + { + size = 1; + } + FontFamily family = CreateFontFamily(name); + FontStyle fontStyle = ConvertFontStyle(style); + if (!family.IsStyleAvailable(fontStyle)) + { + //Some Fonts (for example Aharoni) does not support Regular style. This throw an exception else it is not documented. + if(family.IsStyleAvailable(FontStyle.Regular)){ + fontStyle = FontStyle.Regular; + }else + if(family.IsStyleAvailable(FontStyle.Bold)){ + fontStyle = FontStyle.Bold; + }else + if(family.IsStyleAvailable(FontStyle.Italic)){ + fontStyle = FontStyle.Italic; + }else + if(family.IsStyleAvailable(FontStyle.Bold | FontStyle.Italic)){ + fontStyle = FontStyle.Bold | FontStyle.Italic; + } + } + return new Font(family, size, fontStyle, GraphicsUnit.Pixel); + } + + + internal static Region ConvertRegion(sun.java2d.pipe.Region shape) + { + if (shape == null) + { + return null; + } + if (shape.isRectangular()) + { + int x = shape.getLoX(); + int y = shape.getLoY(); + int w = shape.getHiX() - x; + int h = shape.getHiY() - y; + if (w < 0 || h < 0) + { + return new Region(); + } + else + { + return new Region(new Rectangle(x, y, w, h)); + } + } + else + { + using (GraphicsPath path = new GraphicsPath()) + { + sun.java2d.pipe.SpanIterator iter = shape.getSpanIterator(); + int[] box = new int[4]; + while (iter.nextSpan(box)) + { + path.AddRectangle(new Rectangle(box[0], box[1], box[2] - box[0], box[3] - box[1])); + } + return new Region(path); + } + } + } + + internal static string ConvertGlyphVector(java.awt.font.GlyphVector gv) { + int count = gv.getNumGlyphs(); + char[] text = new char[count]; + for (int i = 0; i < count; i++) { + text[i] = (char)gv.getGlyphCode(i); + } + return new string(text); + } + + } + + /// + /// This class has some static convertion function from C# to Java objects + /// + class C2J + { + internal static java.awt.geom.AffineTransform ConvertMatrix(Matrix matrix) + { + float[] elements = matrix.Elements; + return new java.awt.geom.AffineTransform(elements); + } + + internal static java.awt.Rectangle ConvertRectangle(RectangleF rec) + { + return new java.awt.Rectangle((int)rec.X, (int)rec.Y, (int)rec.Width, (int)rec.Height); + } + + internal static java.awt.Color ConvertColor(Color color) + { + return color == Color.Empty ? null : new java.awt.Color(color.ToArgb(),true); + } + + internal static java.awt.Font ConvertFont(Font font) + { + float size = font.Size; + if (font.Unit != GraphicsUnit.Pixel) + { + size = font.SizeInPoints * java.awt.Toolkit.getDefaultToolkit().getScreenResolution() / 72; + } + java.awt.Font jFont = new java.awt.Font(font.Name, (int)font.Style, (int)size); + if (jFont.getSize2D() != size) + { + jFont = jFont.deriveFont(size); + } + //TODO performance we should set the .NET Font, we can do it with an aditional constructor. + return jFont; + } + + internal static java.awt.Shape ConvertShape(GraphicsPath path) { + java.awt.geom.GeneralPath shape = new java.awt.geom.GeneralPath(); + shape.setWindingRule((int)path.FillMode); + for (int i = 0; i < path.PointCount; i++) { + byte pathType = path.PathTypes[i]; + int type = pathType & 0x07; + PointF point = path.PathPoints[i]; + switch (type) { + case 0: + // Indicates that the point is the start of a figure. + shape.moveTo(point.X, point.Y); + break; + case 1: + // Indicates that the point is one of the two endpoints of a line. + shape.lineTo(point.X, point.Y); + break; + case 3: + // Indicates that the point is an endpoint or control point of a cubic B�zier spline. + PointF point2 = path.PathPoints[++i]; + PointF point3 = path.PathPoints[++i]; + shape.curveTo(point.X, point.Y, point2.X, point2.Y, point3.X, point3.Y); + pathType = path.PathTypes[i]; + break; + default: + Console.WriteLine("Unknown GraphicsPath type: " + type); + break; + } + if ((pathType & 0x80) > 0) { + // Specifies that the point is the last point in a closed subpath (figure). + shape.closePath(); + } + } + return shape; + } + } +} \ No newline at end of file diff --git a/awt/fonts-0.95.cs b/awt/fonts-0.95.cs new file mode 100644 index 0000000..9d68065 --- /dev/null +++ b/awt/fonts-0.95.cs @@ -0,0 +1,557 @@ +/* + Copyright (C) 2002, 2004, 2005, 2006, 2007 Jeroen Frijters + Copyright (C) 2006 Active Endpoints, Inc. + Copyright (C) 2006, 2007, 2009 - 2011 Volker Berlin + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +using System; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Text; +using System.Text; +using java.awt.font; +using java.awt.geom; +using java.util; +#if WINFX +using System.Windows; +using System.Windows.Media; +#endif + + +namespace ikvm.awt +{ + + /*class NetFontMetrics : java.awt.FontMetrics + { + private static readonly Bitmap defaultbitmap = new Bitmap(1, 1); + [ThreadStatic] + private static Graphics threadLocalDefaultGraphics; + + private static Graphics GetDefaultGraphics() + { + Graphics g = threadLocalDefaultGraphics; + if (g == null) + { + g = threadLocalDefaultGraphics = Graphics.FromImage(defaultbitmap); + g.SmoothingMode = SmoothingMode.None; + g.PixelOffsetMode = PixelOffsetMode.None; + g.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit; + } + return g; + } + + public NetFontMetrics(java.awt.Font font) : base(font) + { + } + + private Font GetNetFont() + { + return font.getNetFont(); + } + + public override int getHeight() + { + return GetNetFont().Height; + } + + public override int getLeading() + { + return (int)Math.Round(GetLeadingFloat()); + } + + public override int getMaxAdvance() + { + // HACK very lame + return charWidth('M'); + } + + public override int charWidth(char ch) + { + // HACK we average 20 characters to decrease the influence of the pre/post spacing + return stringWidth(new String(ch, 20)) / 20; + } + + public override int charsWidth(char[] data, int off, int len) + { + return stringWidth(new String(data, off, len)); + } + + public override int getAscent() + { + return (int)Math.Round(GetAscentFloat()); + } + + public override int getDescent() + { + return (int)Math.Round(GetDescentFloat()); + } + + public override int stringWidth(string s) + { + return (int)Math.Round(GetStringWidth(s, GetDefaultGraphics())); + } + + public float GetAscentFloat() + { + Font f = GetNetFont(); + int ascent = f.FontFamily.GetCellAscent(f.Style); + return f.Size * ascent / f.FontFamily.GetEmHeight(f.Style); + } + + public float GetDescentFloat() + { + Font f = GetNetFont(); + int descent = f.FontFamily.GetCellDescent(f.Style); + return f.Size * descent / f.FontFamily.GetEmHeight(f.Style); + } + + public float GetLeadingFloat() + { + float leading = getHeight() - (GetAscentFloat() + GetDescentFloat()); + return Math.Max(0.0f, leading); + } + + internal float GetStringWidth(String aString, System.Drawing.Graphics g) + { + if (aString.Length == 0) + { + return 0; + } + // System.Windows.Forms.TextRenderer#MeasureText seems to large + // Graphics#MeasureString is many faster but work only correct with TextRenderingHint.AntiAlias + bool rounding; + StringFormat format; + switch (g.TextRenderingHint) + { + // Fractional metrics + case TextRenderingHint.AntiAlias: + case TextRenderingHint.SingleBitPerPixel: + // this very mystic, if a StringFormat extends from GenericTypographic then the metric are different but like Java with fractional metrics + format = new StringFormat(StringFormat.GenericTypographic); + rounding = false; + break; + default: + format = new StringFormat(); + rounding = true; + break; + } + + format.FormatFlags = StringFormatFlags.MeasureTrailingSpaces | StringFormatFlags.NoWrap | + StringFormatFlags.FitBlackBox; + format.Trimming = StringTrimming.None; + format.SetMeasurableCharacterRanges(new CharacterRange[] {new CharacterRange(0, aString.Length)}); + Region[] regions = g.MeasureCharacterRanges(aString, GetNetFont(), + new RectangleF(0, 0, int.MaxValue, int.MaxValue), format); + SizeF size = regions[0].GetBounds(g).Size; + regions[0].Dispose(); + //with Arial 9.0 and only one character under Vista .NET does not round it, that we rounding manualy + return rounding ? (int) Math.Round(size.Width) : size.Width; + } + + internal java.awt.geom.Rectangle2D GetStringBounds(String aString, System.Drawing.Graphics g) + { + Font netFont = GetNetFont(); + FontFamily family = netFont.FontFamily; + FontStyle style = netFont.Style; + float factor = netFont.Size / family.GetEmHeight(style); + float height = family.GetLineSpacing(style) * factor; + float descent = family.GetCellDescent(style) * factor; + float ascent = family.GetCellAscent(style) * factor; + float leading = height - ascent - descent; + + return new java.awt.geom.Rectangle2D.Float(0, -ascent - leading / 2, GetStringWidth(aString, g), height); + } + + public override java.awt.geom.Rectangle2D getStringBounds(String aString, java.awt.Graphics gr) + { + if (gr is NetGraphics) + { + return GetStringBounds(aString, ((NetGraphics)gr).JGraphics); + } + return GetStringBounds(aString, GetDefaultGraphics()); + } + }*/ + +/* class NetFontPeer : java.awt.peer.FontPeer, IDisposable + { + internal readonly Font netFont; + + internal NetFontPeer(string name, java.util.Map attrs) + : base(name, attrs) + { + netFont = J2C.ConvertFont(name, getStyle(null), getSize(null)); + } + + public override bool canDisplay(int codePoint) + { + //HACK There is no equivalent in C# http://msdn2.microsoft.com/en-us/library/sf4dhbw8(VS.80).aspx + return true; + } + + public override int canDisplayUpTo(java.awt.Font font, java.text.CharacterIterator param2, int param3, int param4) + { + //HACK There is no equivalent in C# http://msdn2.microsoft.com/en-us/library/e8bh4szw(VS.80).aspx + return -1; + } + + public override GlyphVector createGlyphVector(java.awt.Font font, FontRenderContext frc, int[] glyphCodes) + { + char[] chars = new char[glyphCodes.Length]; + for (int i = 0; i < chars.Length; i++) + { + chars[i] = (char)glyphCodes[i]; + } + return new NetGlyphVector(netFont, font, frc, chars); + } + + public override GlyphVector createGlyphVector(java.awt.Font font, FontRenderContext frc, java.text.CharacterIterator text) + { + int count = text.getEndIndex() - text.getBeginIndex(); + char[] chars = new char[count]; + text.first(); + for (int i = 0; i < count; i++) + { + chars[i] = text.current(); + text.next(); + } + return new NetGlyphVector(netFont, font, frc, chars); + } + + public override byte getBaselineFor(java.awt.Font font, char param2) + { + throw new NotImplementedException(); + } + + public override java.awt.FontMetrics getFontMetrics(java.awt.Font font) + { + return new NetFontMetrics(font); + } + + public override string getGlyphName(java.awt.Font font, int param2) + { + throw new NotImplementedException(); + } + + public override LineMetrics getLineMetrics(java.awt.Font font, java.text.CharacterIterator aCharacterIterator, int aBegin, int aLimit, FontRenderContext aFontRenderContext) + { + string s = ToString(aCharacterIterator, aBegin, aLimit); + return new NetLineMetrics(font, s); + } + + public override java.awt.geom.Rectangle2D getMaxCharBounds(java.awt.Font font, FontRenderContext param2) + { + throw new NotImplementedException(); + } + + public override int getMissingGlyphCode(java.awt.Font font) + { + throw new NotImplementedException(); + } + + public override int getNumGlyphs(java.awt.Font font) + { + throw new NotImplementedException(); + } + + public override string getPostScriptName(java.awt.Font font) + { + throw new NotImplementedException(); + } + + public override bool hasUniformLineMetrics(java.awt.Font font) + { + throw new NotImplementedException(); + } + + public override GlyphVector layoutGlyphVector(java.awt.Font font, FontRenderContext frc, char[] text, int beginIndex, int endIndex, int flags) + { + char[] chars = new char[endIndex - beginIndex]; + Array.Copy(text, beginIndex, chars, 0, chars.Length); + return new NetGlyphVector(netFont, font, frc, chars); + } + + public override string getSubFamilyName(java.awt.Font font, Locale param2) + { + throw new NotImplementedException(); + } + + private static string ToString(java.text.CharacterIterator aCharacterIterator, int aBegin, int aLimit) + { + aCharacterIterator.setIndex(aBegin); + StringBuilder sb = new StringBuilder(); + + for (int i = aBegin; i <= aLimit; ++i) + { + char c = aCharacterIterator.current(); + sb.Append(c); + aCharacterIterator.next(); + } + + return sb.ToString(); + } + + #region IDisposable Members + + public void Dispose() + { + netFont.Dispose(); + } + + #endregion + }*/ + + /* class NetGlyphVector : GlyphVector + { + private readonly Font netFont; + private readonly java.awt.Font font; + private readonly FontRenderContext frc; + private readonly char[] text; + private NetFontMetrics metrics; + + + internal NetGlyphVector(Font netFont, java.awt.Font font, FontRenderContext frc, char[] text) + { + this.netFont = netFont; + this.font = font; + this.frc = frc; + this.text = text; + } + + private NetFontMetrics getMetrics() + { + if(metrics == null) + { + metrics = new NetFontMetrics(font); + } + return metrics; + } + + public override bool equals(GlyphVector gv) + { + throw new NotImplementedException(); + } + + public override java.awt.Font getFont() + { + return font; + } + + public override FontRenderContext getFontRenderContext() + { + return frc; + } + + public override int getGlyphCode(int i) + { + throw new NotImplementedException(); + } + + public override int[] getGlyphCodes(int i1, int i2, int[] iarr) + { + throw new NotImplementedException(); + } + + public override GlyphJustificationInfo getGlyphJustificationInfo(int i) + { + throw new NotImplementedException(); + } + + public override java.awt.Shape getGlyphLogicalBounds(int i) + { + throw new NotImplementedException(); + } + + public override GlyphMetrics getGlyphMetrics(int i) + { + throw new NotImplementedException(); + } + + public override java.awt.Shape getGlyphOutline(int i) + { + throw new NotImplementedException(); + } + + public override Point2D getGlyphPosition(int i) + { + throw new NotImplementedException(); + } + + public override float[] getGlyphPositions(int i1, int i2, float[] farr) + { + throw new NotImplementedException(); + } + + public override AffineTransform getGlyphTransform(int i) + { + throw new NotImplementedException(); + } + + public override java.awt.Shape getGlyphVisualBounds(int index) + { + return getMetrics().GetStringBounds(new String(text, index, 1)); + } + + public override Rectangle2D getLogicalBounds() + { + return getMetrics().GetStringBounds(new String(text)); + } + + public override int getNumGlyphs() + { + return text.Length; + } + + public override java.awt.Shape getOutline() + { + throw new NotImplementedException(); + } + + public override java.awt.Shape getOutline(float f1, float f2) + { + throw new NotImplementedException(); + } + + public override Rectangle2D getVisualBounds() + { + return new NetFontMetrics(font).GetStringBounds(new String(text)); + } + + public override void performDefaultLayout() + { + throw new NotImplementedException(); + } + + public override void setGlyphPosition(int i, Point2D pd) + { + throw new NotImplementedException(); + } + + public override void setGlyphTransform(int i, AffineTransform at) + { + throw new NotImplementedException(); + } + + public char[] getText() + { + return text; + } + }*/ + + /*class NetLineMetrics : LineMetrics + { + private java.awt.Font mFont; + private String mString; + private FontFamily fontFamily; + private FontStyle style; + private float factor; + + public NetLineMetrics(java.awt.Font aFont, String aString) + { + mFont = aFont; + mString = aString; + fontFamily = J2C.CreateFontFamily(aFont.getName()); + style = (FontStyle)mFont.getStyle(); + factor = aFont.getSize2D() / fontFamily.GetEmHeight(style); + } + + public override float getAscent() + { + return fontFamily.GetCellAscent(style) * factor; + } + + public override int getBaselineIndex() + { + return 0; //I have no font see that return another value. + } + + public override float[] getBaselineOffsets() + { + float ascent = getAscent(); + return new float[] { 0, (getDescent() / 2f - ascent) / 2f, -ascent }; + } + + public override float getDescent() + { + return fontFamily.GetCellDescent(style) * factor; + } + + public override float getHeight() + { + return fontFamily.GetLineSpacing(style) * factor; + } + + public override float getLeading() + { + return getHeight() - getAscent() - getDescent(); + } + + public override int getNumChars() + { + return mString.Length; + } + +#if WINFX + private Typeface GetTypeface() + { + return new Typeface(fontFamily, style, FontWeight.Normal, FontStretch.Medium); + } +#endif + + public override float getStrikethroughOffset() + { +#if WINFX + return GetTypeface().StrikethroughPosition * factor; +#else + return getAscent() / -3; +#endif + } + + public override float getStrikethroughThickness() + { +#if WINFX + return GetTypeface().StrikethroughThickness * factor; +#else + return mFont.getSize2D() / 18; +#endif + } + + public override float getUnderlineOffset() + { +#if WINFX + return GetTypeface().UnderlinePosition * factor; +#else + return mFont.getSize2D() / 8.7F; +#endif + } + + public override float getUnderlineThickness() + { +#if WINFX + return GetTypeface().UnderlineThickness * factor; +#else + return mFont.getSize2D() / 18; +#endif + } + }*/ + +} diff --git a/awt/graphics.cs b/awt/graphics.cs new file mode 100644 index 0000000..b8e61a0 --- /dev/null +++ b/awt/graphics.cs @@ -0,0 +1,2344 @@ +/* + Copyright (C) 2002, 2004, 2005, 2006, 2007 Jeroen Frijters + Copyright (C) 2006 Active Endpoints, Inc. + Copyright (C) 2006 - 2014 Volker Berlin (i-net software) + Copyright (C) 2011 Karsten Heinrich (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +using System; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Text; +using System.Globalization; +using System.Windows.Forms; +using java.awt.image; +using java.util; + +namespace ikvm.awt +{ + + internal class BitmapGraphics : NetGraphics + { + private readonly Bitmap bitmap; + private readonly BufferedImage image; + + internal BitmapGraphics(Bitmap bitmap, Object destination, java.awt.Font font, Color fgcolor, Color bgcolor) + : base(createGraphics(bitmap), destination, font, fgcolor, bgcolor) + { + this.bitmap = bitmap; + image = destination as BufferedImage; + } + + internal BitmapGraphics(Bitmap bitmap, Object destination) + : this(bitmap, destination, null, Color.White, Color.Black) + { + } + + internal override Graphics g + { + get { + if (image != null) + { + image.toBitmap(); + } + return base.g; + } + } + + protected override SizeF GetSize() { + return bitmap.Size; + } + + private static Graphics createGraphics(Bitmap bitmap) + { + // lock to prevent the exception + // System.InvalidOperationException: Object is currently in use elsewhere + lock (bitmap) + { + return Graphics.FromImage(bitmap); + } + } + + public override java.awt.Graphics create() + { + BitmapGraphics newGraphics = (BitmapGraphics)MemberwiseClone(); + newGraphics.init(createGraphics(bitmap)); + return newGraphics; + } + + public override void copyArea(int x, int y, int width, int height, int dx, int dy) + { + Bitmap copy = new Bitmap(width, height); + using (Graphics gCopy = Graphics.FromImage(copy)) + { + gCopy.DrawImage(bitmap, new Rectangle(0, 0, width, height), x, y, width, height, GraphicsUnit.Pixel); + } + g.DrawImageUnscaled(copy, x + dx, y + dy); + } + } + + internal class ComponentGraphics : NetGraphics + { + private readonly Control control; + + internal ComponentGraphics(Control control, java.awt.Component target, java.awt.Color fgColor, java.awt.Color bgColor, java.awt.Font font) + : base(control.CreateGraphics(), target, font, J2C.ConvertColor(fgColor), J2C.ConvertColor(bgColor)) + { + this.control = control; + } + + protected override SizeF GetSize() { + return control.Size; + } + + public override java.awt.Graphics create() + { + ComponentGraphics newGraphics = (ComponentGraphics)MemberwiseClone(); + newGraphics.init(control.CreateGraphics()); + return newGraphics; + } + + private Point getPointToScreenImpl(Point point) + { + return this.control.PointToScreen(point); + } + + private Point getPointToScreen(Point point) + { + return (Point)this.control.Invoke(new Converter(getPointToScreenImpl),point); + } + + public override void copyArea(int x, int y, int width, int height, int dx, int dy) + { + Matrix t = g.Transform; + Point src = getPointToScreen(new Point(x + (int)t.OffsetX, y + (int)t.OffsetY)); + Bitmap copy = new Bitmap(width, height); + using (Graphics gCopy = Graphics.FromImage(copy)) + { + gCopy.CopyFromScreen(src, new Point(0, 0), new Size(width, height)); + } + g.DrawImageUnscaled(copy, x + dx, y + dy); + } + + public override void clip(java.awt.Shape shape) + { + if (shape == null) + { + // the API specification says that this will clear + // the clip, but in fact the reference implementation throws a + // NullPointerException - see the following entry in the bug parade: + // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6206189 + throw new java.lang.NullPointerException(); + } + base.clip(shape); + } + } + + internal class PrintGraphicsContext + { + internal PrintGraphics Current; + } + + internal class PrintGraphics : NetGraphics + { + private NetGraphicsState myState; + private PrintGraphicsContext baseContext; + private bool disposed = false; + private bool isBase = true; + + internal PrintGraphics(Graphics g) + : base(g, null, null, Color.White, Color.Black) + { + baseContext = new PrintGraphicsContext(); + baseContext.Current = this; + } + + public override java.awt.Graphics create() + { + checkState(); + myState = new NetGraphicsState(); + myState.saveGraphics(this); + PrintGraphics newGraphics = (PrintGraphics)MemberwiseClone(); + newGraphics.myState = null; + newGraphics.isBase = false; + newGraphics.baseContext = baseContext; + baseContext.Current = newGraphics; // since it is very likely that the next op will be on that graphics + // this is similar to init + myState.restoreGraphics(newGraphics); + return newGraphics; + } + + /// + /// Checks whether the properties of this instance are set to the bse Graphics. If not, the context + /// of the currently PrintGraphics is saved and the context if this instance is restored. + /// + private void checkState() + { + // this is required to simulate Graphics.create(), which is not possible in .NET + // we simply call Save on create() an restore this state, if any method is called + // on the current graphics. This will work for almost any use case of create() + if (baseContext != null && baseContext.Current != this) + { + if (!baseContext.Current.disposed) + { + if (baseContext.Current.myState == null) + { + baseContext.Current.myState = new NetGraphicsState(baseContext.Current); + } + else + { + baseContext.Current.myState.saveGraphics(baseContext.Current); + } + } + baseContext.Current = this; + if (myState != null) // is only null, if this instance was already disposed + { + myState.restoreGraphics(this); + } + } + } + + public override void copyArea(int x, int y, int width, int height, int dx, int dy) + { + throw new NotImplementedException(); + } + + public override void clearRect(int x, int y, int width, int height) + { + checkState(); + base.clearRect(x, y, width, height); + } + + public override void clipRect(int x, int y, int w, int h) + { + checkState(); + base.clipRect(x, y, w, h); + } + + public override void clip(java.awt.Shape shape) + { + checkState(); + base.clip(shape); + } + + public override void dispose() + { + myState = null; + if (pen != null) pen.Dispose(); + if (brush != null) brush.Dispose(); + disposed = true; + if (!isBase) + { + // only dispose the underlying Graphics if this is the base PrintGraphics! + return; + } + base.dispose(); + } + + public override void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) + { + checkState(); + base.drawArc(x, y, width, height, startAngle, arcAngle); + } + + public override void drawBytes(byte[] data, int offset, int length, int x, int y) + { + checkState(); + base.drawBytes(data, offset, length, x, y); + } + + public override void drawChars(char[] data, int offset, int length, int x, int y) + { + checkState(); + base.drawChars(data, offset, length, x, y); + } + + public override bool drawImage(java.awt.Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, java.awt.Color color, java.awt.image.ImageObserver observer) + { + checkState(); + return base.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, color, observer); + } + + public override bool drawImage(java.awt.Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, java.awt.image.ImageObserver observer) + { + checkState(); + return base.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer); + } + + public override bool drawImage(java.awt.Image img, int x, int y, int width, int height, java.awt.Color bgcolor, java.awt.image.ImageObserver observer) + { + checkState(); + return base.drawImage( img, x, y, width, height, bgcolor, observer); + } + + public override bool drawImage(java.awt.Image img, int x, int y, java.awt.Color bgcolor, java.awt.image.ImageObserver observer) + { + checkState(); + return base.drawImage(img, x, y, bgcolor, observer); + } + + public override bool drawImage(java.awt.Image img, int x, int y, int width, int height, java.awt.image.ImageObserver observer) + { + checkState(); + return base.drawImage( img, x, y, width, height, observer); + } + + public override bool drawImage(java.awt.Image img, int x, int y, java.awt.image.ImageObserver observer) + { + checkState(); + return base.drawImage(img, x, y, observer); + } + + public override void drawLine(int x1, int y1, int x2, int y2) + { + checkState(); + base.drawLine(x1, y1, x2, y2); + } + + public override void drawOval(int x, int y, int w, int h) + { + checkState(); + base.drawOval(x, y, w, h); + } + + public override void drawPolygon(java.awt.Polygon polygon) + { + checkState(); + base.drawPolygon(polygon); + } + + public override void drawPolygon(int[] aX, int[] aY, int aLength) + { + checkState(); + base.drawPolygon(aX, aY, aLength); + } + + public override void drawPolyline(int[] aX, int[] aY, int aLength) + { + checkState(); + base.drawPolyline(aX, aY, aLength); + } + + public override void drawRect(int x, int y, int width, int height) + { + checkState(); + base.drawRect(x, y, width, height); + } + + public override void drawRoundRect(int x, int y, int w, int h, int arcWidth, int arcHeight) + { + checkState(); + base.drawRoundRect(x, y, w, h, arcWidth, arcHeight); + } + + public override void fill3DRect(int x, int y, int width, int height, bool raised) + { + checkState(); + base.fill3DRect(x, y, width, height, raised); + } + + public override void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) + { + checkState(); + base.fillArc(x, y, width, height, startAngle, arcAngle); + } + + public override void fillOval(int x, int y, int w, int h) + { + checkState(); + base.fillOval(x, y, w, h); + } + + public override void fillPolygon(java.awt.Polygon polygon) + { + checkState(); + base.fillPolygon(polygon); + } + + public override void fillPolygon(int[] aX, int[] aY, int aLength) + { + checkState(); + base.fillPolygon(aX, aY, aLength); + } + + public override void fillRect(int x, int y, int width, int height) + { + checkState(); + base.fillRect(x, y, width, height); + } + + public override void fillRoundRect(int x, int y, int w, int h, int arcWidth, int arcHeight) + { + checkState(); + base.fillRoundRect(x, y, w, h, arcWidth, arcHeight); + } + + public override java.awt.Shape getClip() + { + checkState(); + return base.getClip(); + } + + public override java.awt.Rectangle getClipBounds(java.awt.Rectangle r) + { + checkState(); + return base.getClipBounds( r ); + } + + public override java.awt.Rectangle getClipBounds() + { + checkState(); + return base.getClipBounds(); + } + + [Obsolete] + public override java.awt.Rectangle getClipRect() + { + checkState(); + return base.getClipRect(); + } + + public override java.awt.Color getColor() + { + checkState(); + return base.getColor(); + } + + public override java.awt.Font getFont() + { + checkState(); + return base.getFont(); + } + + public override java.awt.FontMetrics getFontMetrics(java.awt.Font f) + { + checkState(); + return base.getFontMetrics(f); + } + + public override java.awt.FontMetrics getFontMetrics() + { + checkState(); + return base.getFontMetrics(); + } + + public override void setClip(int x, int y, int width, int height) + { + checkState(); + base.setClip(x,y,width,height); + } + + public override void setClip(java.awt.Shape shape) + { + checkState(); + base.setClip(shape); + } + + public override void setColor(java.awt.Color color) + { + checkState(); + base.setColor(color); + } + + public override void setFont(java.awt.Font f) + { + checkState(); + base.setFont(f); + } + + public override void setPaintMode() + { + checkState(); + base.setPaintMode(); + } + + public override void setXORMode(java.awt.Color param) + { + checkState(); + base.setXORMode(param); + } + + public override void translate(int x, int y) + { + checkState(); + base.translate(x, y); + } + + public override void draw(java.awt.Shape shape) + { + checkState(); + base.draw(shape); + } + + public override bool drawImage(java.awt.Image img, java.awt.geom.AffineTransform xform, ImageObserver observer) + { + checkState(); + return base.drawImage(img, xform, observer); + } + + public override void drawImage(java.awt.image.BufferedImage image, BufferedImageOp op, int x, int y) + { + checkState(); + base.drawImage(image, op, x, y); + } + + public override void drawRenderedImage(java.awt.image.RenderedImage img, java.awt.geom.AffineTransform xform) + { + checkState(); + base.drawRenderedImage(img, xform); + } + + public override void drawRenderableImage(java.awt.image.renderable.RenderableImage image, java.awt.geom.AffineTransform xform) + { + checkState(); + base.drawRenderableImage(image, xform); + } + + public override void drawString(string str, int x, int y) + { + checkState(); + base.drawString(str, x, y); + } + + public override void drawString(string text, float x, float y) + { + checkState(); + base.drawString(text, x, y); + } + + public override void drawString(java.text.AttributedCharacterIterator iterator, int x, int y) + { + checkState(); + base.drawString(iterator, x, y); + } + + public override void drawString(java.text.AttributedCharacterIterator iterator, float x, float y) + { + checkState(); + base.drawString(iterator, x, y); + } + + public override void fill(java.awt.Shape shape) + { + checkState(); + base.fill(shape); + } + + public override bool hit(java.awt.Rectangle rect, java.awt.Shape s, bool onStroke) + { + checkState(); + return base.hit(rect, s, onStroke); + } + + public override java.awt.GraphicsConfiguration getDeviceConfiguration() + { + // no check here, since invariant + return base.getDeviceConfiguration(); + } + + public override void setComposite(java.awt.Composite comp) + { + checkState(); + base.setComposite(comp); + } + + public override void setPaint(java.awt.Paint paint) + { + checkState(); + base.setPaint(paint); + } + + public override void setStroke(java.awt.Stroke stroke) + { + checkState(); + base.setStroke(stroke); + } + + public override void setRenderingHint(java.awt.RenderingHints.Key hintKey, Object hintValue) + { + checkState(); + base.setRenderingHint(hintKey, hintValue); + } + + public override object getRenderingHint(java.awt.RenderingHints.Key hintKey) + { + checkState(); + return base.getRenderingHint(hintKey); + } + + public override void setRenderingHints(java.util.Map hints) + { + checkState(); + base.setRenderingHints(hints); + } + + public override void addRenderingHints(java.util.Map hints) + { + checkState(); + base.addRenderingHints(hints); + } + + public override java.awt.RenderingHints getRenderingHints() + { + checkState(); + return base.getRenderingHints(); + } + + public override void translate(double x, double y) + { + checkState(); + base.translate(x, y); + } + + public override void rotate(double theta) + { + checkState(); + base.rotate(theta); + } + + public override void rotate(double theta, double x, double y) + { + checkState(); + base.rotate(theta, x, y); + } + + public override void scale(double scaleX, double scaleY) + { + checkState(); + base.scale(scaleX, scaleY); + } + + public override void shear(double shearX, double shearY) + { + checkState(); + base.shear(shearX, shearY); + } + + public override void transform(java.awt.geom.AffineTransform tx) + { + checkState(); + base.transform(tx); + } + + public override void setTransform(java.awt.geom.AffineTransform tx) + { + checkState(); + base.setTransform(tx); + } + + public override java.awt.geom.AffineTransform getTransform() + { + checkState(); + return base.getTransform(); + } + + public override java.awt.Paint getPaint() + { + checkState(); + return base.getPaint(); + } + + public override java.awt.Composite getComposite() + { + checkState(); + return base.getComposite(); + } + + public override void setBackground(java.awt.Color color) + { + checkState(); + base.setBackground(color); + } + + public override java.awt.Color getBackground() + { + checkState(); + return base.getBackground(); + } + + public override java.awt.Stroke getStroke() + { + checkState(); + return base.getStroke(); + } + + public override java.awt.font.FontRenderContext getFontRenderContext() + { + checkState(); + return base.getFontRenderContext(); + } + + public override void drawGlyphVector(java.awt.font.GlyphVector gv, float x, float y) + { + checkState(); + base.drawGlyphVector(gv, x, y); + } + } + + /// + /// State to store/restore the state of a NetGraphics/Graphics object + /// + internal class NetGraphicsState + { + private Brush brush; + private Pen pen; + + // Graphics State + private Matrix Transform; + private Region Clip; + private SmoothingMode SmoothingMode; + private PixelOffsetMode PixelOffsetMode; + private TextRenderingHint TextRenderingHint; + private InterpolationMode InterpolationMode; + private CompositingMode CompositingMode; + + private bool savedGraphics = false; + + public NetGraphicsState() + { + } + + public NetGraphicsState( NetGraphics netG ) + { + saveGraphics(netG); + } + + public void saveGraphics(NetGraphics netG) + { + if (netG == null ) + { + return; + } + if (netG.g != null ) + { + this.Transform = netG.g.Transform; + this.Clip = netG.g.Clip; + this.SmoothingMode = netG.g.SmoothingMode; + this.PixelOffsetMode = netG.g.PixelOffsetMode; + this.TextRenderingHint = netG.g.TextRenderingHint; + this.InterpolationMode = netG.g.InterpolationMode; + this.CompositingMode = netG.g.CompositingMode; + savedGraphics = true; + } + if (netG.pen != null && netG.brush != null) + { + pen = (Pen)netG.pen.Clone(); + brush = (Brush)netG.brush.Clone(); + } + } + + public void restoreGraphics(NetGraphics netG) + { + if (netG == null) + { + return; + } + if (netG.g != null) + { + if (savedGraphics) + { + netG.g.Transform = Transform; + netG.g.Clip = Clip; + netG.g.SmoothingMode = SmoothingMode; + netG.g.PixelOffsetMode = PixelOffsetMode; + netG.setTextRenderingHint(TextRenderingHint); + netG.g.InterpolationMode = InterpolationMode; + netG.g.CompositingMode = CompositingMode; + } + else + { + // default values that Java used + netG.g.InterpolationMode = InterpolationMode.NearestNeighbor; + } + } + if ( pen != null && brush != null ) + { + netG.pen = (Pen)pen.Clone(); + netG.brush = (Brush)brush.Clone(); + } + else + { + netG.pen = new Pen(netG.color); + netG.brush = new SolidBrush(netG.color); + netG.setRenderingHint(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING, java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT); + } + } + } + + internal abstract class NetGraphics : java.awt.Graphics2D//sun.java2d.SunGraphics2D + { + private Graphics graphics; + private java.awt.Color javaColor; + private java.awt.Paint javaPaint; + internal Color color; + private Color bgcolor; + private java.awt.Font font; + private java.awt.Stroke stroke; + private static java.awt.BasicStroke defaultStroke = new java.awt.BasicStroke(); + private Font netfont; + private int baseline; + internal Brush brush; + internal Pen pen; + private CompositeHelper composite; + private java.awt.Composite javaComposite = java.awt.AlphaComposite.SrcOver; + private Object textAntialiasHint; + private Object fractionalHint = java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_DEFAULT; + + private static System.Collections.Generic.Dictionary baselines = new System.Collections.Generic.Dictionary(); + + internal static readonly StringFormat FORMAT = new StringFormat(StringFormat.GenericTypographic); + static NetGraphics() + { + FORMAT.FormatFlags = StringFormatFlags.MeasureTrailingSpaces | StringFormatFlags.NoWrap | StringFormatFlags.FitBlackBox; + FORMAT.Trimming = StringTrimming.None; + } + + protected NetGraphics(Graphics g, Object destination, java.awt.Font font, Color fgcolor, Color bgcolor) //: base( new sun.java2d.SurfaceData(destination) ) + { + if (font == null) + { + font = new java.awt.Font("Dialog", java.awt.Font.PLAIN, 12); + } + this.font = font; + netfont = font.getNetFont(); + this.color = fgcolor; + this.bgcolor = bgcolor; + composite = CompositeHelper.Create(javaComposite, g); + init(g); + } + + /// + /// The current C# Graphics + /// + internal virtual Graphics g + { + get { return graphics; } + set { graphics = value; } + } + + protected void init(Graphics graphics) + { + NetGraphicsState state = new NetGraphicsState(); + state.saveGraphics(this); + g = graphics; + state.restoreGraphics(this); + } + + /// + /// Get the size of the graphics. This is used as a hind for some hacks. + /// + /// + protected virtual SizeF GetSize() { + return g.ClipBounds.Size; + } + + public override void clearRect(int x, int y, int width, int height) + { + using (Brush br = bgcolor != Color.Empty ? new SolidBrush(bgcolor) : brush) + { + CompositingMode tempMode = g.CompositingMode; + g.CompositingMode = CompositingMode.SourceCopy; + g.FillRectangle(br, x, y, width, height); + g.CompositingMode = tempMode; + } + } + + public override void clipRect(int x, int y, int w, int h) + { + g.IntersectClip(new Rectangle(x, y, w, h)); + } + + public override void clip(java.awt.Shape shape) + { + if (shape == null) + { + // note that ComponentGraphics overrides clip() to throw a NullPointerException when shape is null + g.ResetClip(); + } + else + { + g.IntersectClip(new Region(J2C.ConvertShape(shape))); + } + } + + public override void dispose() + { + if (pen!=null) pen.Dispose(); + if (brush!=null) brush.Dispose(); + graphics.Dispose(); //for dispose we does not need to synchronize the buffer of a bitmap + } + + public override void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) + { + g.DrawArc(pen, x, y, width, height, 360 - startAngle - arcAngle, arcAngle); + } + + public override void drawBytes(byte[] data, int offset, int length, int x, int y) + { + char[] chars = new char[length]; + for (int i = 0; i < length; i++) + { + chars[i] = (char)data[offset + i]; + } + drawChars(chars, 0, length, x, y); + } + + public override void drawChars(char[] data, int offset, int length, int x, int y) + { + drawString(new String(data, offset, length), x, y); + } + + public override bool drawImage(java.awt.Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, java.awt.Color color, java.awt.image.ImageObserver observer) + { + Image image = J2C.ConvertImage(img); + if (image == null) + { + return false; + } + Rectangle destRect = new Rectangle(dx1, dy1, dx2 - dx1, dy2 - dy1); + using (Brush brush = new SolidBrush(composite.GetColor(color))) { + g.FillRectangle(brush, destRect); + } + lock (image) + { + g.DrawImage(image, destRect, sx1, sy1, sx2 - sx1, sy2 - sy1, GraphicsUnit.Pixel, composite.GetImageAttributes()); + } + return true; + } + + public override bool drawImage(java.awt.Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, java.awt.image.ImageObserver observer) + { + Image image = J2C.ConvertImage(img); + if (image == null) + { + return false; + } + Rectangle destRect = new Rectangle(dx1, dy1, dx2 - dx1, dy2 - dy1); + lock (image) + { + g.DrawImage(image, destRect, sx1, sy1, sx2 - sx1, sy2 - sy1, GraphicsUnit.Pixel, composite.GetImageAttributes()); + } + return true; + } + + public override bool drawImage(java.awt.Image img, int x, int y, int width, int height, java.awt.Color bgcolor, java.awt.image.ImageObserver observer) + { + Image image = J2C.ConvertImage(img); + if (image == null) + { + return false; + } + using (Brush brush = new SolidBrush(composite.GetColor(bgcolor))) { + g.FillRectangle(brush, x, y, width, height); + } + lock (image) + { + g.DrawImage(image, new Rectangle( x, y, width, height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, composite.GetImageAttributes()); + } + return true; + } + + public override bool drawImage(java.awt.Image img, int x, int y, java.awt.Color bgcolor, java.awt.image.ImageObserver observer) + { + if (img == null) { + return false; + } + return drawImage(img, x, y, img.getWidth(observer), img.getHeight(observer), bgcolor, observer); + } + + public override bool drawImage(java.awt.Image img, int x, int y, int width, int height, java.awt.image.ImageObserver observer) + { + Image image = J2C.ConvertImage(img); + if (image == null) + { + return false; + } + lock (image) + { + g.DrawImage(image, new Rectangle(x, y, width, height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, composite.GetImageAttributes()); + } + return true; + } + + public override bool drawImage(java.awt.Image img, int x, int y, java.awt.image.ImageObserver observer) + { + if (img == null) { + return false; + } + return drawImage(img, x, y, img.getWidth(observer), img.getHeight(observer), observer); + } + + public override void drawLine(int x1, int y1, int x2, int y2) + { + // HACK DrawLine doesn't appear to draw the last pixel, so for single pixel lines, we have + // a freaky workaround + if (x1 == x2 && y1 == y2) + { + g.DrawLine(pen, x1, y1, x1 + 0.01f, y2 + 0.01f); + } + else + { + g.DrawLine(pen, x1, y1, x2, y2); + } + } + + public override void drawOval(int x, int y, int w, int h) + { + g.DrawEllipse(pen, x, y, w, h); + } + + public override void drawPolygon(java.awt.Polygon polygon) + { + drawPolygon(polygon.xpoints, polygon.ypoints, polygon.npoints); + } + + public override void drawPolygon(int[] aX, int[] aY, int aLength) + { + Point[] points = new Point[aLength]; + for (int i = 0; i < aLength; i++) + { + points[i].X = aX[i]; + points[i].Y = aY[i]; + } + g.DrawPolygon(pen, points); + } + + /// + /// Draw a sequence of connected lines + /// + /// Array of x coordinates + /// Array of y coordinates + /// Length of coordinate arrays + public override void drawPolyline(int[] aX, int[] aY, int aLength) + { + for (int i = 0; i < aLength - 1; i++) + { + Point point1 = new Point(aX[i], aY[i]); + Point point2 = new Point(aX[i + 1], aY[i + 1]); + g.DrawLine(pen, point1, point2); + } + } + + public override void drawRect(int x, int y, int width, int height) + { + g.DrawRectangle(pen, x, y, width, height); + } + + /// + /// Apparently there is no rounded rec function in .Net. Draw the + /// rounded rectangle by using lines and arcs. + /// + public override void drawRoundRect(int x, int y, int w, int h, int arcWidth, int arcHeight) + { + using (GraphicsPath gp = J2C.ConvertRoundRect(x, y, w, h, arcWidth, arcHeight)) + g.DrawPath(pen, gp); + } + + public override void fill3DRect(int x, int y, int width, int height, bool raised) + { + java.awt.Paint p = getPaint(); + java.awt.Color c = getColor(); + java.awt.Color brighter = c.brighter(); + java.awt.Color darker = c.darker(); + + if( !raised ) { + setColor(darker); + } else if( p != c ) { + setColor(c); + } + fillRect(x + 1, y + 1, width - 2, height - 2); + setColor(raised ? brighter : darker); + fillRect(x, y, 1, height); + fillRect(x + 1, y, width - 2, 1); + setColor(raised ? darker : brighter); + fillRect(x + 1, y + height - 1, width - 1, 1); + fillRect(x + width - 1, y, 1, height - 1); + setPaint(p); + } + + public override void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) + { + g.FillPie(brush, x, y, width, height, 360 - startAngle - arcAngle, arcAngle); + } + + public override void fillOval(int x, int y, int w, int h) + { + g.FillEllipse(brush, x, y, w, h); + } + + public override void fillPolygon(java.awt.Polygon polygon) + { + fillPolygon(polygon.xpoints, polygon.ypoints, polygon.npoints); + } + + public override void fillPolygon(int[] aX, int[] aY, int aLength) + { + Point[] points = new Point[aLength]; + for (int i = 0; i < aLength; i++) + { + points[i].X = aX[i]; + points[i].Y = aY[i]; + } + g.FillPolygon(brush, points); + } + + public override void fillRect(int x, int y, int width, int height) + { + g.FillRectangle(brush, x, y, width, height); + } + + public override void fillRoundRect(int x, int y, int w, int h, int arcWidth, int arcHeight) + { + GraphicsPath gp = J2C.ConvertRoundRect(x, y, w, h, arcWidth, arcHeight); + g.FillPath(brush, gp); + gp.Dispose(); + } + + public override java.awt.Shape getClip() + { + return getClipBounds(); + } + + public override java.awt.Rectangle getClipBounds(java.awt.Rectangle r) + { + using (Region clip = g.Clip) + { + if (!clip.IsInfinite(g)) + { + RectangleF rec = clip.GetBounds(g); + r.x = (int) rec.X; + r.y = (int) rec.Y; + r.width = (int) rec.Width; + r.height = (int) rec.Height; + } + return r; + } + } + + public override java.awt.Rectangle getClipBounds() + { + using (Region clip = g.Clip) + { + if (clip.IsInfinite(g)) + { + return null; + } + RectangleF rec = clip.GetBounds(g); + return C2J.ConvertRectangle(rec); + } + } + + [Obsolete] + public override java.awt.Rectangle getClipRect() + { + return getClipBounds(); + } + + public override java.awt.Color getColor() + { + if (javaColor == null) + { + javaColor = composite.GetColor(color); + } + return javaColor; + } + + public override java.awt.Font getFont() + { + return font; + } + + public override java.awt.FontMetrics getFontMetrics(java.awt.Font f) + { + return sun.font.FontDesignMetrics.getMetrics(f); + } + + public override java.awt.FontMetrics getFontMetrics() + { + return sun.font.FontDesignMetrics.getMetrics(font); + } + + public override void setClip(int x, int y, int width, int height) + { + g.Clip = new Region(new Rectangle(x, y, width, height)); + } + + public override void setClip(java.awt.Shape shape) + { + if (shape == null) + { + Region clip = g.Clip; + clip.MakeInfinite(); + g.Clip = clip; + } + else + { + g.Clip = new Region(J2C.ConvertShape(shape)); + } + } + + public override void setColor(java.awt.Color color) + { + if (color == null || color == this.javaPaint) + { + // Does not change the color, if it is null like in SunGraphics2D + return; + } + this.javaPaint = this.javaColor = color; + this.color = composite.GetColor(color); + if (brush is SolidBrush) + { + ((SolidBrush)brush).Color = this.color; + } + else + { + brush.Dispose(); + brush = new SolidBrush(this.color); + } + pen.Color = this.color; + pen.Brush = brush; + } + + public override void setFont(java.awt.Font f) + { + if (f != null && f != font) + { + netfont = f.getNetFont(); + font = f; + baseline = getBaseline( netfont, g.TextRenderingHint ); + } + } + + public override void setPaintMode() + { + throw new NotImplementedException(); + } + + public override void setXORMode(java.awt.Color param) + { + if( param == null ) { + throw new java.lang.IllegalArgumentException("null XORColor"); + } + throw new NotImplementedException(); + } + + public override void translate(int x, int y) + { + Matrix transform = g.Transform; + transform.Translate(x, y); + g.Transform = transform; + } + + public override void draw(java.awt.Shape shape) + { + using (GraphicsPath gp = J2C.ConvertShape(shape)) + { + g.DrawPath(pen, gp); + } + } + + public override bool drawImage(java.awt.Image img, java.awt.geom.AffineTransform xform, ImageObserver observer) + { + if (img == null) { + return true; + } + + if (xform == null || xform.isIdentity()) { + return drawImage(img, 0, 0, null, observer); + } + + NetGraphics clone = (NetGraphics)create(); + clone.transform(xform); + bool rendered = clone.drawImage(img, 0, 0, null, observer); + clone.dispose(); + return rendered; + } + + public override void drawImage(java.awt.image.BufferedImage image, BufferedImageOp op, int x, int y) + { + + if( op == null ) { + drawImage(image, x, y, null); + } else { + if( !(op is AffineTransformOp) ) { + drawImage(op.filter(image, null), x, y, null); + } else { + Console.WriteLine(new System.Diagnostics.StackTrace()); + throw new NotImplementedException(); + } + } + } + + public override void drawRenderedImage(java.awt.image.RenderedImage img, java.awt.geom.AffineTransform xform) + { + if (img == null) { + return; + } + + // BufferedImage case: use a simple drawImage call + if (img is BufferedImage) { + BufferedImage bufImg = (BufferedImage)img; + drawImage(bufImg,xform,null); + return; + } + throw new NotImplementedException("drawRenderedImage not implemented for images which are not BufferedImages."); + } + + public override void drawRenderableImage(java.awt.image.renderable.RenderableImage image, java.awt.geom.AffineTransform xform) + { + throw new NotImplementedException(); + } + + public override void drawString(string str, int x, int y) + { + drawString(str, (float)x, (float)y); + } + + public override void drawString(String text, float x, float y) { + if (text.Length == 0) { + return; + } + CompositingMode origCM = g.CompositingMode; + try { + if (origCM != CompositingMode.SourceOver) { + // Java has a different behaviar for AlphaComposite and Text Antialiasing + g.CompositingMode = CompositingMode.SourceOver; + } + + bool fractional = isFractionalMetrics(); + if (fractional || !sun.font.StandardGlyphVector.isSimpleString(font, text)) { + g.DrawString(text, netfont, brush, x, y - baseline, FORMAT); + } else { + // fixed metric for simple text, we position every character to simulate the Java behaviour + java.awt.font.FontRenderContext frc = new java.awt.font.FontRenderContext(null, isAntiAlias(), fractional); + sun.font.FontDesignMetrics metrics = sun.font.FontDesignMetrics.getMetrics(font, frc); + y -= baseline; + for (int i = 0; i < text.Length; i++) { + g.DrawString(text.Substring(i, 1), netfont, brush, x, y, FORMAT); + x += metrics.charWidth(text[i]); + } + } + } finally { + if (origCM != CompositingMode.SourceOver) { + g.CompositingMode = origCM; + } + } + } + + public override void drawString(java.text.AttributedCharacterIterator iterator, int x, int y) + { + drawString(iterator, (float) x, (float) y); + } + + public override void drawString(java.text.AttributedCharacterIterator iterator, float x, float y) + { + if( iterator == null ) { + throw new java.lang.NullPointerException("AttributedCharacterIterator is null"); + } + if( iterator.getBeginIndex() == iterator.getEndIndex() ) { + return; /* nothing to draw */ + } + java.awt.font.TextLayout tl = new java.awt.font.TextLayout(iterator, getFontRenderContext()); + tl.draw(this, x, y); + } + + public override void fill(java.awt.Shape shape) + { + g.FillPath(brush, J2C.ConvertShape(shape)); + } + + public override bool hit(java.awt.Rectangle rect, java.awt.Shape s, bool onStroke) + { + if (onStroke) + { + //TODO use stroke + //s = stroke.createStrokedShape(s); + } + return s.intersects(rect); + } + + public override java.awt.GraphicsConfiguration getDeviceConfiguration() + { + return new NetGraphicsConfiguration(Screen.PrimaryScreen); + } + + public override void setComposite(java.awt.Composite comp) + { + if (javaComposite == comp) { + return; + } + if (comp == null) + { + throw new java.lang.IllegalArgumentException("null Composite"); + } + this.javaComposite = comp; + java.awt.Paint oldPaint = getPaint(); //getPaint() is never null + composite = CompositeHelper.Create(comp, g); + javaPaint = null; + setPaint(oldPaint); + } + + public override void setPaint(java.awt.Paint paint) + { + if (paint is java.awt.Color) + { + setColor((java.awt.Color)paint); + return; + } + + if (paint == null || this.javaPaint == paint) + { + return; + } + this.javaPaint = paint; + + if (paint is java.awt.GradientPaint) + { + java.awt.GradientPaint gradient = (java.awt.GradientPaint)paint; + LinearGradientBrush linear; + if (gradient.isCyclic()) + { + linear = new LinearGradientBrush( + J2C.ConvertPoint(gradient.getPoint1()), + J2C.ConvertPoint(gradient.getPoint2()), + composite.GetColor(gradient.getColor1()), + composite.GetColor(gradient.getColor2())); + } + else + { + //HACK because .NET does not support continue gradient like Java else Tile Gradient + //that we receize the rectangle very large (factor z) and set 4 color values + // a exact solution will calculate the size of the Graphics with the current transform + Color color1 = composite.GetColor(gradient.getColor1()); + Color color2 = composite.GetColor(gradient.getColor2()); + float x1 = (float)gradient.getPoint1().getX(); + float x2 = (float)gradient.getPoint2().getX(); + float y1 = (float)gradient.getPoint1().getY(); + float y2 = (float)gradient.getPoint2().getY(); + float diffX = x2 - x1; + float diffY = y2 - y1; + const float z = 60; //HACK zoom factor, with a larger factor .NET will make the gradient wider. + linear = new LinearGradientBrush( + new PointF(x1 - z * diffX, y1 - z * diffY), + new PointF(x2 + z * diffX, y2 + z * diffY), + color1, + color1); + ColorBlend colorBlend = new ColorBlend(4); + Color[] colors = colorBlend.Colors; + colors[0] = colors[1] = color1; + colors[2] = colors[3] = color2; + float[] positions = colorBlend.Positions; + positions[1] = z / (2 * z + 1); + positions[2] = (z + 1) / (2 * z + 1); + positions[3] = 1.0f; + linear.InterpolationColors = colorBlend; + } + linear.WrapMode = WrapMode.TileFlipXY; + brush = linear; + pen.Brush = brush; + return; + } + + if (paint is java.awt.TexturePaint) + { + java.awt.TexturePaint texture = (java.awt.TexturePaint)paint; + Bitmap txtr = J2C.ConvertImage(texture.getImage()); + java.awt.geom.Rectangle2D anchor = texture.getAnchorRect(); + TextureBrush txtBrush; + brush = txtBrush = new TextureBrush(txtr, new Rectangle(0, 0, txtr.Width, txtr.Height), composite.GetImageAttributes()); + txtBrush.TranslateTransform((float)anchor.getX(), (float)anchor.getY()); + txtBrush.ScaleTransform((float)anchor.getWidth() / txtr.Width, (float)anchor.getHeight() / txtr.Height); + txtBrush.WrapMode = WrapMode.Tile; + pen.Brush = brush; + return; + } + + if (paint is java.awt.LinearGradientPaint) { + java.awt.LinearGradientPaint gradient = (java.awt.LinearGradientPaint)paint; + PointF start = J2C.ConvertPoint(gradient.getStartPoint()); + PointF end = J2C.ConvertPoint(gradient.getEndPoint()); + + java.awt.Color[] javaColors = gradient.getColors(); + ColorBlend colorBlend; + Color[] colors; + bool noCycle = gradient.getCycleMethod() == java.awt.MultipleGradientPaint.CycleMethod.NO_CYCLE; + if (noCycle) { + //HACK because .NET does not support continue gradient like Java else Tile Gradient + //that we receize the rectangle very large (factor z) and set 2 additional color values + //an exact solution will calculate the size of the Graphics with the current transform + float diffX = end.X - start.X; + float diffY = end.Y - start.Y; + SizeF size = GetSize(); + //HACK zoom factor, with a larger factor .NET will make the gradient wider. + float z = Math.Min(10, Math.Max(size.Width / diffX, size.Height / diffY)); + start.X -= z * diffX; + start.Y -= z * diffY; + end.X += z * diffX; + end.Y += z * diffY; + + colorBlend = new ColorBlend(javaColors.Length + 2); + colors = colorBlend.Colors; + float[] fractions = gradient.getFractions(); + float[] positions = colorBlend.Positions; + for (int i = 0; i < javaColors.Length; i++) { + colors[i + 1] = composite.GetColor(javaColors[i]); + positions[i + 1] = (z + fractions[i]) / (2 * z + 1); + } + colors[0] = colors[1]; + colors[colors.Length - 1] = colors[colors.Length - 2]; + positions[positions.Length - 1] = 1.0f; + } else { + colorBlend = new ColorBlend(javaColors.Length); + colors = colorBlend.Colors; + colorBlend.Positions = gradient.getFractions(); + for (int i = 0; i < javaColors.Length; i++) { + colors[i] = composite.GetColor(javaColors[i]); + } + } + LinearGradientBrush linear = new LinearGradientBrush(start, end, colors[0], colors[colors.Length - 1]); + linear.InterpolationColors = colorBlend; + switch (gradient.getCycleMethod().ordinal()) { + case (int)java.awt.MultipleGradientPaint.CycleMethod.__Enum.NO_CYCLE: + case (int)java.awt.MultipleGradientPaint.CycleMethod.__Enum.REFLECT: + linear.WrapMode = WrapMode.TileFlipXY; + break; + case (int)java.awt.MultipleGradientPaint.CycleMethod.__Enum.REPEAT: + linear.WrapMode = WrapMode.Tile; + break; + } + brush = linear; + pen.Brush = brush; + return; + } + + if (paint is java.awt.RadialGradientPaint ) + { + java.awt.RadialGradientPaint gradient = (java.awt.RadialGradientPaint)paint; + GraphicsPath path = new GraphicsPath(); + SizeF size = GetSize(); + + PointF center = J2C.ConvertPoint(gradient.getCenterPoint()); + + float radius = gradient.getRadius(); + int factor = (int)Math.Ceiling(Math.Max(size.Width, size.Height) / radius); + + float diameter = radius * factor; + path.AddEllipse(center.X - diameter, center.Y - diameter, diameter * 2, diameter * 2); + + java.awt.Color[] javaColors = gradient.getColors(); + float[] fractions = gradient.getFractions(); + int length = javaColors.Length; + ColorBlend colorBlend = new ColorBlend(length * factor); + Color[] colors = colorBlend.Colors; + float[] positions = colorBlend.Positions; + + for (int c = 0, j = length - 1; j >= 0; ) + { + positions[c] = (1 - fractions[j]) / factor; + colors[c++] = composite.GetColor(javaColors[j--]); + } + + java.awt.MultipleGradientPaint.CycleMethod.__Enum cycle = (java.awt.MultipleGradientPaint.CycleMethod.__Enum)gradient.getCycleMethod().ordinal(); + for (int f = 1; f < factor; f++) + { + int off = f * length; + for (int c = 0, j = length - 1; j >= 0; j--, c++) + { + switch (cycle) + { + case java.awt.MultipleGradientPaint.CycleMethod.__Enum.REFLECT: + if (f % 2 == 0) + { + positions[off + c] = (f + 1 - fractions[j]) / factor; + colors[off + c] = colors[c]; + } + else + { + positions[off + c] = (f + fractions[c]) / factor; + colors[off + c] = colors[j]; + } + break; + case java.awt.MultipleGradientPaint.CycleMethod.__Enum.NO_CYCLE: + positions[off + c] = (f + 1 - fractions[j]) / factor; + break; + default: //CycleMethod.REPEAT + positions[off + c] = (f + 1 - fractions[j]) / factor; + colors[off + c] = colors[c]; + break; + } + } + } + if (cycle == java.awt.MultipleGradientPaint.CycleMethod.__Enum.NO_CYCLE && factor > 1) + { + Array.Copy(colors, 0, colors, colors.Length - length, length); + Color color = colors[length - 1]; + for (int i = colors.Length - length - 1; i >= 0; i--) + { + colors[i] = color; + } + } + + PathGradientBrush pathBrush = new PathGradientBrush(path); + pathBrush.CenterPoint = center; + pathBrush.InterpolationColors = colorBlend; + + brush = pathBrush; + pen.Brush = brush; + return; + } + + //generic paint to brush conversion for custom paints + //the tranform of the graphics should not change between the creation and it usage + using (Matrix transform = g.Transform) + { + SizeF size = GetSize(); + int width = (int)size.Width; + int height = (int)size.Height; + java.awt.Rectangle bounds = new java.awt.Rectangle(0, 0, width, height); + + java.awt.PaintContext context = paint.createContext(ColorModel.getRGBdefault(), bounds, bounds, C2J.ConvertMatrix(transform), getRenderingHints()); + WritableRaster raster = (WritableRaster)context.getRaster(0, 0, width, height); + BufferedImage txtrImage = new BufferedImage(context.getColorModel(), raster, true, null); + Bitmap txtr = J2C.ConvertImage(txtrImage); + + TextureBrush txtBrush; + brush = txtBrush = new TextureBrush(txtr, new Rectangle(0, 0, width, height), composite.GetImageAttributes()); + transform.Invert(); + txtBrush.Transform = transform; + txtBrush.WrapMode = WrapMode.Tile; + pen.Brush = brush; + return; + } + } + + public override void setStroke(java.awt.Stroke stroke) + { + if (this.stroke != null && this.stroke.Equals(stroke)) + { + return; + } + this.stroke = stroke; + if (stroke is java.awt.BasicStroke) + { + java.awt.BasicStroke s = (java.awt.BasicStroke)stroke; + + pen = new Pen(pen.Brush, s.getLineWidth()); + + SetLineJoin(s); + SetLineDash(s); + } + else + { + Console.WriteLine("Unknown Stroke type: " + stroke.GetType().FullName); + } + } + + private void SetLineJoin(java.awt.BasicStroke s) + { + pen.MiterLimit = s.getMiterLimit(); + pen.LineJoin = J2C.ConvertLineJoin(s.getLineJoin()); + } + + private void SetLineDash(java.awt.BasicStroke s) + { + float[] dash = s.getDashArray(); + if (dash == null) + { + pen.DashStyle = DashStyle.Solid; + } else { + if (dash.Length % 2 == 1) + { + int len = dash.Length; + Array.Resize(ref dash, len * 2); + Array.Copy(dash, 0, dash, len, len); + } + float lineWidth = s.getLineWidth(); + if (lineWidth > 1) // for values < 0 there is no correctur needed + { + for (int i = 0; i < dash.Length; i++) + { + //dividing by line thickness because of the representation difference + dash[i] = dash[i] / lineWidth; + } + } + // To fix the problem where solid style in Java can be represented at { 1.0, 0.0 }. + // In .NET, however, array can only have positive value + if (dash.Length == 2 && dash[dash.Length - 1] == 0) + { + Array.Resize(ref dash, 1); + } + + float dashPhase = s.getDashPhase(); + // correct the dash cap + switch (s.getEndCap()) + { + case java.awt.BasicStroke.CAP_BUTT: + pen.DashCap = DashCap.Flat; + break; + case java.awt.BasicStroke.CAP_ROUND: + pen.DashCap = DashCap.Round; + break; + case java.awt.BasicStroke.CAP_SQUARE: + pen.DashCap = DashCap.Flat; + // there is no equals DashCap in .NET, we need to emulate it + dashPhase += lineWidth / 2; + for (int i = 0; i < dash.Length; i++) + { + if (i % 2 == 0) + { + dash[i] += 1; + } + else + { + dash[i] = Math.Max(0.00001F, dash[i] - 1); + } + } + break; + default: + Console.WriteLine("Unknown dash cap type:" + s.getEndCap()); + break; + } + + // calc the dash offset + if (lineWidth > 0) + { + //dividing by line thickness because of the representation difference + pen.DashOffset = dashPhase / lineWidth; + } + else + { + // thickness == 0 + if (dashPhase > 0) + { + pen.Width = lineWidth = 0.001F; // hack to prevent a division with 0 + pen.DashOffset = dashPhase / lineWidth; + } + else + { + pen.DashOffset = 0; + } + } + + // set the final dash pattern + pen.DashPattern = dash; + } + } + + public override void setRenderingHint(java.awt.RenderingHints.Key hintKey, Object hintValue) + { + if (hintKey == java.awt.RenderingHints.KEY_ANTIALIASING) + { + if (hintValue == java.awt.RenderingHints.VALUE_ANTIALIAS_DEFAULT) + { + g.SmoothingMode = SmoothingMode.Default; + g.PixelOffsetMode = PixelOffsetMode.Default; + return; + } + if (hintValue == java.awt.RenderingHints.VALUE_ANTIALIAS_OFF) + { + g.SmoothingMode = SmoothingMode.None; + g.PixelOffsetMode = PixelOffsetMode.Default; + return; + } + if (hintValue == java.awt.RenderingHints.VALUE_ANTIALIAS_ON) + { + g.SmoothingMode = SmoothingMode.AntiAlias; + g.PixelOffsetMode = PixelOffsetMode.HighQuality; + return; + } + return; + } + if (hintKey == java.awt.RenderingHints.KEY_INTERPOLATION) + { + if (hintValue == java.awt.RenderingHints.VALUE_INTERPOLATION_BILINEAR) + { + g.InterpolationMode = InterpolationMode.HighQualityBilinear; + return; + } + if (hintValue == java.awt.RenderingHints.VALUE_INTERPOLATION_BICUBIC) + { + g.InterpolationMode = InterpolationMode.HighQualityBicubic; + return; + } + if (hintValue == java.awt.RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR) + { + g.InterpolationMode = InterpolationMode.NearestNeighbor; + return; + } + return; + } + if (hintKey == java.awt.RenderingHints.KEY_TEXT_ANTIALIASING) + { + if (hintValue == java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT || + hintValue == java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_OFF) + { + setTextRenderingHint(TextRenderingHint.SingleBitPerPixelGridFit); + textAntialiasHint = hintValue; + return; + } + if (hintValue == java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON) + { + setTextRenderingHint(TextRenderingHint.AntiAlias); + textAntialiasHint = hintValue; + return; + } + return; + } + if (hintKey == java.awt.RenderingHints.KEY_FRACTIONALMETRICS) + { + if (hintValue == java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_DEFAULT || + hintValue == java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_OFF || + hintValue == java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_ON) + { + fractionalHint = hintValue; + } + return; + } + + } + + public override object getRenderingHint(java.awt.RenderingHints.Key hintKey) + { + return getRenderingHints().get(hintKey); + } + + public override void setRenderingHints(java.util.Map hints) + { + addRenderingHints(hints); + //TODO all not included values should reset to default, but was is default? + } + + public override void addRenderingHints(java.util.Map hints) + { + Iterator iterator = hints.entrySet().iterator(); + while (iterator.hasNext()) + { + java.util.Map.Entry entry = (java.util.Map.Entry)iterator.next(); + setRenderingHint((java.awt.RenderingHints.Key)entry.getKey(), entry.getValue()); + } + } + + public override java.awt.RenderingHints getRenderingHints() + { + java.awt.RenderingHints hints = new java.awt.RenderingHints(null); + switch (g.SmoothingMode) + { + case SmoothingMode.Default: + hints.put(java.awt.RenderingHints.KEY_ANTIALIASING, java.awt.RenderingHints.VALUE_ANTIALIAS_DEFAULT); + break; + case SmoothingMode.None: + hints.put(java.awt.RenderingHints.KEY_ANTIALIASING, java.awt.RenderingHints.VALUE_ANTIALIAS_OFF); + break; + case SmoothingMode.AntiAlias: + hints.put(java.awt.RenderingHints.KEY_ANTIALIASING, java.awt.RenderingHints.VALUE_ANTIALIAS_ON); + break; + } + + switch (g.InterpolationMode) + { + case InterpolationMode.Bilinear: + case InterpolationMode.HighQualityBilinear: + hints.put(java.awt.RenderingHints.KEY_INTERPOLATION, java.awt.RenderingHints.VALUE_INTERPOLATION_BILINEAR); + break; + case InterpolationMode.Bicubic: + case InterpolationMode.HighQualityBicubic: + hints.put(java.awt.RenderingHints.KEY_INTERPOLATION, java.awt.RenderingHints.VALUE_INTERPOLATION_BICUBIC); + break; + case InterpolationMode.NearestNeighbor: + hints.put(java.awt.RenderingHints.KEY_INTERPOLATION, java.awt.RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); + break; + } + + hints.put(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING, textAntialiasHint); + hints.put(java.awt.RenderingHints.KEY_FRACTIONALMETRICS, fractionalHint); + return hints; + } + + public override void translate(double x, double y) + { + Matrix transform = g.Transform; + transform.Translate((float)x, (float)y); + g.Transform = transform; + } + + private static double RadiansToDegrees(double radians) + { + return radians * (180 / Math.PI); + } + + public override void rotate(double theta) + { + Matrix transform = g.Transform; + transform.Rotate((float)RadiansToDegrees(theta)); + g.Transform = transform; + } + + public override void rotate(double theta, double x, double y) + { + Matrix transform = g.Transform; + transform.Translate((float)x, (float)y); + transform.Rotate((float)RadiansToDegrees(theta)); + transform.Translate(-(float)x, -(float)y); + g.Transform = transform; + } + + public override void scale(double scaleX, double scaleY) + { + using (Matrix transform = g.Transform) + { + transform.Scale((float)scaleX, (float)scaleY); + g.Transform = transform; + } + } + + public override void shear(double shearX, double shearY) + { + using (Matrix transform = g.Transform) + { + transform.Shear((float)shearX, (float)shearY); + g.Transform = transform; + } + } + + public override void transform(java.awt.geom.AffineTransform tx) + { + using (Matrix transform = g.Transform, + matrix = J2C.ConvertTransform(tx)) + { + transform.Multiply(matrix); + g.Transform = transform; + } + } + + public override void setTransform(java.awt.geom.AffineTransform tx) + { + g.Transform = J2C.ConvertTransform(tx); + } + + public override java.awt.geom.AffineTransform getTransform() + { + using (Matrix matrix = g.Transform) + { + return C2J.ConvertMatrix(matrix); + } + } + + public override java.awt.Paint getPaint() + { + if( javaPaint == null ) { + javaPaint = composite.GetColor(color); + } + return javaPaint; + } + + public override java.awt.Composite getComposite() + { + return javaComposite; + } + + public override void setBackground(java.awt.Color backcolor) + { + bgcolor = backcolor == null ? Color.Empty : Color.FromArgb(backcolor.getRGB()); + } + + public override java.awt.Color getBackground() + { + return bgcolor == Color.Empty ? null : new java.awt.Color(bgcolor.ToArgb(), true); + } + + public override java.awt.Stroke getStroke() + { + if (stroke == null) + { + return defaultStroke; + } + return stroke; + } + + internal void setTextRenderingHint(TextRenderingHint hint) + { + g.TextRenderingHint = hint; + baseline = getBaseline(netfont, hint); + } + + /// + /// Caclulate the baseline from a font and a TextRenderingHint + /// + /// the font + /// the used TextRenderingHint + /// + private static int getBaseline(Font font, TextRenderingHint hint) + { + lock (baselines) + { + String key = font.ToString() + hint.ToString(); + int baseline; + if (!baselines.TryGetValue(key, out baseline)) + { + FontFamily family = font.FontFamily; + FontStyle style = font.Style; + float ascent = family.GetCellAscent(style); + float lineSpace = family.GetLineSpacing(style); + + baseline = (int)Math.Round(font.GetHeight() * ascent / lineSpace); + + // Until this point the calulation use only the Font. But with different TextRenderingHint there are smal differences. + // There is no API that calulate the offset from TextRenderingHint that we messure it. + const int w = 3; + const int h = 3; + + Bitmap bitmap = new Bitmap(w, h); + Graphics g = Graphics.FromImage(bitmap); + g.TextRenderingHint = hint; + g.FillRectangle(new SolidBrush(Color.White), 0, 0, w, h); + g.DrawString("A", font, new SolidBrush(Color.Black), 0, -baseline, FORMAT); + g.DrawString("X", font, new SolidBrush(Color.Black), 0, -baseline, FORMAT); + g.Dispose(); + + int y = 0; + LINE: + while (y < h) + { + for (int x = 0; x < w; x++) + { + Color color = bitmap.GetPixel(x, y); + if (color.GetBrightness() < 0.5) + { + //there is a black pixel, we continue in the next line. + baseline++; + y++; + goto LINE; + } + } + break; // there was a line without black pixel + } + + + baselines[key] = baseline; + } + return baseline; + } + } + + private bool isAntiAlias() + { + switch (g.TextRenderingHint) + { + case TextRenderingHint.AntiAlias: + case TextRenderingHint.AntiAliasGridFit: + case TextRenderingHint.ClearTypeGridFit: + return true; + default: + return false; + } + } + + private bool isFractionalMetrics() + { + return fractionalHint == java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_ON; + } + + public override java.awt.font.FontRenderContext getFontRenderContext() + { + return new java.awt.font.FontRenderContext(getTransform(), isAntiAlias(), isFractionalMetrics()); + } + + public override void drawGlyphVector(java.awt.font.GlyphVector gv, float x, float y) + { + java.awt.font.FontRenderContext frc = gv.getFontRenderContext(); + Matrix currentMatrix = null; + Font currentFont = netfont; + TextRenderingHint currentHint = g.TextRenderingHint; + int currentBaseline = baseline; + try + { + java.awt.Font javaFont = gv.getFont(); + if (javaFont != null) + { + netfont = javaFont.getNetFont(); + } + TextRenderingHint hint; + if (frc.isAntiAliased()) { + if( frc.usesFractionalMetrics() ){ + hint = TextRenderingHint.AntiAlias; + } else { + hint = TextRenderingHint.AntiAliasGridFit; + } + } else { + if (frc.usesFractionalMetrics()) { + hint = TextRenderingHint.SingleBitPerPixel; + } else { + hint = TextRenderingHint.SingleBitPerPixelGridFit; + } + } + g.TextRenderingHint = hint; + baseline = getBaseline(netfont, hint); + if (!frc.getTransform().equals(getTransform())) + { + // save the old context and use the transformation from the renderContext + currentMatrix = g.Transform; + g.Transform = J2C.ConvertTransform(frc.getTransform()); + } + drawString(J2C.ConvertGlyphVector(gv), x, y); + } + finally + { + // Restore the old context if needed + g.TextRenderingHint = currentHint; + baseline = currentBaseline; + netfont = currentFont; + if (currentMatrix != null) + { + g.Transform = currentMatrix; + } + } + } + } + + sealed class NetGraphicsConfiguration : java.awt.GraphicsConfiguration + { + internal readonly Screen screen; + + public NetGraphicsConfiguration(Screen screen) + { + this.screen = screen; + } + + public override java.awt.image.BufferedImage createCompatibleImage(int width, int height, int transparency) + { + switch (transparency) + { + case java.awt.Transparency.__Fields.OPAQUE: + return new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + case java.awt.Transparency.__Fields.BITMASK: + return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE); + case java.awt.Transparency.__Fields.TRANSLUCENT: + return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + default: + throw new java.lang.IllegalArgumentException("transparency:" + transparency); + } + } + + public override java.awt.image.BufferedImage createCompatibleImage(int width, int height) + { + return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + } + + public override java.awt.image.VolatileImage createCompatibleVolatileImage(int param1, int param2, java.awt.ImageCapabilities param3) + { + throw new NotImplementedException(); + } + + public override java.awt.image.VolatileImage createCompatibleVolatileImage(int width, int height) + { + return new NetVolatileImage(width, height); + } + + public override java.awt.Rectangle getBounds() + { + System.Drawing.Rectangle bounds = screen.Bounds; + return new java.awt.Rectangle(bounds.X, bounds.Y, bounds.Width, bounds.Height); + } + + public override java.awt.BufferCapabilities getBufferCapabilities() + { + throw new NotImplementedException(); + } + + public override java.awt.image.ColorModel getColorModel(int transparency) + { + if (transparency == java.awt.Transparency.__Fields.TRANSLUCENT) + { + //we return the default ColorModel because this produce the fewest problems with convertions + return ColorModel.getRGBdefault(); + } + else + { + return null; + } + } + + public override java.awt.image.ColorModel getColorModel() + { + //we return the default ColorModel because this produce the fewest problems with convertions + return ColorModel.getRGBdefault(); + } + + public override java.awt.geom.AffineTransform getDefaultTransform() + { + return new java.awt.geom.AffineTransform(); + } + + public override java.awt.GraphicsDevice getDevice() + { + return new NetGraphicsDevice(screen); + } + + public override java.awt.ImageCapabilities getImageCapabilities() + { + throw new NotImplementedException(); + } + + public override java.awt.geom.AffineTransform getNormalizingTransform() + { + throw new NotImplementedException(); + } + + public override VolatileImage createCompatibleVolatileImage(int width, int height, int transparency) + { + return new NetVolatileImage(width, height); + } + + public override VolatileImage createCompatibleVolatileImage(int width, int height, java.awt.ImageCapabilities caps, int transparency) + { + return new NetVolatileImage(width, height); + } + + public override bool isTranslucencyCapable() + { + return true; + } + } + + class NetGraphicsDevice : java.awt.GraphicsDevice + { + internal readonly Screen screen; + + internal NetGraphicsDevice(Screen screen) + { + this.screen = screen; + } + + public override java.awt.GraphicsConfiguration[] getConfigurations() + { + Screen[] screens = Screen.AllScreens; + NetGraphicsConfiguration[] configs = new NetGraphicsConfiguration[screens.Length]; + for (int i = 0; i < screens.Length; i++) + { + configs[i] = new NetGraphicsConfiguration(screens[i]); + } + return configs; + } + + public override java.awt.GraphicsConfiguration getDefaultConfiguration() + { + return new NetGraphicsConfiguration(screen); + } + + public override string getIDstring() + { + return screen.DeviceName; + } + + public override int getType() + { + return TYPE_RASTER_SCREEN; + } + } + + public class NetGraphicsEnvironment : sun.java2d.SunGraphicsEnvironment + { + + public override bool isDisplayLocal() + { + return true; + } + + // Create a bitmap with the dimensions of the argument image. Then + // create a graphics objects from the bitmap. All paint operations will + // then paint the bitmap. + public override java.awt.Graphics2D createGraphics(BufferedImage bi) + { + return new BitmapGraphics(bi.getBitmap(), bi ); + } + + public override java.awt.Font[] getAllFonts() + { +#if WINFX + System.Collections.Generic.ICollection typefaces = System.Windows.Media.Fonts.SystemTypefaces; + java.awt.Font[] fonts = new java.awt.Font[typefaces.Count]; + int i = 0; + foreach (Typeface face in typefaces) + { + FontFamily family = face.FontFamily; + fonts[i++] = new java.awt.Font(family.GetName(0), face.Style, 1); + } +#else + String[] names = getAvailableFontFamilyNames(); + java.awt.Font[] fonts = new java.awt.Font[names.Length]; + for(int i=0; i need invoke or lock + } + + public override int getWidth(ImageObserver io) + { + return width; // bitmap.Width --> need invoke or lock + } + + public override object getProperty(string str, ImageObserver io) + { + throw new NotImplementedException(); + } + + public override java.awt.Graphics2D createGraphics() + { + //Graphics g = Graphics.FromImage(bitmap); + // HACK for off-screen images we don't want ClearType or anti-aliasing + // TODO I'm sure Java 2D has a way to control text rendering quality, we should honor that + //g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit; + return new BitmapGraphics(bitmap, this, getFont(), J2C.ConvertColor(getForeground()), J2C.ConvertColor(getBackground())); + } + + public override int getHeight() + { + return height; // bitmap.Height --> need invoke or lock + } + + public override int getWidth() + { + return width; // bitmap.Width --> need invoke or lock + } + + public override BufferedImage getSnapshot() + { + return new BufferedImage(bitmap); + } + + public override int validate(java.awt.GraphicsConfiguration gc) + { + return 0; + } + + public override java.awt.ImageCapabilities getCapabilities() + { + throw new NotImplementedException(); + } + + public override void flush() + { + } + } + + class NoImage : java.awt.Image + { + private sun.awt.image.InputStreamImageSource source; + + internal NoImage(sun.awt.image.InputStreamImageSource source) { + this.source = source; + } + + public override int getWidth(java.awt.image.ImageObserver observer) + { + if (observer != null) + { + observer.imageUpdate(this, java.awt.image.ImageObserver.__Fields.ERROR | java.awt.image.ImageObserver.__Fields.ABORT, 0, 0, -1, -1); + } + return -1; + } + + public override int getHeight(java.awt.image.ImageObserver observer) + { + if (observer != null) + { + observer.imageUpdate(this, java.awt.image.ImageObserver.__Fields.ERROR | java.awt.image.ImageObserver.__Fields.ABORT, 0, 0, -1, -1); + } + return -1; + } + + public override ImageProducer getSource() + { + return source; + } + + public override java.awt.Graphics getGraphics() + { + // TODO throw java.lang.IllegalAccessError: getGraphics() only valid for images created with createImage(w, h) + return null; + } + + public override object getProperty(string name, java.awt.image.ImageObserver observer) + { + if (observer != null) + { + observer.imageUpdate(this, java.awt.image.ImageObserver.__Fields.ERROR | java.awt.image.ImageObserver.__Fields.ABORT, 0, 0, -1, -1); + } + return null; + } + + public override void flush() + { + } + } + + +} \ No newline at end of file diff --git a/awt/native.cs b/awt/native.cs new file mode 100644 index 0000000..62b92dd --- /dev/null +++ b/awt/native.cs @@ -0,0 +1,1038 @@ +/* + Copyright (C) 2007, 2008, 2010 Jeroen Frijters + Copyright (C) 2009 - 2012 Volker Berlin (i-net software) + Copyright (C) 2010 Karsten Heinrich (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Runtime.InteropServices; +using System.Text; +using System.Drawing; +using System.Drawing.Imaging; +using awt; + +namespace IKVM.NativeCode.sun.awt +{ + static class KeyboardFocusManagerPeerImpl + { + public static object getNativeFocusedWindow() { return null; } + public static object getNativeFocusOwner() { return null; } + public static void clearNativeGlobalFocusOwner(object activeWindow) { } + } + + static class SunToolkit + { + public static void closeSplashScreen() { } + } +} + +namespace IKVM.NativeCode.sun.awt.shell +{ + /// + /// This class should use only on Windows that we can access shell32.dll + /// + public static class Win32ShellFolder2 + { + private const uint IMAGE_BITMAP = 0; + private const uint IMAGE_ICON = 1; + + private const int HINST_COMMCTRL = -1; + private const int IDB_VIEW_SMALL_COLOR = 4; + + private const uint WM_USER = 0x0400; + private const uint TB_GETIMAGELIST = WM_USER + 49; + private const uint TB_LOADIMAGES = WM_USER + 50; + + private const uint ILD_TRANSPARENT = 0x00000001; + + private static readonly IntPtr hmodShell32; + private static readonly bool isXP; + + [System.Security.SecuritySafeCritical] + static Win32ShellFolder2() + { + hmodShell32 = LoadLibrary("shell32.dll"); + isXP = Environment.OSVersion.Version >= new Version(5, 1); + } + + [System.Security.SecurityCritical] + private sealed class SafeGdiObjectHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid + { + private SafeGdiObjectHandle() + : base(true) + { + } + + [System.Security.SecurityCritical] + protected override bool ReleaseHandle() + { + return DeleteObject(handle); + } + } + + [System.Security.SecurityCritical] + private sealed class SafeDeviceContextHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid + { + [DllImport("user32.dll")] + private static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc); + + [DllImport("user32.dll")] + private static extern SafeDeviceContextHandle GetDC(IntPtr hwnd); + + internal static SafeDeviceContextHandle Get() + { + return GetDC(IntPtr.Zero); + } + + private SafeDeviceContextHandle() + : base(true) + { + } + + [System.Security.SecurityCritical] + protected override bool ReleaseHandle() + { + return ReleaseDC(IntPtr.Zero, handle) == 1; + } + } + + [DllImport("gdi32.dll")] + private static extern int GetDIBits(SafeDeviceContextHandle hdc, IntPtr hbmp, uint uStartScan, uint cScanLines, int[] lpvBits, ref BITMAPINFO lpbmi, uint uUsage); + + [DllImport("gdi32.dll")] + private static extern int GetDIBits(SafeDeviceContextHandle hdc, SafeGdiObjectHandle hbmp, uint uStartScan, uint cScanLines, int[] lpvBits, ref BITMAPINFO lpbmi, uint uUsage); + + [DllImport("gdi32.dll")] + private static extern int GetObject(SafeGdiObjectHandle hgdiobj, int cbBuffer, ref BITMAPINFO lpvObject); + + [DllImport("shlwapi.dll")] + private static extern int StrRetToBuf(ref ShellApi.STRRET pstr, IntPtr pIDL, StringBuilder pszBuf, uint cchBuf); + + [StructLayout(LayoutKind.Sequential)] + private struct ICONINFO + { + internal bool fIcon; + internal int xHotspot; + internal int yHotspot; + internal IntPtr hbmMask; + internal IntPtr hbmColor; + } + + [DllImport("user32.dll")] + static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO piconinfo); + + [DllImport("user32.dll", SetLastError = true)] + static extern IntPtr CreateWindowEx( + uint dwExStyle, + string lpClassName, + string lpWindowName, + uint dwStyle, + int x, + int y, + int nWidth, + int nHeight, + IntPtr hWndParent, + IntPtr hMenu, + IntPtr hInstance, + IntPtr lpParam); + + [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + static extern bool DestroyWindow(IntPtr hwnd); + + [DllImport("user32.dll")] + static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam); + + [DllImport("comctl32.dll", SetLastError = true)] + public static extern IntPtr ImageList_GetIcon(IntPtr himl, int i, uint flags); + + [DllImport("comctl32")] + [return: MarshalAs(UnmanagedType.Bool)] + static extern bool ImageList_Destroy(IntPtr himl); + + [DllImport("user32")] + public static extern int DestroyIcon(IntPtr hIcon); + + [StructLayout(LayoutKind.Sequential)] + private struct BITMAPINFO + { + internal uint biSize; + internal int biWidth; + internal int biHeight; + internal ushort biPlanes; + internal ushort biBitCount; + internal uint biCompression; + internal uint biSizeImage; + internal int biXPelsPerMeter; + internal int biYPelsPerMeter; + internal uint biClrUsed; + internal uint biClrImportant; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] + internal uint[] cols; + } + + [DllImport("user32.dll")] + private static extern SafeGdiObjectHandle LoadImage(IntPtr hInstance, IntPtr uID, uint type, int width, int height, int load); + + [DllImport("user32.dll")] + private static extern SafeGdiObjectHandle LoadImage(IntPtr hInstance, string lpszName, uint type, int width, int height, int load); + + [DllImport("kernel32.dll")] + private static extern IntPtr LoadLibrary(string Library); + + [DllImport("gdi32.dll")] + private static extern bool DeleteObject(IntPtr hDc); + + /// + /// Get the program to execute or open the file. If it is a exe then it is self + /// + /// path to the file + /// + [System.Security.SecuritySafeCritical] + public static string getExecutableType(string path) + { + StringBuilder objResultBuffer = new StringBuilder(1024); + int result = ShellApi.FindExecutable(path, path, objResultBuffer); + if (result >= 32) + { + return objResultBuffer.ToString(); + } + return null; + } + + /// + /// Get the type of a file or folder. On a file it depends on its extension. + /// + /// the path of the file or folder + /// The type in readable form or null, if the path cannot be resolved + [System.Security.SecuritySafeCritical] + public static string getFolderType(string path) + { + ShellApi.SHFILEINFO shinfo = new ShellApi.SHFILEINFO(); + if (ShellApi.SHGetFileInfo(path, 0, out shinfo, (uint)Marshal.SizeOf(shinfo), ShellApi.SHGFI.SHGFI_TYPENAME) == IntPtr.Zero) + { + return null; + } + return shinfo.szTypeName; + } + + [System.Security.SecurityCritical] + public static Bitmap getIconBits(IntPtr hIcon, int iconSize) + { + ICONINFO iconInfo; + if (GetIconInfo(hIcon, out iconInfo)) + { + using (SafeDeviceContextHandle dc = SafeDeviceContextHandle.Get()) + { + BITMAPINFO bmi = new BITMAPINFO(); + bmi.biSize = 40; + bmi.biWidth = iconSize; + bmi.biHeight = -iconSize; + bmi.biPlanes = 1; + bmi.biBitCount = 32; + bmi.biCompression = 0; + int intArrSize = iconSize * iconSize; + int[] iconBits = new int[intArrSize]; + GetDIBits(dc, iconInfo.hbmColor, 0, (uint)iconSize, iconBits, ref bmi, 0); + bool hasAlpha = false; + if (isXP) + { + for (int i = 0; i < iconBits.Length; i++) + { + if ((iconBits[i] & 0xFF000000) != 0) + { + hasAlpha = true; + break; + } + } + } + if (!hasAlpha) + { + int[] maskBits = new int[intArrSize]; + GetDIBits(dc, iconInfo.hbmMask, 0, (uint)iconSize, maskBits, ref bmi, 0); + for (int i = 0; i < iconBits.Length; i++) + { + if (maskBits[i] == 0) + { + iconBits[i] = (int)((uint)iconBits[i] | 0xFF000000); + } + } + } + DeleteObject(iconInfo.hbmColor); + DeleteObject(iconInfo.hbmMask); + + DeleteObject(hIcon); + Bitmap bitmap = new Bitmap(iconSize, iconSize, PixelFormat.Format32bppArgb); + BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, iconSize, iconSize), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); + Marshal.Copy(iconBits, 0, bitmapData.Scan0, iconBits.Length); + bitmap.UnlockBits(bitmapData); + return bitmap; + } + } + return null; + } + + /// + /// Retrieves information about an object in the file system, such as a file, folder, directory, or drive root. + /// + /// The path of the file system object + /// The SHGFI flags with the attributes + [System.Security.SecuritySafeCritical] + public static int getAttribute(string path) + { + ShellApi.SHFILEINFO shinfo = new ShellApi.SHFILEINFO(); + if (ShellApi.SHGetFileInfo(path, 0, out shinfo, (uint)Marshal.SizeOf(shinfo), ShellApi.SHGFI.SHGFI_ATTRIBUTES) == IntPtr.Zero) + { + return 0; + } + return (int)shinfo.dwAttributes; + } + + /// Returns the link target as a pIDL relative to the desktop without resolving the link + /// The path of the .lnk file + /// the link target as a pIDL relative to the desktop + [System.Security.SecuritySafeCritical] + public static string getLinkLocation(string path ) + { + using (ShellLink link = new ShellLink()) + { + link.Load(path); + return link.GetPath(); + } + } + /// Returns the link target as a pIDL relative to the desktop + /// The path of the .lnk file + /// If true, attempts to find the target of a Shell link, + /// even if it has been moved or renamed. This may open a file chooser + /// the link target as a pIDL relative to the desktop + [System.Security.SecuritySafeCritical] + public static IntPtr getLinkLocation(string path, Boolean resolve) + { + using (ShellLink link = new ShellLink()) + { + link.Load(path); + if (resolve) + { + link.Resolve(); + } + return link.GetIDList(); + } + } + + // Code copied from Java_sun_awt_shell_Win32ShellFolder2_getStandardViewButton0 + [System.Security.SecuritySafeCritical] + public static Bitmap getStandardViewButton0(int iconIndex) + { + Bitmap result = null; + using (new ThemingActivationContext()) + { + // Create a toolbar + IntPtr hWndToolbar = CreateWindowEx(0, "ToolbarWindow32", null, 0, 0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); + if (hWndToolbar != IntPtr.Zero) + { + SendMessage(hWndToolbar, TB_LOADIMAGES, IDB_VIEW_SMALL_COLOR, HINST_COMMCTRL); + + IntPtr hImageList = SendMessage(hWndToolbar, TB_GETIMAGELIST, 0, 0); + if (hImageList != IntPtr.Zero) + { + IntPtr hIcon = ImageList_GetIcon(hImageList, iconIndex, ILD_TRANSPARENT); + if (hIcon != IntPtr.Zero) + { + Icon icon = Icon.FromHandle(hIcon); + result = icon.ToBitmap(); + icon.Dispose(); + DestroyIcon(hIcon); + } + ImageList_Destroy(hImageList); + } + DestroyWindow(hWndToolbar); + } + } + return result; + } + + /// + /// Retrieves an icon from the shell32.dell + /// + /// the index of the icon + /// The icon or null, if there is no icon at the given index + [System.Security.SecuritySafeCritical] + public static Bitmap getShell32IconResourceAsBitmap(int iconID, bool getLargeIcon) + { + if (hmodShell32 == IntPtr.Zero) + { + return null; + } + int size = getLargeIcon ? 32 : 16; + using (SafeGdiObjectHandle hicon = LoadImage(hmodShell32, (IntPtr)iconID, IMAGE_ICON, size, size, 0)) + { + if (hicon != null) + { + return getIconBits(hicon.DangerousGetHandle(), 16); + } + } + return null; + } + + /// + /// Returns the pIDL of the desktop itself + /// + [System.Security.SecurityCritical] + public static IntPtr initDesktopPIDL() + { + IntPtr pidl = new IntPtr(); + + // get the root shell folder + ShellApi.SHGetSpecialFolderLocation(IntPtr.Zero, ShellApi.CSIDL.CSIDL_DESKTOP, ref pidl); + + return pidl; + } + + /// + /// Returns an IShellFolder for the desktop + /// + [System.Security.SecurityCritical] + public static Object initDesktopFolder() + { + ShellApi.IShellFolder rootShell = null; + + // get the root shell folder + ShellApi.SHGetDesktopFolder(ref rootShell); + + return rootShell; + } + + /// + /// Returns the desktop relative pIDL of a special folder + /// + /// The IShellFolder instance of the Desktop + /// The CSIDL of the special folder + /// the desktop relative pIDL of a special folder + [System.Security.SecurityCritical] + public static IntPtr initSpecialPIDL(Object desktopIShellFolder, int csidl) + { + IntPtr result = new IntPtr(); + ShellApi.SHGetSpecialFolderLocation(IntPtr.Zero, (ShellApi.CSIDL)csidl, ref result); + return result; + } + + /// + /// Creates an IShellFolder for a special folder + /// + /// The IShellFolder instance of the Desktop + /// The desktop relative pIDL of the special folder + /// The IShellFolder for a special folder + [System.Security.SecurityCritical] + public static Object initSpecialFolder(Object desktopIShellFolder, IntPtr pidl) + { + try + { + // get desktop instance + ShellApi.IShellFolder desktop = (ShellApi.IShellFolder)desktopIShellFolder; + // call BindToObject of the desktop + ShellApi.IShellFolder specialFolder = null; + desktop.BindToObject(pidl, IntPtr.Zero, ref ShellApi.GUID_ISHELLFOLDER, out specialFolder); + return specialFolder; + } + catch (System.ArgumentException ) + { + return 0; + } + } + + /// + /// Goes down one entry in the given pIDL + /// + /// the pIDL to operate on + /// the next entry in the pIDL + [System.Security.SecurityCritical] + public static IntPtr getNextPIDLEntry(IntPtr pIDL) + { + if (pIDL == IntPtr.Zero) + { + return IntPtr.Zero; + } + + int length = Marshal.ReadInt16(pIDL); + if (length == 0) // defined as terminator of a ITEMIDLIST + { + return IntPtr.Zero; + } + IntPtr newpIDL = new IntPtr(pIDL.ToInt64() + length); + if (Marshal.ReadInt16(newpIDL) == 0) + { + return IntPtr.Zero; + } + else + { + return newpIDL; + } + } + /// + /// Copies the first entry in the given pIDL into a new relative pIDL (with terminator) + /// + /// The pIDL to copy from + /// the relative pIDL of the first entry + [System.Security.SecurityCritical] + public static IntPtr copyFirstPIDLEntry(IntPtr pIDL) + { + if (pIDL == IntPtr.Zero) + { + return IntPtr.Zero; + } + int length = Marshal.ReadInt16(pIDL) + 2; // +2 for the terminator + byte[] buffer = new byte[length]; + IntPtr newpIDLptr = Marshal.AllocCoTaskMem(length); // create pointer to new pIDL + Marshal.Copy(pIDL, buffer, 0, length - 2); // copy content + Marshal.Copy(buffer, 0, newpIDLptr, length); // copy content + return newpIDLptr; + } + + /// + /// Concatinates two pIDLs + /// + /// a pIDL, if IntPtr.Zero, IntPtr.Zero will be returned + /// a pIDL, if IntPtr.Zero, IntPtr.Zero will be returned + /// the concatination of ppIDL and pIDL + [System.Security.SecurityCritical] + public static IntPtr combinePIDLs(IntPtr ppIDL, IntPtr pIDL) + { + if (ppIDL == IntPtr.Zero) + { + return IntPtr.Zero; + } + if (pIDL == IntPtr.Zero) + { + return IntPtr.Zero; + } + int lengthP = getPIDLlength(ppIDL); + int lengthR = getPIDLlength(pIDL); + byte[] newPIDL = new byte[lengthP + lengthR + 2]; + Marshal.Copy(ppIDL, newPIDL, 0, lengthP); + Marshal.Copy(pIDL, newPIDL, lengthP, lengthR); + IntPtr newpIDLptr = Marshal.AllocCoTaskMem(lengthP + lengthR + 2); // create pointer to new pIDL + Marshal.Copy(newPIDL,0,newpIDLptr,newPIDL.Length); // set pointer to new pIDL and delete local structure + return newpIDLptr; + } + + /// + /// Calculates the size of a ITEMIDLIST without the two bytes of the terminator + /// + /// a pointer to the IDL to get the length of + /// the length in bytes + [System.Security.SecurityCritical] + public static int getPIDLlength(IntPtr pIDL) + { + if( pIDL == IntPtr.Zero ) + { + return 0; + } + int length = Marshal.ReadInt16(pIDL); + int offset = length; + while (length > 0) + { + length = Marshal.ReadInt16(new IntPtr( pIDL.ToInt64() + offset)); + offset += length; + } + return offset; + } + /// + /// Releases the allocted memory of a pIDL + /// + /// The pIDL to be released + [System.Security.SecurityCritical] + public static void releasePIDL(IntPtr pIDL) + { + if (pIDL == IntPtr.Zero) + { + return; + } + Marshal.FreeCoTaskMem(pIDL); + } + + /// + /// Releases an IShellFolder COM object + /// + /// The IShellFolder to be released, must not be null + [System.Security.SecurityCritical] + public static void releaseIShellFolder(Object pIShellFolder) + { + if (pIShellFolder == null) + { + return; + } + Marshal.ReleaseComObject(pIShellFolder); + } + + [System.Security.SecurityCritical] + public static int compareIDs(Object pParentIShellFolder, IntPtr pidl1, IntPtr pidl2) + { + if (pParentIShellFolder == null) + { + return 0; + } + ShellApi.IShellFolder folder = (ShellApi.IShellFolder)pParentIShellFolder; + return folder.CompareIDs(0, pidl1, pidl2); + } + + [System.Security.SecurityCritical] + public static int getAttributes0(Object pParentIShellFolder, IntPtr pIDL, int attrsMask) + { + if (pParentIShellFolder == null || pIDL == IntPtr.Zero ) + { + return 0; + } + ShellApi.IShellFolder folder = (ShellApi.IShellFolder)pParentIShellFolder; + ShellApi.SFGAOF[] atts = new ShellApi.SFGAOF[]{ (ShellApi.SFGAOF)attrsMask }; + IntPtr[] pIDLs = new IntPtr[] { pIDL }; + folder.GetAttributesOf(1, pIDLs, atts); + return (int)atts[0]; + } + + [System.Security.SecuritySafeCritical] + public static String getFileSystemPath0(int csidl) + { + IntPtr pIDL = new IntPtr(); + int hRes = ShellApi.SHGetSpecialFolderLocation(IntPtr.Zero, (ShellApi.CSIDL)csidl, ref pIDL); + if (hRes != 0) + { + //throw Marshal.ThrowExceptionForHR(hRes); + // TODO exception for hRes + return null; + } + StringBuilder builder = new StringBuilder( 1024 ); + if (ShellApi.SHGetPathFromIDList(pIDL, builder)) + { + return builder.ToString(); + } + else + { + return null; + } + } + + [System.Security.SecurityCritical] + public static Object getEnumObjects(Object pIShellFolder, Boolean isDesktop, Boolean includeHiddenFiles) + { + if (pIShellFolder == null) + { + return null; + } + ShellApi.IShellFolder folder = (ShellApi.IShellFolder)pIShellFolder; + ShellApi.SHCONTF flags = ShellApi.SHCONTF.SHCONTF_FOLDERS | ShellApi.SHCONTF.SHCONTF_NONFOLDERS; + if( includeHiddenFiles ) + { + flags |= ShellApi.SHCONTF.SHCONTF_INCLUDEHIDDEN; + } + + ShellApi.IEnumIDList list = null; + folder.EnumObjects(IntPtr.Zero, flags, out list); + return list; + } + + /// + /// Returns the next pIDL in an IEnumIDList + /// + /// The IEnumIDList to get the next element of + /// a pIDL or IntPtr.Zero in case the end of the enum is reached + [System.Security.SecurityCritical] + public static IntPtr getNextChild(Object pEnumObjects) + { + if (pEnumObjects == null) + { + return IntPtr.Zero; + } + ShellApi.IEnumIDList list = (ShellApi.IEnumIDList)pEnumObjects; + IntPtr pIDL = new IntPtr(); + int pceltFetched; // can be ignored, if celt = 1 + uint hRes = list.Next(1, out pIDL, out pceltFetched); + if ( hRes != 0 || pceltFetched == 0 ) + { + return IntPtr.Zero; + } + else + { + return pIDL; + } + } + + /// + /// Releases an IEnumIDList + /// + /// The IEnumIDList to be released + [System.Security.SecurityCritical] + public static void releaseEnumObjects(Object pEnumObjects) + { + if (pEnumObjects != null) + { + Marshal.ReleaseComObject(pEnumObjects); + } + } + + /// + /// Binds an IShellFolder to the child of a given shell folder + /// + /// the parent IShellFolder + /// the relative pIDL to the child + /// The IShellFolder of the child or null, if there is no such child + [System.Security.SecurityCritical] + public static Object bindToObject(Object parentIShellFolder, IntPtr pIDL) + { + if (parentIShellFolder == null || pIDL == IntPtr.Zero ) + { + return null; + } + ShellApi.IShellFolder folder = (ShellApi.IShellFolder)parentIShellFolder; + ShellApi.IShellFolder newFolder = null; + folder.BindToObject(pIDL, IntPtr.Zero, ref ShellApi.GUID_ISHELLFOLDER, out newFolder); + return newFolder; + } + + /// + /// Parses the displayname of a child of a given folder + /// + /// The IShellFolder to get the chilf of + /// The display name of the child + /// the relative pIDL of the child or IntPrt.Zero in case there is no such child + [System.Security.SecurityCritical] + public static IntPtr parseDisplayName0(Object pIShellFolder, String name) + { + if (pIShellFolder == null) + { + return IntPtr.Zero; + } + ShellApi.IShellFolder folder = (ShellApi.IShellFolder)pIShellFolder; + IntPtr pIDL = new IntPtr(); + uint pchEaten; + uint pdwAttribute = 0; + folder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, name, out pchEaten, out pIDL, ref pdwAttribute); + return pIDL; + } + + [System.Security.SecurityCritical] + public static String getDisplayNameOf(Object parentIShellFolder, IntPtr relativePIDL, int attrs) + { + if (parentIShellFolder == null || relativePIDL == IntPtr.Zero) + { + return null; + } + ShellApi.IShellFolder folder = (ShellApi.IShellFolder)parentIShellFolder; + ShellApi.STRRET result; + uint hRes = folder.GetDisplayNameOf(relativePIDL, (ShellApi.SHGDN)attrs, out result); + if ( hRes == 0 ) + { + StringBuilder name = new StringBuilder( 1024 ); + StrRetToBuf(ref result, relativePIDL, name, 1024); + string stringName = name.ToString(); + return stringName; + } + return null; + } + + [System.Security.SecurityCritical] + public static String getFolderType(IntPtr pIDL) + { + ShellApi.SHFILEINFO fileInfo = new ShellApi.SHFILEINFO(); + ShellApi.SHGetFileInfo(pIDL, 0, out fileInfo, (uint)Marshal.SizeOf(fileInfo), ShellApi.SHGFI.SHGFI_PIDL | ShellApi.SHGFI.SHGFI_TYPENAME); + return fileInfo.szTypeName; + } + + public static Object getIShellIcon(Object pIShellFolder) + { + if (pIShellFolder is ShellApi.IShellIcon) + { + return pIShellFolder; + } + return null; + } + + [System.Security.SecurityCritical] + public static int getIconIndex(Object parentIShellFolder, IntPtr relativePIDL) + { + if (parentIShellFolder is ShellApi.IShellIcon) + { + ShellApi.IShellIcon shellIcon = (ShellApi.IShellIcon)parentIShellFolder; + int index = 0; + if( shellIcon.GetIconOf(relativePIDL, (uint)ShellApi.GIL.GIL_FORSHELL, out index) == 0 ) + { + return index; + } + } + return 0; + } + + [System.Security.SecurityCritical] + public static IntPtr getIcon(String absolutePath, Boolean getLargeIcon) + { + ShellApi.SHFILEINFO shinfo = new ShellApi.SHFILEINFO(); + if (ShellApi.SHGetFileInfo(absolutePath, 0, out shinfo, (uint)Marshal.SizeOf(shinfo), ShellApi.SHGFI.SHGFI_ICON | (getLargeIcon ? ShellApi.SHGFI.SHGFI_LARGEICON : ShellApi.SHGFI.SHGFI_SMALLICON)) == IntPtr.Zero) + { + return IntPtr.Zero; + } + return shinfo.hIcon; + } + + [System.Security.SecurityCritical] + public static IntPtr extractIcon(Object parentIShellFolder, IntPtr relativePIDL, Boolean getLargeIcon) + { + if (parentIShellFolder == null || relativePIDL == IntPtr.Zero) + { + return IntPtr.Zero; + } + ShellApi.IShellFolder folder = (ShellApi.IShellFolder)parentIShellFolder; + Guid guid = new Guid("000214fa-0000-0000-c000-000000000046"); + object ppv; + if (folder.GetUIObjectOf(IntPtr.Zero, 1, new IntPtr[] { relativePIDL }, ref guid, IntPtr.Zero, out ppv) == 0) + { + ShellApi.IExtractIcon extractor = (ShellApi.IExtractIcon)ppv; + int size = 1024; + StringBuilder path = new StringBuilder( size ); + int piIndex; + uint pwFlags; + if (extractor.GetIconLocation((uint)ShellApi.GIL.GIL_FORSHELL, path, size, out piIndex, out pwFlags) == 0) + { + IntPtr hIconL = new IntPtr(); + IntPtr hIconS = new IntPtr(); + if (extractor.Extract(path.ToString(), (uint)piIndex, out hIconL, out hIconS, (16 << 16) + 32) == 0) + { + if (getLargeIcon) + { + ShellApi.DestroyIcon(hIconS); + return hIconL; + } + else + { + ShellApi.DestroyIcon(hIconL); + return hIconS; + } + } + } + } + return IntPtr.Zero; + } + + [System.Security.SecurityCritical] + public static void disposeIcon(IntPtr hIcon) + { + ShellApi.DestroyIcon(hIcon); + } + + public static Object doGetColumnInfo(Object iShellFolder2) + { + // TODO Dummy + return null; + } + + public static Object doGetColumnValue(Object parentIShellFolder2, IntPtr childPIDL, int columnIdx) + { + // TODO Dummy + return null; + } + + public static int compareIDsByColumn(Object pParentIShellFolder, IntPtr pidl1, IntPtr pidl2, int columnIdx) + { + // TODO Dummy + return 0; + } + } + + [System.Security.SecurityCritical] + class ShellLink : IDisposable + { + [ComImport] + [Guid("0000010B-0000-0000-C000-000000000046")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IPersistFile + { + [PreserveSig] + void GetClassID(out Guid pClassID); + [PreserveSig] + void IsDirty(); + [PreserveSig] + void Load([MarshalAs(UnmanagedType.LPWStr)] string pszFileName, uint dwMode); + [PreserveSig] + void Save([MarshalAs(UnmanagedType.LPWStr)] string pszFileName, [MarshalAs(UnmanagedType.Bool)] bool fRemember); + [PreserveSig] + void SaveCompleted([MarshalAs(UnmanagedType.LPWStr)] string pszFileName); + [PreserveSig] + void GetCurFile([MarshalAs(UnmanagedType.LPWStr)] out string ppszFileName); + } + + [ComImport] + [Guid("000214F9-0000-0000-C000-000000000046")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + private interface IShellLinkW + { + void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, IntPtr pfd, uint fFlags); + void GetIDList(out IntPtr ppidl); + void SetIDList(IntPtr pidl); + void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxName); + void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); + void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath); + void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); + void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath); + void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); + void GetHotkey(out short pwHotkey); + void SetHotkey(short pwHotkey); + void GetShowCmd(out uint piShowCmd); + void SetShowCmd(uint piShowCmd); + void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon); + void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); + void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, uint dwReserved); + /// Attempts to find the target of a Shell link, even if it has been moved or renamed. + void Resolve(IntPtr hWnd, uint fFlags); + void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); + } + + [Guid("00021401-0000-0000-C000-000000000046")] + [ClassInterfaceAttribute(ClassInterfaceType.None)] + [ComImport] + private class CShellLink { } + + [Flags] + public enum EShowWindowFlags : uint + { + SW_HIDE = 0, + SW_SHOWNORMAL = 1, + SW_NORMAL = 1, + SW_SHOWMINIMIZED = 2, + SW_SHOWMAXIMIZED = 3, + SW_MAXIMIZE = 3, + SW_SHOWNOACTIVATE = 4, + SW_SHOW = 5, + SW_MINIMIZE = 6, + SW_SHOWMINNOACTIVE = 7, + SW_SHOWNA = 8, + SW_RESTORE = 9, + SW_SHOWDEFAULT = 10, + SW_MAX = 10 + } + + private IShellLinkW linkW = (IShellLinkW)new CShellLink(); + + [System.Security.SecuritySafeCritical] + public void Dispose() + { + if (linkW != null) + { + Marshal.ReleaseComObject(linkW); + linkW = null; + } + } + + public void SetPath(string path) + { + linkW.SetPath(path); + } + + public void SetDescription(string description) + { + linkW.SetDescription(description); + } + + public void SetWorkingDirectory(string dir) + { + linkW.SetWorkingDirectory(dir); + } + + public void SetArguments(string args) + { + linkW.SetArguments(args); + } + + public void SetShowCmd(EShowWindowFlags cmd) + { + linkW.SetShowCmd((uint)cmd); + } + + public void Save(string linkFile) + { + ((IPersistFile)linkW).Save(linkFile, true); + } + + public void Load(string linkFile) + { + ((IPersistFile)linkW).Load(linkFile, 0); + } + + public string GetArguments() + { + StringBuilder sb = new StringBuilder(512); + linkW.GetArguments(sb, sb.Capacity); + return sb.ToString(); + } + + public void Resolve() + { + linkW.Resolve(IntPtr.Zero, 0); + } + + public IntPtr GetIDList(){ + IntPtr ppidl; + linkW.GetIDList( out ppidl ); + return ppidl; + } + + public string GetPath() + { + StringBuilder sb = new StringBuilder(512); + linkW.GetPath(sb, sb.Capacity, IntPtr.Zero, 0); + return sb.ToString(); + } + } + + +} + +namespace IKVM.NativeCode.sun.java2d +{ + static class DefaultDisposerRecord + { + public static void invokeNativeDispose(long disposerMethodPointer, long dataPointer) + { + throw new NotImplementedException(); + } + } + + static class Disposer + { + public static void initIDs() + { + } + } +} + +namespace IKVM.NativeCode.sun.java2d.pipe +{ + static class Region + { + public static void initIDs() { } + } + + static class RenderBuffer + { + public static void copyFromArray(object srcArray, long srcPos, long dstAddr, long length) + { + throw new NotImplementedException(); + } + } +} diff --git a/awt/printing.cs b/awt/printing.cs new file mode 100644 index 0000000..1cce482 --- /dev/null +++ b/awt/printing.cs @@ -0,0 +1,335 @@ +/* + Copyright (C) 2009 Volker Berlin (i-net software) + Copyright (C) 2010 Karsten Heinrich (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +using System; +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; +using System.Drawing.Printing; + +namespace ikvm.awt.printing +{ + /// + /// Base Implementation of the PrintPeer + /// + abstract class BasePrintPeer : sun.print.PrintPeer + { + public virtual Object getPrinterStatus(String PrinterName, java.lang.Class category) + { + return null; + } + + public String getDefaultPrinterName() + { + return new PrinterSettings().PrinterName; + } + + public String[] getAllPrinterNames() + { + PrinterSettings.StringCollection printers = PrinterSettings.InstalledPrinters; + String[] result = new String[printers.Count]; + printers.CopyTo(result, 0); + return result; + } + + public java.awt.Graphics2D createGraphics(System.Drawing.Graphics g) + { + return new PrintGraphics(g); + } + } + + /// + /// Implementation of the PrintPeer for Linux + /// + class LinuxPrintPeer : BasePrintPeer + { + } + + /// + /// Implementation of the PrintPeer for Windows + /// + class Win32PrintPeer : BasePrintPeer + { + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + private struct PRINTER_INFO_2 + { + [MarshalAs(UnmanagedType.LPTStr)] + public string pServerName; + [MarshalAs(UnmanagedType.LPTStr)] + public string pPrinterName; + [MarshalAs(UnmanagedType.LPTStr)] + public string pShareName; + [MarshalAs(UnmanagedType.LPTStr)] + public string pPortName; + [MarshalAs(UnmanagedType.LPTStr)] + public string pDriverName; + [MarshalAs(UnmanagedType.LPTStr)] + public string pComment; + [MarshalAs(UnmanagedType.LPTStr)] + public string pLocation; + public IntPtr pDevMode; + [MarshalAs(UnmanagedType.LPTStr)] + public string pSepFile; + [MarshalAs(UnmanagedType.LPTStr)] + public string pPrintProcessor; + [MarshalAs(UnmanagedType.LPTStr)] + public string pDatatype; + [MarshalAs(UnmanagedType.LPTStr)] + public string pParameters; + public IntPtr pSecurityDescriptor; + public uint Attributes; + public uint Priority; + public uint DefaultPriority; + public uint StartTime; + public uint UntilTime; + public int Status; + public int cJobs; + public uint AveragePPM; + } + + [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)] + private static extern bool GetPrinter(SafePrinterHandle hPrinter, int dwLevel, IntPtr pPrinter, int cbBuf, out int pcbNeeded); + + [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)] + private static extern bool OpenPrinter(string pPrinterName, out SafePrinterHandle hPrinter, IntPtr pDefault); + + private const int ERROR_INSUFFICIENT_BUFFER = 122; + + private const int PRINTER_STATUS_PAUSED = 0x1; + private const int PRINTER_STATUS_ERROR = 0x2; // MSDN says that this value is not used + private const int PRINTER_STATUS_PENDING_DELETION = 0x4; + private const int PRINTER_STATUS_PAPER_JAM = 0x8; + private const int PRINTER_STATUS_PAPER_OUT = 0x10; + private const int PRINTER_STATUS_MANUAL_FEED = 0x20; + private const int PRINTER_STATUS_PAPER_PROBLEM = 0x40; + private const int PRINTER_STATUS_OFFLINE = 0x80; + private const int PRINTER_STATUS_IO_ACTIVE = 0x100; + private const int PRINTER_STATUS_BUSY = 0x200; + private const int PRINTER_STATUS_PRINTING = 0x400; + private const int PRINTER_STATUS_OUTPUT_BIN_FULL = 0x800; + private const int PRINTER_STATUS_NOT_AVAILABLE = 0x1000; + private const int PRINTER_STATUS_WAITING = 0x2000; + private const int PRINTER_STATUS_PROCESSING = 0x4000; + private const int PRINTER_STATUS_INITIALIZING = 0x8000; + private const int PRINTER_STATUS_WARMING_UP = 0x10000; + private const int PRINTER_STATUS_TONER_LOW = 0x20000; + private const int PRINTER_STATUS_NO_TONER = 0x40000; + private const int PRINTER_STATUS_PAGE_PUNT = 0x80000; + private const int PRINTER_STATUS_USER_INTERVENTION = 0x100000; + private const int PRINTER_STATUS_OUT_OF_MEMORY = 0x200000; + private const int PRINTER_STATUS_DOOR_OPEN = 0x400000; + private const int PRINTER_STATUS_SERVER_UNKNOWN = 0x800000; + private const int PRINTER_STATUS_POWER_SAVE = 0x1000000; + + /// + /// Get a printer status + /// + /// a valid printer name + /// a category that should request + /// a printer attribute or null + public override Object getPrinterStatus(String printerName, java.lang.Class category) + { + int cJobs; + int status; + if (GetPrinterInfo2(printerName, out cJobs, out status)) + { + if (category == (java.lang.Class)typeof(javax.print.attribute.standard.PrinterState)) + { + if ((status & + (PRINTER_STATUS_ERROR | PRINTER_STATUS_NO_TONER | PRINTER_STATUS_OUT_OF_MEMORY | + PRINTER_STATUS_OFFLINE | PRINTER_STATUS_USER_INTERVENTION | + PRINTER_STATUS_DOOR_OPEN | PRINTER_STATUS_NOT_AVAILABLE )) > 0) + { + return javax.print.attribute.standard.PrinterState.STOPPED; + } + if( (status & (PRINTER_STATUS_BUSY | PRINTER_STATUS_PRINTING ))> 0 ) + { + return javax.print.attribute.standard.PrinterState.PROCESSING; + } + return null; + // null seems to be the default instead of unknown - UNKOWN ist not used in the reference RT + // javax.print.attribute.standard.PrinterState.UNKNOWN; + } + if (category == (java.lang.Class)typeof(javax.print.attribute.standard.PrinterStateReasons)) + { + return extractResions(status); + } + if (category == (java.lang.Class)typeof(javax.print.attribute.standard.QueuedJobCount)) + { + return new javax.print.attribute.standard.QueuedJobCount(cJobs); + } + if (category == (java.lang.Class)typeof(javax.print.attribute.standard.PrinterIsAcceptingJobs)) + { + if ((status & + (PRINTER_STATUS_ERROR | + PRINTER_STATUS_NO_TONER | + PRINTER_STATUS_OUT_OF_MEMORY | + PRINTER_STATUS_OFFLINE | + PRINTER_STATUS_USER_INTERVENTION | + PRINTER_STATUS_DOOR_OPEN)) > 0) + { + return javax.print.attribute.standard.PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS; + } + else + { + return javax.print.attribute.standard.PrinterIsAcceptingJobs.ACCEPTING_JOBS; + } + } + } + return null; + } + + private javax.print.attribute.standard.PrinterStateReasons extractResions(int status) + { + javax.print.attribute.standard.PrinterStateReasons reasons = new javax.print.attribute.standard.PrinterStateReasons(); + if ((status & PRINTER_STATUS_PAUSED) > 0) + { + reasons.put(javax.print.attribute.standard.PrinterStateReason.PAUSED, javax.print.attribute.standard.Severity.REPORT); + } + if ((status & PRINTER_STATUS_ERROR) > 0) + { + reasons.put(javax.print.attribute.standard.PrinterStateReason.OTHER, javax.print.attribute.standard.Severity.ERROR); + } + if ((status & PRINTER_STATUS_PENDING_DELETION) > 0) { } + if ((status & PRINTER_STATUS_PAPER_JAM) > 0) + { + reasons.put(javax.print.attribute.standard.PrinterStateReason.MEDIA_JAM, javax.print.attribute.standard.Severity.WARNING); + } + if ((status & PRINTER_STATUS_PAPER_OUT) > 0) + { + reasons.put(javax.print.attribute.standard.PrinterStateReason.MEDIA_EMPTY, javax.print.attribute.standard.Severity.WARNING); + } + if ((status & PRINTER_STATUS_MANUAL_FEED) > 0) { } + if ((status & PRINTER_STATUS_PAPER_PROBLEM) > 0) {} + if ((status & PRINTER_STATUS_OFFLINE) > 0) { + reasons.put(javax.print.attribute.standard.PrinterStateReason.TIMED_OUT, javax.print.attribute.standard.Severity.ERROR); + } + if ((status & PRINTER_STATUS_IO_ACTIVE) > 0) { } + if ((status & PRINTER_STATUS_BUSY) > 0) { } + if ((status & PRINTER_STATUS_PRINTING) > 0) { } + if ((status & PRINTER_STATUS_OUTPUT_BIN_FULL) > 0) { + reasons.put(javax.print.attribute.standard.PrinterStateReason.OUTPUT_AREA_FULL, javax.print.attribute.standard.Severity.WARNING); + } + if ((status & PRINTER_STATUS_NOT_AVAILABLE) > 0) { } + if ((status & PRINTER_STATUS_WAITING) > 0) { } + if ((status & PRINTER_STATUS_PROCESSING) > 0) { } + if ((status & PRINTER_STATUS_INITIALIZING) > 0) { } + if ((status & PRINTER_STATUS_WARMING_UP) > 0) { } + if ((status & PRINTER_STATUS_TONER_LOW) > 0) { + reasons.put(javax.print.attribute.standard.PrinterStateReason.TONER_LOW, javax.print.attribute.standard.Severity.WARNING); + } + if ((status & PRINTER_STATUS_NO_TONER) > 0) { + reasons.put(javax.print.attribute.standard.PrinterStateReason.TONER_EMPTY, javax.print.attribute.standard.Severity.ERROR); + } + if ((status & PRINTER_STATUS_PAGE_PUNT) > 0) { } + if ((status & PRINTER_STATUS_USER_INTERVENTION) > 0) { + reasons.put(javax.print.attribute.standard.PrinterStateReason.OTHER, javax.print.attribute.standard.Severity.ERROR); + } + if ((status & PRINTER_STATUS_OUT_OF_MEMORY) > 0) { + reasons.put(javax.print.attribute.standard.PrinterStateReason.OTHER, javax.print.attribute.standard.Severity.ERROR); + } + if ((status & PRINTER_STATUS_DOOR_OPEN) > 0) { + reasons.put(javax.print.attribute.standard.PrinterStateReason.DOOR_OPEN, javax.print.attribute.standard.Severity.ERROR); + } + if ((status & PRINTER_STATUS_SERVER_UNKNOWN) > 0) { } + if ((status & PRINTER_STATUS_POWER_SAVE) > 0) { + reasons.put(javax.print.attribute.standard.PrinterStateReason.PAUSED, javax.print.attribute.standard.Severity.REPORT); + } + return reasons.isEmpty() ? null : reasons; + } + + /// + /// Get infos from the PRINTER_INFO_2 struc + /// + /// The name of a valid printer + /// returns the current count of print jobs + /// returns the current status of the printer + /// true if the return is valid + [System.Security.SecuritySafeCritical] + private static bool GetPrinterInfo2(string printerName, out int cJobs, out int status) + { + SafePrinterHandle printer = null; + try + { + int needed = 0; + if (OpenPrinter(printerName, out printer, IntPtr.Zero) + && !GetPrinter(printer, 2, IntPtr.Zero, 0, out needed)) + { + int lastWin32Error = Marshal.GetLastWin32Error(); + if (lastWin32Error == ERROR_INSUFFICIENT_BUFFER) + { + IntPtr pPrinter = Marshal.AllocHGlobal((int)needed); + try + { + if (GetPrinter(printer, 2, pPrinter, needed, out needed)) + { + PRINTER_INFO_2 printerInfo2 = (PRINTER_INFO_2)Marshal.PtrToStructure(pPrinter, typeof(PRINTER_INFO_2)); + cJobs = printerInfo2.cJobs; + status = printerInfo2.Status; + return true; + } + } + finally + { + Marshal.FreeHGlobal(pPrinter); + } + } + } + } + finally + { + if (printer != null) + { + printer.Close(); + } + } + cJobs = 0; + status = 0; + return false; + } + + } + + [System.Security.SecurityCritical] + sealed class SafePrinterHandle : SafeHandleZeroOrMinusOneIsInvalid + { + [DllImport("winspool.drv")] + private static extern bool ClosePrinter(IntPtr hPrinter); + + private SafePrinterHandle() + : base(true) + { + } + + [System.Security.SecurityCritical] + protected override bool ReleaseHandle() + { + return ClosePrinter(handle); + } + } + + class Win32Print + { + } +} diff --git a/awt/robot.cs b/awt/robot.cs new file mode 100644 index 0000000..5df6a94 --- /dev/null +++ b/awt/robot.cs @@ -0,0 +1,404 @@ +/* + Copyright (C) 2007 Volker Berlin + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +using System; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Windows.Forms; +using java.awt.peer; +using java.awt.@event; + +namespace ikvm.awt +{ + + internal class WindowsRobot : RobotPeer + { + internal WindowsRobot(java.awt.GraphicsDevice device) + { + } + + public void dispose() + { + } + + public int getRGBPixel(int x, int y) + { + Bitmap bitmap = new Bitmap(1, 1); + Graphics g = Graphics.FromImage(bitmap); + g.CopyFromScreen( x, y, 0, 0, new Size(1,1)); + g.Dispose(); + Color color = bitmap.GetPixel(0,0); + bitmap.Dispose(); + return color.ToArgb(); + } + + public int[] getRGBPixels(java.awt.Rectangle r) + { + int width = r.width; + int height = r.height; + Bitmap bitmap = new Bitmap(width, height); + Graphics g = Graphics.FromImage(bitmap); + g.CopyFromScreen(r.x, r.y, 0, 0, new Size(width, height)); + g.Dispose(); + int[] pixels = new int[width * height]; + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) + { + pixels[i+j*width] = bitmap.GetPixel(i, j).ToArgb(); + } + } + bitmap.Dispose(); + return pixels; + } + + private byte MapKeyCode(int keyCode) + { + //TODO there need a keymap for some special chars + //http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/VirtualKeyCodes.asp + switch (keyCode) + { + case KeyEvent.VK_DELETE: + return VK_DELETE; + default: + return (byte)keyCode; + } + } + + public void keyPress(int keycode) + { + keybd_event(MapKeyCode(keycode), 0, KEYEVENTF_KEYDOWN, IntPtr.Zero); + } + + public void keyRelease(int keycode) + { + keybd_event(MapKeyCode(keycode), 0, KEYEVENTF_KEYUP, IntPtr.Zero); + } + + public void mouseMove(int x, int y) + { + Cursor.Position = new Point(x,y); + } + + public void mousePress(int button) + { + int dwFlags = 0; + switch (button) + { + case InputEvent.BUTTON1_MASK: + dwFlags |= MOUSEEVENTF_LEFTDOWN; + break; + case InputEvent.BUTTON2_MASK: + dwFlags |= MOUSEEVENTF_MIDDLEDOWN; + break; + case InputEvent.BUTTON3_MASK: + dwFlags |= MOUSEEVENTF_RIGHTDOWN; + break; + } + mouse_event(dwFlags, 0, 0, 0, IntPtr.Zero); + } + + public void mouseRelease(int button) + { + int dwFlags = 0; + switch (button) + { + case InputEvent.BUTTON1_MASK: + dwFlags |= MOUSEEVENTF_LEFTUP; + break; + case InputEvent.BUTTON2_MASK: + dwFlags |= MOUSEEVENTF_MIDDLEUP; + break; + case InputEvent.BUTTON3_MASK: + dwFlags |= MOUSEEVENTF_RIGHTUP; + break; + } + mouse_event(dwFlags, 0, 0, 0, IntPtr.Zero); + } + + public void mouseWheel(int wheel) + { + mouse_event(0, 0, 0, wheel, IntPtr.Zero); + } + + [DllImport("user32.dll")] + private static extern void keybd_event(byte vk, byte scan, int flags, IntPtr extrainfo); + + private const int KEYEVENTF_KEYDOWN = 0x0000; + private const int KEYEVENTF_KEYUP = 0x0002; + + [DllImport("user32.dll")] + private static extern void mouse_event( + int dwFlags, // motion and click options + int dx, // horizontal position or change + int dy, // vertical position or change + int dwData, // wheel movement + IntPtr dwExtraInfo // application-defined information + ); + + private const int MOUSEEVENTF_LEFTDOWN = 0x0002; + private const int MOUSEEVENTF_LEFTUP = 0x0004; + private const int MOUSEEVENTF_RIGHTDOWN = 0x0008; + private const int MOUSEEVENTF_RIGHTUP = 0x0010; + private const int MOUSEEVENTF_MIDDLEDOWN = 0x0020; + private const int MOUSEEVENTF_MIDDLEUP = 0x0040; + + + + private const int VK_BACK = 0x08; + private const int VK_TAB = 0x09; + +/* + * 0x0A - 0x0B : reserved + */ + + private const int VK_CLEAR = 0x0C; + private const int VK_RETURN = 0x0D; + + private const int VK_SHIFT = 0x10; + private const int VK_CONTROL = 0x11; + private const int VK_MENU = 0x12; + private const int VK_PAUSE = 0x13; + private const int VK_CAPITAL = 0x14; + + private const int VK_KANA = 0x15; + private const int VK_HANGEUL = 0x15; /* old name - should be here for compatibility */ + private const int VK_HANGUL = 0x15; + private const int VK_JUNJA = 0x17; + private const int VK_FINAL = 0x18; + private const int VK_HANJA = 0x19; + private const int VK_KANJI = 0x19; + + private const int VK_ESCAPE = 0x1B; + + private const int VK_CONVERT = 0x1C; + private const int VK_NONCONVERT = 0x1D; + private const int VK_ACCEPT = 0x1E; + private const int VK_MODECHANGE = 0x1F; + + private const int VK_SPACE = 0x20; + private const int VK_PRIOR = 0x21; + private const int VK_NEXT = 0x22; + private const int VK_END = 0x23; + private const int VK_HOME = 0x24; + private const int VK_LEFT = 0x25; + private const int VK_UP = 0x26; + private const int VK_RIGHT = 0x27; + private const int VK_DOWN = 0x28; + private const int VK_SELECT = 0x29; + private const int VK_PRINT = 0x2A; + private const int VK_EXECUTE = 0x2B; + private const int VK_SNAPSHOT = 0x2C; + private const int VK_INSERT = 0x2D; + private const int VK_DELETE = 0x2E; + private const int VK_HELP = 0x2F; + +/* + * VK_0 - VK_9 are the same as ASCII '0' - '9' (0x30 - 0x39) + * 0x40 : unassigned + * VK_A - VK_Z are the same as ASCII 'A' - 'Z' (0x41 - 0x5A) + */ + + private const int VK_LWIN = 0x5B; + private const int VK_RWIN = 0x5C; + private const int VK_APPS = 0x5D; + +/* + * 0x5E : reserved + */ + + private const int VK_SLEEP = 0x5F; + + private const int VK_NUMPAD0 = 0x60; + private const int VK_NUMPAD1 = 0x61; + private const int VK_NUMPAD2 = 0x62; + private const int VK_NUMPAD3 = 0x63; + private const int VK_NUMPAD4 = 0x64; + private const int VK_NUMPAD5 = 0x65; + private const int VK_NUMPAD6 = 0x66; + private const int VK_NUMPAD7 = 0x67; + private const int VK_NUMPAD8 = 0x68; + private const int VK_NUMPAD9 = 0x69; + private const int VK_MULTIPLY = 0x6A; + private const int VK_ADD = 0x6B; + private const int VK_SEPARATOR = 0x6C; + private const int VK_SUBTRACT = 0x6D; + private const int VK_DECIMAL = 0x6E; + private const int VK_DIVIDE = 0x6F; + private const int VK_F1 = 0x70; + private const int VK_F2 = 0x71; + private const int VK_F3 = 0x72; + private const int VK_F4 = 0x73; + private const int VK_F5 = 0x74; + private const int VK_F6 = 0x75; + private const int VK_F7 = 0x76; + private const int VK_F8 = 0x77; + private const int VK_F9 = 0x78; + private const int VK_F10 = 0x79; + private const int VK_F11 = 0x7A; + private const int VK_F12 = 0x7B; + private const int VK_F13 = 0x7C; + private const int VK_F14 = 0x7D; + private const int VK_F15 = 0x7E; + private const int VK_F16 = 0x7F; + private const int VK_F17 = 0x80; + private const int VK_F18 = 0x81; + private const int VK_F19 = 0x82; + private const int VK_F20 = 0x83; + private const int VK_F21 = 0x84; + private const int VK_F22 = 0x85; + private const int VK_F23 = 0x86; + private const int VK_F24 = 0x87; + +/* + * 0x88 - 0x8F : unassigned + */ + + private const int VK_NUMLOCK = 0x90; + private const int VK_SCROLL = 0x91; + +/* + * NEC PC-9800 kbd definitions + */ + private const int VK_OEM_NEC_EQUAL = 0x92; // '=' key on numpad + +/* + * Fujitsu/OASYS kbd definitions + */ + private const int VK_OEM_FJ_JISHO = 0x92; // 'Dictionary' key + private const int VK_OEM_FJ_MASSHOU= 0x93; // 'Unregister word' key + private const int VK_OEM_FJ_TOUROKU= 0x94; // 'Register word' key + private const int VK_OEM_FJ_LOYA = 0x95; // 'Left OYAYUBI' key + private const int VK_OEM_FJ_ROYA = 0x96; // 'Right OYAYUBI' key + +/* + * 0x97 - 0x9F : unassigned + */ + +/* + * VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys. + * Used only as parameters to GetAsyncKeyState() and GetKeyState(). + * No other API or message will distinguish left and right keys in this way. + */ + private const int VK_LSHIFT = 0xA0; + private const int VK_RSHIFT = 0xA1; + private const int VK_LCONTROL = 0xA2; + private const int VK_RCONTROL = 0xA3; + private const int VK_LMENU = 0xA4; + private const int VK_RMENU = 0xA5; + + private const int VK_BROWSER_BACK = 0xA6; + private const int VK_BROWSER_FORWARD = 0xA7; + private const int VK_BROWSER_REFRESH = 0xA8; + private const int VK_BROWSER_STOP = 0xA9; + private const int VK_BROWSER_SEARCH = 0xAA; + private const int VK_BROWSER_FAVORITES = 0xAB; + private const int VK_BROWSER_HOME = 0xAC; + + private const int VK_VOLUME_MUTE = 0xAD; + private const int VK_VOLUME_DOWN = 0xAE; + private const int VK_VOLUME_UP = 0xAF; + private const int VK_MEDIA_NEXT_TRACK = 0xB0; + private const int VK_MEDIA_PREV_TRACK = 0xB1; + private const int VK_MEDIA_STOP = 0xB2; + private const int VK_MEDIA_PLAY_PAUSE = 0xB3; + private const int VK_LAUNCH_MAIL = 0xB4; + private const int VK_LAUNCH_MEDIA_SELECT= 0xB5; + private const int VK_LAUNCH_APP1 = 0xB6; + private const int VK_LAUNCH_APP2 = 0xB7; + + +/* + * 0xB8 - 0xB9 : reserved + */ + + private const int VK_OEM_1 = 0xBA; // ';:' for US + private const int VK_OEM_PLUS = 0xBB; // '+' any country + private const int VK_OEM_COMMA = 0xBC; // ',' any country + private const int VK_OEM_MINUS = 0xBD; // '-' any country + private const int VK_OEM_PERIOD = 0xBE; // '.' any country + private const int VK_OEM_2 = 0xBF; // '/?' for US + private const int VK_OEM_3 = 0xC0; // '`~' for US + +/* + * 0xC1 - 0xD7 : reserved + */ + +/* + * 0xD8 - 0xDA : unassigned + */ + + private const int VK_OEM_4 = 0xDB; // '[{' for US + private const int VK_OEM_5 = 0xDC; // '\|' for US + private const int VK_OEM_6 = 0xDD; // ']}' for US + private const int VK_OEM_7 = 0xDE; // ''"' for US + private const int VK_OEM_8 = 0xDF; + +/* + * 0xE0 : reserved + */ + +/* + * Various extended or enhanced keyboards + */ + private const int VK_OEM_AX = 0xE1; // 'AX' key on Japanese AX kbd + private const int VK_OEM_102 = 0xE2; // "<>" or "\|" on RT 102-key kbd. + private const int VK_ICO_HELP = 0xE3; // Help key on ICO + private const int VK_ICO_00 = 0xE4; // 00 key on ICO + + +/* + * 0xE8 : unassigned + */ + +/* + * Nokia/Ericsson definitions + */ + private const int VK_OEM_RESET = 0xE9; + private const int VK_OEM_JUMP = 0xEA; + private const int VK_OEM_PA1 = 0xEB; + private const int VK_OEM_PA2 = 0xEC; + private const int VK_OEM_PA3 = 0xED; + private const int VK_OEM_WSCTRL = 0xEE; + private const int VK_OEM_CUSEL = 0xEF; + private const int VK_OEM_ATTN = 0xF0; + private const int VK_OEM_FINISH = 0xF1; + private const int VK_OEM_COPY = 0xF2; + private const int VK_OEM_AUTO = 0xF3; + private const int VK_OEM_ENLW = 0xF4; + private const int VK_OEM_BACKTAB = 0xF5; + + private const int VK_ATTN = 0xF6; + private const int VK_CRSEL = 0xF7; + private const int VK_EXSEL = 0xF8; + private const int VK_EREOF = 0xF9; + private const int VK_PLAY = 0xFA; + private const int VK_ZOOM = 0xFB; + private const int VK_NONAME = 0xFC; + private const int VK_PA1 = 0xFD; + private const int VK_OEM_CLEAR = 0xFE; + + + } +} \ No newline at end of file diff --git a/awt/theming.cs b/awt/theming.cs new file mode 100644 index 0000000..faddced --- /dev/null +++ b/awt/theming.cs @@ -0,0 +1,94 @@ +/* + Copyright (C) 2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.IO; +using System.Threading; +using System.Runtime.InteropServices; +using System.Security; + +sealed class ThemingActivationContext : IDisposable +{ + private IntPtr cookie; + + [SecurityCritical] + public ThemingActivationContext() + { + if (Context.hActCtx != IntPtr.Zero) + { + IntPtr tmp; + if (ActivateActCtx(Context.hActCtx, out tmp)) + { + cookie = tmp; + } + } + } + + [SecuritySafeCritical] + public void Dispose() + { + IntPtr tmp = Interlocked.Exchange(ref cookie, IntPtr.Zero); + if (tmp != IntPtr.Zero) + { + DeactivateActCtx(0, tmp); + } + } + + static class Context + { + internal static readonly IntPtr hActCtx; + + [SecurityCritical] + static Context() + { + ACTCTX actctx = new ACTCTX(); + actctx.cbSize = Marshal.SizeOf(typeof(ACTCTX)); + actctx.lpSource = Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), "XPThemes.manifest"); + IntPtr handle = CreateActCtx(ref actctx); + if (handle != new IntPtr(-1)) + { + hActCtx = handle; + } + } + + struct ACTCTX + { + internal int cbSize; + internal uint dwFlags; + internal string lpSource; + internal ushort wProcessorArchitecture; + internal ushort wLangId; + internal string lpAssemblyDirectory; + internal string lpResourceName; + internal string lpApplicationName; + } + + [DllImport("kernel32.dll")] + extern static IntPtr CreateActCtx(ref ACTCTX actctx); + } + + [DllImport("kernel32.dll")] + extern static bool ActivateActCtx(IntPtr hActCtx, out IntPtr lpCookie); + [DllImport("kernel32.dll")] + extern static bool DeactivateActCtx(uint dwFlags, IntPtr lpCookie); +} diff --git a/awt/toolkit-0.95.cs b/awt/toolkit-0.95.cs new file mode 100644 index 0000000..3326c8c --- /dev/null +++ b/awt/toolkit-0.95.cs @@ -0,0 +1,5666 @@ +/* + * Copyright 1996-2007 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. + */ + +/* +Copyright (C) 2002, 2004-2009 Jeroen Frijters +Copyright (C) 2006 Active Endpoints, Inc. +Copyright (C) 2006-2013 Volker Berlin (i-net software) +Copyright (C) 2010-2011 Karsten Heinrich (i-net software) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +Jeroen Frijters +jeroen@frijters.net + +*/ + +using System; +using System.Drawing; +using System.Drawing.Imaging; +using System.Diagnostics; +using System.IO; +using System.Threading; +using System.Windows.Forms; +using System.ComponentModel; +using System.Reflection; +using java.net; +using java.util; +using ikvm.awt.printing; +using ikvm.runtime; +using sun.awt; +using System.Runtime.InteropServices; +using System.Drawing.Drawing2D; + +namespace ikvm.awt +{ + internal delegate TResult Func(); + internal delegate void Action(T t); + + class UndecoratedForm : Form + { + private bool focusableWindow = true; + private bool alwaysOnTop; + + public UndecoratedForm() + { + setBorderStyle(); + SetStyle(ControlStyles.UserPaint | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor, true); + } + + protected virtual void setBorderStyle() + { + this.FormBorderStyle = FormBorderStyle.None; + this.ShowInTaskbar = false; + } + + internal void SetWindowState(bool focusableWindow, bool alwaysOnTop) + { + this.focusableWindow = focusableWindow; + this.alwaysOnTop = alwaysOnTop; + } + + protected override bool ShowWithoutActivation { + // This work not like in Java. In Java it is not possible to click on a not focusable Window + // But now the windows is not stealing the focus on showing + get + { + return !focusableWindow; + } + } + + private const int WS_EX_TOPMOST = 0x00000008; + private const int WS_EX_NOACTIVATE = 0x08000000; + private const int WS_DISABLED = 0x08000000; + + protected override CreateParams CreateParams { + get { + CreateParams baseParams = base.CreateParams; + int exStyle = baseParams.ExStyle; + + // This work not like in Java. In Java it is not possible to click on a not focusable Window + // But now the windows is not stealing the focus on showing + exStyle = focusableWindow ? exStyle & ~WS_EX_NOACTIVATE : exStyle | WS_EX_NOACTIVATE; + + // we need to set TOPMOST here because the property TopMost does not work with ShowWithoutActivation + baseParams.ExStyle = alwaysOnTop ? exStyle | WS_EX_TOPMOST : exStyle & ~WS_EX_TOPMOST; + + // the Enabled on Forms has no effect. In Java a window beep if ot is disabled + // the same effect have we with this flag + baseParams.Style = Enabled ? baseParams.Style & ~WS_DISABLED : baseParams.Style | WS_DISABLED; + return baseParams; + } + } + + private const int WM_MOUSEACTIVATE = 0x0021; + private const int MA_NOACTIVATE = 0x0003; + + protected override void WndProc(ref Message m) + { + if (!focusableWindow && m.Msg == WM_MOUSEACTIVATE) + { + m.Result = (IntPtr)MA_NOACTIVATE; + return; + } + base.WndProc(ref m); + } + + protected override void OnPaintBackground(PaintEventArgs e) + { + NetComponentPeer peer = NetComponentPeer.FromControl(this); + if (peer.eraseBackground) + { + base.OnPaintBackground(e); + } + } + } + + class MyForm : UndecoratedForm + { + /// + /// Original MaximizedBounds + /// + private Rectangle maxBounds; + private bool maxBoundsSet; + public java.awt.Insets peerInsets; + + /// + /// Creates the native form + /// + /// the insets instance of the peer instance + public MyForm( java.awt.Insets peerInsets ) + { + this.peerInsets = peerInsets; + } + + protected override void setBorderStyle() + { + //nothing, default behaviour + } + + public void setMaximizedBounds(java.awt.Rectangle rect) + { + if (rect == null) + { + // null means reset to the original system setting + if (maxBoundsSet) + { + SetMaximizedBoundsImpl(maxBounds); + } + } + else + { + if (!maxBoundsSet) + { + maxBounds = MaximizedBounds; + maxBoundsSet = true; + } + SetMaximizedBoundsImpl(J2C.ConvertRect(rect)); + } + } + + private void SetMaximizedBoundsImpl(Rectangle rect) + { + NetToolkit.Invoke(delegate { MaximizedBounds = rect; }); + } + } + + sealed class EventQueueSynchronizationContext : SynchronizationContext + { + public override SynchronizationContext CreateCopy() + { + return new EventQueueSynchronizationContext(); + } + + public override void Post(SendOrPostCallback d, object state) + { + java.awt.EventQueue.invokeLater(Delegates.toRunnable(delegate { d(state); })); + } + + public override void Send(SendOrPostCallback d, object state) + { + java.awt.EventQueue.invokeAndWait(Delegates.toRunnable(delegate { d(state); })); + } + + [System.Security.SecuritySafeCritical] + internal static void Install() + { + SynchronizationContext.SetSynchronizationContext(new EventQueueSynchronizationContext()); + } + } + + static class WinFormsMessageLoop + { + private static readonly object mylock = new object(); + private static Form theForm; + + private static Form GetForm() + { + lock (mylock) + { + if (theForm == null) + { + Thread thread = new Thread(MessageLoop); + thread.SetApartmentState(ApartmentState.STA); + thread.Name = "IKVM AWT WinForms Message Loop"; + thread.IsBackground = true; + thread.Start(); + while (theForm == null && thread.IsAlive) + { + Thread.Sleep(1); + } + } + } + return theForm; + } + + private static void MessageLoop() + { + using (Form form = new Form()) + { + NetToolkit.CreateNative(form); + theForm = form; + Application.Run(); + } + } + + internal static bool InvokeRequired + { + get { return GetForm().InvokeRequired; } + } + + internal static object Invoke(Delegate method) + { + return GetForm().Invoke(method); + } + + internal static object Invoke(Delegate method, params object[] args) + { + return GetForm().Invoke(method, args); + } + + internal static IAsyncResult BeginInvoke(Delegate method) + { + return GetForm().BeginInvoke(method); + } + + internal static IAsyncResult BeginInvoke(Delegate method, params object[] args) + { + return GetForm().BeginInvoke(method, args); + } + } + + public sealed class NetToolkit : sun.awt.SunToolkit, ikvm.awt.IkvmToolkit, sun.awt.KeyboardFocusManagerPeerProvider + { + private int resolution; + private NetClipboard clipboard; + private bool eventQueueSynchronizationContext; + + protected internal override java.awt.EventQueue getSystemEventQueueImpl() + { + java.awt.EventQueue eq = base.getSystemEventQueueImpl(); + if (!eventQueueSynchronizationContext) + { + InstallEventQueueSynchronizationContext(eq); + } + return eq; + } + + private void InstallEventQueueSynchronizationContext(java.awt.EventQueue eq) + { + bool install; + lock (this) + { + install = !eventQueueSynchronizationContext; + eventQueueSynchronizationContext = true; + } + if (install) + { + eq.postEvent(new java.awt.@event.InvocationEvent(this, Delegates.toRunnable(EventQueueSynchronizationContext.Install), null, true)); + } + } + + internal static void CreateNative(Control control) + { + control.CreateControl(); + // HACK I have no idea why this line is necessary... + IntPtr p = control.Handle; + if (p == IntPtr.Zero) + { + // shut up compiler warning + } + } + + public NetToolkit() + { + } + + /// + /// Run on a win 32 system + /// + /// + internal static bool isWin32() + { + return Environment.OSVersion.Platform == PlatformID.Win32NT || Environment.OSVersion.Platform == PlatformID.Win32Windows; + } + + protected internal override void loadSystemColors(int[] systemColors) + { + // initialize all colors to purple to make the ones we might have missed stand out + for (int i = 0; i < systemColors.Length; i++) + { + systemColors[i] = Color.Purple.ToArgb(); + } + systemColors[java.awt.SystemColor.DESKTOP] = SystemColors.Desktop.ToArgb(); + systemColors[java.awt.SystemColor.ACTIVE_CAPTION] = SystemColors.ActiveCaption.ToArgb(); + systemColors[java.awt.SystemColor.ACTIVE_CAPTION_TEXT] = SystemColors.ActiveCaptionText.ToArgb(); + systemColors[java.awt.SystemColor.ACTIVE_CAPTION_BORDER] = SystemColors.ActiveBorder.ToArgb(); + systemColors[java.awt.SystemColor.INACTIVE_CAPTION] = SystemColors.InactiveCaption.ToArgb(); + systemColors[java.awt.SystemColor.INACTIVE_CAPTION_TEXT] = SystemColors.InactiveCaptionText.ToArgb(); + systemColors[java.awt.SystemColor.INACTIVE_CAPTION_BORDER] = SystemColors.InactiveBorder.ToArgb(); + systemColors[java.awt.SystemColor.WINDOW] = SystemColors.Window.ToArgb(); + systemColors[java.awt.SystemColor.WINDOW_BORDER] = SystemColors.WindowFrame.ToArgb(); + systemColors[java.awt.SystemColor.WINDOW_TEXT] = SystemColors.WindowText.ToArgb(); + systemColors[java.awt.SystemColor.MENU] = SystemColors.Menu.ToArgb(); + systemColors[java.awt.SystemColor.MENU_TEXT] = SystemColors.MenuText.ToArgb(); + systemColors[java.awt.SystemColor.TEXT] = SystemColors.Window.ToArgb(); + systemColors[java.awt.SystemColor.TEXT_TEXT] = SystemColors.WindowText.ToArgb(); + systemColors[java.awt.SystemColor.TEXT_HIGHLIGHT] = SystemColors.Highlight.ToArgb(); + systemColors[java.awt.SystemColor.TEXT_HIGHLIGHT_TEXT] = SystemColors.HighlightText.ToArgb(); + systemColors[java.awt.SystemColor.TEXT_INACTIVE_TEXT] = SystemColors.GrayText.ToArgb(); + systemColors[java.awt.SystemColor.CONTROL] = SystemColors.Control.ToArgb(); + systemColors[java.awt.SystemColor.CONTROL_TEXT] = SystemColors.ControlText.ToArgb(); + systemColors[java.awt.SystemColor.CONTROL_HIGHLIGHT] = SystemColors.ControlLight.ToArgb(); + systemColors[java.awt.SystemColor.CONTROL_LT_HIGHLIGHT] = SystemColors.ControlLightLight.ToArgb(); + systemColors[java.awt.SystemColor.CONTROL_SHADOW] = SystemColors.ControlDark.ToArgb(); + systemColors[java.awt.SystemColor.CONTROL_DK_SHADOW] = SystemColors.ControlDarkDark.ToArgb(); + systemColors[java.awt.SystemColor.SCROLLBAR] = SystemColors.ScrollBar.ToArgb(); + systemColors[java.awt.SystemColor.INFO] = SystemColors.Info.ToArgb(); + systemColors[java.awt.SystemColor.INFO_TEXT] = SystemColors.InfoText.ToArgb(); + } + + public override java.awt.peer.ButtonPeer createButton(java.awt.Button target) + { + java.awt.peer.ButtonPeer peer = Invoke(delegate { return new NetButtonPeer(target); }); + targetCreatedPeer(target, peer); + return peer; + } + + // MONOBUG mcs refuses to override these two methods, so we disable them when building with mcs + // (since AWT isn't supported anyway) +#if !__MonoCS__ + public override java.awt.peer.CanvasPeer createCanvas(java.awt.Canvas target) + { + java.awt.peer.CanvasPeer peer = Invoke(delegate { return new NetCanvasPeer(target); }); + targetCreatedPeer(target, peer); + return peer; + } + + public override java.awt.peer.PanelPeer createPanel(java.awt.Panel target) + { + java.awt.peer.PanelPeer peer = Invoke(delegate { return new NetPanelPeer(target); }); + targetCreatedPeer(target, peer); + return peer; + } +#endif + + public override java.awt.peer.TextFieldPeer createTextField(java.awt.TextField target) + { + java.awt.peer.TextFieldPeer peer = Invoke(delegate { return new NetTextFieldPeer(target); }); + targetCreatedPeer(target, peer); + return peer; + } + + public override java.awt.peer.LabelPeer createLabel(java.awt.Label target) + { + java.awt.peer.LabelPeer peer = Invoke(delegate { return new NetLabelPeer(target); }); + targetCreatedPeer(target, peer); + return peer; + } + + public override java.awt.peer.ListPeer createList(java.awt.List target) + { + java.awt.peer.ListPeer peer = Invoke(delegate { return new NetListPeer(target); }); + targetCreatedPeer(target, peer); + return peer; + } + + public override java.awt.peer.CheckboxPeer createCheckbox(java.awt.Checkbox target) + { + java.awt.peer.CheckboxPeer peer = Invoke(delegate { return new NetCheckboxPeer(target); }); + targetCreatedPeer(target, peer); + return peer; + } + + public override java.awt.peer.ScrollbarPeer createScrollbar(java.awt.Scrollbar target) + { + java.awt.peer.ScrollbarPeer peer = Invoke(delegate { return new NetScrollbarPeer(target); }); + targetCreatedPeer(target, peer); + return peer; + } + + public override java.awt.peer.ScrollPanePeer createScrollPane(java.awt.ScrollPane target) + { + java.awt.peer.ScrollPanePeer peer = Invoke(delegate { return new NetScrollPanePeer(target); }); + targetCreatedPeer(target, peer); + return peer; + } + + public override java.awt.peer.TextAreaPeer createTextArea(java.awt.TextArea target) + { + java.awt.peer.TextAreaPeer peer = Invoke(delegate { return new NetTextAreaPeer(target); }); + targetCreatedPeer(target, peer); + return peer; + } + + public override java.awt.peer.ChoicePeer createChoice(java.awt.Choice target) + { + java.awt.peer.ChoicePeer peer = Invoke(delegate { return new NetChoicePeer(target); }); + targetCreatedPeer(target, peer); + return peer; + } + + public override java.awt.peer.FramePeer createFrame(java.awt.Frame target) + { + bool isFocusableWindow = target.isFocusableWindow(); + bool isAlwaysOnTop = target.isAlwaysOnTop(); + java.awt.peer.FramePeer peer = Invoke(delegate { return new NetFramePeer(target, isFocusableWindow, isAlwaysOnTop); }); + targetCreatedPeer(target, peer); + return peer; + } + + public override java.awt.peer.WindowPeer createWindow(java.awt.Window target) + { + bool isFocusableWindow = target.isFocusableWindow(); + bool isAlwaysOnTop = target.isAlwaysOnTop(); + java.awt.peer.WindowPeer peer = Invoke(delegate { return new NetWindowPeer(target, isFocusableWindow, isAlwaysOnTop); }); + targetCreatedPeer(target, peer); + return peer; + } + + public override java.awt.peer.DialogPeer createDialog(java.awt.Dialog target) + { + bool isFocusableWindow = target.isFocusableWindow(); + bool isAlwaysOnTop = target.isAlwaysOnTop(); + java.awt.peer.DialogPeer peer = Invoke(delegate { return new NetDialogPeer(target, isFocusableWindow, isAlwaysOnTop); }); + targetCreatedPeer(target, peer); + return peer; + } + + public override java.awt.peer.MenuBarPeer createMenuBar(java.awt.MenuBar target) + { + // we need to force peer creation of the sub menus here, because we're + // transitioning to the UI thread to do the rest of the work and there + // we cannot acquire the AWT tree lock (because it is owned by the current thread) + for (int i = 0; i < target.getMenuCount(); i++) + { + target.getMenu(i).addNotify(); + } + java.awt.Menu help = target.getHelpMenu(); + if (help != null) + { + help.addNotify(); + } + java.awt.peer.MenuBarPeer peer = Invoke(delegate { return new NetMenuBarPeer(target); }); + targetCreatedPeer(target, peer); + return peer; + } + + public override java.awt.peer.MenuPeer createMenu(java.awt.Menu target) + { + for (int i = 0; i < target.getItemCount(); i++) + { + target.getItem(i).addNotify(); + } + java.awt.peer.MenuPeer peer = Invoke(delegate { return new NetMenuPeer(target); }); + targetCreatedPeer(target, peer); + return peer; + } + + public override java.awt.peer.PopupMenuPeer createPopupMenu(java.awt.PopupMenu target) + { + for (int i = 0; i < target.getItemCount(); i++) + { + target.getItem(i).addNotify(); + } + java.awt.peer.PopupMenuPeer peer = Invoke(delegate { return new NetPopupMenuPeer(target); }); + targetCreatedPeer(target, peer); + return peer; + } + + public override java.awt.peer.MenuItemPeer createMenuItem(java.awt.MenuItem target) + { + java.awt.peer.MenuItemPeer peer = Invoke(delegate { return new NetMenuItemPeer(target); }); + targetCreatedPeer(target, peer); + return peer; + } + + public override java.awt.peer.FileDialogPeer createFileDialog(java.awt.FileDialog target) + { + bool isFocusableWindow = target.isFocusableWindow(); + bool isAlwaysOnTop = target.isAlwaysOnTop(); + java.awt.peer.FileDialogPeer peer = Invoke(delegate { return new NetFileDialogPeer(target, isFocusableWindow, isAlwaysOnTop); }); + targetCreatedPeer(target, peer); + return peer; + } + + public override java.awt.peer.CheckboxMenuItemPeer createCheckboxMenuItem(java.awt.CheckboxMenuItem target) + { + return new NetCheckboxMenuItemPeer(target); + } + + public override java.awt.peer.FontPeer getFontPeer(string name, int style) + { + throw new NotImplementedException(); + } + + public override java.awt.peer.KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() + { + return new NetKeyboardFocusManagerPeer(); + } + + public override java.awt.Dimension getScreenSize() + { + return new java.awt.Dimension(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); + } + + public override int getScreenResolution() + { + if (resolution == 0) + { + using (Form form = new Form()) + using (Graphics g = form.CreateGraphics()) + { + resolution = (int)Math.Round(g.DpiY); + } + } + return resolution; + } + + public override java.awt.image.ColorModel getColorModel() + { + //we return the default ColorModel because this produce the fewest problems with convertions + return java.awt.image.ColorModel.getRGBdefault(); + } + + public override void sync() + { + } + + public override java.awt.Image getImage(string filename) + { + try + { + filename = new java.io.File(filename).getPath(); //convert a Java file name to .NET filename (slahes, backslasches, etc) + using (System.IO.FileStream stream = new System.IO.FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + { + return new java.awt.image.BufferedImage(new Bitmap(Image.FromStream(stream))); + } + } + catch (Exception) + { + return new NoImage(new sun.awt.image.FileImageSource(filename)); + } + } + + public override java.awt.Image getImage(URL url) + { + // TODO extremely lame... + System.IO.MemoryStream mem = new System.IO.MemoryStream(); + java.io.InputStream inS = url.openStream(); + int b; + while ((b = inS.read()) >= 0) + { + mem.WriteByte((byte)b); + } + try + { + mem.Position = 0; + return new java.awt.image.BufferedImage(new Bitmap(Image.FromStream(mem))); + } + catch + { + return new NoImage(new sun.awt.image.URLImageSource(url)); + } + } + + public override java.awt.Image createImage(string filename) + { + return getImage(filename); + } + + public override java.awt.Image createImage(URL url) + { + return getImage(url); + } + + public override java.awt.Image createImage(byte[] imagedata, int imageoffset, int imagelength) + { + try + { + return new java.awt.image.BufferedImage(new Bitmap(new MemoryStream(imagedata, imageoffset, imagelength, false))); + } + catch (Exception) + { + return new NoImage(new sun.awt.image.ByteArrayImageSource(imagedata, imageoffset, imagelength)); + } + } + + public override java.awt.PrintJob getPrintJob(java.awt.Frame frame, string jobtitle, java.util.Properties props) + { + throw new NotImplementedException(); + } + + public override void beep() + { + Console.Beep(); + } + + public override java.awt.datatransfer.Clipboard getSystemClipboard() + { + lock(this) + { + if (clipboard==null) + { + clipboard = new NetClipboard(); + } + } + return clipboard; + } + + public override java.awt.dnd.DragGestureRecognizer createDragGestureRecognizer(java.lang.Class abstractRecognizerClass, java.awt.dnd.DragSource ds, java.awt.Component c, int srcActions, java.awt.dnd.DragGestureListener dgl) + { + java.lang.Class clazz = typeof(java.awt.dnd.MouseDragGestureRecognizer); + if (abstractRecognizerClass == clazz) + return new NetMouseDragGestureRecognizer(ds, c, srcActions, dgl); + else + return null; + } + + public override java.awt.dnd.peer.DragSourceContextPeer createDragSourceContextPeer(java.awt.dnd.DragGestureEvent dge) + { + return NetDragSourceContextPeer.createDragSourceContextPeer(dge); + } + + public override Map mapInputMethodHighlight(java.awt.im.InputMethodHighlight highlight) + { + throw new NotImplementedException(); + } + +#if false + protected override java.awt.peer.LightweightPeer createComponent(java.awt.Component target) + { + if(target is java.awt.Container) + { + return new NetLightweightContainerPeer((java.awt.Container)target); + } + return new NetLightweightComponentPeer(target); + } +#endif + +/* public override java.awt.Font createFont(int format, java.io.InputStream stream) + { + throw new NotImplementedException(); + } + + public override gnu.java.awt.peer.ClasspathFontPeer getClasspathFontPeer(string name, java.util.Map attrs) + { + return new NetFontPeer(name, attrs); + } + + public override java.awt.GraphicsEnvironment getLocalGraphicsEnvironment() + { + return new NetGraphicsEnvironment(); + } + + public override RobotPeer createRobot(java.awt.GraphicsDevice screen) + { + if (Environment.OSVersion.Platform == PlatformID.Win32NT || Environment.OSVersion.Platform == PlatformID.Win32Windows) + { + return new WindowsRobot(screen); + } + throw new java.awt.AWTException("Robot not supported for this OS"); + } + + public override gnu.java.awt.peer.EmbeddedWindowPeer createEmbeddedWindow(gnu.java.awt.EmbeddedWindow ew) + { + throw new NotImplementedException(); + } +*/ + protected internal override java.awt.peer.DesktopPeer createDesktopPeer(java.awt.Desktop target) + { + return new NetDesktopPeer(); + } + + public override java.awt.Dimension getBestCursorSize(int preferredWidth, int preferredHeight) + { + // TODO + return new java.awt.Dimension(preferredWidth, preferredHeight); + } + + public override java.awt.Cursor createCustomCursor(java.awt.Image cursor, java.awt.Point hotSpot, string name) + { + return new NetCustomCursor(cursor, hotSpot, name); + } + + private object getRegistry(string subKey, string valueName) + { + using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(subKey, false)) + { + return key == null ? null : key.GetValue(valueName); + } + } + + protected internal override void initializeDesktopProperties() + { + //copied from WToolkit.java + desktopProperties.put("DnD.Autoscroll.initialDelay", java.lang.Integer.valueOf(50)); + desktopProperties.put("DnD.Autoscroll.interval", java.lang.Integer.valueOf(50)); + + try + { + if (isWin32()) + { + desktopProperties.put("Shell.shellFolderManager", "sun.awt.shell.Win32ShellFolderManager2" ); + object themeActive = getRegistry("Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager", "ThemeActive"); +// string dllName = (string)getRegistry("Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager", "DllName"); +// string sizeName = (string)getRegistry("Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager", "SizeName"); +// string colorName = (string)getRegistry("Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager", "ColorName"); + desktopProperties.put("win.xpstyle.themeActive", java.lang.Boolean.valueOf("1".Equals(themeActive))); +// desktopProperties.put("win.xpstyle.dllName", dllName); +// desktopProperties.put("win.xpstyle.sizeName", sizeName); +// desktopProperties.put("win.xpstyle.colorName", colorName); + } + } + catch (java.lang.ClassNotFoundException) + { + } + } + + protected internal override Object lazilyLoadDesktopProperty(String name) + { + switch (name) + { + case "win.defaultGUI.font": + return C2J.ConvertFont(Control.DefaultFont); + case "win.highContrast.on": + return java.lang.Boolean.valueOf(SystemInformation.HighContrast); + default: + return null; + } + } + + protected internal override java.awt.peer.MouseInfoPeer getMouseInfoPeer() { + return new NetMouseInfoPeer(); + } + + /*=============================== + * Implementations of interface IkvmToolkit + */ + + /// + /// Get a helper class for implementing the print API + /// + /// + public sun.print.PrintPeer getPrintPeer() + { + if (isWin32()) + { + return new Win32PrintPeer(); + } + else + { + return new LinuxPrintPeer(); + } + } + + /// + /// Create a outline from the given text and font parameter + /// + /// the font + /// font render context + /// the text + /// x - position + /// y - position + /// + public java.awt.Shape outline(java.awt.Font javaFont, java.awt.font.FontRenderContext frc, string text, float x, float y) { + GraphicsPath path = new GraphicsPath(FillMode.Winding); + Font netFont = javaFont.getNetFont(); + FontFamily family = netFont.FontFamily; + FontStyle style = netFont.Style; + float factor = netFont.Size / family.GetEmHeight(style); + float ascent = family.GetCellAscent(style) * factor; + y -= ascent; + + StringFormat format = new StringFormat(StringFormat.GenericTypographic); + format.FormatFlags = StringFormatFlags.MeasureTrailingSpaces | StringFormatFlags.NoWrap | StringFormatFlags.FitBlackBox; + format.Trimming = StringTrimming.None; + + path.AddString(text, family, (int)style, netFont.Size, new PointF(x, y), format); + return C2J.ConvertShape(path); + } + + /*=============================== + * Implementations of interface SunToolkit + */ + + public override bool isModalExclusionTypeSupported(java.awt.Dialog.ModalExclusionType dmet) + { + return false; + } + + public override bool isModalityTypeSupported(java.awt.Dialog.ModalityType type) + { + return type.ordinal() == java.awt.Dialog.ModalityType.MODELESS.ordinal() || + type.ordinal() == java.awt.Dialog.ModalityType.APPLICATION_MODAL.ordinal(); + } + + public override java.awt.Window createInputMethodWindow(string __p1, sun.awt.im.InputContext __p2) + { + throw new NotImplementedException(); + } + + public override java.awt.peer.RobotPeer createRobot(java.awt.Robot r, java.awt.GraphicsDevice screen) + { + if (isWin32()) + { + return new WindowsRobot(screen); + } + throw new java.awt.AWTException("Robot not supported for this OS"); + } + + public override java.awt.peer.SystemTrayPeer createSystemTray(java.awt.SystemTray target) + { + NetSystemTrayPeer peer = new NetSystemTrayPeer(target); + targetCreatedPeer(target, peer); + return peer; + } + + public override java.awt.peer.TrayIconPeer createTrayIcon(java.awt.TrayIcon target) + { + NetTrayIconPeer peer = new NetTrayIconPeer(target); + targetCreatedPeer(target, peer); + return peer; + } + + public override java.awt.im.spi.InputMethodDescriptor getInputMethodAdapterDescriptor() + { + return null; + } + + protected internal override int getScreenHeight() + { + return Screen.PrimaryScreen.Bounds.Height; + } + + protected internal override int getScreenWidth() + { + return Screen.PrimaryScreen.Bounds.Width; + } + + public override java.awt.Insets getScreenInsets(java.awt.GraphicsConfiguration gc) + { + NetGraphicsConfiguration ngc = gc as NetGraphicsConfiguration; + if (ngc != null) + { + Rectangle rectWorkingArea = ngc.screen.WorkingArea; + Rectangle rectBounds = ngc.screen.Bounds; + return new java.awt.Insets( + rectWorkingArea.Top - rectBounds.Top, + rectWorkingArea.Left - rectBounds.Left, + rectBounds.Bottom - rectWorkingArea.Bottom, + rectBounds.Right - rectWorkingArea.Right); + } + else + { + return base.getScreenInsets(gc); + } + } + + public override void grab(java.awt.Window window) + { + NetWindowPeer peer = (NetWindowPeer)window.getPeer(); + if (peer != null) + { + peer.Grab(); + } + } + + public override bool isDesktopSupported() + { + return true; + } + + public override bool isTraySupported() + { + return true; + } + + public override bool isFrameStateSupported(int state) + { + switch (state) + { + case java.awt.Frame.NORMAL: + case java.awt.Frame.ICONIFIED: + case java.awt.Frame.MAXIMIZED_BOTH: + return true; + default: + return false; + } + } + + protected internal override bool syncNativeQueue(long l) + { + throw new NotImplementedException(); + } + + public override void ungrab(java.awt.Window window) + { + NetWindowPeer peer = (NetWindowPeer)window.getPeer(); + if (peer != null) + { + peer.Ungrab(false); + } + } + + internal new static object targetToPeer(object target) + { + return SunToolkit.targetToPeer(target); + } + + internal new static void targetDisposedPeer(object target, object peer) + { + SunToolkit.targetDisposedPeer(target, peer); + } + + internal static void BeginInvoke(MethodInvoker del) + { + if (WinFormsMessageLoop.InvokeRequired) + { + WinFormsMessageLoop.BeginInvoke(del); + } + else + { + del(); + } + } + + internal static void BeginInvoke(Action del, T t) + { + if (WinFormsMessageLoop.InvokeRequired) + { + WinFormsMessageLoop.BeginInvoke(del, t); + } + else + { + del(t); + } + } + internal static void Invoke(Action del, T t) + { + if (WinFormsMessageLoop.InvokeRequired) + { + WinFormsMessageLoop.Invoke(del, t); + } + else + { + del(t); + } + } + + internal static TResult Invoke(Func del) + { + if (WinFormsMessageLoop.InvokeRequired) + { + return (TResult)WinFormsMessageLoop.Invoke(del); + } + else + { + return del(); + } + } + + internal static void Invoke(MethodInvoker del) + { + if (WinFormsMessageLoop.InvokeRequired) + { + WinFormsMessageLoop.Invoke(del); + } + else + { + del(); + } + } + + public override bool areExtraMouseButtonsEnabled() + { + return true; + } + + public override java.awt.peer.FramePeer createLightweightFrame(sun.awt.LightweightFrame lf) + { + throw new NotImplementedException(); + } + + public override sun.awt.datatransfer.DataTransferer getDataTransferer() + { + return NetDataTransferer.getInstanceImpl(); + } + } + + sealed class NetMenuBarPeer : java.awt.peer.MenuBarPeer + { + internal readonly MainMenu menu = new MainMenu(); + + internal NetMenuBarPeer(java.awt.MenuBar target) + { + menu.Tag = target; + for (int i = 0; i < target.getMenuCount(); i++) + { + addMenu(target.getMenu(i)); + } + } + + public void addHelpMenu(java.awt.Menu m) + { + addMenu(m); + } + + public void addMenu(java.awt.Menu m) + { + if (m.getPeer() == null) + { + m.addNotify(); + } + NetToolkit.Invoke(delegate { menu.MenuItems.Add(((NetMenuPeer)m.getPeer()).menu); }); + } + + public void delMenu(int i) + { + NetToolkit.Invoke(delegate { menu.MenuItems.RemoveAt(i); }); + } + + public void dispose() + { + NetToolkit.Invoke(delegate { menu.Dispose(); }); + } + + public void setFont(java.awt.Font f) + { + throw new NotImplementedException(); + } + } + + sealed class NetMenuPeer : java.awt.peer.MenuPeer + { + internal readonly MenuItem menu = new MenuItem(); + + internal NetMenuPeer(java.awt.Menu target) + { + menu.Tag = target; + menu.Text = target.getLabel(); + for (int i = 0; i < target.getItemCount(); i++) + { + addItem(target.getItem(i)); + } + } + + public void addItem(java.awt.MenuItem item) + { + if (item.getPeer() == null) + { + item.addNotify(); + } + if (item.getPeer() is NetMenuItemPeer) + { + NetToolkit.Invoke(delegate { menu.MenuItems.Add(((NetMenuItemPeer)item.getPeer()).menuitem); }); + } + else + { + NetToolkit.Invoke(delegate { menu.MenuItems.Add(((NetMenuPeer)item.getPeer()).menu); }); + } + } + + public void addSeparator() + { + NetToolkit.Invoke(delegate { menu.MenuItems.Add(new MenuItem("-")); }); + } + + public void delItem(int i) + { + NetToolkit.Invoke(delegate { menu.MenuItems.RemoveAt(i); }); + } + + public void dispose() + { + NetToolkit.Invoke(delegate { menu.Dispose(); }); + } + + public void setFont(java.awt.Font f) + { + throw new NotImplementedException(); + } + + public void disable() + { + setEnabled(false); + } + + public void enable() + { + setEnabled(true); + } + + public void setEnabled(bool b) + { + NetToolkit.Invoke(delegate { menu.Enabled = b; }); + } + + public void setLabel(string str) + { + NetToolkit.Invoke(delegate { menu.Text = str; }); + } + } + + class NetMenuItemPeer : java.awt.peer.MenuItemPeer + { + protected readonly java.awt.MenuItem target; + internal readonly MenuItem menuitem = new MenuItem(); + + internal NetMenuItemPeer(java.awt.MenuItem target) + { + this.target = target; + setEnabled(target.isEnabled()); + setLabel(target.getLabel()); + menuitem.Click += OnClick; + } + + protected virtual void OnClick(object sender, EventArgs e) + { + long when = java.lang.System.currentTimeMillis(); + int modifiers = NetComponentPeer.GetModifiers(Control.ModifierKeys); + NetToolkit.executeOnEventHandlerThread(target, Delegates.toRunnable(delegate + { + NetToolkit.postEvent(NetToolkit.targetToAppContext(target), new java.awt.@event.ActionEvent(target, java.awt.@event.ActionEvent.ACTION_PERFORMED, + target.getActionCommand(), when, modifiers)); + })); + } + + public void disable() + { + setEnabled(false); + } + + public void enable() + { + setEnabled(true); + } + + public void setEnabled(bool b) + { + NetToolkit.Invoke(delegate { menuitem.Enabled = b; }); + } + + public void setLabel(string str) + { + NetToolkit.Invoke(delegate { menuitem.Text = str; }); + } + + public void dispose() + { + NetToolkit.Invoke(delegate { menuitem.Dispose(); }); + } + + public void setFont(java.awt.Font f) + { + } + } + + sealed class NetCheckboxMenuItemPeer : NetMenuItemPeer, java.awt.peer.CheckboxMenuItemPeer + { + internal NetCheckboxMenuItemPeer(java.awt.CheckboxMenuItem target) + : base(target) + { + setState(target.getState()); + } + + protected override void OnClick(object sender, EventArgs e) + { + java.awt.CheckboxMenuItem target = (java.awt.CheckboxMenuItem)this.target; + NetToolkit.executeOnEventHandlerThread(target, Delegates.toRunnable(delegate + { + bool state = !menuitem.Checked; + target.setState(state); + NetToolkit.postEvent(NetToolkit.targetToAppContext(target), new java.awt.@event.ItemEvent(target, java.awt.@event.ItemEvent.ITEM_STATE_CHANGED, + target.getLabel(), (state) + ? java.awt.@event.ItemEvent.SELECTED + : java.awt.@event.ItemEvent.DESELECTED)); + })); + } + + public void setState(bool b) + { + NetToolkit.Invoke(delegate { menuitem.Checked = b; }); + } + } + + internal class NetDragSourceContextPeer : sun.awt.dnd.SunDragSourceContextPeer + { + private static readonly NetDragSourceContextPeer theInstance = new NetDragSourceContextPeer(null); + private bool dragStart = false; + + private NetDragSourceContextPeer(java.awt.dnd.DragGestureEvent dge) : base(dge) + { + } + + public static NetDragSourceContextPeer createDragSourceContextPeer(java.awt.dnd.DragGestureEvent dge) + { + theInstance.setTrigger(dge); + return theInstance; + } + + public override void startSecondaryEventLoop() + { + //NetToolkit.startSecondaryEventLoop(); + } + + public override void quitSecondaryEventLoop() + { + //NetToolkit.quitSecondaryEventLoop(); + } + + internal static new java.awt.dnd.DragSourceContext getDragSourceContext() + { + return theInstance.getDragSourceContextCore(); + } + + internal static NetDragSourceContextPeer getInstance() + { + return theInstance; + } + + internal java.awt.dnd.DragSourceContext getDragSourceContextCore() + { + return base.getDragSourceContext(); + } + + internal new void dragDropFinished(bool success, int operations, int x, int y) + { + if (dragStart) + { + java.awt.EventQueue.invokeLater(Delegates.toRunnable(delegate { + base.dragDropFinished(success, operations, x, y); + })); + } + dragStart = false; + } + + protected internal override void startDrag(java.awt.datatransfer.Transferable trans, long[] formats, Map formatMap) + { + dragStart = true; + + createDragSource(getTrigger().getComponent(), + trans, + getTrigger().getTriggerEvent(), + getTrigger().getSourceAsDragGestureRecognizer().getSourceActions(), + formats, + formatMap); + NetDropTargetContextPeer.setCurrentJVMLocalSourceTransferable(trans); + } + + private long createDragSource(java.awt.Component component, + java.awt.datatransfer.Transferable transferable, + java.awt.@event.InputEvent nativeTrigger, + int actions, + long[] formats, + Map formatMap) + { + java.awt.Component controlOwner = component; + while (controlOwner!=null && (controlOwner.getPeer() == null || controlOwner.getPeer() is sun.awt.NullComponentPeer)) + { + controlOwner = controlOwner.getParent(); + } + if (controlOwner != null) + { + NetComponentPeer peer = controlOwner.getPeer() as NetComponentPeer; + if (peer != null) + { + peer.performedDragDropEffects = DragDropEffects.None; + Control control = peer.Control; + if (control != null) + { + java.awt.dnd.DragSource dragSource = getTrigger().getDragSource(); + IDataObject data = NetDataTransferer.getInstanceImpl().getDataObject(transferable, + NetDataTransferer.adaptFlavorMap(dragSource.getFlavorMap())); + NetToolkit.BeginInvoke(delegate + { + DragDropEffects effects = control.DoDragDrop(data, DragDropEffects.All); + if (effects == DragDropEffects.None && peer.performedDragDropEffects!=DragDropEffects.None) + { + effects = peer.performedDragDropEffects; + } + peer.performedDragDropEffects = DragDropEffects.None; + dragDropFinished(effects != DragDropEffects.None, + NetComponentPeer.getAction(effects), + Control.MousePosition.X, Control.MousePosition.Y); + }); + } + } + } + return 0; + } + + protected internal override void setNativeCursor(long nativeCtxt, java.awt.Cursor c, int cType) + { + + } + } + + internal class NetDropTargetContextPeer : sun.awt.dnd.SunDropTargetContextPeer + { + private IDataObject data; + + internal static NetDropTargetContextPeer getNetDropTargetContextPeer() + { + return new NetDropTargetContextPeer(); + } + + internal int handleEnterMessage(java.awt.Component component, + int x, int y, + int dropAction, + int actions, + long[] formats, + long nativeCtxt) + { + return postDropTargetEvent(component, x, y, dropAction, actions, + formats, nativeCtxt, + sun.awt.dnd.SunDropTargetEvent.MOUSE_ENTERED, + sun.awt.dnd.SunDropTargetContextPeer.DISPATCH_SYNC); + } + + internal void handleExitMessage(java.awt.Component component, + long nativeCtxt) + { + postDropTargetEvent(component, 0, 0, java.awt.dnd.DnDConstants.ACTION_NONE, + java.awt.dnd.DnDConstants.ACTION_NONE, null, nativeCtxt, + sun.awt.dnd.SunDropTargetEvent.MOUSE_EXITED, + sun.awt.dnd.SunDropTargetContextPeer.DISPATCH_SYNC); + } + + internal int handleMotionMessage(java.awt.Component component, + int x, int y, + int dropAction, + int actions, long[] formats, + long nativeCtxt) + { + return postDropTargetEvent(component, x, y, dropAction, actions, + formats, nativeCtxt, + sun.awt.dnd.SunDropTargetEvent.MOUSE_DRAGGED, + sun.awt.dnd.SunDropTargetContextPeer.DISPATCH_SYNC); + } + + internal void handleDropMessage(java.awt.Component component, + int x, int y, + int dropAction, int actions, + long[] formats, + long nativeCtxt, IDataObject data) + { + this.data = data; + postDropTargetEvent(component, x, y, dropAction, actions, + formats, nativeCtxt, + sun.awt.dnd.SunDropTargetEvent.MOUSE_DROPPED, + !sun.awt.dnd.SunDropTargetContextPeer.DISPATCH_SYNC); + } + + internal new int postDropTargetEvent(java.awt.Component component, + int x, int y, + int dropAction, + int actions, + long[] formats, + long nativeCtxt, + int eventID, + bool dispatchType) + { + NetComponentPeer peer = (NetComponentPeer)component.getPeer(); + Control control = peer.Control; + Point screenPt = new Point(x, y); + Point clientPt = control.PointToClient(screenPt); + return base.postDropTargetEvent(component, clientPt.X, clientPt.Y, + dropAction, actions, formats, nativeCtxt, eventID, dispatchType); + } + + protected internal override void doDropDone(bool success, int dropAction, bool isLocal) + { + // Don't do anything as .NET framework already handle the message pump + } + + public override bool isDataFlavorSupported(java.awt.datatransfer.DataFlavor df) + { + if (isTransferableJVMLocal()) + return base.isDataFlavorSupported(df); + return base.isDataFlavorSupported(df); + } + + public override object getTransferData(java.awt.datatransfer.DataFlavor df) + { + if (isTransferableJVMLocal()) + return base.getTransferData(df); + return new NetClipboardTransferable(data).getTransferData(df); + } + + protected internal override object getNativeData(long l) + { + throw new NotImplementedException(); + } + } + + internal class NetMouseDragGestureRecognizer : java.awt.dnd.MouseDragGestureRecognizer + { + protected static int motionThreshold; + + protected static readonly int ButtonMask = java.awt.@event.InputEvent.BUTTON1_DOWN_MASK | + java.awt.@event.InputEvent.BUTTON2_DOWN_MASK | + java.awt.@event.InputEvent.BUTTON3_DOWN_MASK; + + public NetMouseDragGestureRecognizer(java.awt.dnd.DragSource source, java.awt.Component component1, int actions, + java.awt.dnd.DragGestureListener listener) : + base(source, component1, actions, listener) + { + } + + protected int mapDragOperationFromModifiers(java.awt.@event.MouseEvent e) + { + int mods = e.getModifiersEx(); + int btns = mods & ButtonMask; + + // Prohibit multi-button drags. + if (!(btns == java.awt.@event.InputEvent.BUTTON1_DOWN_MASK || + btns == java.awt.@event.InputEvent.BUTTON2_DOWN_MASK || + btns == java.awt.@event.InputEvent.BUTTON3_DOWN_MASK)) + { + return java.awt.dnd.DnDConstants.ACTION_NONE; + } + + return + sun.awt.dnd.SunDragSourceContextPeer.convertModifiersToDropAction(mods, + getSourceActions()); + } + + public override void mouseClicked(java.awt.@event.MouseEvent e) + { + // do nothing + } + + public override void mousePressed(java.awt.@event.MouseEvent e) + { + events.clear(); + + if (mapDragOperationFromModifiers(e) != java.awt.dnd.DnDConstants.ACTION_NONE) + { + try + { + motionThreshold = java.awt.dnd.DragSource.getDragThreshold(); + } + catch + { + motionThreshold = 5; + } + appendEvent(e); + } + } + + public override void mouseReleased(java.awt.@event.MouseEvent e) + { + events.clear(); + } + + public override void mouseEntered(java.awt.@event.MouseEvent e) + { + events.clear(); + } + + public override void mouseExited(java.awt.@event.MouseEvent e) + { + if (!events.isEmpty()) + { // gesture pending + int dragAction = mapDragOperationFromModifiers(e); + + if (dragAction == java.awt.dnd.DnDConstants.ACTION_NONE) + { + events.clear(); + } + } + } + + public override void mouseDragged(java.awt.@event.MouseEvent e) + { + if (!events.isEmpty()) + { // gesture pending + int dop = mapDragOperationFromModifiers(e); + + if (dop == java.awt.dnd.DnDConstants.ACTION_NONE) + { + return; + } + + java.awt.@event.MouseEvent trigger = (java.awt.@event.MouseEvent)events.get(0); + + + java.awt.Point origin = trigger.getPoint(); + java.awt.Point current = e.getPoint(); + + int dx = java.lang.Math.abs(origin.x - current.x); + int dy = java.lang.Math.abs(origin.y - current.y); + + if (dx > motionThreshold || dy > motionThreshold) + { + fireDragGestureRecognized(dop, ((java.awt.@event.MouseEvent)getTriggerEvent()).getPoint()); + } + else + appendEvent(e); + } + } + + } + + class NetInputMethodDescriptor : java.awt.im.spi.InputMethodDescriptor + { + public java.awt.im.spi.InputMethod createInputMethod() + { + throw new NotImplementedException(); + } + + public Locale[] getAvailableLocales() + { + // TODO Feature with .NET 3.0 available + //IEnumerable languages = System.Windows.Input.InputLanguageManager.AvailableInputLanguages; + // as a hack we return the default locale + return new Locale[]{Locale.getDefault()}; + } + + public string getInputMethodDisplayName(Locale inputLocale, Locale displayLanguage) + { + // copied from WInputMethodDescriptor + + // We ignore the input locale. + // When displaying for the default locale, rely on the localized AWT properties; + // for any other locale, fall back to English. + String name = "System Input Methods"; + if (Locale.getDefault().equals(displayLanguage)) + { + name = java.awt.Toolkit.getProperty("AWT.HostInputMethodDisplayName", name); + } + return name; + } + + public java.awt.Image getInputMethodIcon(Locale l) + { + //WInputMethodDescriptor return also ever null + return null; + } + + public bool hasDynamicLocaleList() + { + // Java return also true + return true; + } + } + + class NetCustomCursor : java.awt.Cursor + { + private Cursor cursor; + public Cursor Cursor + { + get { return cursor; } + } + + internal NetCustomCursor(java.awt.Image cursorIm, java.awt.Point hotSpot, String name) // throws IndexOutOfBoundsException + : base(name) + { + java.awt.Toolkit toolkit = java.awt.Toolkit.getDefaultToolkit(); + + // Make sure image is fully loaded. + java.awt.Component c = new java.awt.Canvas(); // for its imageUpdate method + java.awt.MediaTracker tracker = new java.awt.MediaTracker(c); + tracker.addImage(cursorIm, 0); + try + { + tracker.waitForAll(); + } + catch (java.lang.InterruptedException) + { + } + int width = cursorIm.getWidth(c); + int height = cursorIm.getHeight(c); + + // Fix for bug 4212593 The Toolkit.createCustomCursor does not + // check absence of the image of cursor + // If the image is invalid, the cursor will be hidden (made completely + // transparent). In this case, getBestCursorSize() will adjust negative w and h, + // but we need to set the hotspot inside the image here. + if (tracker.isErrorAny() || width < 0 || height < 0) + { + hotSpot.x = hotSpot.y = 0; + } + + // Scale image to nearest supported size. + java.awt.Dimension nativeSize = toolkit.getBestCursorSize(width, height); + if (nativeSize.width != width || nativeSize.height != height) + { + cursorIm = cursorIm.getScaledInstance(nativeSize.width, + nativeSize.height, + java.awt.Image.SCALE_DEFAULT); + width = nativeSize.width; + height = nativeSize.height; + } + + // Verify that the hotspot is within cursor bounds. + if (hotSpot.x >= width || hotSpot.y >= height || hotSpot.x < 0 || hotSpot.y < 0) + { + throw new ArgumentException("invalid hotSpot"); + } + + Bitmap bitmap = J2C.ConvertImage(cursorIm); + IntPtr hIcon = bitmap.GetHicon(); + cursor = new Cursor(hIcon); + } + } + + sealed class NetLightweightComponentPeer : NetComponentPeer, java.awt.peer.LightweightPeer + { + public NetLightweightComponentPeer(java.awt.Component target) + : base(target) + { + } + + protected override Control CreateControl() + { + throw new NotImplementedException(); + } + } + + sealed class NetLightweightContainerPeer : NetContainerPeer, java.awt.peer.LightweightPeer + { + public NetLightweightContainerPeer(java.awt.Container target) + : base(target) + { + } + } + + abstract class NetComponentPeer : java.awt.peer.ComponentPeer + { + internal bool eraseBackground = true; + + public abstract void applyShape(sun.java2d.pipe.Region r); + public abstract bool canDetermineObscurity(); + public abstract int checkImage(java.awt.Image i1, int i2, int i3, java.awt.image.ImageObserver io); + public abstract void coalescePaintEvent(java.awt.@event.PaintEvent pe); + public abstract void createBuffers(int i, java.awt.BufferCapabilities bc); + public abstract java.awt.Image createImage(int i1, int i2); + public abstract java.awt.Image createImage(java.awt.image.ImageProducer ip); + public abstract java.awt.image.VolatileImage createVolatileImage(int i1, int i2); + public abstract void destroyBuffers(); + public abstract void disable(); + public abstract void dispose(); + public abstract void enable(); + public abstract void flip(java.awt.BufferCapabilities.FlipContents bcfc); + public abstract java.awt.Image getBackBuffer(); + public abstract java.awt.Rectangle getBounds(); + public abstract java.awt.image.ColorModel getColorModel(); + public abstract java.awt.FontMetrics getFontMetrics(java.awt.Font f); + public abstract java.awt.Graphics getGraphics(); + public abstract java.awt.GraphicsConfiguration getGraphicsConfiguration(); + public abstract java.awt.Point getLocationOnScreen(); + public abstract java.awt.Dimension getMinimumSize(); + public abstract java.awt.Dimension getPreferredSize(); + public abstract java.awt.Toolkit getToolkit(); + public abstract void handleEvent(java.awt.AWTEvent awte); + public abstract bool handlesWheelScrolling(); + public abstract void hide(); + public abstract bool isFocusable(); + public abstract bool isObscured(); + public abstract bool isReparentSupported(); + public abstract void layout(); + public abstract java.awt.Dimension minimumSize(); + public abstract void paint(java.awt.Graphics g); + public abstract java.awt.Dimension preferredSize(); + public abstract bool prepareImage(java.awt.Image i1, int i2, int i3, java.awt.image.ImageObserver io); + public abstract void print(java.awt.Graphics g); + public abstract void repaint(long l, int i1, int i2, int i3, int i4); + public abstract void reparent(java.awt.peer.ContainerPeer cp); + public abstract bool requestFocus(java.awt.Component c, bool b1, bool b2, long l, CausedFocusEvent.Cause cfec); + public abstract void reshape(int i1, int i2, int i3, int i4); + public abstract void setBackground(java.awt.Color c); + public abstract void setBounds(int i1, int i2, int i3, int i4, int i5); + public abstract void setEnabled(bool b); + public abstract void setFont(java.awt.Font f); + public abstract void setForeground(java.awt.Color c); + public abstract void setVisible(bool b); + public abstract void show(); + public abstract void updateCursorImmediately(); + public abstract void flip(int x1, int y1, int x2, int y2, java.awt.BufferCapabilities.FlipContents flipAction); + public abstract void setZOrder(java.awt.peer.ComponentPeer above); + public abstract bool updateGraphicsData(java.awt.GraphicsConfiguration gc); + + internal DragDropEffects performedDragDropEffects = DragDropEffects.None; + + internal abstract Control Control { get; } + internal abstract java.awt.Component Target { get; } + + internal abstract int getInsetsLeft(); + internal abstract int getInsetsTop(); + + internal static int getAction(DragDropEffects effects) + { + int actions = java.awt.dnd.DnDConstants.ACTION_NONE; + switch (effects) + { + case DragDropEffects.None: + actions = java.awt.dnd.DnDConstants.ACTION_NONE; + break; + case DragDropEffects.Copy: + actions = java.awt.dnd.DnDConstants.ACTION_COPY; + break; + case DragDropEffects.Move: + actions = java.awt.dnd.DnDConstants.ACTION_MOVE; + break; + case DragDropEffects.Move | DragDropEffects.Copy: + actions = java.awt.dnd.DnDConstants.ACTION_COPY_OR_MOVE; + break; + case DragDropEffects.Link: + actions = java.awt.dnd.DnDConstants.ACTION_LINK; + break; + } + return actions; + } + + internal static int GetMouseEventModifiers(MouseEventArgs ev) + { + int modifiers = GetModifiers(Control.ModifierKeys); + //Which button was pressed or released, because it can only one that it is a switch + MouseButtons button = ev.Button; + switch (button) + { + case MouseButtons.Left: + modifiers |= java.awt.@event.InputEvent.BUTTON1_MASK; + break; + case MouseButtons.Middle: + modifiers |= java.awt.@event.InputEvent.BUTTON2_MASK; + break; + case MouseButtons.Right: + modifiers |= java.awt.@event.InputEvent.BUTTON3_MASK; + break; + } + return modifiers; + } + + internal static int GetModifiers(Keys keys) + { + int modifiers = 0; + if ((keys & Keys.Shift) != 0) + { + modifiers |= java.awt.@event.InputEvent.SHIFT_DOWN_MASK; + } + switch (keys & (Keys.Control | Keys.Alt)) + { + case Keys.Control: + modifiers |= java.awt.@event.InputEvent.CTRL_DOWN_MASK; + break; + case Keys.Alt: + modifiers |= java.awt.@event.InputEvent.ALT_DOWN_MASK; + break; + case Keys.Control | Keys.Alt: + modifiers |= java.awt.@event.InputEvent.ALT_GRAPH_DOWN_MASK; + break; + } + if ((Control.MouseButtons & MouseButtons.Left) != 0) + { + modifiers |= java.awt.@event.InputEvent.BUTTON1_DOWN_MASK; + } + if ((Control.MouseButtons & MouseButtons.Middle) != 0) + { + modifiers |= java.awt.@event.InputEvent.BUTTON2_DOWN_MASK; + } + if ((Control.MouseButtons & MouseButtons.Right) != 0) + { + modifiers |= java.awt.@event.InputEvent.BUTTON3_DOWN_MASK; + } + return modifiers; + } + + internal static int GetButton(MouseEventArgs e) + { + if ((e.Button & MouseButtons.Left) != 0) + { + return java.awt.@event.MouseEvent.BUTTON1; + } + else if ((e.Button & MouseButtons.Middle) != 0) + { + return java.awt.@event.MouseEvent.BUTTON2; + } + else if ((e.Button & MouseButtons.Right) != 0) + { + return java.awt.@event.MouseEvent.BUTTON3; + } + else + { + return java.awt.@event.MouseEvent.NOBUTTON; + } + } + + internal static NetComponentPeer FromControl(Control control) + { + return (NetComponentPeer)control.Tag; + } + } + + abstract class NetComponentPeer : NetComponentPeer + where T : java.awt.Component + where C : Control + { + protected static readonly java.awt.Font defaultFont = new java.awt.Font(java.awt.Font.DIALOG, java.awt.Font.PLAIN, 12); + internal readonly T target; + internal readonly C control; + private bool isMouseClick; + private bool isDoubleClick; + private bool isPopupMenu; + private int oldWidth = -1; + private int oldHeight = -1; + private bool sm_suppressFocusAndActivation; + //private bool m_callbacksEnabled; + //private int m_validationNestCount; + private int serialNum = 0; + private bool isLayouting = false; + private bool paintPending = false; + private RepaintArea paintArea; + private java.awt.Font font; + private java.awt.Color foreground; + private java.awt.Color background; + private volatile bool disposed; + private NetDropTargetContextPeer dropTargetPeer; + + internal override Control Control + { + get { return control; } + } + + internal override java.awt.Component Target + { + get { return target; } + } + + public NetComponentPeer(T target) + { + this.target = target; + this.paintArea = new RepaintArea(); + java.awt.Container parent = SunToolkit.getNativeContainer(target); + NetComponentPeer parentPeer = (NetComponentPeer)NetToolkit.targetToPeer(parent); + control = Create(parentPeer); + // fix for 5088782: check if window object is created successfully + //checkCreation(); + //this.winGraphicsConfig = (NetGraphicsConfiguration)getGraphicsConfiguration(); + /* + this.surfaceData = + winGraphicsConfig.createSurfaceData(this, numBackBuffers); + */ + initialize(); + start(); // Initialize enable/disable state, turn on callbacks + } + + protected virtual void initialize() + { + if (target.isVisible()) + { + show(); // the wnd starts hidden + } + java.awt.Color fg = target.getForeground(); + if (fg != null) + { + setForeground(fg); + } + // Set background color in C++, to avoid inheriting a parent's color. + java.awt.Font f = target.getFont(); + if (f != null) + { + setFont(f); + } + if (!target.isEnabled()) + { + disable(); + } + java.awt.Rectangle r = target.getBounds(); + setBounds(r.x, r.y, r.width, r.height, java.awt.peer.ComponentPeer.__Fields.SET_BOUNDS); + + // this is from initialize() in WCanvasPeer.java + eraseBackground = !SunToolkit.getSunAwtNoerasebackground(); + if (!PaintEventDispatcher.getPaintEventDispatcher().shouldDoNativeBackgroundErase(target)) + { + eraseBackground = false; + } + } + + void start() + { + NetToolkit.BeginInvoke(delegate + { + hookEvents(); + // JDK native code also disables the window here, but since that is already done in initialize(), + // I don't see the point + EnableCallbacks(true); + control.Invalidate(); + control.Update(); + }); + } + + void EnableCallbacks(bool enabled) + { + //m_callbacksEnabled = enabled; + } + + private C Create(NetComponentPeer parent) + { + C control = CreateControl(); + control.Tag = this; + if (parent != null) + { + Form form = control as Form; + if (form != null) + { + form.Owner = parent.Control.FindForm(); + } + else + { + control.Parent = parent.Control; + } + } + NetToolkit.CreateNative(control); + return control; + } + + protected abstract C CreateControl(); + + void pShow() + { + NetToolkit.BeginInvoke(delegate { control.Visible = true; }); + } + + void Enable(bool enable) + { + sm_suppressFocusAndActivation = true; + control.Enabled = enable; + sm_suppressFocusAndActivation = false; + } + + internal virtual void hookEvents() + { + // TODO we really only should hook these events when they are needed... + control.KeyDown += new KeyEventHandler(OnKeyDown); + control.KeyUp += new KeyEventHandler(OnKeyUp); + control.KeyPress += new KeyPressEventHandler(OnKeyPress); + control.MouseMove += new MouseEventHandler(OnMouseMove); + control.MouseDown += new MouseEventHandler(OnMouseDown); + control.MouseWheel += new MouseEventHandler(OnMouseWheel); + control.Click += new EventHandler(OnClick); + control.DoubleClick += new EventHandler(OnDoubleClick); + control.MouseUp += new MouseEventHandler(OnMouseUp); + control.MouseEnter += new EventHandler(OnMouseEnter); + control.MouseLeave += new EventHandler(OnMouseLeave); + control.GotFocus += new EventHandler(OnGotFocus); + control.LostFocus += new EventHandler(OnLostFocus); + //control.Leave += new EventHandler(OnBoundsChanged); + control.Paint += new PaintEventHandler(OnPaint); + control.ContextMenu = new ContextMenu(); + control.ContextMenu.Popup += new EventHandler(OnPopupMenu); + control.AllowDrop = true; + control.DragDrop += new DragEventHandler(OnDragDrop); + control.DragOver += new DragEventHandler(OnDragOver); + control.DragLeave += new EventHandler(OnDragLeave); + control.DragEnter += new DragEventHandler(OnDragEnter); + control.QueryContinueDrag += new QueryContinueDragEventHandler(OnQueryContinueDrag); + } + + internal virtual void unhookEvents() + { + control.KeyDown -= new KeyEventHandler(OnKeyDown); + control.KeyUp -= new KeyEventHandler(OnKeyUp); + control.KeyPress -= new KeyPressEventHandler(OnKeyPress); + control.MouseMove -= new MouseEventHandler(OnMouseMove); + control.MouseDown -= new MouseEventHandler(OnMouseDown); + control.MouseWheel -= new MouseEventHandler(OnMouseWheel); + control.Click -= new EventHandler(OnClick); + control.DoubleClick -= new EventHandler(OnDoubleClick); + control.MouseUp -= new MouseEventHandler(OnMouseUp); + control.MouseEnter -= new EventHandler(OnMouseEnter); + control.MouseLeave -= new EventHandler(OnMouseLeave); + control.GotFocus -= new EventHandler(OnGotFocus); + control.LostFocus -= new EventHandler(OnLostFocus); + //control.Leave -= new EventHandler(OnBoundsChanged); + control.Paint -= new PaintEventHandler(OnPaint); + control.DragDrop -= new DragEventHandler(OnDragDrop); + control.DragOver -= new DragEventHandler(OnDragOver); + control.DragLeave -= new EventHandler(OnDragLeave); + control.DragEnter -= new DragEventHandler(OnDragEnter); + if (control.ContextMenu != null) + control.ContextMenu.Popup -= new EventHandler(OnPopupMenu); + } + + protected void SendEvent(java.awt.AWTEvent evt) + { + postEvent(evt); + } + + /// + /// Get the left insets of the .NET Window. + /// In .NET the coordinate of a window start on the most left, top point with 0,0 + /// In Java the most left, top point with 0,0 is in the detail area of the window. + /// In all not Windows Component this return ever 0. + /// + /// + internal override int getInsetsLeft() + { + return 0; + } + + /// + /// Get the top insets of the .NET Window. + /// In .NET the coordinate of a window start on the most left, top point with 0,0 + /// In Java the most left, top point with 0,0 is in the detail area of the window. + /// In all not Windows Component this return ever 0. + /// + /// + internal override int getInsetsTop() + { + return 0; + } + + + /// + /// .NET calculates the offset relative to the detail area. + /// Java uses the top left point of a window. + /// That means we must compensate the coordinate of a component + /// if the parent is a window, frame or dialog. + /// + /// The offset of the details area in the parent + private Point getParentOffset() + { + if (!(target is java.awt.Window)) + { + java.awt.Container parent = target.getParent(); + if (parent != null) + { + NetComponentPeer peer = parent.getPeer() as NetComponentPeer; + if (peer != null) + { + return new Point(peer.getInsetsLeft(), peer.getInsetsTop()); + } + } + } + return new Point(); + } + + private void OnPaint(object sender, PaintEventArgs e) + { + //CheckFontSmoothingSettings(GetHWnd()); + /* Set draw state */ + //SetDrawState(GetDrawState() | JAWT_LOCK_CLIP_CHANGED); + WmPaint(e.Graphics, e.ClipRectangle); + } + + private void WmPaint(Graphics g, Rectangle r) + { + handlePaint(r.X + getInsetsLeft(), r.Y + getInsetsTop(), r.Width, r.Height); + } + + /* Invoke a paint() method call on the target, without clearing the + * damaged area. This is normally called by a native control after + * it has painted itself. + * + * NOTE: This is called on the privileged toolkit thread. Do not + * call directly into user code using this thread! + */ + private void handlePaint(int x, int y, int w, int h) + { + postPaintIfNecessary(x, y, w, h); + } + + private void postPaintIfNecessary(int x, int y, int w, int h) + { + if (!AWTAccessor.getComponentAccessor().getIgnoreRepaint(target)) + { + java.awt.@event.PaintEvent evt = PaintEventDispatcher.getPaintEventDispatcher().createPaintEvent(target, x, y, w, h); + if (evt != null) + { + postEvent(evt); + } + } + } + + private static int MapKeyCode(Keys key) + { + switch (key) + { + case Keys.Delete: + return java.awt.@event.KeyEvent.VK_DELETE; + + case Keys.Enter: + return java.awt.@event.KeyEvent.VK_ENTER; + + default: + return (int)key; + } + } + + private void OnKeyDown(object sender, KeyEventArgs e) + { + long when = java.lang.System.currentTimeMillis(); + int modifiers = GetModifiers(e.Modifiers); + int keyCode = MapKeyCode(e.KeyCode); + // TODO set keyChar + char keyChar = ' '; + int keyLocation = java.awt.@event.KeyEvent.KEY_LOCATION_STANDARD; + java.awt.EventQueue.invokeLater(Delegates.toRunnable(delegate { + postEvent(new java.awt.@event.KeyEvent(target, java.awt.@event.KeyEvent.KEY_PRESSED, when, modifiers, keyCode, keyChar, keyLocation)); + })); + } + + private void OnQueryContinueDrag(object sender, QueryContinueDragEventArgs e) + { + } + + private void OnDragEnter(object sender, DragEventArgs e) + { + IDataObject obj = e.Data; + long[] formats = NetDataTransferer.getInstanceImpl().getClipboardFormatCodes(obj.GetFormats()); + dropTargetPeer = NetDropTargetContextPeer.getNetDropTargetContextPeer(); + int actions = dropTargetPeer.handleEnterMessage(target, e.X, e.Y, getDropAction(e.AllowedEffect, e.KeyState), getAction(e.AllowedEffect), + formats, 0); + e.Effect = getDragDropEffects(actions); + } + + private void OnDragOver(object sender, DragEventArgs e) + { + IDataObject obj = e.Data; + long[] formats = NetDataTransferer.getInstanceImpl().getClipboardFormatCodes(obj.GetFormats()); + dropTargetPeer = NetDropTargetContextPeer.getNetDropTargetContextPeer(); + int actions = dropTargetPeer.handleMotionMessage(target, e.X, e.Y, getDropAction(e.AllowedEffect, e.KeyState), getAction(e.AllowedEffect), + formats, 0); + e.Effect = getDragDropEffects(actions); + } + + private void OnDragLeave(object sender, EventArgs e) + { + if (dropTargetPeer!=null) + dropTargetPeer.handleExitMessage(target, 0); + dropTargetPeer = null; + } + + private void OnDragDrop(object sender, DragEventArgs e) + { + IDataObject obj = e.Data; + long[] formats = NetDataTransferer.getInstanceImpl().getClipboardFormatCodes(obj.GetFormats()); + int actions = getAction(e.Effect); + if (dropTargetPeer != null) + dropTargetPeer.handleDropMessage(target, e.X, e.Y, getAction(e.Effect), getAction(e.AllowedEffect), + formats, 0, e.Data); + NetDragSourceContextPeer.getInstance().dragDropFinished(true, actions, e.X, e.Y); + performedDragDropEffects = e.Effect; + dropTargetPeer = null; + } + + private static DragDropEffects getDragDropEffects(int actions) + { + switch(actions) + { + case java.awt.dnd.DnDConstants.ACTION_COPY: + return DragDropEffects.Copy; + case java.awt.dnd.DnDConstants.ACTION_MOVE: + return DragDropEffects.Move; + case java.awt.dnd.DnDConstants.ACTION_COPY_OR_MOVE: + return DragDropEffects.Move | DragDropEffects.Copy; + case java.awt.dnd.DnDConstants.ACTION_LINK: + return DragDropEffects.Link; + default: + return DragDropEffects.None; + } + } + + private static int getDropAction(DragDropEffects effects, int keyState) + { + int ret = java.awt.dnd.DnDConstants.ACTION_NONE; + const int MK_CONTROL = 0x8; + const int MK_SHIFT = 0x4; +// const int WM_MOUSEWHEEL = 0x20A; +// const int MK_LBUTTON = 0x1; +// const int MK_MBUTTON = 0x10; +// const int MK_RBUTTON = 0x2; +// const int MK_XBUTTON1 = 0x20; +// const int MK_XBUTTON2 = 0x40; + switch (keyState & (MK_CONTROL | MK_SHIFT)) + { + case MK_CONTROL: + if ((effects & DragDropEffects.Copy) == DragDropEffects.Copy) + ret = java.awt.dnd.DnDConstants.ACTION_COPY; + else + ret = java.awt.dnd.DnDConstants.ACTION_NONE; + break; + + case MK_CONTROL | MK_SHIFT: + if ((effects & DragDropEffects.Link) == DragDropEffects.Link) + ret = java.awt.dnd.DnDConstants.ACTION_LINK; + else + ret = java.awt.dnd.DnDConstants.ACTION_NONE; + break; + + case MK_SHIFT: + if ((effects & DragDropEffects.Move) == DragDropEffects.Move) + ret = java.awt.dnd.DnDConstants.ACTION_MOVE; + else + ret = java.awt.dnd.DnDConstants.ACTION_NONE; + break; + + default: + if ((effects & DragDropEffects.Move) == DragDropEffects.Move) + { + ret = java.awt.dnd.DnDConstants.ACTION_MOVE; + } + else if ((effects & DragDropEffects.Copy) == DragDropEffects.Copy) + { + ret = java.awt.dnd.DnDConstants.ACTION_COPY; + } + else if ((effects & DragDropEffects.Link) == DragDropEffects.Link) + { + ret = java.awt.dnd.DnDConstants.ACTION_LINK; + } + break; + } + + return ret; + } + + private void OnKeyUp(object sender, KeyEventArgs e) + { + long when = java.lang.System.currentTimeMillis(); + int modifiers = GetModifiers(e.Modifiers); + int keyCode = MapKeyCode(e.KeyCode); + // TODO set keyChar + char keyChar = ' '; + int keyLocation = java.awt.@event.KeyEvent.KEY_LOCATION_STANDARD; + java.awt.EventQueue.invokeLater(Delegates.toRunnable(delegate { + postEvent(new java.awt.@event.KeyEvent(target, java.awt.@event.KeyEvent.KEY_RELEASED, when, modifiers, keyCode, keyChar, keyLocation)); + })); + } + + protected virtual void OnKeyPress(object sender, KeyPressEventArgs e) + { + long when = java.lang.System.currentTimeMillis(); + int modifiers = GetModifiers(Control.ModifierKeys); + int keyCode = java.awt.@event.KeyEvent.VK_UNDEFINED; + char keyChar = e.KeyChar; + int keyLocation = java.awt.@event.KeyEvent.KEY_LOCATION_UNKNOWN; + java.awt.EventQueue.invokeLater(Delegates.toRunnable(delegate { + postEvent(new java.awt.@event.KeyEvent(target, java.awt.@event.KeyEvent.KEY_TYPED, when, modifiers, keyCode, keyChar, keyLocation)); + })); + } + + private void postMouseEvent(MouseEventArgs ev, int id, int clicks) + { + long when = java.lang.System.currentTimeMillis(); + int modifiers = GetMouseEventModifiers(ev); + int button = GetButton(ev); + int clickCount = clicks; + int x = ev.X + getInsetsLeft(); //The Inset correctur is needed for Window and extended classes + int y = ev.Y + getInsetsTop(); + bool isPopup = isPopupMenu; + java.awt.EventQueue.invokeLater(Delegates.toRunnable(delegate { + postEvent(new java.awt.@event.MouseEvent(target, id, when, modifiers, x, y, clickCount, isPopup, button)); + })); + isPopupMenu = false; + } + + private void postMouseEvent(EventArgs ev, int id) + { + long when = java.lang.System.currentTimeMillis(); + int modifiers = GetModifiers(Control.ModifierKeys); + int button = 0; + int clickCount = 0; + int x = Control.MousePosition.X - control.Location.X; + int y = Control.MousePosition.Y - control.Location.Y; + bool isPopup = isPopupMenu; + java.awt.EventQueue.invokeLater(Delegates.toRunnable(delegate { + postEvent(new java.awt.@event.MouseEvent(target, id, when, modifiers, x, y, clickCount, isPopup, button)); + })); + isPopupMenu = false; + } + + private void postMouseWheelEvent(EventArgs ev, int id, int delta) + { + long when = java.lang.System.currentTimeMillis(); + int modifiers = GetModifiers(Control.ModifierKeys); + int scrollAmount = -delta * SystemInformation.MouseWheelScrollLines / 120; + int clickCount = 0; + int x = Control.MousePosition.X - control.Location.X; + int y = Control.MousePosition.Y - control.Location.Y; + bool isPopup = isPopupMenu; + java.awt.EventQueue.invokeLater(Delegates.toRunnable(delegate + { + postEvent(new java.awt.@event.MouseWheelEvent(target, id, when, modifiers, x, y, clickCount, isPopup, java.awt.@event.MouseWheelEvent.WHEEL_UNIT_SCROLL, scrollAmount, scrollAmount)); + })); + } + + protected virtual void OnMouseMove(object sender, MouseEventArgs ev) + { + if((ev.Button & (MouseButtons.Left | MouseButtons.Right)) != 0) + { + postMouseEvent(ev, java.awt.@event.MouseEvent.MOUSE_DRAGGED, ev.Clicks); + } + else + { + postMouseEvent(ev, java.awt.@event.MouseEvent.MOUSE_MOVED, ev.Clicks); + } + } + + protected virtual void OnMouseDown(object sender, MouseEventArgs ev) + { + isMouseClick = false; + isDoubleClick = false; + isPopupMenu = false; + postMouseEvent(ev, java.awt.@event.MouseEvent.MOUSE_PRESSED, ev.Clicks); + } + + private void OnMouseWheel(object sender, MouseEventArgs ev) + { + postMouseWheelEvent(ev, java.awt.@event.MouseEvent.MOUSE_WHEEL, ev.Delta); + } + + private void OnClick(object sender, EventArgs ev) + { + isMouseClick = true; + } + + private void OnDoubleClick(object sender, EventArgs ev) + { + isDoubleClick = true; + } + + private void OnMouseUp(object sender, MouseEventArgs ev) + { + postMouseEvent(ev, java.awt.@event.MouseEvent.MOUSE_RELEASED, ev.Clicks); + if (isMouseClick || isDoubleClick) // there can only be an Click OR an DoubleClick event - both count as click here + { + //We make our own mouse click event because the event order is different in .NET + //in .NET the click occured before MouseUp + int clicks = ev.Clicks; + if (isDoubleClick) + { + clicks = 2; + } + postMouseEvent(ev, java.awt.@event.MouseEvent.MOUSE_CLICKED, clicks); + } + isMouseClick = false; + } + + private void OnMouseEnter(object sender, EventArgs ev) + { + postMouseEvent(ev, java.awt.@event.MouseEvent.MOUSE_ENTERED); + } + + private void OnMouseLeave(object sender, EventArgs ev) + { + postMouseEvent(ev, java.awt.@event.MouseEvent.MOUSE_EXITED); + } + + private void OnGotFocus(object sender, EventArgs e) + { + if (sm_suppressFocusAndActivation) + { + return; + } + java.awt.EventQueue.invokeLater(Delegates.toRunnable(delegate { + postEvent(new java.awt.@event.FocusEvent(target, java.awt.@event.FocusEvent.FOCUS_GAINED)); + })); + } + + private void OnLostFocus(object sender, EventArgs e) + { + java.awt.EventQueue.invokeLater(Delegates.toRunnable(delegate { + postEvent(new java.awt.@event.FocusEvent(target, java.awt.@event.FocusEvent.FOCUS_LOST)); + })); + } + + /* + * Called from native code (on Toolkit thread) in order to + * dynamically layout the Container during resizing + */ + internal void dynamicallyLayoutContainer() { + // If we got the WM_SIZING, this must be a Container, right? + // In fact, it must be the top-level Container. + //if (log.isLoggable(Level.FINE)) { + // java.awt.Container parent = NetToolkit.getNativeContainer((java.awt.Component)target); + // if (parent != null) { + // log.log(Level.FINE, "Assertion (parent == null) failed"); + // } + //} + java.awt.Container cont = (java.awt.Container)(object)target; + + NetToolkit.executeOnEventHandlerThread(cont, Delegates.toRunnable(delegate { + // Discarding old paint events doesn't seem to be necessary. + cont.invalidate(); + cont.validate(); + + //if (surfaceData instanceof OGLSurfaceData) { + // // 6290245: When OGL is enabled, it is necessary to + // // replace the SurfaceData for each dynamic layout + // // request so that the OGL viewport stays in sync + // // with the window bounds. + // try { + // replaceSurfaceData(); + // } catch (InvalidPipeException e) { + // // REMIND: this is unlikely to occur for OGL, but + // // what do we do if surface creation fails? + // } + //} + + // Forcing a paint here doesn't seem to be necessary. + // paintDamagedAreaImmediately(); + })); + } + + /* + * Paints any portion of the component that needs updating + * before the call returns (similar to the Win32 API UpdateWindow) + */ + internal void paintDamagedAreaImmediately() + { + // force Windows to send any pending WM_PAINT events so + // the damage area is updated on the Java side + updateWindow(); + // make sure paint events are transferred to main event queue + // for coalescing + NetToolkit.flushPendingEvents(); + // paint the damaged area + paintArea.paint(target, shouldClearRectBeforePaint()); + } + + private void updateWindow() + { + NetToolkit.BeginInvoke(delegate + { + control.Update(); + }); + } + + /* override and return false on components that DO NOT require + a clearRect() before painting (i.e. native components) */ + public virtual bool shouldClearRectBeforePaint() + { + return true; + } + + private void OnPopupMenu(object sender, EventArgs ev) + { + isPopupMenu = true; + } + + /* + * Post an event. Queue it for execution by the callback thread. + */ + internal void postEvent(java.awt.AWTEvent evt) + { + NetToolkit.postEvent(NetToolkit.targetToAppContext(target), evt); + } + + // Routines to support deferred window positioning. + public void beginLayout() + { + // Skip all painting till endLayout + isLayouting = true; + } + + public void endLayout() + { + if (!paintArea.isEmpty() && !paintPending && + !target.getIgnoreRepaint()) + { + // if not waiting for native painting repaint damaged area + postEvent(new java.awt.@event.PaintEvent(target, java.awt.@event.PaintEvent.PAINT, new java.awt.Rectangle())); + } + isLayouting = false; + } + + public void beginValidate() + { + // Invoke(delegate + // { + // if (m_validationNestCount == 0) + // { + // m_hdwp = BeginDeferWindowPos(); + // } + // m_validationNestCount++; + // }); + } + + public void endValidate() + { + // Invoke(delegate + // { + // m_validationNestCount--; + // if (m_validationNestCount == 0) { + // // if this call to EndValidate is not nested inside another + // // Begin/EndValidate pair, end deferred window positioning + // ::EndDeferWindowPos(m_hdwp); + // m_hdwp = NULL; + // } + // }); + } + + // Returns true if we are inside begin/endLayout and + // are waiting for native painting + public bool isPaintPending() + { + return paintPending && isLayouting; + } + + public override int checkImage(java.awt.Image img, int width, int height, java.awt.image.ImageObserver ob) + { + return getToolkit().checkImage(img, width, height, ob); + } + + public override java.awt.Image createImage(java.awt.image.ImageProducer prod) + { + return new sun.awt.image.ToolkitImage(prod); + } + + public override java.awt.Image createImage(int width, int height) + { + return new java.awt.image.BufferedImage(width, height, java.awt.image.BufferedImage.TYPE_INT_ARGB); + } + + public override void disable() + { + NetToolkit.BeginInvoke(delegate { Enable( false ); }); + } + + public override void dispose() + { + bool callDisposed = true; + lock(this) + { + if (disposed) + callDisposed = false; + disposed = true; + } + if (callDisposed) + { + disposeImpl(); + } + } + + protected virtual void disposeImpl() + { + NetToolkit.targetDisposedPeer(target, this); + NetToolkit.Invoke(nativeDispose); + } + + protected virtual void nativeDispose() + { + unhookEvents(); + control.Dispose(); + } + + public override void enable() + { + NetToolkit.BeginInvoke(delegate { Enable(true); }); + } + + public override java.awt.image.ColorModel getColorModel() + { + //we return the default ColorModel because this causes the least problems with conversions + return java.awt.image.ColorModel.getRGBdefault(); + } + + public override java.awt.FontMetrics getFontMetrics(java.awt.Font f) + { + return sun.font.FontDesignMetrics.getMetrics(f); + } + + public override java.awt.Graphics getGraphics() + { + if (!control.IsDisposed) + { + /* Fix for bug 4746122. Color and Font shouldn't be null */ + java.awt.Color bgColor = background; + if (bgColor == null) + { + bgColor = java.awt.SystemColor.window; + } + java.awt.Color fgColor = foreground; + if (fgColor == null) + { + fgColor = java.awt.SystemColor.windowText; + } + java.awt.Font font = this.font; + if (font == null) + { + font = defaultFont; + } + return new ComponentGraphics(this.control, target, fgColor, bgColor, font); + } + return null; + } + + public override java.awt.Point getLocationOnScreen() + { + return NetToolkit.Invoke(delegate + { + Point p = new Point(0 - getInsetsLeft(), 0 - getInsetsTop()); + p = control.PointToScreen(p); + return new java.awt.Point(p.X, p.Y); + }); + } + + public override java.awt.Dimension getMinimumSize() + { + return target.getSize(); + } + + public override java.awt.Dimension getPreferredSize() + { + return getMinimumSize(); + } + + public override java.awt.Toolkit getToolkit() + { + return java.awt.Toolkit.getDefaultToolkit(); + } + + // returns true if the event has been handled and shouldn't be propagated + // though handleEvent method chain - e.g. WTextFieldPeer returns true + // on handling '\n' to prevent it from being passed to native code + public virtual bool handleJavaKeyEvent(java.awt.@event.KeyEvent e) { return false; } + + private void nativeHandleEvent(java.awt.AWTEvent e) + { + // TODO arrghh!! code from void AwtComponent::_NativeHandleEvent(void *param) in awt_Component.cpp should be here + } + + public override void handleEvent(java.awt.AWTEvent e) + { + int id = e.getID(); + + if (((java.awt.Component)target).isEnabled() && (e is java.awt.@event.KeyEvent) && !((java.awt.@event.KeyEvent)e).isConsumed()) + { + if (handleJavaKeyEvent((java.awt.@event.KeyEvent)e)) + { + return; + } + } + + switch (id) + { + case java.awt.@event.PaintEvent.PAINT: + // Got native painting + paintPending = false; + // Fallthrough to next statement + goto case java.awt.@event.PaintEvent.UPDATE; + case java.awt.@event.PaintEvent.UPDATE: + // Skip all painting while layouting and all UPDATEs + // while waiting for native paint + if (!isLayouting && !paintPending) + { + paintArea.paint(target, shouldClearRectBeforePaint()); + } + return; + default: + break; + } + + // Call the native code + nativeHandleEvent(e); + } + + public override void hide() + { + NetToolkit.BeginInvoke(delegate { control.Visible = false; }); + } + + public bool isFocusTraversable() + { + return true; + } + + public override java.awt.Dimension minimumSize() + { + return getMinimumSize(); + } + + public override java.awt.Dimension preferredSize() + { + return getPreferredSize(); + } + + public override void paint(java.awt.Graphics graphics) + { + target.paint(graphics); + } + + public override bool prepareImage(java.awt.Image img, int width, int height, java.awt.image.ImageObserver ob) + { + return getToolkit().prepareImage(img, width, height, ob); + } + + public override void print(java.awt.Graphics graphics) + { + throw new NotImplementedException(); + } + + public override void repaint(long tm, int x, int y, int width, int height) + { + } + + public void requestFocus() + { + NetToolkit.Invoke(control.Focus); + } + + /// + /// + /// + /// the component for which the focus is requested + /// indicates if the focus change is temporary (true) or permanent (false) + /// indicates if it's allowed to change window focus + /// the timestamp + /// + public bool requestFocus(java.awt.Component request, bool temporary, bool allowWindowFocus, long time) + { + if (!getEnabled() || !getVisible()) + { + return false; + } + postEvent(new java.awt.@event.FocusEvent(request, java.awt.@event.FocusEvent.FOCUS_GAINED, temporary, target)); + return true; + } + + public override void reshape(int x, int y, int width, int height) + { + NetToolkit.BeginInvoke(delegate + { + Form window = control.FindForm(); + java.awt.Insets insets; + if (window is MyForm) + { + insets = ((MyForm)window).peerInsets; + } + else + { + insets = new java.awt.Insets(0, 0, 0, 0); + } + control.SetBounds(x - insets.left, y - insets.top, width, height); + //If the .NET control does not accept the new bounds (minimum size, maximum size) + //then we need to reflect the real bounds on the .NET site to the Java site + Rectangle bounds = control.Bounds; + if (bounds.X + insets.left != x || bounds.Y + insets.top != y) + { + AWTAccessor.getComponentAccessor().setLocation(target, bounds.X + insets.left, bounds.Y + insets.top); + } + if (bounds.Width != width || bounds.Height != height) + { + AWTAccessor.getComponentAccessor().setSize(target, bounds.Width, bounds.Height); + } + }); + } + + public override void setBackground(java.awt.Color color) + { + lock (this) + { + this.background = color; + NetToolkit.BeginInvoke(delegate { control.BackColor = J2C.ConvertColor(color); }); + } + } + + private void reshapeNoCheck(int x, int y, int width, int height) + { + NetToolkit.BeginInvoke(delegate { control.SetBounds(x, y, width, height); }); + } + + public override void setBounds(int x, int y, int width, int height, int op) + { + // Should set paintPending before reahape to prevent + // thread race between paint events + // Native components do redraw after resize + paintPending = (width != oldWidth) || (height != oldHeight); + + if ((op & java.awt.peer.ComponentPeer.__Fields.NO_EMBEDDED_CHECK) != 0) + { + reshapeNoCheck(x, y, width, height); + } + else + { + reshape(x, y, width, height); + } + if ((width != oldWidth) || (height != oldHeight)) + { + // Only recreate surfaceData if this setBounds is called + // for a resize; a simple move should not trigger a recreation + try + { + //replaceSurfaceData(); + } + catch (sun.java2d.InvalidPipeException) + { + // REMIND : what do we do if our surface creation failed? + } + oldWidth = width; + oldHeight = height; + } + + serialNum++; + } + + private void setCursorImpl(java.awt.Cursor cursor) + { + if (cursor is NetCustomCursor) + { + NetCustomCursor ncc = (NetCustomCursor)cursor; + control.Cursor = ncc.Cursor; + return; + } + switch(cursor.getType()) + { + case java.awt.Cursor.WAIT_CURSOR: + control.Cursor = Cursors.WaitCursor; + break; + case java.awt.Cursor.DEFAULT_CURSOR: + control.Cursor = Cursors.Default; + break; + case java.awt.Cursor.HAND_CURSOR: + control.Cursor = Cursors.Hand; + break; + case java.awt.Cursor.CROSSHAIR_CURSOR: + control.Cursor = Cursors.Cross; + break; + case java.awt.Cursor.W_RESIZE_CURSOR: + case java.awt.Cursor.E_RESIZE_CURSOR: + control.Cursor = Cursors.SizeWE; + break; + case java.awt.Cursor.MOVE_CURSOR: + control.Cursor = Cursors.SizeAll; + break; + case java.awt.Cursor.N_RESIZE_CURSOR: + case java.awt.Cursor.S_RESIZE_CURSOR: + control.Cursor = Cursors.SizeNS; + break; + case java.awt.Cursor.NE_RESIZE_CURSOR: + case java.awt.Cursor.SW_RESIZE_CURSOR: + control.Cursor = Cursors.SizeNESW; + break; + case java.awt.Cursor.NW_RESIZE_CURSOR: + case java.awt.Cursor.SE_RESIZE_CURSOR: + control.Cursor = Cursors.SizeNWSE; + break; + case java.awt.Cursor.TEXT_CURSOR: + control.Cursor = Cursors.IBeam; + break; + default: + Console.WriteLine("setCursor not implement for: " + cursor); + break; + } + } + + public void setCursor(java.awt.Cursor cursor) + { + NetToolkit.Invoke(setCursorImpl, cursor); + } + + public bool getEnabled() + { + return NetToolkit.Invoke(delegate { return control.Enabled; }); + } + + public bool getFocused() + { + return NetToolkit.Invoke(delegate { return control.Focused; }); + } + + public bool getVisible() + { + return NetToolkit.Invoke(delegate { return control.Visible; }); + } + + public override void setEnabled(bool enabled) + { + if (enabled) + { + enable(); + } + else + { + disable(); + } + } + + public override void setFont(java.awt.Font font) + { + lock (this) + { + this.font = font; + NetToolkit.BeginInvoke(delegate { control.Font = font.getNetFont(); }); + } + } + + public override void setForeground(java.awt.Color color) + { + lock (this) + { + this.foreground = color; + NetToolkit.BeginInvoke(delegate { control.ForeColor = J2C.ConvertColor(color); }); + } + } + + public override void setVisible(bool visible) + { + if (visible) + { + show(); + } + else + { + hide(); + } + } + + public override void show() + { + java.awt.Dimension s = target.getSize(); + oldHeight = s.height; + oldWidth = s.width; + pShow(); + } + + /* + * Return the GraphicsConfiguration associated with this peer, either + * the locally stored winGraphicsConfig, or that of the target Component. + */ + public override java.awt.GraphicsConfiguration getGraphicsConfiguration() + { + // we don't need a treelock here, since + // Component.getGraphicsConfiguration() gets it itself. + return target.getGraphicsConfiguration(); + } + + public void setEventMask (long mask) + { + //Console.WriteLine("NOTE: NetComponentPeer.setEventMask not implemented"); + } + + public override bool isObscured() + { + // should never be called because we return false from canDetermineObscurity() + return true; + } + + public override bool canDetermineObscurity() + { + // JDK returns true here and uses GetClipBox to determine if the window is partially obscured, + // this is an optimization for scrolling in javax.swing.JViewport, since there appears to be + // no managed equivalent of GetClipBox, we'll simply return false and forgo the optimization. + return false; + } + + public override void coalescePaintEvent(java.awt.@event.PaintEvent e) + { + java.awt.Rectangle r = e.getUpdateRect(); + if (!(e is sun.awt.@event.IgnorePaintEvent)) + { + paintArea.add(r, e.getID()); + } + } + + public override void updateCursorImmediately() + { + } + + public override java.awt.image.VolatileImage createVolatileImage(int width, int height) + { + return new NetVolatileImage(target, width, height); + } + + public override bool handlesWheelScrolling() + { + return true; + } + + public override void createBuffers(int x, java.awt.BufferCapabilities capabilities) + { + throw new NotImplementedException(); + } + + public override java.awt.Image getBackBuffer() + { + throw new NotImplementedException(); + } + + public override void flip(java.awt.BufferCapabilities.FlipContents contents) + { + throw new NotImplementedException(); + } + + public override void destroyBuffers() + { + throw new NotImplementedException(); + } + + public override bool isFocusable() + { + return false; + } + + protected bool isDisposed() + { + return disposed; + } + + public override java.awt.Rectangle getBounds() + { + return target.getBounds(); + } + + public override void reparent(java.awt.peer.ContainerPeer parent) + { + throw new NotImplementedException(); + } + + public override bool isReparentSupported() + { + return false; + } + + // Do nothing for heavyweight implementation + public override void layout() + { + } + + public override void applyShape(sun.java2d.pipe.Region shape) + { + NetToolkit.BeginInvoke(ApplyShapeImpl, shape); + } + + private void ApplyShapeImpl(sun.java2d.pipe.Region shape) + { + control.Region = J2C.ConvertRegion(shape); + } + + //copied form KeyboardFocusManager + private const int SNFH_FAILURE = 0; + private const int SNFH_SUCCESS_HANDLED = 1; + private const int SNFH_SUCCESS_PROCEED = 2; + + private static java.lang.reflect.Method shouldNativelyFocusHeavyweight; + private static java.lang.reflect.Method processSynchronousLightweightTransfer; + private static java.lang.reflect.Method removeLastFocusRequest; + + public override bool requestFocus(java.awt.Component lightweightChild, bool temporary, bool focusedWindowChangeAllowed, long time, sun.awt.CausedFocusEvent.Cause cause) + { + // this is a interpretation of the code in WComponentPeer.java and awt_component.cpp + try + { + if (processSynchronousLightweightTransfer == null) + { + java.security.AccessController.doPrivileged(Delegates.toPrivilegedAction(delegate + { + java.lang.Class keyboardFocusManagerCls = typeof(java.awt.KeyboardFocusManager); + java.lang.reflect.Method method = keyboardFocusManagerCls.getDeclaredMethod( + "processSynchronousLightweightTransfer", + typeof(java.awt.Component), + typeof(java.awt.Component), + java.lang.Boolean.TYPE, + java.lang.Boolean.TYPE, + java.lang.Long.TYPE); + method.setAccessible(true); + processSynchronousLightweightTransfer = method; + return null; + })); + } + processSynchronousLightweightTransfer.invoke( + null, + target, + lightweightChild, + java.lang.Boolean.valueOf(temporary), + java.lang.Boolean.valueOf(focusedWindowChangeAllowed), + java.lang.Long.valueOf(time)); + } + catch + { + return true; + } + if (shouldNativelyFocusHeavyweight == null) + { + java.security.AccessController.doPrivileged(Delegates.toPrivilegedAction(delegate + { + java.lang.Class keyboardFocusManagerCls = typeof(java.awt.KeyboardFocusManager); + java.lang.reflect.Method method = keyboardFocusManagerCls.getDeclaredMethod( + "shouldNativelyFocusHeavyweight", + typeof(java.awt.Component), + typeof(java.awt.Component), + java.lang.Boolean.TYPE, + java.lang.Boolean.TYPE, + java.lang.Long.TYPE, + typeof(sun.awt.CausedFocusEvent.Cause)); + method.setAccessible(true); + shouldNativelyFocusHeavyweight = method; + return null; + })); + } + int retval = ((java.lang.Integer)shouldNativelyFocusHeavyweight.invoke( + null, + target, + lightweightChild, + java.lang.Boolean.valueOf(temporary), + java.lang.Boolean.valueOf(focusedWindowChangeAllowed), + java.lang.Long.valueOf(time), + cause)).intValue(); + if (retval == SNFH_SUCCESS_HANDLED) + { + return true; + } + else if (retval == SNFH_SUCCESS_PROCEED) + { + if (getFocused()) + { + return true; + } + if (removeLastFocusRequest == null) + { + java.security.AccessController.doPrivileged(Delegates.toPrivilegedAction(delegate + { + java.lang.Class keyboardFocusManagerCls = typeof(java.awt.KeyboardFocusManager); + java.lang.reflect.Method method = keyboardFocusManagerCls.getDeclaredMethod( + "removeLastFocusRequest", + typeof(java.awt.Component)); + method.setAccessible(true); + removeLastFocusRequest = method; + return null; + })); + } + removeLastFocusRequest.invoke(null, target); + } + //SNFH_FAILURE + return false; + } + + /** + * Move the back buffer to the front buffer. + * + * @param x1 the area to be flipped, upper left X coordinate + * @param y1 the area to be flipped, upper left Y coordinate + * @param x2 the area to be flipped, lower right X coordinate + * @param y2 the area to be flipped, lower right Y coordinate + * @param flipAction the flip action to perform + * + * @see Component.FlipBufferStrategy#flip + */ + public override void flip(int x1, int y1, int x2, int y2, java.awt.BufferCapabilities.FlipContents flipAction) + { + throw new ikvm.@internal.NotYetImplementedError(); + } + + /** + * Lowers this component at the bottom of the above HW peer. If the above parameter + * is null then the method places this component at the top of the Z-order. + */ + public override void setZOrder(java.awt.peer.ComponentPeer above) + { + Control.ControlCollection controls = control.Controls; + if (!controls.Contains(control)) + { + // Control was not added to any window. Occur if you call addNotify without + return; + } + if (above == null) + { + controls.SetChildIndex(control, 0); + } + else + { + NetComponentPeer netPeer = (NetComponentPeer)above; + controls.SetChildIndex(control, controls.GetChildIndex(netPeer.control)); + } + } + + /** + * Updates internal data structures related to the component's GC. + * + * @return if the peer needs to be recreated for the changes to take effect + * @since 1.7 + */ + public override bool updateGraphicsData(java.awt.GraphicsConfiguration gc) + { + throw new ikvm.@internal.NotYetImplementedError(); + } + + } + + sealed class NetScrollbarPeer : NetComponentPeer, java.awt.peer.ScrollbarPeer + { + internal NetScrollbarPeer(java.awt.Scrollbar target) + : base(target) + { + } + + public void setLineIncrement(int i) + { + } + + public void setPageIncrement(int i) + { + } + + public void setValues(int i1, int i2, int i3, int i4) + { + } + + protected override ScrollBar CreateControl() + { + switch (target.getOrientation()) + { + case java.awt.Scrollbar.VERTICAL: + return new VScrollBar(); + default: + return new HScrollBar(); + } + } + } + + sealed class NetScrollPanePeer : NetComponentPeer, java.awt.peer.ScrollPanePeer + { + internal NetScrollPanePeer(java.awt.ScrollPane pane) + : base(pane) + { + } + + public void childResized(int i1, int i2) + { + } + + public int getHScrollbarHeight() + { + return NetToolkit.Invoke(delegate { return 0; }); + } + + public int getVScrollbarWidth() + { + return NetToolkit.Invoke(delegate { return 0; }); + } + + public void setScrollPosition(int i1, int i2) + { + } + + public void setUnitIncrement(java.awt.Adjustable a, int i) + { + } + + public void setValue(java.awt.Adjustable a, int i) + { + } + + public java.awt.Insets getInsets() + { + return NetToolkit.Invoke(delegate { return new java.awt.Insets(0, 0, 0, 0); }); + } + + public java.awt.Insets insets() + { + return getInsets(); + } + + public bool isRestackSupported() + { + return false; + } + + public void restack() + { + throw new NotImplementedException(); + } + + protected override ScrollableControl CreateControl() + { + return new ScrollableControl(); + } + } + + sealed class NetButtonPeer : NetComponentPeer, java.awt.peer.ButtonPeer + { + public NetButtonPeer(java.awt.Button awtbutton) + : base(awtbutton) + { + if (!awtbutton.isBackgroundSet()) + { + awtbutton.setBackground(java.awt.SystemColor.control); + } + control.BackColor = Color.FromArgb(awtbutton.getBackground().getRGB()); + control.Text = awtbutton.getLabel(); + control.Click += new EventHandler(OnClick); + } + + private void OnClick(object sender, EventArgs e) + { + // TODO set all these properties correctly + string cmd = ""; + long when = 0; + int modifiers = 0; + postEvent(new java.awt.@event.ActionEvent(target, java.awt.@event.ActionEvent.ACTION_PERFORMED, cmd, when, modifiers)); + } + + public void setLabel(string label) + { + NetToolkit.Invoke(delegate { control.Text = label; }); + } + + public override java.awt.Dimension getMinimumSize() + { + using(Graphics g = control.CreateGraphics()) + { + // TODO get these fudge factors from somewhere + return new java.awt.Dimension((int)Math.Round(12 + g.MeasureString(control.Text, control.Font).Width) * 8 / 7, 6 + control.Font.Height * 8 / 7); + } + } + + public override bool shouldClearRectBeforePaint() + { + return false; + } + + protected override Button CreateControl() + { + return new Button(); + } + } + + abstract class NetTextComponentPeer : NetComponentPeer, java.awt.peer.TextComponentPeer + where T : java.awt.TextComponent + { + public NetTextComponentPeer(java.awt.TextComponent textComponent) + : base((T)textComponent) + { +#if __MonoCS__ + // MONOBUG mcs generates a ldflda on a readonly field, so we use a temp + T target = this.target; +#endif + if (!target.isBackgroundSet()) + { + target.setBackground(java.awt.SystemColor.window); + } + setBackground(target.getBackground()); + control.AutoSize = false; + control.Text = target.getText(); + } + + public override bool isFocusable() + { + return true; + } + + protected override void OnKeyPress(object sender, KeyPressEventArgs e) + { + base.OnKeyPress(sender, e); + // TODO for TextAreas this probably isn't the right behaviour + if(e.KeyChar == '\r') + { + // TODO set all these properties correctly + string cmd = ""; + long when = 0; + int modifiers = 0; + postEvent(new java.awt.@event.ActionEvent(target, java.awt.@event.ActionEvent.ACTION_PERFORMED, cmd, when, modifiers)); + } + } + + public int getSelectionEnd() + { + return NetToolkit.Invoke(delegate { return control.SelectionStart + control.SelectionLength; }); + } + + public int getSelectionStart() + { + return NetToolkit.Invoke(delegate { return control.SelectionStart; }); + } + + public string getText() + { + return NetToolkit.Invoke(delegate { return control.Text; }); + } + + public void setText(string text) + { + NetToolkit.Invoke(delegate { control.Text = text; }); + } + + public void select(int start_pos, int end_pos) + { + throw new NotImplementedException(); + } + + public void setEditable(bool editable) + { + throw new NotImplementedException(); + } + + public int getCaretPosition() + { + return getSelectionStart(); + } + + private void setCaretPositionImpl(int pos) + { + control.SelectionStart = pos; + control.SelectionLength = 0; + } + + public void setCaretPosition(int pos) + { + NetToolkit.Invoke(setCaretPositionImpl, pos); + } + + public long filterEvents(long filter) + { + throw new NotImplementedException(); + } + + public int getIndexAtPoint(int x, int y) + { + throw new NotImplementedException(); + } + + public java.awt.Rectangle getCharacterBounds(int pos) + { + throw new NotImplementedException(); + } + + public java.awt.im.InputMethodRequests getInputMethodRequests() + { + throw new NotImplementedException(); + } + + protected sealed override TextBox CreateControl() + { + return new TextBox(); + } + } + + sealed class NetChoicePeer : NetComponentPeer, java.awt.peer.ChoicePeer + { + public NetChoicePeer(java.awt.Choice target) + : base(target) + { + } + + public void add(string str, int i) + { + // TODO: Add NetChoicePeer.add implementation + } + + public void addItem(string str, int i) + { + // TODO: Add NetChoicePeer.addItem implementation + } + + public void select(int i) + { + // TODO: Add NetChoicePeer.select implementation + } + + public void removeAll() + { + // TODO: Add NetChoicePeer.removeAll implementation + } + + public void remove(int i) + { + // TODO: Add NetChoicePeer.remove implementation + } + + protected override RadioButton CreateControl() + { + return new RadioButton(); + } + } + + sealed class NetCheckboxPeer : NetComponentPeer, java.awt.peer.CheckboxPeer + { + public NetCheckboxPeer(java.awt.Checkbox target) + : base(target) + { + } + + public void setCheckboxGroup(java.awt.CheckboxGroup cg) + { + // TODO: Add NetCheckboxPeer.setCheckboxGroup implementation + } + + public void setState(bool b) + { + // TODO: Add NetCheckboxPeer.setState implementation + } + + public void setLabel(string str) + { + // TODO: Add NetCheckboxPeer.setLabel implementation + } + + protected override CheckBox CreateControl() + { + return new CheckBox(); + } + } + + sealed class NetLabelPeer : NetComponentPeer, java.awt.peer.LabelPeer + { + public NetLabelPeer(java.awt.Label jlabel) + : base(jlabel) + { + control.Text = jlabel.getText(); + setAlignment(jlabel.getAlignment()); + } + + public void setAlignment(int align) + { + ContentAlignment alignment; + switch(align) + { + case java.awt.Label.LEFT: + alignment = ContentAlignment.TopLeft; + break; + case java.awt.Label.CENTER: + alignment = ContentAlignment.TopCenter; + break; + case java.awt.Label.RIGHT: + alignment = ContentAlignment.TopRight; + break; + default: + return; + } + NetToolkit.Invoke(setAlignImpl, alignment); + } + + private void setAlignImpl(ContentAlignment alignment) + { + control.TextAlign = (ContentAlignment)alignment; + } + + public void setText(string s) + { + NetToolkit.Invoke(setTextImpl, s); + } + + private void setTextImpl(string s) + { + control.Text = s; + } + + public override java.awt.Dimension preferredSize() + { + return NetToolkit.Invoke(getPreferredSizeImpl); + } + + private java.awt.Dimension getPreferredSizeImpl() + { + // HACK get these fudge factors from somewhere + return new java.awt.Dimension(control.PreferredWidth, 2 + control.PreferredHeight); + } + + public override bool shouldClearRectBeforePaint() + { + // is native control, don't clear + return false; + } + + protected override Label CreateControl() + { + return new Label(); + } + } + + sealed class NetTextFieldPeer : NetTextComponentPeer, java.awt.peer.TextFieldPeer + { + public NetTextFieldPeer(java.awt.TextField textField) + : base(textField) + { + setEchoCharacterImpl(textField.getEchoChar()); + } + + public java.awt.Dimension minimumSize(int len) + { + return getMinimumSize(len); + } + + public java.awt.Dimension preferredSize(int len) + { + return getPreferredSize(len); + } + + public java.awt.Dimension getMinimumSize(int len) + { + return getPreferredSize(len); + } + + public java.awt.Dimension getPreferredSize(int len) + { + // TODO use control.Invoke + using(Graphics g = control.CreateGraphics()) + { + return new java.awt.Dimension((int)Math.Round((g.MeasureString("abcdefghijklm", control.Font).Width * len) / 13), ((TextBox)control).PreferredHeight); + } + } + + public void setEchoChar(char echo_char) + { + setEchoCharacter(echo_char); + } + + private void setEchoCharacterImpl(char echo_char) + { + control.PasswordChar = echo_char; + } + + public void setEchoCharacter(char echo_char) + { + control.Invoke(new Action(setEchoCharacterImpl), echo_char); + } + + public override bool handleJavaKeyEvent(java.awt.@event.KeyEvent e) + { + switch (e.getID()) + { + case java.awt.@event.KeyEvent.KEY_TYPED: + if ((e.getKeyChar() == '\n') && !e.isAltDown() && !e.isControlDown()) + { + postEvent(new java.awt.@event.ActionEvent(target, java.awt.@event.ActionEvent.ACTION_PERFORMED, + getText(), e.getWhen(), e.getModifiers())); + return true; + } + break; + } + return false; + } + } + + sealed class NetTextAreaPeer : NetComponentPeer, java.awt.peer.TextAreaPeer + { + public NetTextAreaPeer(java.awt.TextArea textArea) + : base(textArea) + { + control.ReadOnly = !((java.awt.TextArea)target).isEditable(); + control.WordWrap = false; + control.ScrollBars = RichTextBoxScrollBars.Both; + control.Multiline = true; + control.AutoSize = false; + control.Text = target.getText(); + } + + public override bool isFocusable() + { + return true; + } + + public int getSelectionEnd() + { + return NetToolkit.Invoke(delegate { return control.SelectionStart + control.SelectionLength; }); + } + + public int getSelectionStart() + { + return NetToolkit.Invoke(delegate { return control.SelectionStart; }); + } + + public string getText() + { + return NetToolkit.Invoke(delegate { return control.Text; }); + } + + public void setText(string text) + { + NetToolkit.Invoke(delegate { control.Text = text; }); + } + + public void select(int start_pos, int end_pos) + { + throw new NotImplementedException(); + } + + public void setEditable(bool editable) + { + throw new NotImplementedException(); + } + + public int getCaretPosition() + { + return getSelectionStart(); + } + + private void setCaretPositionImpl(int pos) + { + control.SelectionStart = pos; + control.SelectionLength = 0; + } + + public void setCaretPosition(int pos) + { + NetToolkit.Invoke(setCaretPositionImpl, pos); + } + + public void insert(string text, int pos) + { + NetToolkit.Invoke(delegate { control.Text = control.Text.Insert(pos, text); }); + } + + public void insertText(string text, int pos) + { + insert(text, pos); + } + + public override java.awt.Dimension getMinimumSize() + { + return getMinimumSize(10, 60); + } + + public java.awt.Dimension minimumSize(int rows, int cols) + { + return getMinimumSize(rows, cols); + } + + public java.awt.Dimension getMinimumSize(int rows, int cols) + { + java.awt.FontMetrics fm = getFontMetrics(target.getFont()); + return new java.awt.Dimension(fm.charWidth('0') * cols + 20, fm.getHeight() * rows + 20); + } + + public java.awt.Dimension preferredSize(int rows, int cols) + { + return getPreferredSize(rows, cols); + } + + public java.awt.Dimension getPreferredSize(int rows, int cols) + { + return getMinimumSize(rows, cols); + } + + public void replaceRange(string text, int start_pos, int end_pos) + { + NetToolkit.Invoke(delegate { control.Text = control.Text.Substring(0, start_pos) + text + control.Text.Substring(end_pos); }); + } + + public void replaceText(string text, int start_pos, int end_pos) + { + replaceRange(text, start_pos, end_pos); + } + + public java.awt.im.InputMethodRequests getInputMethodRequests() + { + throw new NotImplementedException(); + } + + protected sealed override RichTextBox CreateControl() + { + return new RichTextBox(); + } + } + + class NetContainerPeer : NetComponentPeer, java.awt.peer.ContainerPeer + where T : java.awt.Container + where C : Control + { + /// + /// The native insets of the .NET Window + /// + protected java.awt.Insets _insets = new java.awt.Insets(0, 0, 0, 0); + + public NetContainerPeer(java.awt.Container awtcontainer) + : base((T)awtcontainer) + { + } + + internal override int getInsetsLeft() + { + return _insets.left; ; + } + + internal override int getInsetsTop() + { + return _insets.top; + } + + public java.awt.Insets insets() + { + return getInsets(); + } + + public java.awt.Insets getInsets() + { + return _insets; + } + + public bool isRestackSupported() + { + return false; + } + + public void cancelPendingPaint(int x, int y, int width, int height) + { + throw new NotImplementedException(); + } + + public void restack() + { + throw new NotImplementedException(); + } + + protected override C CreateControl() + { + throw new NotImplementedException(); + } + } + + sealed class NetPanelPeer : NetContainerPeer, java.awt.peer.PanelPeer + { + public NetPanelPeer(java.awt.Panel panel) + : base(panel) + { + } + + protected override ContainerControl CreateControl() + { + return new ContainerControl(); + } + } + + sealed class NetCanvasPeer : NetComponentPeer, java.awt.peer.CanvasPeer + { + public NetCanvasPeer(java.awt.Canvas canvas) + : base(canvas) + { + } + + protected override Control CreateControl() + { + return new Control(); + } + + /** + * Requests a GC that best suits this Canvas. The returned GC may differ + * from the requested GC passed as the argument to this method. This method + * must return a non-null value (given the argument is non-null as well). + * + * @since 1.7 + */ + public java.awt.GraphicsConfiguration getAppropriateGraphicsConfiguration(java.awt.GraphicsConfiguration gc) + { + return gc; + } + } + + class NetWindowPeer : NetContainerPeer, java.awt.peer.WindowPeer + { + // we can't use NetDialogPeer as blocker may be an instance of NetPrintDialogPeer that + // extends NetWindowPeer, not NetDialogPeer + private NetWindowPeer modalBlocker; + private bool modalSavedEnabled; + + private static NetWindowPeer grabbedWindow; + + public NetWindowPeer(java.awt.Window window, bool isFocusableWindow, bool isAlwaysOnTop) + : base(window) + { + //form.Shown += new EventHandler(OnOpened); Will already post in java.awt.Window.show() + control.Closing += new CancelEventHandler(OnClosing); + control.Closed += new EventHandler(OnClosed); + control.Activated += new EventHandler(OnActivated); + control.Deactivate += new EventHandler(OnDeactivate); + control.SizeChanged += new EventHandler(OnSizeChanged); + control.Resize += new EventHandler(OnResize); + control.Move += new EventHandler(OnMove); + ((UndecoratedForm)control).SetWindowState(isFocusableWindow, isAlwaysOnTop); + } + + protected override void initialize() + { + base.initialize(); + updateIconImages(); + if (target.getBackground() == null) + { + AWTAccessor.getComponentAccessor().setBackground(target, target is java.awt.Dialog ? java.awt.SystemColor.control : java.awt.SystemColor.window); + } + control.BackColor = J2C.ConvertColor(target.getBackground()); + if (target.getForeground() == null) + { + target.setForeground(java.awt.SystemColor.windowText); + } + if (target.getFont() == null) + { + //target.setFont(defaultFont); + //HACK: Sun is calling setFont(Font) here and this is calling firePropertyChange("font", oldFont, newFont) + //but this produce a deadlock with getTreeLock() because the creating of the peer is already in this synchronized + java.security.AccessController.doPrivileged(Delegates.toPrivilegedAction(delegate + { + java.lang.Class component = typeof(java.awt.Component); + java.lang.reflect.Field field = component.getDeclaredField("font"); + field.setAccessible(true); + field.set(target, defaultFont); + java.lang.reflect.Method method = component.getDeclaredMethod( + "firePropertyChange", + typeof(java.lang.String), + typeof(java.lang.Object), + typeof(java.lang.Object)); + method.setAccessible(true); + method.invoke(target, "font", null, defaultFont); + return null; + })); + } + } + + private void OnResize(object sender, EventArgs e) + { + // WmSizing + SendComponentEvent(java.awt.@event.ComponentEvent.COMPONENT_RESIZED); + dynamicallyLayoutContainer(); + } + + private void OnMove(object sender, EventArgs e) + { + // WmMove + AWTAccessor.getComponentAccessor().setLocation(target, control.Left, control.Top); + SendComponentEvent(java.awt.@event.ComponentEvent.COMPONENT_MOVED); + } + + /* + * Although this function sends ComponentEvents, it needs to be defined + * here because only top-level windows need to have move and resize + * events fired from native code. All contained windows have these events + * fired from common Java code. + */ + private void SendComponentEvent(int eventId) + { + SendEvent(new java.awt.@event.ComponentEvent(target, eventId)); + } + + private void OnSizeChanged(object sender, EventArgs e) + { + // WmSize + typeof(java.awt.Component).GetField("width", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(target, control.Width); + typeof(java.awt.Component).GetField("height", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(target, control.Height); + SendComponentEvent(java.awt.@event.ComponentEvent.COMPONENT_RESIZED); + } + + private void OnOpened(object sender, EventArgs e) + { + postEvent(new java.awt.@event.WindowEvent((java.awt.Window)target, java.awt.@event.WindowEvent.WINDOW_OPENED)); + } + + private void OnClosing(object sender, CancelEventArgs e) + { + e.Cancel = true; + postEvent(new java.awt.@event.WindowEvent((java.awt.Window)target, java.awt.@event.WindowEvent.WINDOW_CLOSING)); + } + + private void OnClosed(object sender, EventArgs e) + { + postEvent(new java.awt.@event.WindowEvent((java.awt.Window)target, java.awt.@event.WindowEvent.WINDOW_CLOSED)); + } + + private const int WA_ACTIVE = 1; + private const int WA_INACTIVE = 2; + + private void OnActivated(object sender, EventArgs e) + { + WmActivate(WA_ACTIVE, control.WindowState == FormWindowState.Minimized, null); + } + + private void OnDeactivate(object sender, EventArgs e) + { + WmActivate(WA_INACTIVE, control.WindowState == FormWindowState.Minimized, null); + } + + private void WmActivate(int nState, bool fMinimized, Control opposite) + { + int type; + + if (nState != WA_INACTIVE) + { + type = java.awt.@event.WindowEvent.WINDOW_GAINED_FOCUS; + } + else + { + if (grabbedWindow != null && !grabbedWindow.IsOneOfOwnersOf(this)) + { + grabbedWindow.Ungrab(true); + } + type = java.awt.@event.WindowEvent.WINDOW_LOST_FOCUS; + } + + SendWindowEvent(type, opposite); + } + + private void SendWindowEvent(int id, Control opposite) { SendWindowEvent(id, opposite, 0, 0); } + + private void SendWindowEvent(int id, Control opposite, int oldState, int newState) + { + java.awt.AWTEvent evt = new java.awt.@event.WindowEvent((java.awt.Window)target, id, null); + + if (id == java.awt.@event.WindowEvent.WINDOW_GAINED_FOCUS + || id == java.awt.@event.WindowEvent.WINDOW_LOST_FOCUS) + { + Type type = typeof(java.awt.Component).Assembly.GetType("java.awt.SequencedEvent"); + ConstructorInfo cons = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, new Type[] { typeof(java.awt.AWTEvent) }, null); + evt = (java.awt.AWTEvent)cons.Invoke(new object[] { evt }); + } + + SendEvent(evt); + } + + public override java.awt.Graphics getGraphics() + { + java.awt.Graphics g = base.getGraphics(); + java.awt.Insets insets = getInsets(); + g.translate(-insets.left, -insets.top); + g.setClip(insets.left, insets.top, control.ClientRectangle.Width, control.ClientRectangle.Height); + return g; + } + + public override bool shouldClearRectBeforePaint() + { + // clearing the window before repainting causes the controls to "flicker" on screen + return false; + } + + /// + /// Set the border style of the window and recalc the insets + /// + /// the new style + protected void setFormBorderStyle(FormBorderStyle style) + { + NetToolkit.BeginInvoke(delegate + { + control.FormBorderStyle = style; + //Calculate the Insets one time + //This is many faster because there no thread change is needed. + CalcInsetsImpl(); + }); + } + + protected void CalcInsetsImpl() + { + Rectangle client = control.ClientRectangle; + if (client.Height == 0) + { + // HACK for .NET bug if form has the minimum size then ClientRectangle is not recalulate + // if the FormBorderStyle is changed + Size size = control.Size; + size.Height++; + control.Size = size; + size.Height--; + control.Size = size; + client = control.ClientRectangle; + } + Rectangle r = control.RectangleToScreen(client); + int x = r.Location.X - control.Location.X; + int y = r.Location.Y - control.Location.Y; + // only modify this instance, since it's shared by the control-peers of this form + _insets.top = y; + _insets.left = x; + _insets.bottom = control.Height - client.Height - y; + if (control.Menu != null) + { + _insets.bottom += SystemInformation.MenuHeight; + } + _insets.right = control.Width - client.Width - x; + } + + public override void reshape(int x, int y, int width, int height) + { + NetToolkit.BeginInvoke(delegate + { + control.SetBounds(x, y, width, height); + //If the .NET control does not accept the new bounds (minimum size, maximum size) + //then we need to reflect the real bounds on the .NET site to the Java site + Rectangle bounds = control.Bounds; + if (bounds.X != x || bounds.Y != y) + { + AWTAccessor.getComponentAccessor().setLocation(target, bounds.X, bounds.Y); + } + if (bounds.Width != width || bounds.Height != height) + { + AWTAccessor.getComponentAccessor().setSize(target, bounds.Width, bounds.Height); + } + }); + } + + public void toBack() + { + NetToolkit.BeginInvoke(control.SendToBack); + } + + public void toFront() + { + NetToolkit.BeginInvoke(control.Activate); + } + + public bool requestWindowFocus() + { + return NetToolkit.Invoke(control.Focus); + } + + public void updateAlwaysOnTopState() + { + // The .NET property TopMost does not work with a not focusable Window + // that we need to set the window flags directly. To reduce double code + // we call updateFocusableWindowState(). + updateFocusableWindowState(); + } + + public bool isModalBlocked() + { + return modalBlocker != null; + } + + public void setModalBlocked(java.awt.Dialog dialog, bool blocked) + { + lock (target.getTreeLock()) // State lock should always be after awtLock + { + // use NetWindowPeer instead of NetDialogPeer because of FileDialogs and PrintDialogs + NetWindowPeer blockerPeer = (NetWindowPeer)dialog.getPeer(); + if (blocked) + { + modalBlocker = blockerPeer; + modalSavedEnabled = control.Enabled; + disable(); + } + else + { + modalBlocker = null; + if(modalSavedEnabled){ + enable(); + } + else + { + disable(); + } + } + } + } + + public void updateFocusableWindowState() + { + ((UndecoratedForm)control).SetWindowState(((java.awt.Window)target).isFocusableWindow(), ((java.awt.Window)target).isAlwaysOnTop()); + } + + public void updateIconImages() + { + java.util.List imageList = ((java.awt.Window)target).getIconImages(); + Icon icon; + if (imageList == null || imageList.size() == 0) + { + icon = null; + } + else + { + IconFactory factory = new IconFactory(); + icon = factory.CreateIcon(imageList, SystemInformation.IconSize); + } + NetToolkit.BeginInvoke(delegate + { + ((Form)control).Icon = icon; + }); + } + + public void updateMinimumSize() + { + java.awt.Dimension dim = target.getMinimumSize(); + NetToolkit.BeginInvoke(delegate + { + control.MinimumSize = new Size(dim.width, dim.height); + }); + } + + /** + * Sets the level of opacity for the window. + * + * @see Window#setOpacity(float) + */ + public void setOpacity(float opacity) + { + throw new ikvm.@internal.NotYetImplementedError(); + } + + /** + * Enables the per-pixel alpha support for the window. + * + * @see Window#setBackground(Color) + */ + public void setOpaque(bool isOpaque) + { + throw new ikvm.@internal.NotYetImplementedError(); + } + + + /** + * Updates the native part of non-opaque window. + * + * @see Window#setBackground(Color) + */ + public void updateWindow() + { + throw new ikvm.@internal.NotYetImplementedError(); + } + + + /** + * Instructs the peer to update the position of the security warning. + */ + public void repositionSecurityWarning() + { + throw new ikvm.@internal.NotYetImplementedError(); + } + + + + protected override Form CreateControl() + { + return new UndecoratedForm(); + } + + protected override void OnMouseDown(object sender, MouseEventArgs ev) + { + if (grabbedWindow != null && !grabbedWindow.IsOneOfOwnersOf(this)) + { + grabbedWindow.Ungrab(true); + } + base.OnMouseDown(sender, ev); + } + + internal void Grab() + { + //copy from file awt_Windows.cpp + if (grabbedWindow != null) + { + grabbedWindow.Ungrab(true); + } + grabbedWindow = this; + if (Form.ActiveForm == null) + { + Ungrab(true); + } + else if (control != Form.ActiveForm) + { + toFront(); + } + } + + internal void Ungrab(bool doPost) + { + //copy from file awt_Windows.cpp + if (grabbedWindow == this) + { + if (doPost) + { + SendEvent(new sun.awt.UngrabEvent(this.target)); + } + grabbedWindow = null; + } + } + + private bool IsOneOfOwnersOf(NetWindowPeer window) + { + while (window != null) + { + if (window == this) + { + return true; + } + java.awt.Container parent = window.target.getParent(); + window = parent == null ? null : (NetWindowPeer)parent.getPeer(); + } + return false; + } + } + + sealed class NetFramePeer : NetWindowPeer, java.awt.peer.FramePeer + { + public NetFramePeer(java.awt.Frame frame, bool isFocusableWindow, bool isAlwaysOnTop) + : base(frame, isFocusableWindow, isAlwaysOnTop) + { + } + + protected override void initialize() + { + base.initialize(); + java.awt.Frame target = (java.awt.Frame)this.target; + + if (target.getTitle() != null) + { + setTitle(target.getTitle()); + } + setResizable(target.isResizable()); + setState(target.getExtendedState()); + } + + public void setMenuBar(java.awt.MenuBar mb) + { + if (mb == null) + { + NetToolkit.Invoke(delegate + { + control.Menu = null; + CalcInsetsImpl(); + }); + } + else + { + mb.addNotify(); + NetToolkit.Invoke(delegate + { + control.Menu = ((NetMenuBarPeer)mb.getPeer()).menu; + CalcInsetsImpl(); + }); + } + } + + public void setResizable(bool resizable) + { + if (((java.awt.Frame)target).isUndecorated()) + { + setFormBorderStyle(FormBorderStyle.None); + } + else + { + if (resizable) + { + setFormBorderStyle(FormBorderStyle.Sizable); + } + else + { + setFormBorderStyle(FormBorderStyle.FixedSingle); + } + } + } + + public void setTitle(string title) + { + NetToolkit.BeginInvoke(delegate { control.Text = title; }); + } + + public int getState() + { + Form f = (Form)control; + FormWindowState state = f.WindowState; + switch (state) + { + case FormWindowState.Normal: + return java.awt.Frame.NORMAL; + case FormWindowState.Maximized: + return java.awt.Frame.MAXIMIZED_BOTH; + case FormWindowState.Minimized: + return java.awt.Frame.ICONIFIED; + default: + throw new InvalidEnumArgumentException(); + } + } + + public void setState(int state) + { + NetToolkit.BeginInvoke(delegate + { + MyForm form = (MyForm) control; + switch(state) + { + case java.awt.Frame.NORMAL: + form.WindowState = FormWindowState.Normal; + break; + case java.awt.Frame.MAXIMIZED_BOTH: + form.WindowState = FormWindowState.Maximized; + break; + case java.awt.Frame.ICONIFIED: + form.WindowState = FormWindowState.Minimized; + break; + } + }); + } + + public void setMaximizedBounds(java.awt.Rectangle rect) + { + ((MyForm)control).setMaximizedBounds(rect); + } + + public void setBoundsPrivate(int x, int y, int width, int height) + { + NetToolkit.Invoke(delegate { control.Bounds = new Rectangle(x, y, width, height); }); + } + + public java.awt.Rectangle getBoundsPrivate() + { + throw new NotImplementedException(); + } + + protected override Form CreateControl() + { + return new MyForm(_insets); + } + + public void emulateActivation(bool b) + { + throw new NotImplementedException(); + } + } + + sealed class NetDialogPeer : NetWindowPeer, java.awt.peer.DialogPeer + { + public NetDialogPeer(java.awt.Dialog target, bool isFocusableWindow, bool isAlwaysOnTop) + : base(target, isFocusableWindow, isAlwaysOnTop) + { + control.MaximizeBox = false; + control.MinimizeBox = false; + control.ShowInTaskbar = false; + setTitle(target.getTitle()); + setResizable(target.isResizable()); + } + + public void setTitle(string title) + { + NetToolkit.Invoke(delegate { control.Text = title; }); + } + + public void setResizable(bool resizable) + { + if (((java.awt.Dialog)target).isUndecorated()) + { + setFormBorderStyle(FormBorderStyle.None); + } + else + { + if (resizable) + { + setFormBorderStyle(FormBorderStyle.Sizable); + } + else + { + setFormBorderStyle(FormBorderStyle.FixedSingle); + } + } + } + + public void blockWindows(List toBlock) + { + // code copies from sun.awt.windows.WDialogPeer.java + for (Iterator it = toBlock.iterator(); it.hasNext();) { + java.awt.Window w = (java.awt.Window)it.next(); + java.awt.peer.WindowPeer wp = (java.awt.peer.WindowPeer)AWTAccessor.getComponentAccessor().getPeer(w); + if (wp != null) { + wp.setModalBlocked((java.awt.Dialog)target, true); + } + } + } + + protected override Form CreateControl() + { + return new MyForm(_insets); + } + } + + sealed class NetKeyboardFocusManagerPeer : java.awt.peer.KeyboardFocusManagerPeer + { + private static java.lang.reflect.Method m_removeLastFocusRequest; + + public void clearGlobalFocusOwner(java.awt.Window activeWindow) + { + } + + public java.awt.Component getCurrentFocusOwner() + { + return getNativeFocusOwner(); + } + + public void setCurrentFocusOwner(java.awt.Component component) + { + } + + public java.awt.Window getCurrentFocusedWindow() + { + return getNativeFocusedWindow(); + } + + public void setCurrentFocusedWindow(java.awt.Window w) + { + } + + private static java.awt.Component getNativeFocusOwner() + { + return NetToolkit.Invoke(delegate + { + UndecoratedForm form = Form.ActiveForm as UndecoratedForm; + if (form != null) + { + Control control = form.ActiveControl; + while (control is ContainerControl) + { + control = ((ContainerControl)control).ActiveControl; + } + NetComponentPeer peer; + if (control == null) + { + peer = NetComponentPeer.FromControl(form); + } + else + { + while ((peer = NetComponentPeer.FromControl(form)) == null) + { + control = control.Parent; + } + } + return peer.Target; + } + return null; + }); + } + + private static java.awt.Window getNativeFocusedWindow() + { + return NetToolkit.Invoke(delegate + { + Form form = Form.ActiveForm; + if (form != null) + { + NetComponentPeer peer = NetComponentPeer.FromControl(form); + if (peer != null) + { + return (java.awt.Window)peer.Target; + } + } + return null; + }); + } + + public static void removeLastFocusRequest(java.awt.Component heavyweight) + { + try + { + if (m_removeLastFocusRequest == null) + { + java.security.AccessController.doPrivileged(Delegates.toPrivilegedAction(delegate + { + java.lang.Class keyboardFocusManagerCls = typeof(java.awt.KeyboardFocusManager); + java.lang.reflect.Method method = keyboardFocusManagerCls.getDeclaredMethod( + "removeLastFocusRequest", + typeof(java.awt.Component)); + method.setAccessible(true); + m_removeLastFocusRequest = method; + return null; + })); + } + m_removeLastFocusRequest.invoke(null, new Object[] { heavyweight }); + } + catch (java.lang.reflect.InvocationTargetException ite) + { + ite.printStackTrace(); + } + catch (java.lang.IllegalAccessException ex) + { + ex.printStackTrace(); + } + } + } + + sealed class NetListPeer : NetComponentPeer, java.awt.peer.ListPeer + { + internal NetListPeer(java.awt.List target) + : base(target) + { + control.IntegralHeight = false; + setMultipleMode(target.isMultipleMode()); + for (int i = 0; i < target.getItemCount(); i++) + { + add(target.getItem(i), i); + if (target.isSelected(i)) + { + select(i); + } + } + makeVisible(target.getVisibleIndex()); + } + + public void add(string item, int index) + { + NetToolkit.Invoke(delegate { control.Items.Insert(index, item); }); + } + + public void addItem(string item, int index) + { + add(item, index); + } + + public void clear() + { + NetToolkit.Invoke(delegate { control.Items.Clear(); }); + } + + public void delItems(int start_index, int end_index) + { + NetToolkit.Invoke(delegate + { + for (int i = start_index; i < end_index; i++) + { + control.Items.RemoveAt(start_index); + } + }); + } + + public void deselect(int index) + { + NetToolkit.Invoke(delegate { control.SelectedIndices.Remove(index); }); + } + + public int[] getSelectedIndexes() + { + return NetToolkit.Invoke(delegate + { + ListBox.SelectedIndexCollection sic = control.SelectedIndices; + int[] indexes = new int[sic.Count]; + sic.CopyTo(indexes, 0); + return indexes; + }); + } + + public void makeVisible(int index) + { + NetToolkit.Invoke(delegate { control.TopIndex = index; }); + } + + public java.awt.Dimension minimumSize(int s) + { + return getMinimumSize(s); + } + + public java.awt.Dimension preferredSize(int s) + { + return getPreferredSize(s); + } + + public void removeAll() + { + clear(); + } + + public void select(int index) + { + NetToolkit.Invoke(delegate { control.SelectedIndices.Add(index); }); + } + + public void setMultipleMode(bool multi) + { + NetToolkit.Invoke(delegate { control.SelectionMode = multi ? SelectionMode.MultiSimple : SelectionMode.One; }); + } + + public void setMultipleSelections(bool multi) + { + setMultipleMode(multi); + } + + public java.awt.Dimension getPreferredSize(int s) + { + return getMinimumSize(s); + } + + public java.awt.Dimension getMinimumSize(int s) + { + return new java.awt.Dimension(100, 100); + } + + protected override ListBox CreateControl() + { + return new ListBox(); + } + } + + sealed class NetDesktopPeer : java.awt.peer.DesktopPeer + { + private static void ShellExecute(string file, string verb) + { + try + { + ProcessStartInfo psi = new ProcessStartInfo(file); + psi.UseShellExecute = true; + psi.Verb = verb; + Process p = Process.Start(psi); + if (p != null) + { + p.Dispose(); + } + } + catch (System.ComponentModel.Win32Exception x) + { + throw new java.io.IOException(x.Message); + } + } + + public void browse(URI uri) + { + ShellExecute(uri.toString(), "open"); + } + + public void edit(java.io.File f) + { + ShellExecute(f.toString(), "edit"); + } + + public bool isSupported(java.awt.Desktop.Action da) + { + return da == java.awt.Desktop.Action.BROWSE + || da == java.awt.Desktop.Action.EDIT + || da == java.awt.Desktop.Action.MAIL + || da == java.awt.Desktop.Action.OPEN + || da == java.awt.Desktop.Action.PRINT; + } + + public void mail(URI uri) + { + if (uri.getScheme().ToLower(System.Globalization.CultureInfo.InvariantCulture) != "mailto") + { + throw new java.lang.IllegalArgumentException("URI scheme is not \"mailto\""); + } + ShellExecute(uri.toString(), "open"); + } + + public void mail() + { + ShellExecute("mailto:", "open"); + } + + public void open(java.io.File f) + { + ShellExecute(f.toString(), "open"); + } + + public void print(java.io.File f) + { + ShellExecute(f.toString(), "print"); + } + } + + //also WFileDialogPeer extends from WWindowPeer + class NetFileDialogPeer : NetWindowPeer, java.awt.peer.FileDialogPeer + { + internal NetFileDialogPeer(java.awt.FileDialog dialog, bool isFocusableWindow, bool isAlwaysOnTop) + : base(dialog, isFocusableWindow, isAlwaysOnTop) + { + } + + public void setDirectory(string str) + { + } + + public void setFile(string str) + { + } + + public void setFilenameFilter(java.io.FilenameFilter ff) + { + } + + public void setResizable(bool b) + { + } + + public void setTitle(string str) + { + } + + public override void show() + { + java.awt.FileDialog dialog = (java.awt.FileDialog)target; + if (dialog.getMode() != java.awt.FileDialog.LOAD) + { + throw new NotImplementedException(); + } + Thread t = new Thread((ThreadStart)delegate + { + using (OpenFileDialog dlg = new OpenFileDialog()) + { + if (dlg.ShowDialog() == DialogResult.OK) + { + dialog.setFile(Path.GetFileName(dlg.FileName)); + dialog.setDirectory(Path.GetDirectoryName(dlg.FileName) + java.io.File.separator); + dialog.hide(); + } + else + { + dialog.setFile(null); + dialog.hide(); + } + } + }); + t.SetApartmentState(ApartmentState.STA); + t.Start(); + } + + public void blockWindows(List toBlock) + { + // code copies from sun.awt.windows.WFileDialogPeer.java + for (Iterator it = toBlock.iterator(); it.hasNext(); ) { + java.awt.Window w = (java.awt.Window)it.next(); + java.awt.peer.WindowPeer wp = (java.awt.peer.WindowPeer)AWTAccessor.getComponentAccessor().getPeer(w); + if (wp != null) { + wp.setModalBlocked((java.awt.Dialog)target, true); + } + } + } + } + + class NetSystemTrayPeer : java.awt.peer.SystemTrayPeer + { + //private java.awt.SystemTray target; + + internal NetSystemTrayPeer(java.awt.SystemTray target) + { + //this.target = target; + } + + public java.awt.Dimension getTrayIconSize() + { + return new java.awt.Dimension(NetTrayIconPeer.TRAY_ICON_WIDTH, NetTrayIconPeer.TRAY_ICON_HEIGHT); + } + + public bool isSupported() + { + return ((NetToolkit) java.awt.Toolkit.getDefaultToolkit()).isTraySupported(); + } + } + + sealed class NetPopupMenuPeer : java.awt.peer.PopupMenuPeer + { + private readonly java.awt.PopupMenu target; + private readonly ContextMenu menu = new ContextMenu(); + + internal NetPopupMenuPeer(java.awt.PopupMenu target) + { + this.target = target; + for (int i = 0; i < target.getItemCount(); i++) + { + addItem(target.getItem(i)); + } + } + + public void show(java.awt.Event e) + { + show((java.awt.Component)e.target, new java.awt.Point(e.x, e.y)); + } + + public void show(java.awt.Component origin, java.awt.Point p) + { + NetComponentPeer peer = (NetComponentPeer)origin.getPeer(); + Point pt = new Point(p.x, p.y); + pt.Offset(- peer.getInsetsLeft(), - peer.getInsetsTop()); + NetToolkit.Invoke(delegate { menu.Show(peer.Control, pt); }); + } + + public void dispose() + { + NetToolkit.Invoke(delegate { menu.Dispose(); }); + } + + public void setFont(java.awt.Font f) + { + throw new NotImplementedException(); + } + + public void disable() + { + setEnabled(false); + } + + public void enable() + { + setEnabled(true); + } + + public void setEnabled(bool b) + { + NetToolkit.Invoke(delegate + { + for (int i = 0; i < target.getItemCount(); i++) + { + menu.MenuItems[i].Enabled = b && target.getItem(i).isEnabled(); + } + }); + } + + public void setLabel(string str) + { + } + + public void addItem(java.awt.MenuItem item) + { + if (item.getPeer() == null) + { + item.addNotify(); + } + if (item.getPeer() is NetMenuItemPeer) + { + NetToolkit.Invoke(delegate { menu.MenuItems.Add(((NetMenuItemPeer)item.getPeer()).menuitem); }); + } + else + { + NetToolkit.Invoke(delegate { menu.MenuItems.Add(((NetMenuPeer)item.getPeer()).menu); }); + } + } + + public void addSeparator() + { + NetToolkit.Invoke(delegate { menu.MenuItems.Add(new MenuItem("-")); }); + } + + public void delItem(int i) + { + NetToolkit.Invoke(delegate { menu.MenuItems.RemoveAt(i); }); + } + } + + class NetTrayIconPeer : java.awt.peer.TrayIconPeer + { + internal const int TRAY_ICON_WIDTH = 16; + internal const int TRAY_ICON_HEIGHT = 16; + internal const int TRAY_ICON_MASK_SIZE = TRAY_ICON_WIDTH*TRAY_ICON_HEIGHT/8; + + private java.awt.TrayIcon target; + private NotifyIcon notifyIcon; + private java.awt.Frame popupParent = new java.awt.Frame("PopupMessageWindow"); + private java.awt.PopupMenu popup; + private bool disposed; + private bool isPopupMenu; + + internal NetTrayIconPeer(java.awt.TrayIcon target) + { + this.target = target; + popupParent.addNotify(); + create(); + updateImage(); + } + + public void displayMessage(string caption, string text, string messageType) + { + ToolTipIcon icon = ToolTipIcon.None; + switch(messageType) + { + case "ERROR" : + icon = ToolTipIcon.Error; + break; + case "WARNING" : + icon = ToolTipIcon.Warning; + break; + case "INFO" : + icon = ToolTipIcon.Info; + break; + case "NONE" : + icon = ToolTipIcon.None; + break; + } + NetToolkit.BeginInvoke(delegate + { + notifyIcon.ShowBalloonTip(10000, caption, text, icon); + }); + } + + private void create() + { + NetToolkit.Invoke(delegate + { + notifyIcon = new NotifyIcon(); + hookEvents(); + notifyIcon.Visible = true; + }); + } + + public void dispose() + { + bool callDisposed = true; + lock (this) + { + if (disposed) + callDisposed = false; + disposed = true; + } + if (callDisposed) + disposeImpl(); + } + + protected void disposeImpl() + { + if (popupParent != null) + { + popupParent.dispose(); + } + NetToolkit.targetDisposedPeer(target, this); + NetToolkit.BeginInvoke(nativeDispose); + } + + private void hookEvents() + { + notifyIcon.MouseClick += new MouseEventHandler(OnClick); + notifyIcon.MouseDoubleClick += new MouseEventHandler(OnDoubleClick); + notifyIcon.MouseDown += new MouseEventHandler(OnMouseDown); + notifyIcon.MouseUp += new MouseEventHandler(OnMouseUp); + notifyIcon.MouseMove += new MouseEventHandler(OnMouseMove); + } + + private void unhookEvents() + { + notifyIcon.MouseClick -= new MouseEventHandler(OnClick); + notifyIcon.MouseDoubleClick -= new MouseEventHandler(OnDoubleClick); + notifyIcon.MouseDown -= new MouseEventHandler(OnMouseDown); + notifyIcon.MouseUp -= new MouseEventHandler(OnMouseUp); + notifyIcon.MouseMove -= new MouseEventHandler(OnMouseMove); + } + + internal void postEvent(java.awt.AWTEvent evt) + { + NetToolkit.postEvent(NetToolkit.targetToAppContext(target), evt); + } + + private void postMouseEvent(MouseEventArgs ev, int id, int clicks) + { + long when = java.lang.System.currentTimeMillis(); + int modifiers = NetComponentPeer.GetMouseEventModifiers(ev); + int button = NetComponentPeer.GetButton(ev); + int clickCount = clicks; + int x = Control.MousePosition.X; + int y = Control.MousePosition.Y; + bool isPopup = isPopupMenu; + java.awt.EventQueue.invokeLater(Delegates.toRunnable(delegate + { + java.awt.Component fake = new java.awt.TextField(); + java.awt.@event.MouseEvent mouseEvent = new java.awt.@event.MouseEvent(fake, id, when, modifiers, x, y, clickCount, isPopup, button); + mouseEvent.setSource(target); + postEvent(mouseEvent); + })); + isPopupMenu = false; + } + + private void postMouseEvent(EventArgs ev, int id) + { + long when = java.lang.System.currentTimeMillis(); + int modifiers = NetComponentPeer.GetModifiers(Control.ModifierKeys); + int button = 0; + int clickCount = 0; + int x = Control.MousePosition.X; + int y = Control.MousePosition.Y; + bool isPopup = isPopupMenu; + java.awt.EventQueue.invokeLater(Delegates.toRunnable(delegate + { + java.awt.Component fake = new java.awt.TextField(); + java.awt.@event.MouseEvent mouseEvent = new java.awt.@event.MouseEvent(fake, id, when, modifiers, x, y, clickCount, isPopup, button); + mouseEvent.setSource(target); + postEvent(mouseEvent); + })); + isPopupMenu = false; + } + + protected virtual void OnMouseDown(object sender, MouseEventArgs ev) + { + isPopupMenu = false; + postMouseEvent(ev, java.awt.@event.MouseEvent.MOUSE_PRESSED, ev.Clicks); + } + + private void OnClick(object sender, MouseEventArgs ev) + { + postMouseEvent(ev, java.awt.@event.MouseEvent.MOUSE_CLICKED, ev.Clicks); + } + + private void OnDoubleClick(object sender, MouseEventArgs ev) + { + postMouseEvent(ev, java.awt.@event.MouseEvent.MOUSE_CLICKED, ev.Clicks); + long when = java.lang.System.currentTimeMillis(); + int modifiers = NetComponentPeer.GetModifiers(Control.ModifierKeys); + postEvent(new java.awt.@event.ActionEvent(target, java.awt.@event.ActionEvent.ACTION_PERFORMED, target.getActionCommand(), when, modifiers)); + } + + private void OnMouseUp(object sender, MouseEventArgs ev) + { + postMouseEvent(ev, java.awt.@event.MouseEvent.MOUSE_RELEASED, ev.Clicks); + } + + private void OnMouseEnter(object sender, EventArgs ev) + { + postMouseEvent(ev, java.awt.@event.MouseEvent.MOUSE_ENTERED); + } + + private void OnMouseLeave(object sender, EventArgs ev) + { + postMouseEvent(ev, java.awt.@event.MouseEvent.MOUSE_EXITED); + } + + protected virtual void OnMouseMove(object sender, MouseEventArgs ev) + { + if ((ev.Button & (MouseButtons.Left | MouseButtons.Right)) != 0) + { + postMouseEvent(ev, java.awt.@event.MouseEvent.MOUSE_DRAGGED, ev.Clicks); + } + else + { + postMouseEvent(ev, java.awt.@event.MouseEvent.MOUSE_MOVED, ev.Clicks); + } + } + + private void nativeDispose() + { + if (notifyIcon!=null) + { + unhookEvents(); + notifyIcon.Dispose(); + } + } + + public void setToolTip(string str) + { + NetToolkit.BeginInvoke(delegate { notifyIcon.Text = str; }); + } + + protected bool isDisposed() + { + return disposed; + } + + public void showPopupMenu(int x, int y) + { + if (isDisposed()) + return; + java.lang.Runnable runnable = Delegates.toRunnable(delegate + { + java.awt.PopupMenu newPopup = ((java.awt.TrayIcon)target).getPopupMenu(); + if (popup != newPopup) { + if (popup != null) { + popupParent.remove(popup); + } + if (newPopup != null) { + popupParent.add(newPopup); + } + popup = newPopup; + } + if (popup != null) { + ((NetPopupMenuPeer)popup.getPeer()).show(popupParent, new java.awt.Point(x, y)); + } + }); + SunToolkit.executeOnEventHandlerThread(target, runnable); + } + + public void updateImage() + { + java.awt.Image image = ((java.awt.TrayIcon) target).getImage(); + if (image != null) + { + updateNativeImage(image); + } + } + + private void updateNativeImage(java.awt.Image image) + { + lock (this) + { + if (isDisposed()) + return; + bool autosize = ((java.awt.TrayIcon) target).isImageAutoSize(); + + using (Bitmap bitmap = getNativeImage(image, autosize)) + { + IntPtr hicon = bitmap.GetHicon(); + Icon icon = Icon.FromHandle(hicon); + notifyIcon.Icon = icon; + } + } + } + + private Bitmap getNativeImage(java.awt.Image image, bool autosize) + { + if (image is NoImage) + return new Bitmap(TRAY_ICON_WIDTH, TRAY_ICON_HEIGHT); + else + { + Image netImage = J2C.ConvertImage(image); + if (autosize) + return new Bitmap(netImage, TRAY_ICON_WIDTH, TRAY_ICON_HEIGHT); + else + return new Bitmap(netImage); + } + } + } + + + internal class NetMouseInfoPeer : java.awt.peer.MouseInfoPeer + { + public int fillPointWithCoords(java.awt.Point p) + { + p.x = Cursor.Position.X; + p.y = Cursor.Position.Y; + //TODO multi screen device + return 0; //return the number of the screen device + } + + [DllImport("user32.dll")] + private static extern IntPtr WindowFromPoint(POINT Point); + + [StructLayout(LayoutKind.Sequential)] + private struct POINT + { + public int X; + public int Y; + + internal POINT(Point pt) + { + this.X = pt.X; + this.Y = pt.Y; + } + } + + [System.Security.SecuritySafeCritical] + public bool isWindowUnderMouse(java.awt.Window window) + { + if (NetToolkit.isWin32()) + { + NetWindowPeer peer = (NetWindowPeer)window.getPeer(); + if (peer != null) + { + IntPtr hWnd = WindowFromPoint(new POINT(Cursor.Position)); + return peer.control.Handle.Equals(hWnd); + } + return false; + } + else + { + throw new NotImplementedException(); + } + } + } + + public class NetClipboard : java.awt.datatransfer.Clipboard + { + public static readonly java.awt.datatransfer.FlavorTable flavorMap = + (java.awt.datatransfer.FlavorTable)java.awt.datatransfer.SystemFlavorMap.getDefaultFlavorMap(); + + public NetClipboard() : base("System") { } + + public override void setContents(java.awt.datatransfer.Transferable contents, java.awt.datatransfer.ClipboardOwner owner) + { + if (contents == null) + { + throw new java.lang.NullPointerException("contents"); + } + + java.awt.datatransfer.ClipboardOwner oldOwner = this.owner; + java.awt.datatransfer.Transferable oldContents = this.contents; + try + { + this.owner = owner; + this.contents = new sun.awt.datatransfer.TransferableProxy(contents, true); + + setContentsNative(contents); + } + finally + { + if (oldOwner != null && oldOwner != owner) + { + java.awt.EventQueue.invokeLater(Delegates.toRunnable(delegate() + { + oldOwner.lostOwnership(this, oldContents); + })); + } + } + } + + private void setContentsNative(java.awt.datatransfer.Transferable contents) + { + IDataObject clipObj = NetDataTransferer.getInstanceImpl().getDataObject(contents, flavorMap); + NetToolkit.BeginInvoke(delegate + { + Clipboard.SetDataObject(clipObj, true); + }); + } + + public override java.awt.datatransfer.Transferable getContents(object requestor) + { + if (contents != null) + { + return contents; + } + return new NetClipboardTransferable(NetToolkit.Invoke(Clipboard.GetDataObject)); + } + } + + public class NetClipboardTransferable : java.awt.datatransfer.Transferable + { + private readonly Map flavorToData = new HashMap(); + private readonly java.awt.datatransfer.DataFlavor[] flavors; + public NetClipboardTransferable(IDataObject data) + { + flavorToData = NetDataTransferer.getInstanceImpl().translateFromClipboard(data); + flavors = (java.awt.datatransfer.DataFlavor[])flavorToData.keySet().toArray(new java.awt.datatransfer.DataFlavor[0]); + } + + public java.awt.datatransfer.DataFlavor[] getTransferDataFlavors() + { + return flavors; + } + public object getTransferData(java.awt.datatransfer.DataFlavor df) + { + return flavorToData.get(df); + } + + public bool isDataFlavorSupported(java.awt.datatransfer.DataFlavor df) + { + return flavorToData.containsKey(df); + } + } + + public class NetDataTransferer : sun.awt.IkvmDataTransferer + { + class NetToolkitThreadBlockedHandler : sun.awt.datatransfer.ToolkitThreadBlockedHandler + { + private bool locked; + private Thread owner; + + protected bool isOwned() + { + return (locked && Thread.CurrentThread == owner); + } + + public void enter() + { + if (!isOwned()) + { + throw new java.lang.IllegalMonitorStateException(); + } + unlock(); + if (Application.MessageLoop) + { + Application.DoEvents(); + } + @lock(); + } + + public void exit() + { + if (!isOwned()) + { + throw new java.lang.IllegalMonitorStateException(); + } + } + + public void @lock() { + lock(this) + { + if (locked && Thread.CurrentThread == owner) + { + throw new java.lang.IllegalMonitorStateException(); + } + do + { + if (!locked) + { + locked = true; + owner = Thread.CurrentThread; + } + else + { + try + { + Monitor.Wait(this); + } + catch (ThreadInterruptedException) + { + // try again + } + } + } while (owner != Thread.CurrentThread); + } + } + + public void unlock() + { + lock (this) + { + if (Thread.CurrentThread != owner) + { + throw new java.lang.IllegalMonitorStateException(); + } + owner = null; + locked = false; + Monitor.Pulse(this); + } + } + } + + + private static readonly NetDataTransferer instance = new NetDataTransferer(); + private static readonly NetToolkitThreadBlockedHandler handler = new NetToolkitThreadBlockedHandler(); + + public static NetDataTransferer getInstanceImpl() + { + return instance; + } + + internal long[] getClipboardFormatCodes(string[] formats) + { + long[] longData = new long[formats.Length]; + for(int i=0; i*/ map = new HashMap(); + if (data == null) + { + return map; + } + string[] formats = data.GetFormats(); + if (formats != null && formats.Length > 0) + { + long[] longFormats = getClipboardFormatCodes(formats); + Map /**/ flavorMap = getFlavorsForFormats(longFormats, defaultFlavorMap); + java.awt.datatransfer.DataFlavor[] flavors = + (java.awt.datatransfer.DataFlavor[]) + (flavorMap.keySet().toArray(new java.awt.datatransfer.DataFlavor[0])); + for(int i=0; i + string[] nativeFileList = (string[])formatData; + List fileList = new ArrayList(nativeFileList.Length); + for (int j = 0; j < nativeFileList.Length; j++) + { + java.io.File file = new java.io.File(nativeFileList[i]); + fileList.add(file); + } + translatedData = fileList; + } + else if (java.awt.datatransfer.DataFlavor.imageFlavor.equals(df) && formatData is Bitmap) + { + // translate System.Drawing.Bitmap into java.awt.Image + translatedData = new java.awt.image.BufferedImage((Bitmap) formatData); + } + else if (formatData is string) + { + if (df.isFlavorTextType()) + translatedData = formatData; + else if (((java.lang.Class)typeof(java.io.Reader)).equals(df.getRepresentationClass())) + translatedData = new java.io.StringReader((string) formatData); + else if (((java.lang.Class)typeof(java.io.InputStream)).equals(df.getRepresentationClass())) + translatedData = new java.io.StringBufferInputStream((string)formatData); + else + throw new java.awt.datatransfer.UnsupportedFlavorException(df); + } + if (translatedData!=null) + map.put(df, translatedData); + } + } + return map; + } + + internal IDataObject getDataObject(java.awt.datatransfer.Transferable transferable, java.awt.datatransfer.FlavorTable flavorMap) + { + DataObject obj = new DataObject(); + SortedMap/**/ formatMap = getFormatsForTransferable(transferable, flavorMap); + for (Iterator iterator = formatMap.entrySet().iterator(); iterator.hasNext();) + { + Map.Entry entry = (Map.Entry) iterator.next(); + java.lang.Long lFormat = (java.lang.Long) entry.getKey(); + long format = lFormat == null ? -1 : lFormat.longValue(); + java.awt.datatransfer.DataFlavor flavor = (java.awt.datatransfer.DataFlavor) entry.getValue(); + object contents = transferable.getTransferData(flavor); + if (contents==null) continue; + try + { + if (java.awt.datatransfer.DataFlavor.javaFileListFlavor.equals(flavor)) + { + List list = (List)contents; + System.Collections.Specialized.StringCollection files = + new System.Collections.Specialized.StringCollection(); + for (int i = 0; i < list.size(); i++) + { + files.Add(((java.io.File) list.get(i)).getAbsolutePath()); + } + obj.SetFileDropList(files); + } + else if (flavor.isFlavorTextType()) + { + if (contents is string) + { + obj.SetText((string) transferable.getTransferData(flavor)); + } + else + { + try + { + java.io.Reader reader = flavor.getReaderForText(transferable); + java.io.StringWriter writer = new java.io.StringWriter(); + char[] buffer = new char[1024]; + int n; + while ((n = reader.read(buffer)) != -1) + { + writer.write(buffer, 0, n); + } + obj.SetText(writer.toString()); + } + catch + { + } + } + } + else if (java.awt.datatransfer.DataFlavor.imageFlavor.equals(flavor)) + { + java.awt.Image image = contents as java.awt.Image; + if (image != null) + { + Image netImage = J2C.ConvertImage(image); + if (netImage != null) + { + obj.SetImage(netImage); + } + } + } + else if (flavor.isRepresentationClassCharBuffer()) + { + if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) + { + throw new IOException("cannot transfer non-text data as CharBuffer"); + } + java.nio.CharBuffer buffer = (java.nio.CharBuffer)contents; + int size = buffer.remaining(); + char[] chars = new char[size]; + buffer.get(chars, 0, size); + obj.SetText(new string(chars)); + } + else + { + // don't know what to do with it... + obj.SetData(transferable.getTransferData(flavor)); + } + } + catch (java.io.IOException e) + { + if (!(flavor.isMimeTypeEqual(java.awt.datatransfer.DataFlavor.javaJVMLocalObjectMimeType) && + e is java.io.NotSerializableException)) + { + e.printStackTrace(); + } + } + } + return obj; + } + + protected internal override string getClipboardFormatName(long format) + { + return getNativeClipboardFormatName(format); + } + + protected internal override byte[] imageToStandardBytes(java.awt.Image image, string mimeType) + { + if (image is NoImage) return null; + Image netImage = J2C.ConvertImage(image); + ImageFormat format; + switch(mimeType) + { + case "image/jpg": + case "image/jpeg": + format = ImageFormat.Jpeg; + break; + case "image/png": + format = ImageFormat.Png; + break; + case "image/gif": + format = ImageFormat.Gif; + break; + case "image/x-win-metafile": + case "image/x-wmf": + case "image/wmf": + format = ImageFormat.Wmf; + break; + default: + return null; + } + using(MemoryStream stream = new MemoryStream()) + { + netImage.Save(stream, format); + return stream.GetBuffer(); + } + } + + public override sun.awt.datatransfer.ToolkitThreadBlockedHandler getToolkitThreadBlockedHandler() + { + return handler; + } + + protected internal override java.io.ByteArrayOutputStream convertFileListToBytes(java.util.ArrayList fileList) + { + throw new ikvm.@internal.NotYetImplementedError(); + } + + protected internal override java.awt.Image platformImageBytesToImage(byte[] barr, long l) + { + throw new NotImplementedException(); + } + } + +} diff --git a/bin-x64/README b/bin-x64/README new file mode 100644 index 0000000..a5a34e6 --- /dev/null +++ b/bin-x64/README @@ -0,0 +1 @@ +This directory contains the Windows x64 specific version of JVM.DLL. diff --git a/bin-x86/README b/bin-x86/README new file mode 100644 index 0000000..1bc8cc7 --- /dev/null +++ b/bin-x86/README @@ -0,0 +1 @@ +This directory contains the Windows x86 specific version of JVM.DLL. diff --git a/bin/ikvm.exe.config b/bin/ikvm.exe.config new file mode 100644 index 0000000..8667890 --- /dev/null +++ b/bin/ikvm.exe.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/bin/ikvm.exe.manifest b/bin/ikvm.exe.manifest new file mode 100644 index 0000000..3dbbfde --- /dev/null +++ b/bin/ikvm.exe.manifest @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/bin/ikvmc.exe.config b/bin/ikvmc.exe.config new file mode 100644 index 0000000..8667890 --- /dev/null +++ b/bin/ikvmc.exe.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/bin/ikvmstub.exe.config b/bin/ikvmstub.exe.config new file mode 100644 index 0000000..8667890 --- /dev/null +++ b/bin/ikvmstub.exe.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/classpath/gnu/java/net/protocol/ikvmres/Handler.java b/classpath/gnu/java/net/protocol/ikvmres/Handler.java new file mode 100644 index 0000000..e122c48 --- /dev/null +++ b/classpath/gnu/java/net/protocol/ikvmres/Handler.java @@ -0,0 +1,329 @@ +/* + Copyright (C) 2002, 2003, 2004, 2005, 2006 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package gnu.java.net.protocol.ikvmres; + +import cli.System.Reflection.Assembly; +import java.net.*; +import java.io.*; + +class IkvmresURLConnection extends URLConnection +{ + private InputStream inputStream; + + IkvmresURLConnection(URL url) + { + super(url); + doOutput = false; + } + + public void connect() throws IOException + { + if(!connected) + { + String assembly = url.getHost(); + String resource = url.getFile(); + if(assembly == null || resource == null || !resource.startsWith("/")) + { + throw new MalformedURLException(url.toString()); + } + try + { + inputStream = Handler.readResourceFromAssembly(assembly, url.getPort(), resource); + connected = true; + } + catch(cli.System.IO.FileNotFoundException x) + { + throw (IOException)new FileNotFoundException(assembly).initCause(x); + } + catch(cli.System.BadImageFormatException x1) + { + throw (IOException)new IOException().initCause(x1); + } + catch(cli.System.Security.SecurityException x2) + { + throw (IOException)new IOException().initCause(x2); + } + } + } + + public InputStream getInputStream() throws IOException + { + if(!connected) + { + connect(); + } + return inputStream; + } + + public OutputStream getOutputStream() throws IOException + { + throw new IOException("resource URLs are read only"); + } + + public long getLastModified() + { + return -1; + } + + public int getContentLength() + { + return -1; + } +} + +public class Handler extends URLStreamHandler +{ + private static final String RFC2396_DIGIT = "0123456789"; + private static final String RFC2396_LOWALPHA = "abcdefghijklmnopqrstuvwxyz"; + private static final String RFC2396_UPALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + private static final String RFC2396_ALPHA = RFC2396_LOWALPHA + RFC2396_UPALPHA; + private static final String RFC2396_ALPHANUM = RFC2396_DIGIT + RFC2396_ALPHA; + private static final String RFC2396_MARK = "-_.!~*'()"; + private static final String RFC2396_UNRESERVED = RFC2396_ALPHANUM + RFC2396_MARK; + private static final String RFC2396_REG_NAME = RFC2396_UNRESERVED + "$,;:@&=+"; + private static final String RFC2396_PCHAR = RFC2396_UNRESERVED + ":@&=+$,"; + private static final String RFC2396_SEGMENT = RFC2396_PCHAR + ";"; + private static final String RFC2396_PATH_SEGMENTS = RFC2396_SEGMENT + "/"; + + static InputStream readResourceFromAssembly(String assembly, int port, String resource) + throws cli.System.IO.FileNotFoundException, + cli.System.BadImageFormatException, + cli.System.Security.SecurityException, + IOException + { + if(assembly.equals("gen") && port != -1 && resource.endsWith(".class") && resource.indexOf('.') == resource.length() - 6) + { + ClassLoader loader = GetGenericClassLoaderById(port); + try + { + Class c = Class.forName(resource.substring(1, resource.length() - 6).replace('/', '.'), false, loader); + return new ByteArrayInputStream(GenerateStub(c)); + } + catch(ClassNotFoundException _) + { + } + catch(LinkageError _) + { + } + } + return readResourceFromAssembly(LoadAssembly(assembly), resource); + } + + public static InputStream readResourceFromAssembly(Assembly asm, String resource) + throws IOException + { + try + { + if(false) throw new cli.System.Security.SecurityException(); + if(false) throw new cli.System.IO.FileNotFoundException(); + if(false) throw new cli.System.IO.IOException(); + return new ikvm.io.InputStreamWrapper(ReadResourceFromAssemblyImpl(asm, resource)); + } + catch (cli.System.Security.SecurityException x) + { + throw (IOException)new IOException().initCause(x); + } + catch (cli.System.IO.FileNotFoundException x) + { + if(resource.endsWith(".class") && resource.indexOf('.') == resource.length() - 6) + { + Class c = LoadClassFromAssembly(asm, resource.substring(1, resource.length() - 6).replace('/', '.')); + if(c != null) + { + return new ByteArrayInputStream(GenerateStub(c)); + } + } + throw (FileNotFoundException)new FileNotFoundException().initCause(x); + } + catch(cli.System.IO.IOException x) + { + throw (IOException)new IOException().initCause(x); + } + } + + private static native byte[] GenerateStub(Class c); + private static native cli.System.IO.Stream ReadResourceFromAssemblyImpl(Assembly asm, String resource); + private static native Class LoadClassFromAssembly(Assembly asm, String className); + private static native Assembly LoadAssembly(String name) + throws cli.System.IO.FileNotFoundException, cli.System.BadImageFormatException, cli.System.Security.SecurityException; + private static native ClassLoader GetGenericClassLoaderById(int id); + + protected URLConnection openConnection(URL url) throws IOException + { + return new IkvmresURLConnection(url); + } + + protected void parseURL(URL url, String url_string, int start, int end) + { + try + { + // NOTE originally I wanted to use java.net.URI to handling parsing and constructing of these things, + // but it turns out that URI uses regex and that depends on resource loading... + url_string = url_string.substring(start, end); + if(url_string.startsWith("//")) + { + int slash = url_string.indexOf('/', 2); + if(slash == -1) + { + throw new RuntimeException("ikvmres: URLs must contain path"); + } + String assembly = unquote(url_string.substring(2, slash)); + String file = unquote(url_string.substring(slash)); + setURL(url, "ikvmres", assembly, -1, file, null); + } + else if(url_string.startsWith("/")) + { + setURL(url, "ikvmres", url.getHost(), -1, url_string, null); + } + else + { + String[] baseparts = ((cli.System.String)(Object)url.getFile()).Split(new char[] { '/' }); + String[] relparts = ((cli.System.String)(Object)url_string).Split(new char[] { '/' }); + String[] target = new String[baseparts.length + relparts.length - 1]; + for(int i = 1; i < baseparts.length; i++) + { + target[i - 1] = baseparts[i]; + } + int p = baseparts.length - 2; + for(int i = 0; i < relparts.length; i++) + { + if(relparts[i].equals(".")) + { + } + else if(relparts[i].equals("..")) + { + p = Math.max(0, p - 1); + } + else + { + target[p++] = relparts[i]; + } + } + StringBuffer file = new StringBuffer(); + for(int i = 0; i < p; i++) + { + file.append('/').append(target[i]); + } + setURL(url, "ikvmres", url.getHost(), -1, file.toString(), null); + } + } + catch(URISyntaxException x) + { + throw new RuntimeException(x.getMessage()); + } + } + + protected String toExternalForm(URL url) + { + // NOTE originally I wanted to use java.net.URI to handle parsing and constructing of these things, + // but it turns out that URI uses regex and that depends on resource loading... + return "ikvmres://" + quote(url.getHost(), RFC2396_REG_NAME) + quote(url.getFile(), RFC2396_PATH_SEGMENTS); + } + + protected InetAddress getHostAddress(URL url) + { + return null; + } + + private static String quote (String str, String legalCharacters) + { + StringBuffer sb = new StringBuffer(str.length()); + for (int i = 0; i < str.length(); i++) + { + char c = str.charAt(i); + if (legalCharacters.indexOf(c) == -1) + { + String hex = "0123456789ABCDEF"; + if (c <= 127) + { + sb.append('%') + .append(hex.charAt(c / 16)) + .append(hex.charAt(c % 16)); + } + else + { + try + { + // this is far from optimal, but it works + byte[] utf8 = str.substring(i, i + 1).getBytes("utf-8"); + for (int j = 0; j < utf8.length; j++) + { + sb.append('%') + .append(hex.charAt((utf8[j] & 0xff) / 16)) + .append(hex.charAt((utf8[j] & 0xff) % 16)); + } + } + catch (java.io.UnsupportedEncodingException x) + { + throw (Error)new InternalError().initCause(x); + } + } + } + else + { + sb.append(c); + } + } + return sb.toString(); + } + + private static String unquote (String str) + throws URISyntaxException + { + if (str == null) + return null; + byte[] buf = new byte[str.length()]; + int pos = 0; + for (int i = 0; i < str.length(); i++) + { + char c = str.charAt(i); + if (c > 127) + throw new URISyntaxException(str, "Invalid character"); + if (c == '%') + { + if (i + 2 >= str.length()) + throw new URISyntaxException(str, "Invalid quoted character"); + String hex = "0123456789ABCDEF"; + int hi = hex.indexOf(str.charAt(++i)); + int lo = hex.indexOf(str.charAt(++i)); + if (lo < 0 || hi < 0) + throw new URISyntaxException(str, "Invalid quoted character"); + buf[pos++] = (byte)(hi * 16 + lo); + } + else + { + buf[pos++] = (byte)c; + } + } + try + { + return new String(buf, 0, pos, "utf-8"); + } + catch (java.io.UnsupportedEncodingException x2) + { + throw (Error)new InternalError().initCause(x2); + } + } +} diff --git a/classpath/ikvm/extensions/ExtensionMethods.java b/classpath/ikvm/extensions/ExtensionMethods.java new file mode 100644 index 0000000..997777f --- /dev/null +++ b/classpath/ikvm/extensions/ExtensionMethods.java @@ -0,0 +1,565 @@ +/* + Copyright (C) 2008-2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package ikvm.extensions; + +import cli.System.Runtime.CompilerServices.ExtensionAttribute; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.util.Locale; + +@ExtensionAttribute.Annotation +public final class ExtensionMethods +{ + private ExtensionMethods() { } + + /* java.lang.Throwable methods */ + + @ExtensionAttribute.Annotation + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + public static void addSuppressed(Throwable t, Throwable exception) + { + t = ikvm.runtime.Util.mapException(t); + try + { + t.addSuppressed(exception); + } + finally + { + ikvm.runtime.Util.unmapException(t); + } + } + + @ExtensionAttribute.Annotation + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + public static Throwable fillInStackTrace(Throwable t) + { + t = ikvm.runtime.Util.mapException(t); + try + { + return t.fillInStackTrace(); + } + finally + { + ikvm.runtime.Util.unmapException(t); + } + } + + @ExtensionAttribute.Annotation + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + public static Throwable getCause(Throwable t) + { + t = ikvm.runtime.Util.mapException(t); + try + { + return t.getCause(); + } + finally + { + ikvm.runtime.Util.unmapException(t); + } + } + + @ExtensionAttribute.Annotation + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + public static String getLocalizedMessage(Throwable t) + { + t = ikvm.runtime.Util.mapException(t); + try + { + return t.getLocalizedMessage(); + } + finally + { + ikvm.runtime.Util.unmapException(t); + } + } + + @ExtensionAttribute.Annotation + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + public static String getMessage(Throwable t) + { + t = ikvm.runtime.Util.mapException(t); + try + { + return t.getMessage(); + } + finally + { + ikvm.runtime.Util.unmapException(t); + } + } + + @ExtensionAttribute.Annotation + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + public static StackTraceElement[] getStackTrace(Throwable t) + { + t = ikvm.runtime.Util.mapException(t); + try + { + return t.getStackTrace(); + } + finally + { + ikvm.runtime.Util.unmapException(t); + } + } + + @ExtensionAttribute.Annotation + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + public static Throwable[] getSuppressed(Throwable t) + { + t = ikvm.runtime.Util.mapException(t); + try + { + return t.getSuppressed(); + } + finally + { + ikvm.runtime.Util.unmapException(t); + } + } + + @ExtensionAttribute.Annotation + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + public static Throwable initCause(Throwable t, Throwable cause) + { + t = ikvm.runtime.Util.mapException(t); + try + { + return t.initCause(cause); + } + finally + { + ikvm.runtime.Util.unmapException(t); + } + } + + @ExtensionAttribute.Annotation + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + public static void printStackTrace(Throwable t) + { + t = ikvm.runtime.Util.mapException(t); + try + { + t.printStackTrace(); + } + finally + { + ikvm.runtime.Util.unmapException(t); + } + } + + @ExtensionAttribute.Annotation + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + public static void printStackTrace(Throwable t, PrintStream s) + { + t = ikvm.runtime.Util.mapException(t); + try + { + t.printStackTrace(s); + } + finally + { + ikvm.runtime.Util.unmapException(t); + } + } + + @ExtensionAttribute.Annotation + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + public static void printStackTrace(Throwable t, PrintWriter s) + { + t = ikvm.runtime.Util.mapException(t); + try + { + t.printStackTrace(s); + } + finally + { + ikvm.runtime.Util.unmapException(t); + } + } + + @ExtensionAttribute.Annotation + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + public static void setStackTrace(Throwable t, StackTraceElement[] stackTrace) + { + t = ikvm.runtime.Util.mapException(t); + try + { + t.setStackTrace(stackTrace); + } + finally + { + ikvm.runtime.Util.unmapException(t); + } + } + + /* java.lang.Object methods */ + + @ExtensionAttribute.Annotation + public static Class getClass(Object obj) + { + return obj.getClass(); + } + + @ExtensionAttribute.Annotation + public static void notify(Object obj) + { + obj.notify(); + } + + @ExtensionAttribute.Annotation + public static void notifyAll(Object obj) + { + obj.notifyAll(); + } + + @ExtensionAttribute.Annotation + public static String toString(Object obj) + { + return obj.toString(); + } + + @ExtensionAttribute.Annotation + public static void wait(Object obj) throws InterruptedException + { + obj.wait(); + } + + @ExtensionAttribute.Annotation + public static void wait(Object obj, long timeout, int nanos) throws InterruptedException + { + obj.wait(timeout, nanos); + } + + @ExtensionAttribute.Annotation + public static void wait(Object obj, long timeout) throws InterruptedException + { + obj.wait(timeout); + } + + /* java.lang.String methods */ + + @ExtensionAttribute.Annotation + public static int hashCode(String _this) + { + return _this.hashCode(); + } + + @ExtensionAttribute.Annotation + public static String substring(String _this, int beginIndex) + { + return _this.substring(beginIndex); + } + + @ExtensionAttribute.Annotation + public static int length(String _this) + { + return _this.length(); + } + + @ExtensionAttribute.Annotation + public static char charAt(String _this, int index) + { + return _this.charAt(index); + } + + @ExtensionAttribute.Annotation + public static String substring(String _this, int beginIndex, int endIndex) + { + return _this.substring(beginIndex, endIndex); + } + + @ExtensionAttribute.Annotation + public static int indexOf(String _this, int ch) + { + return _this.indexOf(ch); + } + + @ExtensionAttribute.Annotation + public static int indexOf(String _this, int ch, int fromIndex) + { + return _this.indexOf(ch, fromIndex); + } + + @ExtensionAttribute.Annotation + public static int indexOf(String _this, String str) + { + return _this.indexOf(str); + } + + @ExtensionAttribute.Annotation + public static int indexOf(String _this, String str, int fromIndex) + { + return _this.indexOf(str, fromIndex); + } + + @ExtensionAttribute.Annotation + public static int lastIndexOf(String _this, int ch) + { + return _this.lastIndexOf(ch); + } + + @ExtensionAttribute.Annotation + public static int lastIndexOf(String _this, int ch, int fromIndex) + { + return _this.lastIndexOf(ch, fromIndex); + } + + @ExtensionAttribute.Annotation + public static int lastIndexOf(String _this, String str) + { + return _this.lastIndexOf(str); + } + + @ExtensionAttribute.Annotation + public static int lastIndexOf(String _this, String str, int fromIndex) + { + return _this.lastIndexOf(str, fromIndex); + } + + @ExtensionAttribute.Annotation + public static char[] toCharArray(String _this) + { + return _this.toCharArray(); + } + + @ExtensionAttribute.Annotation + public static void getChars(String _this, int srcBegin, int srcEnd, char[] dst, int dstBegin) + { + _this.getChars(srcBegin, srcEnd, dst, dstBegin); + } + + @ExtensionAttribute.Annotation + public static boolean startsWith(String _this, String prefix) + { + return _this.startsWith(prefix); + } + + @ExtensionAttribute.Annotation + public static boolean startsWith(String _this, String prefix, int toffset) + { + return _this.startsWith(prefix, toffset); + } + + @ExtensionAttribute.Annotation + public static boolean endsWith(String _this, String suffix) + { + return _this.endsWith(suffix); + } + + @ExtensionAttribute.Annotation + public static String toUpperCase(String _this) + { + return _this.toUpperCase(); + } + + @ExtensionAttribute.Annotation + public static String toUpperCase(String _this, Locale locale) + { + return _this.toUpperCase(locale); + } + + @ExtensionAttribute.Annotation + public static String toLowerCase(String _this) + { + return _this.toLowerCase(); + } + + @ExtensionAttribute.Annotation + public static String toLowerCase(String _this, Locale locale) + { + return _this.toLowerCase(locale); + } + + @ExtensionAttribute.Annotation + public static int compareToIgnoreCase(String _this, String str) + { + return _this.compareToIgnoreCase(str); + } + + @ExtensionAttribute.Annotation + public static boolean equalsIgnoreCase(String _this, String anotherString) + { + return _this.equalsIgnoreCase(anotherString); + } + + @ExtensionAttribute.Annotation + public static String intern(String _this) + { + return _this.intern(); + } + + @ExtensionAttribute.Annotation + public static int compareTo(String _this, String anotherString) + { + return _this.compareTo(anotherString); + } + + @ExtensionAttribute.Annotation + public static String replace(String _this, char oldChar, char newChar) + { + return _this.replace(oldChar, newChar); + } + + @ExtensionAttribute.Annotation + public static byte[] getBytes(String _this) + { + return _this.getBytes(); + } + + @ExtensionAttribute.Annotation + public static byte[] getBytes(String _this, String charsetName) throws UnsupportedEncodingException + { + return _this.getBytes(charsetName); + } + + @ExtensionAttribute.Annotation + public static CharSequence subSequence(String _this, int beginIndex, int endIndex) + { + return _this.subSequence(beginIndex, endIndex); + } + + @ExtensionAttribute.Annotation + public static String trim(String _this) + { + return _this.trim(); + } + + @ExtensionAttribute.Annotation + public static boolean regionMatches(String _this, boolean ignoreCase, int toffset, String other, int ooffset, int len) + { + return _this.regionMatches(ignoreCase, toffset, other, ooffset, len); + } + + @ExtensionAttribute.Annotation + public static boolean regionMatches(String _this, int toffset, String other, int ooffset, int len) + { + return _this.regionMatches(toffset, other, ooffset, len); + } + + @ExtensionAttribute.Annotation + public static void getBytes(String _this, int srcBegin, int srcEnd, byte[] dst, int dstBegin) + { + _this.getBytes(srcBegin, srcEnd, dst, dstBegin); + } + + @ExtensionAttribute.Annotation + public static String concat(String _this, String str) + { + return _this.concat(str); + } + + @ExtensionAttribute.Annotation + public static boolean contains(String _this, CharSequence s) + { + return _this.contains(s); + } + + @ExtensionAttribute.Annotation + public static int codePointAt(String _this, int index) + { + return _this.codePointAt(index); + } + + @ExtensionAttribute.Annotation + public static int codePointBefore(String _this, int index) + { + return _this.codePointBefore(index); + } + + @ExtensionAttribute.Annotation + public static int codePointCount(String _this, int beginIndex, int endIndex) + { + return _this.codePointCount(beginIndex, endIndex); + } + + @ExtensionAttribute.Annotation + public static int offsetByCodePoints(String _this, int index, int codePointOffset) + { + return _this.offsetByCodePoints(index, codePointOffset); + } + + @ExtensionAttribute.Annotation + public static boolean contentEquals(String _this, CharSequence cs) + { + return _this.contentEquals(cs); + } + + @ExtensionAttribute.Annotation + public static boolean contentEquals(String _this, StringBuffer sb) + { + return _this.contentEquals(sb); + } + + @ExtensionAttribute.Annotation + public static String replace(String _this, CharSequence target, CharSequence replacement) + { + return _this.replace(target, replacement); + } + + @ExtensionAttribute.Annotation + public static boolean matches(String _this, String regex) + { + return _this.matches(regex); + } + + @ExtensionAttribute.Annotation + public static String replaceAll(String _this, String regex, String replacement) + { + return _this.replaceAll(regex, replacement); + } + + @ExtensionAttribute.Annotation + public static String replaceFirst(String _this, String regex, String replacement) + { + return _this.replaceFirst(regex, replacement); + } + + @ExtensionAttribute.Annotation + public static String[] split(String _this, String regex) + { + return _this.split(regex); + } + + @ExtensionAttribute.Annotation + public static String[] split(String _this, String regex, int limit) + { + return _this.split(regex, limit); + } + + @ExtensionAttribute.Annotation + public static boolean isEmpty(String _this) + { + return _this.isEmpty(); + } + + @ExtensionAttribute.Annotation + public static byte[] getBytes(String _this, Charset charset) + { + return _this.getBytes(charset); + } +} diff --git a/classpath/ikvm/internal/AssemblyClassLoader.java b/classpath/ikvm/internal/AssemblyClassLoader.java new file mode 100644 index 0000000..00d79de --- /dev/null +++ b/classpath/ikvm/internal/AssemblyClassLoader.java @@ -0,0 +1,157 @@ +/* + Copyright (C) 2006-2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +// HACK because of historical reasons this class' source lives in ikvm/internal instead of ikvm/runtime +package ikvm.runtime; + +import cli.System.Reflection.Assembly; +import gnu.java.util.EmptyEnumeration; +import ikvm.lang.Internal; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Enumeration; +import java.util.Vector; +import java.util.jar.Attributes; +import java.util.jar.Manifest; + +public final class AssemblyClassLoader extends ClassLoader +{ + private boolean packagesDefined; + + // This constructor is used to manually construct an AssemblyClassLoader that is used + // as a delegation parent for custom assembly class loaders. + // + // In that case the class loader object graph looks like this: + // + // +---------------------------------+ + // |IKVM.Internal.AssemblyClassLoader| + // +---------------------------------+ + // || /\ /\ + // \/ || || + // +-------------------+ || + // |Custom Class Loader| +--------------------------------+ + // +-------------------+ |ikvm.runtime.AssemblyClassLoader| + // +--------------------------------+ + // + public AssemblyClassLoader(Assembly assembly) + { + super(null); + setWrapper(assembly); + } + + private native void setWrapper(Assembly assembly); + + // this constructor is used by the runtime and calls a privileged + // ClassLoader constructor to avoid the security check + AssemblyClassLoader() + { + super(null, null); + } + + @Override + protected native Class loadClass(String name, boolean resolve) throws ClassNotFoundException; + + @Override + public native URL getResource(String name); + + @Override + public native Enumeration getResources(String name) throws IOException; + + @Override + protected native URL findResource(String name); + + @Override + protected native Enumeration findResources(String name) throws IOException; + + private synchronized void lazyDefinePackagesCheck() + { + if(!packagesDefined) + { + packagesDefined = true; + lazyDefinePackages(); + } + } + + private native void lazyDefinePackages(); + + @Override + protected Package getPackage(String name) + { + lazyDefinePackagesCheck(); + return super.getPackage(name); + } + + @Override + protected Package[] getPackages() + { + lazyDefinePackagesCheck(); + return super.getPackages(); + } + + @Override + public native String toString(); + + // return the ClassLoader for the assembly. Note that this doesn't have to be an AssemblyClassLoader. + public static native ClassLoader getAssemblyClassLoader(Assembly asm); +} + +final class GenericClassLoader extends ClassLoader +{ + // this constructor avoids the security check in ClassLoader by passing in null as the security manager + // to the IKVM specific constructor in ClassLoader + GenericClassLoader() + { + super(null, null); + } + + @Override + public native String toString(); + + @Override + public URL getResource(String name) + { + Enumeration e = getResources(name); + return e.hasMoreElements() + ? e.nextElement() + : null; + } + + @Override + public native Enumeration getResources(String name); + + @Override + protected native URL findResource(String name); + + @Override + protected Enumeration findResources(String name) + { + Vector v = new Vector(); + URL url = findResource(name); + if (url != null) + { + v.add(url); + } + return v.elements(); + } +} diff --git a/classpath/ikvm/internal/CallerID.java b/classpath/ikvm/internal/CallerID.java new file mode 100644 index 0000000..342e9ff --- /dev/null +++ b/classpath/ikvm/internal/CallerID.java @@ -0,0 +1,139 @@ +/* + Copyright (C) 2008-2015 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package ikvm.internal; + +import cli.System.Type; +import cli.System.Diagnostics.StackFrame; +import cli.System.Reflection.Assembly; + +public abstract class CallerID +{ + private Class clazz; + private ClassLoader classLoader; + + private CallerID(Class clazz, ClassLoader classLoader) + { + this.clazz = clazz; + this.classLoader = classLoader; + } + + protected CallerID() { } + + @ikvm.lang.Internal + public final Class getCallerClass() + { + if (clazz == null) + { + clazz = GetClass(); + } + return clazz; + } + + @ikvm.lang.Internal + public final ClassLoader getCallerClassLoader() + { + ClassLoader cl = classLoader; + if (cl == null) + { + cl = classLoader = GetClassLoader(); + if (cl == null) + { + cl = classLoader = ClassLoader.DUMMY; + } + } + return cl == ClassLoader.DUMMY ? null : cl; + } + + @ikvm.lang.Internal + public static CallerID create(cli.System.Diagnostics.StackFrame frame) + { + return create(frame.GetMethod()); + } + + @ikvm.lang.Internal + public static CallerID create(final cli.System.Reflection.MethodBase method) + { + return new CallerID() { + Class GetClass() { + if (method == null) { + // this happens if a native thread attaches and calls back into Java + return null; + } + Type type = method.get_DeclaringType(); + if (type == null) { + // TODO we probably should return a class corresponding to + throw new InternalError(); + } + return ikvm.runtime.Util.getClassFromTypeHandle(type.get_TypeHandle()); + } + ClassLoader GetClassLoader() { + if (method == null) { + // this happens if a native thread attaches and calls back into Java + return null; + } + Assembly asm = method.get_Module().get_Assembly(); + return GetAssemblyClassLoader(asm); + } + }; + } + + // this is a shortcut for use inside the core class library, it removes the need to create a nested type for every caller + @ikvm.lang.Internal + public static CallerID create(final cli.System.RuntimeTypeHandle typeHandle) + { + return new CallerID() { + Class GetClass() { + return ikvm.runtime.Util.getClassFromTypeHandle(typeHandle); + } + ClassLoader GetClassLoader() { + // since this optimization is only available inside the core class library, we know that the class loader is null + return null; + } + }; + } + + // used by the runtime for EmitHostCallerID and DynamicCallerID + static CallerID create(Class clazz, ClassLoader classLoader) + { + return new CallerID(clazz, classLoader) { + Class GetClass() { + return null; + } + ClassLoader GetClassLoader() { + return null; + } + }; + } + + @ikvm.lang.Internal + public static CallerID getCallerID() + { + // this is a compiler intrinsic, so there is no meaningful implementation here + return null; + } + + native Class GetClass(); + native ClassLoader GetClassLoader(); + static native ClassLoader GetAssemblyClassLoader(Assembly asm); +} diff --git a/classpath/ikvm/internal/Formatter.java b/classpath/ikvm/internal/Formatter.java new file mode 100644 index 0000000..b5f72ab --- /dev/null +++ b/classpath/ikvm/internal/Formatter.java @@ -0,0 +1,65 @@ +/* + Copyright (C) 2006 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package ikvm.internal; + +import cli.System.IFormatProvider; +import cli.System.IFormattable; +import ikvm.lang.CIL; +import ikvm.lang.Internal; + +@Internal +public final class Formatter +{ + private Formatter() {} + + public static String ToString(Byte b, String format, IFormatProvider provider) + { + return CIL.box_sbyte(b.byteValue()).ToString(format, provider); + } + + public static String ToString(Short s, String format, IFormatProvider provider) + { + return CIL.box_short(s.shortValue()).ToString(format, provider); + } + + public static String ToString(Integer i, String format, IFormatProvider provider) + { + return CIL.box_int(i.intValue()).ToString(format, provider); + } + + public static String ToString(Long l, String format, IFormatProvider provider) + { + return CIL.box_long(l.longValue()).ToString(format, provider); + } + + public static String ToString(Float f, String format, IFormatProvider provider) + { + return CIL.box_float(f.floatValue()).ToString(format, provider); + } + + public static String ToString(Double d, String format, IFormatProvider provider) + { + return CIL.box_double(d.doubleValue()).ToString(format, provider); + } +} diff --git a/classpath/ikvm/internal/JMath.java b/classpath/ikvm/internal/JMath.java new file mode 100644 index 0000000..e6b4de9 --- /dev/null +++ b/classpath/ikvm/internal/JMath.java @@ -0,0 +1,2661 @@ +/* + * ------------------------------------------------------------------------- + * $Id: JMath.java,v 1.2 2009/02/16 05:19:12 jfrijters Exp $ + * ------------------------------------------------------------------------- + * Copyright (c) 1999 Visual Numerics Inc. All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software is freely + * granted by Visual Numerics, Inc., provided that the copyright notice + * above and the following warranty disclaimer are preserved in human + * readable form. + * + * Because this software is licenses free of charge, it is provided + * "AS IS", with NO WARRANTY. TO THE EXTENT PERMITTED BY LAW, VNI + * DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO ITS PERFORMANCE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * VNI WILL NOT BE LIABLE FOR ANY DAMAGES WHATSOEVER ARISING OUT OF THE USE + * OF OR INABILITY TO USE THIS SOFTWARE, INCLUDING BUT NOT LIMITED TO DIRECT, + * INDIRECT, SPECIAL, CONSEQUENTIAL, PUNITIVE, AND EXEMPLARY DAMAGES, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * + * This Java code is based on C code in the package fdlibm, + * which can be obtained from www.netlib.org. + * The original fdlibm C code contains the following notice. + * + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * + *-------------------------------------------------------------------------- + */ + +package ikvm.internal; +import java.util.Random; + + +/* + * Pure Java implementation of the standard java.lang.Math class. + * This Java code is based on C code in the package fdlibm, + * which can be obtained from www.netlib.org. + * + * @author Sun Microsystems (original C code in fdlibm) + * @author John F. Brophy (translated from C to Java) + */ +@ikvm.lang.Internal +public final class JMath { + static public final double PI = 0x1.921fb54442d18p1; /* 3.14159265358979323846 */ + static public final double E = 2.7182818284590452354; + static private Random random; + + /** + * Returns the absolute value of its argument. + * @param x The argument, an integer. + * @return Returns |x|. + */ + strictfp public static int abs(int x) { + return ((x < 0) ? (-x) : x); + } + + /** + * Returns the absolute value of its argument. + * @param x The argument, a long. + * @return Returns |x|. + */ + strictfp public static long abs(long x) { + return ((x < 0L) ? (-x) : x); + } + + /** + * Returns the absolute value of its argument. + * @param x The argument, a float. + * @return Returns |x|. + */ + strictfp public static float abs(float x) { + return ((x <= 0.0f) ? (0.0f - x) : x); + } + + /** + * Returns the absolute value of its argument. + * @param x The argument, a double. + * @return Returns |x|. + */ + strictfp public static double abs(double x) { + return ((x <= 0.0) ? (0.0 - x) : x); + } + + /** + * Returns the smaller of its two arguments. + * @param x The first argument, an integer. + * @param y The second argument, an integer. + * @return Returns the smaller of x and y. + */ + strictfp public static int min(int x, int y) { + return ((x < y) ? x : y); + } + + /** + * Returns the smaller of its two arguments. + * @param x The first argument, a long. + * @param y The second argument, a long. + * @return Returns the smaller of x and y. + */ + strictfp public static long min(long x, long y) { + return ((x < y) ? x : y); + } + + /** + * Returns the smaller of its two arguments. + * @param x The first argument, a float. + * @param y The second argument, a float. + * @return Returns the smaller of x and y. + * This function considers -0.0f to + * be less than 0.0f. + */ + strictfp public static float min(float x, float y) { + if (Float.isNaN(x)) { + return x; + } + float ans = ((x <= y) ? x : y); + if ((ans == 0.0f) && (Float.floatToIntBits(y) == 0x80000000)) { + ans = y; + } + return ans; + } + + /** + * Returns the smaller of its two arguments. + * @param x The first argument, a double. + * @param y The second argument, a double. + * @return Returns the smaller of x and y. + * This function considers -0.0 to + * be less than 0.0. + */ + strictfp public static double min(double x, double y) { + if (Double.isNaN(x)) { + return x; + } + double ans = ((x <= y) ? x : y); + if ((x == 0.0) && (y == 0.0) && + (Double.doubleToLongBits(y) == 0x8000000000000000L)) { + ans = y; + } + return ans; + } + + /** + * Returns the larger of its two arguments. + * @param x The first argument, an integer. + * @param y The second argument, an integer. + * @return Returns the larger of x and y. + */ + strictfp public static int max(int x, int y) { + return ((x > y) ? x : y); + } + + /** + * Returns the larger of its two arguments. + * @param x The first argument, a long. + * @param y The second argument, a long. + * @return Returns the larger of x and y. + */ + strictfp public static long max(long x, long y) { + return ((x > y) ? x : y); + } + + /** + * Returns the larger of its two arguments. + * @param x The first argument, a float. + * @param y The second argument, a float. + * @return Returns the larger of x and y. + * This function considers -0.0f to + * be less than 0.0f. + */ + strictfp public static float max(float x, float y) { + if (Float.isNaN(x)) { + return x; + } + float ans = ((x >= y) ? x : y); + if ((ans == 0.0f) && (Float.floatToIntBits(x) == 0x80000000)) { + ans = y; + } + return ans; + } + + /** + * Returns the larger of its two arguments. + * @param x The first argument, a double. + * @param y The second argument, a double. + * @return Returns the larger of x and y. + * This function considers -0.0 to + * be less than 0.0. + */ + strictfp public static double max(double x, double y) { + if (Double.isNaN(x)) { + return x; + } + double ans = ((x >= y) ? x : y); + if ((x == 0.0) && (y == 0.0) && + (Double.doubleToLongBits(x) == 0x8000000000000000L)) { + ans = y; + } + return ans; + } + + /** + * Returns the integer closest to the arguments. + * @param x The argument, a float. + * @return Returns the integer closest to x. + */ + strictfp public static int round(float x) { + return (int) floor(x + 0.5f); + } + + /** + * Returns the long closest to the arguments. + * @param x The argument, a double. + * @return Returns the long closest to x. + */ + strictfp public static long round(double x) { + return (long) floor(x + 0.5); + } + + /** + * Returns the random number. + * @return Returns a random number from a uniform distribution. + */ + synchronized strictfp public static double random() { + if (random == null) { + random = new Random(); + } + return random.nextDouble(); + } + + /* + * This following code is derived from fdlibm, which contained + * the following notice. + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + static private final double huge = 1.0e+300; + static private final double tiny = 1.0e-300; + + /** + * Returns the value of its argument rounded toward + * positive infinity to an integral value. + * @param x The argument, a double. + * @return Returns the smallest double, not less than x, + * that is an integral value. + */ + static public double ceil(double x) { + int exp; + int sign; + long ix; + + if (x == 0) { + return x; + } + + ix = Double.doubleToLongBits(x); + sign = (int) ((ix >> 63) & 1); + exp = ((int) (ix >> 52) & 0x7ff) - 0x3ff; + + if (exp < 0) { + if (x < 0.0) { + return NEGATIVE_ZERO; + } else if (x == 0.0) { + return x; + } else { + return 1.0; + } + } else if (exp < 53) { + long mask = (0x000fffffffffffffL >>> exp); + if ((mask & ix) == 0) { + return x; // x is integral + } + if (x > 0.0) { + ix += (0x0010000000000000L >> exp); + } + ix = ix & (~mask); + } else if (exp == 1024) { // infinity + return x; + } + + return Double.longBitsToDouble(ix); + } + + /** + * Returns the value of its argument rounded toward + * negative infinity to an integral value. + * @param x The argument, a double. + * @return Returns the smallest double, not greater than x, + * that is an integral value. + */ + static public double floor(double x) { + int exp; + int sign; + long ix; + + if (x == 0) { + return x; + } + + ix = Double.doubleToLongBits(x); + sign = (int) ((ix >> 63) & 1); + exp = ((int) (ix >> 52) & 0x7ff) - 0x3ff; + + if (exp < 0) { + if (x < 0.0) { + return -1.0; + } else if (x == 0.0) { + return x; + } else { + return 0.0; + } + } else if (exp < 53) { + long mask = (0x000fffffffffffffL >>> exp); + if ((mask & ix) == 0) { + return x; // x is integral + } + if (x < 0.0) { + ix += (0x0010000000000000L >> exp); + } + ix = ix & (~mask); + } else if (exp == 1024) { // infinity + return x; + } + + return Double.longBitsToDouble(ix); + } + + static private final double[] TWO52 = { + 0x1.0p52, /* 4.50359962737049600000e+15 */ + -0x1.0p52 /* -4.50359962737049600000e+15 */ + }; + static private final double NEGATIVE_ZERO = -0x0.0p0; + + /** + * Returns the value of its argument rounded toward + * the closest integral value. + * @param x The argument, a double. + * @return Returns the double closest to x + * that is an integral value. + */ + static public double rint(double x) { + int exp; + int sign; + long ix; + double w; + + if (x == 0) { + return x; + } + + ix = Double.doubleToLongBits(x); + sign = (int) ((ix >> 63) & 1); + exp = ((int) (ix >> 52) & 0x7ff) - 0x3ff; + + if (exp < 0) { + if (x < -0.5) { + return -1.0; + } else if (x > 0.5) { + return 1.0; + } else if (sign == 0) { + return 0.0; + } else { + return NEGATIVE_ZERO; + } + } else if (exp < 53) { + long mask = (0x000fffffffffffffL >>> exp); + if ((mask & ix) == 0) { + return x; // x is integral + } + } else if (exp == 1024) { // infinity + return x; + } + + x = Double.longBitsToDouble(ix); + w = TWO52[sign] + x; + return w - TWO52[sign]; + } + + /** + * Returns x REM p = x - [x/p]*p as if in infinite + * precise arithmetic, where [x/p] is the (infinite bit) + * integer nearest x/p (in half way case choose the even one). + * @param x The dividend. + * @param y The divisor. + * @return The remainder computed according to the IEEE 754 standard. + */ + static public double IEEEremainder(double x, double p) { + int hx; + int hp; + int sx; // unsigned + int lx; // unsigned + int lp; // unsigned + double p_half; + + hx = __HI(x); /* high word of x */ + lx = __LO(x); /* low word of x */ + hp = __HI(p); /* high word of p */ + lp = __LO(p); /* low word of p */ + sx = hx & 0x80000000; + hp &= 0x7fffffff; + hx &= 0x7fffffff; + + /* purge off exception values */ + if ((hp | lp) == 0) { + return (x * p) / (x * p); /* p = 0 */ + } + + if ((hx >= 0x7ff00000) || /* x not finite */ + ((hp >= 0x7ff00000) && /* p is NaN */ + (((hp - 0x7ff00000) | lp) != 0))) { + return (x * p) / (x * p); + } + + if (hp <= 0x7fdfffff) { + x = x % (p + p); /* now x < 2p */ + } + + if (((hx - hp) | (lx - lp)) == 0) { + return zero * x; + } + + x = abs(x); + p = abs(p); + if (hp < 0x00200000) { + if ((x + x) > p) { + x -= p; + if ((x + x) >= p) { + x -= p; + } + } + } else { + p_half = 0.5 * p; + if (x > p_half) { + x -= p; + if (x >= p_half) { + x -= p; + } + } + } + lx = __HI(x); + lx ^= sx; + return setHI(x, lx); + } + + /* sqrt(x) + * Return correctly rounded sqrt. + * ------------------------------------------ + * | Use the hardware sqrt if you have one | + * ------------------------------------------ + * Method: + * Bit by bit method using integer arithmetic. (Slow, but portable) + * 1. Normalization + * Scale x to y in [1,4) with even powers of 2: + * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then + * sqrt(x) = 2^k * sqrt(y) + * 2. Bit by bit computation + * Let q = sqrt(y) truncated to i bit after binary point (q = 1), + * i 0 + * i+1 2 + * s = 2*q , and y = 2 * ( y - q ). (1) + * i i i i + * + * To compute q from q , one checks whether + * i+1 i + * + * -(i+1) 2 + * (q + 2 ) <= y. (2) + * i + * -(i+1) + * If (2) is false, then q = q ; otherwise q = q + 2 . + * i+1 i i+1 i + * + * With some algebric manipulation, it is not difficult to see + * that (2) is equivalent to + * -(i+1) + * s + 2 <= y (3) + * i i + * + * The advantage of (3) is that s and y can be computed by + * i i + * the following recurrence formula: + * if (3) is false + * + * s = s , y = y ; (4) + * i+1 i i+1 i + * + * otherwise, + * -i -(i+1) + * s = s + 2 , y = y - s - 2 (5) + * i+1 i i+1 i i + * + * One may easily use induction to prove (4) and (5). + * Note. Since the left hand side of (3) contain only i+2 bits, + * it does not necessary to do a full (53-bit) comparison + * in (3). + * 3. Final rounding + * After generating the 53 bits result, we compute one more bit. + * Together with the remainder, we can decide whether the + * result is exact, bigger than 1/2ulp, or less than 1/2ulp + * (it will never equal to 1/2ulp). + * The rounding mode can be detected by checking whether + * huge + tiny is equal to huge, and whether huge - tiny is + * equal to huge for some floating point number "huge" and "tiny". + * + * + * Special cases: + * sqrt(+-0) = +-0 ... exact + * sqrt(inf) = inf + * sqrt(-ve) = NaN ... with invalid signal + * sqrt(NaN) = NaN ... with invalid signal for signaling NaN + */ + + /** + * Returns the square root of its argument. + * @param x The argument, a double. + * @return Returns the square root of x. + */ + static public double sqrt(double x) { + long ix = Double.doubleToLongBits(x); + + /* take care of Inf and NaN */ + if ((ix & 0x7ff0000000000000L) == 0x7ff0000000000000L) { + + /* sqrt(NaN)=NaN, sqrt(+inf)=+inf sqrt(-inf)=sNaN */ + return (x * x) + x; + } + + /* take care of zero */ + if (x < 0.0) { + return Double.NaN; + } else if (x == 0.0) { + return x; /* sqrt(+-0) = +-0 */ + } + + /* normalize x */ + long m = (ix >> 52); + ix &= 0x000fffffffffffffL; + + /* add implicit bit, if not sub-normal */ + if (m != 0) { + ix |= 0x0010000000000000L; + } + + m -= 1023L; /* unbias exponent */ + if ((m & 1) != 0) { /* odd m, double x to make it even */ + ix += ix; + } + m >>= 1; /* m = [m/2] */ + m += 1023L; + + /* generate sqrt(x) bit by bit */ + ix += ix; + long q = 0L; /* q = sqrt(x) */ + long s = 0L; + long r = 0x0020000000000000L; /* r = moving bit from right to left */ + + while (r != 0) { + long t = s + r; + if (t <= ix) { + s = t + r; + ix -= t; + q += r; + } + ix += ix; + r >>= 1; + } + + /* round */ + if (ix != 0) { + q += (q & 1L); + } + + /* assemble result */ + ix = (m << 52) | (0x000fffffffffffffL & (q >> 1)); + return Double.longBitsToDouble(ix); + } + + static private final double[] halF = { 0.5, -0.5 }; + static private final double twom1000 = 0x1.0p-1000; /* 2**-1000=9.33263618503218878990e-302 */ + static private final double o_threshold = 0x1.62e42fefa39efp9; /* 7.09782712893383973096e+02 */ + static private final double u_threshold = -0x1.74910d52d3051p9; /* -7.45133219101941108420e+02 */ + static private final double[] ln2HI = { + 0x1.62e42feep-1, /* 6.93147180369123816490e-01 */ + -0x1.62e42feep-1 + }; /* -6.93147180369123816490e-01 */ + static private final double[] ln2LO = { + 0x1.a39ef35793c76p-33, /* 1.90821492927058770002e-10 */ + -0x1.a39ef35793c76p-33 + }; /* -1.90821492927058770002e-10 */ + static private final double invln2 = 0x1.71547652b82fep0; /* 1.44269504088896338700e+00 */ + static private final double P1 = 0x1.555555555553ep-3; /* 1.66666666666666019037e-01 */ + static private final double P2 = -0x1.6c16c16bebd93p-9; /* -2.77777777770155933842e-03 */ + static private final double P3 = 0x1.1566aaf25de2cp-14; /* 6.61375632143793436117e-05 */ + static private final double P4 = -0x1.bbd41c5d26bf1p-20; /* -1.65339022054652515390e-06 */ + static private final double P5 = 0x1.6376972bea4dp-25; /* 4.13813679705723846039e-08 */ + + /* exp(x) + * Returns the exponential of x. + * + * Method + * 1. Argument reduction: + * Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658. + * Given x, find r and integer k such that + * + * x = k*ln2 + r, |r| <= 0.5*ln2. + * + * Here r will be represented as r = hi-lo for better + * accuracy. + * + * 2. Approximation of exp(r) by a special rational function on + * the interval [0,0.34658]: + * Write + * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ... + * We use a special Reme algorithm on [0,0.34658] to generate + * a polynomial of degree 5 to approximate R. The maximum error + * of this polynomial approximation is bounded by 2**-59. In + * other words, + * R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5 + * (where z=r*r, and the values of P1 to P5 are listed below) + * and + * | 5 | -59 + * | 2.0+P1*z+...+P5*z - R(z) | <= 2 + * | | + * The computation of exp(r) thus becomes + * 2*r + * exp(r) = 1 + ------- + * R - r + * r*R1(r) + * = 1 + r + ----------- (for better accuracy) + * 2 - R1(r) + * where + * 2 4 10 + * R1(r) = r - (P1*r + P2*r + ... + P5*r ). + * + * 3. Scale back to obtain exp(x): + * From step 1, we have + * exp(x) = 2^k * exp(r) + * + * Special cases: + * exp(INF) is INF, exp(NaN) is NaN; + * exp(-INF) is 0, and + * for finite argument, only exp(0)=1 is exact. + * + * Accuracy: + * according to an error analysis, the error is always less than + * 1 ulp (unit in the last place). + * + * Misc. info. + * For IEEE double + * if x > 7.09782712893383973096e+02 then exp(x) overflow + * if x < -7.45133219101941108420e+02 then exp(x) underflow + */ + + /** + * Returns the exponential of its argument. + * @param x The argument, a double. + * @return Returns e to the power x. + */ + static public double exp(double x) { + double y; + double hi = 0; + double lo = 0; + double c; + double t; + int k = 0; + int xsb; + int hx; + + hx = __HI(x); /* high word of x */ + xsb = (hx >>> 31) & 1; /* sign bit of x */ + hx &= 0x7fffffff; /* high word of |x| */ + + /* filter out non-finite argument */ + if (hx >= 0x40862E42) { /* if |x|>=709.78... */ + if (hx >= 0x7ff00000) { + if (((hx & 0xfffff) | __LO(x)) != 0) { + return x + x; /* NaN */ + } else { + return ((xsb == 0) ? x : 0.0); /* exp(+-inf)={inf,0} */ + } + } + if (x > o_threshold) { + return huge * huge; /* overflow */ + } + if (x < u_threshold) { + return twom1000 * twom1000; /* underflow */ + } + } + + /* argument reduction */ + if (hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ + if (hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */ + hi = x - ln2HI[xsb]; + lo = ln2LO[xsb]; + k = 1 - xsb - xsb; + } else { + k = (int) ((invln2 * x) + halF[xsb]); + t = k; + hi = x - (t * ln2HI[0]); /* t*ln2HI is exact here */ + lo = t * ln2LO[0]; + } + x = hi - lo; + } else if (hx < 0x3e300000) { /* when |x|<2**-28 */ + if ((huge + x) > one) { + return one + x; /* trigger inexact */ + } + } else { + k = 0; + } + + /* x is now in primary range */ + t = x * x; + c = x - (t * (P1 + (t * (P2 + (t * (P3 + (t * (P4 + (t * P5))))))))); + if (k == 0) { + return one - (((x * c) / (c - 2.0)) - x); + } else { + y = one - ((lo - ((x * c) / (2.0 - c))) - hi); + } + + long iy = Double.doubleToLongBits(y); + if (k >= -1021) { + iy += ((long) k << 52); + } else { + iy += ((k + 1000L) << 52); + } + return Double.longBitsToDouble(iy); + } + + static private final double ln2_hi = 0x1.62e42feep-1; /* 6.93147180369123816490e-01 */ + static private final double ln2_lo = 0x1.a39ef35793c76p-33; /* 1.90821492927058770002e-10 */ + static private final double Lg1 = 0x1.5555555555593p-1; /* 6.666666666666735130e-01 */ + static private final double Lg2 = 0x1.999999997fa04p-2; /* 3.999999999940941908e-01 */ + static private final double Lg3 = 0x1.2492494229359p-2; /* 2.857142874366239149e-01 */ + static private final double Lg4 = 0x1.c71c51d8e78afp-3; /* 2.222219843214978396e-01 */ + static private final double Lg5 = 0x1.7466496cb03dep-3; /* 1.818357216161805012e-01 */ + static private final double Lg6 = 0x1.39a09d078c69fp-3; /* 1.531383769920937332e-01 */ + static private final double Lg7 = 0x1.2f112df3e5244p-3; /* 1.479819860511658591e-01 */ + + /* + * Return the logrithm of x + * + * Method : + * 1. Argument Reduction: find k and f such that + * x = 2^k * (1+f), + * where sqrt(2)/2 < 1+f < sqrt(2) . + * + * 2. Approximation of log(1+f). + * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) + * = 2s + 2/3 s**3 + 2/5 s**5 + ....., + * = 2s + s*R + * We use a special Reme algorithm on [0,0.1716] to generate + * a polynomial of degree 14 to approximate R The maximum error + * of this polynomial approximation is bounded by 2**-58.45. In + * other words, + * 2 4 6 8 10 12 14 + * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s + * (the values of Lg1 to Lg7 are listed in the program) + * and + * | 2 14 | -58.45 + * | Lg1*s +...+Lg7*s - R(z) | <= 2 + * | | + * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. + * In order to guarantee error in log below 1ulp, we compute log + * by + * log(1+f) = f - s*(f - R) (if f is not too large) + * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) + * + * 3. Finally, log(x) = k*ln2 + log(1+f). + * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) + * Here ln2 is split into two floating point number: + * ln2_hi + ln2_lo, + * where n*ln2_hi is always exact for |n| < 2000. + * + * Special cases: + * log(x) is NaN with signal if x < 0 (including -INF) ; + * log(+INF) is +INF; log(0) is -INF with signal; + * log(NaN) is that NaN with no signal. + * + * Accuracy: + * according to an error analysis, the error is always less than + * 1 ulp (unit in the last place). + */ + + /** + * Returns the natural logarithm of its argument. + * @param x The argument, a double. + * @return Returns the natural (base e) logarithm of x. + */ + static public double log(double x) { + double hfsq; + double f; + double s; + double z; + double R; + double w; + double t1; + double t2; + double dk; + int k; + int hx; + int i; + int j; + int lx; + + hx = __HI(x); /* high word of x */ + lx = __LO(x); /* low word of x */ + + k = 0; + if (hx < 0x00100000) { /* x < 2**-1022 */ + if (((hx & 0x7fffffff) | lx) == 0) { + return -two54 / zero; /* log(+-0)=-inf */ + } + if (hx < 0) { + return (x - x) / zero; /* log(-#) = NaN */ + } + k -= 54; + x *= two54; /* subnormal number, scale up x */ + hx = __HI(x); /* high word of x */ + } + if (hx >= 0x7ff00000) { + return x + x; + } + k += ((hx >> 20) - 1023); + hx &= 0x000fffff; + i = (hx + 0x95f64) & 0x100000; + x = setHI(x, hx | (i ^ 0x3ff00000)); /* normalize x or x/2 */ + k += (i >> 20); + f = x - 1.0; + if ((0x000fffff & (2 + hx)) < 3) { /* |f| < 2**-20 */ + if (f == zero) { + if (k == 0) { + return zero; + } else { + dk = (double) k; + } + return (dk * ln2_hi) + (dk * ln2_lo); + } + R = f * f * (0.5 - (0.33333333333333333 * f)); + if (k == 0) { + return f - R; + } else { + dk = (double) k; + return (dk * ln2_hi) - ((R - (dk * ln2_lo)) - f); + } + } + s = f / (2.0 + f); + dk = (double) k; + z = s * s; + i = hx - 0x6147a; + w = z * z; + j = 0x6b851 - hx; + t1 = w * (Lg2 + (w * (Lg4 + (w * Lg6)))); + t2 = z * (Lg1 + (w * (Lg3 + (w * (Lg5 + (w * Lg7)))))); + i |= j; + R = t2 + t1; + if (i > 0) { + hfsq = 0.5 * f * f; + if (k == 0) { + return f - (hfsq - (s * (hfsq + R))); + } else { + return (dk * ln2_hi) - + ((hfsq - ((s * (hfsq + R)) + (dk * ln2_lo))) - f); + } + } else { + if (k == 0) { + return f - (s * (f - R)); + } else { + return (dk * ln2_hi) - (((s * (f - R)) - (dk * ln2_lo)) - f); + } + } + } + + /** + * Returns the sine of its argument. + * @param x The argument, a double, assumed to be in radians. + * @return Returns the sine of x. + */ + static public double sin(double x) { + double z = 0.0; + int n; + int ix = __HI(x); + + ix &= 0x7fffffff; /* |x| ~< pi/4 */ + + if (ix <= 0x3fe921fb) { + return __kernel_sin(x, z, 0); + } else if (ix >= 0x7ff00000) { + + /* sin(Inf or NaN) is NaN */ + return x - x; + } else { + + /* argument reduction needed */ + double[] y = new double[2]; + n = __ieee754_rem_pio2(x, y); + switch (n & 3) { + case 0: + return __kernel_sin(y[0], y[1], 1); + case 1: + return __kernel_cos(y[0], y[1]); + case 2: + return -__kernel_sin(y[0], y[1], 1); + default: + return -__kernel_cos(y[0], y[1]); + } + } + } + + static private final double S1 = -1.66666666666666324348e-01; /* 0xBFC55555, 0x55555549 */ + static private final double S2 = 8.33333333332248946124e-03; /* 0x3F811111, 0x1110F8A6 */ + static private final double S3 = -1.98412698298579493134e-04; /* 0xBF2A01A0, 0x19C161D5 */ + static private final double S4 = 2.75573137070700676789e-06; /* 0x3EC71DE3, 0x57B1FE7D */ + static private final double S5 = -2.50507602534068634195e-08; /* 0xBE5AE5E6, 0x8A2B9CEB */ + static private final double S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */ + + /* + * kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854 + * Input x is assumed to be bounded by ~pi/4 in magnitude. + * Input y is the tail of x. * Input iy indicates whether y is 0. (if iy=0, y assume to be 0). + * + * Algorithm + * 1. Since sin(-x) = -sin(x), we need only to consider positive x. + * 2. if x < 2^-27 (hx<0x3e400000 0), return x with inexact if x!=0. + * 3. sin(x) is approximated by a polynomial of degree 13 on + * [0,pi/4] + * 3 13 + * sin(x) ~ x + S1*x + ... + S6*x + * where + * + * |sin(x) 2 4 6 8 10 12 | -58 + * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2 + * | x | + * + * 4. sin(x+y) = sin(x) + sin'(x')*y + * ~ sin(x) + (1-x*x/2)*y + * For better accuracy, let + * 3 2 2 2 2 + * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6)))) + * then 3 2 + * sin(x) = x + (S1*x + (x *(r-y/2)+y)) + */ + static double __kernel_sin(double x, double y, int iy) { + double z; + double r; + double v; + int ix; + ix = __HI(x) & 0x7fffffff; /* high word of x */ + if (ix < 0x3e400000) { /* |x| < 2**-27 */ + if ((int) x == 0) { + return x; /* generate inexact */ + } + } + z = x * x; + v = z * x; + r = S2 + (z * (S3 + (z * (S4 + (z * (S5 + (z * S6))))))); + if (iy == 0) { + return x + (v * (S1 + (z * r))); + } else { + return x - (((z * ((half * y) - (v * r))) - y) - (v * S1)); + } + } + + /** + * Returns the cosine of its argument. + * @param x The argument, a double, assumed to be in radians. + * @return Returns the cosine of x. + */ + static public double cos(double x) { + double z = 0.0; + int n; + int ix; + + /* High word of x. */ + ix = __HI(x); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffff; + if (ix <= 0x3fe921fb) { + return __kernel_cos(x, z); + + /* cos(Inf or NaN) is NaN */ + } else if (ix >= 0x7ff00000) { + return x - x; + + /* argument reduction needed */ + } else { + double[] y = new double[2]; + n = __ieee754_rem_pio2(x, y); + switch (n & 3) { + case 0: + return __kernel_cos(y[0], y[1]); + case 1: + return -__kernel_sin(y[0], y[1], 1); + case 2: + return -__kernel_cos(y[0], y[1]); + default: + return __kernel_sin(y[0], y[1], 1); + } + } + } + + static private final double one = 0x1.0p0; /* 1.00000000000000000000e+00 */ + static private final double C1 = 0x1.555555555554cp-5; /* 4.16666666666666019037e-02 */ + static private final double C2 = -0x1.6c16c16c15177p-10; /* -1.38888888888741095749e-03 */ + static private final double C3 = 0x1.a01a019cb159p-16; /* 2.48015872894767294178e-05 */ + static private final double C4 = -0x1.27e4f809c52adp-22; /* -2.75573143513906633035e-07 */ + static private final double C5 = 0x1.1ee9ebdb4b1c4p-29; /* 2.08757232129817482790e-09 */ + static private final double C6 = -0x1.8fae9be8838d4p-37; /* -1.13596475577881948265e-11 */ + + /* + * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 + * Input x is assumed to be bounded by ~pi/4 in magnitude. + * Input y is the tail of x. + * + * Algorithm + * 1. Since cos(-x) = cos(x), we need only to consider positive x. + * 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0. + * 3. cos(x) is approximated by a polynomial of degree 14 on + * [0,pi/4] + * 4 14 + * cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x + * where the remez error is + * + * | 2 4 6 8 10 12 14 | -58 + * |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2 + * | | + * + * 4 6 8 10 12 14 + * 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then + * cos(x) = 1 - x*x/2 + r + * since cos(x+y) ~ cos(x) - sin(x)*y + * ~ cos(x) - x*y, + * a correction term is necessary in cos(x) and hence + * cos(x+y) = 1 - (x*x/2 - (r - x*y)) + * For better accuracy when x > 0.3, let qx = |x|/4 with + * the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125. + * Then + * cos(x+y) = (1-qx) - ((x*x/2-qx) - (r-x*y)). + * Note that 1-qx and (x*x/2-qx) is EXACT here, and the + * magnitude of the latter is at least a quarter of x*x/2, + * thus, reducing the rounding error in the subtraction. + */ + static private double __kernel_cos(double x, double y) { + double a; + double hz; + double z; + double r; + double qx = zero; + int ix; + ix = __HI(x) & 0x7fffffff; /* ix = |x|'s high word*/ + if (ix < 0x3e400000) { + + /* if x < 2**27 */ + if (((int) x) == 0) { + return one; /* generate inexact */ + } + } + z = x * x; + r = z * (C1 + + (z * (C2 + (z * (C3 + (z * (C4 + (z * (C5 + (z * C6)))))))))); + if (ix < 0x3FD33333) { + + /* if |x| < 0.3 */ + return one - ((0.5 * z) - ((z * r) - (x * y))); + } else { + if (ix > 0x3fe90000) { /* x > 0.78125 */ + qx = 0.28125; + } else { + qx = set(ix - 0x00200000, 0); /* x/4 */ + } + hz = (0.5 * z) - qx; + a = one - qx; + return a - (hz - ((z * r) - (x * y))); + } + } + + /** + * Returns the tangent of its argument. + * @param x The argument, a double, assumed to be in radians. + * @return Returns the tangent of x. + */ + static public double tan(double x) { + double z = zero; + + int n; + int ix = __HI(x); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffff; + if (ix <= 0x3fe921fb) { + return __kernel_tan(x, z, 1); + } else if (ix >= 0x7ff00000) { + + /* tan(Inf or NaN) is NaN */ + return x - x; /* NaN */ + } else { + + /* argument reduction needed */ + double[] y = new double[2]; + n = __ieee754_rem_pio2(x, y); + + /* 1 -- n even -1 -- n odd */ + return __kernel_tan(y[0], y[1], 1 - ((n & 1) << 1)); + } + } + + static private final double pio4 = 0x1.921fb54442d18p-1; /* 7.85398163397448278999e-01 */ + static private final double pio4lo = 0x1.1a62633145c07p-55; /* 3.06161699786838301793e-17 */ + static private final double[] T = { + 0x1.5555555555563p-2, /* 3.33333333333334091986e-01 */ + 0x1.111111110fe7ap-3, /* 1.33333333333201242699e-01 */ + 0x1.ba1ba1bb341fep-5, /* 5.39682539762260521377e-02 */ + 0x1.664f48406d637p-6, /* 2.18694882948595424599e-02 */ + 0x1.226e3e96e8493p-7, /* 8.86323982359930005737e-03 */ + 0x1.d6d22c9560328p-9, /* 3.59207910759131235356e-03 */ + 0x1.7dbc8fee08315p-10, /* 1.45620945432529025516e-03 */ + 0x1.344d8f2f26501p-11, /* 5.88041240820264096874e-04 */ + 0x1.026f71a8d1068p-12, /* 2.46463134818469906812e-04 */ + 0x1.47e88a03792a6p-14, /* 7.81794442939557092300e-05 */ + 0x1.2b80f32f0a7e9p-14, /* 7.14072491382608190305e-05 */ + -0x1.375cbdb605373p-16, /* -1.85586374855275456654e-05 */ + 0x1.b2a7074bf7ad4p-16 /* 2.59073051863633712884e-05 */ + }; + + /* + * __kernel_tan( x, y, k ) + * kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854 + * Input x is assumed to be bounded by ~pi/4 in magnitude. + * Input y is the tail of x. * Input k indicates whether tan (if k=1) or + * -1/tan (if k= -1) is returned. * * Algorithm + * 1. Since tan(-x) = -tan(x), we need only to consider positive x. + * 2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0. + * 3. tan(x) is approximated by a odd polynomial of degree 27 on + * [0,0.67434] + * 3 27 + * tan(x) ~ x + T1*x + ... + T13*x + * where + * + * |tan(x) 2 4 26 | -59.2 + * |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2 + * | x | + * + * Note: tan(x+y) = tan(x) + tan'(x)*y + * ~ tan(x) + (1+x*x)*y + * Therefore, for better accuracy in computing tan(x+y), let + * 3 2 2 2 2 + * r = x *(T2+x *(T3+x *(...+x *(T12+x *T13)))) + * then + * 3 2 + * tan(x+y) = x + (T1*x + (x *(r+y)+y)) * + * 4. For x in [0.67434,pi/4], let y = pi/4 - x, then + * tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y)) + * = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y))) + */ + static private double __kernel_tan(double x, double y, int iy) { + double z; + double r; + double v; + double w; + double s; + int ix; + int hx; + + hx = __HI(x); /* high word of x */ + ix = hx & 0x7fffffff; /* high word of |x| */ + if (ix < 0x3e300000) { /* x < 2**-28 */ + if ((int) x == 0) { /* generate inexact */ + if (((ix | __LO(x)) | (iy + 1)) == 0) { + return one / abs(x); + } else { + return (iy == 1) ? x : (-one / x); + } + } + } + if (ix >= 0x3FE59428) { + + /* |x|>=0.6744 */ + if (hx < 0) { + x = -x; + y = -y; + } + z = pio4 - x; + w = pio4lo - y; + x = z + w; + y = 0.0; + } + z = x * x; + w = z * z; + + /* + * Break x^5*(T[1]+x^2*T[2]+...) into + * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) + + * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12])) + */ + r = T[1] + + (w * (T[3] + + (w * (T[5] + (w * (T[7] + (w * (T[9] + (w * T[11]))))))))); + v = z * (T[2] + + (w * (T[4] + + (w * (T[6] + (w * (T[8] + (w * (T[10] + (w * T[12])))))))))); + s = z * x; + r = y + (z * ((s * (r + v)) + y)); + r += (T[0] * s); + w = x + r; + if (ix >= 0x3FE59428) { + v = (double) iy; + return (double) (1 - ((hx >> 30) & 2)) * (v - + (2.0 * (x - (((w * w) / (w + v)) - r)))); + } + if (iy == 1) { + return w; + } else { + + /* if allow error up to 2 ulp, simply return -1.0/(x+r) here */ + /* compute -1.0/(x+r) accurately */ + double a; + + /* if allow error up to 2 ulp, simply return -1.0/(x+r) here */ + /* compute -1.0/(x+r) accurately */ + double t; + z = w; + z = setLO(z, 0); + v = r - (z - x); + + /* z+v = r+x */ + t = a = -1.0 / w; + + /* a = -1.0/w */ + t = setLO(t, 0); + s = 1.0 + (t * z); + return t + (a * (s + (t * v))); + } + } + + static private final double pio2_hi = 0x1.921fb54442d18p0; /* 1.57079632679489655800e+00 */ + static private final double pio2_lo = 0x1.1a62633145c07p-54; /* 6.12323399573676603587e-17 */ + static private final double pio4_hi = 0x1.921fb54442d18p-1; /* 7.85398163397448278999e-01 */ + + /* coefficient for R(x^2) */ + static private final double pS0 = 0x1.5555555555555p-3; /* 1.66666666666666657415e-01 */ + static private final double pS1 = -0x1.4d61203eb6f7dp-2; /* -3.25565818622400915405e-01 */ + static private final double pS2 = 0x1.9c1550e884455p-3; /* 2.01212532134862925881e-01 */ + static private final double pS3 = -0x1.48228b5688f3bp-5; /* -4.00555345006794114027e-02 */ + static private final double pS4 = 0x1.9efe07501b288p-11; /* 7.91534994289814532176e-04 */ + static private final double pS5 = 0x1.23de10dfdf709p-15; /* 3.47933107596021167570e-05 */ + static private final double qS1 = -0x1.33a271c8a2d4bp1; /* -2.40339491173441421878e+00 */ + static private final double qS2 = 0x1.02ae59c598ac8p1; /* 2.02094576023350569471e+00 */ + static private final double qS3 = -0x1.6066c1b8d0159p-1; /* -6.88283971605453293030e-01 */ + static private final double qS4 = 0x1.3b8c5b12e9282p-4; /* 7.70381505559019352791e-02 */ + + /* + * asin(x) + * Method : + * Since asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ... + * we approximate asin(x) on [0,0.5] by + * asin(x) = x + x*x^2*R(x^2) + * where + * R(x^2) is a rational approximation of (asin(x)-x)/x^3 + * and its remez error is bounded by + * |(asin(x)-x)/x^3 - R(x^2)| < 2^(-58.75) + * + * For x in [0.5,1] + * asin(x) = pi/2-2*asin(sqrt((1-x)/2)) + * Let y = (1-x), z = y/2, s := sqrt(z), and pio2_hi+pio2_lo=pi/2; + * then for x>0.98 + * asin(x) = pi/2 - 2*(s+s*z*R(z)) + * = pio2_hi - (2*(s+s*z*R(z)) - pio2_lo) + * For x<=0.98, let pio4_hi = pio2_hi/2, then + * f = hi part of s; + * c = sqrt(z) - f = (z-f*f)/(s+f) ...f+c=sqrt(z) + * and + * asin(x) = pi/2 - 2*(s+s*z*R(z)) + * = pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo) + * = pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c)) + * + * Special cases: + * if x is NaN, return x itself; + * if |x|>1, return NaN with invalid signal. + * + */ + + /** + * Returns the inverse (arc) sine of its argument. + * @param x The argument, a double. + * @return Returns the angle, in radians, whose sine is x. + * It is in the range [-pi/2,pi/2]. + */ + static public double asin(double x) { + double t = zero; + double w; + double p; + double q; + double c; + double r; + double s; + int hx; + int ix; + hx = __HI(x); + + ix = hx & 0x7fffffff; + if (ix >= 0x3ff00000) { /* |x|>= 1 */ + if (((ix - 0x3ff00000) | __LO(x)) == 0) { + + /* asin(1)=+-pi/2 with inexact */ + return (x * pio2_hi) + (x * pio2_lo); + } + return (x - x) / (x - x); /* asin(|x|>1) is NaN */ + } else if (ix < 0x3fe00000) { /* |x|<0.5 */ + if (ix < 0x3e400000) { /* if |x| < 2**-27 */ + if ((huge + x) > one) { + return x; /* return x with inexact if x!=0*/ + } + } else { + t = x * x; + } + p = t * (pS0 + + (t * (pS1 + + (t * (pS2 + (t * (pS3 + (t * (pS4 + (t * pS5)))))))))); + q = one + (t * (qS1 + (t * (qS2 + (t * (qS3 + (t * qS4))))))); + w = p / q; + return x + (x * w); + } + + /* 1> |x|>= 0.5 */ + w = one - abs(x); + t = w * 0.5; + p = t * (pS0 + + (t * (pS1 + (t * (pS2 + (t * (pS3 + (t * (pS4 + (t * pS5)))))))))); + q = one + (t * (qS1 + (t * (qS2 + (t * (qS3 + (t * qS4))))))); + s = sqrt(t); + if (ix >= 0x3FEF3333) { /* if |x| > 0.975 */ + w = p / q; + t = pio2_hi - ((2.0 * (s + (s * w))) - pio2_lo); + } else { + w = s; + w = setLO(w, 0); + c = (t - (w * w)) / (s + w); + r = p / q; + p = (2.0 * s * r) - (pio2_lo - (2.0 * c)); + q = pio4_hi - (2.0 * w); + t = pio4_hi - (p - q); + } + return ((hx > 0) ? t : (-t)); + } + + /* + * Method : + * acos(x) = pi/2 - asin(x) + * acos(-x) = pi/2 + asin(x) + * For |x|<=0.5 + * acos(x) = pi/2 - (x + x*x^2*R(x^2)) (see asin.c) + * For x>0.5 + * acos(x) = pi/2 - (pi/2 - 2asin(sqrt((1-x)/2))) + * = 2asin(sqrt((1-x)/2)) + * = 2s + 2s*z*R(z) ...z=(1-x)/2, s=sqrt(z) + * = 2f + (2c + 2s*z*R(z)) + * where f=hi part of s, and c = (z-f*f)/(s+f) is the correction term + * for f so that f+c ~ sqrt(z). + * For x<-0.5 + * acos(x) = pi - 2asin(sqrt((1-|x|)/2)) + * = pi - 0.5*(s+s*z*R(z)), where z=(1-|x|)/2,s=sqrt(z) + * + * Special cases: + * if x is NaN, return x itself; + * if |x|>1, return NaN with invalid signal. + * + * Function needed: sqrt + */ + + /** + * Returns the inverse (arc) cosine of its argument. + * @param x The argument, a double. + * @return Returns the angle, in radians, whose cosine is x. + * It is in the range [0,pi]. + */ + static public double acos(double x) { + double z; + double p; + double q; + double r; + double w; + double s; + double c; + double df; + int hx; + int ix; + hx = __HI(x); + ix = hx & 0x7fffffff; + if (ix >= 0x3ff00000) { /* |x| >= 1 */ + if (((ix - 0x3ff00000) | __LO(x)) == 0) { /* |x|==1 */ + if (hx > 0) { + return 0.0; /* acos(1) = 0 */ + } else { + return PI + (2.0 * pio2_lo); /* acos(-1)= pi */ + } + } + return (x - x) / (x - x); /* acos(|x|>1) is NaN */ + } + if (ix < 0x3fe00000) { /* |x| < 0.5 */ + if (ix <= 0x3c600000) { + return pio2_hi + pio2_lo; /*if|x|<2**-57*/ + } + z = x * x; + p = z * (pS0 + + (z * (pS1 + + (z * (pS2 + (z * (pS3 + (z * (pS4 + (z * pS5)))))))))); + q = one + (z * (qS1 + (z * (qS2 + (z * (qS3 + (z * qS4))))))); + r = p / q; + return pio2_hi - (x - (pio2_lo - (x * r))); + } else if (hx < 0) { /* x < -0.5 */ + z = (one + x) * 0.5; + p = z * (pS0 + + (z * (pS1 + + (z * (pS2 + (z * (pS3 + (z * (pS4 + (z * pS5)))))))))); + q = one + (z * (qS1 + (z * (qS2 + (z * (qS3 + (z * qS4))))))); + s = sqrt(z); + r = p / q; + w = (r * s) - pio2_lo; + return PI - (2.0 * (s + w)); + } else { /* x > 0.5 */ + z = (one - x) * 0.5; + s = sqrt(z); + df = s; + df = setLO(df, 0); + c = (z - (df * df)) / (s + df); + p = z * (pS0 + + (z * (pS1 + + (z * (pS2 + (z * (pS3 + (z * (pS4 + (z * pS5)))))))))); + q = one + (z * (qS1 + (z * (qS2 + (z * (qS3 + (z * qS4))))))); + r = p / q; + w = (r * s) + c; + return 2.0 * (df + w); + } + } + + static private final double[] atanhi = { + 0x1.dac670561bb4fp-2, /* 4.63647609000806093515e-01 atan(0.5)hi */ + 0x1.921fb54442d18p-1, /* 7.85398163397448278999e-01 atan(1.0)hi */ + 0x1.f730bd281f69bp-1, /* 9.82793723247329054082e-01 atan(1.5)hi */ + 0x1.921fb54442d18p0 /* 1.57079632679489655800e+00 atan(inf)hi */ + }; + static private final double[] atanlo = { + 0x1.a2b7f222f65e2p-56, /* 2.26987774529616870924e-17 atan(0.5)lo */ + 0x1.1a62633145c07p-55, /* 3.06161699786838301793e-17 atan(1.0)lo */ + 0x1.007887af0cbbdp-56, /* 1.39033110312309984516e-17 atan(1.5)lo */ + 0x1.1a62633145c07p-54 /* 6.12323399573676603587e-17 atan(inf)lo */ + }; + static private final double[] aT = { + 0x1.555555555550dp-2, /* 3.33333333333329318027e-01 */ + -0x1.999999998ebc4p-3, /* -1.99999999998764832476e-01 */ + 0x1.24924920083ffp-3, /* 1.42857142725034663711e-01 */ + -0x1.c71c6fe231671p-4, /* -1.11111104054623557880e-01 */ + 0x1.745cdc54c206ep-4, /* 9.09088713343650656196e-02 */ + -0x1.3b0f2af749a6dp-4, /* -7.69187620504482999495e-02 */ + 0x1.10d66a0d03d51p-4, /* 6.66107313738753120669e-02 */ + -0x1.dde2d52defd9ap-5, /* -5.83357013379057348645e-02 */ + 0x1.97b4b24760debp-5, /* 4.97687799461593236017e-02 */ + -0x1.2b4442c6a6c2fp-5, /* -3.65315727442169155270e-02 */ + 0x1.0ad3ae322da11p-6 /* 1.62858201153657823623e-02 */ + }; + + /* + * Method + * 1. Reduce x to positive by atan(x) = -atan(-x). + * 2. According to the integer k=4t+0.25 chopped, t=x, the argument + * is further reduced to one of the following intervals and the + * arctangent of t is evaluated by the corresponding formula: + * + * [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...) + * [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) ) + * [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) ) + * [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) ) + * [39/16,INF] atan(x) = atan(INF) + atan( -1/t ) + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + + /** + * Returns the inverse (arc) tangent of its argument. + * @param x The argument, a double. + * @return Returns the angle, in radians, whose tangent is x. + * It is in the range [-pi/2,pi/2]. + */ + static public double atan(double x) { + double w; + double s1; + double s2; + double z; + int ix; + int hx; + int id; + + hx = __HI(x); + ix = hx & 0x7fffffff; + if (ix >= 0x44100000) { /* if |x| >= 2^66 */ + if ((ix > 0x7ff00000) || ((ix == 0x7ff00000) && (__LO(x) != 0))) { + return x + x; /* NaN */ + } + if (hx > 0) { + return atanhi[3] + atanlo[3]; + } else { + return -atanhi[3] - atanlo[3]; + } + } + if (ix < 0x3fdc0000) { /* |x| < 0.4375 */ + if (ix < 0x3e200000) { /* |x| < 2^-29 */ + if ((huge + x) > one) { + return x; /* raise inexact */ + } + } + id = -1; + } else { + x = abs(x); + if (ix < 0x3ff30000) { /* |x| < 1.1875 */ + if (ix < 0x3fe60000) { /* 7/16 <=|x|<11/16 */ + id = 0; + x = ((2.0 * x) - one) / (2.0 + x); + } else { /* 11/16<=|x|< 19/16 */ + id = 1; + x = (x - one) / (x + one); + } + } else { + if (ix < 0x40038000) { /* |x| < 2.4375 */ + id = 2; + x = (x - 1.5) / (one + (1.5 * x)); + } else { /* 2.4375 <= |x| < 2^66 */ + id = 3; + x = -1.0 / x; + } + } + } + + /* end of argument reduction */ + z = x * x; + w = z * z; + + /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */ + s1 = z * (aT[0] + + (w * (aT[2] + + (w * (aT[4] + (w * (aT[6] + (w * (aT[8] + (w * aT[10])))))))))); + s2 = w * (aT[1] + + (w * (aT[3] + (w * (aT[5] + (w * (aT[7] + (w * aT[9])))))))); + if (id < 0) { + return x - (x * (s1 + s2)); + } else { + z = atanhi[id] - (((x * (s1 + s2)) - atanlo[id]) - x); + return (hx < 0) ? (-z) : z; + } + } + + static private final double pi_o_4 = 0x1.921fb54442d18p-1; /* 7.8539816339744827900e-01 */ + static private final double pi_o_2 = 0x1.921fb54442d18p0; /* 1.5707963267948965580e+00 */ + static private final double pi_lo = 0x1.1a62633145c07p-53; /* 1.2246467991473531772e-16 */ + + /* + * Method : + * 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x). + * 2. Reduce x to positive by (if x and y are unexceptional): + * ARG (x+iy) = arctan(y/x) ... if x > 0, + * ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0, + * + * Special cases: + * + * ATAN2((anything), NaN ) is NaN; + * ATAN2(NAN , (anything) ) is NaN; + * ATAN2(+-0, +(anything but NaN)) is +-0 ; + * ATAN2(+-0, -(anything but NaN)) is +-pi ; + * ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2; + * ATAN2(+-(anything but INF and NaN), +INF) is +-0 ; + * ATAN2(+-(anything but INF and NaN), -INF) is +-pi; + * ATAN2(+-INF,+INF ) is +-pi/4 ; + * ATAN2(+-INF,-INF ) is +-3pi/4; + * ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2; + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + + /** + * Returns angle corresponding to a Cartesian point. + * @param x The first argument, a double. + * @param y The second argument, a double. + * @return Returns the angle, in radians, the the line + * from (0,0) to (x,y) makes with the x-axis. + * It is in the range [-pi,pi]. + */ + static public double atan2(double y, double x) { + double z; + int k; + int m; + int hx; + int hy; + int ix; + int iy; + int lx; + int ly; + + hx = __HI(x); + ix = hx & 0x7fffffff; + lx = __LO(x); + hy = __HI(y); + iy = hy & 0x7fffffff; + ly = __LO(y); + if (((ix | ((lx | -lx) >>> 31)) > 0x7ff00000) || + ((iy | ((ly | -ly) >>> 31)) > 0x7ff00000)) { /* x or y is NaN */ + return x + y; + } + if (((hx - 0x3ff00000) | lx) == 0) { + return atan(y); /* x=1.0 */ + } + m = ((hy >> 31) & 1) | ((hx >> 30) & 2); /* 2*sign(x)+sign(y) */ + + /* when y = 0 */ + if ((iy | ly) == 0) { + switch (m) { + case 0: + case 1: + return y; /* atan(+-0,+anything)=+-0 */ + case 2: + return PI + tiny; /* atan(+0,-anything) = pi */ + case 3: + return -PI - tiny; /* atan(-0,-anything) =-pi */ + } + } + + /* when x = 0 */ + if ((ix | lx) == 0) { + return ((hy < 0) ? (-pi_o_2 - tiny) : (pi_o_2 + tiny)); + } + + /* when x is INF */ + if (ix == 0x7ff00000) { + if (iy == 0x7ff00000) { + switch (m) { + case 0: + return pi_o_4 + tiny; /* atan(+INF,+INF) */ + case 1: + return -pi_o_4 - tiny; /* atan(-INF,+INF) */ + case 2: + return (3.0 * pi_o_4) + tiny; /*atan(+INF,-INF)*/ + case 3: + return (-3.0 * pi_o_4) - tiny; /*atan(-INF,-INF)*/ + } + } else { + switch (m) { + case 0: + return zero; /* atan(+...,+INF) */ + case 1: + return -zero; /* atan(-...,+INF) */ + case 2: + return PI + tiny; /* atan(+...,-INF) */ + case 3: + return -PI - tiny; /* atan(-...,-INF) */ + } + } + } + + /* when y is INF */ + if (iy == 0x7ff00000) { + return (hy < 0) ? (-pi_o_2 - tiny) : (pi_o_2 + tiny); + } + + /* compute y/x */ + k = (iy - ix) >> 20; + if (k > 60) { + + /* |y/x| > 2**60 */ + z = pi_o_2 + (0.5 * pi_lo); + } else if ((hx < 0) && (k < -60)) { + + /* |y|/x < -2**60 */ + z = 0.0; + } else { + + /* safe to do y/x */ + z = atan(abs(y / x)); + } + + switch (m) { + case 0: + return z; /* atan(+,+) */ + case 1: + return setHI(z, __HI(z) ^ 0x80000000); /* atan(-,+) */ + case 2: + return PI - (z - pi_lo); /* atan(+,-) */ + default: /* case 3 */ + return (z - pi_lo) - PI; /* atan(-,-) */ + } + } + + /* + * kernel function: + * __kernel_sin ... sine function on [-pi/4,pi/4] + * __ieee754_rem_pio2 ... argument reduction routine + * + * Method. + * Let S,C and T denote the sin, cos and tan respectively on + * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 + * in [-pi/4 , +pi/4], and let n = k mod 4. + * We have + * + * n sin(x) cos(x) tan(x) + * ---------------------------------------------------------- + * 0 S C T + * 1 C -S -1/T + * 2 -S -C T + * 3 -C S -1/T + * ---------------------------------------------------------- + * + * Special cases: + * Let trig be any of sin, cos, or tan. + * trig(+-INF) is NaN, with signals; + * trig(NaN) is that NaN; + * + * Accuracy: + * TRIG(x) returns trig(x) nearly rounded + */ + /* + * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi + */ + static private final int[] two_over_pi = { + 0xa2f983, 0x6e4e44, 0x1529fc, 0x2757d1, 0xf534dd, 0xc0db62, 0x95993c, + 0x439041, 0xfe5163, 0xabdebb, 0xc561b7, 0x246e3a, 0x424dd2, 0xe00649, + 0x2eea09, 0xd1921c, 0xfe1deb, 0x1cb129, 0xa73ee8, 0x8235f5, 0x2ebb44, + 0x84e99c, 0x7026b4, 0x5f7e41, 0x3991d6, 0x398353, 0x39f49c, 0x845f8b, + 0xbdf928, 0x3b1ff8, 0x97ffde, 0x05980f, 0xef2f11, 0x8b5a0a, 0x6d1f6d, + 0x367ecf, 0x27cb09, 0xb74f46, 0x3f669e, 0x5fea2d, 0x7527ba, 0xc7ebe5, + 0xf17b3d, 0x0739f7, 0x8a5292, 0xea6bfb, 0x5fb11f, 0x8d5d08, 0x560330, + 0x46fc7b, 0x6babf0, 0xcfbc20, 0x9af436, 0x1da9e3, 0x91615e, 0xe61b08, + 0x659985, 0x5f14a0, 0x68408d, 0xffd880, 0x4d7327, 0x310606, 0x1556ca, + 0x73a8c9, 0x60e27b, 0xc08c6b + }; + static private final int[] npio2_hw = { + 0x3ff921fb, 0x400921fb, 0x4012d97c, 0x401921fb, 0x401f6a7a, + 0x4022d97c, 0x4025fdbb, 0x402921fb, 0x402c463a, 0x402f6a7a, + 0x4031475c, 0x4032d97c, 0x40346b9c, 0x4035fdbb, 0x40378fdb, + 0x403921fb, 0x403ab41b, 0x403c463a, 0x403dd85a, 0x403f6a7a, + 0x40407e4c, 0x4041475c, 0x4042106c, 0x4042d97c, 0x4043a28c, + 0x40446b9c, 0x404534ac, 0x4045fdbb, 0x4046c6cb, 0x40478fdb, + 0x404858eb, 0x404921fb + }; + static private final double zero = 0.00000000000000000000e+00; // 0x0000000000000000 + static private final double half = 0x1.0p-1; /* 5.00000000000000000000e-01 */ + static private final double two24 = 0x1.0p24; /* 1.67772160000000000000e+07 */ + static private final double invpio2 = 0x1.45f306dc9c883p-1; /* 6.36619772367581382433e-01 53 bits of 2/pi */ + static private final double pio2_1 = 0x1.921fb544p0; /* 1.57079632673412561417e+00 first 33 bit of pi/2 */ + static private final double pio2_1t = 0x1.0b4611a626331p-34; /* 6.07710050650619224932e-11 pi/2 - pio2_1 */ + static private final double pio2_2 = 0x1.0b4611a6p-34; /* 6.07710050630396597660e-11 second 33 bit of pi/2 */ + static private final double pio2_2t = 0x1.3198a2e037073p-69; /* 2.02226624879595063154e-21 pi/2 - (pio2_1+pio2_2) */ + static private final double pio2_3 = 0x1.3198a2ep-69; /* 2.02226624871116645580e-21 third 33 bit of pi/2 */ + static private final double pio2_3t = 0x1.b839a252049c1p-104; /* 8.47842766036889956997e-32 pi/2 - (pio2_1+pio2_2+pio2_3) */ + + /* + * Return the remainder of x % pi/2 in y[0]+y[1] + */ + static private int __ieee754_rem_pio2(double x, double[] y) { + double z = zero; + double w; + double t; + double r; + double fn; + int i; + int j; + int nx; + int n; + int ix; + int hx; + + hx = __HI(x); /* high word of x */ + ix = hx & 0x7fffffff; + if (ix <= 0x3fe921fb) { + + /* |x| ~<= pi/4 , no need for reduction */ + y[0] = x; + y[1] = 0; + return 0; + } + + if (ix < 0x4002d97c) { + + /* |x| < 3pi/4, special case with n=+-1 */ + if (hx > 0) { + z = x - pio2_1; + if (ix != 0x3ff921fb) { /* 33+53 bit pi is good enough */ + y[0] = z - pio2_1t; + y[1] = (z - y[0]) - pio2_1t; + } else { /* near pi/2, use 33+33+53 bit pi */ + z -= pio2_2; + y[0] = z - pio2_2t; + y[1] = (z - y[0]) - pio2_2t; + } + return 1; + } else { /* negative x */ + z = x + pio2_1; + if (ix != 0x3ff921fb) { /* 33+53 bit pi is good enough */ + y[0] = z + pio2_1t; + y[1] = (z - y[0]) + pio2_1t; + } else { /* near pi/2, use 33+33+53 bit pi */ + z += pio2_2; + y[0] = z + pio2_2t; + y[1] = (z - y[0]) + pio2_2t; + } + return -1; + } + } + + if (ix <= 0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */ + t = abs(x); + n = (int) ((t * invpio2) + half); + fn = (double) n; + r = t - (fn * pio2_1); + w = fn * pio2_1t; /* 1st round good to 85 bit */ + if ((n < 32) && (ix != npio2_hw[n - 1])) { + y[0] = r - w; /* quick check no cancellation */ + } else { + j = ix >> 20; + y[0] = r - w; + i = j - (((__HI(y[0])) >> 20) & 0x7ff); + if (i > 16) { /* 2nd iteration needed, good to 118 */ + t = r; + w = fn * pio2_2; + r = t - w; + w = (fn * pio2_2t) - ((t - r) - w); + y[0] = r - w; + i = j - (((__HI(y[0])) >> 20) & 0x7ff); + if (i > 49) { /* 3rd iteration need, 151 bits acc */ + t = r; /* will cover all possible cases */ + w = fn * pio2_3; + r = t - w; + w = (fn * pio2_3t) - ((t - r) - w); + y[0] = r - w; + } + } + } + y[1] = (r - y[0]) - w; + if (hx < 0) { + y[0] = -y[0]; + y[1] = -y[1]; + return -n; + } else { + return n; + } + } + + /* + * all other (large) arguments + */ + if (ix >= 0x7ff00000) { + + /* x is inf or NaN */ + y[0] = y[1] = x - x; + return 0; + } + + /* set z = scalbn(|x|,ilogb(x)-23) */ + double[] tx = new double[3]; + long lx = Double.doubleToLongBits(x); + long exp = (0x7ff0000000000000L & lx) >> 52; + exp -= 1046; + lx -= (exp << 52); + lx &= 0x7fffffffffffffffL; + z = Double.longBitsToDouble(lx); + for (i = 0; i < 2; i++) { + tx[i] = (double) ((int) (z)); + z = (z - tx[i]) * two24; + } + tx[2] = z; + nx = 3; + while (tx[nx - 1] == zero) + nx--; /* skip zero term */ + n = __kernel_rem_pio2(tx, y, (int) exp, nx); + //System.out.println("KERNEL"); + //System.out.println("tx "+tx[0]+" "+tx[1]+" "+tx[2]); + //System.out.println("y "+y[0]+" "+y[1]); + //System.out.println("exp "+(int)exp+" nx "+nx+" n "+n); + if (hx < 0) { + y[0] = -y[0]; + y[1] = -y[1]; + return -n; + } + return n; + } + + /* + * __kernel_rem_pio2(x,y,e0,nx) + * double x[],y[]; int e0,nx; int two_over_pi[]; + * + * __kernel_rem_pio2 return the last three digits of N with + * y = x - N*pi/2 + * so that |y| < pi/2. + * + * The method is to compute the integer (mod 8) and fraction parts of + * (2/pi)*x without doing the full multiplication. In general we + * skip the part of the product that are known to be a huge integer + * (more accurately, = 0 mod 8 ). Thus the number of operations are + * independent of the exponent of the input. + * + * (2/pi) is represented by an array of 24-bit integers in two_over_pi[]. + * + * Input parameters: + * x[] The input value (must be positive) is broken into nx + * pieces of 24-bit integers in double precision format. + * x[i] will be the i-th 24 bit of x. The scaled exponent + * of x[0] is given in input parameter e0 (i.e., x[0]*2^e0 + * match x's up to 24 bits. + * + * Example of breaking a double positive z into x[0]+x[1]+x[2]: + * e0 = ilogb(z)-23 + * z = scalbn(z,-e0) + * for i = 0,1,2 + * x[i] = floor(z) + * z = (z-x[i])*2**24 + * + * + * y[] ouput result in an array of double precision numbers. + * The dimension of y[] is: + * 24-bit precision 1 + * 53-bit precision 2 + * 64-bit precision 2 + * 113-bit precision 3 + * The actual value is the sum of them. Thus for 113-bit + * precison, one may have to do something like: + * + * long double t,w,r_head, r_tail; + * t = (long double)y[2] + (long double)y[1]; + * w = (long double)y[0]; + * r_head = t+w; + * r_tail = w - (r_head - t); + * + * e0 The exponent of x[0] + * + * nx dimension of x[] + * + * prec an integer indicating the precision: + * 0 24 bits (single) + * 1 53 bits (double) + * 2 64 bits (extended) + * 3 113 bits (quad) + * + * two_over_pi[] + * integer array, contains the (24*i)-th to (24*i+23)-th + * bit of 2/pi after binary point. The corresponding + * floating value is + * + * two_over_pi[i] * 2^(-24(i+1)). + * + * External function: + * double scalbn(), floor(); + * + * + * Here is the description of some local variables: + * + * jk jk+1 is the initial number of terms of two_over_pi[] needed + * in the computation. The recommended value is 2,3,4, + * 6 for single, double, extended,and quad. + * + * jz local integer variable indicating the number of + * terms of two_over_pi[] used. + * + * jx nx - 1 + * + * jv index for pointing to the suitable two_over_pi[] for the + * computation. In general, we want + * ( 2^e0*x[0] * two_over_pi[jv-1]*2^(-24jv) )/8 + * is an integer. Thus + * e0-3-24*jv >= 0 or (e0-3)/24 >= jv + * Hence jv = max(0,(e0-3)/24). + * + * jp jp+1 is the number of terms in PIo2[] needed, jp = jk. + * + * q[] double array with integral value, representing the + * 24-bits chunk of the product of x and 2/pi. + * + * q0 the corresponding exponent of q[0]. Note that the + * exponent for q[i] would be q0-24*i. + * + * PIo2[] double precision array, obtained by cutting pi/2 + * into 24 bits chunks. + * + * f[] two_over_pi[] in floating point + * + * iq[] integer array by breaking up q[] in 24-bits chunk. + * + * fq[] final product of x*(2/pi) in fq[0],..,fq[jk] + * + * ih integer. If >0 it indicates q[] is >= 0.5, hence + * it also indicates the *sign* of the result. + * + */ + /* + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + static final private double[] PIo2 = { + 0x1.921fb4p0, /* 1.57079625129699707031e+00 */ + 0x1.4442dp-24, /* 7.54978941586159635335e-08 */ + 0x1.846988p-48, /* 5.39030252995776476554e-15 */ + 0x1.8cc516p-72, /* 3.28200341580791294123e-22 */ + 0x1.01b838p-96, /* 1.27065575308067607349e-29 */ + 0x1.a25204p-120, /* 1.22933308981111328932e-36 */ + 0x1.382228p-145, /* 2.73370053816464559624e-44 */ + 0x1.9f31dp-169 /* 2.16741683877804819444e-51 */ + }; + static final private double twon24 = 0x1.0p-24; /* 5.96046447753906250000e-08 */ + + static private int __kernel_rem_pio2(double[] x, double[] y, int e0, int nx) { + int jz; + int jx; + int jv; + int jp; + int jk; + int carry; + int n; + int i; + int j; + int k; + int m; + int q0; + int ih; + double z; + double fw; + double[] f = new double[20]; + double[] q = new double[20]; + double[] fq = new double[20]; + int[] iq = new int[20]; + + /* initialize jk*/ + jk = 4; + jp = jk; + + /* determine jx,jv,q0, note that 3>q0 */ + jx = nx - 1; + jv = (e0 - 3) / 24; + if (jv < 0) { + jv = 0; + } + q0 = e0 - (24 * (jv + 1)); + + /* set up f[0] to f[jx+jk] where f[jx+jk] = two_over_pi[jv+jk] */ + j = jv - jx; + m = jx + jk; + for (i = 0; i <= m; i++, j++) + f[i] = ((j < 0) ? zero : (double) two_over_pi[j]); + + /* compute q[0],q[1],...q[jk] */ + for (i = 0; i <= jk; i++) { + for (j = 0, fw = 0.0; j <= jx; j++) + fw += (x[j] * f[(jx + i) - j]); + q[i] = fw; + } + + jz = jk; + + while (true) { // recompute: + + /* distill q[] into iq[] reversingly */ + for (i = 0, j = jz, z = q[jz]; j > 0; i++, j--) { + fw = (double) ((int) (twon24 * z)); + iq[i] = (int) (z - (two24 * fw)); + z = q[j - 1] + fw; + } + + /* compute n */ + z = scalbn(z, q0); /* actual value of z */ + z -= (8.0 * floor(z * 0.125)); /* trim off integer >= 8 */ + n = (int) z; + z -= (double) n; + ih = 0; + if (q0 > 0) { /* need iq[jz-1] to determine n */ + i = (iq[jz - 1] >> (24 - q0)); + n += i; + iq[jz - 1] -= (i << (24 - q0)); + ih = iq[jz - 1] >> (23 - q0); + } else if (q0 == 0) { + ih = iq[jz - 1] >> 23; + } else if (z >= 0.5) { + ih = 2; + } + if (ih > 0) { /* q > 0.5 */ + n += 1; + carry = 0; + for (i = 0; i < jz; i++) { /* compute 1-q */ + j = iq[i]; + if (carry == 0) { + if (j != 0) { + carry = 1; + iq[i] = 0x1000000 - j; + } + } else { + iq[i] = 0xffffff - j; + } + } + if (q0 > 0) { /* rare case: chance is 1 in 12 */ + switch (q0) { + case 1: + iq[jz - 1] &= 0x7fffff; + break; + case 2: + iq[jz - 1] &= 0x3fffff; + break; + } + } + if (ih == 2) { + z = one - z; + if (carry != 0) { + z -= scalbn(one, q0); + } + } + } + + /* check if recomputation is needed */ + if (z == zero) { + j = 0; + for (i = jz - 1; i >= jk; i--) + j |= iq[i]; + if (j == 0) { /* need recomputation */ + for (k = 1; iq[jk - k] == 0; k++) + ; /* k = no. of terms needed */for (i = jz + 1; + i <= (jz + k); i++) { /* add q[jz+1] to q[jz+k] */ + f[jx + i] = (double) two_over_pi[jv + i]; + for (j = 0, fw = 0.0; j <= jx; j++) + fw += (x[j] * f[(jx + i) - j]); + q[i] = fw; + } + jz += k; + continue; //goto recompute; + } + } + break; + } + + /* chop off zero terms */ + if (z == 0.0) { + jz--; + q0 -= 24; + while (iq[jz] == 0) { + jz--; + q0 -= 24; + } + } else { /* break z into 24-bit if necessary */ + z = scalbn(z, -q0); + if (z >= two24) { + fw = (double) ((int) (twon24 * z)); + iq[jz] = (int) (z - (two24 * fw)); + jz++; + q0 += 24; + iq[jz] = (int) fw; + } else { + iq[jz] = (int) z; + } + } + + /* convert integer "bit" chunk to floating-point value */ + fw = scalbn(one, q0); + for (i = jz; i >= 0; i--) { + q[i] = fw * (double) iq[i]; + fw *= twon24; + } + + /* compute PIo2[0,...,jp]*q[jz,...,0] */ + for (i = jz; i >= 0; i--) { + for (fw = 0.0, k = 0; (k <= jp) && (k <= (jz - i)); k++) + fw += (PIo2[k] * q[i + k]); + fq[jz - i] = fw; + } + + /* compress fq[] into y[] */ + fw = 0.0; + for (i = jz; i >= 0; i--) + fw += fq[i]; + y[0] = (ih == 0) ? fw : (-fw); + fw = fq[0] - fw; + for (i = 1; i <= jz; i++) + fw += fq[i]; + y[1] = ((ih == 0) ? fw : (-fw)); + return n & 7; + } + + static final private double[] bp = { 1.0, 1.5, }; + static final private double[] dp_h = { + 0.0, 0x1.2b8034p-1 + }; /* 5.84962487220764160156e-01 */ + static final private double[] dp_l = { + 0.0, 0x1.cfdeb43cfd006p-27 + }; /* 1.35003920212974897128e-08 */ + static final private double two53 = 0x1.0p53; /* 9007199254740992.0 */ + + /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ + static final private double L1 = 0x1.3333333333303p-1; /* 5.99999999999994648725e-01 */ + static final private double L2 = 0x1.b6db6db6fabffp-2; /* 4.28571428578550184252e-01 */ + static final private double L3 = 0x1.55555518f264dp-2; /* 3.33333329818377432918e-01 */ + static final private double L4 = 0x1.17460a91d4101p-2; /* 2.72728123808534006489e-01 */ + static final private double L5 = 0x1.d864a93c9db65p-3; /* 2.30660745775561754067e-01 */ + static final private double L6 = 0x1.a7e284a454eefp-3; /* 2.06975017800338417784e-01 */ + static final private double lg2 = 0x1.62e42fefa39efp-1; /* 6.93147180559945286227e-01 */ + static final private double lg2_h = 0x1.62e43p-1; /* 6.93147182464599609375e-01 */ + static final private double lg2_l = -1.90465429995776804525e-09; /* 0xbe205c610ca86c39 */ + static final private double ovt = 8.0085662595372944372e-17; /* -(1024-log2(ovfl+.5ulp)) */ + static final private double cp = 0x1.ec709dc3a03fdp-1; /* 9.61796693925975554329e-01 = 2/(3ln2) */ + static final private double cp_h = 0x1.ec709ep-1; /* 9.61796700954437255859e-01 = (float)cp */ + static final private double cp_l = -0x1.e2fe0145b01f5p-28; /* -7.02846165095275826516e-09 = tail of cp_h*/ + static final private double ivln2 = 0x1.71547652b82fep0; /* 1.44269504088896338700e+00 = 1/ln2 */ + static final private double ivln2_h = 0x1.715476p0; /* 1.44269502162933349609e+00 = 24b 1/ln2*/ + static final private double ivln2_l = 0x1.4ae0bf85ddf44p-26; /* 1.92596299112661746887e-08 = 1/ln2 tail*/ + + /* + * Returns x to the power y + * + * n + * Method: Let x = 2 * (1+f) + * 1. Compute and return log2(x) in two pieces: + * log2(x) = w1 + w2, + * where w1 has 53-24 = 29 bit trailing zeros. + * 2. Perform y*log2(x) = n+y' by simulating muti-precision + * arithmetic, where |y'|<=0.5. + * 3. Return x**y = 2**n*exp(y'*log2) + * + * Special cases: + * 1. (anything) ** 0 is 1 + * 2. (anything) ** 1 is itself + * 3. (anything) ** NAN is NAN + * 4. NAN ** (anything except 0) is NAN + * 5. +-(|x| > 1) ** +INF is +INF + * 6. +-(|x| > 1) ** -INF is +0 + * 7. +-(|x| < 1) ** +INF is +0 + * 8. +-(|x| < 1) ** -INF is +INF + * 9. +-1 ** +-INF is NAN + * 10. +0 ** (+anything except 0, NAN) is +0 + * 11. -0 ** (+anything except 0, NAN, odd integer) is +0 + * 12. +0 ** (-anything except 0, NAN) is +INF + * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF + * 14. -0 ** (odd integer) = -( +0 ** (odd integer) ) + * 15. +INF ** (+anything except 0,NAN) is +INF + * 16. +INF ** (-anything except 0,NAN) is +0 + * 17. -INF ** (anything) = -0 ** (-anything) + * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer) + * 19. (-anything except 0 and inf) ** (non-integer) is NAN + * + * Accuracy: + * pow(x,y) returns x**y nearly rounded. In particular + * pow(integer,integer) + * always returns the correct integer provided it is + * representable. + */ + + /** + * Returns x to the power y. + * @param x The base. + * @param y The exponent. + * @return x to the power y. + */ + static public double pow(double x, double y) { + double z; + double ax; + double z_h; + double z_l; + double p_h; + double p_l; + double y1; + double t1; + double t2; + double r; + double s; + double t; + double u; + double v; + double w; + int i; + int j; + int k; + int yisint; + int n; + int hx; + int hy; + int ix; + int iy; + int lx; + int ly; + + hx = __HI(x); + lx = __LO(x); + hy = __HI(y); + ly = __LO(y); + ix = hx & 0x7fffffff; + iy = hy & 0x7fffffff; + + /* y==zero: x**0 = 1 */ + if ((iy | ly) == 0) { + return one; + } + + /* +-NaN return x+y */ + if ((ix > 0x7ff00000) || ((ix == 0x7ff00000) && (lx != 0)) || + (iy > 0x7ff00000) || ((iy == 0x7ff00000) && (ly != 0))) { + return x + y; + } + + /* determine if y is an odd int when x < 0 + * yisint = 0 ... y is not an integer + * yisint = 1 ... y is an odd int + * yisint = 2 ... y is an even int + */ + yisint = 0; + if (hx < 0) { + if (iy >= 0x43400000) { + yisint = 2; /* even integer y */ + } else if (iy >= 0x3ff00000) { + k = (iy >> 20) - 0x3ff; /* exponent */ + if (k > 20) { + j = ly >>> (52 - k); + if ((j << (52 - k)) == ly) { + yisint = 2 - (j & 1); + } + } else if (ly == 0) { + j = iy >> (20 - k); + if ((j << (20 - k)) == iy) { + yisint = 2 - (j & 1); + } + } + } + } + + /* special value of y */ + if (ly == 0) { + if (iy == 0x7ff00000) { /* y is +-inf */ + if (((ix - 0x3ff00000) | lx) == 0) { + return y - y; /* inf**+-1 is NaN */ + } else if (ix >= 0x3ff00000) { /* (|x|>1)**+-inf = inf,0 */ + return (hy >= 0) ? y : zero; + } else { /* (|x|<1)**-,+inf = inf,0 */ + return (hy < 0) ? (-y) : zero; + } + } + if (iy == 0x3ff00000) { /* y is +-1 */ + if (hy < 0) { + return one / x; + } else { + return x; + } + } + if (hy == 0x40000000) { + return x * x; /* y is 2 */ + } + if (hy == 0x3fe00000) { /* y is 0.5 */ + if (hx >= 0) { /* x >= +0 */ + return sqrt(x); + } + } + } + + ax = abs(x); + + /* special value of x */ + if (lx == 0) { + if ((ix == 0x7ff00000) || (ix == 0) || (ix == 0x3ff00000)) { + z = ax; /*x is +-0,+-inf,+-1*/ + if (hy < 0) { + z = one / z; /* z = (1/|x|) */ + } + if (hx < 0) { + if (((ix - 0x3ff00000) | yisint) == 0) { + z = (z - z) / (z - z); /* (-1)**non-int is NaN */ + } else if (yisint == 1) { + z = -z; /* (x<0)**odd = -(|x|**odd) */ + } + } + return z; + } + } + + /* (x<0)**(non-int) is NaN */ + if ((((hx >> 31) + 1) | yisint) == 0) { + return (x - x) / (x - x); + } + + /* |y| is huge */ + if (iy > 0x41e00000) { /* if |y| > 2**31 */ + if (iy > 0x43f00000) { /* if |y| > 2**64, must o/uflow */ + if (ix <= 0x3fefffff) { + return ((hy < 0) ? (huge * huge) : (tiny * tiny)); + } + if (ix >= 0x3ff00000) { + return ((hy > 0) ? (huge * huge) : (tiny * tiny)); + } + } + + /* over/underflow if x is not close to one */ + if (ix < 0x3fefffff) { + return ((hy < 0) ? (huge * huge) : (tiny * tiny)); + } + if (ix > 0x3ff00000) { + return ((hy > 0) ? (huge * huge) : (tiny * tiny)); + } + + /* now |1-x| is tiny <= 2**-20, suffice to compute + log(x) by x-x^2/2+x^3/3-x^4/4 */ + t = x - 1; /* t has 20 trailing zeros */ + w = (t * t) * (0.5 - (t * (0.3333333333333333333333 - (t * 0.25)))); + u = ivln2_h * t; /* ivln2_h has 21 sig. bits */ + v = (t * ivln2_l) - (w * ivln2); + t1 = u + v; + t1 = setLO(t1, 0); + t2 = v - (t1 - u); + } else { + double s2; + double s_h; + double s_l; + double t_h; + double t_l; + n = 0; + + /* take care subnormal number */ + if (ix < 0x00100000) { + ax *= two53; + n -= 53; + ix = __HI(ax); + } + n += (((ix) >> 20) - 0x3ff); + j = ix & 0x000fffff; + + /* determine interval */ + ix = j | 0x3ff00000; /* normalize ix */ + if (j <= 0x3988E) { + k = 0; /* |x|> 1) | 0x20000000) + 0x00080000 + (k << 18)); + t_l = ax - (t_h - bp[k]); + s_l = v * ((u - (s_h * t_h)) - (s_h * t_l)); + + /* compute log(ax) */ + s2 = s * s; + r = s2 * s2 * (L1 + + (s2 * (L2 + + (s2 * (L3 + (s2 * (L4 + (s2 * (L5 + (s2 * L6)))))))))); + r += (s_l * (s_h + s)); + s2 = s_h * s_h; + t_h = 3.0 + s2 + r; + t_h = setLO(t_h, 0); + t_l = r - ((t_h - 3.0) - s2); + + /* u+v = s*(1+...) */ + u = s_h * t_h; + v = (s_l * t_h) + (t_l * s); + + /* 2/(3log2)*(s+...) */ + p_h = u + v; + p_h = setLO(p_h, 0); + p_l = v - (p_h - u); + z_h = cp_h * p_h; /* cp_h+cp_l = 2/(3*log2) */ + z_l = (cp_l * p_h) + (p_l * cp) + dp_l[k]; + + /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */ + t = (double) n; + t1 = (((z_h + z_l) + dp_h[k]) + t); + t1 = setLO(t1, 0); + t2 = z_l - (((t1 - t) - dp_h[k]) - z_h); + } + + s = one; /* s (sign of result -ve**odd) = -1 else = 1 */ + if ((((hx >> 31) + 1) | (yisint - 1)) == 0) { + s = -one; /* (-ve)**(odd int) */ + } + + /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ + y1 = y; + y1 = setLO(y1, 0); + p_l = ((y - y1) * t1) + (y * t2); + p_h = y1 * t1; + z = p_l + p_h; + j = __HI(z); + i = __LO(z); + if (j >= 0x40900000) { /* z >= 1024 */ + if (((j - 0x40900000) | i) != 0) { /* if z > 1024 */ + return s * huge * huge; /* overflow */ + } else { + if ((p_l + ovt) > (z - p_h)) { + return s * huge * huge; /* overflow */ + } + } + } else if ((j & 0x7fffffff) >= 0x4090cc00) { /* z <= -1075 */ + if (((j - 0xc090cc00) | i) != 0) { /* z < -1075 */ + return s * tiny * tiny; /* underflow */ + } else { + if (p_l <= (z - p_h)) { + return s * tiny * tiny; /* underflow */ + } + } + } + + /* + * compute 2**(p_h+p_l) + */ + i = j & 0x7fffffff; + k = (i >> 20) - 0x3ff; + n = 0; + if (i > 0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */ + n = j + (0x00100000 >> (k + 1)); + k = ((n & 0x7fffffff) >> 20) - 0x3ff; /* new k for n */ + t = zero; + t = setHI(t, (n & ~(0x000fffff >> k))); + n = ((n & 0x000fffff) | 0x00100000) >> (20 - k); + if (j < 0) { + n = -n; + } + p_h -= t; + } + t = p_l + p_h; + t = setLO(t, 0); + u = t * lg2_h; + v = ((p_l - (t - p_h)) * lg2) + (t * lg2_l); + z = u + v; + w = v - (z - u); + t = z * z; + t1 = z - (t * (P1 + (t * (P2 + (t * (P3 + (t * (P4 + (t * P5))))))))); + r = ((z * t1) / (t1 - 2.0)) - (w + (z * w)); + z = one - (r - z); + j = __HI(z); + j += (n << 20); + if ((j >> 20) <= 0) { + z = scalbn(z, n); /* subnormal output */ + } else { + i = __HI(z); + i += (n << 20); + z = setHI(z, i); + } + return s * z; + } + + /* + * copysign(double x, double y) + * copysign(x,y) returns a value with the magnitude of x and + * with the sign bit of y. + */ + static private double copysign(double x, double y) { + long ix = Double.doubleToRawLongBits(x); + long iy = Double.doubleToRawLongBits(y); + ix = (0x7fffffffffffffffL & ix) | (0x8000000000000000L & iy); + return Double.longBitsToDouble(ix); + } + + static private final double two54 = 0x1.0p54; /* 1.80143985094819840000e+16 */ + static private final double twom54 = 0x1.0p-54; /* 5.55111512312578270212e-17 */ + + /* + * scalbn (double x, int n) + * scalbn(x,n) returns x* 2**n computed by exponent + * manipulation rather than by actually performing an + * exponentiation or a multiplication. + */ + static private double scalbn(double x, int n) { + int k; + int hx; + int lx; + hx = __HI(x); + lx = __LO(x); + k = (hx & 0x7ff00000) >> 20; /* extract exponent */ + if (k == 0) { /* 0 or subnormal x */ + if ((lx | (hx & 0x7fffffff)) == 0) { + return x; /* +-0 */ + } + x *= two54; + hx = __HI(x); + k = ((hx & 0x7ff00000) >> 20) - 54; + if (n < -50000) { + return tiny * x; /*underflow*/ + } + } + if (k == 0x7ff) { + return x + x; /* NaN or Inf */ + } + k = k + n; + if (k > 0x7fe) { + return huge * copysign(huge, x); /* overflow */ + } + if (k > 0) { + + /* normal result */ + return setHI(x, (hx & 0x800fffff) | (k << 20)); + } + if (k <= -54) { + if (n > 50000) { /* in case integer overflow in n+k */ + return huge * copysign(huge, x); /*overflow*/ + } + } else { + return tiny * copysign(tiny, x); /*underflow*/ + } + k += 54; /* subnormal result */ + return twom54 * setHI(x, (hx & 0x800fffff) | (k << 20)); + } + + static private double set(int newHiPart, int newLowPart) { + return Double.longBitsToDouble((((long) newHiPart) << 32) | newLowPart); + } + + static private double setLO(double x, int newLowPart) { + long lx = Double.doubleToRawLongBits(x); + lx &= 0xFFFFFFFF00000000L; + lx |= newLowPart; + return Double.longBitsToDouble(lx); + } + + static private double setHI(double x, int newHiPart) { + long lx = Double.doubleToRawLongBits(x); + lx &= 0x00000000FFFFFFFFL; + lx |= (((long) newHiPart) << 32); + return Double.longBitsToDouble(lx); + } + + static private int __HI(double x) { + return (int) (0xFFFFFFFF & (Double.doubleToRawLongBits(x) >> 32)); + } + + static private int __LO(double x) { + return (int) (0xFFFFFFFF & Double.doubleToRawLongBits(x)); + } +} \ No newline at end of file diff --git a/classpath/ikvm/internal/Library.java b/classpath/ikvm/internal/Library.java new file mode 100644 index 0000000..214f14c --- /dev/null +++ b/classpath/ikvm/internal/Library.java @@ -0,0 +1,11 @@ +package ikvm.internal; + +public class Library +{ + private static final LibraryVMInterface impl = new java.lang.LibraryVMInterfaceImpl(); + + public static LibraryVMInterface getImpl() + { + return impl; + } +} diff --git a/classpath/ikvm/internal/LibraryVMInterface.java b/classpath/ikvm/internal/LibraryVMInterface.java new file mode 100644 index 0000000..c8b80af --- /dev/null +++ b/classpath/ikvm/internal/LibraryVMInterface.java @@ -0,0 +1,62 @@ +/* + Copyright (C) 2004, 2005, 2006, 2007 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package ikvm.internal; + +public interface LibraryVMInterface +{ + Object newClass(Object wrapper, Object protectionDomain, Object classLoader); + Object getWrapperFromClass(Object clazz); + Object getWrapperFromField(Object field); + Object getWrapperFromMethodOrConstructor(Object methodOrConstructor); + + Object getWrapperFromClassLoader(Object classLoader); + void setWrapperForClassLoader(Object classLoader, Object wrapper); + + Object box(Object val); + Object unbox(Object val); + + Throwable mapException(Throwable t); + + void jniWaitUntilLastThread(); + void jniDetach(); + void setThreadGroup(Object group); + + Object newConstructor(Object clazz, Object wrapper); + Object newMethod(Object clazz, Object wrapper); + Object newField(Object clazz, Object wrapper); + + Object newDirectByteBuffer(cli.System.IntPtr address, int capacity); + cli.System.IntPtr getDirectBufferAddress(Object buffer); + int getDirectBufferCapacity(Object buffer); + + void setProperties(cli.System.Collections.Hashtable props); + + boolean runFinalizersOnExit(); + + Object newAnnotation(Object classLoader, Object definition); + Object newAnnotationElementValue(Object classLoader, Object expectedClass, Object definition); + + Object newAssemblyClassLoader(cli.System.Reflection.Assembly assembly); +} diff --git a/classpath/ikvm/internal/MonoUtils.java b/classpath/ikvm/internal/MonoUtils.java new file mode 100644 index 0000000..9f98ddb --- /dev/null +++ b/classpath/ikvm/internal/MonoUtils.java @@ -0,0 +1,52 @@ +/* + Copyright (C) 2008 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package ikvm.internal; + +import cli.System.Activator; +import cli.System.Reflection.BindingFlags; +import cli.System.Reflection.FieldInfo; +import cli.System.Reflection.MethodInfo; +import cli.System.Type; + +final class MonoUtils +{ + static String unameProperty(String field) + { + Type syscallType = Type.GetType("Mono.Unix.Native.Syscall, Mono.Posix, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756"); + Type utsnameType = Type.GetType("Mono.Unix.Native.Utsname, Mono.Posix, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756"); + if (syscallType != null && utsnameType != null) + { + Object[] arg = new Object[] { Activator.CreateInstance(utsnameType) }; + MethodInfo uname = syscallType.GetMethod("uname", new Type[] { utsnameType.MakeByRefType() }); + FieldInfo fi = utsnameType.GetField(field); + if (uname != null && fi != null) + { + uname.Invoke(null, arg); + return (String)fi.GetValue(arg[0]); + } + } + return null; + } +} diff --git a/classpath/ikvm/internal/Util.java b/classpath/ikvm/internal/Util.java new file mode 100644 index 0000000..90b39df --- /dev/null +++ b/classpath/ikvm/internal/Util.java @@ -0,0 +1,62 @@ +package ikvm.internal; + +import ikvm.lang.Internal; + +@Internal +public final class Util +{ + private Util() {} + + public static final boolean MONO = cli.System.Type.GetType("Mono.Runtime") != null; + + public static final boolean WINDOWS; + public static final boolean MACOSX; + + static + { + switch (cli.System.Environment.get_OSVersion().get_Platform().Value) + { + case cli.System.PlatformID.Win32NT: + case cli.System.PlatformID.Win32Windows: + case cli.System.PlatformID.Win32S: + case cli.System.PlatformID.WinCE: + WINDOWS = true; + MACOSX = false; + break; + case cli.System.PlatformID.MacOSX: + WINDOWS = false; + MACOSX = true; + break; + case cli.System.PlatformID.Unix: + WINDOWS = false; + // as of version 2.6, Mono still returns Unix when running on MacOSX + MACOSX = "Darwin".equals(MonoUtils.unameProperty("sysname")); + break; + default: + WINDOWS = false; + MACOSX = false; + break; + } + } + + public static boolean rangeCheck(int arrayLength, int offset, int length) + { + return offset >= 0 + && offset <= arrayLength + && length >= 0 + && length <= arrayLength - offset; + } + + public static String SafeGetEnvironmentVariable(String name) + { + try + { + if (false) throw new cli.System.Security.SecurityException(); + return cli.System.Environment.GetEnvironmentVariable(name); + } + catch (cli.System.Security.SecurityException _) + { + return null; + } + } +} diff --git a/classpath/ikvm/internal/WeakIdentityMap.java b/classpath/ikvm/internal/WeakIdentityMap.java new file mode 100644 index 0000000..e73ae3d --- /dev/null +++ b/classpath/ikvm/internal/WeakIdentityMap.java @@ -0,0 +1,155 @@ +/* + Copyright (C) 2006, 2007 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package ikvm.internal; + +import cli.System.GC; +import cli.System.WeakReference; + +@ikvm.lang.Internal +public final class WeakIdentityMap +{ + private WeakReference[] keys = new WeakReference[16]; + private Object[] values = new Object[keys.length]; + + public WeakIdentityMap() + { + for (int i = 0; i < keys.length; i++) + { + keys[i] = new WeakReference(null, true); + // NOTE we suppress finalization, to make sure the WeakReference continues to work + // while the AppDomain is finalizing for unload (note that for this to work, + // the code that instantiates us also has to call SuppressFinalize on us.) + GC.SuppressFinalize(keys[i]); + } + } + + protected void finalize() + { + for (int i = 0; i < keys.length; i++) + { + if (keys[i] != null) + { + GC.ReRegisterForFinalize(keys[i]); + } + } + } + + public synchronized Object remove(Object key) + { + for (int i = 0; i < keys.length; i++) + { + if (keys[i].get_Target() == key) + { + Object value = values[i]; + keys[i].set_Target(null); + values[i] = null; + return value; + } + } + return null; + } + + // Note that null values are supported, null keys are not + public synchronized void put(Object key, Object value) + { + if (key == null) + throw new NullPointerException(); + putImpl(key, value, true); + } + + private void putImpl(Object key, Object value, boolean tryGC) + { + int emptySlot = -1; + int keySlot = -1; + for (int i = 0; i < keys.length; i++) + { + Object k = keys[i].get_Target(); + if (k == null) + { + emptySlot = i; + values[i] = null; + } + else if (k == key) + { + keySlot = i; + } + } + if (keySlot != -1) + { + values[keySlot] = value; + } + else if (emptySlot != -1) + { + keys[emptySlot].set_Target(key); + values[emptySlot] = value; + } + else + { + if (tryGC) + { + GC.Collect(0); + putImpl(key, value, false); + return; + } + int len = keys.length; + WeakReference[] newkeys = new WeakReference[len * 2]; + Object[] newvalues = new Object[newkeys.length]; + cli.System.Array.Copy((cli.System.Array)(Object)keys, (cli.System.Array)(Object)newkeys, len); + cli.System.Array.Copy((cli.System.Array)(Object)values, (cli.System.Array)(Object)newvalues, len); + keys = newkeys; + values = newvalues; + for (int i = len; i < keys.length; i++) + { + keys[i] = new WeakReference(null, true); + GC.SuppressFinalize(keys[i]); + } + keys[len].set_Target(key); + values[len] = value; + } + } + + public synchronized Object get(Object key) + { + for (int i = 0; i < keys.length; i++) + { + if (keys[i].get_Target() == key) + { + return values[i]; + } + } + return null; + } + + public synchronized boolean containsKey(Object key) + { + for (int i = 0; i < keys.length; i++) + { + if (keys[i].get_Target() == key) + { + return true; + } + } + return false; + } +} diff --git a/classpath/ikvm/internal/__unspecified.java b/classpath/ikvm/internal/__unspecified.java new file mode 100644 index 0000000..0450e4e --- /dev/null +++ b/classpath/ikvm/internal/__unspecified.java @@ -0,0 +1,29 @@ +/* + Copyright (C) 2007 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package ikvm.internal; + +import java.lang.annotation.*; + +@Target({}) +public @interface __unspecified {} diff --git a/classpath/ikvm/io/InputStreamWrapper.java b/classpath/ikvm/io/InputStreamWrapper.java new file mode 100644 index 0000000..e55ff30 --- /dev/null +++ b/classpath/ikvm/io/InputStreamWrapper.java @@ -0,0 +1,239 @@ +/* + Copyright (C) 2006, 2007 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package ikvm.io; + +public final class InputStreamWrapper extends java.io.InputStream +{ + private cli.System.IO.Stream stream; + private long markPosition = -1; + private boolean atEOF; + + public InputStreamWrapper(cli.System.IO.Stream stream) + { + this.stream = stream; + } + + public int read() throws java.io.IOException + { + try + { + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.ObjectDisposedException(null); + int i = stream.ReadByte(); + if (i == -1) + { + atEOF = true; + } + return i; + } + catch (cli.System.IO.IOException x) + { + java.io.IOException ex = new java.io.IOException(); + ex.initCause(x); + throw ex; + } + catch (cli.System.ObjectDisposedException x) + { + java.io.IOException ex = new java.io.IOException(); + ex.initCause(x); + throw ex; + } + } + + public int read(byte[] b) throws java.io.IOException + { + return read(b, 0, b.length); + } + + public int read(byte[] b, int off, int len) throws java.io.IOException + { + if (b == null) + { + throw new NullPointerException(); + } + if (off < 0 || len < 0 || b.length - off < len) + { + throw new IndexOutOfBoundsException(); + } + if (len == 0) + { + return 0; + } + try + { + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.ObjectDisposedException(null); + int count = stream.Read(b, off, len); + if (count == 0) + { + atEOF = true; + return -1; + } + return count; + } + catch (cli.System.IO.IOException x) + { + java.io.IOException ex = new java.io.IOException(); + ex.initCause(x); + throw ex; + } + catch (cli.System.ObjectDisposedException x) + { + java.io.IOException ex = new java.io.IOException(); + ex.initCause(x); + throw ex; + } + } + + public long skip(long n) throws java.io.IOException + { + if (n <= 0) + { + return 0; + } + else if (stream.get_CanSeek()) + { + try + { + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.ObjectDisposedException(null); + long pos = stream.get_Position(); + n = Math.min(n, Math.max(0, stream.get_Length() - pos)); + stream.set_Position(pos + n); + return n; + } + catch (cli.System.IO.IOException x) + { + java.io.IOException ex = new java.io.IOException(); + ex.initCause(x); + throw ex; + } + catch (cli.System.ObjectDisposedException x) + { + java.io.IOException ex = new java.io.IOException(); + ex.initCause(x); + throw ex; + } + } + else + { + return super.skip(n); + } + } + + public int available() throws java.io.IOException + { + if (stream.get_CanSeek()) + { + try + { + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.ObjectDisposedException(null); + long val = stream.get_Length() - stream.get_Position(); + return (int)Math.min(Math.max(val, 0), Integer.MAX_VALUE); + } + catch (cli.System.IO.IOException x) + { + java.io.IOException ex = new java.io.IOException(); + ex.initCause(x); + throw ex; + } + catch (cli.System.ObjectDisposedException x) + { + java.io.IOException ex = new java.io.IOException(); + ex.initCause(x); + throw ex; + } + } + else + { + // It turns out that it's important that available() return non-zero when + // data is still available, because BufferedInputStream uses the non-zero + // return value as a cue to continue reading. + // As suggested by Mark Reinhold, we emulate InflaterInputStream's behavior + // and return 0 after we've reached EOF and otherwise 1. + return atEOF ? 0 : 1; + } + } + + public void close() throws java.io.IOException + { + stream.Close(); + } + + public void mark(int readlimit) + { + if (stream.get_CanSeek()) + { + try + { + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.ObjectDisposedException(null); + markPosition = stream.get_Position(); + } + catch (cli.System.IO.IOException x) + { + } + catch (cli.System.ObjectDisposedException x) + { + } + } + } + + public void reset() throws java.io.IOException + { + if (!stream.get_CanSeek()) + { + throw new java.io.IOException("mark/reset not supported"); + } + if (markPosition == -1) + { + throw new java.io.IOException("no mark available"); + } + try + { + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.ObjectDisposedException(null); + stream.set_Position(markPosition); + } + catch (cli.System.IO.IOException x) + { + java.io.IOException ex = new java.io.IOException(); + ex.initCause(x); + throw ex; + } + catch (cli.System.ObjectDisposedException x) + { + java.io.IOException ex = new java.io.IOException(); + ex.initCause(x); + throw ex; + } + } + + public boolean markSupported() + { + return stream.get_CanSeek(); + } +} diff --git a/classpath/ikvm/lang/CIL.java b/classpath/ikvm/lang/CIL.java new file mode 100644 index 0000000..670abcf --- /dev/null +++ b/classpath/ikvm/lang/CIL.java @@ -0,0 +1,55 @@ +/* + Copyright (C) 2003, 2004, 2005 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package ikvm.lang; + +public class CIL +{ + public static native byte unbox_byte(Object o); + public static native boolean unbox_boolean(Object o); + public static native short unbox_short(Object o); + public static native char unbox_char(Object o); + public static native int unbox_int(Object o); + public static native float unbox_float(Object o); + public static native long unbox_long(Object o); + public static native double unbox_double(Object o); + + public static native cli.System.Byte box_byte(byte v); + public static native cli.System.Boolean box_boolean(boolean v); + public static native cli.System.Int16 box_short(short v); + public static native cli.System.Char box_char(char v); + public static native cli.System.Int32 box_int(int v); + public static native cli.System.Single box_float(float v); + public static native cli.System.Int64 box_long(long v); + public static native cli.System.Double box_double(double v); + + public static native cli.System.SByte box_sbyte(byte v); + public static native cli.System.UInt16 box_ushort(short v); + public static native cli.System.UInt32 box_uint(int v); + public static native cli.System.UInt64 box_ulong(long v); + + public static native byte unbox_sbyte(cli.System.SByte v); + public static native short unbox_ushort(cli.System.UInt16 v); + public static native int unbox_uint(cli.System.UInt32 v); + public static native long unbox_ulong(cli.System.UInt64 v); +} diff --git a/classpath/ikvm/lang/DllExport.java b/classpath/ikvm/lang/DllExport.java new file mode 100644 index 0000000..5106ae9 --- /dev/null +++ b/classpath/ikvm/lang/DllExport.java @@ -0,0 +1,40 @@ +/* + Copyright (C) 2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package ikvm.lang; + +import java.lang.annotation.*; + +/** + * Can be used to define an unmanaged export for a static method. + * Only works with ikvmc compiled code. + */ + +@Documented +@Retention(RetentionPolicy.CLASS) +@Target({ ElementType.METHOD }) +public @interface DllExport +{ + String name(); + int ordinal(); +} diff --git a/classpath/ikvm/lang/Internal.java b/classpath/ikvm/lang/Internal.java new file mode 100644 index 0000000..646bf17 --- /dev/null +++ b/classpath/ikvm/lang/Internal.java @@ -0,0 +1,38 @@ +/* + Copyright (C) 2006 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package ikvm.lang; + +import java.lang.annotation.*; + +/** + * Can be used to mark public types or members as internal (i.e. private to the assembly) + * + */ + +@Documented +@Retention(RetentionPolicy.CLASS) +@Target({ ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE }) +public @interface Internal +{ +} diff --git a/classpath/ikvm/lang/IterableEnumerator.java b/classpath/ikvm/lang/IterableEnumerator.java new file mode 100644 index 0000000..ab73824 --- /dev/null +++ b/classpath/ikvm/lang/IterableEnumerator.java @@ -0,0 +1,69 @@ +/* + Copyright (C) 2007 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package ikvm.lang; + +import cli.System.Collections.IEnumerator; +import cli.System.InvalidOperationException; +import ikvm.runtime.Util; +import java.util.Iterator; + +public final class IterableEnumerator implements IEnumerator +{ + private static final Object UNDEFINED = new Object(); + private final Iterable src; + private Iterator iter; + private Object current; + + public IterableEnumerator(Iterable src) + { + this.src = src; + Reset(); + } + + public boolean MoveNext() + { + if (iter.hasNext()) + { + current = iter.next(); + return true; + } + current = UNDEFINED; + return false; + } + + public Object get_Current() + { + if (current == UNDEFINED) + { + Util.throwException(new InvalidOperationException()); + } + return current; + } + + public void Reset() + { + iter = src.iterator(); + current = UNDEFINED; + } +} diff --git a/classpath/ikvm/lang/MapEnumerator.java b/classpath/ikvm/lang/MapEnumerator.java new file mode 100644 index 0000000..d65356d --- /dev/null +++ b/classpath/ikvm/lang/MapEnumerator.java @@ -0,0 +1,70 @@ +/* + Copyright (C) 2008 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package ikvm.lang; + +import cli.System.Collections.IDictionaryEnumerator; +import cli.System.Collections.DictionaryEntry; +import java.util.Map; + +public final class MapEnumerator implements IDictionaryEnumerator +{ + private final Map map; + private final IterableEnumerator keys; + + public MapEnumerator(Map map) + { + this.map = map; + keys = new IterableEnumerator(map.keySet()); + } + + public Object get_Current() + { + return new DictionaryEntry(get_Key(), get_Value()); + } + + public boolean MoveNext() + { + return keys.MoveNext(); + } + + public void Reset() + { + keys.Reset(); + } + + public DictionaryEntry get_Entry() + { + return new DictionaryEntry(get_Key(), get_Value()); + } + + public Object get_Key() + { + return keys.get_Current(); + } + + public Object get_Value() + { + return map.get(keys.get_Current()); + } +} diff --git a/classpath/ikvm/lang/Property.java b/classpath/ikvm/lang/Property.java new file mode 100644 index 0000000..f850421 --- /dev/null +++ b/classpath/ikvm/lang/Property.java @@ -0,0 +1,12 @@ +package ikvm.lang; + +import java.lang.annotation.*; + +@Documented +@Retention(RetentionPolicy.CLASS) +@Target({ ElementType.FIELD }) +public @interface Property +{ + String get(); + String set() default ""; +} diff --git a/classpath/ikvm/runtime/AppDomainAssemblyClassLoader.java b/classpath/ikvm/runtime/AppDomainAssemblyClassLoader.java new file mode 100644 index 0000000..2c3f8e7 --- /dev/null +++ b/classpath/ikvm/runtime/AppDomainAssemblyClassLoader.java @@ -0,0 +1,71 @@ +/* + Copyright (C) 2007 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package ikvm.runtime; + +import cli.System.AppDomain; +import cli.System.Reflection.Assembly; +import java.io.IOException; +import java.net.URL; +import java.util.Enumeration; +import java.util.Vector; + +public final class AppDomainAssemblyClassLoader extends ClassLoader +{ + public AppDomainAssemblyClassLoader(Assembly assembly) + { + super(new AssemblyClassLoader(assembly)); + } + + protected Class findClass(String name) throws ClassNotFoundException + { + Assembly[] assemblies = AppDomain.get_CurrentDomain().GetAssemblies(); + for (int i = 0; i < assemblies.length; i++) + { + Class c = loadClassFromAssembly(assemblies[i], name); + if (c != null) + { + return c; + } + } + throw new ClassNotFoundException(name); + } + + private static native Class loadClassFromAssembly(Assembly asm, String className); + + protected native URL findResource(String name); + + // we override getResources() instead of findResources() to be able to filter duplicates + public Enumeration getResources(String name) throws IOException + { + Vector v = new Vector(); + for (Enumeration e = super.getResources(name); e.hasMoreElements(); ) + { + v.add(e.nextElement()); + } + getResources(v, name); + return v.elements(); + } + + private static native void getResources(Vector v, String name); +} diff --git a/classpath/ikvm/runtime/ClassPathAssemblyClassLoader.java b/classpath/ikvm/runtime/ClassPathAssemblyClassLoader.java new file mode 100644 index 0000000..3829313 --- /dev/null +++ b/classpath/ikvm/runtime/ClassPathAssemblyClassLoader.java @@ -0,0 +1,106 @@ +/* + Copyright (C) 2007 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package ikvm.runtime; + +import cli.System.Reflection.Assembly; +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.StringTokenizer; +import sun.net.www.ParseUtil; + +public final class ClassPathAssemblyClassLoader extends URLClassLoader +{ + public ClassPathAssemblyClassLoader(Assembly assembly) + { + super(buildURLs(), new AssemblyClassLoader(assembly)); + } + + private static URL[] buildURLs() + { + // we can assume we're already runnning in a privileged context + // (otherwise you wouldn't be able to construct a ClassLoader anyway) + String classpath = System.getProperty("java.class.path", ""); + if (classpath.length() == 0) + { + classpath = System.getenv("CLASSPATH"); + if (classpath == null || classpath.length() == 0) + { + classpath = "."; + } + } + // Copyright note: this code is identical to the code in GNU Classpath's ClassLoader, + // but I wrote that code so I co-own the copyright and can dual license it to use + // here under the zlib license. + StringTokenizer tok = new StringTokenizer(classpath, File.pathSeparator, true); + ArrayList list = new ArrayList(); + while (tok.hasMoreTokens()) + { + String s = tok.nextToken(); + if (s.equals(File.pathSeparator)) + { + addFileURL(list, "."); + } + else + { + addFileURL(list, s); + if (tok.hasMoreTokens()) + { + // Skip the separator. + tok.nextToken(); + // If the classpath ended with a separator, + // append the current directory. + if (!tok.hasMoreTokens()) + { + addFileURL(list, "."); + } + } + } + } + URL[] urls = new URL[list.size()]; + list.toArray(urls); + return urls; + } + + private static void addFileURL(ArrayList list, String pathname) + { + try + { + File file = new File(pathname); + try + { + file = file.getCanonicalFile(); + } + catch (java.io.IOException _) + { + } + list.add(ParseUtil.fileToEncodedURL(file)); + } + catch (java.net.MalformedURLException x) + { + throw new InternalError(); + } + } +} diff --git a/classpath/ikvm/runtime/Delegates.java b/classpath/ikvm/runtime/Delegates.java new file mode 100644 index 0000000..6e1ba92 --- /dev/null +++ b/classpath/ikvm/runtime/Delegates.java @@ -0,0 +1,91 @@ +/* + Copyright (C) 2009-2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package ikvm.runtime; + +import cli.System.MulticastDelegate; +import java.lang.reflect.InvocationHandler; +import java.security.PrivilegedAction; + +public final class Delegates +{ + private Delegates() { } + + public static Runnable toRunnable(RunnableDelegate delegate) + { + return delegate; + } + + public static PrivilegedAction toPrivilegedAction(PrivilegedActionDelegate delegate) + { + return delegate; + } + + public static InvocationHandler toInvocationHandler(InvocationHandlerDelegate delegate) + { + return delegate; + } + + public static final class RunnableDelegate extends MulticastDelegate implements Runnable + { + public RunnableDelegate(Method m) { } + public native void Invoke(); + public interface Method + { + void Invoke(); + } + public void run() + { + Invoke(); + } + } + + public static final class PrivilegedActionDelegate extends MulticastDelegate implements PrivilegedAction + { + public PrivilegedActionDelegate(Method m) { } + public native Object Invoke(); + public interface Method + { + Object Invoke(); + } + public Object run() + { + return Invoke(); + } + } + + public static final class InvocationHandlerDelegate extends MulticastDelegate implements InvocationHandler + { + public InvocationHandlerDelegate(Method m) { } + public native Object Invoke(Object proxy, java.lang.reflect.Method method, Object[] args) throws Throwable; + public interface Method + { + Object Invoke(Object proxy, java.lang.reflect.Method method, Object[] args) throws Throwable; + } + public Object invoke(Object proxy, java.lang.reflect.Method method, Object[] args) throws Throwable + { + return Invoke(proxy, method, args); + } + } +} diff --git a/classpath/ikvm/runtime/EnumerationWrapper.java b/classpath/ikvm/runtime/EnumerationWrapper.java new file mode 100644 index 0000000..9c8d7b4 --- /dev/null +++ b/classpath/ikvm/runtime/EnumerationWrapper.java @@ -0,0 +1,55 @@ +/* + Copyright (C) 2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package ikvm.runtime; + +import cli.System.Collections.IEnumerable; +import cli.System.Collections.IEnumerator; +import java.util.Enumeration; +import java.util.NoSuchElementException; + +public final class EnumerationWrapper implements Enumeration +{ + private final IEnumerator enumerator; + private boolean next; + + public EnumerationWrapper(IEnumerable enumerable) + { + this.enumerator = enumerable.GetEnumerator(); + next = enumerator.MoveNext(); + } + + public boolean hasMoreElements() + { + return next; + } + + public T nextElement() + { + if (!next) + throw new NoSuchElementException(); + Object value = enumerator.get_Current(); + next = enumerator.MoveNext(); + return (T)value; + } +} diff --git a/classpath/ikvm/runtime/Startup.java b/classpath/ikvm/runtime/Startup.java new file mode 100644 index 0000000..9414916 --- /dev/null +++ b/classpath/ikvm/runtime/Startup.java @@ -0,0 +1,187 @@ +/* + Copyright (C) 2006-2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package ikvm.runtime; + +import cli.System.Collections.ArrayList; +import cli.System.Collections.ICollection; +import cli.System.ComponentModel.EditorBrowsableAttribute; +import cli.System.ComponentModel.EditorBrowsableState; +import cli.System.Environment; +import cli.System.InvalidOperationException; +import cli.System.IO.DirectoryInfo; +import cli.System.IO.FileSystemInfo; +import cli.System.IO.Path; +import cli.System.ObsoleteAttribute; +import cli.System.Reflection.Assembly; +import cli.System.Reflection.AssemblyTitleAttribute; +import cli.System.Reflection.AssemblyCopyrightAttribute; +import cli.System.Text.StringBuilder; +import cli.System.Threading.Thread; +import cli.System.Type; +import sun.misc.SignalHandler; + +public final class Startup +{ + @ikvm.lang.Internal + public static cli.System.Collections.IDictionary props; + + private Startup() + { + } + + private static String[] glob(String arg) + { + try + { + String dir = Path.GetDirectoryName(arg); + if(dir == "") + { + dir = null; + } + ArrayList list = new ArrayList(); + for(FileSystemInfo fsi : new DirectoryInfo(dir == null ? Environment.get_CurrentDirectory() : dir).GetFileSystemInfos(Path.GetFileName(arg))) + { + list.Add(dir != null ? Path.Combine(dir, fsi.get_Name()) : fsi.get_Name()); + } + if(list.get_Count() == 0) + { + return new String[] { arg }; + } + return (String[])(Object)list.ToArray(Type.GetType("System.String")); + } + catch(Throwable _) + { + return new String[] { arg }; + } + } + + @Deprecated + public static String[] glob() + { + return glob(1); + } + + @Deprecated + public static String[] glob(int skip) + { + return glob(Environment.GetCommandLineArgs(), skip); + } + + public static String[] glob(String[] args, int skip) + { + if (!ikvm.internal.Util.WINDOWS) + { + String[] vmargs = new String[args.length - skip]; + System.arraycopy(args, skip, vmargs, 0, args.length - skip); + return vmargs; + } + else + { + ArrayList list = new ArrayList(); + for (int i = skip; i < args.length; i++) + { + String arg = args[i]; + if (arg.indexOf('*') != -1 || arg.indexOf('?') != -1) + { + list.AddRange((ICollection)(Object)glob(arg)); + } + else + { + list.Add(arg); + } + } + return (String[])(Object)list.ToArray(Type.GetType("System.String")); + } + } + + public static void setProperties(cli.System.Collections.IDictionary props) + { + Startup.props = props; + } + + public static void enterMainThread() + { + if(Thread.get_CurrentThread().get_Name() == null) + { + try + { + if(false) throw new InvalidOperationException(); + Thread.get_CurrentThread().set_Name("main"); + } + catch(InvalidOperationException _) + { + } + } + java.lang.Thread.currentThread(); + + try{ + sun.misc.Signal.handle(new sun.misc.Signal("BREAK"), SignalHandler.SIG_DFL); + }catch(IllegalArgumentException ex){ + // ignore it; + } + } + + public static void exitMainThread() + { + // FXBUG when the main thread ends, it doesn't actually die, it stays around to manage the lifetime + // of the CLR, but in doing so it also keeps alive the thread local storage for this thread and we + // use the TLS as a hack to track when the thread dies (if the object stored in the TLS is finalized, + // we know the thread is dead). So to make that work for the main thread, we use jniDetach which + // explicitly cleans up our thread. + jniDetach(); + } + + private static native void jniDetach(); + + public static String getVersionAndCopyrightInfo() + { + Assembly asm = Assembly.GetEntryAssembly(); + Object[] desc = asm.GetCustomAttributes(Util.getInstanceTypeFromClass(AssemblyTitleAttribute.class), false); + if(desc.length == 1) + { + Object[] copyright = asm.GetCustomAttributes(Util.getInstanceTypeFromClass(AssemblyCopyrightAttribute.class), false); + if(copyright.length == 1) + { + return cli.System.String.Format("{0} version {1}{2}{3}{2}http://www.ikvm.net/", + ((AssemblyTitleAttribute)desc[0]).get_Title(), + asm.GetName().get_Version(), + Environment.get_NewLine(), + ((AssemblyCopyrightAttribute)copyright[0]).get_Copyright()); + } + } + return ""; + } + + // note the stupid typo, this exists for compatibility + @EditorBrowsableAttribute.Annotation(EditorBrowsableState.__Enum.Never) + @ObsoleteAttribute.Annotation("Please use the version without the typo.") + @Deprecated + public static void addBootClassPathAssemby(Assembly assembly) + { + addBootClassPathAssembly(assembly); + } + + public static native void addBootClassPathAssembly(Assembly assembly); +} diff --git a/classpath/ikvm/runtime/Util.java b/classpath/ikvm/runtime/Util.java new file mode 100644 index 0000000..46c344b --- /dev/null +++ b/classpath/ikvm/runtime/Util.java @@ -0,0 +1,55 @@ +/* + Copyright (C) 2006, 2007 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package ikvm.runtime; + +import cli.System.Type; +import cli.System.RuntimeTypeHandle; +import sun.misc.Unsafe; + +public final class Util +{ + private Util() + { + } + + public static native Class getClassFromObject(Object o); + + public static native Class getClassFromTypeHandle(RuntimeTypeHandle handle); + + // this is used to create an array of a remapped type (e.g. getClassFromTypeHandle(typeof(object), 1) returns cli.System.Object[]) + public static native Class getClassFromTypeHandle(RuntimeTypeHandle handle, int rank); + + public static native Class getFriendlyClassFromType(Type type); + + public static native Type getInstanceTypeFromClass(Class classObject); + + public static native Throwable mapException(Throwable x); + + public static native Throwable unmapException(Throwable x); + + public static void throwException(cli.System.Exception x) + { + Unsafe.getUnsafe().throwException(x); + } +} diff --git a/classpath/java/util/concurrent/atomic/AtomicBoolean.java b/classpath/java/util/concurrent/atomic/AtomicBoolean.java new file mode 100644 index 0000000..6c1f1b1 --- /dev/null +++ b/classpath/java/util/concurrent/atomic/AtomicBoolean.java @@ -0,0 +1,152 @@ +/* + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +package java.util.concurrent.atomic; + +/** + * A {@code boolean} value that may be updated atomically. See the + * {@link java.util.concurrent.atomic} package specification for + * description of the properties of atomic variables. An + * {@code AtomicBoolean} is used in applications such as atomically + * updated flags, and cannot be used as a replacement for a + * {@link java.lang.Boolean}. + * + * @since 1.5 + * @author Doug Lea + */ +public class AtomicBoolean implements java.io.Serializable { + private static final long serialVersionUID = 4654671469794556979L; + + private volatile int value; + + /** + * Creates a new {@code AtomicBoolean} with the given initial value. + * + * @param initialValue the initial value + */ + public AtomicBoolean(boolean initialValue) { + value = initialValue ? 1 : 0; + } + + /** + * Creates a new {@code AtomicBoolean} with initial value {@code false}. + */ + public AtomicBoolean() { + } + + /** + * Returns the current value. + * + * @return the current value + */ + public final boolean get() { + return value != 0; + } + + /** + * Atomically sets the value to the given updated value + * if the current value {@code ==} the expected value. + * + * @param expect the expected value + * @param update the new value + * @return {@code true} if successful. False return indicates that + * the actual value was not equal to the expected value. + */ + public final boolean compareAndSet(boolean expect, boolean update) { + int e = expect ? 1 : 0; + int u = update ? 1 : 0; + return compareAndSwapInt(e, u); + } + // implemented in map.xml + private native boolean compareAndSwapInt(int expected, int update); + + /** + * Atomically sets the value to the given updated value + * if the current value {@code ==} the expected value. + * + *

May fail + * spuriously and does not provide ordering guarantees, so is + * only rarely an appropriate alternative to {@code compareAndSet}. + * + * @param expect the expected value + * @param update the new value + * @return {@code true} if successful + */ + public boolean weakCompareAndSet(boolean expect, boolean update) { + return compareAndSet(expect, update); + } + + /** + * Unconditionally sets to the given value. + * + * @param newValue the new value + */ + public final void set(boolean newValue) { + value = newValue ? 1 : 0; + } + + /** + * Eventually sets to the given value. + * + * @param newValue the new value + * @since 1.6 + */ + public final void lazySet(boolean newValue) { + value = newValue ? 1 : 0; + } + + /** + * Atomically sets to the given value and returns the previous value. + * + * @param newValue the new value + * @return the previous value + */ + public final boolean getAndSet(boolean newValue) { + boolean prev; + do { + prev = get(); + } while (!compareAndSet(prev, newValue)); + return prev; + } + + /** + * Returns the String representation of the current value. + * @return the String representation of the current value + */ + public String toString() { + return Boolean.toString(get()); + } + +} diff --git a/classpath/java/util/concurrent/atomic/AtomicInteger.java b/classpath/java/util/concurrent/atomic/AtomicInteger.java new file mode 100644 index 0000000..11753d4 --- /dev/null +++ b/classpath/java/util/concurrent/atomic/AtomicInteger.java @@ -0,0 +1,314 @@ +/* + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +package java.util.concurrent.atomic; +import java.util.function.IntUnaryOperator; +import java.util.function.IntBinaryOperator; + +/** + * An {@code int} value that may be updated atomically. See the + * {@link java.util.concurrent.atomic} package specification for + * description of the properties of atomic variables. An + * {@code AtomicInteger} is used in applications such as atomically + * incremented counters, and cannot be used as a replacement for an + * {@link java.lang.Integer}. However, this class does extend + * {@code Number} to allow uniform access by tools and utilities that + * deal with numerically-based classes. + * + * @since 1.5 + * @author Doug Lea +*/ +public class AtomicInteger extends Number implements java.io.Serializable { + private static final long serialVersionUID = 6214790243416807050L; + + private volatile int value; + + /** + * Creates a new AtomicInteger with the given initial value. + * + * @param initialValue the initial value + */ + public AtomicInteger(int initialValue) { + value = initialValue; + } + + /** + * Creates a new AtomicInteger with initial value {@code 0}. + */ + public AtomicInteger() { + } + + /** + * Gets the current value. + * + * @return the current value + */ + public final int get() { + return value; + } + + /** + * Sets to the given value. + * + * @param newValue the new value + */ + public final void set(int newValue) { + value = newValue; + } + + /** + * Eventually sets to the given value. + * + * @param newValue the new value + * @since 1.6 + */ + public final void lazySet(int newValue) { + value = newValue; + } + + /** + * Atomically sets to the given value and returns the old value. + * + * @param newValue the new value + * @return the previous value + */ + public final native int getAndSet(int newValue); + + /** + * Atomically sets the value to the given updated value + * if the current value {@code ==} the expected value. + * + * @param expect the expected value + * @param update the new value + * @return {@code true} if successful. False return indicates that + * the actual value was not equal to the expected value. + */ + public final native boolean compareAndSet(int expect, int update); + + /** + * Atomically sets the value to the given updated value + * if the current value {@code ==} the expected value. + * + *

May fail + * spuriously and does not provide ordering guarantees, so is + * only rarely an appropriate alternative to {@code compareAndSet}. + * + * @param expect the expected value + * @param update the new value + * @return {@code true} if successful + */ + public final boolean weakCompareAndSet(int expect, int update) { + return compareAndSet(expect, update); + } + + /** + * Atomically increments by one the current value. + * + * @return the previous value + */ + public final int getAndIncrement() { + return incrementAndGet() - 1; + } + + /** + * Atomically decrements by one the current value. + * + * @return the previous value + */ + public final int getAndDecrement() { + return decrementAndGet() + 1; + } + + /** + * Atomically adds the given value to the current value. + * + * @param delta the value to add + * @return the previous value + */ + public final int getAndAdd(int delta) { + return addAndGet(delta) - delta; + } + + /** + * Atomically increments by one the current value. + * + * @return the updated value + */ + public final native int incrementAndGet(); + + /** + * Atomically decrements by one the current value. + * + * @return the updated value + */ + public final native int decrementAndGet(); + + /** + * Atomically adds the given value to the current value. + * + * @param delta the value to add + * @return the updated value + */ + public final native int addAndGet(int delta); + + /** + * Atomically updates the current value with the results of + * applying the given function, returning the previous value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param updateFunction a side-effect-free function + * @return the previous value + * @since 1.8 + */ + public final int getAndUpdate(IntUnaryOperator updateFunction) { + int prev, next; + do { + prev = get(); + next = updateFunction.applyAsInt(prev); + } while (!compareAndSet(prev, next)); + return prev; + } + + /** + * Atomically updates the current value with the results of + * applying the given function, returning the updated value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param updateFunction a side-effect-free function + * @return the updated value + * @since 1.8 + */ + public final int updateAndGet(IntUnaryOperator updateFunction) { + int prev, next; + do { + prev = get(); + next = updateFunction.applyAsInt(prev); + } while (!compareAndSet(prev, next)); + return next; + } + + /** + * Atomically updates the current value with the results of + * applying the given function to the current and given values, + * returning the previous value. The function should be + * side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function + * is applied with the current value as its first argument, + * and the given update as the second argument. + * + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the previous value + * @since 1.8 + */ + public final int getAndAccumulate(int x, + IntBinaryOperator accumulatorFunction) { + int prev, next; + do { + prev = get(); + next = accumulatorFunction.applyAsInt(prev, x); + } while (!compareAndSet(prev, next)); + return prev; + } + + /** + * Atomically updates the current value with the results of + * applying the given function to the current and given values, + * returning the updated value. The function should be + * side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function + * is applied with the current value as its first argument, + * and the given update as the second argument. + * + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the updated value + * @since 1.8 + */ + public final int accumulateAndGet(int x, + IntBinaryOperator accumulatorFunction) { + int prev, next; + do { + prev = get(); + next = accumulatorFunction.applyAsInt(prev, x); + } while (!compareAndSet(prev, next)); + return next; + } + + /** + * Returns the String representation of the current value. + * @return the String representation of the current value + */ + public String toString() { + return Integer.toString(get()); + } + + /** + * Returns the value of this {@code AtomicInteger} as an {@code int}. + */ + public int intValue() { + return get(); + } + + /** + * Returns the value of this {@code AtomicInteger} as a {@code long} + * after a widening primitive conversion. + * @jls 5.1.2 Widening Primitive Conversions + */ + public long longValue() { + return (long)get(); + } + + /** + * Returns the value of this {@code AtomicInteger} as a {@code float} + * after a widening primitive conversion. + * @jls 5.1.2 Widening Primitive Conversions + */ + public float floatValue() { + return (float)get(); + } + + /** + * Returns the value of this {@code AtomicInteger} as a {@code double} + * after a widening primitive conversion. + * @jls 5.1.2 Widening Primitive Conversions + */ + public double doubleValue() { + return (double)get(); + } + +} diff --git a/classpath/java/util/concurrent/atomic/AtomicIntegerArray.java b/classpath/java/util/concurrent/atomic/AtomicIntegerArray.java new file mode 100644 index 0000000..893ac07 --- /dev/null +++ b/classpath/java/util/concurrent/atomic/AtomicIntegerArray.java @@ -0,0 +1,315 @@ +/* + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +package java.util.concurrent.atomic; +import java.util.function.IntUnaryOperator; +import java.util.function.IntBinaryOperator; + +/** + * An {@code int} array in which elements may be updated atomically. + * See the {@link java.util.concurrent.atomic} package + * specification for description of the properties of atomic + * variables. + * @since 1.5 + * @author Doug Lea + */ +public class AtomicIntegerArray implements java.io.Serializable { + private static final long serialVersionUID = 2862133569453604235L; + + private final int[] array; + + /** + * Creates a new AtomicIntegerArray of the given length, with all + * elements initially zero. + * + * @param length the length of the array + */ + public AtomicIntegerArray(int length) { + array = new int[length]; + } + + /** + * Creates a new AtomicIntegerArray with the same length as, and + * all elements copied from, the given array. + * + * @param array the array to copy elements from + * @throws NullPointerException if array is null + */ + public AtomicIntegerArray(int[] array) { + // Visibility guaranteed by final field guarantees + this.array = array.clone(); + } + + /** + * Returns the length of the array. + * + * @return the length of the array + */ + public final int length() { + return array.length; + } + + /** + * Gets the current value at position {@code i}. + * + * @param i the index + * @return the current value + */ + public final native int get(int i); + + /** + * Sets the element at position {@code i} to the given value. + * + * @param i the index + * @param newValue the new value + */ + public final native void set(int i, int newValue); + + /** + * Eventually sets the element at position {@code i} to the given value. + * + * @param i the index + * @param newValue the new value + * @since 1.6 + */ + public final void lazySet(int i, int newValue) { + set(i, newValue); + } + + /** + * Atomically sets the element at position {@code i} to the given + * value and returns the old value. + * + * @param i the index + * @param newValue the new value + * @return the previous value + */ + public final native int getAndSet(int i, int newValue); + + /** + * Atomically sets the element at position {@code i} to the given + * updated value if the current value {@code ==} the expected value. + * + * @param i the index + * @param expect the expected value + * @param update the new value + * @return {@code true} if successful. False return indicates that + * the actual value was not equal to the expected value. + */ + public final native boolean compareAndSet(int i, int expect, int update); + + /** + * Atomically sets the element at position {@code i} to the given + * updated value if the current value {@code ==} the expected value. + * + *

May fail + * spuriously and does not provide ordering guarantees, so is + * only rarely an appropriate alternative to {@code compareAndSet}. + * + * @param i the index + * @param expect the expected value + * @param update the new value + * @return {@code true} if successful + */ + public final boolean weakCompareAndSet(int i, int expect, int update) { + return compareAndSet(i, expect, update); + } + + /** + * Atomically increments by one the element at index {@code i}. + * + * @param i the index + * @return the previous value + */ + public final int getAndIncrement(int i) { + return incrementAndGet(i) - 1; + } + + /** + * Atomically decrements by one the element at index {@code i}. + * + * @param i the index + * @return the previous value + */ + public final int getAndDecrement(int i) { + return decrementAndGet(i) + 1; + } + + /** + * Atomically adds the given value to the element at index {@code i}. + * + * @param i the index + * @param delta the value to add + * @return the previous value + */ + public final int getAndAdd(int i, int delta) { + return addAndGet(i, delta) - delta; + } + + /** + * Atomically increments by one the element at index {@code i}. + * + * @param i the index + * @return the updated value + */ + public final native int incrementAndGet(int i); + + /** + * Atomically decrements by one the element at index {@code i}. + * + * @param i the index + * @return the updated value + */ + public final native int decrementAndGet(int i); + + /** + * Atomically adds the given value to the element at index {@code i}. + * + * @param i the index + * @param delta the value to add + * @return the updated value + */ + public final native int addAndGet(int i, int delta); + + /** + * Atomically updates the element at index {@code i} with the results + * of applying the given function, returning the previous value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param i the index + * @param updateFunction a side-effect-free function + * @return the previous value + * @since 1.8 + */ + public final int getAndUpdate(int i, IntUnaryOperator updateFunction) { + int prev, next; + do { + prev = get(i); + next = updateFunction.applyAsInt(prev); + } while (!compareAndSet(i, prev, next)); + return prev; + } + + /** + * Atomically updates the element at index {@code i} with the results + * of applying the given function, returning the updated value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param i the index + * @param updateFunction a side-effect-free function + * @return the updated value + * @since 1.8 + */ + public final int updateAndGet(int i, IntUnaryOperator updateFunction) { + int prev, next; + do { + prev = get(i); + next = updateFunction.applyAsInt(prev); + } while (!compareAndSet(i, prev, next)); + return next; + } + + /** + * Atomically updates the element at index {@code i} with the + * results of applying the given function to the current and + * given values, returning the previous value. The function should + * be side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function is + * applied with the current value at index {@code i} as its first + * argument, and the given update as the second argument. + * + * @param i the index + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the previous value + * @since 1.8 + */ + public final int getAndAccumulate(int i, int x, + IntBinaryOperator accumulatorFunction) { + int prev, next; + do { + prev = get(i); + next = accumulatorFunction.applyAsInt(prev, x); + } while (!compareAndSet(i, prev, next)); + return prev; + } + + /** + * Atomically updates the element at index {@code i} with the + * results of applying the given function to the current and + * given values, returning the updated value. The function should + * be side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function is + * applied with the current value at index {@code i} as its first + * argument, and the given update as the second argument. + * + * @param i the index + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the updated value + * @since 1.8 + */ + public final int accumulateAndGet(int i, int x, + IntBinaryOperator accumulatorFunction) { + int prev, next; + do { + prev = get(i); + next = accumulatorFunction.applyAsInt(prev, x); + } while (!compareAndSet(i, prev, next)); + return next; + } + + /** + * Returns the String representation of the current values of array. + * @return the String representation of the current values of array. + */ + public String toString() { + int iMax = array.length - 1; + if (iMax == -1) + return "[]"; + + StringBuilder b = new StringBuilder(); + b.append('['); + for (int i = 0; ; i++) { + b.append(get(i)); + if (i == iMax) + return b.append(']').toString(); + b.append(',').append(' '); + } + } + +} diff --git a/classpath/java/util/concurrent/atomic/AtomicLong.java b/classpath/java/util/concurrent/atomic/AtomicLong.java new file mode 100644 index 0000000..0d07fb1 --- /dev/null +++ b/classpath/java/util/concurrent/atomic/AtomicLong.java @@ -0,0 +1,322 @@ +/* + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +package java.util.concurrent.atomic; +import java.util.function.LongUnaryOperator; +import java.util.function.LongBinaryOperator; + +/** + * A {@code long} value that may be updated atomically. See the + * {@link java.util.concurrent.atomic} package specification for + * description of the properties of atomic variables. An + * {@code AtomicLong} is used in applications such as atomically + * incremented sequence numbers, and cannot be used as a replacement + * for a {@link java.lang.Long}. However, this class does extend + * {@code Number} to allow uniform access by tools and utilities that + * deal with numerically-based classes. + * + * @since 1.5 + * @author Doug Lea + */ +public class AtomicLong extends Number implements java.io.Serializable { + private static final long serialVersionUID = 1927816293512124184L; + + /** + * Records whether the underlying JVM supports lockless + * compareAndSwap for longs. While the Unsafe.compareAndSwapLong + * method works in either case, some constructions should be + * handled at Java level to avoid locking user-visible locks. + */ + static final boolean VM_SUPPORTS_LONG_CAS = false; + + private volatile long value; + + /** + * Creates a new AtomicLong with the given initial value. + * + * @param initialValue the initial value + */ + public AtomicLong(long initialValue) { + value = initialValue; + } + + /** + * Creates a new AtomicLong with initial value {@code 0}. + */ + public AtomicLong() { + } + + /** + * Gets the current value. + * + * @return the current value + */ + public final long get() { + return value; + } + + /** + * Sets to the given value. + * + * @param newValue the new value + */ + public final void set(long newValue) { + value = newValue; + } + + /** + * Eventually sets to the given value. + * + * @param newValue the new value + * @since 1.6 + */ + public final void lazySet(long newValue) { + value = newValue; + } + + /** + * Atomically sets to the given value and returns the old value. + * + * @param newValue the new value + * @return the previous value + */ + public final native long getAndSet(long newValue); + + /** + * Atomically sets the value to the given updated value + * if the current value {@code ==} the expected value. + * + * @param expect the expected value + * @param update the new value + * @return {@code true} if successful. False return indicates that + * the actual value was not equal to the expected value. + */ + public final native boolean compareAndSet(long expect, long update); + + /** + * Atomically sets the value to the given updated value + * if the current value {@code ==} the expected value. + * + *

May fail + * spuriously and does not provide ordering guarantees, so is + * only rarely an appropriate alternative to {@code compareAndSet}. + * + * @param expect the expected value + * @param update the new value + * @return {@code true} if successful + */ + public final boolean weakCompareAndSet(long expect, long update) { + return compareAndSet(expect, update); + } + + /** + * Atomically increments by one the current value. + * + * @return the previous value + */ + public final long getAndIncrement() { + return incrementAndGet() - 1; + } + + /** + * Atomically decrements by one the current value. + * + * @return the previous value + */ + public final long getAndDecrement() { + return decrementAndGet() + 1; + } + + /** + * Atomically adds the given value to the current value. + * + * @param delta the value to add + * @return the previous value + */ + public final long getAndAdd(long delta) { + return addAndGet(delta) - delta; + } + + /** + * Atomically increments by one the current value. + * + * @return the updated value + */ + public final native long incrementAndGet(); + + /** + * Atomically decrements by one the current value. + * + * @return the updated value + */ + public final native long decrementAndGet(); + + /** + * Atomically adds the given value to the current value. + * + * @param delta the value to add + * @return the updated value + */ + public final native long addAndGet(long delta); + + /** + * Atomically updates the current value with the results of + * applying the given function, returning the previous value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param updateFunction a side-effect-free function + * @return the previous value + * @since 1.8 + */ + public final long getAndUpdate(LongUnaryOperator updateFunction) { + long prev, next; + do { + prev = get(); + next = updateFunction.applyAsLong(prev); + } while (!compareAndSet(prev, next)); + return prev; + } + + /** + * Atomically updates the current value with the results of + * applying the given function, returning the updated value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param updateFunction a side-effect-free function + * @return the updated value + * @since 1.8 + */ + public final long updateAndGet(LongUnaryOperator updateFunction) { + long prev, next; + do { + prev = get(); + next = updateFunction.applyAsLong(prev); + } while (!compareAndSet(prev, next)); + return next; + } + + /** + * Atomically updates the current value with the results of + * applying the given function to the current and given values, + * returning the previous value. The function should be + * side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function + * is applied with the current value as its first argument, + * and the given update as the second argument. + * + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the previous value + * @since 1.8 + */ + public final long getAndAccumulate(long x, + LongBinaryOperator accumulatorFunction) { + long prev, next; + do { + prev = get(); + next = accumulatorFunction.applyAsLong(prev, x); + } while (!compareAndSet(prev, next)); + return prev; + } + + /** + * Atomically updates the current value with the results of + * applying the given function to the current and given values, + * returning the updated value. The function should be + * side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function + * is applied with the current value as its first argument, + * and the given update as the second argument. + * + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the updated value + * @since 1.8 + */ + public final long accumulateAndGet(long x, + LongBinaryOperator accumulatorFunction) { + long prev, next; + do { + prev = get(); + next = accumulatorFunction.applyAsLong(prev, x); + } while (!compareAndSet(prev, next)); + return next; + } + + /** + * Returns the String representation of the current value. + * @return the String representation of the current value + */ + public String toString() { + return Long.toString(get()); + } + + /** + * Returns the value of this {@code AtomicLong} as an {@code int} + * after a narrowing primitive conversion. + * @jls 5.1.3 Narrowing Primitive Conversions + */ + public int intValue() { + return (int)get(); + } + + /** + * Returns the value of this {@code AtomicLong} as a {@code long}. + */ + public long longValue() { + return get(); + } + + /** + * Returns the value of this {@code AtomicLong} as a {@code float} + * after a widening primitive conversion. + * @jls 5.1.2 Widening Primitive Conversions + */ + public float floatValue() { + return (float)get(); + } + + /** + * Returns the value of this {@code AtomicLong} as a {@code double} + * after a widening primitive conversion. + * @jls 5.1.2 Widening Primitive Conversions + */ + public double doubleValue() { + return (double)get(); + } + +} diff --git a/classpath/java/util/concurrent/atomic/AtomicLongArray.java b/classpath/java/util/concurrent/atomic/AtomicLongArray.java new file mode 100644 index 0000000..599a2cd --- /dev/null +++ b/classpath/java/util/concurrent/atomic/AtomicLongArray.java @@ -0,0 +1,314 @@ +/* + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +package java.util.concurrent.atomic; +import java.util.function.LongUnaryOperator; +import java.util.function.LongBinaryOperator; + +/** + * A {@code long} array in which elements may be updated atomically. + * See the {@link java.util.concurrent.atomic} package specification + * for description of the properties of atomic variables. + * @since 1.5 + * @author Doug Lea + */ +public class AtomicLongArray implements java.io.Serializable { + private static final long serialVersionUID = -2308431214976778248L; + + private final long[] array; + + /** + * Creates a new AtomicLongArray of the given length, with all + * elements initially zero. + * + * @param length the length of the array + */ + public AtomicLongArray(int length) { + array = new long[length]; + } + + /** + * Creates a new AtomicLongArray with the same length as, and + * all elements copied from, the given array. + * + * @param array the array to copy elements from + * @throws NullPointerException if array is null + */ + public AtomicLongArray(long[] array) { + // Visibility guaranteed by final field guarantees + this.array = array.clone(); + } + + /** + * Returns the length of the array. + * + * @return the length of the array + */ + public final int length() { + return array.length; + } + + /** + * Gets the current value at position {@code i}. + * + * @param i the index + * @return the current value + */ + public final native long get(int i); + + /** + * Sets the element at position {@code i} to the given value. + * + * @param i the index + * @param newValue the new value + */ + public final native void set(int i, long newValue); + + /** + * Eventually sets the element at position {@code i} to the given value. + * + * @param i the index + * @param newValue the new value + * @since 1.6 + */ + public final void lazySet(int i, long newValue) { + set(i, newValue); + } + + /** + * Atomically sets the element at position {@code i} to the given value + * and returns the old value. + * + * @param i the index + * @param newValue the new value + * @return the previous value + */ + public final native long getAndSet(int i, long newValue); + + /** + * Atomically sets the element at position {@code i} to the given + * updated value if the current value {@code ==} the expected value. + * + * @param i the index + * @param expect the expected value + * @param update the new value + * @return {@code true} if successful. False return indicates that + * the actual value was not equal to the expected value. + */ + public final native boolean compareAndSet(int i, long expect, long update); + + /** + * Atomically sets the element at position {@code i} to the given + * updated value if the current value {@code ==} the expected value. + * + *

May fail + * spuriously and does not provide ordering guarantees, so is + * only rarely an appropriate alternative to {@code compareAndSet}. + * + * @param i the index + * @param expect the expected value + * @param update the new value + * @return {@code true} if successful + */ + public final boolean weakCompareAndSet(int i, long expect, long update) { + return compareAndSet(i, expect, update); + } + + /** + * Atomically increments by one the element at index {@code i}. + * + * @param i the index + * @return the previous value + */ + public final long getAndIncrement(int i) { + return incrementAndGet(i) - 1; + } + + /** + * Atomically decrements by one the element at index {@code i}. + * + * @param i the index + * @return the previous value + */ + public final long getAndDecrement(int i) { + return decrementAndGet(i) + 1; + } + + /** + * Atomically adds the given value to the element at index {@code i}. + * + * @param i the index + * @param delta the value to add + * @return the previous value + */ + public final long getAndAdd(int i, long delta) { + return addAndGet(i, delta) - delta; + } + + /** + * Atomically increments by one the element at index {@code i}. + * + * @param i the index + * @return the updated value + */ + public final native long incrementAndGet(int i); + + /** + * Atomically decrements by one the element at index {@code i}. + * + * @param i the index + * @return the updated value + */ + public final native long decrementAndGet(int i); + + /** + * Atomically adds the given value to the element at index {@code i}. + * + * @param i the index + * @param delta the value to add + * @return the updated value + */ + public native long addAndGet(int i, long delta); + + /** + * Atomically updates the element at index {@code i} with the results + * of applying the given function, returning the previous value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param i the index + * @param updateFunction a side-effect-free function + * @return the previous value + * @since 1.8 + */ + public final long getAndUpdate(int i, LongUnaryOperator updateFunction) { + long prev, next; + do { + prev = get(i); + next = updateFunction.applyAsLong(prev); + } while (!compareAndSet(i, prev, next)); + return prev; + } + + /** + * Atomically updates the element at index {@code i} with the results + * of applying the given function, returning the updated value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param i the index + * @param updateFunction a side-effect-free function + * @return the updated value + * @since 1.8 + */ + public final long updateAndGet(int i, LongUnaryOperator updateFunction) { + long prev, next; + do { + prev = get(i); + next = updateFunction.applyAsLong(prev); + } while (!compareAndSet(i, prev, next)); + return next; + } + + /** + * Atomically updates the element at index {@code i} with the + * results of applying the given function to the current and + * given values, returning the previous value. The function should + * be side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function is + * applied with the current value at index {@code i} as its first + * argument, and the given update as the second argument. + * + * @param i the index + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the previous value + * @since 1.8 + */ + public final long getAndAccumulate(int i, long x, + LongBinaryOperator accumulatorFunction) { + long prev, next; + do { + prev = get(i); + next = accumulatorFunction.applyAsLong(prev, x); + } while (!compareAndSet(i, prev, next)); + return prev; + } + + /** + * Atomically updates the element at index {@code i} with the + * results of applying the given function to the current and + * given values, returning the updated value. The function should + * be side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function is + * applied with the current value at index {@code i} as its first + * argument, and the given update as the second argument. + * + * @param i the index + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the updated value + * @since 1.8 + */ + public final long accumulateAndGet(int i, long x, + LongBinaryOperator accumulatorFunction) { + long prev, next; + do { + prev = get(i); + next = accumulatorFunction.applyAsLong(prev, x); + } while (!compareAndSet(i, prev, next)); + return next; + } + + /** + * Returns the String representation of the current values of array. + * @return the String representation of the current values of array + */ + public String toString() { + int iMax = array.length - 1; + if (iMax == -1) + return "[]"; + + StringBuilder b = new StringBuilder(); + b.append('['); + for (int i = 0; ; i++) { + b.append(get(i)); + if (i == iMax) + return b.append(']').toString(); + b.append(',').append(' '); + } + } + +} diff --git a/classpath/java/util/concurrent/atomic/AtomicReference.java b/classpath/java/util/concurrent/atomic/AtomicReference.java new file mode 100644 index 0000000..f36b59d --- /dev/null +++ b/classpath/java/util/concurrent/atomic/AtomicReference.java @@ -0,0 +1,225 @@ +/* + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +package java.util.concurrent.atomic; +import java.util.function.UnaryOperator; +import java.util.function.BinaryOperator; + +/** + * An object reference that may be updated atomically. See the {@link + * java.util.concurrent.atomic} package specification for description + * of the properties of atomic variables. + * @since 1.5 + * @author Doug Lea + * @param The type of object referred to by this reference + */ +public class AtomicReference implements java.io.Serializable { + private static final long serialVersionUID = -1848883965231344442L; + + private volatile V value; + + /** + * Creates a new AtomicReference with the given initial value. + * + * @param initialValue the initial value + */ + public AtomicReference(V initialValue) { + value = initialValue; + } + + /** + * Creates a new AtomicReference with null initial value. + */ + public AtomicReference() { + } + + /** + * Gets the current value. + * + * @return the current value + */ + public final V get() { + return value; + } + + /** + * Sets to the given value. + * + * @param newValue the new value + */ + public final void set(V newValue) { + value = newValue; + } + + /** + * Eventually sets to the given value. + * + * @param newValue the new value + * @since 1.6 + */ + public final void lazySet(V newValue) { + value = newValue; + } + + /** + * Atomically sets the value to the given updated value + * if the current value {@code ==} the expected value. + * @param expect the expected value + * @param update the new value + * @return {@code true} if successful. False return indicates that + * the actual value was not equal to the expected value. + */ + public final native boolean compareAndSet(V expect, V update); + + /** + * Atomically sets the value to the given updated value + * if the current value {@code ==} the expected value. + * + *

May fail + * spuriously and does not provide ordering guarantees, so is + * only rarely an appropriate alternative to {@code compareAndSet}. + * + * @param expect the expected value + * @param update the new value + * @return {@code true} if successful + */ + public final boolean weakCompareAndSet(V expect, V update) { + return compareAndSet(expect, update); + } + + /** + * Atomically sets to the given value and returns the old value. + * + * @param newValue the new value + * @return the previous value + */ + @SuppressWarnings("unchecked") + public final native V getAndSet(V newValue); + + /** + * Atomically updates the current value with the results of + * applying the given function, returning the previous value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param updateFunction a side-effect-free function + * @return the previous value + * @since 1.8 + */ + public final V getAndUpdate(UnaryOperator updateFunction) { + V prev, next; + do { + prev = get(); + next = updateFunction.apply(prev); + } while (!compareAndSet(prev, next)); + return prev; + } + + /** + * Atomically updates the current value with the results of + * applying the given function, returning the updated value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param updateFunction a side-effect-free function + * @return the updated value + * @since 1.8 + */ + public final V updateAndGet(UnaryOperator updateFunction) { + V prev, next; + do { + prev = get(); + next = updateFunction.apply(prev); + } while (!compareAndSet(prev, next)); + return next; + } + + /** + * Atomically updates the current value with the results of + * applying the given function to the current and given values, + * returning the previous value. The function should be + * side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function + * is applied with the current value as its first argument, + * and the given update as the second argument. + * + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the previous value + * @since 1.8 + */ + public final V getAndAccumulate(V x, + BinaryOperator accumulatorFunction) { + V prev, next; + do { + prev = get(); + next = accumulatorFunction.apply(prev, x); + } while (!compareAndSet(prev, next)); + return prev; + } + + /** + * Atomically updates the current value with the results of + * applying the given function to the current and given values, + * returning the updated value. The function should be + * side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function + * is applied with the current value as its first argument, + * and the given update as the second argument. + * + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the updated value + * @since 1.8 + */ + public final V accumulateAndGet(V x, + BinaryOperator accumulatorFunction) { + V prev, next; + do { + prev = get(); + next = accumulatorFunction.apply(prev, x); + } while (!compareAndSet(prev, next)); + return next; + } + + /** + * Returns the String representation of the current value. + * @return the String representation of the current value + */ + public String toString() { + return String.valueOf(get()); + } + +} diff --git a/classpath/java/util/concurrent/atomic/AtomicReferenceArray.java b/classpath/java/util/concurrent/atomic/AtomicReferenceArray.java new file mode 100644 index 0000000..1e02492 --- /dev/null +++ b/classpath/java/util/concurrent/atomic/AtomicReferenceArray.java @@ -0,0 +1,291 @@ +/* + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +package java.util.concurrent.atomic; +import java.util.function.UnaryOperator; +import java.util.function.BinaryOperator; +import java.util.Arrays; +import java.lang.reflect.Array; +import sun.misc.Unsafe; + +/** + * An array of object references in which elements may be updated + * atomically. See the {@link java.util.concurrent.atomic} package + * specification for description of the properties of atomic + * variables. + * @since 1.5 + * @author Doug Lea + * @param The base class of elements held in this array + */ +public class AtomicReferenceArray implements java.io.Serializable { + private static final long serialVersionUID = -6209656149925076980L; + + private static final Unsafe unsafe; + private static final long arrayFieldOffset; + private final Object[] array; // must have exact type Object[] + + static { + try { + unsafe = Unsafe.getUnsafe(); + arrayFieldOffset = unsafe.objectFieldOffset + (AtomicReferenceArray.class.getDeclaredField("array")); + } catch (Exception e) { + throw new Error(e); + } + } + + /** + * Creates a new AtomicReferenceArray of the given length, with all + * elements initially null. + * + * @param length the length of the array + */ + public AtomicReferenceArray(int length) { + array = new Object[length]; + } + + /** + * Creates a new AtomicReferenceArray with the same length as, and + * all elements copied from, the given array. + * + * @param array the array to copy elements from + * @throws NullPointerException if array is null + */ + public AtomicReferenceArray(E[] array) { + // Visibility guaranteed by final field guarantees + this.array = Arrays.copyOf(array, array.length, Object[].class); + } + + /** + * Returns the length of the array. + * + * @return the length of the array + */ + public final int length() { + return array.length; + } + + /** + * Gets the current value at position {@code i}. + * + * @param i the index + * @return the current value + */ + public final native E get(int i); + + /** + * Sets the element at position {@code i} to the given value. + * + * @param i the index + * @param newValue the new value + */ + public final native void set(int i, E newValue); + + /** + * Eventually sets the element at position {@code i} to the given value. + * + * @param i the index + * @param newValue the new value + * @since 1.6 + */ + public final void lazySet(int i, E newValue) { + set(i, newValue); + } + + /** + * Atomically sets the element at position {@code i} to the given + * value and returns the old value. + * + * @param i the index + * @param newValue the new value + * @return the previous value + */ + @SuppressWarnings("unchecked") + public final native E getAndSet(int i, E newValue); + + /** + * Atomically sets the element at position {@code i} to the given + * updated value if the current value {@code ==} the expected value. + * + * @param i the index + * @param expect the expected value + * @param update the new value + * @return {@code true} if successful. False return indicates that + * the actual value was not equal to the expected value. + */ + public final native boolean compareAndSet(int i, E expect, E update); + + /** + * Atomically sets the element at position {@code i} to the given + * updated value if the current value {@code ==} the expected value. + * + *

May fail + * spuriously and does not provide ordering guarantees, so is + * only rarely an appropriate alternative to {@code compareAndSet}. + * + * @param i the index + * @param expect the expected value + * @param update the new value + * @return {@code true} if successful + */ + public final boolean weakCompareAndSet(int i, E expect, E update) { + return compareAndSet(i, expect, update); + } + + /** + * Atomically updates the element at index {@code i} with the results + * of applying the given function, returning the previous value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param i the index + * @param updateFunction a side-effect-free function + * @return the previous value + * @since 1.8 + */ + public final E getAndUpdate(int i, UnaryOperator updateFunction) { + E prev, next; + do { + prev = get(i); + next = updateFunction.apply(prev); + } while (!compareAndSet(i, prev, next)); + return prev; + } + + /** + * Atomically updates the element at index {@code i} with the results + * of applying the given function, returning the updated value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param i the index + * @param updateFunction a side-effect-free function + * @return the updated value + * @since 1.8 + */ + public final E updateAndGet(int i, UnaryOperator updateFunction) { + E prev, next; + do { + prev = get(i); + next = updateFunction.apply(prev); + } while (!compareAndSet(i, prev, next)); + return next; + } + + /** + * Atomically updates the element at index {@code i} with the + * results of applying the given function to the current and + * given values, returning the previous value. The function should + * be side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function is + * applied with the current value at index {@code i} as its first + * argument, and the given update as the second argument. + * + * @param i the index + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the previous value + * @since 1.8 + */ + public final E getAndAccumulate(int i, E x, + BinaryOperator accumulatorFunction) { + E prev, next; + do { + prev = get(i); + next = accumulatorFunction.apply(prev, x); + } while (!compareAndSet(i, prev, next)); + return prev; + } + + /** + * Atomically updates the element at index {@code i} with the + * results of applying the given function to the current and + * given values, returning the updated value. The function should + * be side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function is + * applied with the current value at index {@code i} as its first + * argument, and the given update as the second argument. + * + * @param i the index + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the updated value + * @since 1.8 + */ + public final E accumulateAndGet(int i, E x, + BinaryOperator accumulatorFunction) { + E prev, next; + do { + prev = get(i); + next = accumulatorFunction.apply(prev, x); + } while (!compareAndSet(i, prev, next)); + return next; + } + + /** + * Returns the String representation of the current values of array. + * @return the String representation of the current values of array + */ + public String toString() { + int iMax = array.length - 1; + if (iMax == -1) + return "[]"; + + StringBuilder b = new StringBuilder(); + b.append('['); + for (int i = 0; ; i++) { + b.append(get(i)); + if (i == iMax) + return b.append(']').toString(); + b.append(',').append(' '); + } + } + + /** + * Reconstitutes the instance from a stream (that is, deserializes it). + */ + private void readObject(java.io.ObjectInputStream s) + throws java.io.IOException, ClassNotFoundException, + java.io.InvalidObjectException { + // Note: This must be changed if any additional fields are defined + Object a = s.readFields().get("array", null); + if (a == null || !a.getClass().isArray()) + throw new java.io.InvalidObjectException("Not array type"); + if (a.getClass() != Object[].class) + a = Arrays.copyOf((Object[])a, Array.getLength(a), Object[].class); + unsafe.putObjectVolatile(this, arrayFieldOffset, a); + } + +} diff --git a/classpath/java/util/concurrent/atomic/Striped64.java b/classpath/java/util/concurrent/atomic/Striped64.java new file mode 100644 index 0000000..1fea75b --- /dev/null +++ b/classpath/java/util/concurrent/atomic/Striped64.java @@ -0,0 +1,380 @@ +/* + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +package java.util.concurrent.atomic; +import java.util.function.LongBinaryOperator; +import java.util.function.DoubleBinaryOperator; +import java.util.concurrent.ThreadLocalRandom; + +/** + * A package-local class holding common representation and mechanics + * for classes supporting dynamic striping on 64bit values. The class + * extends Number so that concrete subclasses must publicly do so. + */ +@SuppressWarnings("serial") +abstract class Striped64 extends Number { + /* + * This class maintains a lazily-initialized table of atomically + * updated variables, plus an extra "base" field. The table size + * is a power of two. Indexing uses masked per-thread hash codes. + * Nearly all declarations in this class are package-private, + * accessed directly by subclasses. + * + * Table entries are of class Cell; a variant of AtomicLong padded + * (via @sun.misc.Contended) to reduce cache contention. Padding + * is overkill for most Atomics because they are usually + * irregularly scattered in memory and thus don't interfere much + * with each other. But Atomic objects residing in arrays will + * tend to be placed adjacent to each other, and so will most + * often share cache lines (with a huge negative performance + * impact) without this precaution. + * + * In part because Cells are relatively large, we avoid creating + * them until they are needed. When there is no contention, all + * updates are made to the base field. Upon first contention (a + * failed CAS on base update), the table is initialized to size 2. + * The table size is doubled upon further contention until + * reaching the nearest power of two greater than or equal to the + * number of CPUS. Table slots remain empty (null) until they are + * needed. + * + * A single spinlock ("cellsBusy") is used for initializing and + * resizing the table, as well as populating slots with new Cells. + * There is no need for a blocking lock; when the lock is not + * available, threads try other slots (or the base). During these + * retries, there is increased contention and reduced locality, + * which is still better than alternatives. + * + * The Thread probe fields maintained via ThreadLocalRandom serve + * as per-thread hash codes. We let them remain uninitialized as + * zero (if they come in this way) until they contend at slot + * 0. They are then initialized to values that typically do not + * often conflict with others. Contention and/or table collisions + * are indicated by failed CASes when performing an update + * operation. Upon a collision, if the table size is less than + * the capacity, it is doubled in size unless some other thread + * holds the lock. If a hashed slot is empty, and lock is + * available, a new Cell is created. Otherwise, if the slot + * exists, a CAS is tried. Retries proceed by "double hashing", + * using a secondary hash (Marsaglia XorShift) to try to find a + * free slot. + * + * The table size is capped because, when there are more threads + * than CPUs, supposing that each thread were bound to a CPU, + * there would exist a perfect hash function mapping threads to + * slots that eliminates collisions. When we reach capacity, we + * search for this mapping by randomly varying the hash codes of + * colliding threads. Because search is random, and collisions + * only become known via CAS failures, convergence can be slow, + * and because threads are typically not bound to CPUS forever, + * may not occur at all. However, despite these limitations, + * observed contention rates are typically low in these cases. + * + * It is possible for a Cell to become unused when threads that + * once hashed to it terminate, as well as in the case where + * doubling the table causes no thread to hash to it under + * expanded mask. We do not try to detect or remove such cells, + * under the assumption that for long-running instances, observed + * contention levels will recur, so the cells will eventually be + * needed again; and for short-lived ones, it does not matter. + */ + + /** + * Padded variant of AtomicLong supporting only raw accesses plus CAS. + * + * JVM intrinsics note: It would be possible to use a release-only + * form of CAS here, if it were provided. + */ + @sun.misc.Contended static final class Cell { + volatile long value; + Cell(long x) { value = x; } + @ikvm.internal.InterlockedCompareAndSet("value") + final native boolean cas(long cmp, long val); + } + + /** Number of CPUS, to place bound on table size */ + static final int NCPU = Runtime.getRuntime().availableProcessors(); + + /** + * Table of cells. When non-null, size is a power of 2. + */ + transient volatile Cell[] cells; + + /** + * Base value, used mainly when there is no contention, but also as + * a fallback during table initialization races. Updated via CAS. + */ + transient volatile long base; + + /** + * Spinlock (locked via CAS) used when resizing and/or creating Cells. + */ + transient volatile int cellsBusy; + + /** + * Package-private default constructor + */ + Striped64() { + } + + /** + * CASes the base field. + */ + @ikvm.internal.InterlockedCompareAndSet("base") + final native boolean casBase(long cmp, long val); + + /** + * CASes the cellsBusy field from 0 to 1 to acquire lock. + */ + final boolean casCellsBusy() { + return casCellsBusy(0, 1); + } + + @ikvm.internal.InterlockedCompareAndSet("cellsBusy") + private native boolean casCellsBusy(int cmp, int newVal); + + /** + * Returns the probe value for the current thread. + * Duplicated from ThreadLocalRandom because of packaging restrictions. + */ + static final int getProbe() { + return Thread.currentThread().threadLocalRandomProbe; + } + + /** + * Pseudo-randomly advances and records the given probe value for the + * given thread. + * Duplicated from ThreadLocalRandom because of packaging restrictions. + */ + static final int advanceProbe(int probe) { + probe ^= probe << 13; // xorshift + probe ^= probe >>> 17; + probe ^= probe << 5; + Thread.currentThread().threadLocalRandomProbe = probe; + return probe; + } + + /** + * Handles cases of updates involving initialization, resizing, + * creating new Cells, and/or contention. See above for + * explanation. This method suffers the usual non-modularity + * problems of optimistic retry code, relying on rechecked sets of + * reads. + * + * @param x the value + * @param fn the update function, or null for add (this convention + * avoids the need for an extra field or function in LongAdder). + * @param wasUncontended false if CAS failed before call + */ + final void longAccumulate(long x, LongBinaryOperator fn, + boolean wasUncontended) { + int h; + if ((h = getProbe()) == 0) { + ThreadLocalRandom.current(); // force initialization + h = getProbe(); + wasUncontended = true; + } + boolean collide = false; // True if last slot nonempty + for (;;) { + Cell[] as; Cell a; int n; long v; + if ((as = cells) != null && (n = as.length) > 0) { + if ((a = as[(n - 1) & h]) == null) { + if (cellsBusy == 0) { // Try to attach new Cell + Cell r = new Cell(x); // Optimistically create + if (cellsBusy == 0 && casCellsBusy()) { + boolean created = false; + try { // Recheck under lock + Cell[] rs; int m, j; + if ((rs = cells) != null && + (m = rs.length) > 0 && + rs[j = (m - 1) & h] == null) { + rs[j] = r; + created = true; + } + } finally { + cellsBusy = 0; + } + if (created) + break; + continue; // Slot is now non-empty + } + } + collide = false; + } + else if (!wasUncontended) // CAS already known to fail + wasUncontended = true; // Continue after rehash + else if (a.cas(v = a.value, ((fn == null) ? v + x : + fn.applyAsLong(v, x)))) + break; + else if (n >= NCPU || cells != as) + collide = false; // At max size or stale + else if (!collide) + collide = true; + else if (cellsBusy == 0 && casCellsBusy()) { + try { + if (cells == as) { // Expand table unless stale + Cell[] rs = new Cell[n << 1]; + for (int i = 0; i < n; ++i) + rs[i] = as[i]; + cells = rs; + } + } finally { + cellsBusy = 0; + } + collide = false; + continue; // Retry with expanded table + } + h = advanceProbe(h); + } + else if (cellsBusy == 0 && cells == as && casCellsBusy()) { + boolean init = false; + try { // Initialize table + if (cells == as) { + Cell[] rs = new Cell[2]; + rs[h & 1] = new Cell(x); + cells = rs; + init = true; + } + } finally { + cellsBusy = 0; + } + if (init) + break; + } + else if (casBase(v = base, ((fn == null) ? v + x : + fn.applyAsLong(v, x)))) + break; // Fall back on using base + } + } + + /** + * Same as longAccumulate, but injecting long/double conversions + * in too many places to sensibly merge with long version, given + * the low-overhead requirements of this class. So must instead be + * maintained by copy/paste/adapt. + */ + final void doubleAccumulate(double x, DoubleBinaryOperator fn, + boolean wasUncontended) { + int h; + if ((h = getProbe()) == 0) { + ThreadLocalRandom.current(); // force initialization + h = getProbe(); + wasUncontended = true; + } + boolean collide = false; // True if last slot nonempty + for (;;) { + Cell[] as; Cell a; int n; long v; + if ((as = cells) != null && (n = as.length) > 0) { + if ((a = as[(n - 1) & h]) == null) { + if (cellsBusy == 0) { // Try to attach new Cell + Cell r = new Cell(Double.doubleToRawLongBits(x)); + if (cellsBusy == 0 && casCellsBusy()) { + boolean created = false; + try { // Recheck under lock + Cell[] rs; int m, j; + if ((rs = cells) != null && + (m = rs.length) > 0 && + rs[j = (m - 1) & h] == null) { + rs[j] = r; + created = true; + } + } finally { + cellsBusy = 0; + } + if (created) + break; + continue; // Slot is now non-empty + } + } + collide = false; + } + else if (!wasUncontended) // CAS already known to fail + wasUncontended = true; // Continue after rehash + else if (a.cas(v = a.value, + ((fn == null) ? + Double.doubleToRawLongBits + (Double.longBitsToDouble(v) + x) : + Double.doubleToRawLongBits + (fn.applyAsDouble + (Double.longBitsToDouble(v), x))))) + break; + else if (n >= NCPU || cells != as) + collide = false; // At max size or stale + else if (!collide) + collide = true; + else if (cellsBusy == 0 && casCellsBusy()) { + try { + if (cells == as) { // Expand table unless stale + Cell[] rs = new Cell[n << 1]; + for (int i = 0; i < n; ++i) + rs[i] = as[i]; + cells = rs; + } + } finally { + cellsBusy = 0; + } + collide = false; + continue; // Retry with expanded table + } + h = advanceProbe(h); + } + else if (cellsBusy == 0 && cells == as && casCellsBusy()) { + boolean init = false; + try { // Initialize table + if (cells == as) { + Cell[] rs = new Cell[2]; + rs[h & 1] = new Cell(Double.doubleToRawLongBits(x)); + cells = rs; + init = true; + } + } finally { + cellsBusy = 0; + } + if (init) + break; + } + else if (casBase(v = base, + ((fn == null) ? + Double.doubleToRawLongBits + (Double.longBitsToDouble(v) + x) : + Double.doubleToRawLongBits + (fn.applyAsDouble + (Double.longBitsToDouble(v), x))))) + break; // Fall back on using base + } + } + + +} diff --git a/classpath/sun/misc/Ref.java b/classpath/sun/misc/Ref.java new file mode 100644 index 0000000..c45e5aa --- /dev/null +++ b/classpath/sun/misc/Ref.java @@ -0,0 +1,66 @@ +/* + Copyright (C) 2002 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package sun.misc; + +import cli.System.WeakReference; + +public abstract class Ref +{ + private WeakReference weakRef = new WeakReference(null); + + public Object get() + { + Object p = weakRef.get_Target(); + if(p == null) + { + synchronized(this) + { + if((p = weakRef.get_Target()) == null) + { + p = reconstitute(); + weakRef.set_Target(p); + } + } + } + return p; + } + + public abstract Object reconstitute(); + + public void flush() + { + weakRef.set_Target(null); + } + + public void setThing(Object thing) + { + weakRef.set_Target(thing); + } + + public Object check() + { + return weakRef.get_Target(); + } +} diff --git a/ikvm.build b/ikvm.build new file mode 100644 index 0000000..4b193c6 --- /dev/null +++ b/ikvm.build @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ikvm.include b/ikvm.include new file mode 100644 index 0000000..727860a --- /dev/null +++ b/ikvm.include @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ikvm/AssemblyInfo.cs b/ikvm/AssemblyInfo.cs new file mode 100644 index 0000000..e67dc47 --- /dev/null +++ b/ikvm/AssemblyInfo.cs @@ -0,0 +1,33 @@ +/* + Copyright (C) 2002, 2003, 2004, 2005, 2006 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("IKVM.NET Launcher")] +[assembly: AssemblyDescription("")] diff --git a/ikvm/ikvm.8.csproj b/ikvm/ikvm.8.csproj new file mode 100644 index 0000000..720fc92 --- /dev/null +++ b/ikvm/ikvm.8.csproj @@ -0,0 +1,94 @@ + + + Local + 9.0.30729 + 2.0 + {4FBAFF23-1E48-4977-8C50-30F87E70A8B5} + Debug + AnyCPU + + + + + ikvm + + + JScript + Grid + IE50 + false + Exe + ikvm + OnBuildSuccess + + + + + + + 2.0 + + + bin\Debug\ + false + 285212672 + false + + + TRACE;DEBUG;WHIDBEY + + + true + 4096 + false + + + false + false + false + false + 4 + full + prompt + + + + False + ..\bin\IKVM.OpenJDK.Core.dll + + + False + ..\bin\IKVM.OpenJDK.Util.dll + + + System + + + IKVM.AWT.WinForms + {E00A0FA2-1FD7-4DD9-8C06-7202CE366102} + {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + {F5C7B588-0403-4AF2-A4DE-5697DE21BC2C} + IKVM.Runtime.8 + + + + + Code + + + Code + + + Code + + + + + + + + + + \ No newline at end of file diff --git a/ikvm/ikvm.build b/ikvm/ikvm.build new file mode 100644 index 0000000..ab0893f --- /dev/null +++ b/ikvm/ikvm.build @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/ikvm/starter.cs b/ikvm/starter.cs new file mode 100644 index 0000000..3275730 --- /dev/null +++ b/ikvm/starter.cs @@ -0,0 +1,438 @@ +/* + Copyright (C) 2002-2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using IKVM.Internal; +using ikvm.runtime; +using java.lang.reflect; + +public static class Starter +{ + private class Timer + { + private static Timer t; + private DateTime now = DateTime.Now; + + internal Timer() + { + t = this; + } + + ~Timer() + { + Console.WriteLine(DateTime.Now - now); + } + } + + private class SaveAssemblyShutdownHook : java.lang.Thread + { + private java.lang.Class clazz; + + internal SaveAssemblyShutdownHook(java.lang.Class clazz) + : base("SaveAssemblyShutdownHook") + { + this.clazz = clazz; + } + + public override void run() + { + System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.AboveNormal; + try + { + IKVM.Internal.Starter.SaveDebugImage(); + } + catch(Exception x) + { + Console.Error.WriteLine(x); + Console.Error.WriteLine(new System.Diagnostics.StackTrace(x, true)); + System.Diagnostics.Debug.Assert(false, x.ToString()); + } + } + } + + private class WaitShutdownHook : java.lang.Thread + { + internal WaitShutdownHook() + : base("WaitShutdownHook") + { + } + + public override void run() + { + Console.Error.WriteLine("IKVM runtime terminated. Waiting for Ctrl+C..."); + for(;;) + { + System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite); + } + } + } + + [STAThread] // NOTE this is here because otherwise SWT's RegisterDragDrop (a COM thing) doesn't work + [IKVM.Attributes.HideFromJava] + static int Main(string[] args) + { + Tracer.EnableTraceConsoleListener(); + Tracer.EnableTraceForDebug(); + System.Collections.Hashtable props = new System.Collections.Hashtable(); + string classpath = Environment.GetEnvironmentVariable("CLASSPATH"); + if(classpath == null || classpath == "") + { + classpath = "."; + } + props["java.class.path"] = classpath; + bool jar = false; + bool saveAssembly = false; + bool saveAssemblyX = false; + bool waitOnExit = false; + bool showVersion = false; + string mainClass = null; + int vmargsIndex = -1; + bool debug = false; + String debugArg = null; + bool noglobbing = false; + for(int i = 0; i < args.Length; i++) + { + String arg = args[i]; + if(arg[0] == '-') + { + if(arg == "-help" || arg == "-?") + { + PrintHelp(); + return 1; + } + else if(arg == "-X") + { + PrintXHelp(); + return 1; + } + else if(arg == "-Xsave") + { + saveAssembly = true; + IKVM.Internal.Starter.PrepareForSaveDebugImage(); + } + else if(arg == "-XXsave") + { + saveAssemblyX = true; + IKVM.Internal.Starter.PrepareForSaveDebugImage(); + } + else if(arg == "-Xtime") + { + new Timer(); + } + else if(arg == "-Xwait") + { + waitOnExit = true; + } + else if(arg == "-Xbreak") + { + System.Diagnostics.Debugger.Break(); + } + else if(arg == "-Xnoclassgc") + { + IKVM.Internal.Starter.ClassUnloading = false; + } + else if(arg == "-Xverify") + { + IKVM.Internal.Starter.RelaxedVerification = false; + } + else if(arg == "-jar") + { + jar = true; + } + else if(arg == "-version") + { + Console.WriteLine(Startup.getVersionAndCopyrightInfo()); + Console.WriteLine(); + Console.WriteLine("CLR version: {0} ({1} bit)", Environment.Version, IntPtr.Size * 8); + System.Type type = System.Type.GetType("Mono.Runtime"); + if(type != null) + { + Console.WriteLine("Mono version: {0}", type.InvokeMember("GetDisplayName", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.NonPublic, null, null, new object[0])); + } + foreach(Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) + { + Console.WriteLine("{0}: {1}", asm.GetName().Name, asm.GetName().Version); + } + string ver = java.lang.System.getProperty("openjdk.version"); + if(ver != null) + { + Console.WriteLine("OpenJDK version: {0}", ver); + } + return 0; + } + else if(arg == "-showversion") + { + showVersion = true; + } + else if(arg.StartsWith("-D")) + { + arg = arg.Substring(2); + string[] keyvalue = arg.Split('='); + string value; + if(keyvalue.Length == 2) // -Dabc=x + { + value = keyvalue[1]; + } + else if (keyvalue.Length == 1) // -Dabc + { + value = ""; + } + else // -Dabc=x=y + { + value = arg.Substring(keyvalue[0].Length + 1); + } + props[keyvalue[0]] = value; + } + else if(arg == "-ea" || arg == "-enableassertions") + { + IKVM.Runtime.Assertions.EnableAssertions(); + } + else if(arg == "-da" || arg == "-disableassertions") + { + IKVM.Runtime.Assertions.DisableAssertions(); + } + else if(arg == "-esa" || arg == "-enablesystemassertions") + { + IKVM.Runtime.Assertions.EnableSystemAssertions(); + } + else if(arg == "-dsa" || arg == "-disablesystemassertions") + { + IKVM.Runtime.Assertions.DisableSystemAssertions(); + } + else if(arg.StartsWith("-ea:") || arg.StartsWith("-enableassertions:")) + { + IKVM.Runtime.Assertions.EnableAssertions(arg.Substring(arg.IndexOf(':') + 1)); + } + else if(arg.StartsWith("-da:") || arg.StartsWith("-disableassertions:")) + { + IKVM.Runtime.Assertions.DisableAssertions(arg.Substring(arg.IndexOf(':') + 1)); + } + else if(arg == "-cp" || arg == "-classpath") + { + props["java.class.path"] = args[++i]; + } + else if(arg.StartsWith("-Xtrace:")) + { + Tracer.SetTraceLevel(arg.Substring(8)); + } + else if(arg.StartsWith("-Xmethodtrace:")) + { + Tracer.HandleMethodTrace(arg.Substring(14)); + } + else if(arg == "-Xdebug") + { + debug = true; + } + else if (arg == "-Xnoagent") + { + //ignore it, disable support for oldjdb + } + else if (arg.StartsWith("-Xrunjdwp") || arg.StartsWith("-agentlib:jdwp")) + { + debugArg = arg; + debug = true; + } + else if (arg.StartsWith("-Xreference:")) + { + Startup.addBootClassPathAssembly(Assembly.LoadFrom(arg.Substring(12))); + } + else if (arg == "-Xnoglobbing") + { + noglobbing = true; + } + else if (arg == "-XX:+AllowNonVirtualCalls") + { + IKVM.Internal.Starter.AllowNonVirtualCalls = true; + } + else if (arg.StartsWith("-Xms") + || arg.StartsWith("-Xmx") + || arg.StartsWith("-Xmn") + || arg.StartsWith("-Xss") + || arg.StartsWith("-XX:") + || arg == "-Xmixed" + || arg == "-Xint" + || arg == "-Xincgc" + || arg == "-Xbatch" + || arg == "-Xfuture" + || arg == "-Xrs" + || arg == "-Xcheck:jni" + || arg == "-Xshare:off" + || arg == "-Xshare:auto" + || arg == "-Xshare:on" + ) + { + Console.Error.WriteLine("Unsupported option ignored: {0}", arg); + } + else + { + Console.Error.WriteLine("{0}: illegal argument", arg); + break; + } + } + else + { + mainClass = arg; + vmargsIndex = i + 1; + break; + } + } + if(mainClass == null || showVersion) + { + Console.Error.WriteLine(Startup.getVersionAndCopyrightInfo()); + Console.Error.WriteLine(); + } + if(mainClass == null) + { + PrintHelp(); + return 1; + } + try + { + if (debug) + { + // Starting the debugger + Assembly asm = Assembly.GetExecutingAssembly(); + String arguments = debugArg + " -pid:" + System.Diagnostics.Process.GetCurrentProcess().Id; + String program = new FileInfo(asm.Location).DirectoryName + "\\debugger.exe"; + try + { + ProcessStartInfo info = new ProcessStartInfo(program, arguments); + info.UseShellExecute = false; + Process debugger = new Process(); + debugger.StartInfo = info; + debugger.Start(); + } + catch (Exception ex) + { + Console.Error.WriteLine(program + " " + arguments); + throw ex; + } + } + if(jar) + { + props["java.class.path"] = mainClass; + } + // like the JDK we don't quote the args (even if they contain spaces) + props["sun.java.command"] = String.Join(" ", args, vmargsIndex - 1, args.Length - (vmargsIndex - 1)); + props["sun.java.launcher"] = "SUN_STANDARD"; + Startup.setProperties(props); + Startup.enterMainThread(); + string[] vmargs; + if (noglobbing) + { + vmargs = new string[args.Length - vmargsIndex]; + System.Array.Copy(args, vmargsIndex, vmargs, 0, vmargs.Length); + } + else + { + // Startup.glob() uses Java code, so we need to do this after we've initialized + vmargs = Startup.glob(args, vmargsIndex); + } + try + { + java.lang.Class clazz = sun.launcher.LauncherHelper.checkAndLoadMain(true, jar ? 2 : 1, mainClass); + // we don't need to do any checking on the main method, as that was already done by checkAndLoadMain + Method method = clazz.getMethod("main", typeof(string[])); + // if clazz isn't public, we can still call main + method.setAccessible(true); + if(saveAssembly) + { + java.lang.Runtime.getRuntime().addShutdownHook(new SaveAssemblyShutdownHook(clazz)); + } + if(waitOnExit) + { + java.lang.Runtime.getRuntime().addShutdownHook(new WaitShutdownHook()); + } + try + { + method.invoke(null, new object[] { vmargs }); + return 0; + } + catch(InvocationTargetException x) + { + throw x.getCause(); + } + } + finally + { + if(saveAssemblyX) + { + IKVM.Internal.Starter.SaveDebugImage(); + } + } + } + catch(System.Exception x) + { + java.lang.Thread thread = java.lang.Thread.currentThread(); + thread.getThreadGroup().uncaughtException(thread, ikvm.runtime.Util.mapException(x)); + } + finally + { + Startup.exitMainThread(); + } + return 1; + } + + private static void PrintHelp() + { + Console.Error.WriteLine("usage: ikvm [-options] [args...]"); + Console.Error.WriteLine(" (to execute a class)"); + Console.Error.WriteLine(" or ikvm -jar [-options] [args...]"); + Console.Error.WriteLine(" (to execute a jar file)"); + Console.Error.WriteLine(); + Console.Error.WriteLine("where options include:"); + Console.Error.WriteLine(" -? -help Display this message"); + Console.Error.WriteLine(" -X Display non-standard options"); + Console.Error.WriteLine(" -version Display IKVM and runtime version"); + Console.Error.WriteLine(" -showversion Display version and continue running"); + Console.Error.WriteLine(" -cp -classpath ", Path.PathSeparator); + Console.Error.WriteLine(" Set search path for application classes and resources"); + Console.Error.WriteLine(" -D= Set a system property"); + Console.Error.WriteLine(" -ea[:...|:]"); + Console.Error.WriteLine(" -enableassertions[:...|:]"); + Console.Error.WriteLine(" Enable assertions."); + Console.Error.WriteLine(" -da[:...|:]"); + Console.Error.WriteLine(" -disableassertions[:...|:]"); + Console.Error.WriteLine(" Disable assertions"); + } + + private static void PrintXHelp() + { + Console.Error.WriteLine(" -Xsave Save the generated assembly (for troubleshooting)"); + Console.Error.WriteLine(" -Xtime Time the execution"); + Console.Error.WriteLine(" -Xtrace: Displays all tracepoints with the given name"); + Console.Error.WriteLine(" -Xmethodtrace:"); + Console.Error.WriteLine(" Builds method trace into the specified output methods"); + Console.Error.WriteLine(" -Xwait Keep process hanging around after exit"); + Console.Error.WriteLine(" -Xbreak Trigger a user defined breakpoint at startup"); + Console.Error.WriteLine(" -Xnoclassgc Disable class garbage collection"); + Console.Error.WriteLine(" -Xnoglobbing Disable argument globbing"); + Console.Error.WriteLine(" -Xverify Enable strict class file verification"); + Console.Error.WriteLine(); + Console.Error.WriteLine("The -X options are non-standard and subject to change without notice."); + Console.Error.WriteLine(); + } +} diff --git a/ikvm9.sln b/ikvm9.sln new file mode 100644 index 0000000..c87909f --- /dev/null +++ b/ikvm9.sln @@ -0,0 +1,77 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IKVM.Runtime.8", "runtime\IKVM.Runtime.8.csproj", "{F5C7B588-0403-4AF2-A4DE-5697DE21BC2C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ikvm.8", "ikvm\ikvm.8.csproj", "{4FBAFF23-1E48-4977-8C50-30F87E70A8B5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ikvmstub.8", "ikvmstub\ikvmstub.8.csproj", "{D2A9434D-59E4-43E9-8D9C-332AA138CEAD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ikvmc.8", "ikvmc.8.csproj", "{4CA3F3DF-D2B7-4FA2-874C-BFC4B04286A2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IKVM.AWT.WinForms.8", "awt\IKVM.AWT.WinForms.8.csproj", "{E00A0FA2-1FD7-4DD9-8C06-7202CE366102}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ikvm-native", "native\native.9.vcproj", "{14EC8F2A-90C6-4CFC-AD26-04C9A3392B8E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IKVM.Runtime.JNI.8", "runtime\IKVM.Runtime.JNI.8.csproj", "{CEA4FEC4-1D24-4004-908E-F86C8D7AC772}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IKVM.Reflection", "reflect\IKVM.Reflection.csproj", "{4CB170EF-DFE6-4A56-9E1B-A85449E827A7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IKVM.MSBuild", "msbuild\IKVM.MSBuild.csproj", "{D7FF23BC-49C2-490D-B702-8EEE8F5AF296}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|Win32 = Debug|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F5C7B588-0403-4AF2-A4DE-5697DE21BC2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F5C7B588-0403-4AF2-A4DE-5697DE21BC2C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F5C7B588-0403-4AF2-A4DE-5697DE21BC2C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {F5C7B588-0403-4AF2-A4DE-5697DE21BC2C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {F5C7B588-0403-4AF2-A4DE-5697DE21BC2C}.Debug|Win32.ActiveCfg = Debug|Any CPU + {4FBAFF23-1E48-4977-8C50-30F87E70A8B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4FBAFF23-1E48-4977-8C50-30F87E70A8B5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4FBAFF23-1E48-4977-8C50-30F87E70A8B5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {4FBAFF23-1E48-4977-8C50-30F87E70A8B5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {4FBAFF23-1E48-4977-8C50-30F87E70A8B5}.Debug|Win32.ActiveCfg = Debug|Any CPU + {D2A9434D-59E4-43E9-8D9C-332AA138CEAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D2A9434D-59E4-43E9-8D9C-332AA138CEAD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D2A9434D-59E4-43E9-8D9C-332AA138CEAD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {D2A9434D-59E4-43E9-8D9C-332AA138CEAD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {D2A9434D-59E4-43E9-8D9C-332AA138CEAD}.Debug|Win32.ActiveCfg = Debug|Any CPU + {4CA3F3DF-D2B7-4FA2-874C-BFC4B04286A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4CA3F3DF-D2B7-4FA2-874C-BFC4B04286A2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4CA3F3DF-D2B7-4FA2-874C-BFC4B04286A2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {4CA3F3DF-D2B7-4FA2-874C-BFC4B04286A2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {4CA3F3DF-D2B7-4FA2-874C-BFC4B04286A2}.Debug|Win32.ActiveCfg = Debug|Any CPU + {E00A0FA2-1FD7-4DD9-8C06-7202CE366102}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E00A0FA2-1FD7-4DD9-8C06-7202CE366102}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E00A0FA2-1FD7-4DD9-8C06-7202CE366102}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {E00A0FA2-1FD7-4DD9-8C06-7202CE366102}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {E00A0FA2-1FD7-4DD9-8C06-7202CE366102}.Debug|Win32.ActiveCfg = Debug|Any CPU + {14EC8F2A-90C6-4CFC-AD26-04C9A3392B8E}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {14EC8F2A-90C6-4CFC-AD26-04C9A3392B8E}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {14EC8F2A-90C6-4CFC-AD26-04C9A3392B8E}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {14EC8F2A-90C6-4CFC-AD26-04C9A3392B8E}.Debug|Win32.ActiveCfg = Debug|Win32 + {14EC8F2A-90C6-4CFC-AD26-04C9A3392B8E}.Debug|Win32.Build.0 = Debug|Win32 + {CEA4FEC4-1D24-4004-908E-F86C8D7AC772}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CEA4FEC4-1D24-4004-908E-F86C8D7AC772}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CEA4FEC4-1D24-4004-908E-F86C8D7AC772}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {CEA4FEC4-1D24-4004-908E-F86C8D7AC772}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {CEA4FEC4-1D24-4004-908E-F86C8D7AC772}.Debug|Win32.ActiveCfg = Debug|Any CPU + {4CB170EF-DFE6-4A56-9E1B-A85449E827A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4CB170EF-DFE6-4A56-9E1B-A85449E827A7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4CB170EF-DFE6-4A56-9E1B-A85449E827A7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {4CB170EF-DFE6-4A56-9E1B-A85449E827A7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {4CB170EF-DFE6-4A56-9E1B-A85449E827A7}.Debug|Win32.ActiveCfg = Debug|Any CPU + {D7FF23BC-49C2-490D-B702-8EEE8F5AF296}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D7FF23BC-49C2-490D-B702-8EEE8F5AF296}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D7FF23BC-49C2-490D-B702-8EEE8F5AF296}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {D7FF23BC-49C2-490D-B702-8EEE8F5AF296}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {D7FF23BC-49C2-490D-B702-8EEE8F5AF296}.Debug|Win32.ActiveCfg = Debug|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ikvmc.8.csproj b/ikvmc.8.csproj new file mode 100644 index 0000000..188dba9 --- /dev/null +++ b/ikvmc.8.csproj @@ -0,0 +1,161 @@ + + + Local + 9.0.30729 + 2.0 + {4CA3F3DF-D2B7-4FA2-874C-BFC4B04286A2} + Debug + AnyCPU + + + + + ikvmc + + + JScript + Grid + IE50 + false + Exe + ikvmc + OnBuildSuccess + + + + + + + 2.0 + + + ikvmc\bin\Debug\ + false + 285212672 + false + + + TRACE;DEBUG;STATIC_COMPILER;EMITTERS + + + true + 4096 + false + + + false + false + false + false + 4 + full + prompt + + + + ICSharpCode.SharpZipLib + bin\ICSharpCode.SharpZipLib.dll + + + System + + + + System.XML + + + + + Code + + + Code + + + + Code + + + Code + + + + + Code + + + + + Code + + + Code + + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + + Code + + + + + Code + + + + + + Code + + + + Code + + + + + + + + Code + + + Code + + + Code + + + + + + {4CB170EF-DFE6-4A56-9E1B-A85449E827A7} + IKVM.Reflection + + + + + + + + + + \ No newline at end of file diff --git a/ikvmc/AotTypeWrapper.cs b/ikvmc/AotTypeWrapper.cs new file mode 100644 index 0000000..272a2d9 --- /dev/null +++ b/ikvmc/AotTypeWrapper.cs @@ -0,0 +1,1296 @@ +/* + Copyright (C) 2002-2015 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +using System; +using System.Collections.Generic; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; +using System.Diagnostics; +using System.Security; +using System.Security.Permissions; +using IKVM.Attributes; + +namespace IKVM.Internal +{ + sealed class AotTypeWrapper : DynamicTypeWrapper + { + private FieldInfo ghostRefField; + private MethodBuilder ghostIsInstanceMethod; + private MethodBuilder ghostIsInstanceArrayMethod; + private MethodBuilder ghostCastMethod; + private MethodBuilder ghostCastArrayMethod; + private TypeBuilder typeBuilderGhostInterface; + private Annotation annotation; + private Type enumType; + private MethodWrapper[] replacedMethods; + private WorkaroundBaseClass workaroundBaseClass; + + internal AotTypeWrapper(ClassFile f, CompilerClassLoader loader) + : base(null, f, loader, null) + { + } + + protected override Type GetBaseTypeForDefineType() + { + TypeWrapper baseTypeWrapper = BaseTypeWrapper; + if (this.IsPublic && this.IsAbstract && baseTypeWrapper.IsPublic && baseTypeWrapper.IsAbstract && classLoader.WorkaroundAbstractMethodWidening) + { + // FXBUG + // if the current class widens access on an abstract base class method, + // we need to inject an artificial base class to workaround a C# compiler bug + List methods = null; + foreach (MethodWrapper mw in GetMethods()) + { + if (!mw.IsStatic && mw.IsPublic) + { + MethodWrapper baseMethod = baseTypeWrapper.GetMethodWrapper(mw.Name, mw.Signature, true); + if (baseMethod != null && baseMethod.IsAbstract && baseMethod.IsProtected) + { + if (methods == null) + { + methods = new List(); + } + methods.Add(baseMethod); + } + } + } + if (methods != null) + { + string name = "__WorkaroundBaseClass__." + UnicodeUtil.EscapeInvalidSurrogates(Name); + while (!classLoader.ReserveName(name)) + { + name = "_" + name; + } + TypeWrapperFactory context = classLoader.GetTypeWrapperFactory(); + TypeBuilder typeBuilder = context.ModuleBuilder.DefineType(name, TypeAttributes.Public | TypeAttributes.Abstract, base.GetBaseTypeForDefineType()); + AttributeHelper.HideFromJava(typeBuilder); + AttributeHelper.SetEditorBrowsableNever(typeBuilder); + workaroundBaseClass = new WorkaroundBaseClass(this, typeBuilder, methods.ToArray()); + List constructors = new List(); + foreach (MethodWrapper mw in baseTypeWrapper.GetMethods()) + { + if (ReferenceEquals(mw.Name, StringConstants.INIT) && mw.IsAccessibleFrom(baseTypeWrapper, this, this)) + { + constructors.Add(new ConstructorForwarder(context, typeBuilder, mw)); + } + } + replacedMethods = constructors.ToArray(); + return typeBuilder; + } + } + return base.GetBaseTypeForDefineType(); + } + + internal override void Finish() + { + base.Finish(); + if (workaroundBaseClass != null) + { + workaroundBaseClass.Finish(); + } + } + + private sealed class WorkaroundBaseClass + { + private readonly AotTypeWrapper wrapper; + private readonly TypeBuilder typeBuilder; + private readonly MethodWrapper[] methods; + private MethodBuilder baseSerializationCtor; + + internal WorkaroundBaseClass(AotTypeWrapper wrapper, TypeBuilder typeBuilder, MethodWrapper[] methods) + { + this.wrapper = wrapper; + this.typeBuilder = typeBuilder; + this.methods = methods; + } + + internal MethodBuilder GetSerializationConstructor() + { + if (baseSerializationCtor == null) + { + baseSerializationCtor = Serialization.AddAutomagicSerializationToWorkaroundBaseClass(typeBuilder, wrapper.BaseTypeWrapper.GetSerializationConstructor()); + } + return baseSerializationCtor; + } + + internal void Finish() + { + if (!typeBuilder.IsCreated()) + { + foreach (MethodWrapper mw in methods) + { + MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(wrapper, typeBuilder, mw.Name, MethodAttributes.FamORAssem | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.CheckAccessOnOverride); + AttributeHelper.HideFromJava(mb); + CodeEmitter ilgen = CodeEmitter.Create(mb); + ilgen.EmitThrow("java.lang.AbstractMethodError"); + ilgen.DoEmit(); + } + typeBuilder.CreateType(); + } + } + } + + private sealed class ConstructorForwarder : MethodWrapper + { + private readonly TypeWrapperFactory context; + private readonly TypeBuilder typeBuilder; + private readonly MethodWrapper ctor; + private MethodBuilder constructorBuilder; + + internal ConstructorForwarder(TypeWrapperFactory context, TypeBuilder typeBuilder, MethodWrapper ctor) + : base(ctor.DeclaringType, ctor.Name, ctor.Signature, null, null, null, ctor.Modifiers, MemberFlags.None) + { + this.context = context; + this.typeBuilder = typeBuilder; + this.ctor = ctor; + } + + protected override void DoLinkMethod() + { + ctor.Link(); + DefineMethodHelper dmh = ctor.GetDefineMethodHelper(); + constructorBuilder = dmh.DefineConstructor(context, typeBuilder, MethodAttributes.PrivateScope); + AttributeHelper.HideFromJava(constructorBuilder); + CodeEmitter ilgen = CodeEmitter.Create(constructorBuilder); + ilgen.Emit(OpCodes.Ldarg_0); + for (int i = 1; i <= dmh.ParameterCount; i++) + { + ilgen.EmitLdarg(i); + } + ctor.EmitCall(ilgen); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + + internal override void EmitCall(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Call, constructorBuilder); + } + } + + internal override bool IsGhost + { + get + { + return classLoader.IsGhost(this); + } + } + + internal override bool IsMapUnsafeException + { + get + { + return classLoader.IsMapUnsafeException(this); + } + } + + internal override Type TypeAsBaseType + { + get + { + return typeBuilderGhostInterface != null ? typeBuilderGhostInterface : base.TypeAsBaseType; + } + } + + internal void GetParameterNamesFromXml(string methodName, string methodSig, string[] parameterNames) + { + IKVM.Internal.MapXml.Param[] parameters = classLoader.GetXmlMapParameters(Name, methodName, methodSig); + if(parameters != null) + { + for(int i = 0; i < parameters.Length; i++) + { + if(parameters[i].Name != null) + { + parameterNames[i] = parameters[i].Name; + } + } + } + } + + internal void AddXmlMapParameterAttributes(MethodBuilder method, string className, string methodName, string methodSig, ref ParameterBuilder[] pbs) + { + IKVM.Internal.MapXml.Param[] parameters = classLoader.GetXmlMapParameters(className, methodName, methodSig); + if(parameters != null) + { + if(pbs == null) + { + // let's hope that the parameters array is the right length + pbs = GetParameterBuilders(method, parameters.Length, null); + } + for(int i = 0; i < pbs.Length; i++) + { + if(parameters[i].Attributes != null) + { + foreach(IKVM.Internal.MapXml.Attribute attr in parameters[i].Attributes) + { + AttributeHelper.SetCustomAttribute(classLoader, pbs[i], attr); + } + } + } + } + } + + private void AddParameterMetadata(MethodBuilder method, MethodWrapper mw) + { + ParameterBuilder[] pbs; + if((mw.DeclaringType.IsPublic && (mw.IsPublic || mw.IsProtected)) || classLoader.EmitDebugInfo) + { + string[] parameterNames = new string[mw.GetParameters().Length]; + GetParameterNamesFromXml(mw.Name, mw.Signature, parameterNames); + GetParameterNamesFromSig(mw.Signature, parameterNames); + pbs = GetParameterBuilders(method, parameterNames.Length, parameterNames); + } + else + { + pbs = GetParameterBuilders(method, mw.GetParameters().Length, null); + } + if((mw.Modifiers & Modifiers.VarArgs) != 0 && pbs.Length > 0) + { + AttributeHelper.SetParamArrayAttribute(pbs[pbs.Length - 1]); + } + AddXmlMapParameterAttributes(method, Name, mw.Name, mw.Signature, ref pbs); + } + + protected override void AddMapXmlFields(ref FieldWrapper[] fields) + { + Dictionary mapxml = classLoader.GetMapXmlClasses(); + if(mapxml != null) + { + IKVM.Internal.MapXml.Class clazz; + if(mapxml.TryGetValue(this.Name, out clazz)) + { + if(clazz.Fields != null) + { + foreach(IKVM.Internal.MapXml.Field field in clazz.Fields) + { + // are we adding a new field? + bool found = false; + foreach(FieldWrapper fw in fields) + { + if(fw.Name == field.Name && fw.Signature == field.Sig) + { + found = true; + break; + } + } + if(!found) + { + fields = ArrayUtil.Concat(fields, FieldWrapper.Create(this, null, null, field.Name, field.Sig, new ExModifiers((Modifiers)field.Modifiers, false))); + } + } + } + } + } + } + + protected override bool EmitMapXmlMethodPrologueAndOrBody(CodeEmitter ilgen, ClassFile f, ClassFile.Method m) + { + IKVM.Internal.MapXml.InstructionList prologue = classLoader.GetMethodPrologue(new MethodKey(f.Name, m.Name, m.Signature)); + if(prologue != null) + { + prologue.Emit(classLoader, ilgen); + } + Dictionary mapxml = classLoader.GetMapXmlMethodBodies(); + if(mapxml != null) + { + IKVM.Internal.MapXml.InstructionList opcodes; + if(mapxml.TryGetValue(new MethodKey(f.Name, m.Name, m.Signature), out opcodes)) + { + opcodes.Emit(classLoader, ilgen); + return true; + } + } + return false; + } + + private void PublishAttributes(TypeBuilder typeBuilder, IKVM.Internal.MapXml.Class clazz) + { + foreach(IKVM.Internal.MapXml.Attribute attr in clazz.Attributes) + { + AttributeHelper.SetCustomAttribute(classLoader, typeBuilder, attr); + } + } + + private static bool CheckPropertyArgs(Type[] args1, Type[] args2) + { + if(args1.Length == args2.Length) + { + for(int i = 0; i < args1.Length; i++) + { + if(args1[i] != args2[i]) + { + return false; + } + } + return true; + } + return false; + } + + private static MethodAttributes GetPropertyMethodAttributes(MethodWrapper mw, bool final) + { + MethodAttributes attribs = MethodAttributes.HideBySig; + if(mw.IsStatic) + { + attribs |= MethodAttributes.Static; + } + else + { + // NOTE in order for IntelliSense to consider the property a "real" property, + // the getter and setter methods need to have substantially the same method attributes, + // so we may need to look at our peer to determine whether we should be final + // or not (and vice versa). + attribs |= MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.CheckAccessOnOverride; + if(final) + { + attribs |= MethodAttributes.Final; + } + } + // TODO what happens if accessibility doesn't match our peer? + if(mw.IsPublic) + { + attribs |= MethodAttributes.Public; + } + else if(mw.IsProtected) + { + attribs |= MethodAttributes.FamORAssem; + } + else if(mw.IsPrivate) + { + attribs |= MethodAttributes.Private; + } + else + { + attribs |= MethodAttributes.Assembly; + } + return attribs; + } + + private void PublishProperties(TypeBuilder typeBuilder, IKVM.Internal.MapXml.Class clazz) + { + foreach(IKVM.Internal.MapXml.Property prop in clazz.Properties) + { + TypeWrapper typeWrapper = GetClassLoader().RetTypeWrapperFromSig(prop.Sig, LoadMode.Link); + TypeWrapper[] propargs = GetClassLoader().ArgTypeWrapperListFromSig(prop.Sig, LoadMode.Link); + Type[] indexer = new Type[propargs.Length]; + for(int i = 0; i < propargs.Length; i++) + { + indexer[i] = propargs[i].TypeAsSignatureType; + } + PropertyBuilder propbuilder = typeBuilder.DefineProperty(prop.Name, PropertyAttributes.None, typeWrapper.TypeAsSignatureType, indexer); + AttributeHelper.HideFromJava(propbuilder); + if(prop.Attributes != null) + { + foreach(IKVM.Internal.MapXml.Attribute attr in prop.Attributes) + { + AttributeHelper.SetCustomAttribute(classLoader, propbuilder, attr); + } + } + MethodWrapper getter = null; + MethodWrapper setter = null; + if(prop.getter != null) + { + getter = GetMethodWrapper(prop.getter.Name, prop.getter.Sig, true); + if(getter == null) + { + Console.Error.WriteLine("Warning: getter not found for {0}::{1}", clazz.Name, prop.Name); + } + } + if(prop.setter != null) + { + setter = GetMethodWrapper(prop.setter.Name, prop.setter.Sig, true); + if(setter == null) + { + Console.Error.WriteLine("Warning: setter not found for {0}::{1}", clazz.Name, prop.Name); + } + } + bool final = (getter != null && getter.IsFinal) || (setter != null && setter.IsFinal); + if(getter != null) + { + MethodWrapper mw = getter; + if(!CheckPropertyArgs(mw.GetParametersForDefineMethod(), indexer) || mw.ReturnType != typeWrapper) + { + Console.Error.WriteLine("Warning: ignoring invalid property getter for {0}::{1}", clazz.Name, prop.Name); + } + else + { + MethodBuilder mb = mw.GetMethod() as MethodBuilder; + if(mb == null || mb.DeclaringType != typeBuilder || (!mb.IsFinal && final)) + { + mb = typeBuilder.DefineMethod("get_" + prop.Name, GetPropertyMethodAttributes(mw, final), typeWrapper.TypeAsSignatureType, indexer); + AttributeHelper.HideFromJava(mb); + CodeEmitter ilgen = CodeEmitter.Create(mb); + if(mw.IsStatic) + { + for(int i = 0; i < indexer.Length; i++) + { + ilgen.EmitLdarg(i); + } + mw.EmitCall(ilgen); + } + else + { + ilgen.Emit(OpCodes.Ldarg_0); + for(int i = 0; i < indexer.Length; i++) + { + ilgen.EmitLdarg(i + 1); + } + mw.EmitCallvirt(ilgen); + } + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + propbuilder.SetGetMethod(mb); + } + } + if(setter != null) + { + MethodWrapper mw = setter; + Type[] args = ArrayUtil.Concat(indexer, typeWrapper.TypeAsSignatureType); + if(!CheckPropertyArgs(args, mw.GetParametersForDefineMethod())) + { + Console.Error.WriteLine("Warning: ignoring invalid property setter for {0}::{1}", clazz.Name, prop.Name); + } + else + { + MethodBuilder mb = mw.GetMethod() as MethodBuilder; + if(mb == null || mb.DeclaringType != typeBuilder || (!mb.IsFinal && final)) + { + mb = typeBuilder.DefineMethod("set_" + prop.Name, GetPropertyMethodAttributes(mw, final), mw.ReturnTypeForDefineMethod, args); + AttributeHelper.HideFromJava(mb); + CodeEmitter ilgen = CodeEmitter.Create(mb); + if(mw.IsStatic) + { + for(int i = 0; i <= indexer.Length; i++) + { + ilgen.EmitLdarg(i); + } + mw.EmitCall(ilgen); + } + else + { + ilgen.Emit(OpCodes.Ldarg_0); + for(int i = 0; i <= indexer.Length; i++) + { + ilgen.EmitLdarg(i + 1); + } + mw.EmitCallvirt(ilgen); + } + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + propbuilder.SetSetMethod(mb); + } + } + } + } + + private static void MapModifiers(MapXml.MapModifiers mapmods, bool isConstructor, out bool setmodifiers, ref MethodAttributes attribs, bool isNewSlot) + { + setmodifiers = false; + Modifiers modifiers = (Modifiers)mapmods; + if((modifiers & Modifiers.Public) != 0) + { + attribs |= MethodAttributes.Public; + } + else if((modifiers & Modifiers.Protected) != 0) + { + attribs |= MethodAttributes.FamORAssem; + } + else if((modifiers & Modifiers.Private) != 0) + { + attribs |= MethodAttributes.Private; + } + else + { + attribs |= MethodAttributes.Assembly; + } + if((modifiers & Modifiers.Static) != 0) + { + attribs |= MethodAttributes.Static; + if((modifiers & Modifiers.Final) != 0) + { + setmodifiers = true; + } + } + else if(!isConstructor) + { + // NOTE we're abusing the MethodAttributes.NewSlot and Modifiers.Final combination to mean non-virtual + if((modifiers & Modifiers.Final) != 0 && (attribs & MethodAttributes.NewSlot) != 0 && (attribs & MethodAttributes.Virtual) == 0) + { + // remove NewSlot, because it doesn't make sense on a non-virtual method + attribs &= ~MethodAttributes.NewSlot; + } + else if(((modifiers & (Modifiers.Public | Modifiers.Final)) == Modifiers.Final && isNewSlot && (attribs & MethodAttributes.Virtual) == 0)) + { + // final method that doesn't need to be virtual + } + else + { + if((modifiers & Modifiers.Private) == 0) + { + attribs |= MethodAttributes.Virtual; + } + if((modifiers & Modifiers.Final) != 0) + { + attribs |= MethodAttributes.Final; + } + else if((modifiers & Modifiers.Abstract) != 0) + { + attribs |= MethodAttributes.Abstract; + } + } + } + if((modifiers & Modifiers.Synchronized) != 0) + { + throw new NotImplementedException(); + } + } + + private void MapSignature(string sig, out Type returnType, out Type[] parameterTypes) + { + returnType = GetClassLoader().RetTypeWrapperFromSig(sig, LoadMode.Link).TypeAsSignatureType; + TypeWrapper[] parameterTypeWrappers = GetClassLoader().ArgTypeWrapperListFromSig(sig, LoadMode.Link); + parameterTypes = new Type[parameterTypeWrappers.Length]; + for(int i = 0; i < parameterTypeWrappers.Length; i++) + { + parameterTypes[i] = parameterTypeWrappers[i].TypeAsSignatureType; + } + } + + protected override void EmitMapXmlMetadata(TypeBuilder typeBuilder, ClassFile classFile, FieldWrapper[] fields, MethodWrapper[] methods) + { + Dictionary mapxml = classLoader.GetMapXmlClasses(); + if(mapxml != null) + { + IKVM.Internal.MapXml.Class clazz; + if(mapxml.TryGetValue(classFile.Name, out clazz)) + { + if(clazz.Attributes != null) + { + PublishAttributes(typeBuilder, clazz); + } + if(clazz.Properties != null) + { + PublishProperties(typeBuilder, clazz); + } + if(clazz.Fields != null) + { + foreach(IKVM.Internal.MapXml.Field field in clazz.Fields) + { + if(field.Attributes != null) + { + foreach(FieldWrapper fw in fields) + { + if(fw.Name == field.Name && fw.Signature == field.Sig) + { + FieldBuilder fb = fw.GetField() as FieldBuilder; + if(fb != null) + { + foreach(IKVM.Internal.MapXml.Attribute attr in field.Attributes) + { + AttributeHelper.SetCustomAttribute(classLoader, fb, attr); + } + } + } + } + } + } + } + if(clazz.Constructors != null) + { + // HACK this isn't the right place to do this, but for now it suffices + foreach(IKVM.Internal.MapXml.Constructor constructor in clazz.Constructors) + { + // are we adding a new constructor? + if(GetMethodWrapper(StringConstants.INIT, constructor.Sig, false) == null) + { + if(constructor.body == null) + { + Console.Error.WriteLine("Error: Constructor {0}.{1} in xml remap file doesn't have a body.", clazz.Name, constructor.Sig); + continue; + } + bool setmodifiers = false; + MethodAttributes attribs = 0; + MapModifiers(constructor.Modifiers, true, out setmodifiers, ref attribs, false); + Type returnType; + Type[] parameterTypes; + MapSignature(constructor.Sig, out returnType, out parameterTypes); + MethodBuilder cb = ReflectUtil.DefineConstructor(typeBuilder, attribs, parameterTypes); + if(setmodifiers) + { + AttributeHelper.SetModifiers(cb, (Modifiers)constructor.Modifiers, false); + } + CompilerClassLoader.AddDeclaredExceptions(cb, constructor.throws); + CodeEmitter ilgen = CodeEmitter.Create(cb); + constructor.Emit(classLoader, ilgen); + ilgen.DoEmit(); + if(constructor.Attributes != null) + { + foreach(IKVM.Internal.MapXml.Attribute attr in constructor.Attributes) + { + AttributeHelper.SetCustomAttribute(classLoader, cb, attr); + } + } + } + } + foreach(IKVM.Internal.MapXml.Constructor constructor in clazz.Constructors) + { + if(constructor.Attributes != null) + { + foreach(MethodWrapper mw in methods) + { + if(mw.Name == "" && mw.Signature == constructor.Sig) + { + MethodBuilder mb = mw.GetMethod() as MethodBuilder; + if(mb != null) + { + foreach(IKVM.Internal.MapXml.Attribute attr in constructor.Attributes) + { + AttributeHelper.SetCustomAttribute(classLoader, mb, attr); + } + } + } + } + } + } + } + if(clazz.Methods != null) + { + // HACK this isn't the right place to do this, but for now it suffices + foreach(IKVM.Internal.MapXml.Method method in clazz.Methods) + { + // are we adding a new method? + if(GetMethodWrapper(method.Name, method.Sig, false) == null) + { + bool setmodifiers = false; + MethodAttributes attribs = method.MethodAttributes; + MapModifiers(method.Modifiers, false, out setmodifiers, ref attribs, BaseTypeWrapper == null || BaseTypeWrapper.GetMethodWrapper(method.Name, method.Sig, true) == null); + if(method.body == null && (attribs & MethodAttributes.Abstract) == 0) + { + Console.Error.WriteLine("Error: Method {0}.{1}{2} in xml remap file doesn't have a body.", clazz.Name, method.Name, method.Sig); + continue; + } + Type returnType; + Type[] parameterTypes; + MapSignature(method.Sig, out returnType, out parameterTypes); + MethodBuilder mb = typeBuilder.DefineMethod(method.Name, attribs, returnType, parameterTypes); + if(setmodifiers) + { + AttributeHelper.SetModifiers(mb, (Modifiers)method.Modifiers, false); + } + if(method.@override != null) + { + MethodWrapper mw = GetClassLoader().LoadClassByDottedName(method.@override.Class).GetMethodWrapper(method.@override.Name, method.Sig, true); + mw.Link(); + typeBuilder.DefineMethodOverride(mb, (MethodInfo)mw.GetMethod()); + } + CompilerClassLoader.AddDeclaredExceptions(mb, method.throws); + if(method.body != null) + { + CodeEmitter ilgen = CodeEmitter.Create(mb); + method.Emit(classLoader, ilgen); + ilgen.DoEmit(); + } + if(method.Attributes != null) + { + foreach(IKVM.Internal.MapXml.Attribute attr in method.Attributes) + { + AttributeHelper.SetCustomAttribute(classLoader, mb, attr); + } + } + } + } + foreach(IKVM.Internal.MapXml.Method method in clazz.Methods) + { + if(method.Attributes != null) + { + foreach(MethodWrapper mw in methods) + { + if(mw.Name == method.Name && mw.Signature == method.Sig) + { + MethodBuilder mb = mw.GetMethod() as MethodBuilder; + if(mb != null) + { + foreach(IKVM.Internal.MapXml.Attribute attr in method.Attributes) + { + AttributeHelper.SetCustomAttribute(classLoader, mb, attr); + } + } + } + } + } + } + } + if(clazz.Interfaces != null) + { + foreach(IKVM.Internal.MapXml.Interface iface in clazz.Interfaces) + { + TypeWrapper tw = GetClassLoader().LoadClassByDottedName(iface.Name); + // NOTE since this interface won't be part of the list in the ImplementAttribute, + // it won't be visible from Java that the type implements this interface. + typeBuilder.AddInterfaceImplementation(tw.TypeAsBaseType); + if(iface.Methods != null) + { + foreach(IKVM.Internal.MapXml.Method m in iface.Methods) + { + MethodWrapper mw = tw.GetMethodWrapper(m.Name, m.Sig, false); + if(mw == null) + { + throw new InvalidOperationException("Method " + m.Name + m.Sig + " not found in interface " + tw.Name); + } + mw.Link(); + MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(this, typeBuilder, tw.Name + "/" + m.Name, MethodAttributes.Private | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.CheckAccessOnOverride); + AttributeHelper.HideFromJava(mb); + typeBuilder.DefineMethodOverride(mb, (MethodInfo)mw.GetMethod()); + CodeEmitter ilgen = CodeEmitter.Create(mb); + m.Emit(classLoader, ilgen); + ilgen.DoEmit(); + } + } + } + } + } + } + } + + protected override MethodBuilder DefineGhostMethod(TypeBuilder typeBuilder, string name, MethodAttributes attribs, MethodWrapper mw) + { + if(typeBuilderGhostInterface != null && mw.IsVirtual) + { + DefineMethodHelper helper = mw.GetDefineMethodHelper(); + MethodBuilder stub = helper.DefineMethod(this, typeBuilder, name, MethodAttributes.Public); + ((GhostMethodWrapper)mw).SetGhostMethod(stub); + return helper.DefineMethod(this, typeBuilderGhostInterface, name, attribs); + } + return null; + } + + protected override void FinishGhost(TypeBuilder typeBuilder, MethodWrapper[] methods) + { + if(typeBuilderGhostInterface != null) + { + // TODO consider adding methods from base interface and java.lang.Object as well + for(int i = 0; i < methods.Length; i++) + { + // skip and non-virtual interface methods introduced in Java 8 + GhostMethodWrapper gmw = methods[i] as GhostMethodWrapper; + if(gmw != null) + { + TypeWrapper[] args = methods[i].GetParameters(); + MethodBuilder stub = gmw.GetGhostMethod(); + AddParameterMetadata(stub, methods[i]); + AttributeHelper.SetModifiers(stub, methods[i].Modifiers, methods[i].IsInternal); + CodeEmitter ilgen = CodeEmitter.Create(stub); + CodeEmitterLabel end = ilgen.DefineLabel(); + TypeWrapper[] implementers = classLoader.GetGhostImplementers(this); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ldfld, ghostRefField); + ilgen.Emit(OpCodes.Dup); + ilgen.Emit(OpCodes.Isinst, typeBuilderGhostInterface); + CodeEmitterLabel label = ilgen.DefineLabel(); + ilgen.EmitBrfalse(label); + ilgen.Emit(OpCodes.Castclass, typeBuilderGhostInterface); + for(int k = 0; k < args.Length; k++) + { + ilgen.EmitLdarg(k + 1); + } + ilgen.Emit(OpCodes.Callvirt, (MethodInfo)methods[i].GetMethod()); + ilgen.EmitBr(end); + ilgen.MarkLabel(label); + for(int j = 0; j < implementers.Length; j++) + { + ilgen.Emit(OpCodes.Dup); + ilgen.Emit(OpCodes.Isinst, implementers[j].TypeAsTBD); + label = ilgen.DefineLabel(); + ilgen.EmitBrfalse(label); + MethodWrapper mw = implementers[j].GetMethodWrapper(methods[i].Name, methods[i].Signature, true); + if(mw == null) + { + if(methods[i].IsAbstract) + { + // This should only happen for remapped types (defined in map.xml), because normally you'd get a miranda method. + throw new FatalCompilerErrorException(Message.GhostInterfaceMethodMissing, implementers[j].Name, Name, methods[i].Name, methods[i].Signature); + } + // We're inheriting a default method + ilgen.Emit(OpCodes.Pop); + ilgen.Emit(OpCodes.Ldarg_0); + for (int k = 0; k < args.Length; k++) + { + ilgen.EmitLdarg(k + 1); + } + ilgen.Emit(OpCodes.Call, DefaultInterfaceMethodWrapper.GetImpl(methods[i])); + } + else + { + ilgen.Emit(OpCodes.Castclass, implementers[j].TypeAsTBD); + for (int k = 0; k < args.Length; k++) + { + ilgen.EmitLdarg(k + 1); + } + mw.EmitCallvirt(ilgen); + } + ilgen.EmitBr(end); + ilgen.MarkLabel(label); + } + // we need to do a null check (null fails all the isinst checks) + ilgen.EmitNullCheck(); + ilgen.EmitThrow("java.lang.IncompatibleClassChangeError", Name); + ilgen.MarkLabel(end); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + } + // HACK create a scope to enable reuse of "implementers" name + if(true) + { + MethodBuilder mb; + CodeEmitter ilgen; + CodeEmitterLocal local; + // add implicit conversions for all the ghost implementers + TypeWrapper[] implementers = classLoader.GetGhostImplementers(this); + for(int i = 0; i < implementers.Length; i++) + { + mb = typeBuilder.DefineMethod("op_Implicit", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, TypeAsSignatureType, new Type[] { implementers[i].TypeAsSignatureType }); + AttributeHelper.HideFromJava(mb); + ilgen = CodeEmitter.Create(mb); + local = ilgen.DeclareLocal(TypeAsSignatureType); + ilgen.Emit(OpCodes.Ldloca, local); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Stfld, ghostRefField); + ilgen.Emit(OpCodes.Ldloca, local); + ilgen.Emit(OpCodes.Ldobj, TypeAsSignatureType); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + // Implement the "IsInstance" method + mb = ghostIsInstanceMethod; + AttributeHelper.HideFromJava(mb); + ilgen = CodeEmitter.Create(mb); + CodeEmitterLabel end = ilgen.DefineLabel(); + for(int i = 0; i < implementers.Length; i++) + { + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Isinst, implementers[i].TypeAsTBD); + CodeEmitterLabel label = ilgen.DefineLabel(); + ilgen.EmitBrfalse(label); + ilgen.Emit(OpCodes.Ldc_I4_1); + ilgen.EmitBr(end); + ilgen.MarkLabel(label); + } + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Isinst, typeBuilderGhostInterface); + ilgen.Emit(OpCodes.Ldnull); + ilgen.Emit(OpCodes.Cgt_Un); + ilgen.MarkLabel(end); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + // Implement the "IsInstanceArray" method + mb = ghostIsInstanceArrayMethod; + AttributeHelper.HideFromJava(mb); + ilgen = CodeEmitter.Create(mb); + CodeEmitterLocal localType = ilgen.DeclareLocal(Types.Type); + CodeEmitterLocal localRank = ilgen.DeclareLocal(Types.Int32); + ilgen.Emit(OpCodes.Ldarg_0); + CodeEmitterLabel skip = ilgen.DefineLabel(); + ilgen.EmitBrtrue(skip); + ilgen.Emit(OpCodes.Ldc_I4_0); + ilgen.Emit(OpCodes.Ret); + ilgen.MarkLabel(skip); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Call, Compiler.getTypeMethod); + ilgen.Emit(OpCodes.Stloc, localType); + ilgen.Emit(OpCodes.Ldarg_1); + ilgen.Emit(OpCodes.Stloc, localRank); + skip = ilgen.DefineLabel(); + ilgen.EmitBr(skip); + CodeEmitterLabel iter = ilgen.DefineLabel(); + ilgen.MarkLabel(iter); + ilgen.Emit(OpCodes.Ldloc, localType); + ilgen.Emit(OpCodes.Callvirt, Types.Type.GetMethod("GetElementType")); + ilgen.Emit(OpCodes.Stloc, localType); + ilgen.Emit(OpCodes.Ldloc, localRank); + ilgen.Emit(OpCodes.Ldc_I4_1); + ilgen.Emit(OpCodes.Sub); + ilgen.Emit(OpCodes.Stloc, localRank); + ilgen.Emit(OpCodes.Ldloc, localRank); + CodeEmitterLabel typecheck = ilgen.DefineLabel(); + ilgen.EmitBrfalse(typecheck); + ilgen.MarkLabel(skip); + ilgen.Emit(OpCodes.Ldloc, localType); + ilgen.Emit(OpCodes.Callvirt, Types.Type.GetMethod("get_IsArray")); + ilgen.EmitBrtrue(iter); + ilgen.Emit(OpCodes.Ldc_I4_0); + ilgen.Emit(OpCodes.Ret); + ilgen.MarkLabel(typecheck); + for(int i = 0; i < implementers.Length; i++) + { + ilgen.Emit(OpCodes.Ldtoken, implementers[i].TypeAsTBD); + ilgen.Emit(OpCodes.Call, Types.Type.GetMethod("GetTypeFromHandle")); + ilgen.Emit(OpCodes.Ldloc, localType); + ilgen.Emit(OpCodes.Callvirt, Types.Type.GetMethod("IsAssignableFrom")); + CodeEmitterLabel label = ilgen.DefineLabel(); + ilgen.EmitBrfalse(label); + ilgen.Emit(OpCodes.Ldc_I4_1); + ilgen.Emit(OpCodes.Ret); + ilgen.MarkLabel(label); + } + ilgen.Emit(OpCodes.Ldtoken, typeBuilderGhostInterface); + ilgen.Emit(OpCodes.Call, Types.Type.GetMethod("GetTypeFromHandle")); + ilgen.Emit(OpCodes.Ldloc, localType); + ilgen.Emit(OpCodes.Callvirt, Types.Type.GetMethod("IsAssignableFrom")); + skip = ilgen.DefineLabel(); + ilgen.EmitBrfalse(skip); + ilgen.Emit(OpCodes.Ldc_I4_1); + ilgen.Emit(OpCodes.Ret); + ilgen.MarkLabel(skip); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ldtoken, typeBuilder); + ilgen.Emit(OpCodes.Ldarg_1); + ilgen.Emit(OpCodes.Call, StaticCompiler.GetRuntimeType("IKVM.Runtime.GhostTag").GetMethod("IsGhostArrayInstance", BindingFlags.NonPublic | BindingFlags.Static)); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + + // Implement the "Cast" method + mb = ghostCastMethod; + AttributeHelper.HideFromJava(mb); + ilgen = CodeEmitter.Create(mb); + end = ilgen.DefineLabel(); + for(int i = 0; i < implementers.Length; i++) + { + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Isinst, implementers[i].TypeAsTBD); + ilgen.EmitBrtrue(end); + } + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Castclass, typeBuilderGhostInterface); + ilgen.Emit(OpCodes.Pop); + ilgen.MarkLabel(end); + local = ilgen.DeclareLocal(TypeAsSignatureType); + ilgen.Emit(OpCodes.Ldloca, local); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Stfld, ghostRefField); + ilgen.Emit(OpCodes.Ldloca, local); + ilgen.Emit(OpCodes.Ldobj, TypeAsSignatureType); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + // Add "ToObject" methods + mb = typeBuilder.DefineMethod("ToObject", MethodAttributes.HideBySig | MethodAttributes.Public, Types.Object, Type.EmptyTypes); + AttributeHelper.HideFromJava(mb); + ilgen = CodeEmitter.Create(mb); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ldfld, ghostRefField); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + + // Implement the "CastArray" method + // NOTE unlike "Cast" this doesn't return anything, it just throws a ClassCastException if the + // cast is unsuccessful. Also, because of the complexity of this test, we call IsInstanceArray + // instead of reimplementing the check here. + mb = ghostCastArrayMethod; + AttributeHelper.HideFromJava(mb); + ilgen = CodeEmitter.Create(mb); + end = ilgen.DefineLabel(); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.EmitBrfalse(end); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ldarg_1); + ilgen.Emit(OpCodes.Call, ghostIsInstanceArrayMethod); + ilgen.EmitBrtrue(end); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ldtoken, typeBuilder); + ilgen.Emit(OpCodes.Ldarg_1); + ilgen.Emit(OpCodes.Call, StaticCompiler.GetRuntimeType("IKVM.Runtime.GhostTag").GetMethod("ThrowClassCastException", BindingFlags.NonPublic | BindingFlags.Static)); + ilgen.MarkLabel(end); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + + // Implement the "Equals" method + mb = typeBuilder.DefineMethod("Equals", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual, Types.Boolean, new Type[] { Types.Object }); + AttributeHelper.HideFromJava(mb); + ilgen = CodeEmitter.Create(mb); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ldfld, ghostRefField); + ilgen.Emit(OpCodes.Ldarg_1); + ilgen.Emit(OpCodes.Ceq); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + + // Implement the "GetHashCode" method + mb = typeBuilder.DefineMethod("GetHashCode", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual, Types.Int32, Type.EmptyTypes); + AttributeHelper.HideFromJava(mb); + ilgen = CodeEmitter.Create(mb); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ldfld, ghostRefField); + ilgen.Emit(OpCodes.Callvirt, Types.Object.GetMethod("GetHashCode")); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + + // Implement the "op_Equality" method + mb = typeBuilder.DefineMethod("op_Equality", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, Types.Boolean, new Type[] { typeBuilder, typeBuilder }); + AttributeHelper.HideFromJava(mb); + ilgen = CodeEmitter.Create(mb); + ilgen.EmitLdarga(0); + ilgen.Emit(OpCodes.Ldfld, ghostRefField); + ilgen.EmitLdarga(1); + ilgen.Emit(OpCodes.Ldfld, ghostRefField); + ilgen.Emit(OpCodes.Ceq); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + + // Implement the "op_Inequality" method + mb = typeBuilder.DefineMethod("op_Inequality", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, Types.Boolean, new Type[] { typeBuilder, typeBuilder }); + AttributeHelper.HideFromJava(mb); + ilgen = CodeEmitter.Create(mb); + ilgen.EmitLdarga(0); + ilgen.Emit(OpCodes.Ldfld, ghostRefField); + ilgen.EmitLdarga(1); + ilgen.Emit(OpCodes.Ldfld, ghostRefField); + ilgen.Emit(OpCodes.Ceq); + ilgen.Emit(OpCodes.Ldc_I4_0); + ilgen.Emit(OpCodes.Ceq); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + } + } + + protected override void FinishGhostStep2() + { + if(typeBuilderGhostInterface != null) + { + typeBuilderGhostInterface.CreateType(); + } + } + + protected override TypeBuilder DefineGhostType(string mangledTypeName, TypeAttributes typeAttribs) + { + typeAttribs &= ~(TypeAttributes.Interface | TypeAttributes.Abstract); + typeAttribs |= TypeAttributes.Class | TypeAttributes.Sealed; + TypeBuilder typeBuilder = classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(mangledTypeName, typeAttribs, Types.ValueType); + AttributeHelper.SetGhostInterface(typeBuilder); + AttributeHelper.SetModifiers(typeBuilder, Modifiers, IsInternal); + ghostRefField = typeBuilder.DefineField("__", Types.Object, FieldAttributes.Public | FieldAttributes.SpecialName); + typeBuilderGhostInterface = typeBuilder.DefineNestedType("__Interface", TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.NestedPublic); + AttributeHelper.HideFromJava(typeBuilderGhostInterface); + ghostIsInstanceMethod = typeBuilder.DefineMethod("IsInstance", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static, Types.Boolean, new Type[] { Types.Object }); + ghostIsInstanceMethod.DefineParameter(1, ParameterAttributes.None, "obj"); + ghostIsInstanceArrayMethod = typeBuilder.DefineMethod("IsInstanceArray", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static, Types.Boolean, new Type[] { Types.Object, Types.Int32 }); + ghostIsInstanceArrayMethod.DefineParameter(1, ParameterAttributes.None, "obj"); + ghostIsInstanceArrayMethod.DefineParameter(2, ParameterAttributes.None, "rank"); + ghostCastMethod = typeBuilder.DefineMethod("Cast", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static, typeBuilder, new Type[] { Types.Object }); + ghostCastMethod.DefineParameter(1, ParameterAttributes.None, "obj"); + ghostCastArrayMethod = typeBuilder.DefineMethod("CastArray", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static, Types.Void, new Type[] { Types.Object, Types.Int32 }); + ghostCastArrayMethod.DefineParameter(1, ParameterAttributes.None, "obj"); + ghostCastArrayMethod.DefineParameter(2, ParameterAttributes.None, "rank"); + return typeBuilder; + } + + internal override FieldInfo GhostRefField + { + get + { + return ghostRefField; + } + } + + internal override void EmitCheckcast(CodeEmitter ilgen) + { + if(IsGhost) + { + ilgen.Emit(OpCodes.Dup); + ilgen.Emit(OpCodes.Call, ghostCastMethod); + ilgen.Emit(OpCodes.Pop); + } + else if(IsGhostArray) + { + ilgen.Emit(OpCodes.Dup); + TypeWrapper tw = this; + int rank = 0; + while(tw.IsArray) + { + rank++; + tw = tw.ElementTypeWrapper; + } + ilgen.EmitLdc_I4(rank); + ilgen.Emit(OpCodes.Call, ghostCastArrayMethod); + ilgen.Emit(OpCodes.Castclass, ArrayTypeWrapper.MakeArrayType(Types.Object, rank)); + } + else + { + base.EmitCheckcast(ilgen); + } + } + + internal override void EmitInstanceOf(CodeEmitter ilgen) + { + if(IsGhost) + { + ilgen.Emit(OpCodes.Call, ghostIsInstanceMethod); + } + else if(IsGhostArray) + { + ilgen.Emit(OpCodes.Call, ghostIsInstanceArrayMethod); + } + else + { + base.EmitInstanceOf(ilgen); + } + } + + internal void SetAnnotation(Annotation annotation) + { + this.annotation = annotation; + } + + internal override Annotation Annotation + { + get + { + return annotation; + } + } + + internal void SetEnumType(Type enumType) + { + this.enumType = enumType; + } + + internal override Type EnumType + { + get + { + return enumType; + } + } + + private sealed class ReplacedMethodWrapper : MethodWrapper + { + private IKVM.Internal.MapXml.InstructionList code; + + internal ReplacedMethodWrapper(TypeWrapper tw, string name, string sig, IKVM.Internal.MapXml.InstructionList code) + : base(tw, name, sig, null, null, null, Modifiers.Public, MemberFlags.None) + { + this.code = code; + } + + internal ReplacedMethodWrapper(ClassFile.ConstantPoolItemMI cpi, IKVM.Internal.MapXml.InstructionList code) + : base(cpi.GetClassType(), cpi.Name, cpi.Signature, null, cpi.GetRetType(), cpi.GetArgTypes(), Modifiers.Public, MemberFlags.None) + { + this.code = code; + } + + protected override void DoLinkMethod() + { + } + + private void DoEmit(CodeEmitter ilgen) + { + IKVM.Internal.MapXml.CodeGenContext context = new IKVM.Internal.MapXml.CodeGenContext(this.DeclaringType.GetClassLoader()); + // we don't want the line numbers from map.xml, so we have our own emit loop + for (int i = 0; i < code.invoke.Length; i++) + { + code.invoke[i].Generate(context, ilgen); + } + } + + internal override void EmitCall(CodeEmitter ilgen) + { + DoEmit(ilgen); + } + + internal override void EmitCallvirt(CodeEmitter ilgen) + { + DoEmit(ilgen); + } + + internal override void EmitNewobj(CodeEmitter ilgen) + { + DoEmit(ilgen); + } + } + + internal override MethodWrapper[] GetReplacedMethodsFor(MethodWrapper mw) + { + IKVM.Internal.MapXml.ReplaceMethodCall[] replacedMethods = ((CompilerClassLoader)GetClassLoader()).GetReplacedMethodsFor(mw); + MethodWrapper[] baseReplacedMethodWrappers = base.GetReplacedMethodsFor(mw); + if (replacedMethods != null || baseReplacedMethodWrappers != null || this.replacedMethods != null) + { + List list = new List(); + if (replacedMethods != null) + { + for (int i = 0; i < replacedMethods.Length; i++) + { + list.Add(new ReplacedMethodWrapper(GetClassLoader().LoadClassByDottedName(replacedMethods[i].Class), replacedMethods[i].Name, replacedMethods[i].Sig, replacedMethods[i].code)); + } + } + if (baseReplacedMethodWrappers != null) + { + list.AddRange(baseReplacedMethodWrappers); + } + if (this.replacedMethods != null) + { + list.AddRange(this.replacedMethods); + } + return list.ToArray(); + } + return null; + } + + internal override bool IsFastClassLiteralSafe + { + get { return true; } + } + + internal MethodWrapper ReplaceMethodWrapper(MethodWrapper mw) + { + if (replacedMethods != null) + { + foreach (MethodWrapper r in replacedMethods) + { + if (mw.DeclaringType == r.DeclaringType + && mw.Name == r.Name + && mw.Signature == r.Signature) + { + return r; + } + } + } + return mw; + } + + internal override MethodBase GetBaseSerializationConstructor() + { + if (workaroundBaseClass != null) + { + return workaroundBaseClass.GetSerializationConstructor(); + } + else + { + return base.GetBaseSerializationConstructor(); + } + } + } +} diff --git a/ikvmc/AssemblyInfo.cs b/ikvmc/AssemblyInfo.cs new file mode 100644 index 0000000..1cb1de4 --- /dev/null +++ b/ikvmc/AssemblyInfo.cs @@ -0,0 +1,32 @@ +/* + Copyright (C) 2002, 2003, 2004, 2005, 2006 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System.Reflection; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("IKVM.NET Compiler")] +[assembly: AssemblyDescription("")] diff --git a/ikvmc/AssemblyResolver.cs b/ikvmc/AssemblyResolver.cs new file mode 100644 index 0000000..3e90541 --- /dev/null +++ b/ikvmc/AssemblyResolver.cs @@ -0,0 +1,474 @@ +/* + Copyright (C) 2010-2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; +using IKVM.Reflection; + +namespace IKVM.Internal +{ + sealed class AssemblyResolver + { + private readonly List libpath = new List(); + private Universe universe; + private Version mscorlibVersion; + + internal enum WarningId + { + HigherVersion = 1, + LocationIgnored = 2, + InvalidLibDirectoryOption = 3, + InvalidLibDirectoryEnvironment = 4, + LegacySearchRule = 5, + } + + internal delegate void WarningEvent(WarningId warning, string message, string[] parameters); + internal event WarningEvent Warning; + + private void EmitWarning(WarningId warning, string message, params string[] parameters) + { + if (Warning != null) + { + Warning(warning, message, parameters); + } + else + { + Console.Error.WriteLine("Warning: " + message, parameters); + } + } + + internal void Init(Universe universe, bool nostdlib, IList references, IList userLibPaths) + { + this.universe = universe; + // like the C# compiler, the references are loaded from: + // current directory, CLR directory, -lib: option, %LIB% environment + // (note that, unlike the C# compiler, we don't add the CLR directory if -nostdlib has been specified) + libpath.Add(Environment.CurrentDirectory); + if (!nostdlib) + { + libpath.Add(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()); + } + foreach (string str in userLibPaths) + { + AddLibraryPaths(str, true); + } + AddLibraryPaths(Environment.GetEnvironmentVariable("LIB") ?? "", false); + if (nostdlib) + { + mscorlibVersion = LoadMscorlib(references).GetName().Version; + } + else + { + mscorlibVersion = universe.Load("mscorlib").GetName().Version; + } +#if STATIC_COMPILER + universe.AssemblyResolve += AssemblyResolve; +#else + universe.AssemblyResolve += LegacyAssemblyResolve; +#endif + } + + internal Assembly LoadFile(string path) + { + string ex = null; + try + { + using (RawModule module = universe.OpenRawModule(path)) + { + if (mscorlibVersion != null) + { + // to avoid problems (i.e. weird exceptions), we don't allow assemblies to load that reference a newer version of mscorlib + foreach (AssemblyName asmref in module.GetReferencedAssemblies()) + { + if (asmref.Name == "mscorlib" && asmref.Version > mscorlibVersion) + { + Console.Error.WriteLine("Error: unable to load assembly '{0}' as it depends on a higher version of mscorlib than the one currently loaded", path); + Environment.Exit(1); + } + } + } + Assembly asm = universe.LoadAssembly(module); + if (asm.Location != module.Location && CanonicalizePath(asm.Location) != CanonicalizePath(module.Location)) + { + EmitWarning(WarningId.LocationIgnored, "assembly \"{0}\" is ignored as previously loaded assembly \"{1}\" has the same identity \"{2}\"", path, asm.Location, asm.FullName); + } + return asm; + } + } + catch (IOException x) + { + ex = x.Message; + } + catch (UnauthorizedAccessException x) + { + ex = x.Message; + } + catch (IKVM.Reflection.BadImageFormatException x) + { + ex = x.Message; + } + Console.Error.WriteLine("Error: unable to load assembly '{0}'" + Environment.NewLine + " ({1})", path, ex); + Environment.Exit(1); + return null; + } + + private static string CanonicalizePath(string path) + { + try + { + System.IO.FileInfo fi = new System.IO.FileInfo(path); + if (fi.DirectoryName == null) + { + return path.Length > 1 && path[1] == ':' ? path.ToUpper() : path; + } + string dir = CanonicalizePath(fi.DirectoryName); + string name = fi.Name; + try + { + string[] arr = System.IO.Directory.GetFileSystemEntries(dir, name); + if (arr.Length == 1) + { + name = arr[0]; + } + } + catch (System.UnauthorizedAccessException) + { + } + catch (System.IO.IOException) + { + } + return System.IO.Path.Combine(dir, name); + } + catch (System.UnauthorizedAccessException) + { + } + catch (System.IO.IOException) + { + } + catch (System.Security.SecurityException) + { + } + catch (System.NotSupportedException) + { + } + return path; + } + + internal Assembly LoadWithPartialName(string name) + { + foreach (string path in FindAssemblyPath(name + ".dll")) + { + return LoadFile(path); + } + return null; + } + + internal bool ResolveReference(Dictionary cache, ref Assembly[] references, string reference) + { + string[] files = new string[0]; + try + { + string path = Path.GetDirectoryName(reference); + files = Directory.GetFiles(path == "" ? "." : path, Path.GetFileName(reference)); + } + catch (ArgumentException) + { + } + catch (IOException) + { + } + if (files.Length == 0) + { + Assembly asm = null; + cache.TryGetValue(reference, out asm); + if (asm == null) + { + foreach (string found in FindAssemblyPath(reference)) + { + asm = LoadFile(found); + cache.Add(reference, asm); + break; + } + } + if (asm == null) + { + return false; + } + ArrayAppend(ref references, asm); + } + else + { + foreach (string file in files) + { + Assembly asm; + if (!cache.TryGetValue(file, out asm)) + { + asm = LoadFile(file); + } + ArrayAppend(ref references, asm); + } + } + return true; + } + + private static void ArrayAppend(ref T[] array, T element) + { + if (array == null) + { + array = new T[] { element }; + } + else + { + array = ArrayUtil.Concat(array, element); + } + } + + private Assembly AssemblyResolve(object sender, IKVM.Reflection.ResolveEventArgs args) + { + AssemblyName name = new AssemblyName(args.Name); + AssemblyName previousMatch = null; + int previousMatchLevel = 0; + foreach (Assembly asm in universe.GetAssemblies()) + { + if (Match(asm.GetName(), name, ref previousMatch, ref previousMatchLevel)) + { + return asm; + } + } + if (previousMatch != null) + { + if (previousMatchLevel == 2) + { + EmitWarning(WarningId.HigherVersion, "assuming assembly reference \"{0}\" matches \"{1}\", you may need to supply runtime policy", previousMatch.FullName, name.FullName); + return universe.Load(previousMatch.FullName); + } + else if (args.RequestingAssembly != null) + { + Console.Error.WriteLine("Error: Assembly '{0}' uses '{1}' which has a higher version than referenced assembly '{2}'", args.RequestingAssembly.FullName, name.FullName, previousMatch.FullName); + Environment.Exit(1); + return null; + } + else + { + Console.Error.WriteLine("Error: Assembly '{0}' was requested which is a higher version than referenced assembly '{1}'", name.FullName, previousMatch.FullName); + Environment.Exit(1); + return null; + } + } + else if (args.RequestingAssembly != null) + { + return universe.CreateMissingAssembly(args.Name); + } + else + { + return null; + } + } + + private Assembly LegacyAssemblyResolve(object sender, IKVM.Reflection.ResolveEventArgs args) + { + return LegacyLoad(new AssemblyName(args.Name), args.RequestingAssembly); + } + + internal Assembly LegacyLoad(AssemblyName name, Assembly requestingAssembly) + { + AssemblyName previousMatch = null; + int previousMatchLevel = 0; + foreach (Assembly asm in universe.GetAssemblies()) + { + if (Match(asm.GetName(), name, ref previousMatch, ref previousMatchLevel)) + { + return asm; + } + } + foreach (string file in FindAssemblyPath(name.Name + ".dll")) + { + if (Match(AssemblyName.GetAssemblyName(file), name, ref previousMatch, ref previousMatchLevel)) + { + return LoadFile(file); + } + } + if (requestingAssembly != null) + { + string path = Path.Combine(Path.GetDirectoryName(requestingAssembly.Location), name.Name + ".dll"); + if (File.Exists(path) && Match(AssemblyName.GetAssemblyName(path), name, ref previousMatch, ref previousMatchLevel)) + { + return LoadFile(path); + } + } + if (previousMatch != null) + { + if (previousMatchLevel == 2) + { + EmitWarning(WarningId.HigherVersion, "assuming assembly reference \"{0}\" matches \"{1}\", you may need to supply runtime policy", previousMatch.FullName, name.FullName); + return LoadFile(new Uri(previousMatch.CodeBase).LocalPath); + } + else if (requestingAssembly != null) + { + Console.Error.WriteLine("Error: Assembly '{0}' uses '{1}' which has a higher version than referenced assembly '{2}'", requestingAssembly.FullName, name.FullName, previousMatch.FullName); + } + else + { + Console.Error.WriteLine("Error: Assembly '{0}' was requested which is a higher version than referenced assembly '{1}'", name.FullName, previousMatch.FullName); + } + } + else + { +#if STUB_GENERATOR + return universe.CreateMissingAssembly(name.FullName); +#else + Console.Error.WriteLine("Error: unable to find assembly '{0}'", name.FullName); + if (requestingAssembly != null) + { + Console.Error.WriteLine(" (a dependency of '{0}')", requestingAssembly.FullName); + } +#endif + } + Environment.Exit(1); + return null; + } + + private bool Match(AssemblyName assemblyDef, AssemblyName assemblyRef, ref AssemblyName bestMatch, ref int bestMatchLevel) + { + // Match levels: + // 0 = no match + // 1 = lower version match (i.e. not a suitable match, but used in error reporting: something was found but the version was too low) + // 2 = higher version potential match (i.e. we can use this version, but if it is available the exact match will be preferred) + // + // If we find a perfect match, bestMatch is not changed but we return true to signal that the search can end right now. + AssemblyComparisonResult result; + universe.CompareAssemblyIdentity(assemblyRef.FullName, false, assemblyDef.FullName, true, out result); + switch (result) + { + case AssemblyComparisonResult.EquivalentFullMatch: + case AssemblyComparisonResult.EquivalentPartialMatch: + case AssemblyComparisonResult.EquivalentFXUnified: + case AssemblyComparisonResult.EquivalentPartialFXUnified: + case AssemblyComparisonResult.EquivalentPartialWeakNamed: + case AssemblyComparisonResult.EquivalentWeakNamed: + return true; + case AssemblyComparisonResult.NonEquivalentPartialVersion: + case AssemblyComparisonResult.NonEquivalentVersion: + if (bestMatchLevel < 1) + { + bestMatchLevel = 1; + bestMatch = assemblyDef; + } + return false; + case AssemblyComparisonResult.EquivalentUnified: + case AssemblyComparisonResult.EquivalentPartialUnified: + if (bestMatchLevel < 2) + { + bestMatchLevel = 2; + bestMatch = assemblyDef; + } + return false; + case AssemblyComparisonResult.NonEquivalent: + case AssemblyComparisonResult.Unknown: + return false; + default: + throw new NotImplementedException(); + } + } + + private void AddLibraryPaths(string str, bool option) + { + foreach (string dir in str.Split(Path.PathSeparator)) + { + if (Directory.Exists(dir)) + { + libpath.Add(dir); + } + else if (dir != "") + { + if (option) + { + EmitWarning(WarningId.InvalidLibDirectoryOption, "directory \"{0}\" specified in -lib option is not valid", dir); + } + else + { + EmitWarning(WarningId.InvalidLibDirectoryEnvironment, "directory \"{0}\" specified in LIB environment is not valid", dir); + } + } + } + } + + private Assembly LoadMscorlib(IList references) + { + if (references != null) + { + foreach (string r in references) + { + try + { + if (AssemblyName.GetAssemblyName(r).Name == "mscorlib") + { + return LoadFile(r); + } + } + catch + { + } + } + } + foreach (string mscorlib in FindAssemblyPath("mscorlib.dll")) + { + return LoadFile(mscorlib); + } + Console.Error.WriteLine("Error: unable to find mscorlib.dll"); + Environment.Exit(1); + return null; + } + + private IEnumerable FindAssemblyPath(string file) + { + if (Path.IsPathRooted(file)) + { + if (File.Exists(file)) + { + yield return file; + } + } + else + { + foreach (string dir in libpath) + { + string path = Path.Combine(dir, file); + if (File.Exists(path)) + { + yield return path; + } + // for legacy compat, we try again after appending .dll + path = Path.Combine(dir, file + ".dll"); + if (File.Exists(path)) + { + EmitWarning(WarningId.LegacySearchRule, "found assembly \"{0}\" using legacy search rule, please append '.dll' to the reference", file); + yield return path; + } + } + } + } + } +} diff --git a/ikvmc/Compiler.cs b/ikvmc/Compiler.cs new file mode 100644 index 0000000..159052c --- /dev/null +++ b/ikvmc/Compiler.cs @@ -0,0 +1,1554 @@ +/* + Copyright (C) 2002-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; +using System.Threading; +using ICSharpCode.SharpZipLib.Zip; +using IKVM.Internal; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; + +sealed class FatalCompilerErrorException : Exception +{ + internal FatalCompilerErrorException(Message id, params object[] args) + : base(string.Format("fatal error IKVMC{0}: {1}", (int)id, args.Length == 0 ? GetMessage(id) : string.Format(GetMessage(id), args))) + { + } + + private static string GetMessage(Message id) + { + switch (id) + { + case IKVM.Internal.Message.ResponseFileDepthExceeded: + return "Response file nesting depth exceeded"; + case IKVM.Internal.Message.ErrorReadingFile: + return "Unable to read file: {0}\n\t({1})"; + case IKVM.Internal.Message.NoTargetsFound: + return "No targets found"; + case IKVM.Internal.Message.FileFormatLimitationExceeded: + return "File format limitation exceeded: {0}"; + case IKVM.Internal.Message.CannotSpecifyBothKeyFileAndContainer: + return "You cannot specify both a key file and container"; + case IKVM.Internal.Message.DelaySignRequiresKey: + return "You cannot delay sign without a key file or container"; + case IKVM.Internal.Message.InvalidStrongNameKeyPair: + return "Invalid key {0} specified.\n\t(\"{1}\")"; + case IKVM.Internal.Message.ReferenceNotFound: + return "Reference not found: {0}"; + case IKVM.Internal.Message.OptionsMustPreceedChildLevels: + return "You can only specify options before any child levels"; + case IKVM.Internal.Message.UnrecognizedTargetType: + return "Invalid value '{0}' for -target option"; + case IKVM.Internal.Message.UnrecognizedPlatform: + return "Invalid value '{0}' for -platform option"; + case IKVM.Internal.Message.UnrecognizedApartment: + return "Invalid value '{0}' for -apartment option"; + case IKVM.Internal.Message.MissingFileSpecification: + return "Missing file specification for '{0}' option"; + case IKVM.Internal.Message.PathTooLong: + return "Path too long: {0}"; + case IKVM.Internal.Message.PathNotFound: + return "Path not found: {0}"; + case IKVM.Internal.Message.InvalidPath: + return "Invalid path: {0}"; + case IKVM.Internal.Message.InvalidOptionSyntax: + return "Invalid option: {0}"; + case IKVM.Internal.Message.ExternalResourceNotFound: + return "External resource file does not exist: {0}"; + case IKVM.Internal.Message.ExternalResourceNameInvalid: + return "External resource file may not include path specification: {0}"; + case IKVM.Internal.Message.InvalidVersionFormat: + return "Invalid version specified: {0}"; + case IKVM.Internal.Message.InvalidFileAlignment: + return "Invalid value '{0}' for -filealign option"; + case IKVM.Internal.Message.ErrorWritingFile: + return "Unable to write file: {0}\n\t({1})"; + case IKVM.Internal.Message.UnrecognizedOption: + return "Unrecognized option: {0}"; + case IKVM.Internal.Message.NoOutputFileSpecified: + return "No output file specified"; + case IKVM.Internal.Message.SharedClassLoaderCannotBeUsedOnModuleTarget: + return "Incompatible options: -target:module and -sharedclassloader cannot be combined"; + case IKVM.Internal.Message.RuntimeNotFound: + return "Unable to load runtime assembly"; + case IKVM.Internal.Message.MainClassRequiresExe: + return "Main class cannot be specified for library or module"; + case IKVM.Internal.Message.ExeRequiresMainClass: + return "No main method found"; + case IKVM.Internal.Message.PropertiesRequireExe: + return "Properties cannot be specified for library or module"; + case IKVM.Internal.Message.ModuleCannotHaveClassLoader: + return "Cannot specify assembly class loader for modules"; + case IKVM.Internal.Message.ErrorParsingMapFile: + return "Unable to parse remap file: {0}\n\t({1})"; + case IKVM.Internal.Message.BootstrapClassesMissing: + return "Bootstrap classes missing and core assembly not found"; + case IKVM.Internal.Message.StrongNameRequiresStrongNamedRefs: + return "All referenced assemblies must be strong named, to be able to sign the output assembly"; + case IKVM.Internal.Message.MainClassNotFound: + return "Main class not found"; + case IKVM.Internal.Message.MainMethodNotFound: + return "Main method not found"; + case IKVM.Internal.Message.UnsupportedMainMethod: + return "Redirected main method not supported"; + case IKVM.Internal.Message.ExternalMainNotAccessible: + return "External main method must be public and in a public class"; + case IKVM.Internal.Message.ClassLoaderNotFound: + return "Custom assembly class loader class not found"; + case IKVM.Internal.Message.ClassLoaderNotAccessible: + return "Custom assembly class loader class is not accessible"; + case IKVM.Internal.Message.ClassLoaderIsAbstract: + return "Custom assembly class loader class is abstract"; + case IKVM.Internal.Message.ClassLoaderNotClassLoader: + return "Custom assembly class loader class does not extend java.lang.ClassLoader"; + case IKVM.Internal.Message.ClassLoaderConstructorMissing: + return "Custom assembly class loader constructor is missing"; + case IKVM.Internal.Message.MapFileTypeNotFound: + return "Type '{0}' referenced in remap file was not found"; + case IKVM.Internal.Message.MapFileClassNotFound: + return "Class '{0}' referenced in remap file was not found"; + case IKVM.Internal.Message.MaximumErrorCountReached: + return "Maximum error count reached"; + case IKVM.Internal.Message.LinkageError: + return "Link error: {0}"; + case IKVM.Internal.Message.RuntimeMismatch: + return "Referenced assembly {0} was compiled with an incompatible IKVM.Runtime version\n" + + "\tCurrent runtime: {1}\n" + + "\tReferenced assembly runtime: {2}"; + case IKVM.Internal.Message.CoreClassesMissing: + return "Failed to find core classes in core library"; + case IKVM.Internal.Message.CriticalClassNotFound: + return "Unable to load critical class '{0}'"; + case IKVM.Internal.Message.AssemblyContainsDuplicateClassNames: + return "Type '{0}' and '{1}' both map to the same name '{2}'\n" + + "\t({3})"; + case IKVM.Internal.Message.CallerIDRequiresHasCallerIDAnnotation: + return "CallerID.getCallerID() requires a HasCallerID annotation"; + case IKVM.Internal.Message.UnableToResolveInterface: + return "Unable to resolve interface '{0}' on type '{1}'"; + case IKVM.Internal.Message.MissingBaseType: + return "The base class or interface '{0}' in assembly '{1}' referenced by type '{2}' in '{3}' could not be resolved"; + case IKVM.Internal.Message.MissingBaseTypeReference: + return "The type '{0}' is defined in an assembly that is not referenced. You must add a reference to assembly '{1}'"; + case IKVM.Internal.Message.FileNotFound: + return "File not found: {0}"; + case IKVM.Internal.Message.RuntimeMethodMissing: + return "Runtime method '{0}' not found"; + case IKVM.Internal.Message.MapFileFieldNotFound: + return "Field '{0}' referenced in remap file was not found in class '{1}'"; + case IKVM.Internal.Message.GhostInterfaceMethodMissing: + return "Remapped class '{0}' does not implement ghost interface method\n" + + "\t({1}.{2}{3})"; + default: + return "Missing Error Message. Please file a bug."; + } + } +} + +sealed class IkvmcCompiler +{ + private bool nonleaf; + private string manifestMainClass; + private string defaultAssemblyName; + private static bool time; + private static string runtimeAssembly; + private static bool nostdlib; + private static bool emitSymbols; + private static readonly List libpaths = new List(); + internal static readonly AssemblyResolver resolver = new AssemblyResolver(); + + private static void AddArg(List arglist, string s, int depth) + { + if (s.StartsWith("@")) + { + if (depth++ > 16) + { + throw new FatalCompilerErrorException(Message.ResponseFileDepthExceeded); + } + try + { + using (StreamReader sr = new StreamReader(s.Substring(1))) + { + string line; + while ((line = sr.ReadLine()) != null) + { + string arg = line.Trim(); + if (arg != "" && !arg.StartsWith("#")) + { + AddArg(arglist, arg, depth); + } + } + } + } + catch (FatalCompilerErrorException) + { + throw; + } + catch (Exception x) + { + throw new FatalCompilerErrorException(Message.ErrorReadingFile, s.Substring(1), x.Message); + } + } + else + { + arglist.Add(s); + } + } + + private static List GetArgs(string[] args) + { + List arglist = new List(); + foreach(string s in args) + { + AddArg(arglist, s, 0); + } + return arglist; + } + + static int Main(string[] args) + { + DateTime start = DateTime.Now; + System.Threading.Thread.CurrentThread.Name = "compiler"; + Tracer.EnableTraceConsoleListener(); + Tracer.EnableTraceForDebug(); + try + { + try + { + return Compile(args); + } + catch (TypeInitializationException x) + { + if (x.InnerException is FatalCompilerErrorException) + { + throw x.InnerException; + } + throw; + } + } + catch (FatalCompilerErrorException x) + { + Console.Error.WriteLine(x.Message); + return 1; + } + catch (Exception x) + { + Console.Error.WriteLine(); + Console.Error.WriteLine("*** INTERNAL COMPILER ERROR ***"); + Console.Error.WriteLine(); + Console.Error.WriteLine("PLEASE FILE A BUG REPORT FOR IKVM.NET WHEN YOU SEE THIS MESSAGE"); + Console.Error.WriteLine(); + Console.Error.WriteLine(System.Reflection.Assembly.GetExecutingAssembly().FullName); + Console.Error.WriteLine(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()); + Console.Error.WriteLine("{0} {1}-bit", Environment.Version, IntPtr.Size * 8); + Console.Error.WriteLine(); + Console.Error.WriteLine(x); + return 2; + } + finally + { + if (time) + { + Console.WriteLine("Total cpu time: {0}", System.Diagnostics.Process.GetCurrentProcess().TotalProcessorTime); + Console.WriteLine("User cpu time: {0}", System.Diagnostics.Process.GetCurrentProcess().UserProcessorTime); + Console.WriteLine("Total wall clock time: {0}", DateTime.Now - start); + Console.WriteLine("Peak virtual memory: {0}", System.Diagnostics.Process.GetCurrentProcess().PeakVirtualMemorySize64); + for (int i = 0; i <= GC.MaxGeneration; i++) + { + Console.WriteLine("GC({0}) count: {1}", i, GC.CollectionCount(i)); + } + } + } + } + + static int Compile(string[] args) + { + List argList = GetArgs(args); + if (argList.Count == 0 || argList.Contains("-?") || argList.Contains("-help")) + { + PrintHelp(); + return 0; + } + if (!argList.Contains("-nologo")) + { + PrintHeader(); + } + IkvmcCompiler comp = new IkvmcCompiler(); + List targets = new List(); + CompilerOptions toplevel = new CompilerOptions(); + StaticCompiler.toplevel = toplevel; + comp.ParseCommandLine(argList.GetEnumerator(), targets, toplevel); + StaticCompiler.Init(emitSymbols); + resolver.Warning += loader_Warning; + resolver.Init(StaticCompiler.Universe, nostdlib, toplevel.unresolvedReferences, libpaths); + ResolveReferences(targets); + ResolveStrongNameKeys(targets); + if (targets.Count == 0) + { + throw new FatalCompilerErrorException(Message.NoTargetsFound); + } + if (StaticCompiler.errorCount != 0) + { + return 1; + } + try + { + return CompilerClassLoader.Compile(runtimeAssembly, targets); + } + catch (FileFormatLimitationExceededException x) + { + throw new FatalCompilerErrorException(Message.FileFormatLimitationExceeded, x.Message); + } + } + + static void loader_Warning(AssemblyResolver.WarningId warning, string message, string[] parameters) + { + switch (warning) + { + case AssemblyResolver.WarningId.HigherVersion: + StaticCompiler.IssueMessage(Message.AssumeAssemblyVersionMatch, parameters); + break; + case AssemblyResolver.WarningId.InvalidLibDirectoryOption: + StaticCompiler.IssueMessage(Message.InvalidDirectoryInLibOptionPath, parameters); + break; + case AssemblyResolver.WarningId.InvalidLibDirectoryEnvironment: + StaticCompiler.IssueMessage(Message.InvalidDirectoryInLibEnvironmentPath, parameters); + break; + case AssemblyResolver.WarningId.LegacySearchRule: + StaticCompiler.IssueMessage(Message.LegacySearchRule, parameters); + break; + case AssemblyResolver.WarningId.LocationIgnored: + StaticCompiler.IssueMessage(Message.AssemblyLocationIgnored, parameters); + break; + default: + StaticCompiler.IssueMessage(Message.UnknownWarning, string.Format(message, parameters)); + break; + } + } + + static void ResolveStrongNameKeys(List targets) + { + foreach (CompilerOptions options in targets) + { + if (options.keyfile != null && options.keycontainer != null) + { + throw new FatalCompilerErrorException(Message.CannotSpecifyBothKeyFileAndContainer); + } + if (options.keyfile == null && options.keycontainer == null && options.delaysign) + { + throw new FatalCompilerErrorException(Message.DelaySignRequiresKey); + } + if (options.keyfile != null) + { + if (options.delaysign) + { + byte[] buf = ReadAllBytes(options.keyfile); + try + { + // maybe it is a key pair, if so we need to extract just the public key + buf = new StrongNameKeyPair(buf).PublicKey; + } + catch { } + options.publicKey = buf; + } + else + { + SetStrongNameKeyPair(ref options.keyPair, options.keyfile, null); + } + } + else if (options.keycontainer != null) + { + StrongNameKeyPair keyPair = null; + SetStrongNameKeyPair(ref keyPair, null, options.keycontainer); + if (options.delaysign) + { + options.publicKey = keyPair.PublicKey; + } + else + { + options.keyPair = keyPair; + } + } + } + } + + internal static byte[] ReadAllBytes(FileInfo path) + { + try + { + return File.ReadAllBytes(path.FullName); + } + catch (Exception x) + { + throw new FatalCompilerErrorException(Message.ErrorReadingFile, path.ToString(), x.Message); + } + } + + static string GetVersionAndCopyrightInfo() + { + System.Reflection.Assembly asm = System.Reflection.Assembly.GetEntryAssembly(); + object[] desc = asm.GetCustomAttributes(typeof(System.Reflection.AssemblyTitleAttribute), false); + if (desc.Length == 1) + { + object[] copyright = asm.GetCustomAttributes(typeof(System.Reflection.AssemblyCopyrightAttribute), false); + if (copyright.Length == 1) + { + return string.Format("{0} version {1}{2}{3}{2}http://www.ikvm.net/", + ((System.Reflection.AssemblyTitleAttribute)desc[0]).Title, + asm.GetName().Version, + Environment.NewLine, + ((System.Reflection.AssemblyCopyrightAttribute)copyright[0]).Copyright); + } + } + return ""; + } + + private static void PrintHeader() + { + Console.Error.WriteLine(GetVersionAndCopyrightInfo()); + Console.Error.WriteLine(); + } + + private static void PrintHelp() + { + PrintHeader(); + Console.Error.WriteLine("Usage: ikvmc [-options] ... "); + Console.Error.WriteLine(); + Console.Error.WriteLine("Compiler Options:"); + Console.Error.WriteLine(); + Console.Error.WriteLine(" - OUTPUT FILES -"); + Console.Error.WriteLine("-out: Specify the output filename"); + Console.Error.WriteLine("-assembly: Specify assembly name"); + Console.Error.WriteLine("-version: Specify assembly version"); + Console.Error.WriteLine("-target:exe Build a console executable"); + Console.Error.WriteLine("-target:winexe Build a windows executable"); + Console.Error.WriteLine("-target:library Build a library"); + Console.Error.WriteLine("-target:module Build a module for use by the linker"); + Console.Error.WriteLine("-platform: Limit which platforms this code can run on:"); + Console.Error.WriteLine(" x86, x64, arm, anycpu32bitpreferred, or"); + Console.Error.WriteLine(" anycpu. The default is anycpu."); + Console.Error.WriteLine("-keyfile: Use keyfile to sign the assembly"); + Console.Error.WriteLine("-key: Use keycontainer to sign the assembly"); + Console.Error.WriteLine("-delaysign Delay-sign the assembly"); + Console.Error.WriteLine(); + Console.Error.WriteLine(" - INPUT FILES -"); + Console.Error.WriteLine("-reference: Reference an assembly (short form -r:)"); + Console.Error.WriteLine("-recurse: Recurse directory and include matching files"); + Console.Error.WriteLine("-exclude: A file containing a list of classes to exclude"); + Console.Error.WriteLine(); + Console.Error.WriteLine(" - RESOURCES -"); + Console.Error.WriteLine("-fileversion: File version"); + Console.Error.WriteLine("-win32icon: Embed specified icon in output"); + Console.Error.WriteLine("-win32manifest: Specify a Win32 manifest file (.xml)"); + Console.Error.WriteLine("-resource:= Include file as Java resource"); + Console.Error.WriteLine("-externalresource:="); + Console.Error.WriteLine(" Reference file as Java resource"); + Console.Error.WriteLine("-compressresources Compress resources"); + Console.Error.WriteLine(); + Console.Error.WriteLine(" - CODE GENERATION -"); + Console.Error.WriteLine("-debug Generate debug info for the output file"); + Console.Error.WriteLine(" (Note that this also causes the compiler to"); + Console.Error.WriteLine(" generated somewhat less efficient CIL code.)"); + Console.Error.WriteLine("-noautoserialization Disable automatic .NET serialization support"); + Console.Error.WriteLine("-noglobbing Don't glob the arguments passed to main"); + Console.Error.WriteLine("-nojni Do not generate JNI stub for native methods"); + Console.Error.WriteLine("-opt:fields Remove unused private fields"); + Console.Error.WriteLine("-removeassertions Remove all assert statements"); + Console.Error.WriteLine("-strictfinalfieldsemantics Don't allow final fields to be modified outside"); + Console.Error.WriteLine(" of initializer methods"); + Console.Error.WriteLine(); + Console.Error.WriteLine(" - ERRORS AND WARNINGS -"); + Console.Error.WriteLine("-nowarn: Suppress specified warnings"); + Console.Error.WriteLine("-warnaserror Treat all warnings as errors"); + Console.Error.WriteLine("-warnaserror: Treat specified warnings as errors"); + Console.Error.WriteLine("-writeSuppressWarningsFile:"); + Console.Error.WriteLine(" Write response file with -nowarn:"); + Console.Error.WriteLine(" options to suppress all encountered warnings"); + Console.Error.WriteLine(); + Console.Error.WriteLine(" - MISCELLANEOUS -"); + Console.Error.WriteLine("@ Read more options from file"); + Console.Error.WriteLine("-help Display this usage message (Short form: -?)"); + Console.Error.WriteLine("-nologo Suppress compiler copyright message"); + Console.Error.WriteLine(); + Console.Error.WriteLine(" - ADVANCED -"); + Console.Error.WriteLine("-main: Specify the class containing the main method"); + Console.Error.WriteLine("-srcpath: Prepend path and package name to source file"); + Console.Error.WriteLine("-apartment:sta (default) Apply STAThreadAttribute to main"); + Console.Error.WriteLine("-apartment:mta Apply MTAThreadAttribute to main"); + Console.Error.WriteLine("-apartment:none Don't apply STAThreadAttribute to main"); + Console.Error.WriteLine("-D= Set system property (at runtime)"); + Console.Error.WriteLine("-ea[:...|:]"); + Console.Error.WriteLine("-enableassertions[:...|:]"); + Console.Error.WriteLine(" Set system property to enable assertions"); + Console.Error.WriteLine("-da[:...|:]"); + Console.Error.WriteLine("-disableassertions[:...|:]"); + Console.Error.WriteLine(" Set system property to disable assertions"); + Console.Error.WriteLine("-nostacktraceinfo Don't create metadata to emit rich stack traces"); + Console.Error.WriteLine("-Xtrace: Displays all tracepoints with the given name"); + Console.Error.WriteLine("-Xmethodtrace: Build tracing into the specified output methods"); + Console.Error.WriteLine("-privatepackage: Mark all classes with a package name starting"); + Console.Error.WriteLine(" with as internal to the assembly"); + Console.Error.WriteLine("-time Display timing statistics"); + Console.Error.WriteLine("-classloader: Set custom class loader class for assembly"); + Console.Error.WriteLine("-sharedclassloader All targets below this level share a common"); + Console.Error.WriteLine(" class loader"); + Console.Error.WriteLine("-baseaddress:

Base address for the library to be built"); + Console.Error.WriteLine("-filealign: Specify the alignment used for output file"); + Console.Error.WriteLine("-nopeercrossreference Do not automatically cross reference all peers"); + Console.Error.WriteLine("-nostdlib Do not reference standard libraries"); + Console.Error.WriteLine("-lib: Additional directories to search for references"); + Console.Error.WriteLine("-highentropyva Enable high entropy ASLR"); + Console.Error.WriteLine("-static Disable dynamic binding"); + Console.Error.WriteLine("-assemblyattributes: Read assembly custom attributes from specified"); + Console.Error.WriteLine(" class file."); + } + + void ParseCommandLine(IEnumerator arglist, List targets, CompilerOptions options) + { + options.target = PEFileKinds.ConsoleApplication; + options.guessFileKind = true; + options.version = new Version(0, 0, 0, 0); + options.apartment = ApartmentState.STA; + options.props = new Dictionary(); + ContinueParseCommandLine(arglist, targets, options); + } + + void ContinueParseCommandLine(IEnumerator arglist, List targets, CompilerOptions options) + { + List fileNames = new List(); + while(arglist.MoveNext()) + { + string s = arglist.Current; + if(s == "{") + { + if (!nonleaf) + { + ReadFiles(options, fileNames); + nonleaf = true; + } + IkvmcCompiler nestedLevel = new IkvmcCompiler(); + nestedLevel.manifestMainClass = manifestMainClass; + nestedLevel.defaultAssemblyName = defaultAssemblyName; + nestedLevel.ContinueParseCommandLine(arglist, targets, options.Copy()); + } + else if(s == "}") + { + break; + } + else if(nonleaf) + { + throw new FatalCompilerErrorException(Message.OptionsMustPreceedChildLevels); + } + else if(s[0] == '-') + { + if(s.StartsWith("-out:")) + { + options.path = GetFileInfo(s.Substring(5)); + } + else if(s.StartsWith("-Xtrace:")) + { + Tracer.SetTraceLevel(s.Substring(8)); + } + else if(s.StartsWith("-Xmethodtrace:")) + { + Tracer.HandleMethodTrace(s.Substring(14)); + } + else if(s.StartsWith("-assembly:")) + { + options.assembly = s.Substring(10); + } + else if(s.StartsWith("-target:")) + { + switch(s) + { + case "-target:exe": + options.target = PEFileKinds.ConsoleApplication; + options.guessFileKind = false; + break; + case "-target:winexe": + options.target = PEFileKinds.WindowApplication; + options.guessFileKind = false; + break; + case "-target:module": + options.targetIsModule = true; + options.target = PEFileKinds.Dll; + options.guessFileKind = false; + break; + case "-target:library": + options.target = PEFileKinds.Dll; + options.guessFileKind = false; + break; + default: + throw new FatalCompilerErrorException(Message.UnrecognizedTargetType, s.Substring(8)); + } + } + else if(s.StartsWith("-platform:")) + { + switch(s) + { + case "-platform:x86": + options.pekind = PortableExecutableKinds.ILOnly | PortableExecutableKinds.Required32Bit; + options.imageFileMachine = ImageFileMachine.I386; + break; + case "-platform:x64": + options.pekind = PortableExecutableKinds.ILOnly | PortableExecutableKinds.PE32Plus; + options.imageFileMachine = ImageFileMachine.AMD64; + break; + case "-platform:arm": + options.pekind = PortableExecutableKinds.ILOnly; + options.imageFileMachine = ImageFileMachine.ARM; + break; + case "-platform:anycpu32bitpreferred": + options.pekind = PortableExecutableKinds.ILOnly | PortableExecutableKinds.Preferred32Bit; + options.imageFileMachine = ImageFileMachine.I386; + break; + case "-platform:anycpu": + options.pekind = PortableExecutableKinds.ILOnly; + options.imageFileMachine = ImageFileMachine.I386; + break; + default: + throw new FatalCompilerErrorException(Message.UnrecognizedPlatform, s.Substring(10)); + } + } + else if(s.StartsWith("-apartment:")) + { + switch(s) + { + case "-apartment:sta": + options.apartment = ApartmentState.STA; + break; + case "-apartment:mta": + options.apartment = ApartmentState.MTA; + break; + case "-apartment:none": + options.apartment = ApartmentState.Unknown; + break; + default: + throw new FatalCompilerErrorException(Message.UnrecognizedApartment, s.Substring(11)); + } + } + else if(s == "-noglobbing") + { + options.noglobbing = true; + } + else if(s.StartsWith("-D")) + { + string[] keyvalue = s.Substring(2).Split('='); + if(keyvalue.Length != 2) + { + keyvalue = new string[] { keyvalue[0], "" }; + } + options.props[keyvalue[0]] = keyvalue[1]; + } + else if(s == "-ea" || s == "-enableassertions") + { + options.props["ikvm.assert.default"] = "true"; + } + else if(s == "-da" || s == "-disableassertions") + { + options.props["ikvm.assert.default"] = "false"; + } + else if(s.StartsWith("-ea:") || s.StartsWith("-enableassertions:")) + { + options.props["ikvm.assert.enable"] = s.Substring(s.IndexOf(':') + 1); + } + else if(s.StartsWith("-da:") || s.StartsWith("-disableassertions:")) + { + options.props["ikvm.assert.disable"] = s.Substring(s.IndexOf(':') + 1); + } + else if(s == "-removeassertions") + { + options.codegenoptions |= CodeGenOptions.RemoveAsserts; + } + else if(s.StartsWith("-main:")) + { + options.mainClass = s.Substring(6); + } + else if(s.StartsWith("-reference:") || s.StartsWith("-r:")) + { + string r = s.Substring(s.IndexOf(':') + 1); + if(r == "") + { + throw new FatalCompilerErrorException(Message.MissingFileSpecification, s); + } + ArrayAppend(ref options.unresolvedReferences, r); + } + else if(s.StartsWith("-recurse:")) + { + string spec = s.Substring(9); + bool exists = false; + // MONOBUG On Mono 1.0.2, Directory.Exists throws an exception if we pass an invalid directory name + try + { + exists = Directory.Exists(spec); + } + catch(IOException) + { + } + bool found; + if(exists) + { + DirectoryInfo dir = new DirectoryInfo(spec); + found = Recurse(options, dir, dir, "*"); + } + else + { + try + { + DirectoryInfo dir = new DirectoryInfo(Path.GetDirectoryName(spec)); + if(dir.Exists) + { + found = Recurse(options, dir, dir, Path.GetFileName(spec)); + } + else + { + found = RecurseJar(options, spec); + } + } + catch(PathTooLongException) + { + throw new FatalCompilerErrorException(Message.PathTooLong, spec); + } + catch(DirectoryNotFoundException) + { + throw new FatalCompilerErrorException(Message.PathNotFound, spec); + } + catch(ArgumentException) + { + throw new FatalCompilerErrorException(Message.InvalidPath, spec); + } + } + if(!found) + { + throw new FatalCompilerErrorException(Message.FileNotFound, spec); + } + } + else if(s.StartsWith("-resource:")) + { + string[] spec = s.Substring(10).Split('='); + if(spec.Length != 2) + { + throw new FatalCompilerErrorException(Message.InvalidOptionSyntax, s); + } + FileInfo fileInfo = GetFileInfo(spec[1]); + options.GetResourcesJar().Add(spec[0].TrimStart('/'), ReadAllBytes(fileInfo), fileInfo); + } + else if(s.StartsWith("-externalresource:")) + { + string[] spec = s.Substring(18).Split('='); + if(spec.Length != 2) + { + throw new FatalCompilerErrorException(Message.InvalidOptionSyntax, s); + } + if(!File.Exists(spec[1])) + { + throw new FatalCompilerErrorException(Message.ExternalResourceNotFound, spec[1]); + } + if(Path.GetFileName(spec[1]) != spec[1]) + { + throw new FatalCompilerErrorException(Message.ExternalResourceNameInvalid, spec[1]); + } + if(options.externalResources == null) + { + options.externalResources = new Dictionary(); + } + // TODO resource name clashes should be tested + options.externalResources.Add(spec[0], spec[1]); + } + else if(s == "-nojni") + { + options.codegenoptions |= CodeGenOptions.NoJNI; + } + else if(s.StartsWith("-exclude:")) + { + ProcessExclusionFile(ref options.classesToExclude, s.Substring(9)); + } + else if(s.StartsWith("-version:")) + { + string str = s.Substring(9); + if(!TryParseVersion(s.Substring(9), out options.version)) + { + throw new FatalCompilerErrorException(Message.InvalidVersionFormat, str); + } + } + else if(s.StartsWith("-fileversion:")) + { + options.fileversion = s.Substring(13); + } + else if(s.StartsWith("-win32icon:")) + { + options.iconfile = GetFileInfo(s.Substring(11)); + } + else if(s.StartsWith("-win32manifest:")) + { + options.manifestFile = GetFileInfo(s.Substring(15)); + } + else if(s.StartsWith("-keyfile:")) + { + options.keyfile = GetFileInfo(s.Substring(9)); + } + else if(s.StartsWith("-key:")) + { + options.keycontainer = s.Substring(5); + } + else if(s == "-delaysign") + { + options.delaysign = true; + } + else if(s == "-debug") + { + emitSymbols = true; + options.codegenoptions |= CodeGenOptions.Debug; + } + else if(s.StartsWith("-srcpath:")) + { + options.sourcepath = s.Substring(9); + } + else if(s.StartsWith("-remap:")) + { + options.remapfile = GetFileInfo(s.Substring(7)); + } + else if(s == "-nostacktraceinfo") + { + options.codegenoptions |= CodeGenOptions.NoStackTraceInfo; + } + else if(s == "-opt:fields") + { + options.codegenoptions |= CodeGenOptions.RemoveUnusedFields; + } + else if(s == "-compressresources") + { + options.compressedResources = true; + } + else if(s == "-strictfinalfieldsemantics") + { + options.codegenoptions |= CodeGenOptions.StrictFinalFieldSemantics; + } + else if(s.StartsWith("-privatepackage:")) + { + string prefix = s.Substring(16); + ArrayAppend(ref options.privatePackages, prefix); + } + else if(s.StartsWith("-publicpackage:")) + { + string prefix = s.Substring(15); + ArrayAppend(ref options.publicPackages, prefix); + } + else if(s.StartsWith("-nowarn:")) + { + foreach(string w in s.Substring(8).Split(',')) + { + string ws = w; + // lame way to chop off the leading zeroes + while(ws.StartsWith("0")) + { + ws = ws.Substring(1); + } + options.suppressWarnings[ws] = ws; + } + } + else if(s == "-warnaserror") + { + options.warnaserror = true; + } + else if(s.StartsWith("-warnaserror:")) + { + foreach(string w in s.Substring(13).Split(',')) + { + string ws = w; + // lame way to chop off the leading zeroes + while(ws.StartsWith("0")) + { + ws = ws.Substring(1); + } + options.errorWarnings[ws] = ws; + } + } + else if(s.StartsWith("-runtime:")) + { + // NOTE this is an undocumented option + runtimeAssembly = s.Substring(9); + } + else if(s == "-time") + { + time = true; + } + else if(s.StartsWith("-classloader:")) + { + options.classLoader = s.Substring(13); + } + else if(s == "-sharedclassloader") + { + if(options.sharedclassloader == null) + { + options.sharedclassloader = new List(); + } + } + else if(s.StartsWith("-baseaddress:")) + { + string baseAddress = s.Substring(13); + ulong baseAddressParsed; + if (baseAddress.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) + { + baseAddressParsed = UInt64.Parse(baseAddress.Substring(2), System.Globalization.NumberStyles.AllowHexSpecifier); + } + else + { + // note that unlike CSC we don't support octal + baseAddressParsed = UInt64.Parse(baseAddress); + } + options.baseAddress = (long)(baseAddressParsed & 0xFFFFFFFFFFFF0000UL); + } + else if(s.StartsWith("-filealign:")) + { + int filealign; + if (!Int32.TryParse(s.Substring(11), out filealign) + || filealign < 512 + || filealign > 8192 + || (filealign & (filealign - 1)) != 0) + { + throw new FatalCompilerErrorException(Message.InvalidFileAlignment, s.Substring(11)); + } + options.fileAlignment = filealign; + } + else if(s == "-nopeercrossreference") + { + options.crossReferenceAllPeers = false; + } + else if(s=="-nostdlib") + { + // this is a global option + nostdlib = true; + } + else if(s.StartsWith("-lib:")) + { + // this is a global option + libpaths.Add(s.Substring(5)); + } + else if(s == "-noautoserialization") + { + options.codegenoptions |= CodeGenOptions.NoAutomagicSerialization; + } + else if(s == "-highentropyva") + { + options.highentropyva = true; + } + else if(s.StartsWith("-writeSuppressWarningsFile:")) + { + options.writeSuppressWarningsFile = GetFileInfo(s.Substring(27)); + try + { + options.writeSuppressWarningsFile.Delete(); + } + catch(Exception x) + { + throw new FatalCompilerErrorException(Message.ErrorWritingFile, options.writeSuppressWarningsFile, x.Message); + } + } + else if(s.StartsWith("-proxy:")) // currently undocumented! + { + string proxy = s.Substring(7); + if(options.proxies.Contains(proxy)) + { + StaticCompiler.IssueMessage(Message.DuplicateProxy, proxy); + } + options.proxies.Add(proxy); + } + else if(s == "-nologo") + { + // Ignore. This is handled earlier. + } + else if(s == "-XX:+AllowNonVirtualCalls") + { + JVM.AllowNonVirtualCalls = true; + } + else if(s == "-static") + { + // we abuse -static to also enable support for NoRefEmit scenarios + options.codegenoptions |= CodeGenOptions.DisableDynamicBinding | CodeGenOptions.NoRefEmitHelpers; + } + else if(s == "-nojarstubs") // undocumented temporary option to mitigate risk + { + options.nojarstubs = true; + } + else if(s.StartsWith("-assemblyattributes:", StringComparison.Ordinal)) + { + ProcessAttributeAnnotationsClass(ref options.assemblyAttributeAnnotations, s.Substring(20)); + } + else if(s == "-w4") // undocumented option to always warn if a class isn't found + { + options.warningLevelHigh = true; + } + else if(s == "-noparameterreflection") // undocumented option to compile core class libraries with, to disable MethodParameter attribute + { + options.noParameterReflection = true; + } + else + { + throw new FatalCompilerErrorException(Message.UnrecognizedOption, s); + } + } + else + { + fileNames.Add(s); + } + if(options.targetIsModule && options.sharedclassloader != null) + { + throw new FatalCompilerErrorException(Message.SharedClassLoaderCannotBeUsedOnModuleTarget); + } + } + if(nonleaf) + { + return; + } + ReadFiles(options, fileNames); + if(options.assembly == null) + { + string basename = options.path == null ? defaultAssemblyName : options.path.Name; + if(basename == null) + { + throw new FatalCompilerErrorException(Message.NoOutputFileSpecified); + } + int idx = basename.LastIndexOf('.'); + if(idx > 0) + { + options.assembly = basename.Substring(0, idx); + } + else + { + options.assembly = basename; + } + } + if(options.path != null && options.guessFileKind) + { + if(options.path.Extension.Equals(".dll", StringComparison.OrdinalIgnoreCase)) + { + options.target = PEFileKinds.Dll; + } + options.guessFileKind = false; + } + if(options.mainClass == null && manifestMainClass != null && (options.guessFileKind || options.target != PEFileKinds.Dll)) + { + StaticCompiler.IssueMessage(options, Message.MainMethodFromManifest, manifestMainClass); + options.mainClass = manifestMainClass; + } + targets.Add(options); + } + + internal static FileInfo GetFileInfo(string path) + { + try + { + FileInfo fileInfo = new FileInfo(path); + if (fileInfo.Directory == null) + { + // this happens with an incorrect unc path (e.g. "\\foo\bar") + throw new FatalCompilerErrorException(Message.InvalidPath, path); + } + return fileInfo; + } + catch (ArgumentException) + { + throw new FatalCompilerErrorException(Message.InvalidPath, path); + } + catch (NotSupportedException) + { + throw new FatalCompilerErrorException(Message.InvalidPath, path); + } + catch (PathTooLongException) + { + throw new FatalCompilerErrorException(Message.PathTooLong, path); + } + catch (UnauthorizedAccessException) + { + // this exception does not appear to be possible + throw new FatalCompilerErrorException(Message.InvalidPath, path); + } + } + + private void ReadFiles(CompilerOptions options, List fileNames) + { + foreach (string fileName in fileNames) + { + if (defaultAssemblyName == null) + { + try + { + defaultAssemblyName = new FileInfo(Path.GetFileName(fileName)).Name; + } + catch (ArgumentException) + { + // if the filename contains a wildcard (or any other invalid character), we ignore + // it as a potential default assembly name + } + catch (NotSupportedException) + { + } + catch (PathTooLongException) + { + } + } + string[] files = null; + try + { + string path = Path.GetDirectoryName(fileName); + files = Directory.GetFiles(path == "" ? "." : path, Path.GetFileName(fileName)); + } + catch { } + if (files == null || files.Length == 0) + { + StaticCompiler.IssueMessage(Message.InputFileNotFound, fileName); + } + else + { + foreach (string f in files) + { + ProcessFile(options, null, f); + } + } + } + } + + internal static bool TryParseVersion(string str, out Version version) + { + if (str.EndsWith(".*")) + { + str = str.Substring(0, str.Length - 1); + int count = str.Split('.').Length; + // NOTE this is the published algorithm for generating automatic build and revision numbers + // (see AssemblyVersionAttribute constructor docs), but it turns out that the revision + // number is off an hour (on my system)... + DateTime now = DateTime.Now; + int seconds = (int)(now.TimeOfDay.TotalSeconds / 2); + int days = (int)(now - new DateTime(2000, 1, 1)).TotalDays; + if (count == 3) + { + str += days + "." + seconds; + } + else if (count == 4) + { + str += seconds; + } + else + { + version = null; + return false; + } + } + try + { + version = new Version(str); + return version.Major <= 65535 && version.Minor <= 65535 && version.Build <= 65535 && version.Revision <= 65535; + } + catch (ArgumentException) { } + catch (FormatException) { } + catch (OverflowException) { } + version = null; + return false; + } + + static void SetStrongNameKeyPair(ref StrongNameKeyPair strongNameKeyPair, FileInfo keyFile, string keyContainer) + { + try + { + if (keyFile != null) + { + strongNameKeyPair = new StrongNameKeyPair(ReadAllBytes(keyFile)); + } + else + { + strongNameKeyPair = new StrongNameKeyPair(keyContainer); + } + // FXBUG we explicitly try to access the public key force a check (the StrongNameKeyPair constructor doesn't validate the key) + if (strongNameKeyPair.PublicKey != null) { } + } + catch (Exception x) + { + throw new FatalCompilerErrorException(Message.InvalidStrongNameKeyPair, keyFile != null ? "file" : "container", x.Message); + } + } + + static void ResolveReferences(List targets) + { + Dictionary cache = new Dictionary(); + foreach (CompilerOptions target in targets) + { + if (target.unresolvedReferences != null) + { + foreach (string reference in target.unresolvedReferences) + { + foreach (CompilerOptions peer in targets) + { + if (peer.assembly.Equals(reference, StringComparison.OrdinalIgnoreCase)) + { + ArrayAppend(ref target.peerReferences, peer.assembly); + goto next_reference; + } + } + if (!resolver.ResolveReference(cache, ref target.references, reference)) + { + throw new FatalCompilerErrorException(Message.ReferenceNotFound, reference); + } + next_reference: ; + } + } + } + // verify that we didn't reference any secondary assemblies of a shared class loader group + foreach (CompilerOptions target in targets) + { + if (target.references != null) + { + foreach (Assembly asm in target.references) + { + Type forwarder = asm.GetType("__"); + if (forwarder != null && forwarder.Assembly != asm) + { + StaticCompiler.IssueMessage(Message.NonPrimaryAssemblyReference, asm.Location, forwarder.Assembly.GetName().Name); + } + } + } + } + // add legacy references (from stub files) + foreach (CompilerOptions target in targets) + { + foreach (string assemblyName in target.legacyStubReferences.Keys) + { + ArrayAppend(ref target.references, resolver.LegacyLoad(new AssemblyName(assemblyName), null)); + } + } + // now pre-load the secondary assemblies of any shared class loader groups + foreach (CompilerOptions target in targets) + { + if (target.references != null) + { + foreach (Assembly asm in target.references) + { + AssemblyClassLoader.PreloadExportedAssemblies(asm); + } + } + } + } + + private static void ArrayAppend(ref T[] array, T element) + { + if (array == null) + { + array = new T[] { element }; + } + else + { + array = ArrayUtil.Concat(array, element); + } + } + + private static void ArrayAppend(ref T[] array, T[] append) + { + if (array == null) + { + array = append; + } + else if (append != null) + { + T[] tmp = new T[array.Length + append.Length]; + Array.Copy(array, tmp, array.Length); + Array.Copy(append, 0, tmp, array.Length, append.Length); + array = tmp; + } + } + + private static byte[] ReadFromZip(ZipFile zf, ZipEntry ze) + { + byte[] buf = new byte[ze.Size]; + int pos = 0; + Stream s = zf.GetInputStream(ze); + while(pos < buf.Length) + { + pos += s.Read(buf, pos, buf.Length - pos); + } + return buf; + } + + private static bool EmitStubWarning(CompilerOptions options, byte[] buf) + { + ClassFile cf; + try + { + cf = new ClassFile(buf, 0, buf.Length, "", ClassFileParseOptions.None, null); + } + catch (ClassFormatError) + { + return false; + } + if (cf.IKVMAssemblyAttribute == null) + { + return false; + } + if (cf.IKVMAssemblyAttribute.StartsWith("[[")) + { + Regex r = new Regex(@"\[([^\[\]]+)\]"); + MatchCollection mc = r.Matches(cf.IKVMAssemblyAttribute); + foreach (Match m in mc) + { + options.legacyStubReferences[m.Groups[1].Value] = null; + StaticCompiler.IssueMessage(options, Message.StubsAreDeprecated, m.Groups[1].Value); + } + } + else + { + options.legacyStubReferences[cf.IKVMAssemblyAttribute] = null; + StaticCompiler.IssueMessage(options, Message.StubsAreDeprecated, cf.IKVMAssemblyAttribute); + } + return true; + } + + private static bool IsExcludedOrStubLegacy(CompilerOptions options, ZipEntry ze, byte[] data) + { + if (ze.Name.EndsWith(".class", StringComparison.OrdinalIgnoreCase)) + { + try + { + bool stub; + string name = ClassFile.GetClassName(data, 0, data.Length, out stub); + if (options.IsExcludedClass(name) || (stub && EmitStubWarning(options, data))) + { + // we use stubs to add references, but otherwise ignore them + return true; + } + } + catch (ClassFormatError) + { + } + } + return false; + } + + private void ProcessManifest(CompilerOptions options, ZipFile zf, ZipEntry ze) + { + if (manifestMainClass == null) + { + // read main class from manifest + // TODO find out if we can use other information from manifest + StreamReader rdr = new StreamReader(zf.GetInputStream(ze)); + string line; + while ((line = rdr.ReadLine()) != null) + { + if (line.StartsWith("Main-Class: ")) + { + line = line.Substring(12); + string continuation; + while ((continuation = rdr.ReadLine()) != null + && continuation.StartsWith(" ", StringComparison.Ordinal)) + { + line += continuation.Substring(1); + } + manifestMainClass = line.Replace('/', '.'); + break; + } + } + } + } + + private bool ProcessZipFile(CompilerOptions options, string file, Predicate filter) + { + try + { + ZipFile zf = new ZipFile(file); + try + { + bool found = false; + Jar jar = null; + foreach (ZipEntry ze in zf) + { + if (filter != null && !filter(ze)) + { + // skip + } + else + { + found = true; + byte[] data = ReadFromZip(zf, ze); + if (IsExcludedOrStubLegacy(options, ze, data)) + { + continue; + } + if (jar == null) + { + jar = options.GetJar(zf); + } + jar.Add(ze, data); + if (ze.Name == "META-INF/MANIFEST.MF") + { + ProcessManifest(options, zf, ze); + } + } + } + // include empty zip file if it has a comment + if (!found && !string.IsNullOrEmpty(zf.ZipFileComment)) + { + options.GetJar(zf); + } + return found; + } + finally + { + zf.Close(); + } + } + catch (ICSharpCode.SharpZipLib.SharpZipBaseException x) + { + throw new FatalCompilerErrorException(Message.ErrorReadingFile, file, x.Message); + } + } + + private void ProcessFile(CompilerOptions options, DirectoryInfo baseDir, string file) + { + FileInfo fileInfo = GetFileInfo(file); + if (fileInfo.Extension.Equals(".jar", StringComparison.OrdinalIgnoreCase) || fileInfo.Extension.Equals(".zip", StringComparison.OrdinalIgnoreCase)) + { + ProcessZipFile(options, file, null); + } + else + { + if (fileInfo.Extension.Equals(".class", StringComparison.OrdinalIgnoreCase)) + { + byte[] data = ReadAllBytes(fileInfo); + try + { + bool stub; + string name = ClassFile.GetClassName(data, 0, data.Length, out stub); + if (options.IsExcludedClass(name)) + { + return; + } + if (stub && EmitStubWarning(options, data)) + { + // we use stubs to add references, but otherwise ignore them + return; + } + options.GetClassesJar().Add(name.Replace('.', '/') + ".class", data, fileInfo); + return; + } + catch (ClassFormatError x) + { + StaticCompiler.IssueMessage(Message.ClassFormatError, file, x.Message); + } + } + if (baseDir == null) + { + StaticCompiler.IssueMessage(Message.UnknownFileType, file); + } + else + { + // include as resource + // extract the resource name by chopping off the base directory + string name = file.Substring(baseDir.FullName.Length); + name = name.TrimStart(Path.DirectorySeparatorChar).Replace('\\', '/'); + options.GetResourcesJar().Add(name, ReadAllBytes(fileInfo), fileInfo); + } + } + } + + private bool Recurse(CompilerOptions options, DirectoryInfo baseDir, DirectoryInfo dir, string spec) + { + bool found = false; + foreach(FileInfo file in dir.GetFiles(spec)) + { + found = true; + ProcessFile(options, baseDir, file.FullName); + } + foreach(DirectoryInfo sub in dir.GetDirectories()) + { + found |= Recurse(options, baseDir, sub, spec); + } + return found; + } + + private bool RecurseJar(CompilerOptions options, string path) + { + string file = ""; + for (; ; ) + { + file = Path.Combine(Path.GetFileName(path), file); + path = Path.GetDirectoryName(path); + if (Directory.Exists(path)) + { + throw new DirectoryNotFoundException(); + } + else if (File.Exists(path)) + { + string pathFilter = Path.GetDirectoryName(file) + Path.DirectorySeparatorChar; + string fileFilter = "^" + Regex.Escape(Path.GetFileName(file)).Replace("\\*", ".*").Replace("\\?", ".") + "$"; + return ProcessZipFile(options, path, delegate(ZipEntry ze) { + // MONOBUG Path.GetDirectoryName() doesn't normalize / to \ on Windows + string name = ze.Name.Replace('/', Path.DirectorySeparatorChar); + return (Path.GetDirectoryName(name) + Path.DirectorySeparatorChar).StartsWith(pathFilter) + && Regex.IsMatch(Path.GetFileName(ze.Name), fileFilter); + }); + } + } + } + + //This processes an exclusion file with a single regular expression per line + private static void ProcessExclusionFile(ref string[] classesToExclude, string filename) + { + try + { + List list = classesToExclude == null ? new List() : new List(classesToExclude); + using(StreamReader file = new StreamReader(filename)) + { + String line; + while((line = file.ReadLine()) != null) + { + line = line.Trim(); + if(!line.StartsWith("//") && line.Length != 0) + { + list.Add(line); + } + } + } + classesToExclude = list.ToArray(); + } + catch(Exception x) + { + throw new FatalCompilerErrorException(Message.ErrorReadingFile, filename, x.Message); + } + } + + private static void ProcessAttributeAnnotationsClass(ref object[] annotations, string filename) + { + try + { + byte[] buf = File.ReadAllBytes(filename); + ClassFile cf = new ClassFile(buf, 0, buf.Length, null, ClassFileParseOptions.None, null); + ArrayAppend(ref annotations, cf.Annotations); + } + catch (Exception x) + { + throw new FatalCompilerErrorException(Message.ErrorReadingFile, filename, x.Message); + } + } +} diff --git a/ikvmc/CompilerClassLoader.cs b/ikvmc/CompilerClassLoader.cs new file mode 100644 index 0000000..1d6e66a --- /dev/null +++ b/ikvmc/CompilerClassLoader.cs @@ -0,0 +1,4172 @@ +/* + Copyright (C) 2002-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +using System; +using System.Resources; +using System.IO; +using System.Collections.Generic; +using System.Xml; +using System.Diagnostics; +using System.Text.RegularExpressions; +using System.Text; +using System.Threading; +using System.Security.Permissions; +using System.Security; +using System.Runtime.CompilerServices; +using ICSharpCode.SharpZipLib.Zip; +using IKVM.Attributes; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; + +namespace IKVM.Internal +{ + sealed class CompilerClassLoader : ClassLoaderWrapper + { + private Dictionary classes; + private Dictionary remapped = new Dictionary(); + private string assemblyName; + private string assemblyFile; + private string assemblyDir; + private bool targetIsModule; + private AssemblyBuilder assemblyBuilder; + private IKVM.Internal.MapXml.Attribute[] assemblyAttributes; + private CompilerOptions options; + private AssemblyClassLoader[] referencedAssemblies; + private Dictionary nameMappings = new Dictionary(); + private Packages packages; + private Dictionary> ghosts; + private TypeWrapper[] mappedExceptions; + private bool[] mappedExceptionsAllSubClasses; + private Dictionary mapxml_Classes; + private Dictionary mapxml_MethodBodies; + private Dictionary mapxml_ReplacedMethods; + private Dictionary mapxml_MethodPrologues; + private IKVM.Internal.MapXml.Root map; + private List classesToCompile; + private List peerReferences = new List(); + private Dictionary peerLoading = new Dictionary(); + private List internalsVisibleTo = new List(); + private List dynamicallyImportedTypes = new List(); + private List jarList = new List(); + private List allwrappers; + private bool compilingCoreAssembly; + + internal CompilerClassLoader(AssemblyClassLoader[] referencedAssemblies, CompilerOptions options, FileInfo assemblyPath, bool targetIsModule, string assemblyName, Dictionary classes, bool compilingCoreAssembly) + : base(options.codegenoptions, null) + { + this.referencedAssemblies = referencedAssemblies; + this.options = options; + this.classes = classes; + this.assemblyName = assemblyName; + this.assemblyFile = assemblyPath.Name; + this.assemblyDir = assemblyPath.DirectoryName; + this.targetIsModule = targetIsModule; + this.compilingCoreAssembly = compilingCoreAssembly; + Tracer.Info(Tracer.Compiler, "Instantiate CompilerClassLoader for {0}", assemblyName); + } + + internal bool ReserveName(string javaName) + { + return !classes.ContainsKey(javaName) && GetTypeWrapperFactory().ReserveName(javaName); + } + + internal void AddNameMapping(string javaName, string typeName) + { + nameMappings.Add(javaName, typeName); + } + + internal void AddReference(AssemblyClassLoader acl) + { + referencedAssemblies = ArrayUtil.Concat(referencedAssemblies, acl); + } + + internal void AddReference(CompilerClassLoader ccl) + { + peerReferences.Add(ccl); + } + + internal AssemblyName GetAssemblyName() + { + return assemblyBuilder.GetName(); + } + + private static PermissionSet Combine(PermissionSet p1, PermissionSet p2) + { + if (p1 == null) + { + return p2; + } + if (p2 == null) + { + return p1; + } + return p1.Union(p2); + } + + internal ModuleBuilder CreateModuleBuilder() + { + AssemblyName name = new AssemblyName(); + name.Name = assemblyName; + if (options.keyPair != null) + { + name.KeyPair = options.keyPair; + } + else if (options.publicKey != null) + { + name.SetPublicKey(options.publicKey); + } + name.Version = options.version; + assemblyBuilder = + StaticCompiler.Universe + .DefineDynamicAssembly(name, AssemblyBuilderAccess.ReflectionOnly, assemblyDir); + ModuleBuilder moduleBuilder; + moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName, assemblyFile, this.EmitDebugInfo); + if(this.EmitStackTraceInfo) + { + AttributeHelper.SetSourceFile(moduleBuilder, null); + } + if(this.EmitDebugInfo || this.EmitStackTraceInfo) + { + CustomAttributeBuilder debugAttr = new CustomAttributeBuilder(JVM.Import(typeof(DebuggableAttribute)).GetConstructor(new Type[] { Types.Boolean, Types.Boolean }), new object[] { true, this.EmitDebugInfo }); + assemblyBuilder.SetCustomAttribute(debugAttr); + } + AttributeHelper.SetRuntimeCompatibilityAttribute(assemblyBuilder); + if(options.baseAddress != 0) + { + moduleBuilder.__ImageBase = options.baseAddress; + } + if(options.fileAlignment != 0) + { + moduleBuilder.__FileAlignment = options.fileAlignment; + } + if(options.highentropyva) + { + moduleBuilder.__DllCharacteristics |= DllCharacteristics.HighEntropyVA; + } + // allow the runtime to "inject" dynamic classes into the assembly + string mainAssemblyName = options.sharedclassloader != null && options.sharedclassloader[0] != this + ? options.sharedclassloader[0].assemblyName + : assemblyName; + if(!DisableDynamicBinding) + { + AttributeHelper.SetInternalsVisibleToAttribute(assemblyBuilder, mainAssemblyName + DynamicClassLoader.DynamicAssemblySuffixAndPublicKey); + } + return moduleBuilder; + } + + public override string ToString() + { + return "CompilerClassLoader:" + options.assembly; + } + + protected override TypeWrapper LoadClassImpl(string name, LoadMode mode) + { + foreach(AssemblyClassLoader acl in referencedAssemblies) + { + TypeWrapper tw = acl.DoLoad(name); + if(tw != null) + { + return tw; + } + } + if(!peerLoading.ContainsKey(name)) + { + peerLoading.Add(name, null); + try + { + foreach(CompilerClassLoader ccl in peerReferences) + { + TypeWrapper tw = ccl.PeerLoad(name); + if(tw != null) + { + return tw; + } + } + if(options.sharedclassloader != null && options.sharedclassloader[0] != this) + { + TypeWrapper tw = options.sharedclassloader[0].PeerLoad(name); + if(tw != null) + { + return tw; + } + } + } + finally + { + peerLoading.Remove(name); + } + } + TypeWrapper tw1 = GetTypeWrapperCompilerHook(name); + if(tw1 != null) + { + return tw1; + } + // HACK the peer loading mess above may have indirectly loaded the classes without returning it, + // so we try once more here + tw1 = FindLoadedClass(name); + if(tw1 != null) + { + return tw1; + } + return FindOrLoadGenericClass(name, mode); + } + + private TypeWrapper PeerLoad(string name) + { + // To keep the performance acceptable in cases where we're compiling many targets, we first check if the load can + // possibly succeed on this class loader, otherwise we'll end up doing a lot of futile recursive loading attempts. + if(classes.ContainsKey(name) || remapped.ContainsKey(name) || FindLoadedClass(name) != null) + { + TypeWrapper tw = LoadClassByDottedNameFast(name); + // HACK we don't want to load classes referenced by peers, hence the "== this" check + if(tw != null && tw.GetClassLoader() == this) + { + return tw; + } + } + if(options.sharedclassloader != null && options.sharedclassloader[0] == this) + { + foreach(CompilerClassLoader ccl in options.sharedclassloader) + { + if(ccl != this) + { + TypeWrapper tw = ccl.PeerLoad(name); + if(tw != null) + { + return tw; + } + } + } + } + return null; + } + + private TypeWrapper GetTypeWrapperCompilerHook(string name) + { + RemapperTypeWrapper rtw; + if(remapped.TryGetValue(name, out rtw)) + { + return rtw; + } + else + { + Jar.Item itemRef; + if(classes.TryGetValue(name, out itemRef)) + { + classes.Remove(name); + ClassFile f; + try + { + byte[] buf = itemRef.GetData(); + f = new ClassFile(buf, 0, buf.Length, name, ClassFileParseOptions, null); + } + catch(ClassFormatError x) + { + StaticCompiler.SuppressWarning(options, Message.ClassNotFound, name); + StaticCompiler.IssueMessage(options, Message.ClassFormatError, name, x.Message); + return null; + } + if(f.Name != name) + { + StaticCompiler.SuppressWarning(options, Message.ClassNotFound, name); + StaticCompiler.IssueMessage(options, Message.WrongClassName, name, f.Name); + return null; + } + if(f.IsPublic && options.privatePackages != null) + { + foreach(string p in options.privatePackages) + { + if(f.Name.StartsWith(p)) + { + f.SetInternal(); + break; + } + } + } + if(f.IsPublic && options.publicPackages != null) + { + bool found = false; + foreach(string package in options.publicPackages) + { + if(f.Name.StartsWith(package)) + { + found = true; + break; + } + } + if(!found) + { + f.SetInternal(); + } + } + if(f.SourceFileAttribute != null) + { + FileInfo path = itemRef.Path; + if(path != null) + { + string sourceFile = Path.GetFullPath(Path.Combine(path.DirectoryName, f.SourceFileAttribute)); + if(File.Exists(sourceFile)) + { + f.SourcePath = sourceFile; + } + } + if(f.SourcePath == null) + { + if (options.sourcepath != null) + { + string package = f.Name; + int index = package.LastIndexOf('.'); + package = index == -1 ? "" : package.Substring(0, index).Replace('.', '/'); + f.SourcePath = Path.GetFullPath(Path.Combine(options.sourcepath + "/" + package, f.SourceFileAttribute)); + } + else + { + f.SourcePath = f.SourceFileAttribute; + } + } + } + try + { + TypeWrapper tw = DefineClass(f, null); + // we successfully created the type, so we don't need to include the class as a resource + if (options.nojarstubs) + { + itemRef.Remove(); + } + else + { + itemRef.MarkAsStub(); + } + int pos = f.Name.LastIndexOf('.'); + if (pos != -1) + { + string manifestJar = options.IsClassesJar(itemRef.Jar) ? null : itemRef.Jar.Name; + packages.DefinePackage(f.Name.Substring(0, pos), manifestJar); + } + return tw; + } + catch (ClassFormatError x) + { + StaticCompiler.IssueMessage(options, Message.ClassFormatError, name, x.Message); + } + catch (IllegalAccessError x) + { + StaticCompiler.IssueMessage(options, Message.IllegalAccessError, name, x.Message); + } + catch (VerifyError x) + { + StaticCompiler.IssueMessage(options, Message.VerificationError, name, x.Message); + } + catch (NoClassDefFoundError x) + { + if ((options.codegenoptions & CodeGenOptions.DisableDynamicBinding) != 0) + { + StaticCompiler.IssueMessage(options, Message.NoClassDefFoundError, name, x.Message); + } + StaticCompiler.IssueMessage(options, Message.ClassNotFound, x.Message); + } + catch (RetargetableJavaException x) + { + StaticCompiler.IssueMessage(options, Message.GenericUnableToCompileError, name, x.GetType().Name, x.Message); + } + StaticCompiler.SuppressWarning(options, Message.ClassNotFound, name); + return null; + } + else + { + return null; + } + } + } + + // HACK when we're compiling multiple targets with -sharedclassloader, each target will have its own CompilerClassLoader, + // so we need to consider them equivalent (because they represent the same class loader). + internal bool IsEquivalentTo(ClassLoaderWrapper other) + { + if (this == other) + { + return true; + } + CompilerClassLoader ccl = other as CompilerClassLoader; + if (ccl != null && options.sharedclassloader != null && options.sharedclassloader.Contains(ccl)) + { + if (!internalsVisibleTo.Contains(ccl)) + { + AddInternalsVisibleToAttribute(ccl); + } + return true; + } + return false; + } + + internal override bool InternalsVisibleToImpl(TypeWrapper wrapper, TypeWrapper friend) + { + Debug.Assert(wrapper.GetClassLoader() == this); + ClassLoaderWrapper other = friend.GetClassLoader(); + // TODO ideally we should also respect InternalsVisibleToAttribute.Annotation here + if (this == other || internalsVisibleTo.Contains(other)) + { + return true; + } + CompilerClassLoader ccl = other as CompilerClassLoader; + if (ccl != null) + { + AddInternalsVisibleToAttribute(ccl); + return true; + } + return false; + } + + private void AddInternalsVisibleToAttribute(CompilerClassLoader ccl) + { + internalsVisibleTo.Add(ccl); + AssemblyBuilder asm = ccl.assemblyBuilder; + AssemblyName asmName = asm.GetName(); + string name = asmName.Name; + byte[] pubkey = asmName.GetPublicKey(); + if (pubkey == null && asmName.KeyPair != null) + { + pubkey = asmName.KeyPair.PublicKey; + } + if (pubkey != null && pubkey.Length != 0) + { + StringBuilder sb = new StringBuilder(name); + sb.Append(", PublicKey="); + foreach (byte b in pubkey) + { + sb.AppendFormat("{0:X2}", b); + } + name = sb.ToString(); + } + AttributeHelper.SetInternalsVisibleToAttribute(this.assemblyBuilder, name); + } + + internal void SetMain(MethodInfo m, PEFileKinds target, Dictionary props, bool noglobbing, Type apartmentAttributeType) + { + MethodBuilder mainStub = this.GetTypeWrapperFactory().ModuleBuilder.DefineGlobalMethod("main", MethodAttributes.Public | MethodAttributes.Static, Types.Int32, new Type[] { Types.String.MakeArrayType() }); + if(apartmentAttributeType != null) + { + mainStub.SetCustomAttribute(new CustomAttributeBuilder(apartmentAttributeType.GetConstructor(Type.EmptyTypes), new object[0])); + } + CodeEmitter ilgen = CodeEmitter.Create(mainStub); + CodeEmitterLocal rc = ilgen.DeclareLocal(Types.Int32); + TypeWrapper startupType = LoadClassByDottedName("ikvm.runtime.Startup"); + if(props.Count > 0) + { + ilgen.Emit(OpCodes.Newobj, JVM.Import(typeof(System.Collections.Generic.Dictionary)).GetConstructor(Type.EmptyTypes)); + foreach(KeyValuePair kv in props) + { + ilgen.Emit(OpCodes.Dup); + ilgen.Emit(OpCodes.Ldstr, kv.Key); + ilgen.Emit(OpCodes.Ldstr, kv.Value); + if(kv.Value.IndexOf('%') < kv.Value.LastIndexOf('%')) + { + ilgen.Emit(OpCodes.Call, JVM.Import(typeof(Environment)).GetMethod("ExpandEnvironmentVariables", new Type[] { Types.String })); + } + ilgen.Emit(OpCodes.Callvirt, JVM.Import(typeof(System.Collections.Generic.Dictionary)).GetMethod("Add")); + } + startupType.GetMethodWrapper("setProperties", "(Lcli.System.Collections.IDictionary;)V", false).EmitCall(ilgen); + } + ilgen.BeginExceptionBlock(); + startupType.GetMethodWrapper("enterMainThread", "()V", false).EmitCall(ilgen); + ilgen.Emit(OpCodes.Ldarg_0); + if (!noglobbing) + { + ilgen.Emit(OpCodes.Ldc_I4_0); + startupType.GetMethodWrapper("glob", "([Ljava.lang.String;I)[Ljava.lang.String;", false).EmitCall(ilgen); + } + ilgen.Emit(OpCodes.Call, m); + CodeEmitterLabel label = ilgen.DefineLabel(); + ilgen.EmitLeave(label); + ilgen.BeginCatchBlock(Types.Exception); + LoadClassByDottedName("ikvm.runtime.Util").GetMethodWrapper("mapException", "(Ljava.lang.Throwable;)Ljava.lang.Throwable;", false).EmitCall(ilgen); + CodeEmitterLocal exceptionLocal = ilgen.DeclareLocal(Types.Exception); + ilgen.Emit(OpCodes.Stloc, exceptionLocal); + TypeWrapper threadTypeWrapper = ClassLoaderWrapper.LoadClassCritical("java.lang.Thread"); + CodeEmitterLocal threadLocal = ilgen.DeclareLocal(threadTypeWrapper.TypeAsLocalOrStackType); + threadTypeWrapper.GetMethodWrapper("currentThread", "()Ljava.lang.Thread;", false).EmitCall(ilgen); + ilgen.Emit(OpCodes.Stloc, threadLocal); + ilgen.Emit(OpCodes.Ldloc, threadLocal); + threadTypeWrapper.GetMethodWrapper("getThreadGroup", "()Ljava.lang.ThreadGroup;", false).EmitCallvirt(ilgen); + ilgen.Emit(OpCodes.Ldloc, threadLocal); + ilgen.Emit(OpCodes.Ldloc, exceptionLocal); + ClassLoaderWrapper.LoadClassCritical("java.lang.ThreadGroup").GetMethodWrapper("uncaughtException", "(Ljava.lang.Thread;Ljava.lang.Throwable;)V", false).EmitCallvirt(ilgen); + ilgen.Emit(OpCodes.Ldc_I4_1); + ilgen.Emit(OpCodes.Stloc, rc); + ilgen.EmitLeave(label); + ilgen.BeginFinallyBlock(); + startupType.GetMethodWrapper("exitMainThread", "()V", false).EmitCall(ilgen); + ilgen.Emit(OpCodes.Endfinally); + ilgen.EndExceptionBlock(); + ilgen.MarkLabel(label); + ilgen.Emit(OpCodes.Ldloc, rc); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + assemblyBuilder.SetEntryPoint(mainStub, target); + } + + private void PrepareSave() + { + ((DynamicClassLoader)this.GetTypeWrapperFactory()).FinishAll(); + } + + private void Save() + { + ModuleBuilder mb = GetTypeWrapperFactory().ModuleBuilder; + if(targetIsModule) + { + // HACK force all referenced assemblies to end up as references in the assembly + // (even if they are otherwise unused), to make sure that the assembly class loader + // delegates to them at runtime. + // NOTE now we only do this for modules, when we're an assembly we store the exported + // assemblies in the ikvm.exports resource. + for(int i = 0;i < referencedAssemblies.Length; i++) + { + Type[] types = referencedAssemblies[i].MainAssembly.GetExportedTypes(); + if(types.Length > 0) + { + mb.GetTypeToken(types[0]); + } + } + } + mb.CreateGlobalFunctions(); + + AddJavaModuleAttribute(mb); + + // add a package list and export map + if(options.sharedclassloader == null || options.sharedclassloader[0] == this) + { + ConstructorInfo packageListAttributeCtor = JVM.LoadType(typeof(PackageListAttribute)).GetConstructor(new Type[] { Types.String, Types.String.MakeArrayType() }); + foreach(object[] args in packages.ToArray()) + { + args[1] = UnicodeUtil.EscapeInvalidSurrogates((string[])args[1]); + mb.SetCustomAttribute(new CustomAttributeBuilder(packageListAttributeCtor, args)); + } + // We can't add the resource when we're a module, because a multi-module assembly has a single resource namespace + // and since you cannot combine -target:module with -sharedclassloader we don't need an export map + // (the wildcard exports have already been added above, by making sure that we statically reference the assemblies). + if(!targetIsModule) + { + WriteExportMap(); + } + } + + if(targetIsModule) + { + Tracer.Info(Tracer.Compiler, "CompilerClassLoader saving {0} in {1}", assemblyFile, assemblyDir); + try + { + GetTypeWrapperFactory().ModuleBuilder.__Save(options.pekind, options.imageFileMachine); + } + catch(IOException x) + { + throw new FatalCompilerErrorException(Message.ErrorWritingFile, GetTypeWrapperFactory().ModuleBuilder.FullyQualifiedName, x.Message); + } + catch(UnauthorizedAccessException x) + { + throw new FatalCompilerErrorException(Message.ErrorWritingFile, GetTypeWrapperFactory().ModuleBuilder.FullyQualifiedName, x.Message); + } + } + else + { + Tracer.Info(Tracer.Compiler, "CompilerClassLoader saving {0} in {1}", assemblyFile, assemblyDir); + try + { + assemblyBuilder.Save(assemblyFile, options.pekind, options.imageFileMachine); + } + catch(IOException x) + { + throw new FatalCompilerErrorException(Message.ErrorWritingFile, Path.Combine(assemblyDir, assemblyFile), x.Message); + } + catch(UnauthorizedAccessException x) + { + throw new FatalCompilerErrorException(Message.ErrorWritingFile, Path.Combine(assemblyDir, assemblyFile), x.Message); + } + } + } + + private void AddJavaModuleAttribute(ModuleBuilder mb) + { + Type typeofJavaModuleAttribute = JVM.LoadType(typeof(JavaModuleAttribute)); + PropertyInfo[] propInfos = new PropertyInfo[] { + typeofJavaModuleAttribute.GetProperty("Jars") + }; + object[] propValues = new object[] { + jarList.ToArray() + }; + if (nameMappings.Count > 0) + { + string[] list = new string[nameMappings.Count * 2]; + int i = 0; + foreach (KeyValuePair kv in nameMappings) + { + list[i++] = kv.Key; + list[i++] = kv.Value; + } + list = UnicodeUtil.EscapeInvalidSurrogates(list); + CustomAttributeBuilder cab = new CustomAttributeBuilder(typeofJavaModuleAttribute.GetConstructor(new Type[] { JVM.Import(typeof(string[])) }), new object[] { list }, propInfos, propValues); + mb.SetCustomAttribute(cab); + } + else + { + CustomAttributeBuilder cab = new CustomAttributeBuilder(typeofJavaModuleAttribute.GetConstructor(Type.EmptyTypes), new object[0], propInfos, propValues); + mb.SetCustomAttribute(cab); + } + } + + private static void AddExportMapEntry(Dictionary> map, CompilerClassLoader ccl, string name) + { + string assemblyName = ccl.assemblyBuilder.FullName; + List list; + if (!map.TryGetValue(assemblyName, out list)) + { + list = new List(); + map.Add(assemblyName, list); + } + if (list != null) // if list is null, we already have a wildcard export for this assembly + { + list.Add(name); + } + } + + private void AddWildcardExports(Dictionary> exportedNamesPerAssembly) + { + foreach (AssemblyClassLoader acl in referencedAssemblies) + { + exportedNamesPerAssembly[acl.MainAssembly.FullName] = null; + } + } + + private void WriteExportMap() + { + Dictionary> exportedNamesPerAssembly = new Dictionary>(); + AddWildcardExports(exportedNamesPerAssembly); + foreach (TypeWrapper tw in dynamicallyImportedTypes) + { + AddExportMapEntry(exportedNamesPerAssembly, (CompilerClassLoader)tw.GetClassLoader(), tw.Name); + } + if (options.sharedclassloader == null) + { + foreach (CompilerClassLoader ccl in peerReferences) + { + exportedNamesPerAssembly[ccl.assemblyBuilder.FullName] = null; + } + } + else + { + foreach (CompilerClassLoader ccl in options.sharedclassloader) + { + if (ccl != this) + { + ccl.AddWildcardExports(exportedNamesPerAssembly); + foreach (Jar jar in ccl.options.jars) + { + foreach (Jar.Item item in jar) + { + if (!item.IsStub) + { + AddExportMapEntry(exportedNamesPerAssembly, ccl, item.Name); + } + } + } + if (ccl.options.externalResources != null) + { + foreach (string name in ccl.options.externalResources.Keys) + { + AddExportMapEntry(exportedNamesPerAssembly, ccl, name); + } + } + } + } + } + MemoryStream ms = new MemoryStream(); + BinaryWriter bw = new BinaryWriter(ms); + bw.Write(exportedNamesPerAssembly.Count); + foreach (KeyValuePair> kv in exportedNamesPerAssembly) + { + bw.Write(kv.Key); + if (kv.Value == null) + { + // wildcard export + bw.Write(0); + } + else + { + Debug.Assert(kv.Value.Count != 0); + bw.Write(kv.Value.Count); + foreach (string name in kv.Value) + { + bw.Write(JVM.PersistableHash(name)); + } + } + } + ms.Position = 0; + this.GetTypeWrapperFactory().ModuleBuilder.DefineManifestResource("ikvm.exports", ms, ResourceAttributes.Public); + } + + private void WriteResources() + { + Tracer.Info(Tracer.Compiler, "CompilerClassLoader adding resources..."); + + // BUG we need to call GetTypeWrapperFactory() to make sure that the assemblyBuilder is created (when building an empty target) + ModuleBuilder moduleBuilder = this.GetTypeWrapperFactory().ModuleBuilder; + + for (int i = 0; i < options.jars.Count; i++) + { + bool hasEntries = false; + MemoryStream mem = new MemoryStream(); + using (ZipOutputStream zip = new ZipOutputStream(mem)) + { + if (!string.IsNullOrEmpty(options.jars[i].Comment)) + { + zip.SetComment(options.jars[i].Comment); + } + zip.SetLevel(9); + List stubs = new List(); + foreach (Jar.Item item in options.jars[i]) + { + if (item.IsStub) + { + // we don't want stub class pseudo resources for classes loaded from the file system + if (i != options.classesJar) + { + stubs.Add(item.Name); + } + continue; + } + ZipEntry zipEntry = item.ZipEntry; + if (options.compressedResources || zipEntry.CompressionMethod != CompressionMethod.Stored) + { + zipEntry.CompressionMethod = CompressionMethod.Deflated; + } + zip.PutNextEntry(zipEntry); + byte[] data = item.GetData(); + zip.Write(data, 0, data.Length); + zip.CloseEntry(); + hasEntries = true; + } + if (stubs.Count != 0) + { + // generate the --ikvm-classes-- file in the jar + ZipEntry zipEntry = new ZipEntry(JVM.JarClassList); + zipEntry.CompressionMethod = CompressionMethod.Deflated; + zip.PutNextEntry(zipEntry); + BinaryWriter bw = new BinaryWriter(zip); + bw.Write(stubs.Count); + foreach (string classFile in stubs) + { + bw.Write(classFile); + } + bw.Flush(); + zip.CloseEntry(); + hasEntries = true; + } + } + // don't include empty classes.jar + if (i != options.classesJar || hasEntries) + { + mem = new MemoryStream(mem.ToArray()); + string name = options.jars[i].Name; + if (options.targetIsModule) + { + name = Path.GetFileNameWithoutExtension(name) + "-" + moduleBuilder.ModuleVersionId.ToString("N") + Path.GetExtension(name); + } + jarList.Add(name); + moduleBuilder.DefineManifestResource(name, mem, ResourceAttributes.Public); + } + } + } + + private static MethodAttributes MapMethodAccessModifiers(IKVM.Internal.MapXml.MapModifiers mod) + { + const IKVM.Internal.MapXml.MapModifiers access = IKVM.Internal.MapXml.MapModifiers.Public | IKVM.Internal.MapXml.MapModifiers.Protected | IKVM.Internal.MapXml.MapModifiers.Private; + switch(mod & access) + { + case IKVM.Internal.MapXml.MapModifiers.Public: + return MethodAttributes.Public; + case IKVM.Internal.MapXml.MapModifiers.Protected: + return MethodAttributes.FamORAssem; + case IKVM.Internal.MapXml.MapModifiers.Private: + return MethodAttributes.Private; + default: + return MethodAttributes.Assembly; + } + } + + private static FieldAttributes MapFieldAccessModifiers(IKVM.Internal.MapXml.MapModifiers mod) + { + const IKVM.Internal.MapXml.MapModifiers access = IKVM.Internal.MapXml.MapModifiers.Public | IKVM.Internal.MapXml.MapModifiers.Protected | IKVM.Internal.MapXml.MapModifiers.Private; + switch(mod & access) + { + case IKVM.Internal.MapXml.MapModifiers.Public: + return FieldAttributes.Public; + case IKVM.Internal.MapXml.MapModifiers.Protected: + return FieldAttributes.FamORAssem; + case IKVM.Internal.MapXml.MapModifiers.Private: + return FieldAttributes.Private; + default: + return FieldAttributes.Assembly; + } + } + + private sealed class RemapperTypeWrapper : TypeWrapper + { + private CompilerClassLoader classLoader; + private TypeBuilder typeBuilder; + private TypeBuilder helperTypeBuilder; + private Type shadowType; + private IKVM.Internal.MapXml.Class classDef; + private TypeWrapper baseTypeWrapper; + private TypeWrapper[] interfaceWrappers; + + internal override ClassLoaderWrapper GetClassLoader() + { + return classLoader; + } + + internal override bool IsRemapped + { + get + { + return true; + } + } + + private static TypeWrapper GetBaseWrapper(IKVM.Internal.MapXml.Class c) + { + if((c.Modifiers & IKVM.Internal.MapXml.MapModifiers.Interface) != 0) + { + return null; + } + if(c.Name == "java.lang.Object") + { + return null; + } + return CoreClasses.java.lang.Object.Wrapper; + } + + internal RemapperTypeWrapper(CompilerClassLoader classLoader, IKVM.Internal.MapXml.Class c, IKVM.Internal.MapXml.Root map) + : base(TypeFlags.None, (Modifiers)c.Modifiers, c.Name) + { + this.classLoader = classLoader; + this.baseTypeWrapper = GetBaseWrapper(c); + classDef = c; + bool baseIsSealed = false; + shadowType = StaticCompiler.Universe.GetType(c.Shadows, true); + classLoader.SetRemappedType(shadowType, this); + Type baseType = shadowType; + Type baseInterface = null; + if(baseType.IsInterface) + { + baseInterface = baseType; + } + TypeAttributes attrs = TypeAttributes.Public; + if((c.Modifiers & IKVM.Internal.MapXml.MapModifiers.Interface) == 0) + { + attrs |= TypeAttributes.Class; + if(baseType.IsSealed) + { + baseIsSealed = true; + attrs |= TypeAttributes.Abstract | TypeAttributes.Sealed; + } + } + else + { + attrs |= TypeAttributes.Interface | TypeAttributes.Abstract; + baseType = null; + } + if((c.Modifiers & IKVM.Internal.MapXml.MapModifiers.Abstract) != 0) + { + attrs |= TypeAttributes.Abstract; + } + string name = c.Name.Replace('/', '.'); + typeBuilder = classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(name, attrs, baseIsSealed ? Types.Object : baseType); + if(c.Attributes != null) + { + foreach(IKVM.Internal.MapXml.Attribute custattr in c.Attributes) + { + AttributeHelper.SetCustomAttribute(classLoader, typeBuilder, custattr); + } + } + if(baseInterface != null) + { + typeBuilder.AddInterfaceImplementation(baseInterface); + } + if(classLoader.EmitStackTraceInfo) + { + AttributeHelper.SetSourceFile(typeBuilder, classLoader.options.remapfile.Name); + } + + if(baseIsSealed) + { + AttributeHelper.SetModifiers(typeBuilder, (Modifiers)c.Modifiers, false); + } + + if(c.scope == IKVM.Internal.MapXml.Scope.Public) + { + // FXBUG we would like to emit an attribute with a Type argument here, but that doesn't work because + // of a bug in SetCustomAttribute that causes type arguments to be serialized incorrectly (if the type + // is in the same assembly). Normally we use AttributeHelper.FreezeDry to get around this, but that doesn't + // work in this case (no attribute is emitted at all). So we work around by emitting a string instead + AttributeHelper.SetRemappedClass(classLoader.assemblyBuilder, name, shadowType); + + AttributeHelper.SetRemappedType(typeBuilder, shadowType); + } + + List methods = new List(); + + if(c.Constructors != null) + { + foreach(IKVM.Internal.MapXml.Constructor m in c.Constructors) + { + methods.Add(new RemappedConstructorWrapper(this, m)); + } + } + + if(c.Methods != null) + { + foreach(IKVM.Internal.MapXml.Method m in c.Methods) + { + methods.Add(new RemappedMethodWrapper(this, m, map, false)); + } + } + // add methods from our super classes (e.g. Throwable should have Object's methods) + if(!this.IsFinal && !this.IsInterface && this.BaseTypeWrapper != null) + { + foreach(MethodWrapper mw in BaseTypeWrapper.GetMethods()) + { + RemappedMethodWrapper rmw = mw as RemappedMethodWrapper; + if(rmw != null && (rmw.IsPublic || rmw.IsProtected)) + { + if(!FindMethod(methods, rmw.Name, rmw.Signature)) + { + methods.Add(new RemappedMethodWrapper(this, rmw.XmlMethod, map, true)); + } + } + } + } + + SetMethods(methods.ToArray()); + } + + internal sealed override TypeWrapper BaseTypeWrapper + { + get { return baseTypeWrapper; } + } + + internal void LoadInterfaces(IKVM.Internal.MapXml.Class c) + { + if (c.Interfaces != null) + { + interfaceWrappers = new TypeWrapper[c.Interfaces.Length]; + for (int i = 0; i < c.Interfaces.Length; i++) + { + interfaceWrappers[i] = classLoader.LoadClassByDottedName(c.Interfaces[i].Name); + } + } + else + { + interfaceWrappers = TypeWrapper.EmptyArray; + } + } + + private static bool FindMethod(List methods, string name, string sig) + { + foreach(MethodWrapper mw in methods) + { + if(mw.Name == name && mw.Signature == sig) + { + return true; + } + } + return false; + } + + abstract class RemappedMethodBaseWrapper : MethodWrapper + { + internal RemappedMethodBaseWrapper(RemapperTypeWrapper typeWrapper, string name, string sig, Modifiers modifiers) + : base(typeWrapper, name, sig, null, null, null, modifiers, MemberFlags.None) + { + } + + internal abstract MethodBase DoLink(); + + internal abstract void Finish(); + } + + sealed class RemappedConstructorWrapper : RemappedMethodBaseWrapper + { + private IKVM.Internal.MapXml.Constructor m; + private MethodBuilder mbHelper; + + internal RemappedConstructorWrapper(RemapperTypeWrapper typeWrapper, IKVM.Internal.MapXml.Constructor m) + : base(typeWrapper, "", m.Sig, (Modifiers)m.Modifiers) + { + this.m = m; + } + + internal override void EmitCall(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Call, GetMethod()); + } + + internal override void EmitNewobj(CodeEmitter ilgen) + { + if(mbHelper != null) + { + ilgen.Emit(OpCodes.Call, mbHelper); + } + else + { + ilgen.Emit(OpCodes.Newobj, GetMethod()); + } + } + + internal override MethodBase DoLink() + { + MethodAttributes attr = MapMethodAccessModifiers(m.Modifiers); + RemapperTypeWrapper typeWrapper = (RemapperTypeWrapper)DeclaringType; + Type[] paramTypes = typeWrapper.GetClassLoader().ArgTypeListFromSig(m.Sig); + + MethodBuilder cbCore = null; + + if(typeWrapper.shadowType.IsSealed) + { + mbHelper = typeWrapper.typeBuilder.DefineMethod("newhelper", attr | MethodAttributes.Static, CallingConventions.Standard, typeWrapper.shadowType, paramTypes); + if(m.Attributes != null) + { + foreach(IKVM.Internal.MapXml.Attribute custattr in m.Attributes) + { + AttributeHelper.SetCustomAttribute(DeclaringType.GetClassLoader(), mbHelper, custattr); + } + } + SetParameters(DeclaringType.GetClassLoader(), mbHelper, m.Params); + AttributeHelper.SetModifiers(mbHelper, (Modifiers)m.Modifiers, false); + AttributeHelper.SetNameSig(mbHelper, "", m.Sig); + AddDeclaredExceptions(mbHelper, m.throws); + } + else + { + cbCore = ReflectUtil.DefineConstructor(typeWrapper.typeBuilder, attr, paramTypes); + if(m.Attributes != null) + { + foreach(IKVM.Internal.MapXml.Attribute custattr in m.Attributes) + { + AttributeHelper.SetCustomAttribute(DeclaringType.GetClassLoader(), cbCore, custattr); + } + } + SetParameters(DeclaringType.GetClassLoader(), cbCore, m.Params); + AddDeclaredExceptions(cbCore, m.throws); + } + return cbCore; + } + + internal override void Finish() + { + // TODO we should insert method tracing (if enabled) + + Type[] paramTypes = this.GetParametersForDefineMethod(); + + MethodBuilder cbCore = GetMethod() as MethodBuilder; + + if(cbCore != null) + { + CodeEmitter ilgen = CodeEmitter.Create(cbCore); + // TODO we need to support ghost (and other funky?) parameter types + if(m.body != null) + { + // TODO do we need return type conversion here? + m.body.Emit(DeclaringType.GetClassLoader(), ilgen); + } + else + { + ilgen.Emit(OpCodes.Ldarg_0); + for(int i = 0; i < paramTypes.Length; i++) + { + ilgen.EmitLdarg(i + 1); + } + if(m.redirect != null) + { + throw new NotImplementedException(); + } + else + { + ConstructorInfo baseCon = DeclaringType.TypeAsTBD.GetConstructor(paramTypes); + if(baseCon == null) + { + // TODO better error handling + throw new InvalidOperationException("base class constructor not found: " + DeclaringType.Name + "." + m.Sig); + } + ilgen.Emit(OpCodes.Call, baseCon); + } + ilgen.Emit(OpCodes.Ret); + } + ilgen.DoEmit(); + if(this.DeclaringType.GetClassLoader().EmitStackTraceInfo) + { + ilgen.EmitLineNumberTable(cbCore); + } + } + + if(mbHelper != null) + { + CodeEmitter ilgen = CodeEmitter.Create(mbHelper); + if(m.redirect != null) + { + m.redirect.Emit(DeclaringType.GetClassLoader(), ilgen); + } + else if(m.alternateBody != null) + { + m.alternateBody.Emit(DeclaringType.GetClassLoader(), ilgen); + } + else if(m.body != null) + { + // doesn't make sense for helper constructors (which are actually factory methods) + throw new InvalidOperationException(); + } + else + { + ConstructorInfo baseCon = DeclaringType.TypeAsTBD.GetConstructor(paramTypes); + if(baseCon == null) + { + // TODO better error handling + throw new InvalidOperationException("constructor not found: " + DeclaringType.Name + "." + m.Sig); + } + for(int i = 0; i < paramTypes.Length; i++) + { + ilgen.EmitLdarg(i); + } + ilgen.Emit(OpCodes.Newobj, baseCon); + ilgen.Emit(OpCodes.Ret); + } + ilgen.DoEmit(); + if(this.DeclaringType.GetClassLoader().EmitStackTraceInfo) + { + ilgen.EmitLineNumberTable(mbHelper); + } + } + } + } + + sealed class RemappedMethodWrapper : RemappedMethodBaseWrapper + { + private IKVM.Internal.MapXml.Method m; + private IKVM.Internal.MapXml.Root map; + private MethodBuilder mbHelper; + private List overriders = new List(); + private bool inherited; + + internal RemappedMethodWrapper(RemapperTypeWrapper typeWrapper, IKVM.Internal.MapXml.Method m, IKVM.Internal.MapXml.Root map, bool inherited) + : base(typeWrapper, m.Name, m.Sig, (Modifiers)m.Modifiers) + { + this.m = m; + this.map = map; + this.inherited = inherited; + } + + internal IKVM.Internal.MapXml.Method XmlMethod + { + get + { + return m; + } + } + + internal override void EmitCall(CodeEmitter ilgen) + { + if(!IsStatic && IsFinal) + { + // When calling a final instance method on a remapped type from a class derived from a .NET class (i.e. a cli.System.Object or cli.System.Exception derived base class) + // then we can't call the java.lang.Object or java.lang.Throwable methods and we have to go through the instancehelper_ method. Note that since the method + // is final, this won't affect the semantics. + EmitCallvirt(ilgen); + } + else + { + ilgen.Emit(OpCodes.Call, (MethodInfo)GetMethod()); + } + } + + internal override void EmitCallvirt(CodeEmitter ilgen) + { + EmitCallvirtImpl(ilgen, this.IsProtected && !mbHelper.IsPublic); + } + + private void EmitCallvirtImpl(CodeEmitter ilgen, bool cloneOrFinalizeHack) + { + if(mbHelper != null && !cloneOrFinalizeHack) + { + ilgen.Emit(OpCodes.Call, mbHelper); + } + else + { + ilgen.Emit(OpCodes.Callvirt, (MethodInfo)GetMethod()); + } + } + + internal override MethodBase DoLink() + { + RemapperTypeWrapper typeWrapper = (RemapperTypeWrapper)DeclaringType; + + if(typeWrapper.IsInterface) + { + if(m.@override == null) + { + throw new InvalidOperationException(typeWrapper.Name + "." + m.Name + m.Sig); + } + MethodInfo interfaceMethod = typeWrapper.shadowType.GetMethod(m.@override.Name, typeWrapper.GetClassLoader().ArgTypeListFromSig(m.Sig)); + if(interfaceMethod == null) + { + throw new InvalidOperationException(typeWrapper.Name + "." + m.Name + m.Sig); + } + // if any of the remapped types has a body for this interface method, we need a helper method + // to special invocation through this interface for that type + List specialCases = null; + foreach(IKVM.Internal.MapXml.Class c in map.assembly.Classes) + { + if(c.Methods != null) + { + foreach(IKVM.Internal.MapXml.Method mm in c.Methods) + { + if(mm.Name == m.Name && mm.Sig == m.Sig && mm.body != null) + { + if(specialCases == null) + { + specialCases = new List(); + } + specialCases.Add(c); + break; + } + } + } + } + string[] throws; + if (m.throws == null) + { + throws = new string[0]; + } + else + { + throws = new string[m.throws.Length]; + for (int i = 0; i < throws.Length; i++) + { + throws[i] = m.throws[i].Class; + } + } + AttributeHelper.SetRemappedInterfaceMethod(typeWrapper.typeBuilder, m.Name, m.@override.Name, throws); + MethodBuilder helper = null; + if(specialCases != null) + { + CodeEmitter ilgen; + Type[] argTypes = ArrayUtil.Concat(typeWrapper.shadowType, typeWrapper.GetClassLoader().ArgTypeListFromSig(m.Sig)); + if(typeWrapper.helperTypeBuilder == null) + { + typeWrapper.helperTypeBuilder = typeWrapper.typeBuilder.DefineNestedType("__Helper", TypeAttributes.NestedPublic | TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.Abstract); + AttributeHelper.HideFromJava(typeWrapper.helperTypeBuilder); + } + helper = typeWrapper.helperTypeBuilder.DefineMethod(m.Name, MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static, typeWrapper.GetClassLoader().RetTypeWrapperFromSig(m.Sig, LoadMode.LoadOrThrow).TypeAsSignatureType, argTypes); + if(m.Attributes != null) + { + foreach(IKVM.Internal.MapXml.Attribute custattr in m.Attributes) + { + AttributeHelper.SetCustomAttribute(DeclaringType.GetClassLoader(), helper, custattr); + } + } + SetParameters(DeclaringType.GetClassLoader(), helper, m.Params); + ilgen = CodeEmitter.Create(helper); + foreach(IKVM.Internal.MapXml.Class c in specialCases) + { + TypeWrapper tw = typeWrapper.GetClassLoader().LoadClassByDottedName(c.Name); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Isinst, tw.TypeAsTBD); + ilgen.Emit(OpCodes.Dup); + CodeEmitterLabel label = ilgen.DefineLabel(); + ilgen.EmitBrfalse(label); + for(int i = 1; i < argTypes.Length; i++) + { + ilgen.EmitLdarg(i); + } + MethodWrapper mw = tw.GetMethodWrapper(m.Name, m.Sig, false); + mw.Link(); + mw.EmitCallvirt(ilgen); + ilgen.Emit(OpCodes.Ret); + ilgen.MarkLabel(label); + ilgen.Emit(OpCodes.Pop); + } + for(int i = 0; i < argTypes.Length; i++) + { + ilgen.EmitLdarg(i); + } + ilgen.Emit(OpCodes.Callvirt, interfaceMethod); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + mbHelper = helper; + return interfaceMethod; + } + else + { + MethodBuilder mbCore = null; + Type[] paramTypes = typeWrapper.GetClassLoader().ArgTypeListFromSig(m.Sig); + Type retType = typeWrapper.GetClassLoader().RetTypeWrapperFromSig(m.Sig, LoadMode.LoadOrThrow).TypeAsSignatureType; + + if(typeWrapper.shadowType.IsSealed && (m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Static) == 0) + { + // skip instance methods in sealed types, but we do need to add them to the overriders + if(typeWrapper.BaseTypeWrapper != null && (m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Private) == 0) + { + RemappedMethodWrapper baseMethod = typeWrapper.BaseTypeWrapper.GetMethodWrapper(m.Name, m.Sig, true) as RemappedMethodWrapper; + if(baseMethod != null && + !baseMethod.IsFinal && + !baseMethod.IsPrivate && + (baseMethod.m.@override != null || + baseMethod.m.redirect != null || + baseMethod.m.body != null || + baseMethod.m.alternateBody != null)) + { + baseMethod.overriders.Add(typeWrapper); + } + } + } + else + { + MethodInfo overrideMethod = null; + MethodAttributes attr = m.MethodAttributes | MapMethodAccessModifiers(m.Modifiers) | MethodAttributes.HideBySig; + if((m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Static) != 0) + { + attr |= MethodAttributes.Static; + } + else if((m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Private) == 0 && (m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Final) == 0) + { + attr |= MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.CheckAccessOnOverride; + if(!typeWrapper.shadowType.IsSealed) + { + MethodInfo autoOverride = typeWrapper.shadowType.GetMethod(m.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, paramTypes, null); + if(autoOverride != null && autoOverride.ReturnType == retType && !autoOverride.IsFinal) + { + // the method we're processing is overriding a method in its shadowType (which is the actual base type) + attr &= ~MethodAttributes.NewSlot; + } + } + if(typeWrapper.BaseTypeWrapper != null) + { + RemappedMethodWrapper baseMethod = typeWrapper.BaseTypeWrapper.GetMethodWrapper(m.Name, m.Sig, true) as RemappedMethodWrapper; + if(baseMethod != null) + { + baseMethod.overriders.Add(typeWrapper); + if(baseMethod.m.@override != null) + { + overrideMethod = typeWrapper.BaseTypeWrapper.TypeAsTBD.GetMethod(baseMethod.m.@override.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, paramTypes, null); + if(overrideMethod == null) + { + throw new InvalidOperationException(); + } + } + } + } + } + mbCore = GetDefineMethodHelper().DefineMethod(DeclaringType.GetClassLoader().GetTypeWrapperFactory(), typeWrapper.typeBuilder, m.Name, attr); + if(m.Attributes != null) + { + foreach(IKVM.Internal.MapXml.Attribute custattr in m.Attributes) + { + AttributeHelper.SetCustomAttribute(DeclaringType.GetClassLoader(), mbCore, custattr); + } + } + SetParameters(DeclaringType.GetClassLoader(), mbCore, m.Params); + if(overrideMethod != null && !inherited) + { + typeWrapper.typeBuilder.DefineMethodOverride(mbCore, overrideMethod); + } + if(inherited) + { + AttributeHelper.HideFromReflection(mbCore); + } + AddDeclaredExceptions(mbCore, m.throws); + } + + if((m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Static) == 0 && !IsHideFromJava(m)) + { + // instance methods must have an instancehelper method + MethodAttributes attr = MapMethodAccessModifiers(m.Modifiers) | MethodAttributes.HideBySig | MethodAttributes.Static; + // NOTE instancehelpers for protected methods are made internal + // and special cased in DotNetTypeWrapper.LazyPublishMembers + if((m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Protected) != 0) + { + attr &= ~MethodAttributes.MemberAccessMask; + attr |= MethodAttributes.Assembly; + } + mbHelper = typeWrapper.typeBuilder.DefineMethod("instancehelper_" + m.Name, attr, CallingConventions.Standard, retType, ArrayUtil.Concat(typeWrapper.shadowType, paramTypes)); + if(m.Attributes != null) + { + foreach(IKVM.Internal.MapXml.Attribute custattr in m.Attributes) + { + AttributeHelper.SetCustomAttribute(DeclaringType.GetClassLoader(), mbHelper, custattr); + } + } + IKVM.Internal.MapXml.Param[] parameters; + if(m.Params == null) + { + parameters = new IKVM.Internal.MapXml.Param[1]; + } + else + { + parameters = new IKVM.Internal.MapXml.Param[m.Params.Length + 1]; + m.Params.CopyTo(parameters, 1); + } + parameters[0] = new IKVM.Internal.MapXml.Param(); + parameters[0].Name = "this"; + SetParameters(DeclaringType.GetClassLoader(), mbHelper, parameters); + if(!typeWrapper.IsFinal) + { + AttributeHelper.SetEditorBrowsableNever(mbHelper); + } + AttributeHelper.SetModifiers(mbHelper, (Modifiers)m.Modifiers, false); + AttributeHelper.SetNameSig(mbHelper, m.Name, m.Sig); + AddDeclaredExceptions(mbHelper, m.throws); + mbHelper.SetCustomAttribute(new CustomAttributeBuilder(JVM.Import(typeof(ObsoleteAttribute)).GetConstructor(new Type[] { Types.String }), new object[] { "This function will be removed from future versions. Please use extension methods from ikvm.extensions namespace instead." })); + } + return mbCore; + } + } + + private static bool IsHideFromJava(IKVM.Internal.MapXml.Method m) + { + if (m.Attributes != null) + { + foreach (MapXml.Attribute attr in m.Attributes) + { + if (attr.Type == "IKVM.Attributes.HideFromJavaAttribute") + { + return true; + } + } + } + return m.Name.StartsWith("__<", StringComparison.Ordinal); + } + + internal override void Finish() + { + // TODO we should insert method tracing (if enabled) + Type[] paramTypes = this.GetParametersForDefineMethod(); + + MethodBuilder mbCore = GetMethod() as MethodBuilder; + + // NOTE sealed types don't have instance methods (only instancehelpers) + if(mbCore != null) + { + CodeEmitter ilgen = CodeEmitter.Create(mbCore); + MethodInfo baseMethod = null; + if(m.@override != null) + { + baseMethod = DeclaringType.TypeAsTBD.GetMethod(m.@override.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, paramTypes, null); + if(baseMethod == null) + { + throw new InvalidOperationException(); + } + ((TypeBuilder)DeclaringType.TypeAsBaseType).DefineMethodOverride(mbCore, baseMethod); + } + // TODO we need to support ghost (and other funky?) parameter types + if(m.body != null) + { + // we manually walk the instruction list, because we need to special case the ret instructions + IKVM.Internal.MapXml.CodeGenContext context = new IKVM.Internal.MapXml.CodeGenContext(DeclaringType.GetClassLoader()); + foreach(IKVM.Internal.MapXml.Instruction instr in m.body.invoke) + { + if(instr is IKVM.Internal.MapXml.Ret) + { + this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null); + } + instr.Generate(context, ilgen); + } + } + else + { + if(m.redirect != null && m.redirect.LineNumber != -1) + { + ilgen.SetLineNumber((ushort)m.redirect.LineNumber); + } + int thisOffset = 0; + if((m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Static) == 0) + { + thisOffset = 1; + ilgen.Emit(OpCodes.Ldarg_0); + } + for(int i = 0; i < paramTypes.Length; i++) + { + ilgen.EmitLdarg(i + thisOffset); + } + if(m.redirect != null) + { + EmitRedirect(DeclaringType.TypeAsTBD, ilgen); + } + else + { + if(baseMethod == null) + { + throw new InvalidOperationException(DeclaringType.Name + "." + m.Name + m.Sig); + } + ilgen.Emit(OpCodes.Call, baseMethod); + } + this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null); + ilgen.Emit(OpCodes.Ret); + } + ilgen.DoEmit(); + if(this.DeclaringType.GetClassLoader().EmitStackTraceInfo) + { + ilgen.EmitLineNumberTable(mbCore); + } + } + + // NOTE static methods don't have helpers + // NOTE for interface helpers we don't have to do anything, + // because they've already been generated in DoLink + // (currently this only applies to Comparable.compareTo). + if(mbHelper != null && !this.DeclaringType.IsInterface) + { + CodeEmitter ilgen = CodeEmitter.Create(mbHelper); + // check "this" for null + if(m.@override != null && m.redirect == null && m.body == null && m.alternateBody == null) + { + // we're going to be calling the overridden version, so we don't need the null check + } + else if(!m.NoNullCheck) + { + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.EmitNullCheck(); + } + if(mbCore != null && + (m.@override == null || m.redirect != null) && + (m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Private) == 0 && (m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Final) == 0) + { + // TODO we should have a way to supress this for overridden methods + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Isinst, DeclaringType.TypeAsBaseType); + ilgen.Emit(OpCodes.Dup); + CodeEmitterLabel skip = ilgen.DefineLabel(); + ilgen.EmitBrfalse(skip); + for(int i = 0; i < paramTypes.Length; i++) + { + ilgen.EmitLdarg(i + 1); + } + ilgen.Emit(OpCodes.Callvirt, mbCore); + this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null); + ilgen.Emit(OpCodes.Ret); + ilgen.MarkLabel(skip); + ilgen.Emit(OpCodes.Pop); + } + foreach(RemapperTypeWrapper overrider in overriders) + { + RemappedMethodWrapper mw = (RemappedMethodWrapper)overrider.GetMethodWrapper(Name, Signature, false); + if(mw.m.redirect == null && mw.m.body == null && mw.m.alternateBody == null) + { + // the overridden method doesn't actually do anything special (that means it will end + // up calling the .NET method it overrides), so we don't need to special case this + } + else + { + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Isinst, overrider.TypeAsTBD); + ilgen.Emit(OpCodes.Dup); + CodeEmitterLabel skip = ilgen.DefineLabel(); + ilgen.EmitBrfalse(skip); + for(int i = 0; i < paramTypes.Length; i++) + { + ilgen.EmitLdarg(i + 1); + } + mw.Link(); + mw.EmitCallvirtImpl(ilgen, false); + this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null); + ilgen.Emit(OpCodes.Ret); + ilgen.MarkLabel(skip); + ilgen.Emit(OpCodes.Pop); + } + } + if(m.body != null || m.alternateBody != null) + { + IKVM.Internal.MapXml.InstructionList body = m.alternateBody == null ? m.body : m.alternateBody; + // we manually walk the instruction list, because we need to special case the ret instructions + IKVM.Internal.MapXml.CodeGenContext context = new IKVM.Internal.MapXml.CodeGenContext(DeclaringType.GetClassLoader()); + foreach(IKVM.Internal.MapXml.Instruction instr in body.invoke) + { + if(instr is IKVM.Internal.MapXml.Ret) + { + this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null); + } + instr.Generate(context, ilgen); + } + } + else + { + if(m.redirect != null && m.redirect.LineNumber != -1) + { + ilgen.SetLineNumber((ushort)m.redirect.LineNumber); + } + Type shadowType = ((RemapperTypeWrapper)DeclaringType).shadowType; + for(int i = 0; i < paramTypes.Length + 1; i++) + { + ilgen.EmitLdarg(i); + } + if(m.redirect != null) + { + EmitRedirect(shadowType, ilgen); + } + else if(m.@override != null) + { + MethodInfo baseMethod = shadowType.GetMethod(m.@override.Name, BindingFlags.Instance | BindingFlags.Public, null, paramTypes, null); + if(baseMethod == null) + { + throw new InvalidOperationException(DeclaringType.Name + "." + m.Name + m.Sig); + } + ilgen.Emit(OpCodes.Callvirt, baseMethod); + } + else + { + RemappedMethodWrapper baseMethod = DeclaringType.BaseTypeWrapper.GetMethodWrapper(Name, Signature, true) as RemappedMethodWrapper; + if(baseMethod == null || baseMethod.m.@override == null) + { + throw new InvalidOperationException(DeclaringType.Name + "." + m.Name + m.Sig); + } + MethodInfo overrideMethod = shadowType.GetMethod(baseMethod.m.@override.Name, BindingFlags.Instance | BindingFlags.Public, null, paramTypes, null); + if(overrideMethod == null) + { + throw new InvalidOperationException(DeclaringType.Name + "." + m.Name + m.Sig); + } + ilgen.Emit(OpCodes.Callvirt, overrideMethod); + } + this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null); + ilgen.Emit(OpCodes.Ret); + } + ilgen.DoEmit(); + if(this.DeclaringType.GetClassLoader().EmitStackTraceInfo) + { + ilgen.EmitLineNumberTable(mbHelper); + } + } + + // do we need a helper for non-virtual reflection invocation? + if(m.nonvirtualAlternateBody != null || (m.@override != null && overriders.Count > 0)) + { + RemapperTypeWrapper typeWrapper = (RemapperTypeWrapper)DeclaringType; + MethodBuilder mb = typeWrapper.typeBuilder.DefineMethod("nonvirtualhelper/" + this.Name, MethodAttributes.Private | MethodAttributes.Static, + ReturnTypeForDefineMethod, ArrayUtil.Concat(typeWrapper.TypeAsSignatureType, GetParametersForDefineMethod())); + if(m.Attributes != null) + { + foreach(IKVM.Internal.MapXml.Attribute custattr in m.Attributes) + { + AttributeHelper.SetCustomAttribute(DeclaringType.GetClassLoader(), mb, custattr); + } + } + SetParameters(DeclaringType.GetClassLoader(), mb, m.Params); + AttributeHelper.HideFromJava(mb); + CodeEmitter ilgen = CodeEmitter.Create(mb); + if(m.nonvirtualAlternateBody != null) + { + m.nonvirtualAlternateBody.Emit(DeclaringType.GetClassLoader(), ilgen); + } + else + { + Type shadowType = ((RemapperTypeWrapper)DeclaringType).shadowType; + MethodInfo baseMethod = shadowType.GetMethod(m.@override.Name, BindingFlags.Instance | BindingFlags.Public, null, paramTypes, null); + if(baseMethod == null) + { + throw new InvalidOperationException(DeclaringType.Name + "." + m.Name + m.Sig); + } + ilgen.Emit(OpCodes.Ldarg_0); + for(int i = 0; i < paramTypes.Length; i++) + { + ilgen.EmitLdarg(i + 1); + } + ilgen.Emit(OpCodes.Call, baseMethod); + ilgen.Emit(OpCodes.Ret); + } + ilgen.DoEmit(); + } + } + + private void EmitRedirect(Type baseType, CodeEmitter ilgen) + { + string redirName = m.redirect.Name; + string redirSig = m.redirect.Sig; + if(redirName == null) + { + redirName = m.Name; + } + if(redirSig == null) + { + redirSig = m.Sig; + } + ClassLoaderWrapper classLoader = DeclaringType.GetClassLoader(); + // HACK if the class name contains a comma, we assume it is a .NET type + if(m.redirect.Class == null || m.redirect.Class.IndexOf(',') >= 0) + { + // TODO better error handling + Type type = m.redirect.Class == null ? baseType : StaticCompiler.Universe.GetType(m.redirect.Class, true); + Type[] redirParamTypes = classLoader.ArgTypeListFromSig(redirSig); + MethodInfo mi = type.GetMethod(m.redirect.Name, redirParamTypes); + if(mi == null) + { + throw new InvalidOperationException(); + } + ilgen.Emit(OpCodes.Call, mi); + } + else + { + TypeWrapper tw = classLoader.LoadClassByDottedName(m.redirect.Class); + MethodWrapper mw = tw.GetMethodWrapper(redirName, redirSig, false); + if(mw == null) + { + throw new InvalidOperationException("Missing redirect method: " + tw.Name + "." + redirName + redirSig); + } + mw.Link(); + mw.EmitCall(ilgen); + } + } + } + + private static void SetParameters(ClassLoaderWrapper loader, MethodBuilder mb, IKVM.Internal.MapXml.Param[] parameters) + { + if(parameters != null) + { + for(int i = 0; i < parameters.Length; i++) + { + ParameterBuilder pb = mb.DefineParameter(i + 1, ParameterAttributes.None, parameters[i].Name); + if(parameters[i].Attributes != null) + { + for(int j = 0; j < parameters[i].Attributes.Length; j++) + { + AttributeHelper.SetCustomAttribute(loader, pb, parameters[i].Attributes[j]); + } + } + } + } + } + + internal void Process2ndPassStep1() + { + if (!shadowType.IsSealed) + { + foreach (TypeWrapper ifaceTypeWrapper in interfaceWrappers) + { + typeBuilder.AddInterfaceImplementation(ifaceTypeWrapper.TypeAsBaseType); + } + } + AttributeHelper.SetImplementsAttribute(typeBuilder, interfaceWrappers); + } + + internal void Process2ndPassStep2(IKVM.Internal.MapXml.Root map) + { + IKVM.Internal.MapXml.Class c = classDef; + TypeBuilder tb = typeBuilder; + + List fields = new List(); + + // TODO fields should be moved to the RemapperTypeWrapper constructor as well + if(c.Fields != null) + { + foreach(IKVM.Internal.MapXml.Field f in c.Fields) + { + { + FieldAttributes attr = MapFieldAccessModifiers(f.Modifiers); + if(f.Constant != null) + { + attr |= FieldAttributes.Literal; + } + else if((f.Modifiers & IKVM.Internal.MapXml.MapModifiers.Final) != 0) + { + attr |= FieldAttributes.InitOnly; + } + if((f.Modifiers & IKVM.Internal.MapXml.MapModifiers.Static) != 0) + { + attr |= FieldAttributes.Static; + } + FieldBuilder fb = tb.DefineField(f.Name, GetClassLoader().FieldTypeWrapperFromSig(f.Sig, LoadMode.LoadOrThrow).TypeAsSignatureType, attr); + if(f.Attributes != null) + { + foreach(IKVM.Internal.MapXml.Attribute custattr in f.Attributes) + { + AttributeHelper.SetCustomAttribute(classLoader, fb, custattr); + } + } + object constant; + if(f.Constant != null) + { + switch(f.Sig[0]) + { + case 'J': + constant = long.Parse(f.Constant); + break; + default: + // TODO support other types + throw new NotImplementedException("remapped constant field of type: " + f.Sig); + } + fb.SetConstant(constant); + fields.Add(new ConstantFieldWrapper(this, GetClassLoader().FieldTypeWrapperFromSig(f.Sig, LoadMode.LoadOrThrow), f.Name, f.Sig, (Modifiers)f.Modifiers, fb, constant, MemberFlags.None)); + } + else + { + fields.Add(FieldWrapper.Create(this, GetClassLoader().FieldTypeWrapperFromSig(f.Sig, LoadMode.LoadOrThrow), fb, f.Name, f.Sig, new ExModifiers((Modifiers)f.Modifiers, false))); + } + } + } + } + SetFields(fields.ToArray()); + } + + internal void Process3rdPass() + { + foreach(RemappedMethodBaseWrapper m in GetMethods()) + { + m.Link(); + } + } + + internal void Process4thPass(ICollection remappedTypes) + { + foreach(RemappedMethodBaseWrapper m in GetMethods()) + { + m.Finish(); + } + + if(classDef.Clinit != null) + { + MethodBuilder cb = ReflectUtil.DefineTypeInitializer(typeBuilder, classLoader); + CodeEmitter ilgen = CodeEmitter.Create(cb); + // TODO emit code to make sure super class is initialized + classDef.Clinit.body.Emit(classLoader, ilgen); + ilgen.DoEmit(); + } + + // FXBUG because the AppDomain.TypeResolve event doesn't work correctly for inner classes, + // we need to explicitly finish the interface we implement (if they are ghosts, we need the nested __Interface type) + if(classDef.Interfaces != null) + { + foreach(IKVM.Internal.MapXml.Interface iface in classDef.Interfaces) + { + GetClassLoader().LoadClassByDottedName(iface.Name).Finish(); + } + } + + CreateShadowInstanceOf(remappedTypes); + CreateShadowCheckCast(remappedTypes); + + if(!shadowType.IsInterface) + { + // For all inherited methods, we emit a method that hides the inherited method and + // annotate it with EditorBrowsableAttribute(EditorBrowsableState.Never) to make + // sure the inherited methods don't show up in Intellisense. + Dictionary methods = new Dictionary(); + foreach(MethodWrapper mw in GetMethods()) + { + MethodBuilder mb = mw.GetMethod() as MethodBuilder; + if(mb != null) + { + methods.Add(MakeMethodKey(mb), mb); + } + } + foreach(MethodInfo mi in typeBuilder.BaseType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy)) + { + string key = MakeMethodKey(mi); + if(!methods.ContainsKey(key)) + { + ParameterInfo[] paramInfo = mi.GetParameters(); + Type[] paramTypes = new Type[paramInfo.Length]; + for(int i = 0; i < paramInfo.Length; i++) + { + paramTypes[i] = paramInfo[i].ParameterType; + } + MethodBuilder mb = typeBuilder.DefineMethod(mi.Name, mi.Attributes & (MethodAttributes.MemberAccessMask | MethodAttributes.SpecialName | MethodAttributes.Static), mi.ReturnType, paramTypes); + AttributeHelper.HideFromJava(mb); + AttributeHelper.SetEditorBrowsableNever(mb); + CopyLinkDemands(mb, mi); + CodeEmitter ilgen = CodeEmitter.Create(mb); + for(int i = 0; i < paramTypes.Length; i++) + { + ilgen.EmitLdarg(i); + } + if(!mi.IsStatic) + { + ilgen.EmitLdarg(paramTypes.Length); + ilgen.Emit(OpCodes.Callvirt, mi); + } + else + { + ilgen.Emit(OpCodes.Call, mi); + } + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + methods[key] = mb; + } + } + foreach(PropertyInfo pi in typeBuilder.BaseType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)) + { + ParameterInfo[] paramInfo = pi.GetIndexParameters(); + Type[] paramTypes = new Type[paramInfo.Length]; + for(int i = 0; i < paramInfo.Length; i++) + { + paramTypes[i] = paramInfo[i].ParameterType; + } + PropertyBuilder pb = typeBuilder.DefineProperty(pi.Name, PropertyAttributes.None, pi.PropertyType, paramTypes); + if(pi.GetGetMethod() != null) + { + pb.SetGetMethod(methods[MakeMethodKey(pi.GetGetMethod())]); + } + if(pi.GetSetMethod() != null) + { + pb.SetSetMethod(methods[MakeMethodKey(pi.GetSetMethod())]); + } + AttributeHelper.SetEditorBrowsableNever(pb); + } + } + + typeBuilder.CreateType(); + if(helperTypeBuilder != null) + { + helperTypeBuilder.CreateType(); + } + } + + private static void CopyLinkDemands(MethodBuilder mb, MethodInfo mi) + { + foreach (CustomAttributeData cad in CustomAttributeData.__GetDeclarativeSecurity(mi)) + { + if (cad.ConstructorArguments.Count == 0 || (int)cad.ConstructorArguments[0].Value == (int)SecurityAction.LinkDemand) + { + mb.__AddDeclarativeSecurity(cad.__ToBuilder()); + } + } + } + + private static string MakeMethodKey(MethodInfo method) + { + StringBuilder sb = new StringBuilder(); + sb.Append(method.ReturnType.AssemblyQualifiedName).Append(":").Append(method.Name); + ParameterInfo[] paramInfo = method.GetParameters(); + Type[] paramTypes = new Type[paramInfo.Length]; + for(int i = 0; i < paramInfo.Length; i++) + { + paramTypes[i] = paramInfo[i].ParameterType; + sb.Append(":").Append(paramInfo[i].ParameterType.AssemblyQualifiedName); + } + return sb.ToString(); + } + + private void CreateShadowInstanceOf(ICollection remappedTypes) + { + // FXBUG .NET 1.1 doesn't allow static methods on interfaces + if(typeBuilder.IsInterface) + { + return; + } + MethodAttributes attr = MethodAttributes.SpecialName | MethodAttributes.Public | MethodAttributes.Static; + MethodBuilder mb = typeBuilder.DefineMethod("__", attr, Types.Boolean, new Type[] { Types.Object }); + AttributeHelper.HideFromJava(mb); + AttributeHelper.SetEditorBrowsableNever(mb); + CodeEmitter ilgen = CodeEmitter.Create(mb); + + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Isinst, shadowType); + CodeEmitterLabel retFalse = ilgen.DefineLabel(); + ilgen.EmitBrfalse(retFalse); + + if(!shadowType.IsSealed) + { + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Isinst, typeBuilder); + ilgen.EmitBrtrue(retFalse); + } + + if(shadowType == Types.Object) + { + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Isinst, Types.Array); + ilgen.EmitBrtrue(retFalse); + } + + foreach(RemapperTypeWrapper r in remappedTypes) + { + if(!r.shadowType.IsInterface && r.shadowType.IsSubclassOf(shadowType)) + { + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Isinst, r.shadowType); + ilgen.EmitBrtrue(retFalse); + } + } + ilgen.Emit(OpCodes.Ldc_I4_1); + ilgen.Emit(OpCodes.Ret); + + ilgen.MarkLabel(retFalse); + ilgen.Emit(OpCodes.Ldc_I4_0); + ilgen.Emit(OpCodes.Ret); + + ilgen.DoEmit(); + } + + private void CreateShadowCheckCast(ICollection remappedTypes) + { + // FXBUG .NET 1.1 doesn't allow static methods on interfaces + if(typeBuilder.IsInterface) + { + return; + } + MethodAttributes attr = MethodAttributes.SpecialName | MethodAttributes.Public | MethodAttributes.Static; + MethodBuilder mb = typeBuilder.DefineMethod("__", attr, shadowType, new Type[] { Types.Object }); + AttributeHelper.HideFromJava(mb); + AttributeHelper.SetEditorBrowsableNever(mb); + CodeEmitter ilgen = CodeEmitter.Create(mb); + + CodeEmitterLabel fail = ilgen.DefineLabel(); + bool hasfail = false; + + if(!shadowType.IsSealed) + { + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Isinst, typeBuilder); + ilgen.EmitBrtrue(fail); + hasfail = true; + } + + if(shadowType == Types.Object) + { + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Isinst, Types.Array); + ilgen.EmitBrtrue(fail); + hasfail = true; + } + + foreach(RemapperTypeWrapper r in remappedTypes) + { + if(!r.shadowType.IsInterface && r.shadowType.IsSubclassOf(shadowType)) + { + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Isinst, r.shadowType); + ilgen.EmitBrtrue(fail); + hasfail = true; + } + } + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.EmitCastclass(shadowType); + ilgen.Emit(OpCodes.Ret); + + if(hasfail) + { + ilgen.MarkLabel(fail); + ilgen.ThrowException(JVM.Import(typeof(InvalidCastException))); + } + + ilgen.DoEmit(); + } + + internal override MethodBase LinkMethod(MethodWrapper mw) + { + return ((RemappedMethodBaseWrapper)mw).DoLink(); + } + + internal override TypeWrapper[] Interfaces + { + get + { + return interfaceWrappers; + } + } + + internal override Type TypeAsTBD + { + get + { + return shadowType; + } + } + + internal override Type TypeAsBaseType + { + get + { + return typeBuilder; + } + } + + internal override bool IsMapUnsafeException + { + get + { + // any remapped exceptions are automatically unsafe + return shadowType == Types.Exception || shadowType.IsSubclassOf(Types.Exception); + } + } + + internal override bool IsFastClassLiteralSafe + { + get { return true; } + } + } + + internal static void AddDeclaredExceptions(MethodBuilder mb, IKVM.Internal.MapXml.Throws[] throws) + { + if (throws != null) + { + string[] exceptions = new string[throws.Length]; + for (int i = 0; i < exceptions.Length; i++) + { + exceptions[i] = throws[i].Class; + } + AttributeHelper.SetThrowsAttribute(mb, exceptions); + } + } + + internal void EmitRemappedTypes() + { + Tracer.Info(Tracer.Compiler, "Emit remapped types"); + + assemblyAttributes = map.assembly.Attributes; + + if(map.assembly.Classes != null) + { + // 1st pass, put all types in remapped to make them loadable + bool hasRemappedTypes = false; + foreach(IKVM.Internal.MapXml.Class c in map.assembly.Classes) + { + if(c.Shadows != null) + { + if(classes.ContainsKey(c.Name)) + { + StaticCompiler.IssueMessage(Message.DuplicateClassName, c.Name); + } + remapped.Add(c.Name, new RemapperTypeWrapper(this, c, map)); + hasRemappedTypes = true; + } + } + + if(hasRemappedTypes) + { + SetupGhosts(map); + foreach(IKVM.Internal.MapXml.Class c in map.assembly.Classes) + { + if(c.Shadows != null) + { + remapped[c.Name].LoadInterfaces(c); + } + } + } + } + } + + internal void EmitRemappedTypes2ndPass() + { + if (map != null && map.assembly != null && map.assembly.Classes != null) + { + // 2nd pass, resolve interfaces, publish methods/fields + foreach(IKVM.Internal.MapXml.Class c in map.assembly.Classes) + { + if(c.Shadows != null) + { + RemapperTypeWrapper typeWrapper = remapped[c.Name]; + typeWrapper.Process2ndPassStep1(); + } + } + foreach(IKVM.Internal.MapXml.Class c in map.assembly.Classes) + { + if(c.Shadows != null) + { + RemapperTypeWrapper typeWrapper = remapped[c.Name]; + typeWrapper.Process2ndPassStep2(map); + } + } + } + } + + internal bool IsMapUnsafeException(TypeWrapper tw) + { + if(mappedExceptions != null) + { + for(int i = 0; i < mappedExceptions.Length; i++) + { + if(mappedExceptions[i].IsSubTypeOf(tw) || + (mappedExceptionsAllSubClasses[i] && tw.IsSubTypeOf(mappedExceptions[i]))) + { + return true; + } + } + } + return false; + } + + internal void LoadMappedExceptions(IKVM.Internal.MapXml.Root map) + { + if(map.exceptionMappings != null) + { + mappedExceptionsAllSubClasses = new bool[map.exceptionMappings.Length]; + mappedExceptions = new TypeWrapper[map.exceptionMappings.Length]; + for(int i = 0; i < mappedExceptions.Length; i++) + { + string dst = map.exceptionMappings[i].dst; + if(dst[0] == '*') + { + mappedExceptionsAllSubClasses[i] = true; + dst = dst.Substring(1); + } + mappedExceptions[i] = LoadClassByDottedName(dst); + } + // HACK we need to find the element and bind it + foreach(IKVM.Internal.MapXml.Class c in map.assembly.Classes) + { + if(c.Methods != null) + { + foreach(IKVM.Internal.MapXml.Method m in c.Methods) + { + if(m.body != null && m.body.invoke != null) + { + foreach(IKVM.Internal.MapXml.Instruction instr in m.body.invoke) + { + IKVM.Internal.MapXml.EmitExceptionMapping eem = instr as IKVM.Internal.MapXml.EmitExceptionMapping; + if(eem != null) + { + eem.mapping = map.exceptionMappings; + } + } + } + } + } + } + } + } + + internal sealed class ExceptionMapEmitter + { + private IKVM.Internal.MapXml.ExceptionMapping[] map; + + internal ExceptionMapEmitter(IKVM.Internal.MapXml.ExceptionMapping[] map) + { + this.map = map; + } + + internal void Emit(IKVM.Internal.MapXml.CodeGenContext context, CodeEmitter ilgen) + { + MethodWrapper mwSuppressFillInStackTrace = CoreClasses.java.lang.Throwable.Wrapper.GetMethodWrapper("__", "()V", false); + mwSuppressFillInStackTrace.Link(); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Callvirt, Compiler.getTypeMethod); + for(int i = 0; i < map.Length; i++) + { + ilgen.Emit(OpCodes.Dup); + ilgen.Emit(OpCodes.Ldtoken, StaticCompiler.Universe.GetType(map[i].src, true)); + ilgen.Emit(OpCodes.Call, Compiler.getTypeFromHandleMethod); + ilgen.Emit(OpCodes.Ceq); + CodeEmitterLabel label = ilgen.DefineLabel(); + ilgen.EmitBrfalse(label); + ilgen.Emit(OpCodes.Pop); + if(map[i].code != null) + { + ilgen.Emit(OpCodes.Ldarg_0); + if(map[i].code.invoke != null) + { + foreach(MapXml.Instruction instr in map[i].code.invoke) + { + MapXml.NewObj newobj = instr as MapXml.NewObj; + if(newobj != null + && newobj.Class != null + && context.ClassLoader.LoadClassByDottedName(newobj.Class).IsSubTypeOf(CoreClasses.java.lang.Throwable.Wrapper)) + { + mwSuppressFillInStackTrace.EmitCall(ilgen); + } + instr.Generate(context, ilgen); + } + } + ilgen.Emit(OpCodes.Ret); + } + else + { + TypeWrapper tw = context.ClassLoader.LoadClassByDottedName(map[i].dst); + MethodWrapper mw = tw.GetMethodWrapper("", "()V", false); + mw.Link(); + mwSuppressFillInStackTrace.EmitCall(ilgen); + mw.EmitNewobj(ilgen); + ilgen.Emit(OpCodes.Ret); + } + ilgen.MarkLabel(label); + } + ilgen.Emit(OpCodes.Pop); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ret); + } + } + + internal void LoadMapXml() + { + if(map.assembly.Classes != null) + { + mapxml_Classes = new Dictionary(); + mapxml_MethodBodies = new Dictionary(); + mapxml_ReplacedMethods = new Dictionary(); + mapxml_MethodPrologues = new Dictionary(); + foreach(IKVM.Internal.MapXml.Class c in map.assembly.Classes) + { + // if it is not a remapped type, it must be a container for native, patched or augmented methods + if(c.Shadows == null) + { + string className = c.Name; + mapxml_Classes.Add(className, c); + AddMapXmlMethods(className, c.Constructors); + AddMapXmlMethods(className, c.Methods); + if (c.Clinit != null) + { + AddMapXmlMethod(className, c.Clinit); + } + } + } + } + } + + private void AddMapXmlMethods(string className, IKVM.Internal.MapXml.MethodBase[] methods) + { + if(methods != null) + { + foreach(IKVM.Internal.MapXml.MethodBase method in methods) + { + AddMapXmlMethod(className, method); + } + } + } + + private void AddMapXmlMethod(string className, IKVM.Internal.MapXml.MethodBase method) + { + if(method.body != null) + { + mapxml_MethodBodies.Add(method.ToMethodKey(className), method.body); + } + if(method.ReplaceMethodCalls != null) + { + mapxml_ReplacedMethods.Add(method.ToMethodKey(className), method.ReplaceMethodCalls); + } + if (method.prologue != null) + { + mapxml_MethodPrologues.Add(method.ToMethodKey(className), method.prologue); + } + } + + internal IKVM.Internal.MapXml.InstructionList GetMethodPrologue(MethodKey method) + { + if(mapxml_MethodPrologues == null) + { + return null; + } + IKVM.Internal.MapXml.InstructionList prologue; + mapxml_MethodPrologues.TryGetValue(method, out prologue); + return prologue; + } + + internal IKVM.Internal.MapXml.ReplaceMethodCall[] GetReplacedMethodsFor(MethodWrapper mw) + { + if(mapxml_ReplacedMethods == null) + { + return null; + } + IKVM.Internal.MapXml.ReplaceMethodCall[] rmc; + mapxml_ReplacedMethods.TryGetValue(new MethodKey(mw.DeclaringType.Name, mw.Name, mw.Signature), out rmc); + return rmc; + } + + internal Dictionary GetMapXmlClasses() + { + return mapxml_Classes; + } + + internal Dictionary GetMapXmlMethodBodies() + { + return mapxml_MethodBodies; + } + + internal IKVM.Internal.MapXml.Param[] GetXmlMapParameters(string classname, string method, string sig) + { + if(mapxml_Classes != null) + { + IKVM.Internal.MapXml.Class clazz; + if(mapxml_Classes.TryGetValue(classname, out clazz)) + { + if(method == "" && clazz.Constructors != null) + { + for(int i = 0; i < clazz.Constructors.Length; i++) + { + if(clazz.Constructors[i].Sig == sig) + { + return clazz.Constructors[i].Params; + } + } + } + else if(clazz.Methods != null) + { + for(int i = 0; i < clazz.Methods.Length; i++) + { + if(clazz.Methods[i].Name == method && clazz.Methods[i].Sig == sig) + { + return clazz.Methods[i].Params; + } + } + } + } + } + return null; + } + + internal bool IsGhost(TypeWrapper tw) + { + return ghosts != null && tw.IsInterface && ghosts.ContainsKey(tw.Name); + } + + private void SetupGhosts(IKVM.Internal.MapXml.Root map) + { + ghosts = new Dictionary>(); + + // find the ghost interfaces + foreach(IKVM.Internal.MapXml.Class c in map.assembly.Classes) + { + if(c.Shadows != null && c.Interfaces != null) + { + // NOTE we don't support interfaces that inherit from other interfaces + // (actually, if they are explicitly listed it would probably work) + TypeWrapper typeWrapper = FindLoadedClass(c.Name); + foreach(IKVM.Internal.MapXml.Interface iface in c.Interfaces) + { + TypeWrapper ifaceWrapper = FindLoadedClass(iface.Name); + if(ifaceWrapper == null || !ifaceWrapper.TypeAsTBD.IsAssignableFrom(typeWrapper.TypeAsTBD)) + { + AddGhost(iface.Name, typeWrapper); + } + } + } + } + // we manually add the array ghost interfaces + TypeWrapper array = ClassLoaderWrapper.GetWrapperFromType(Types.Array); + AddGhost("java.io.Serializable", array); + AddGhost("java.lang.Cloneable", array); + } + + private void AddGhost(string interfaceName, TypeWrapper implementer) + { + List list; + if(!ghosts.TryGetValue(interfaceName, out list)) + { + list = new List(); + ghosts[interfaceName] = list; + } + list.Add(implementer); + } + + internal TypeWrapper[] GetGhostImplementers(TypeWrapper wrapper) + { + List list; + if (!ghosts.TryGetValue(wrapper.Name, out list)) + { + return TypeWrapper.EmptyArray; + } + return list.ToArray(); + } + + internal void FinishRemappedTypes() + { + // 3rd pass, link the methods. Note that a side effect of the linking is the + // twiddling with the overriders array in the base methods, so we need to do this + // as a separate pass before we compile the methods + foreach(RemapperTypeWrapper typeWrapper in remapped.Values) + { + typeWrapper.Process3rdPass(); + } + // 4th pass, implement methods/fields and bake the type + foreach(RemapperTypeWrapper typeWrapper in remapped.Values) + { + typeWrapper.Process4thPass(remapped.Values); + } + + if(assemblyAttributes != null) + { + foreach(IKVM.Internal.MapXml.Attribute attr in assemblyAttributes) + { + AttributeHelper.SetCustomAttribute(this, assemblyBuilder, attr); + } + } + } + + private static bool IsSigned(Assembly asm) + { + byte[] key = asm.GetName().GetPublicKey(); + return key != null && key.Length != 0; + } + + internal static bool IsCoreAssembly(Assembly asm) + { + return asm.IsDefined(StaticCompiler.GetRuntimeType("IKVM.Attributes.RemappedClassAttribute"), false); + } + + private bool CheckCompilingCoreAssembly() + { + if (map != null && map.assembly != null && map.assembly.Classes != null) + { + foreach (IKVM.Internal.MapXml.Class c in map.assembly.Classes) + { + if (c.Shadows != null && c.Name == "java.lang.Object") + { + return compilingCoreAssembly = true; + } + } + } + return false; + } + + internal static int Compile(string runtimeAssembly, List optionsList) + { + try + { + if(runtimeAssembly == null) + { + // we assume that the runtime is in the same directory as the compiler + runtimeAssembly = Path.Combine(typeof(CompilerClassLoader).Assembly.Location, ".." + Path.DirectorySeparatorChar + "IKVM.Runtime.dll"); + } + StaticCompiler.runtimeAssembly = StaticCompiler.LoadFile(runtimeAssembly); + StaticCompiler.runtimeJniAssembly = StaticCompiler.LoadFile(Path.Combine(StaticCompiler.runtimeAssembly.Location, ".." + Path.DirectorySeparatorChar + "IKVM.Runtime.JNI.dll")); + } + catch(FileNotFoundException) + { + if(StaticCompiler.runtimeAssembly == null) + { + throw new FatalCompilerErrorException(Message.RuntimeNotFound); + } + StaticCompiler.IssueMessage(Message.NoJniRuntime); + } + Tracer.Info(Tracer.Compiler, "Loaded runtime assembly: {0}", StaticCompiler.runtimeAssembly.FullName); + bool compilingCoreAssembly = false; + List compilers = new List(); + foreach (CompilerOptions options in optionsList) + { + CompilerClassLoader compiler = null; + int rc = CreateCompiler(options, ref compiler, ref compilingCoreAssembly); + if(rc != 0) + { + return rc; + } + compilers.Add(compiler); + if(options.sharedclassloader != null) + { + options.sharedclassloader.Add(compiler); + } + } + foreach (CompilerClassLoader compiler1 in compilers) + { + foreach (CompilerClassLoader compiler2 in compilers) + { + if (compiler1 != compiler2 + && (compiler1.options.crossReferenceAllPeers || (compiler1.options.peerReferences != null && Array.IndexOf(compiler1.options.peerReferences, compiler2.options.assembly) != -1))) + { + compiler1.AddReference(compiler2); + } + } + } + foreach (CompilerClassLoader compiler in compilers) + { + compiler.CompilePass0(); + } + Dictionary mainAssemblyTypes = new Dictionary(); + foreach (CompilerClassLoader compiler in compilers) + { + if (compiler.options.sharedclassloader != null) + { + Type mainAssemblyType; + if (!mainAssemblyTypes.TryGetValue(compiler.options.sharedclassloader[0], out mainAssemblyType)) + { + TypeBuilder tb = compiler.options.sharedclassloader[0].GetTypeWrapperFactory().ModuleBuilder.DefineType("__", TypeAttributes.NotPublic | TypeAttributes.Abstract | TypeAttributes.SpecialName); + AttributeHelper.HideFromJava(tb); + mainAssemblyType = tb.CreateType(); + mainAssemblyTypes.Add(compiler.options.sharedclassloader[0], mainAssemblyType); + } + if (compiler.options.sharedclassloader[0] != compiler) + { + ((AssemblyBuilder)compiler.GetTypeWrapperFactory().ModuleBuilder.Assembly).__AddTypeForwarder(mainAssemblyType); + } + } + compiler.CompilePass1(); + } + foreach (CompilerClassLoader compiler in compilers) + { + compiler.CompilePass2(); + } + if (compilingCoreAssembly) + { + RuntimeHelperTypes.Create(compilers[0]); + foreach (CompilerClassLoader compiler in compilers) + { + compiler.EmitRemappedTypes2ndPass(); + } + } + foreach (CompilerClassLoader compiler in compilers) + { + int rc = compiler.CompilePass3(); + if (rc != 0) + { + return rc; + } + } + Tracer.Info(Tracer.Compiler, "CompilerClassLoader.Save..."); + foreach (CompilerClassLoader compiler in compilers) + { + compiler.PrepareSave(); + } + if (StaticCompiler.errorCount > 0) + { + return 1; + } + foreach (CompilerClassLoader compiler in compilers) + { + compiler.Save(); + } + return StaticCompiler.errorCount == 0 ? 0 : 1; + } + + private static int CreateCompiler(CompilerOptions options, ref CompilerClassLoader loader, ref bool compilingCoreAssembly) + { + Tracer.Info(Tracer.Compiler, "JVM.Compile path: {0}, assembly: {1}", options.path, options.assembly); + AssemblyName runtimeAssemblyName = StaticCompiler.runtimeAssembly.GetName(); + bool allReferencesAreStrongNamed = IsSigned(StaticCompiler.runtimeAssembly); + List references = new List(); + foreach(Assembly reference in options.references ?? new Assembly[0]) + { + references.Add(reference); + allReferencesAreStrongNamed &= IsSigned(reference); + Tracer.Info(Tracer.Compiler, "Loaded reference assembly: {0}", reference.FullName); + // if it's an IKVM compiled assembly, make sure that it was compiled + // against same version of the runtime + foreach(AssemblyName asmref in reference.GetReferencedAssemblies()) + { + if(asmref.Name == runtimeAssemblyName.Name) + { + if(IsSigned(StaticCompiler.runtimeAssembly)) + { + // TODO we really should support binding redirects here to allow different revisions to be mixed + if(asmref.FullName != runtimeAssemblyName.FullName) + { + throw new FatalCompilerErrorException(Message.RuntimeMismatch, reference.Location, runtimeAssemblyName.FullName, asmref.FullName); + } + } + else + { + if(asmref.GetPublicKeyToken() != null && asmref.GetPublicKeyToken().Length != 0) + { + throw new FatalCompilerErrorException(Message.RuntimeMismatch, reference.Location, runtimeAssemblyName.FullName, asmref.FullName); + } + } + } + } + } + Tracer.Info(Tracer.Compiler, "Parsing class files"); + // map the class names to jar entries + Dictionary h = new Dictionary(); + List classNames = new List(); + foreach (Jar jar in options.jars) + { + if (options.IsResourcesJar(jar)) + { + continue; + } + foreach (Jar.Item item in jar) + { + string name = item.Name; + if (name.EndsWith(".class", StringComparison.Ordinal) + && name.Length > 6 + && name.IndexOf('.') == name.Length - 6) + { + string className = name.Substring(0, name.Length - 6).Replace('/', '.'); + if (h.ContainsKey(className)) + { + StaticCompiler.IssueMessage(Message.DuplicateClassName, className); + Jar.Item itemRef = h[className]; + if ((options.classesJar != -1 && itemRef.Jar == options.jars[options.classesJar]) || jar != itemRef.Jar) + { + // the previous class stays, because it was either in an earlier jar or we're processing the classes.jar + // which contains the classes loaded from the file system (where the first encountered class wins) + continue; + } + else + { + // we have a jar that contains multiple entries with the same name, the last one wins + h.Remove(className); + classNames.Remove(className); + } + } + h.Add(className, item); + classNames.Add(className); + } + } + } + + if (options.assemblyAttributeAnnotations == null) + { + // look for "assembly" type that acts as a placeholder for assembly attributes + Jar.Item assemblyType; + if (h.TryGetValue("assembly", out assemblyType)) + { + try + { + byte[] buf = assemblyType.GetData(); + ClassFile f = new ClassFile(buf, 0, buf.Length, null, ClassFileParseOptions.None, null); + // NOTE the "assembly" type in the unnamed package is a magic type + // that acts as the placeholder for assembly attributes + if (f.Name == "assembly" && f.Annotations != null) + { + options.assemblyAttributeAnnotations = f.Annotations; + // HACK remove "assembly" type that exists only as a placeholder for assembly attributes + h.Remove(f.Name); + assemblyType.Remove(); + StaticCompiler.IssueMessage(Message.LegacyAssemblyAttributesFound); + } + } + catch (ClassFormatError) { } + } + } + + // now look for a main method + if (options.mainClass == null && (options.guessFileKind || options.target != PEFileKinds.Dll)) + { + foreach (string className in classNames) + { + try + { + byte[] buf = h[className].GetData(); + ClassFile f = new ClassFile(buf, 0, buf.Length, null, ClassFileParseOptions.None, null); + if (f.Name == className) + { + foreach (ClassFile.Method m in f.Methods) + { + if (m.IsPublic && m.IsStatic && m.Name == "main" && m.Signature == "([Ljava.lang.String;)V") + { + StaticCompiler.IssueMessage(Message.MainMethodFound, f.Name); + options.mainClass = f.Name; + goto break_outer; + } + } + } + } + catch (ClassFormatError) { } + } + break_outer: ; + } + + if(options.guessFileKind && options.mainClass == null) + { + options.target = PEFileKinds.Dll; + } + + if(options.target == PEFileKinds.Dll && options.mainClass != null) + { + throw new FatalCompilerErrorException(Message.MainClassRequiresExe); + } + + if(options.target != PEFileKinds.Dll && options.mainClass == null) + { + throw new FatalCompilerErrorException(Message.ExeRequiresMainClass); + } + + if(options.target == PEFileKinds.Dll && options.props.Count != 0) + { + throw new FatalCompilerErrorException(Message.PropertiesRequireExe); + } + + if(options.path == null) + { + if(options.target == PEFileKinds.Dll) + { + if(options.targetIsModule) + { + options.path = IkvmcCompiler.GetFileInfo(options.assembly + ".netmodule"); + } + else + { + options.path = IkvmcCompiler.GetFileInfo(options.assembly + ".dll"); + } + } + else + { + options.path = IkvmcCompiler.GetFileInfo(options.assembly + ".exe"); + } + StaticCompiler.IssueMessage(Message.OutputFileIs, options.path.ToString()); + } + + if(options.targetIsModule) + { + if(options.classLoader != null) + { + throw new FatalCompilerErrorException(Message.ModuleCannotHaveClassLoader); + } + // TODO if we're overwriting a user specified assembly name, we need to emit a warning + options.assembly = options.path.Name; + } + + Tracer.Info(Tracer.Compiler, "Constructing compiler"); + AssemblyClassLoader[] referencedAssemblies = new AssemblyClassLoader[references.Count]; + for(int i = 0; i < references.Count; i++) + { + AssemblyClassLoader acl = AssemblyClassLoader.FromAssembly(references[i]); + if (Array.IndexOf(referencedAssemblies, acl) != -1) + { + StaticCompiler.IssueMessage(options, Message.DuplicateAssemblyReference, acl.MainAssembly.FullName); + } + referencedAssemblies[i] = acl; + } + loader = new CompilerClassLoader(referencedAssemblies, options, options.path, options.targetIsModule, options.assembly, h, compilingCoreAssembly); + loader.classesToCompile = new List(h.Keys); + if(options.remapfile != null) + { + Tracer.Info(Tracer.Compiler, "Loading remapped types (1) from {0}", options.remapfile); + System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(IKVM.Internal.MapXml.Root)); + ser.UnknownElement += new System.Xml.Serialization.XmlElementEventHandler(ser_UnknownElement); + ser.UnknownAttribute += new System.Xml.Serialization.XmlAttributeEventHandler(ser_UnknownAttribute); + FileStream fs; + try + { + fs = options.remapfile.OpenRead(); + } + catch(Exception x) + { + throw new FatalCompilerErrorException(Message.ErrorReadingFile, options.remapfile, x.Message); + } + try + { + XmlTextReader rdr = new XmlTextReader(fs); + IKVM.Internal.MapXml.Root.xmlReader = rdr; + IKVM.Internal.MapXml.Root map; + try + { + map = (IKVM.Internal.MapXml.Root)ser.Deserialize(rdr); + } + catch(InvalidOperationException x) + { + throw new FatalCompilerErrorException(Message.ErrorParsingMapFile, options.remapfile, x.Message); + } + if(!loader.ValidateAndSetMap(map)) + { + return 1; + } + } + finally + { + fs.Close(); + } + if(loader.CheckCompilingCoreAssembly()) + { + compilingCoreAssembly = true; + ClassLoaderWrapper.SetBootstrapClassLoader(loader); + } + } + // If we do not yet have a reference to the core assembly and we are not compiling the core assembly, + // try to find the core assembly by looking at the assemblies that the runtime references + if(JVM.CoreAssembly == null && !compilingCoreAssembly) + { + foreach(AssemblyName name in StaticCompiler.runtimeAssembly.GetReferencedAssemblies()) + { + Assembly asm = null; + try + { + asm = LoadReferencedAssembly(StaticCompiler.runtimeAssembly.Location + "/../" + name.Name + ".dll"); + } + catch(FileNotFoundException) + { + } + if(asm != null && IsCoreAssembly(asm)) + { + AssemblyClassLoader.PreloadExportedAssemblies(asm); + JVM.CoreAssembly = asm; + break; + } + } + if(JVM.CoreAssembly == null) + { + throw new FatalCompilerErrorException(Message.BootstrapClassesMissing); + } + // we need to scan again for remapped types, now that we've loaded the core library + ClassLoaderWrapper.LoadRemappedTypes(); + } + + if(!compilingCoreAssembly) + { + allReferencesAreStrongNamed &= IsSigned(JVM.CoreAssembly); + loader.AddReference(AssemblyClassLoader.FromAssembly(JVM.CoreAssembly)); + } + + if((options.keyPair != null || options.publicKey != null) && !allReferencesAreStrongNamed) + { + throw new FatalCompilerErrorException(Message.StrongNameRequiresStrongNamedRefs); + } + + if(loader.map != null) + { + loader.LoadMapXml(); + } + + if(!compilingCoreAssembly) + { + FakeTypes.Load(JVM.CoreAssembly); + } + return 0; + } + + private static Assembly LoadReferencedAssembly(string r) + { + Assembly asm = StaticCompiler.LoadFile(r); + return asm; + } + + private void CompilePass0() + { + if(options.sharedclassloader != null && options.sharedclassloader[0] != this) + { + packages = options.sharedclassloader[0].packages; + } + else + { + packages = new Packages(); + } + } + + private void CompilePass1() + { + Tracer.Info(Tracer.Compiler, "Compiling class files (1)"); + if(CheckCompilingCoreAssembly()) + { + EmitRemappedTypes(); + } + // if we're compiling the core class library, generate the "fake" generic types + // that represent the not-really existing types (i.e. the Java enums that represent .NET enums, + // the Method interface for delegates and the Annotation annotation for custom attributes) + if(map != null && CheckCompilingCoreAssembly()) + { + FakeTypes.Create(GetTypeWrapperFactory().ModuleBuilder, this); + } + allwrappers = new List(); + foreach(string s in classesToCompile) + { + TypeWrapper wrapper = LoadClassByDottedNameFast(s); + if(wrapper != null) + { + ClassLoaderWrapper loader = wrapper.GetClassLoader(); + if(loader != this) + { + if(loader is AssemblyClassLoader) + { + StaticCompiler.IssueMessage(options, Message.SkippingReferencedClass, s, ((AssemblyClassLoader)loader).GetAssembly(wrapper).FullName); + } + continue; + } + if(options.sharedclassloader != null && options.sharedclassloader[0] != this) + { + options.sharedclassloader[0].dynamicallyImportedTypes.Add(wrapper); + } + allwrappers.Add(wrapper); + } + } + } + + private void CompilePass2() + { + Tracer.Info(Tracer.Compiler, "Compiling class files (2)"); + foreach(TypeWrapper tw in allwrappers) + { + DynamicTypeWrapper dtw = tw as DynamicTypeWrapper; + if(dtw != null) + { + dtw.CreateStep2(); + } + } + } + + private int CompilePass3() + { + Tracer.Info(Tracer.Compiler, "Compiling class files (3)"); + if(map != null && CheckCompilingCoreAssembly()) + { + FakeTypes.Finish(this); + } + foreach(string proxy in options.proxies) + { + ProxyGenerator.Create(this, proxy); + } + if(options.mainClass != null) + { + TypeWrapper wrapper = null; + try + { + wrapper = LoadClassByDottedNameFast(options.mainClass); + } + catch(RetargetableJavaException) + { + } + if(wrapper == null) + { + throw new FatalCompilerErrorException(Message.MainClassNotFound); + } + MethodWrapper mw = wrapper.GetMethodWrapper("main", "([Ljava.lang.String;)V", false); + if(mw == null || !mw.IsStatic) + { + throw new FatalCompilerErrorException(Message.MainMethodNotFound); + } + mw.Link(); + MethodInfo method = mw.GetMethod() as MethodInfo; + if(method == null) + { + throw new FatalCompilerErrorException(Message.UnsupportedMainMethod); + } + if(!ReflectUtil.IsFromAssembly(method.DeclaringType, assemblyBuilder) + && (!method.IsPublic || !method.DeclaringType.IsPublic)) + { + throw new FatalCompilerErrorException(Message.ExternalMainNotAccessible); + } + Type apartmentAttributeType = null; + if(options.apartment == ApartmentState.STA) + { + apartmentAttributeType = JVM.Import(typeof(STAThreadAttribute)); + } + else if(options.apartment == ApartmentState.MTA) + { + apartmentAttributeType = JVM.Import(typeof(MTAThreadAttribute)); + } + SetMain(method, options.target, options.props, options.noglobbing, apartmentAttributeType); + } + if(map != null) + { + LoadMappedExceptions(map); + Tracer.Info(Tracer.Compiler, "Loading remapped types (2)"); + try + { + FinishRemappedTypes(); + } + catch (IKVM.Reflection.MissingMemberException x) + { + StaticCompiler.IssueMissingTypeMessage((Type)x.MemberInfo); + return 1; + } + } + Tracer.Info(Tracer.Compiler, "Compiling class files (2)"); + WriteResources(); + if(options.externalResources != null) + { + foreach(KeyValuePair kv in options.externalResources) + { + assemblyBuilder.AddResourceFile(JVM.MangleResourceName(kv.Key), kv.Value); + } + } + if(options.fileversion != null) + { + CustomAttributeBuilder filever = new CustomAttributeBuilder(JVM.Import(typeof(System.Reflection.AssemblyFileVersionAttribute)).GetConstructor(new Type[] { Types.String }), new object[] { options.fileversion }); + assemblyBuilder.SetCustomAttribute(filever); + } + if(options.assemblyAttributeAnnotations != null) + { + foreach(object[] def in options.assemblyAttributeAnnotations) + { + Annotation annotation = Annotation.LoadAssemblyCustomAttribute(this, def); + if(annotation != null) + { + annotation.Apply(this, assemblyBuilder, def); + } + } + } + if(options.classLoader != null) + { + TypeWrapper wrapper = null; + try + { + wrapper = LoadClassByDottedNameFast(options.classLoader); + } + catch(RetargetableJavaException) + { + } + if(wrapper == null) + { + throw new FatalCompilerErrorException(Message.ClassLoaderNotFound); + } + if(!wrapper.IsPublic && !ReflectUtil.IsFromAssembly(wrapper.TypeAsBaseType, assemblyBuilder)) + { + throw new FatalCompilerErrorException(Message.ClassLoaderNotAccessible); + } + if(wrapper.IsAbstract) + { + throw new FatalCompilerErrorException(Message.ClassLoaderIsAbstract); + } + if(!wrapper.IsAssignableTo(ClassLoaderWrapper.LoadClassCritical("java.lang.ClassLoader"))) + { + throw new FatalCompilerErrorException(Message.ClassLoaderNotClassLoader); + } + MethodWrapper mw = wrapper.GetMethodWrapper("", "(Lcli.System.Reflection.Assembly;)V", false); + if(mw == null) + { + throw new FatalCompilerErrorException(Message.ClassLoaderConstructorMissing); + } + ConstructorInfo ci = JVM.LoadType(typeof(CustomAssemblyClassLoaderAttribute)).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { Types.Type }, null); + assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder(ci, new object[] { wrapper.TypeAsTBD })); + // TODO it would be better to do this for all assemblies in a shared class loader group (because options.classloader is relevant only for the main assembly), + // but since it is probably common to specify the custom assembly class loader at the group level, it hopefully won't make much difference in practice. + MethodWrapper mwModuleInit = wrapper.GetMethodWrapper("InitializeModule", "(Lcli.System.Reflection.Module;)V", false); + if(mwModuleInit != null && !mwModuleInit.IsStatic) + { + MethodBuilder moduleInitializer = GetTypeWrapperFactory().ModuleBuilder.DefineGlobalMethod(".cctor", MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, null, Type.EmptyTypes); + ILGenerator ilgen = moduleInitializer.GetILGenerator(); + ilgen.Emit(OpCodes.Ldtoken, moduleInitializer); + ilgen.Emit(OpCodes.Call, JVM.Import(typeof(System.Reflection.MethodBase)).GetMethod("GetMethodFromHandle", new Type[] { JVM.Import(typeof(RuntimeMethodHandle)) })); + ilgen.Emit(OpCodes.Callvirt, JVM.Import(typeof(System.Reflection.MemberInfo)).GetMethod("get_Module")); + ilgen.Emit(OpCodes.Call, StaticCompiler.GetRuntimeType("IKVM.Runtime.ByteCodeHelper").GetMethod("InitializeModule")); + ilgen.Emit(OpCodes.Ret); + } + } + if (options.iconfile != null) + { + assemblyBuilder.__DefineIconResource(IkvmcCompiler.ReadAllBytes(options.iconfile)); + } + if (options.manifestFile != null) + { + assemblyBuilder.__DefineManifestResource(IkvmcCompiler.ReadAllBytes(options.manifestFile)); + } + assemblyBuilder.DefineVersionInfoResource(); + return 0; + } + + private static void ser_UnknownElement(object sender, System.Xml.Serialization.XmlElementEventArgs e) + { + StaticCompiler.IssueMessage(Message.UnknownElementInMapFile, e.Element.Name, e.LineNumber.ToString(), e.LinePosition.ToString()); + } + + private static void ser_UnknownAttribute(object sender, System.Xml.Serialization.XmlAttributeEventArgs e) + { + StaticCompiler.IssueMessage(Message.UnknownAttributeInMapFile, e.Attr.Name, e.LineNumber.ToString(), e.LinePosition.ToString()); + } + + private bool ValidateAndSetMap(IKVM.Internal.MapXml.Root map) + { + bool valid = true; + if (map.assembly != null) + { + if (map.assembly.Classes != null) + { + foreach (IKVM.Internal.MapXml.Class c in map.assembly.Classes) + { + if (c.Fields != null) + { + foreach (IKVM.Internal.MapXml.Field f in c.Fields) + { + ValidateNameSig("field", c.Name, f.Name, f.Sig, ref valid, true); + } + } + if (c.Methods != null) + { + foreach (IKVM.Internal.MapXml.Method m in c.Methods) + { + ValidateNameSig("method", c.Name, m.Name, m.Sig, ref valid, false); + } + } + if (c.Constructors != null) + { + foreach (IKVM.Internal.MapXml.Constructor ctor in c.Constructors) + { + ValidateNameSig("constructor", c.Name, "", ctor.Sig, ref valid, false); + } + } + if (c.Properties != null) + { + foreach (IKVM.Internal.MapXml.Property prop in c.Properties) + { + ValidateNameSig("property", c.Name, prop.Name, prop.Sig, ref valid, false); + ValidatePropertyGetterSetter("getter", c.Name, prop.Name, prop.getter, ref valid); + ValidatePropertyGetterSetter("setter", c.Name, prop.Name, prop.setter, ref valid); + } + } + } + } + } + this.map = map; + return valid; + } + + private static void ValidateNameSig(string member, string clazz, string name, string sig, ref bool valid, bool field) + { + if (!IsValidName(name)) + { + valid = false; + StaticCompiler.IssueMessage(Message.InvalidMemberNameInMapFile, member, name, clazz); + } + if (!IsValidSig(sig, field)) + { + valid = false; + StaticCompiler.IssueMessage(Message.InvalidMemberSignatureInMapFile, member, clazz, name, sig); + } + } + + private static void ValidatePropertyGetterSetter(string getterOrSetter, string clazz, string property, IKVM.Internal.MapXml.Method method, ref bool valid) + { + if (method != null) + { + if (!IsValidName(method.Name)) + { + valid = false; + StaticCompiler.IssueMessage(Message.InvalidPropertyNameInMapFile, getterOrSetter, clazz, property, method.Name); + } + if (!ClassFile.IsValidMethodSig(method.Sig)) + { + valid = false; + StaticCompiler.IssueMessage(Message.InvalidPropertySignatureInMapFile, getterOrSetter, clazz, property, method.Sig); + } + } + } + + private static bool IsValidName(string name) + { + return name != null && name.Length != 0; + } + + private static bool IsValidSig(string sig, bool field) + { + return sig != null && (field ? ClassFile.IsValidFieldSig(sig) : ClassFile.IsValidMethodSig(sig)); + } + + internal Type GetTypeFromReferencedAssembly(string name) + { + foreach (AssemblyClassLoader acl in referencedAssemblies) + { + Type type = acl.MainAssembly.GetType(name, false); + if (type != null) + { + return type; + } + } + return null; + } + + internal override void IssueMessage(Message msgId, params string[] values) + { + StaticCompiler.IssueMessage(options, msgId, values); + } + + internal bool TryEnableUnmanagedExports() + { + // we only support -platform:x86 and -platform:x64 + // (currently IKVM.Reflection doesn't support unmanaged exports for ARM) + if ((options.imageFileMachine == ImageFileMachine.I386 && (options.pekind & PortableExecutableKinds.Required32Bit) != 0) + || options.imageFileMachine == ImageFileMachine.AMD64) + { + // when you add unmanaged exports, the ILOnly flag MUST NOT be set or the DLL will fail to load + options.pekind &= ~PortableExecutableKinds.ILOnly; + return true; + } + else + { + StaticCompiler.IssueMessage(options, Message.DllExportRequiresSupportedPlatform); + return false; + } + } + + internal override bool WarningLevelHigh + { + get { return options.warningLevelHigh; } + } + + internal override bool NoParameterReflection + { + get { return options.noParameterReflection; } + } + + protected override void CheckProhibitedPackage(string className) + { + if (!compilingCoreAssembly) + { + base.CheckProhibitedPackage(className); + } + } + } + + sealed class Jar + { + internal readonly string Name; + internal readonly string Comment; + private readonly List Items = new List(); + + internal Jar(string name, string comment) + { + this.Name = name; + this.Comment = comment; + } + + internal Jar Copy() + { + Jar newJar = new Jar(Name, Comment); + newJar.Items.AddRange(Items); + return newJar; + } + + internal void Add(ZipEntry ze, byte[] data) + { + Items.Add(new JarItem(ze, data, null)); + } + + internal void Add(string name, byte[] data, FileInfo fileInfo) + { + ZipEntry zipEntry = new ZipEntry(name); + zipEntry.DateTime = fileInfo.LastWriteTimeUtc; + zipEntry.CompressionMethod = CompressionMethod.Stored; + Items.Add(new JarItem(zipEntry, data, fileInfo)); + } + + private struct JarItem + { + internal readonly ZipEntry zipEntry; + internal readonly byte[] data; + internal readonly FileInfo path; // path of the original file, if it was individual file (used to construct source file path) + + internal JarItem(ZipEntry zipEntry, byte[] data, FileInfo path) + { + this.zipEntry = zipEntry; + this.data = data; + this.path = path; + } + } + + public struct Item + { + internal readonly Jar Jar; + private readonly int Index; + + internal Item(Jar jar, int index) + { + this.Jar = jar; + this.Index = index; + } + + internal string Name + { + get { return Jar.Items[Index].zipEntry.Name; } + } + + internal byte[] GetData() + { + return Jar.Items[Index].data; + } + + internal FileInfo Path + { + get { return Jar.Items[Index].path; } + } + + internal ZipEntry ZipEntry + { + get + { + ZipEntry org = Jar.Items[Index].zipEntry; + ZipEntry zipEntry = new ZipEntry(org.Name); + zipEntry.Comment = org.Comment; + zipEntry.CompressionMethod = org.CompressionMethod; + zipEntry.DosTime = org.DosTime; + zipEntry.ExternalFileAttributes = org.ExternalFileAttributes; + zipEntry.ExtraData = org.ExtraData; + zipEntry.Flags = org.Flags; + return zipEntry; + } + } + + internal void Remove() + { + Jar.Items[Index] = new JarItem(); + } + + internal void MarkAsStub() + { + Jar.Items[Index] = new JarItem(Jar.Items[Index].zipEntry, null, null); + } + + internal bool IsStub + { + get { return Jar.Items[Index].data == null; } + } + } + + internal struct JarEnumerator + { + private readonly Jar jar; + private int index; + + internal JarEnumerator(Jar jar) + { + this.jar = jar; + this.index = -1; + } + + public Item Current + { + get { return new Item(jar, index); } + } + + public bool MoveNext() + { + while (index + 1 < jar.Items.Count) + { + if (jar.Items[++index].zipEntry != null) + { + return true; + } + } + return false; + } + } + + public JarEnumerator GetEnumerator() + { + return new JarEnumerator(this); + } + } + + sealed class CompilerOptions + { + internal List jars = new List(); + private Dictionary jarMap = new Dictionary(); + internal int classesJar = -1; + internal int resourcesJar = -1; + internal bool nojarstubs; + internal FileInfo path; + internal FileInfo keyfile; + internal string keycontainer; + internal bool delaysign; + internal byte[] publicKey; + internal StrongNameKeyPair keyPair; + internal Version version; + internal string fileversion; + internal FileInfo iconfile; + internal FileInfo manifestFile; + internal bool targetIsModule; + internal string assembly; + internal string mainClass; + internal ApartmentState apartment; + internal PEFileKinds target; + internal bool guessFileKind; + internal string[] unresolvedReferences; // only used during command line parsing + internal Dictionary legacyStubReferences = new Dictionary(); // only used during command line parsing + internal Assembly[] references; + internal string[] peerReferences; + internal bool crossReferenceAllPeers = true; + internal string[] classesToExclude; // only used during command line parsing + internal FileInfo remapfile; + internal Dictionary props; + internal bool noglobbing; + internal CodeGenOptions codegenoptions; + internal bool compressedResources; + internal string[] privatePackages; + internal string[] publicPackages; + internal string sourcepath; + internal Dictionary externalResources; + internal string classLoader; + internal PortableExecutableKinds pekind = PortableExecutableKinds.ILOnly; + internal ImageFileMachine imageFileMachine = ImageFileMachine.I386; + internal long baseAddress; + internal int fileAlignment; + internal bool highentropyva; + internal List sharedclassloader; // should *not* be deep copied in Copy(), because we want the list of all compilers that share a class loader + internal Dictionary suppressWarnings = new Dictionary(); + internal Dictionary errorWarnings = new Dictionary(); // treat specific warnings as errors + internal bool warnaserror; // treat all warnings as errors + internal FileInfo writeSuppressWarningsFile; + internal List proxies = new List(); + internal object[] assemblyAttributeAnnotations; + internal bool warningLevelHigh; + internal bool noParameterReflection; + + internal CompilerOptions Copy() + { + CompilerOptions copy = (CompilerOptions)MemberwiseClone(); + copy.jars = Copy(jars); + copy.jarMap = new Dictionary(jarMap); + if (props != null) + { + copy.props = new Dictionary(props); + } + if (externalResources != null) + { + copy.externalResources = new Dictionary(externalResources); + } + copy.suppressWarnings = new Dictionary(suppressWarnings); + copy.errorWarnings = new Dictionary(errorWarnings); + return copy; + } + + private static List Copy(List jars) + { + List newJars = new List(); + foreach (Jar jar in jars) + { + newJars.Add(jar.Copy()); + } + return newJars; + } + + internal Jar GetJar(ZipFile zf) + { + int existingJar; + if (jarMap.TryGetValue(zf.Name, out existingJar)) + { + return jars[existingJar]; + } + jarMap.Add(zf.Name, jars.Count); + return CreateJar(Path.GetFileName(zf.Name), zf.ZipFileComment); + } + + private Jar CreateJar(string jarName, string comment) + { + int count = 0; + string name = jarName; + retry: + foreach (Jar jar in jars) + { + if (jar.Name == name) + { + name = Path.GetFileNameWithoutExtension(jarName) + "-" + (++count) + Path.GetExtension(jarName); + goto retry; + } + } + Jar newJar = new Jar(name, comment); + jars.Add(newJar); + return newJar; + } + + internal Jar GetClassesJar() + { + if (classesJar == -1) + { + classesJar = jars.Count; + CreateJar("classes.jar", null); + } + return jars[classesJar]; + } + + internal bool IsClassesJar(Jar jar) + { + return classesJar != -1 && jars[classesJar] == jar; + } + + internal Jar GetResourcesJar() + { + if (resourcesJar == -1) + { + resourcesJar = jars.Count; + CreateJar("resources.jar", null); + } + return jars[resourcesJar]; + } + + internal bool IsResourcesJar(Jar jar) + { + return resourcesJar != -1 && jars[resourcesJar] == jar; + } + + internal bool IsExcludedClass(string className) + { + if (classesToExclude != null) + { + for (int i = 0; i < classesToExclude.Length; i++) + { + if (Regex.IsMatch(className, classesToExclude[i])) + { + return true; + } + } + } + return false; + } + } + + enum Message + { + // These are the informational messages + MainMethodFound = 1, + OutputFileIs = 2, + AutoAddRef = 3, + MainMethodFromManifest = 4, + // This is were the warnings start + StartWarnings = 100, + ClassNotFound = 100, + ClassFormatError = 101, + DuplicateClassName = 102, + IllegalAccessError = 103, + VerificationError = 104, + NoClassDefFoundError = 105, + GenericUnableToCompileError = 106, + DuplicateResourceName = 107, + SkippingReferencedClass = 109, + NoJniRuntime= 110, + EmittedNoClassDefFoundError = 111, + EmittedIllegalAccessError = 112, + EmittedInstantiationError = 113, + EmittedIncompatibleClassChangeError = 114, + EmittedNoSuchFieldError = 115, + EmittedAbstractMethodError = 116, + EmittedNoSuchMethodError = 117, + EmittedLinkageError = 118, + EmittedVerificationError = 119, + EmittedClassFormatError = 120, + InvalidCustomAttribute = 121, + IgnoredCustomAttribute = 122, + AssumeAssemblyVersionMatch = 123, + InvalidDirectoryInLibOptionPath = 124, + InvalidDirectoryInLibEnvironmentPath = 125, + LegacySearchRule = 126, + AssemblyLocationIgnored = 127, + InterfaceMethodCantBeInternal = 128, + DllExportMustBeStaticMethod = 129, + DllExportRequiresSupportedPlatform = 130, + DuplicateAssemblyReference = 132, + UnableToResolveType = 133, + StubsAreDeprecated = 134, + WrongClassName = 135, + ReflectionCallerClassRequiresCallerID = 136, + LegacyAssemblyAttributesFound = 137, + UnableToCreateLambdaFactory = 138, + UnknownWarning = 999, + // This is where the errors start + StartErrors = 4000, + UnableToCreateProxy = 4001, + DuplicateProxy = 4002, + MapXmlUnableToResolveOpCode = 4003, + MapXmlError = 4004, + InputFileNotFound = 4005, + UnknownFileType = 4006, + UnknownElementInMapFile = 4007, + UnknownAttributeInMapFile = 4008, + InvalidMemberNameInMapFile = 4009, + InvalidMemberSignatureInMapFile = 4010, + InvalidPropertyNameInMapFile = 4011, + InvalidPropertySignatureInMapFile = 4012, + NonPrimaryAssemblyReference = 4013, + MissingType = 4014, + MissingReference = 4015, + CallerSensitiveOnUnsupportedMethod = 4016, + // Fatal errors + ResponseFileDepthExceeded = 5000, + ErrorReadingFile = 5001, + NoTargetsFound = 5002, + FileFormatLimitationExceeded = 5003, + CannotSpecifyBothKeyFileAndContainer = 5004, + DelaySignRequiresKey = 5005, + InvalidStrongNameKeyPair = 5006, + ReferenceNotFound = 5007, + OptionsMustPreceedChildLevels = 5008, + UnrecognizedTargetType = 5009, + UnrecognizedPlatform = 5010, + UnrecognizedApartment = 5011, + MissingFileSpecification = 5012, + PathTooLong = 5013, + PathNotFound = 5014, + InvalidPath = 5015, + InvalidOptionSyntax = 5016, + ExternalResourceNotFound = 5017, + ExternalResourceNameInvalid = 5018, + InvalidVersionFormat = 5019, + InvalidFileAlignment = 5020, + ErrorWritingFile = 5021, + UnrecognizedOption = 5022, + NoOutputFileSpecified = 5023, + SharedClassLoaderCannotBeUsedOnModuleTarget = 5024, + RuntimeNotFound = 5025, + MainClassRequiresExe = 5026, + ExeRequiresMainClass = 5027, + PropertiesRequireExe = 5028, + ModuleCannotHaveClassLoader = 5029, + ErrorParsingMapFile = 5030, + BootstrapClassesMissing = 5031, + StrongNameRequiresStrongNamedRefs = 5032, + MainClassNotFound = 5033, + MainMethodNotFound = 5034, + UnsupportedMainMethod = 5035, + ExternalMainNotAccessible = 5036, + ClassLoaderNotFound = 5037, + ClassLoaderNotAccessible = 5038, + ClassLoaderIsAbstract = 5039, + ClassLoaderNotClassLoader = 5040, + ClassLoaderConstructorMissing = 5041, + MapFileTypeNotFound = 5042, + MapFileClassNotFound = 5043, + MaximumErrorCountReached = 5044, + LinkageError = 5045, + RuntimeMismatch = 5046, + RuntimeMismatchStrongName = 5047, + CoreClassesMissing = 5048, + CriticalClassNotFound = 5049, + AssemblyContainsDuplicateClassNames = 5050, + CallerIDRequiresHasCallerIDAnnotation = 5051, + UnableToResolveInterface = 5052, + MissingBaseType = 5053, + MissingBaseTypeReference = 5054, + FileNotFound = 5055, + RuntimeMethodMissing = 5056, + MapFileFieldNotFound = 5057, + GhostInterfaceMethodMissing = 5058, + } + + static class StaticCompiler + { + private static Universe universe; + internal static Assembly runtimeAssembly; + internal static Assembly runtimeJniAssembly; + internal static CompilerOptions toplevel; + internal static int errorCount; + + internal static Universe Universe + { + get + { + Debug.Assert(universe != null); + return universe; + } + } + + internal static void Init(bool emitSymbols) + { + UniverseOptions options = UniverseOptions.ResolveMissingMembers | UniverseOptions.EnableFunctionPointers; + if (!emitSymbols) + { + options |= UniverseOptions.DeterministicOutput; + } + universe = new Universe(options); + universe.ResolvedMissingMember += ResolvedMissingMember; + } + + private static void ResolvedMissingMember(Module requestingModule, MemberInfo member) + { + if (requestingModule != null && member is Type) + { + IssueMessage(Message.UnableToResolveType, requestingModule.Name, ((Type)member).FullName, member.Module.FullyQualifiedName); + } + } + + internal static Assembly Load(string assemblyString) + { + Assembly asm = Universe.Load(assemblyString); + if (asm.__IsMissing) + { + throw new FileNotFoundException(assemblyString); + } + return asm; + } + + internal static Assembly LoadFile(string path) + { + return Universe.LoadFile(path); + } + + internal static Type GetRuntimeType(string name) + { + Type type = runtimeAssembly.GetType(name); + if (type != null) + { + return type; + } + if (runtimeJniAssembly != null) + { + return runtimeJniAssembly.GetType(name, true); + } + else + { + throw new TypeLoadException(name); + } + } + + internal static Type GetTypeForMapXml(ClassLoaderWrapper loader, string name) + { + Type type = GetType(loader, name); + if (type == null) + { + throw new FatalCompilerErrorException(Message.MapFileTypeNotFound, name); + } + return type; + } + + internal static TypeWrapper GetClassForMapXml(ClassLoaderWrapper loader, string name) + { + TypeWrapper tw = loader.LoadClassByDottedNameFast(name); + if (tw == null) + { + throw new FatalCompilerErrorException(Message.MapFileClassNotFound, name); + } + return tw; + } + + internal static FieldWrapper GetFieldForMapXml(ClassLoaderWrapper loader, string clazz, string name, string sig) + { + FieldWrapper fw = GetClassForMapXml(loader, clazz).GetFieldWrapper(name, sig); + if (fw == null) + { + throw new FatalCompilerErrorException(Message.MapFileFieldNotFound, name, clazz); + } + fw.Link(); + return fw; + } + + internal static Type GetType(ClassLoaderWrapper loader, string name) + { + CompilerClassLoader ccl = (CompilerClassLoader)loader; + return ccl.GetTypeFromReferencedAssembly(name); + } + + internal static void IssueMessage(Message msgId, params string[] values) + { + IssueMessage(toplevel, msgId, values); + } + + internal static void IssueMessage(CompilerOptions options, Message msgId, params string[] values) + { + if (errorCount != 0 && msgId < Message.StartErrors && !options.warnaserror) + { + // don't display any warnings after we've emitted an error message + return; + } + string key = ((int)msgId).ToString(); + for (int i = 0; ; i++) + { + if (options.suppressWarnings.ContainsKey(key)) + { + return; + } + if (i == values.Length) + { + break; + } + key += ":" + values[i]; + } + options.suppressWarnings.Add(key, key); + if(options.writeSuppressWarningsFile != null) + { + File.AppendAllText(options.writeSuppressWarningsFile.FullName, "-nowarn:" + key + Environment.NewLine); + } + string msg; + switch(msgId) + { + case Message.MainMethodFound: + msg = "Found main method in class \"{0}\""; + break; + case Message.OutputFileIs: + msg = "Output file is \"{0}\""; + break; + case Message.AutoAddRef: + msg = "Automatically adding reference to \"{0}\""; + break; + case Message.MainMethodFromManifest: + msg = "Using main class \"{0}\" based on jar manifest"; + break; + case Message.ClassNotFound: + msg = "Class \"{0}\" not found"; + break; + case Message.ClassFormatError: + msg = "Unable to compile class \"{0}\"" + Environment.NewLine + + " (class format error \"{1}\")"; + break; + case Message.DuplicateClassName: + msg = "Duplicate class name: \"{0}\""; + break; + case Message.IllegalAccessError: + msg = "Unable to compile class \"{0}\"" + Environment.NewLine + + " (illegal access error \"{1}\")"; + break; + case Message.VerificationError: + msg = "Unable to compile class \"{0}\"" + Environment.NewLine + + " (verification error \"{1}\")"; + break; + case Message.NoClassDefFoundError: + msg = "Unable to compile class \"{0}\"" + Environment.NewLine + + " (missing class \"{1}\")"; + break; + case Message.GenericUnableToCompileError: + msg = "Unable to compile class \"{0}\"" + Environment.NewLine + + " (\"{1}\": \"{2}\")"; + break; + case Message.DuplicateResourceName: + msg = "Skipping resource (name clash): \"{0}\""; + break; + case Message.SkippingReferencedClass: + msg = "Skipping class: \"{0}\"" + Environment.NewLine + + " (class is already available in referenced assembly \"{1}\")"; + break; + case Message.NoJniRuntime: + msg = "Unable to load runtime JNI assembly"; + break; + case Message.EmittedNoClassDefFoundError: + msg = "Emitted java.lang.NoClassDefFoundError in \"{0}\"" + Environment.NewLine + + " (\"{1}\")"; + break; + case Message.EmittedIllegalAccessError: + msg = "Emitted java.lang.IllegalAccessError in \"{0}\"" + Environment.NewLine + + " (\"{1}\")"; + break; + case Message.EmittedInstantiationError: + msg = "Emitted java.lang.InstantiationError in \"{0}\"" + Environment.NewLine + + " (\"{1}\")"; + break; + case Message.EmittedIncompatibleClassChangeError: + msg = "Emitted java.lang.IncompatibleClassChangeError in \"{0}\"" + Environment.NewLine + + " (\"{1}\")"; + break; + case Message.EmittedNoSuchFieldError: + msg = "Emitted java.lang.NoSuchFieldError in \"{0}\"" + Environment.NewLine + + " (\"{1}\")"; + break; + case Message.EmittedAbstractMethodError: + msg = "Emitted java.lang.AbstractMethodError in \"{0}\"" + Environment.NewLine + + " (\"{1}\")"; + break; + case Message.EmittedNoSuchMethodError: + msg = "Emitted java.lang.NoSuchMethodError in \"{0}\"" + Environment.NewLine + + " (\"{1}\")"; + break; + case Message.EmittedLinkageError: + msg = "Emitted java.lang.LinkageError in \"{0}\"" + Environment.NewLine + + " (\"{1}\")"; + break; + case Message.EmittedVerificationError: + msg = "Emitted java.lang.VerificationError in \"{0}\"" + Environment.NewLine + + " (\"{1}\")"; + break; + case Message.EmittedClassFormatError: + msg = "Emitted java.lang.ClassFormatError in \"{0}\"" + Environment.NewLine + + " (\"{1}\")"; + break; + case Message.InvalidCustomAttribute: + msg = "Error emitting \"{0}\" custom attribute" + Environment.NewLine + + " (\"{1}\")"; + break; + case Message.IgnoredCustomAttribute: + msg = "Custom attribute \"{0}\" was ignored" + Environment.NewLine + + " (\"{1}\")"; + break; + case Message.AssumeAssemblyVersionMatch: + msg = "Assuming assembly reference \"{0}\" matches \"{1}\", you may need to supply runtime policy"; + break; + case Message.InvalidDirectoryInLibOptionPath: + msg = "Directory \"{0}\" specified in -lib option is not valid"; + break; + case Message.InvalidDirectoryInLibEnvironmentPath: + msg = "Directory \"{0}\" specified in LIB environment is not valid"; + break; + case Message.LegacySearchRule: + msg = "Found assembly \"{0}\" using legacy search rule, please append '.dll' to the reference"; + break; + case Message.AssemblyLocationIgnored: + msg = "Assembly \"{0}\" is ignored as previously loaded assembly \"{1}\" has the same identity \"{2}\""; + break; + case Message.InterfaceMethodCantBeInternal: + msg = "Ignoring @ikvm.lang.Internal annotation on interface method" + Environment.NewLine + + " (\"{0}.{1}{2}\")"; + break; + case Message.DllExportMustBeStaticMethod: + msg = "Ignoring @ikvm.lang.DllExport annotation on non-static method" + Environment.NewLine + + " (\"{0}.{1}{2}\")"; + break; + case Message.DllExportRequiresSupportedPlatform: + msg = "Ignoring @ikvm.lang.DllExport annotation due to unsupported target platform"; + break; + case Message.NonPrimaryAssemblyReference: + msg = "Referenced assembly \"{0}\" is not the primary assembly of a shared class loader group, please reference primary assembly \"{1}\" instead"; + break; + case Message.MissingType: + msg = "Reference to type \"{0}\" claims it is defined in \"{1}\", but it could not be found"; + break; + case Message.MissingReference: + msg = "The type '{0}' is defined in an assembly that is not referenced. You must add a reference to assembly '{1}'"; + break; + case Message.DuplicateAssemblyReference: + msg = "Duplicate assembly reference \"{0}\""; + break; + case Message.UnableToResolveType: + msg = "Reference in \"{0}\" to type \"{1}\" claims it is defined in \"{2}\", but it could not be found"; + break; + case Message.StubsAreDeprecated: + msg = "Compiling stubs is deprecated. Please add a reference to assembly \"{0}\" instead."; + break; + case Message.WrongClassName: + msg = "Unable to compile \"{0}\" (wrong name: \"{1}\")"; + break; + case Message.ReflectionCallerClassRequiresCallerID: + msg = "Reflection.getCallerClass() called from non-CallerID method" + Environment.NewLine + + " (\"{0}.{1}{2}\")"; + break; + case Message.LegacyAssemblyAttributesFound: + msg = "Legacy assembly attributes container found. Please use the -assemblyattributes: option."; + break; + case Message.UnableToCreateLambdaFactory: + msg = "Unable to create static lambda factory."; + break; + case Message.UnableToCreateProxy: + msg = "Unable to create proxy \"{0}\"" + Environment.NewLine + + " (\"{1}\")"; + break; + case Message.DuplicateProxy: + msg = "Duplicate proxy \"{0}\""; + break; + case Message.MapXmlUnableToResolveOpCode: + msg = "Unable to resolve opcode in remap file: {0}"; + break; + case Message.MapXmlError: + msg = "Error in remap file: {0}"; + break; + case Message.InputFileNotFound: + msg = "Source file '{0}' not found"; + break; + case Message.UnknownFileType: + msg = "Unknown file type: {0}"; + break; + case Message.UnknownElementInMapFile: + msg = "Unknown element {0} in remap file, line {1}, column {2}"; + break; + case Message.UnknownAttributeInMapFile: + msg = "Unknown attribute {0} in remap file, line {1}, column {2}"; + break; + case Message.InvalidMemberNameInMapFile: + msg = "Invalid {0} name '{1}' in remap file in class {2}"; + break; + case Message.InvalidMemberSignatureInMapFile: + msg = "Invalid {0} signature '{3}' in remap file for {0} {1}.{2}"; + break; + case Message.InvalidPropertyNameInMapFile: + msg = "Invalid property {0} name '{3}' in remap file for property {1}.{2}"; + break; + case Message.InvalidPropertySignatureInMapFile: + msg = "Invalid property {0} signature '{3}' in remap file for property {1}.{2}"; + break; + case Message.UnknownWarning: + msg = "{0}"; + break; + case Message.CallerSensitiveOnUnsupportedMethod: + msg = "CallerSensitive annotation on unsupported method" + Environment.NewLine + + " (\"{0}.{1}{2}\")"; + break; + default: + throw new InvalidProgramException(); + } + bool error = msgId >= Message.StartErrors + || (options.warnaserror && msgId >= Message.StartWarnings) + || options.errorWarnings.ContainsKey(key) + || options.errorWarnings.ContainsKey(((int)msgId).ToString()); + Console.Error.Write("{0} IKVMC{1:D4}: ", error ? "error" : msgId < Message.StartWarnings ? "note" : "warning", (int)msgId); + if (error && Message.StartWarnings <= msgId && msgId < Message.StartErrors) + { + Console.Error.Write("Warning as Error: "); + } + Console.Error.WriteLine(msg, values); + if(options != toplevel && options.path != null) + { + Console.Error.WriteLine(" (in {0})", options.path); + } + if(error) + { + if (++errorCount == 100) + { + throw new FatalCompilerErrorException(Message.MaximumErrorCountReached); + } + } + } + + internal static void LinkageError(string msg, TypeWrapper actualType, TypeWrapper expectedType, params object[] values) + { + object[] args = new object[values.Length + 2]; + values.CopyTo(args, 2); + args[0] = AssemblyQualifiedName(actualType); + args[1] = AssemblyQualifiedName(expectedType); + string str = string.Format(msg, args); + if (actualType is UnloadableTypeWrapper && (expectedType is CompiledTypeWrapper || expectedType is DotNetTypeWrapper)) + { + str += string.Format("\n\t(Please add a reference to {0})", expectedType.TypeAsBaseType.Assembly.Location); + } + throw new FatalCompilerErrorException(Message.LinkageError, str); + } + + private static string AssemblyQualifiedName(TypeWrapper tw) + { + ClassLoaderWrapper loader = tw.GetClassLoader(); + AssemblyClassLoader acl = loader as AssemblyClassLoader; + if(acl != null) + { + return tw.Name + ", " + acl.GetAssembly(tw).FullName; + } + CompilerClassLoader ccl = loader as CompilerClassLoader; + if(ccl != null) + { + return tw.Name + ", " + ccl.GetTypeWrapperFactory().ModuleBuilder.Assembly.FullName; + } + return tw.Name + " (unknown assembly)"; + } + + internal static void IssueMissingTypeMessage(Type type) + { + type = ReflectUtil.GetMissingType(type); + StaticCompiler.IssueMessage(type.Assembly.__IsMissing ? Message.MissingReference : Message.MissingType, type.FullName, type.Assembly.FullName); + } + + internal static void SuppressWarning(CompilerOptions options, Message message, string name) + { + options.suppressWarnings[(int)message + ":" + name] = null; + } + } + + sealed class Packages + { + private readonly List packages = new List(); + private readonly Dictionary packagesSet = new Dictionary(); + + internal void DefinePackage(string packageName, string jar) + { + if (!packagesSet.ContainsKey(packageName)) + { + packages.Add(packageName); + packagesSet.Add(packageName, jar); + } + } + + // returns an array of PackageListAttribute constructor argument arrays + internal object[][] ToArray() + { + List list = new List(); + // we use an empty string to indicate we don't yet have a jar, + // because null is used for packages that were defined from + // the file system (i.e. don't have a jar to load a manifest from) + string currentJar = ""; + List currentList = new List(); + foreach (string package in packages) + { + string jar = packagesSet[package]; + if (jar != currentJar) + { + if (currentList.Count != 0) + { + list.Add(new object[] { currentJar, currentList.ToArray() }); + currentList.Clear(); + } + currentJar = jar; + } + currentList.Add(package); + } + if (currentList.Count != 0) + { + list.Add(new object[] { currentJar, currentList.ToArray() }); + } + return list.ToArray(); + } + } +} diff --git a/ikvmc/FakeTypes.cs b/ikvmc/FakeTypes.cs new file mode 100644 index 0000000..ee85e7b --- /dev/null +++ b/ikvmc/FakeTypes.cs @@ -0,0 +1,118 @@ +/* + Copyright (C) 2008 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; + +namespace IKVM.Internal +{ + static class FakeTypes + { + private static Type genericEnumEnumType; + private static Type genericDelegateInterfaceType; + private static Type genericAttributeAnnotationType; + private static Type genericAttributeAnnotationMultipleType; + private static Type genericAttributeAnnotationReturnValueType; + + internal static Type GetEnumType(Type enumType) + { + return genericEnumEnumType.MakeGenericType(enumType); + } + + internal static Type GetDelegateType(Type delegateType) + { + return genericDelegateInterfaceType.MakeGenericType(delegateType); + } + + internal static Type GetAttributeType(Type attributeType) + { + return genericAttributeAnnotationType.MakeGenericType(attributeType); + } + + internal static Type GetAttributeMultipleType(Type attributeType) + { + return genericAttributeAnnotationMultipleType.MakeGenericType(attributeType); + } + + internal static Type GetAttributeReturnValueType(Type attributeType) + { + return genericAttributeAnnotationReturnValueType.MakeGenericType(attributeType); + } + + internal static void Create(ModuleBuilder modb, ClassLoaderWrapper loader) + { + TypeBuilder tb = modb.DefineType(DotNetTypeWrapper.GenericDelegateInterfaceTypeName, TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.Public); + tb.DefineGenericParameters("T")[0].SetBaseTypeConstraint(Types.MulticastDelegate); + genericDelegateInterfaceType = tb.CreateType(); + + genericAttributeAnnotationType = CreateAnnotationType(modb, DotNetTypeWrapper.GenericAttributeAnnotationTypeName); + genericAttributeAnnotationMultipleType = CreateAnnotationType(modb, DotNetTypeWrapper.GenericAttributeAnnotationMultipleTypeName); + genericAttributeAnnotationReturnValueType = CreateAnnotationType(modb, DotNetTypeWrapper.GenericAttributeAnnotationReturnValueTypeName); + CreateEnumEnum(modb, loader); + } + + internal static void Finish(ClassLoaderWrapper loader) + { + TypeBuilder tb = (TypeBuilder)genericEnumEnumType; + TypeWrapper enumTypeWrapper = loader.LoadClassByDottedName("java.lang.Enum"); + enumTypeWrapper.Finish(); + tb.SetParent(enumTypeWrapper.TypeAsBaseType); + CodeEmitter ilgen = CodeEmitter.Create(ReflectUtil.DefineConstructor(tb, MethodAttributes.Private, new Type[] { Types.String, Types.Int32 })); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ldarg_1); + ilgen.Emit(OpCodes.Ldarg_2); + enumTypeWrapper.GetMethodWrapper("", "(Ljava.lang.String;I)V", false).EmitCall(ilgen); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + genericEnumEnumType = tb.CreateType(); + } + + private static void CreateEnumEnum(ModuleBuilder modb, ClassLoaderWrapper loader) + { + TypeBuilder tb = modb.DefineType(DotNetTypeWrapper.GenericEnumEnumTypeName, TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.Public); + GenericTypeParameterBuilder gtpb = tb.DefineGenericParameters("T")[0]; + gtpb.SetBaseTypeConstraint(Types.Enum); + genericEnumEnumType = tb; + } + + private static Type CreateAnnotationType(ModuleBuilder modb, string name) + { + TypeBuilder tb = modb.DefineType(name, TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.Public); + tb.DefineGenericParameters("T")[0].SetBaseTypeConstraint(Types.Attribute); + return tb.CreateType(); + } + + internal static void Load(Assembly assembly) + { + genericEnumEnumType = assembly.GetType(DotNetTypeWrapper.GenericEnumEnumTypeName); + genericDelegateInterfaceType = assembly.GetType(DotNetTypeWrapper.GenericDelegateInterfaceTypeName); + genericAttributeAnnotationType = assembly.GetType(DotNetTypeWrapper.GenericAttributeAnnotationTypeName); + genericAttributeAnnotationMultipleType = assembly.GetType(DotNetTypeWrapper.GenericAttributeAnnotationMultipleTypeName); + genericAttributeAnnotationReturnValueType = assembly.GetType(DotNetTypeWrapper.GenericAttributeAnnotationReturnValueTypeName); + } + } +} diff --git a/ikvmc/Proxy.cs b/ikvmc/Proxy.cs new file mode 100644 index 0000000..4bd2a4f --- /dev/null +++ b/ikvmc/Proxy.cs @@ -0,0 +1,457 @@ +/* + Copyright (C) 2011-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using IKVM.Attributes; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; + +namespace IKVM.Internal +{ + static class ProxyGenerator + { + private static readonly TypeWrapper proxyClass; + private static readonly TypeWrapper errorClass; + private static readonly TypeWrapper runtimeExceptionClass; + private static readonly MethodWrapper undeclaredThrowableExceptionConstructor; + private static readonly FieldWrapper invocationHandlerField; + private static readonly TypeWrapper javaLangReflectMethod; + private static readonly TypeWrapper javaLangNoSuchMethodException; + private static readonly MethodWrapper javaLangNoClassDefFoundErrorConstructor; + private static readonly MethodWrapper javaLangThrowable_getMessage; + private static readonly MethodWrapper javaLangClass_getMethod; + private static readonly TypeWrapper invocationHandlerClass; + private static readonly MethodWrapper invokeMethod; + private static readonly MethodWrapper proxyConstructor; + private static readonly MethodWrapper hashCodeMethod; + private static readonly MethodWrapper equalsMethod; + private static readonly MethodWrapper toStringMethod; + + static ProxyGenerator() + { + ClassLoaderWrapper bootClassLoader = ClassLoaderWrapper.GetBootstrapClassLoader(); + proxyClass = bootClassLoader.LoadClassByDottedNameFast("java.lang.reflect.Proxy"); + errorClass = bootClassLoader.LoadClassByDottedNameFast("java.lang.Error"); + runtimeExceptionClass = bootClassLoader.LoadClassByDottedNameFast("java.lang.RuntimeException"); + undeclaredThrowableExceptionConstructor = bootClassLoader.LoadClassByDottedNameFast("java.lang.reflect.UndeclaredThrowableException").GetMethodWrapper("", "(Ljava.lang.Throwable;)V", false); + undeclaredThrowableExceptionConstructor.Link(); + invocationHandlerField = proxyClass.GetFieldWrapper("h", "Ljava.lang.reflect.InvocationHandler;"); + invocationHandlerField.Link(); + javaLangReflectMethod = bootClassLoader.LoadClassByDottedNameFast("java.lang.reflect.Method"); + javaLangNoSuchMethodException = bootClassLoader.LoadClassByDottedNameFast("java.lang.NoSuchMethodException"); + javaLangNoClassDefFoundErrorConstructor = bootClassLoader.LoadClassByDottedNameFast("java.lang.NoClassDefFoundError").GetMethodWrapper("", "(Ljava.lang.String;)V", false); + javaLangNoClassDefFoundErrorConstructor.Link(); + javaLangThrowable_getMessage = bootClassLoader.LoadClassByDottedNameFast("java.lang.Throwable").GetMethodWrapper("getMessage", "()Ljava.lang.String;", false); + javaLangThrowable_getMessage.Link(); + javaLangClass_getMethod = CoreClasses.java.lang.Class.Wrapper.GetMethodWrapper("getMethod", "(Ljava.lang.String;[Ljava.lang.Class;)Ljava.lang.reflect.Method;", false); + javaLangClass_getMethod.Link(); + invocationHandlerClass = bootClassLoader.LoadClassByDottedNameFast("java.lang.reflect.InvocationHandler"); + invokeMethod = invocationHandlerClass.GetMethodWrapper("invoke", "(Ljava.lang.Object;Ljava.lang.reflect.Method;[Ljava.lang.Object;)Ljava.lang.Object;", false); + proxyConstructor = proxyClass.GetMethodWrapper("", "(Ljava.lang.reflect.InvocationHandler;)V", false); + proxyConstructor.Link(); + hashCodeMethod = CoreClasses.java.lang.Object.Wrapper.GetMethodWrapper("hashCode", "()I", false); + equalsMethod = CoreClasses.java.lang.Object.Wrapper.GetMethodWrapper("equals", "(Ljava.lang.Object;)Z", false); + toStringMethod = CoreClasses.java.lang.Object.Wrapper.GetMethodWrapper("toString", "()Ljava.lang.String;", false); + } + + internal static void Create(CompilerClassLoader loader, string proxy) + { + string[] interfaces = proxy.Split(','); + TypeWrapper[] wrappers = new TypeWrapper[interfaces.Length]; + for (int i = 0; i < interfaces.Length; i++) + { + try + { + wrappers[i] = loader.LoadClassByDottedNameFast(interfaces[i]); + } + catch (RetargetableJavaException) + { + } + if (wrappers[i] == null) + { + StaticCompiler.IssueMessage(Message.UnableToCreateProxy, proxy, "unable to load interface " + interfaces[i]); + return; + } + } + Create(loader, proxy, wrappers); + } + + private static void Create(CompilerClassLoader loader, string proxy, TypeWrapper[] interfaces) + { + List methods; + try + { + methods = CheckAndCollect(loader, interfaces); + } + catch (RetargetableJavaException x) + { + StaticCompiler.IssueMessage(Message.UnableToCreateProxy, proxy, x.Message); + return; + } + catch (ProxyException x) + { + StaticCompiler.IssueMessage(Message.UnableToCreateProxy, proxy, x.Message); + return; + } + CreateNoFail(loader, interfaces, methods); + } + + private static List CheckAndCollect(CompilerClassLoader loader, TypeWrapper[] interfaces) + { + List methods = new List(); + + // The java.lang.Object methods precede any interface methods. + methods.Add(equalsMethod); + methods.Add(hashCodeMethod); + methods.Add(toStringMethod); + + // Add the interfaces methods in order. + foreach (TypeWrapper tw in interfaces) + { + if (!tw.IsInterface) + { + throw new ProxyException(tw.Name + " is not an interface"); + } + if (tw.IsRemapped) + { + // TODO handle java.lang.Comparable + throw new ProxyException(tw.Name + " is a remapped interface (not currently supported)"); + } + foreach (MethodWrapper mw in GetInterfaceMethods(tw)) + { + // Check for duplicates + if (!MethodExists(methods, mw)) + { + mw.Link(); + methods.Add(mw); + } + } + } + + // TODO verify restrictions + + // Collect declared exceptions. + Dictionary exceptions = new Dictionary(); + foreach (MethodWrapper mw in methods) + { + Add(loader, exceptions, mw); + } + + // Build the definitive proxy method list. + List proxyMethods = new List(); + foreach (MethodWrapper mw in methods) + { + proxyMethods.Add(new ProxyMethod(mw, exceptions[mw.Signature])); + } + return proxyMethods; + } + + private static bool MethodExists(List methods, MethodWrapper mw) + { + foreach (MethodWrapper mw1 in methods) + { + // TODO what do we do with differing return types? + if (mw1.Name == mw.Name && mw1.Signature == mw.Signature) + { + return true; + } + } + return false; + } + + private static void Add(CompilerClassLoader loader, Dictionary exceptions, MethodWrapper mw) + { + string signature = mw.Signature; + TypeWrapper[] newExceptionTypes = LoadTypes(loader, mw.GetDeclaredExceptions()); + TypeWrapper[] curExceptionTypes; + if (exceptions.TryGetValue(signature, out curExceptionTypes)) + { + exceptions[signature] = Merge(newExceptionTypes, curExceptionTypes); + } + else + { + exceptions.Add(signature, newExceptionTypes); + } + } + + private static TypeWrapper[] Merge(TypeWrapper[] newExceptionTypes, TypeWrapper[] curExceptionTypes) + { + List list = new List(); + foreach (TypeWrapper twNew in newExceptionTypes) + { + TypeWrapper match = null; + foreach (TypeWrapper twCur in curExceptionTypes) + { + if (twNew.IsAssignableTo(twCur)) + { + if (match == null || twCur.IsAssignableTo(match)) + { + match = twCur; + } + } + } + if (match != null && !list.Contains(match)) + { + list.Add(match); + } + } + return list.ToArray(); + } + + private static void CreateNoFail(CompilerClassLoader loader, TypeWrapper[] interfaces, List methods) + { + bool ispublic = true; + Type[] interfaceTypes = new Type[interfaces.Length]; + for (int i = 0; i < interfaceTypes.Length; i++) + { + ispublic &= interfaces[i].IsPublic; + interfaceTypes[i] = interfaces[i].TypeAsBaseType; + } + TypeAttributes attr = TypeAttributes.Class | TypeAttributes.Sealed; + attr |= ispublic ? TypeAttributes.NestedPublic : TypeAttributes.NestedAssembly; + DynamicClassLoader factory = (DynamicClassLoader)loader.GetTypeWrapperFactory(); + TypeBuilder tb = factory.DefineProxy(TypeNameUtil.GetProxyNestedName(interfaces), attr, proxyClass.TypeAsBaseType, interfaceTypes); + AttributeHelper.SetImplementsAttribute(tb, interfaces); + // we apply an InnerClass attribute to avoid the CompiledTypeWrapper heuristics for figuring out the modifiers + AttributeHelper.SetInnerClass(tb, null, ispublic ? Modifiers.Public | Modifiers.Final : Modifiers.Final); + CreateConstructor(tb); + for (int i = 0; i < methods.Count; i++) + { + methods[i].fb = tb.DefineField("m" + i, javaLangReflectMethod.TypeAsSignatureType, FieldAttributes.Private | FieldAttributes.Static); + } + foreach (ProxyMethod method in methods) + { + CreateMethod(loader, tb, method); + } + CreateStaticInitializer(tb, methods, loader); + } + + private static void CreateConstructor(TypeBuilder tb) + { + CodeEmitter ilgen = CodeEmitter.Create(ReflectUtil.DefineConstructor(tb, MethodAttributes.Public, new Type[] { invocationHandlerClass.TypeAsSignatureType })); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ldarg_1); + proxyConstructor.EmitCall(ilgen); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + + private static void CreateMethod(CompilerClassLoader loader, TypeBuilder tb, ProxyMethod pm) + { + MethodBuilder mb = pm.mw.GetDefineMethodHelper().DefineMethod(loader.GetTypeWrapperFactory(), tb, pm.mw.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final); + List exceptions = new List(); + foreach (TypeWrapper tw in pm.exceptions) + { + exceptions.Add(tw.Name); + } + AttributeHelper.SetThrowsAttribute(mb, exceptions.ToArray()); + CodeEmitter ilgen = CodeEmitter.Create(mb); + ilgen.BeginExceptionBlock(); + ilgen.Emit(OpCodes.Ldarg_0); + invocationHandlerField.EmitGet(ilgen); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ldsfld, pm.fb); + TypeWrapper[] parameters = pm.mw.GetParameters(); + if (parameters.Length == 0) + { + ilgen.Emit(OpCodes.Ldnull); + } + else + { + ilgen.EmitLdc_I4(parameters.Length); + ilgen.Emit(OpCodes.Newarr, Types.Object); + for (int i = 0; i < parameters.Length; i++) + { + ilgen.Emit(OpCodes.Dup); + ilgen.EmitLdc_I4(i); + ilgen.EmitLdarg(i); + if (parameters[i].IsNonPrimitiveValueType) + { + parameters[i].EmitBox(ilgen); + } + else if (parameters[i].IsPrimitive) + { + Boxer.EmitBox(ilgen, parameters[i]); + } + ilgen.Emit(OpCodes.Stelem_Ref); + } + } + invokeMethod.EmitCallvirt(ilgen); + TypeWrapper returnType = pm.mw.ReturnType; + CodeEmitterLocal returnValue = null; + if (returnType != PrimitiveTypeWrapper.VOID) + { + returnValue = ilgen.DeclareLocal(returnType.TypeAsSignatureType); + if (returnType.IsNonPrimitiveValueType) + { + returnType.EmitUnbox(ilgen); + } + else if (returnType.IsPrimitive) + { + Boxer.EmitUnbox(ilgen, returnType, true); + } + else if (returnType != CoreClasses.java.lang.Object.Wrapper) + { + ilgen.EmitCastclass(returnType.TypeAsSignatureType); + } + ilgen.Emit(OpCodes.Stloc, returnValue); + } + CodeEmitterLabel returnLabel = ilgen.DefineLabel(); + ilgen.EmitLeave(returnLabel); + // TODO consider using a filter here (but we would need to add filter support to CodeEmitter) + ilgen.BeginCatchBlock(Types.Exception); + ilgen.EmitLdc_I4(0); + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.mapException.MakeGenericMethod(Types.Exception)); + CodeEmitterLocal exception = ilgen.DeclareLocal(Types.Exception); + ilgen.Emit(OpCodes.Stloc, exception); + CodeEmitterLabel rethrow = ilgen.DefineLabel(); + ilgen.Emit(OpCodes.Ldloc, exception); + errorClass.EmitInstanceOf(ilgen); + ilgen.EmitBrtrue(rethrow); + ilgen.Emit(OpCodes.Ldloc, exception); + runtimeExceptionClass.EmitInstanceOf(ilgen); + ilgen.EmitBrtrue(rethrow); + foreach (TypeWrapper tw in pm.exceptions) + { + ilgen.Emit(OpCodes.Ldloc, exception); + tw.EmitInstanceOf(ilgen); + ilgen.EmitBrtrue(rethrow); + } + ilgen.Emit(OpCodes.Ldloc, exception); + undeclaredThrowableExceptionConstructor.EmitNewobj(ilgen); + ilgen.Emit(OpCodes.Throw); + ilgen.MarkLabel(rethrow); + ilgen.Emit(OpCodes.Rethrow); + ilgen.EndExceptionBlock(); + ilgen.MarkLabel(returnLabel); + if (returnValue != null) + { + ilgen.Emit(OpCodes.Ldloc, returnValue); + } + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + + private static void CreateStaticInitializer(TypeBuilder tb, List methods, CompilerClassLoader loader) + { + CodeEmitter ilgen = CodeEmitter.Create(ReflectUtil.DefineTypeInitializer(tb, loader)); + CodeEmitterLocal callerID = ilgen.DeclareLocal(CoreClasses.ikvm.@internal.CallerID.Wrapper.TypeAsSignatureType); + TypeBuilder tbCallerID = DynamicTypeWrapper.FinishContext.EmitCreateCallerID(tb, ilgen); + ilgen.Emit(OpCodes.Stloc, callerID); + // HACK we shouldn't create the nested type here (the outer type must be created first) + tbCallerID.CreateType(); + ilgen.BeginExceptionBlock(); + foreach (ProxyMethod method in methods) + { + method.mw.DeclaringType.EmitClassLiteral(ilgen); + ilgen.Emit(OpCodes.Ldstr, method.mw.Name); + TypeWrapper[] parameters = method.mw.GetParameters(); + ilgen.EmitLdc_I4(parameters.Length); + ilgen.Emit(OpCodes.Newarr, CoreClasses.java.lang.Class.Wrapper.TypeAsArrayType); + for (int i = 0; i < parameters.Length; i++) + { + ilgen.Emit(OpCodes.Dup); + ilgen.EmitLdc_I4(i); + parameters[i].EmitClassLiteral(ilgen); + ilgen.Emit(OpCodes.Stelem_Ref); + } + if (javaLangClass_getMethod.HasCallerID) + { + ilgen.Emit(OpCodes.Ldloc, callerID); + } + javaLangClass_getMethod.EmitCallvirt(ilgen); + ilgen.Emit(OpCodes.Stsfld, method.fb); + } + CodeEmitterLabel label = ilgen.DefineLabel(); + ilgen.EmitLeave(label); + ilgen.BeginCatchBlock(javaLangNoSuchMethodException.TypeAsExceptionType); + javaLangThrowable_getMessage.EmitCallvirt(ilgen); + javaLangNoClassDefFoundErrorConstructor.EmitNewobj(ilgen); + ilgen.Emit(OpCodes.Throw); + ilgen.EndExceptionBlock(); + ilgen.MarkLabel(label); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + + private sealed class ProxyMethod + { + internal readonly MethodWrapper mw; + internal readonly TypeWrapper[] exceptions; + internal FieldBuilder fb; + + internal ProxyMethod(MethodWrapper mw, TypeWrapper[] exceptions) + { + this.mw = mw; + this.exceptions = exceptions; + } + } + + private static IEnumerable GetInterfaceMethods(TypeWrapper tw) + { + Dictionary methods = new Dictionary(); + foreach (MethodWrapper mw in tw.GetMethods()) + { + if (mw.IsVirtual) + { + methods.Add(mw.Name + mw.Signature, mw); + } + } + foreach (TypeWrapper iface in tw.Interfaces) + { + foreach (MethodWrapper mw in GetInterfaceMethods(iface)) + { + if (!methods.ContainsKey(mw.Name + mw.Signature)) + { + methods.Add(mw.Name + mw.Signature, mw); + } + } + } + return methods.Values; + } + + private static TypeWrapper[] LoadTypes(ClassLoaderWrapper loader, string[] classes) + { + if (classes == null || classes.Length == 0) + { + return TypeWrapper.EmptyArray; + } + TypeWrapper[] tw = new TypeWrapper[classes.Length]; + for (int i = 0; i < tw.Length; i++) + { + tw[i] = loader.LoadClassByDottedName(classes[i]); + } + return tw; + } + + private sealed class ProxyException : Exception + { + internal ProxyException(string msg) + : base(msg) + { + } + } + } +} diff --git a/ikvmc/ikvmc.build b/ikvmc/ikvmc.build new file mode 100644 index 0000000..06dda99 --- /dev/null +++ b/ikvmc/ikvmc.build @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ikvmc/remapper.cs b/ikvmc/remapper.cs new file mode 100644 index 0000000..1993b3a --- /dev/null +++ b/ikvmc/remapper.cs @@ -0,0 +1,1833 @@ +/* + Copyright (C) 2002-2010 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +using System; +using System.Collections.Generic; +using System.Xml.Serialization; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; +using System.Diagnostics; +using IKVM.Attributes; +using IKVM.Internal; + +namespace IKVM.Internal.MapXml +{ + sealed class CodeGenContext + { + private ClassLoaderWrapper classLoader; + private readonly Dictionary h = new Dictionary(); + + internal CodeGenContext(ClassLoaderWrapper classLoader) + { + this.classLoader = classLoader; + } + + internal object this[string key] + { + get + { + object val; + h.TryGetValue(key, out val); + return val; + } + set { h[key] = value; } + } + + internal ClassLoaderWrapper ClassLoader { get { return classLoader; } } + } + + public abstract class Instruction + { + private int lineNumber = Root.LineNumber; + + internal int LineNumber + { + get + { + return lineNumber; + } + } + + internal abstract void Generate(CodeGenContext context, CodeEmitter ilgen); + + public override string ToString() + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + sb.Append('<'); + object[] attr = GetType().GetCustomAttributes(typeof(XmlTypeAttribute), false); + if (attr.Length == 1) + { + sb.Append(((XmlTypeAttribute)attr[0]).TypeName); + } + else + { + sb.Append(GetType().Name); + } + foreach (System.Reflection.FieldInfo field in GetType().GetFields()) + { + if (!field.IsStatic) + { + object value = field.GetValue(this); + if (value != null) + { + attr = field.GetCustomAttributes(typeof(XmlAttributeAttribute), false); + if (attr.Length == 1) + { + sb.AppendFormat(" {0}=\"{1}\"", ((XmlAttributeAttribute)attr[0]).AttributeName, value); + } + } + } + } + sb.Append(" />"); + return sb.ToString(); + } + } + + [XmlType("ldstr")] + public sealed class Ldstr : Instruction + { + [XmlAttribute("value")] + public string Value; + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Ldstr, Value); + } + } + + [XmlType("ldnull")] + public sealed class Ldnull : Simple + { + public Ldnull() : base(OpCodes.Ldnull) + { + } + } + + [XmlType("call")] + public class Call : Instruction + { + public Call() : this(OpCodes.Call) + { + } + + internal Call(OpCode opcode) + { + this.opcode = opcode; + } + + [XmlAttribute("class")] + public string Class; + [XmlAttribute("type")] + public string type; + [XmlAttribute("name")] + public string Name; + [XmlAttribute("sig")] + public string Sig; + + private OpCode opcode; + + internal sealed override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + Debug.Assert(Name != null); + if(Name == ".ctor") + { + Debug.Assert(Class == null && type != null); + Type[] argTypes = context.ClassLoader.ArgTypeListFromSig(Sig); + ConstructorInfo ci = StaticCompiler.GetTypeForMapXml(context.ClassLoader, type).GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, CallingConventions.Standard, argTypes, null); + if(ci == null) + { + throw new InvalidOperationException("Missing .ctor: " + type + "..ctor" + Sig); + } + ilgen.Emit(opcode, ci); + } + else + { + Debug.Assert(Class == null ^ type == null); + if(Class != null) + { + Debug.Assert(Sig != null); + MethodWrapper method = context.ClassLoader.LoadClassByDottedName(Class).GetMethodWrapper(Name, Sig, false); + if(method == null) + { + throw new InvalidOperationException("method not found: " + Class + "." + Name + Sig); + } + method.Link(); + // TODO this code is part of what Compiler.CastInterfaceArgs (in compiler.cs) does, + // it would be nice if we could avoid this duplication... + TypeWrapper[] argTypeWrappers = method.GetParameters(); + for(int i = 0; i < argTypeWrappers.Length; i++) + { + if(argTypeWrappers[i].IsGhost) + { + CodeEmitterLocal[] temps = new CodeEmitterLocal[argTypeWrappers.Length + (method.IsStatic ? 0 : 1)]; + for(int j = temps.Length - 1; j >= 0; j--) + { + TypeWrapper tw; + if(method.IsStatic) + { + tw = argTypeWrappers[j]; + } + else + { + if(j == 0) + { + tw = method.DeclaringType; + } + else + { + tw = argTypeWrappers[j - 1]; + } + } + if(tw.IsGhost) + { + tw.EmitConvStackTypeToSignatureType(ilgen, null); + } + temps[j] = ilgen.DeclareLocal(tw.TypeAsSignatureType); + ilgen.Emit(OpCodes.Stloc, temps[j]); + } + for(int j = 0; j < temps.Length; j++) + { + ilgen.Emit(OpCodes.Ldloc, temps[j]); + } + break; + } + } + if(opcode.Value == OpCodes.Call.Value) + { + method.EmitCall(ilgen); + } + else if(opcode.Value == OpCodes.Callvirt.Value) + { + method.EmitCallvirt(ilgen); + } + else if(opcode.Value == OpCodes.Newobj.Value) + { + method.EmitNewobj(ilgen); + } + else + { + // ldftn or ldvirtftn + ilgen.Emit(opcode, (MethodInfo)method.GetMethod()); + } + } + else + { + Type[] argTypes; + if(Sig.StartsWith("(")) + { + argTypes = context.ClassLoader.ArgTypeListFromSig(Sig); + } + else if(Sig == "") + { + argTypes = Type.EmptyTypes; + } + else + { + string[] types = Sig.Split(';'); + argTypes = new Type[types.Length]; + for(int i = 0; i < types.Length; i++) + { + argTypes[i] = StaticCompiler.GetTypeForMapXml(context.ClassLoader, types[i]); + } + } + MethodInfo mi = StaticCompiler.GetTypeForMapXml(context.ClassLoader, type).GetMethod(Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, null, argTypes, null); + if(mi == null) + { + throw new InvalidOperationException("Missing method: " + type + "." + Name + Sig); + } + ilgen.Emit(opcode, mi); + } + } + } + } + + [XmlType("callvirt")] + public sealed class Callvirt : Call + { + public Callvirt() : base(OpCodes.Callvirt) + { + } + } + + [XmlType("newobj")] + public sealed class NewObj : Call + { + public NewObj() : base(OpCodes.Newobj) + { + } + } + + [XmlType("ldftn")] + public sealed class Ldftn : Call + { + public Ldftn() : base(OpCodes.Ldftn) + { + } + } + + [XmlType("ldvirtftn")] + public sealed class Ldvirtftn : Call + { + public Ldvirtftn() : base(OpCodes.Ldvirtftn) + { + } + } + + public abstract class Simple : Instruction + { + private OpCode opcode; + + public Simple(OpCode opcode) + { + this.opcode = opcode; + } + + internal sealed override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + ilgen.Emit(opcode); + } + } + + [XmlType("dup")] + public sealed class Dup : Simple + { + public Dup() : base(OpCodes.Dup) + { + } + } + + [XmlType("pop")] + public sealed class Pop : Instruction + { + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Pop); + } + } + + public abstract class TypeOrTypeWrapperInstruction : Instruction + { + [XmlAttribute("class")] + public string Class; + [XmlAttribute("type")] + public string type; + + internal TypeWrapper typeWrapper; + internal Type typeType; + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + if(typeWrapper == null && typeType == null) + { + Debug.Assert(Class == null ^ type == null); + if(Class != null) + { + typeWrapper = context.ClassLoader.LoadClassByDottedName(Class); + } + else + { + typeType = StaticCompiler.GetTypeForMapXml(context.ClassLoader, type); + } + } + } + } + + [XmlType("isinst")] + public sealed class IsInst : TypeOrTypeWrapperInstruction + { + public IsInst() + { + } + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + base.Generate(context, ilgen); + if(typeType != null) + { + ilgen.Emit(OpCodes.Isinst, typeType); + } + else + { + if(typeWrapper.IsGhost || typeWrapper.IsGhostArray) + { + ilgen.Emit(OpCodes.Dup); + typeWrapper.EmitInstanceOf(ilgen); + CodeEmitterLabel endLabel = ilgen.DefineLabel(); + ilgen.EmitBrtrue(endLabel); + ilgen.Emit(OpCodes.Pop); + ilgen.Emit(OpCodes.Ldnull); + ilgen.MarkLabel(endLabel); + } + else + { + ilgen.Emit(OpCodes.Isinst, typeWrapper.TypeAsTBD); + } + } + } + } + + [XmlType("castclass")] + public sealed class Castclass : TypeOrTypeWrapperInstruction + { + public Castclass() + { + } + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + base.Generate(context, ilgen); + if(typeType != null) + { + ilgen.Emit(OpCodes.Castclass, typeType); + } + else + { + typeWrapper.EmitCheckcast(ilgen); + } + } + } + + [XmlType("castclass_impl")] + public sealed class Castclass_impl : Instruction + { + [XmlAttribute("class")] + public string Class; + + public Castclass_impl() + { + } + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Castclass, context.ClassLoader.LoadClassByDottedName(Class).TypeAsBaseType); + } + } + + public abstract class TypeInstruction : Instruction + { + [XmlAttribute("type")] + public string type; + + private OpCode opcode; + private Type typeType; + + internal TypeInstruction(OpCode opcode) + { + this.opcode = opcode; + } + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + if(typeType == null) + { + Debug.Assert(type != null); + typeType = StaticCompiler.GetTypeForMapXml(context.ClassLoader, type); + } + ilgen.Emit(opcode, typeType); + } + } + + [XmlType("ldobj")] + public sealed class Ldobj : TypeInstruction + { + public Ldobj() : base(OpCodes.Ldobj) + { + } + } + + [XmlType("unbox")] + public sealed class Unbox : TypeInstruction + { + public Unbox() : base(OpCodes.Unbox) + { + } + } + + [XmlType("box")] + public sealed class Box : TypeInstruction + { + public Box() : base(OpCodes.Box) + { + } + } + + public abstract class Branch : Instruction + { + internal sealed override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + CodeEmitterLabel l; + if(context[Name] == null) + { + l = ilgen.DefineLabel(); + context[Name] = l; + } + else + { + l = (CodeEmitterLabel)context[Name]; + } + Emit(ilgen, l); + } + + internal abstract void Emit(CodeEmitter ilgen, CodeEmitterLabel label); + + [XmlAttribute("name")] + public string Name; + } + + [XmlType("brfalse")] + public sealed class BrFalse : Branch + { + internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label) + { + ilgen.EmitBrfalse(label); + } + } + + [XmlType("brtrue")] + public sealed class BrTrue : Branch + { + internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label) + { + ilgen.EmitBrtrue(label); + } + } + + [XmlType("br")] + public sealed class Br : Branch + { + internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label) + { + ilgen.EmitBr(label); + } + } + + [XmlType("beq")] + public sealed class Beq : Branch + { + internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label) + { + ilgen.EmitBeq(label); + } + } + + [XmlType("bne_un")] + public sealed class Bne_Un : Branch + { + internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label) + { + ilgen.EmitBne_Un(label); + } + } + + [XmlType("bge_un")] + public sealed class Bge_Un : Branch + { + internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label) + { + ilgen.EmitBge_Un(label); + } + } + + [XmlType("ble_un")] + public sealed class Ble_Un : Branch + { + internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label) + { + ilgen.EmitBle_Un(label); + } + } + + [XmlType("blt")] + public sealed class Blt : Branch + { + internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label) + { + ilgen.EmitBlt(label); + } + } + + [XmlType("blt_un")] + public sealed class Blt_Un : Branch + { + internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label) + { + ilgen.EmitBlt_Un(label); + } + } + + [XmlType("label")] + public sealed class BrLabel : Instruction + { + [XmlAttribute("name")] + public string Name; + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + CodeEmitterLabel l; + if(context[Name] == null) + { + l = ilgen.DefineLabel(); + context[Name] = l; + } + else + { + l = (CodeEmitterLabel)context[Name]; + } + ilgen.MarkLabel(l); + } + } + + [XmlType("stloc")] + public sealed class StLoc : Instruction + { + [XmlAttribute("name")] + public string Name; + [XmlAttribute("class")] + public string Class; + [XmlAttribute("type")] + public string type; + + private TypeWrapper typeWrapper; + private Type typeType; + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + CodeEmitterLocal lb = (CodeEmitterLocal)context[Name]; + if(lb == null) + { + if(typeWrapper == null && typeType == null) + { + Debug.Assert(Class == null ^ type == null); + if(type != null) + { + typeType = StaticCompiler.GetTypeForMapXml(context.ClassLoader, type); + } + else + { + typeWrapper = context.ClassLoader.LoadClassByDottedName(Class); + } + } + lb = ilgen.DeclareLocal(typeType != null ? typeType : typeWrapper.TypeAsTBD); + context[Name] = lb; + } + ilgen.Emit(OpCodes.Stloc, lb); + } + } + + [XmlType("ldloc")] + public sealed class LdLoc : Instruction + { + [XmlAttribute("name")] + public string Name; + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Ldloc, (CodeEmitterLocal)context[Name]); + } + } + + [XmlType("ldarga")] + public sealed class LdArga : Instruction + { + [XmlAttribute("argNum")] + public ushort ArgNum; + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + ilgen.EmitLdarga(ArgNum); + } + } + + [XmlType("ldarg_s")] + public sealed class LdArg_S : Instruction + { + [XmlAttribute("argNum")] + public byte ArgNum; + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + ilgen.EmitLdarg(ArgNum); + } + } + + [XmlType("ldarg_0")] + public sealed class LdArg_0 : Simple + { + public LdArg_0() : base(OpCodes.Ldarg_0) + { + } + } + + [XmlType("ldarg_1")] + public sealed class LdArg_1 : Simple + { + public LdArg_1() : base(OpCodes.Ldarg_1) + { + } + } + + [XmlType("ldarg_2")] + public sealed class LdArg_2 : Simple + { + public LdArg_2() : base(OpCodes.Ldarg_2) + { + } + } + + [XmlType("ldarg_3")] + public sealed class LdArg_3 : Simple + { + public LdArg_3() : base(OpCodes.Ldarg_3) + { + } + } + + [XmlType("ldind_i1")] + public sealed class Ldind_i1 : Simple + { + public Ldind_i1() : base(OpCodes.Ldind_I1) + { + } + } + + [XmlType("ldind_i2")] + public sealed class Ldind_i2 : Simple + { + public Ldind_i2() : base(OpCodes.Ldind_I2) + { + } + } + + [XmlType("ldind_i4")] + public sealed class Ldind_i4 : Simple + { + public Ldind_i4() : base(OpCodes.Ldind_I4) + { + } + } + + [XmlType("ldind_i8")] + public sealed class Ldind_i8 : Simple + { + public Ldind_i8() : base(OpCodes.Ldind_I8) + { + } + } + + [XmlType("ldind_r4")] + public sealed class Ldind_r4 : Simple + { + public Ldind_r4() : base(OpCodes.Ldind_R4) + { + } + } + + [XmlType("ldind_r8")] + public sealed class Ldind_r8 : Simple + { + public Ldind_r8() : base(OpCodes.Ldind_R8) + { + } + } + + [XmlType("ldind_ref")] + public sealed class Ldind_ref : Simple + { + public Ldind_ref() : base(OpCodes.Ldind_Ref) + { + } + } + + [XmlType("stind_i1")] + public sealed class Stind_i1 : Simple + { + public Stind_i1() : base(OpCodes.Stind_I1) + { + } + } + + [XmlType("stind_i2")] + public sealed class Stind_i2 : Simple + { + public Stind_i2() : base(OpCodes.Stind_I2) + { + } + } + + [XmlType("stind_i4")] + public sealed class Stind_i4 : Simple + { + public Stind_i4() : base(OpCodes.Stind_I4) + { + } + } + + [XmlType("stind_i8")] + public sealed class Stind_i8 : Simple + { + public Stind_i8() + : base(OpCodes.Stind_I8) + { + } + } + + [XmlType("stind_ref")] + public sealed class Stind_ref : Simple + { + public Stind_ref() : base(OpCodes.Stind_Ref) + { + } + } + + [XmlType("ret")] + public sealed class Ret : Simple + { + public Ret() : base(OpCodes.Ret) + { + } + } + + [XmlType("throw")] + public sealed class Throw : Simple + { + public Throw() : base(OpCodes.Throw) + { + } + } + + [XmlType("ldflda")] + public sealed class Ldflda : Instruction + { + [XmlAttribute("class")] + public string Class; + [XmlAttribute("name")] + public string Name; + [XmlAttribute("sig")] + public string Sig; + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Ldflda, StaticCompiler.GetFieldForMapXml(context.ClassLoader, Class, Name, Sig).GetField()); + } + } + + [XmlType("ldfld")] + public sealed class Ldfld : Instruction + { + [XmlAttribute("class")] + public string Class; + [XmlAttribute("name")] + public string Name; + [XmlAttribute("sig")] + public string Sig; + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + // we don't use fw.EmitGet because we don't want automatic unboxing and whatever + ilgen.Emit(OpCodes.Ldfld, StaticCompiler.GetFieldForMapXml(context.ClassLoader, Class, Name, Sig).GetField()); + } + } + + [XmlType("ldsfld")] + public sealed class Ldsfld : Instruction + { + [XmlAttribute("class")] + public string Class; + [XmlAttribute("type")] + public string Type; + [XmlAttribute("name")] + public string Name; + [XmlAttribute("sig")] + public string Sig; + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + if(Type != null) + { + ilgen.Emit(OpCodes.Ldsfld, StaticCompiler.GetTypeForMapXml(context.ClassLoader, Type).GetField(Name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)); + } + else + { + // we don't use fw.EmitGet because we don't want automatic unboxing and whatever + ilgen.Emit(OpCodes.Ldsfld, StaticCompiler.GetFieldForMapXml(context.ClassLoader, Class, Name, Sig).GetField()); + } + } + } + + [XmlType("stfld")] + public sealed class Stfld : Instruction + { + [XmlAttribute("class")] + public string Class; + [XmlAttribute("name")] + public string Name; + [XmlAttribute("sig")] + public string Sig; + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + // we don't use fw.EmitSet because we don't want automatic unboxing and whatever + ilgen.Emit(OpCodes.Stfld, StaticCompiler.GetFieldForMapXml(context.ClassLoader, Class, Name, Sig).GetField()); + } + } + + [XmlType("stsfld")] + public sealed class Stsfld : Instruction + { + [XmlAttribute("class")] + public string Class; + [XmlAttribute("name")] + public string Name; + [XmlAttribute("sig")] + public string Sig; + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + // we don't use fw.EmitSet because we don't want automatic unboxing and whatever + ilgen.Emit(OpCodes.Stsfld, StaticCompiler.GetFieldForMapXml(context.ClassLoader, Class, Name, Sig).GetField()); + } + } + + [XmlType("ldc_i4")] + public sealed class Ldc_I4 : Instruction + { + [XmlAttribute("value")] + public int val; + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + ilgen.EmitLdc_I4(val); + } + } + + [XmlType("ldc_i4_0")] + public sealed class Ldc_I4_0 : Simple + { + public Ldc_I4_0() : base(OpCodes.Ldc_I4_0) + { + } + } + + [XmlType("ldc_i4_1")] + public sealed class Ldc_I4_1 : Simple + { + public Ldc_I4_1() : base(OpCodes.Ldc_I4_1) + { + } + } + + [XmlType("ldc_i4_m1")] + public sealed class Ldc_I4_M1 : Simple + { + public Ldc_I4_M1() : base(OpCodes.Ldc_I4_M1) + { + } + } + + [XmlType("conv_i")] + public sealed class Conv_I : Simple + { + public Conv_I() : base(OpCodes.Conv_I) + { + } + } + + [XmlType("conv_i1")] + public sealed class Conv_I1 : Simple + { + public Conv_I1() : base(OpCodes.Conv_I1) + { + } + } + + [XmlType("conv_u1")] + public sealed class Conv_U1 : Simple + { + public Conv_U1() : base(OpCodes.Conv_U1) + { + } + } + + [XmlType("conv_i2")] + public sealed class Conv_I2 : Simple + { + public Conv_I2() : base(OpCodes.Conv_I2) + { + } + } + + [XmlType("conv_u2")] + public sealed class Conv_U2 : Simple + { + public Conv_U2() : base(OpCodes.Conv_U2) + { + } + } + + [XmlType("conv_i4")] + public sealed class Conv_I4 : Simple + { + public Conv_I4() : base(OpCodes.Conv_I4) + { + } + } + + [XmlType("conv_u4")] + public sealed class Conv_U4 : Simple + { + public Conv_U4() : base(OpCodes.Conv_U4) + { + } + } + + [XmlType("conv_i8")] + public sealed class Conv_I8 : Simple + { + public Conv_I8() : base(OpCodes.Conv_I8) + { + } + } + + [XmlType("conv_u8")] + public sealed class Conv_U8 : Simple + { + public Conv_U8() : base(OpCodes.Conv_U8) + { + } + } + + [XmlType("ldlen")] + public sealed class Ldlen : Simple + { + public Ldlen() : base(OpCodes.Ldlen) + { + } + } + + [XmlType("add")] + public sealed class Add : Simple + { + public Add() : base(OpCodes.Add) + { + } + } + + [XmlType("sub")] + public sealed class Sub : Simple + { + public Sub() + : base(OpCodes.Sub) + { + } + } + + [XmlType("mul")] + public sealed class Mul : Simple + { + public Mul() : base(OpCodes.Mul) + { + } + } + + [XmlType("div_un")] + public sealed class Div_Un : Simple + { + public Div_Un() + : base(OpCodes.Div_Un) + { + } + } + + [XmlType("rem_un")] + public sealed class Rem_Un : Simple + { + public Rem_Un() + : base(OpCodes.Rem_Un) + { + } + } + + [XmlType("and")] + public sealed class And : Simple + { + public And() + : base(OpCodes.And) + { + } + } + + [XmlType("or")] + public sealed class Or : Simple + { + public Or() + : base(OpCodes.Or) + { + } + } + + [XmlType("xor")] + public sealed class Xor : Simple + { + public Xor() + : base(OpCodes.Xor) + { + } + } + + [XmlType("not")] + public sealed class Not : Simple + { + public Not() + : base(OpCodes.Not) + { + } + } + + [XmlType("unaligned")] + public sealed class Unaligned : Instruction + { + [XmlAttribute("alignment")] + public int Alignment; + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + ilgen.EmitUnaligned((byte)Alignment); + } + } + + [XmlType("cpblk")] + public sealed class Cpblk : Simple + { + public Cpblk() : base(OpCodes.Cpblk) + { + } + } + + [XmlType("ceq")] + public sealed class Ceq : Simple + { + public Ceq() : base(OpCodes.Ceq) + { + } + } + + [XmlType("leave")] + public sealed class Leave : Branch + { + internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label) + { + ilgen.EmitLeave(label); + } + } + + [XmlType("endfinally")] + public sealed class Endfinally : Simple + { + public Endfinally() : base(OpCodes.Endfinally) + { + } + } + + [XmlType("exceptionBlock")] + public sealed class ExceptionBlock : Instruction + { + public InstructionList @try; + public CatchBlock @catch; + public InstructionList @finally; + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + ilgen.BeginExceptionBlock(); + @try.Generate(context, ilgen); + if(@catch != null) + { + Type type; + if(@catch.type != null) + { + type = StaticCompiler.GetTypeForMapXml(context.ClassLoader, @catch.type); + } + else + { + type = context.ClassLoader.LoadClassByDottedName(@catch.Class).TypeAsExceptionType; + } + ilgen.BeginCatchBlock(type); + @catch.Generate(context, ilgen); + } + if(@finally != null) + { + ilgen.BeginFinallyBlock(); + @finally.Generate(context, ilgen); + } + ilgen.EndExceptionBlock(); + } + } + + public sealed class CatchBlock : InstructionList + { + [XmlAttribute("type")] + public string type; + [XmlAttribute("class")] + public string Class; + } + + [XmlType("conditional")] + public sealed class ConditionalInstruction : Instruction + { + [XmlAttribute("framework")] + public string framework; + public InstructionList code; + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + if (Environment.Version.ToString().StartsWith(framework)) + { + code.Generate(context, ilgen); + } + } + } + + [XmlType("volatile")] + public sealed class Volatile : Simple + { + public Volatile() : base(OpCodes.Volatile) + { + } + } + + [XmlType("ldelema")] + public sealed class Ldelema : Instruction + { + [XmlAttribute("sig")] + public string Sig; + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Ldelema, context.ClassLoader.FieldTypeWrapperFromSig(Sig, LoadMode.LoadOrThrow).TypeAsArrayType); + } + } + + [XmlType("newarr")] + public sealed class Newarr : Instruction + { + [XmlAttribute("sig")] + public string Sig; + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Newarr, context.ClassLoader.FieldTypeWrapperFromSig(Sig, LoadMode.LoadOrThrow).TypeAsArrayType); + } + } + + [XmlType("ldtoken")] + public sealed class Ldtoken : Instruction + { + [XmlAttribute("type")] + public string type; + [XmlAttribute("class")] + public string Class; + [XmlAttribute("method")] + public string Method; + [XmlAttribute("field")] + public string Field; + [XmlAttribute("sig")] + public string Sig; + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + if (!Validate()) + { + return; + } + + MemberInfo member = Resolve(context); + Type type = member as Type; + MethodInfo method = member as MethodInfo; + ConstructorInfo constructor = member as ConstructorInfo; + FieldInfo field = member as FieldInfo; + + if (type != null) + { + ilgen.Emit(OpCodes.Ldtoken, type); + } + else if (method != null) + { + ilgen.Emit(OpCodes.Ldtoken, method); + } + else if (constructor != null) + { + ilgen.Emit(OpCodes.Ldtoken, constructor); + } + else if (field != null) + { + ilgen.Emit(OpCodes.Ldtoken, field); + } + else + { + StaticCompiler.IssueMessage(Message.MapXmlUnableToResolveOpCode, ToString()); + } + } + + private bool Validate() + { + if (type != null && Class == null) + { + if (Method != null || Field != null || Sig != null) + { + StaticCompiler.IssueMessage(Message.MapXmlError, "not implemented: cannot use 'type' attribute with 'method' or 'field' attribute for ldtoken"); + return false; + } + return true; + } + else if (Class != null && type == null) + { + if (Method == null && Field == null) + { + if (Sig != null) + { + StaticCompiler.IssueMessage(Message.MapXmlError, "cannot specify 'sig' attribute without either 'method' or 'field' attribute for ldtoken"); + } + return true; + } + if (Method != null && Field != null) + { + StaticCompiler.IssueMessage(Message.MapXmlError, "cannot specify both 'method' and 'field' attribute for ldtoken"); + return false; + } + return true; + } + else + { + StaticCompiler.IssueMessage(Message.MapXmlError, "must specify either 'type' or 'class' attribute for ldtoken"); + return false; + } + } + + private MemberInfo Resolve(CodeGenContext context) + { + if (type != null) + { + if (Class != null || Method != null || Field != null || Sig != null) + { + throw new NotImplementedException(); + } + return StaticCompiler.GetTypeForMapXml(context.ClassLoader, type); + } + else if (Class != null) + { + TypeWrapper tw = context.ClassLoader.LoadClassByDottedNameFast(Class); + if (tw == null) + { + return null; + } + else if (Method != null) + { + MethodWrapper mw = tw.GetMethodWrapper(Method, Sig, false); + if (mw == null) + { + return null; + } + return mw.GetMethod(); + } + else if (Field != null) + { + FieldWrapper fw = tw.GetFieldWrapper(Field, Sig); + if (fw == null) + { + return null; + } + return fw.GetField(); + } + else + { + return tw.TypeAsBaseType; + } + } + else + { + return null; + } + } + } + + [XmlType("runclassinit")] + public sealed class RunClassInit : Instruction + { + [XmlAttribute("class")] + public string Class; + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + context.ClassLoader.LoadClassByDottedName(Class).EmitRunClassConstructor(ilgen); + } + } + + [XmlType("exceptionMapping")] + public sealed class EmitExceptionMapping : Instruction + { + internal ExceptionMapping[] mapping; + + internal override void Generate(CodeGenContext context, CodeEmitter ilgen) + { + CompilerClassLoader.ExceptionMapEmitter emitter = new CompilerClassLoader.ExceptionMapEmitter(mapping); + emitter.Emit(context, ilgen); + } + } + + public class InstructionList + { + [XmlElement(typeof(Ldstr))] + [XmlElement(typeof(Call))] + [XmlElement(typeof(Callvirt))] + [XmlElement(typeof(Ldftn))] + [XmlElement(typeof(Ldvirtftn))] + [XmlElement(typeof(Dup))] + [XmlElement(typeof(Pop))] + [XmlElement(typeof(IsInst))] + [XmlElement(typeof(Castclass))] + [XmlElement(typeof(Castclass_impl))] + [XmlElement(typeof(Ldobj))] + [XmlElement(typeof(Unbox))] + [XmlElement(typeof(Box))] + [XmlElement(typeof(BrFalse))] + [XmlElement(typeof(BrTrue))] + [XmlElement(typeof(Br))] + [XmlElement(typeof(Beq))] + [XmlElement(typeof(Bne_Un))] + [XmlElement(typeof(Bge_Un))] + [XmlElement(typeof(Ble_Un))] + [XmlElement(typeof(Blt))] + [XmlElement(typeof(Blt_Un))] + [XmlElement(typeof(BrLabel))] + [XmlElement(typeof(NewObj))] + [XmlElement(typeof(StLoc))] + [XmlElement(typeof(LdLoc))] + [XmlElement(typeof(LdArga))] + [XmlElement(typeof(LdArg_S))] + [XmlElement(typeof(LdArg_0))] + [XmlElement(typeof(LdArg_1))] + [XmlElement(typeof(LdArg_2))] + [XmlElement(typeof(LdArg_3))] + [XmlElement(typeof(Ldind_i1))] + [XmlElement(typeof(Ldind_i2))] + [XmlElement(typeof(Ldind_i4))] + [XmlElement(typeof(Ldind_i8))] + [XmlElement(typeof(Ldind_r4))] + [XmlElement(typeof(Ldind_r8))] + [XmlElement(typeof(Ldind_ref))] + [XmlElement(typeof(Stind_i1))] + [XmlElement(typeof(Stind_i2))] + [XmlElement(typeof(Stind_i4))] + [XmlElement(typeof(Stind_i8))] + [XmlElement(typeof(Stind_ref))] + [XmlElement(typeof(Ret))] + [XmlElement(typeof(Throw))] + [XmlElement(typeof(Ldnull))] + [XmlElement(typeof(Ldflda))] + [XmlElement(typeof(Ldfld))] + [XmlElement(typeof(Ldsfld))] + [XmlElement(typeof(Stfld))] + [XmlElement(typeof(Stsfld))] + [XmlElement(typeof(Ldc_I4))] + [XmlElement(typeof(Ldc_I4_0))] + [XmlElement(typeof(Ldc_I4_1))] + [XmlElement(typeof(Ldc_I4_M1))] + [XmlElement(typeof(Conv_I))] + [XmlElement(typeof(Conv_I1))] + [XmlElement(typeof(Conv_U1))] + [XmlElement(typeof(Conv_I2))] + [XmlElement(typeof(Conv_U2))] + [XmlElement(typeof(Conv_I4))] + [XmlElement(typeof(Conv_U4))] + [XmlElement(typeof(Conv_I8))] + [XmlElement(typeof(Conv_U8))] + [XmlElement(typeof(Ldlen))] + [XmlElement(typeof(ExceptionBlock))] + [XmlElement(typeof(Add))] + [XmlElement(typeof(Sub))] + [XmlElement(typeof(Mul))] + [XmlElement(typeof(Div_Un))] + [XmlElement(typeof(Rem_Un))] + [XmlElement(typeof(And))] + [XmlElement(typeof(Or))] + [XmlElement(typeof(Xor))] + [XmlElement(typeof(Not))] + [XmlElement(typeof(Unaligned))] + [XmlElement(typeof(Cpblk))] + [XmlElement(typeof(Ceq))] + [XmlElement(typeof(ConditionalInstruction))] + [XmlElement(typeof(Volatile))] + [XmlElement(typeof(Ldelema))] + [XmlElement(typeof(Newarr))] + [XmlElement(typeof(Ldtoken))] + [XmlElement(typeof(Leave))] + [XmlElement(typeof(Endfinally))] + [XmlElement(typeof(RunClassInit))] + [XmlElement(typeof(EmitExceptionMapping))] + public Instruction[] invoke; + + internal void Generate(CodeGenContext context, CodeEmitter ilgen) + { + if(invoke != null) + { + for(int i = 0; i < invoke.Length; i++) + { + if(invoke[i].LineNumber != -1) + { + ilgen.SetLineNumber((ushort)invoke[i].LineNumber); + } + invoke[i].Generate(context, ilgen); + } + } + } + + internal void Emit(ClassLoaderWrapper loader, CodeEmitter ilgen) + { + Generate(new CodeGenContext(loader), ilgen); + } + } + + public sealed class Throws + { + [XmlAttribute("class")] + public string Class; + } + + public sealed class Redirect + { + private int linenum = Root.LineNumber; + + internal int LineNumber + { + get + { + return linenum; + } + } + + [XmlAttribute("class")] + public string Class; + [XmlAttribute("name")] + public string Name; + [XmlAttribute("sig")] + public string Sig; + [XmlAttribute("type")] + public string Type; + + internal void Emit(ClassLoaderWrapper loader, CodeEmitter ilgen) + { + if(Type != "static" || Class == null || Name == null || Sig == null) + { + throw new NotImplementedException(); + } + Type[] redirParamTypes = loader.ArgTypeListFromSig(Sig); + for(int i = 0; i < redirParamTypes.Length; i++) + { + ilgen.EmitLdarg(i); + } + // HACK if the class name contains a comma, we assume it is a .NET type + if(Class.IndexOf(',') >= 0) + { + Type type = StaticCompiler.Universe.GetType(Class, true); + MethodInfo mi = type.GetMethod(Name, redirParamTypes); + if(mi == null) + { + throw new InvalidOperationException(); + } + ilgen.Emit(OpCodes.Call, mi); + } + else + { + TypeWrapper tw = loader.LoadClassByDottedName(Class); + MethodWrapper mw = tw.GetMethodWrapper(Name, Sig, false); + if(mw == null) + { + throw new InvalidOperationException(); + } + mw.Link(); + mw.EmitCall(ilgen); + } + // TODO we may need a cast here (or a stack to return type conversion) + ilgen.Emit(OpCodes.Ret); + } + } + + public sealed class Override + { + [XmlAttribute("class")] + public string Class; + [XmlAttribute("name")] + public string Name; + } + + public sealed class ReplaceMethodCall + { + [XmlAttribute("class")] + public string Class; + [XmlAttribute("name")] + public string Name; + [XmlAttribute("sig")] + public string Sig; + public InstructionList code; + } + + public abstract class MethodBase + { + [XmlAttribute("attributes")] + public MethodAttributes MethodAttributes; + public InstructionList body; + [XmlElement("throws", typeof(Throws))] + public Throws[] throws; + [XmlElement("attribute")] + public Attribute[] Attributes; + [XmlElement("replace-method-call")] + public ReplaceMethodCall[] ReplaceMethodCalls; + public InstructionList prologue; + + internal abstract MethodKey ToMethodKey(string className); + } + + public abstract class MethodConstructorBase : MethodBase + { + [XmlAttribute("sig")] + public string Sig; + [XmlAttribute("modifiers")] + public MapModifiers Modifiers; + [XmlElement("parameter")] + public Param[] Params; + public InstructionList alternateBody; + public Redirect redirect; + + internal void Emit(ClassLoaderWrapper loader, CodeEmitter ilgen) + { + if(prologue != null) + { + prologue.Emit(loader, ilgen); + } + if(redirect != null) + { + redirect.Emit(loader, ilgen); + } + else + { + body.Emit(loader, ilgen); + } + } + } + + public sealed class Method : MethodConstructorBase + { + [XmlAttribute("name")] + public string Name; + [XmlAttribute("nonullcheck")] + public bool NoNullCheck; + public InstructionList nonvirtualAlternateBody; + public Override @override; + + internal override MethodKey ToMethodKey(string className) + { + return new MethodKey(className, Name, Sig); + } + } + + public sealed class Constructor : MethodConstructorBase + { + internal override MethodKey ToMethodKey(string className) + { + return new MethodKey(className, StringConstants.INIT, Sig); + } + } + + public sealed class ClassInitializer : MethodBase + { + internal override MethodKey ToMethodKey(string className) + { + return new MethodKey(className, StringConstants.CLINIT, StringConstants.SIG_VOID); + } + } + + public sealed class Field + { + [XmlAttribute("name")] + public string Name; + [XmlAttribute("sig")] + public string Sig; + [XmlAttribute("modifiers")] + public MapModifiers Modifiers; + [XmlAttribute("constant")] + public string Constant; + [XmlElement("attribute")] + public Attribute[] Attributes; + } + + public sealed class Property + { + [XmlAttribute("name")] + public string Name; + [XmlAttribute("sig")] + public string Sig; + public Method getter; + public Method setter; + [XmlElement("attribute")] + public Attribute[] Attributes; + } + + public sealed class Interface + { + [XmlAttribute("class")] + public string Name; + [XmlElement("method")] + public Method[] Methods; + } + + [Flags] + public enum MapModifiers + { + [XmlEnum("public")] + Public = Modifiers.Public, + [XmlEnum("protected")] + Protected = Modifiers.Protected, + [XmlEnum("private")] + Private = Modifiers.Private, + [XmlEnum("final")] + Final = Modifiers.Final, + [XmlEnum("interface")] + Interface = Modifiers.Interface, + [XmlEnum("static")] + Static = Modifiers.Static, + [XmlEnum("abstract")] + Abstract = Modifiers.Abstract, + [XmlEnum("ACC_BRIDGE")] + Bridge = Modifiers.Bridge, + [XmlEnum("ACC_SYNTHETIC")] + Synthetic = Modifiers.Synthetic, + } + + public enum Scope + { + [XmlEnum("public")] + Public = 0, + [XmlEnum("private")] + Private = 1 + } + + public sealed class Element + { + [XmlText] + public string Value; + } + + public sealed class Param + { + [XmlText] + public string Value; + [XmlAttribute("name")] + public string Name; + [XmlAttribute("sig")] + public string Sig; // optional (for object type args) + [XmlElement("element")] + public Element[] Elements; + [XmlElement("attribute")] + public Attribute[] Attributes; + } + + public sealed class Attribute + { + [XmlAttribute("type")] + public string Type; + [XmlAttribute("class")] + public string Class; + [XmlAttribute("sig")] + public string Sig; + [XmlElement("parameter")] + public Param[] Params; + [XmlElement("property")] + public Param[] Properties; + [XmlElement("field")] + public Param[] Fields; + } + + [XmlType("class")] + public sealed class Class + { + [XmlAttribute("name")] + public string Name; + [XmlAttribute("shadows")] + public string Shadows; + [XmlAttribute("modifiers")] + public MapModifiers Modifiers; + [XmlAttribute("scope")] + public Scope scope; + [XmlElement("constructor")] + public Constructor[] Constructors; + [XmlElement("method")] + public Method[] Methods; + [XmlElement("field")] + public Field[] Fields; + [XmlElement("property")] + public Property[] Properties; + [XmlElement("implements")] + public Interface[] Interfaces; + [XmlElement("clinit")] + public ClassInitializer Clinit; + [XmlElement("attribute")] + public Attribute[] Attributes; + } + + public sealed class Assembly + { + [XmlElement("class")] + public Class[] Classes; + [XmlElement("attribute")] + public Attribute[] Attributes; + } + + [XmlType("exception")] + public sealed class ExceptionMapping + { + [XmlAttribute] + public string src; + [XmlAttribute] + public string dst; + public InstructionList code; + } + + [XmlRoot("root")] + public sealed class Root + { + internal static System.Xml.XmlTextReader xmlReader; + + internal static int LineNumber + { + get + { + return xmlReader == null ? -1: xmlReader.LineNumber; + } + } + + [XmlElement("assembly")] + public Assembly assembly; + public ExceptionMapping[] exceptionMappings; + } +} diff --git a/ikvmdoc/IKVMDoc.java b/ikvmdoc/IKVMDoc.java new file mode 100644 index 0000000..5021457 --- /dev/null +++ b/ikvmdoc/IKVMDoc.java @@ -0,0 +1,847 @@ +/* + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely. + +*/ + +import java.io.*; +import java.util.*; + +import javax.xml.parsers.*; + +import org.xml.sax.*; +import org.xml.sax.helpers.*; + +import com.sun.javadoc.*; +import com.sun.tools.javadoc.Main; + +/** + * Java Doclet for generating .NET XML API documentation. + *

+ * The current implementation may has not been tested + * with (and thus may not support) the following features: + * {@code}; should be converted to tags + * {@docRoot} + * {@inheritDoc} + * {@literal} + * {@value} + * references to package documentation + * annotations + *

+ * Other issues: + *

+ *

+ * Usage reports "javadoc" instead of "ikvmdoc":
+ * 
+ * usage: javadoc [options] [packagenames] [sourcefiles] [@files]
+ * 
+ * should be:
+ *  
+ * usage: ikvmdoc [options] [packagenames] [sourcefiles] [@files]
+ * 
+ *

+ * HTML tag parsing is not forgiving; should be made more fault tolerant + *

+ * Javadoc HTML -> .NET tag conversions that should be considered/evaluated: + * true -> + * false -> + * null -> + * + * @author Brian Heineman + */ +public class IKVMDoc extends Doclet { + /** + * Map of Java data types to .NET data types. + */ + private static final Map DATA_TYPE_MAPPING = new HashMap(); + + /** + * Name of the assembly file parameter. + */ + private static final String ASSEMBLY_PARAMETER = "-assembly"; + + /** + * Name of the HTML parameter. + */ + private static final String HTML_PARAMETER = "-nohtml"; + + /** + * Name of the strict final field semantics parameter. + */ + private static final String STRICT_FINAL_FIELD_SEMANTICS_PARAMETER = "-strictfinalfieldsemantics"; + + /** + * Name of the author parameter. + */ + private static final String AUTHOR_PARAMETER = "-author"; + + /** + * Name of the deprecated parameter. + */ + private static final String DEPRECATED_PARAMETER = "-nodeprecated"; + + /** + * Name of the since parameter. + */ + private static final String SINCE_PARAMETER = "-nosince"; + + /** + * Name of the version parameter. + */ + private static final String VERSION_PARAMETER = "-version"; + + /** + * The assembly file the .NET documentation will be generated for. + */ + private static File ASSEMBLY_FILE; + + /** + * Indicates if HTML should be included in the .NET XML documentation. + * Default is true to reflect the standard doclet behavior. + *

+ * NOTE: The Java Runtime API contains invalid HTML which requires this + * option to be set to false when generating its + * .NET XML documentation. + */ + private static boolean OUTPUT_HTML = true; + + /** + * Indicates if the author information should be included in the .NET XML documentation. + * Default is false to reflect the standard doclet behavior. + */ + private static boolean OUTPUT_AUTHOR = false; + + /** + * Indicates if the deprecated information should be included in the .NET XML documentation. + * Default is true to reflect the standard doclet behavior. + */ + private static boolean OUTPUT_DEPRECATED = true; + + /** + * Indicates if the since information should be included in the .NET XML documentation. + * Default is true to reflect the standard doclet behavior. + */ + private static boolean OUTPUT_SINCE = true; + + /** + * Indicates if the version information should be included in the .NET XML documentation. + * Default is false to reflect the standard doclet behavior. + */ + private static boolean OUTPUT_VERSION = false; + + /** + * The reported used to report failures to. + */ + private static DocErrorReporter ERROR_REPORTER; + + static { + // Populate the Java->.NET data type mappings + DATA_TYPE_MAPPING.put("boolean", "System.Boolean"); + DATA_TYPE_MAPPING.put("byte", "System.Byte"); + DATA_TYPE_MAPPING.put("char", "System.Char"); + DATA_TYPE_MAPPING.put("short", "System.Int16"); + DATA_TYPE_MAPPING.put("int", "System.Int32"); + DATA_TYPE_MAPPING.put("long", "System.Int64"); + DATA_TYPE_MAPPING.put("float", "System.Single"); + DATA_TYPE_MAPPING.put("double", "System.Double"); + DATA_TYPE_MAPPING.put("java.lang.Object", "System.Object"); + DATA_TYPE_MAPPING.put("java.lang.String", "System.String"); + DATA_TYPE_MAPPING.put("java.lang.Throwable", "System.Exception"); + } + + /** + * Generate the .NET XML Documentation. + * + * @param root represents the root of the program structure information for one run of javadoc + * @return true on success; false on failure + */ + public static boolean start(RootDoc root) { + String assemblyName = ASSEMBLY_FILE.getName(); + int extensionIndex = assemblyName.lastIndexOf('.'); + + if (extensionIndex != -1) { + assemblyName = assemblyName.substring(0, extensionIndex); + } + + File documentationFile = new File(ASSEMBLY_FILE.getParent(), assemblyName + ".xml"); + PrintWriter pw = null; + + try { + FileOutputStream fos = new FileOutputStream(documentationFile); + OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8"); + BufferedWriter bw = new BufferedWriter(osw); + pw = new PrintWriter(bw); + + // Write the header + pw.println(""); + pw.println(""); + printIndent(pw, 1); + pw.println(""); + printIndent(pw, 2); + pw.print(""); + pw.print(assemblyName); + pw.println(""); + printIndent(pw, 1); + pw.println(""); + printIndent(pw, 1); + pw.println(""); + + ClassDoc[] classes = root.classes(); + + for (ClassDoc classDoc : classes) { + print(pw, classDoc); + } + + // Write the footer + printIndent(pw, 1); + pw.println(""); + pw.println(""); + pw.close(); + + validate(documentationFile); + } catch (Exception e) { + e.printStackTrace(); + return false; + } finally { + if (pw != null) { + pw.close(); + } + } + + return true; + } + + /** + * Prints the member documentation. + * + * @param pw the writer to print the documentation to + * @param programElementDoc the member to document + */ + private static void print(PrintWriter pw, ProgramElementDoc programElementDoc) { + /* + * Implementation of proposed @exclude tag: http://java.sun.com/j2se/javadoc/proposed-tags.html + */ + if (programElementDoc.tags("@exclude").length > 0) { + return; + } + + printIndent(pw, 2); + pw.print(""); + + printIndent(pw, 3); + pw.print("

"); + + if (OUTPUT_DEPRECATED) { + printTags(pw, programElementDoc, "DEPRECATED:", "@deprecated"); + } + + printComment(pw, programElementDoc, programElementDoc.inlineTags()); + + if (OUTPUT_AUTHOR) { + printTags(pw, programElementDoc, "Author:", "@author"); + } + + if (OUTPUT_VERSION) { + printTags(pw, programElementDoc, "Version:", "@version"); + } + + if (OUTPUT_SINCE) { + printTags(pw, programElementDoc, "Since:", "@since"); + } + + printTags(pw, programElementDoc, "Serial:", "@serial"); + printTags(pw, programElementDoc, "Serial Field:", "@serialField"); + printTags(pw, programElementDoc, "Serial Data:", "@serialData"); + + pw.println(""); + + if (programElementDoc instanceof ExecutableMemberDoc) { + ExecutableMemberDoc executableMemberDoc = (ExecutableMemberDoc) programElementDoc; + + printParamTags(pw, executableMemberDoc); + printReturnTag(pw, executableMemberDoc); + printThrowsTags(pw, executableMemberDoc); + } + + printSeeTags(pw, programElementDoc); + + printIndent(pw, 2); + pw.println(""); + + // Document class members + if (programElementDoc instanceof ClassDoc) { + ClassDoc classDoc = (ClassDoc) programElementDoc; + FieldDoc[] fields = classDoc.fields(); + + for (FieldDoc fieldDoc : fields) { + print(pw, fieldDoc); + } + + ConstructorDoc[] constructors = classDoc.constructors(); + + for (ConstructorDoc constructorDoc : constructors) { + print(pw, constructorDoc); + } + + MethodDoc[] methods = classDoc.methods(); + + for (MethodDoc methodDoc : methods) { + print(pw, methodDoc); + } + } + } + + /** + * Prints the parameter documentation. + * + * @param pw the writer to print the parameter documentation to + * @param memberDoc the member to document the parameters for + */ + private static void printParameters(PrintWriter pw, ExecutableMemberDoc memberDoc) { + Parameter[] parameters = memberDoc.parameters(); + + if (parameters.length > 0) { + pw.print("("); + } + + for (int i = 0; i < parameters.length; i++) { + Type parameterType = parameters[i].type(); + + if (i != 0) { + pw.print(","); + } + + String qualifiedTypeName = parameterType.qualifiedTypeName(); + String mappedDataType = DATA_TYPE_MAPPING.get(qualifiedTypeName); + + // Print the mapped data type if there is one + if (mappedDataType != null) { + pw.print(mappedDataType); + } else { + pw.print(qualifiedTypeName); + } + + pw.print(parameterType.dimension()); + } + + if (parameters.length > 0) { + pw.print(")"); + } + } + + /** + * Prints the parameter documentation. + * + * @param pw the writer to print the parameter documentation to + * @param memberDoc the member to document the parameters for + */ + private static void printParamTags(PrintWriter pw, ExecutableMemberDoc memberDoc) { + ParamTag[] paramTags = memberDoc.paramTags(); + + for (ParamTag paramTag : paramTags) { + printIndent(pw, 3); + pw.print(""); + printComment(pw, memberDoc, paramTag.inlineTags()); + pw.println(""); + } + } + + /** + * Prints the return documentation. + * + * @param pw the writer to print the return documentation to + * @param memberDoc the member to document the return for + */ + private static void printReturnTag(PrintWriter pw, ExecutableMemberDoc memberDoc) { + Tag[] returnDoc = memberDoc.tags("@return"); + + if (returnDoc.length == 1) { + printIndent(pw, 3); + pw.print(""); + printComment(pw, memberDoc, returnDoc[0].inlineTags()); + pw.println(""); + } else if (returnDoc.length > 1) { + ERROR_REPORTER.printError("More than one return tag specified for '" + memberDoc.qualifiedName() + "'"); + } + } + + /** + * Prints the exception documentation. + * + * @param pw the writer to print the exception documentation to + * @param memberDoc the member to document the exceptions for + */ + private static void printThrowsTags(PrintWriter pw, ExecutableMemberDoc memberDoc) { + ThrowsTag[] throwsTags = memberDoc.throwsTags(); + + for (ThrowsTag throwsTag : throwsTags) { + ClassDoc exceptionDoc = throwsTag.exception(); + + if (exceptionDoc == null) { + ERROR_REPORTER.printError("Unable to locate class '" + throwsTag.exceptionName() + "' for '" + memberDoc.qualifiedName() + "'"); + continue; + } + + printIndent(pw, 3); + pw.print(""); + printComment(pw, memberDoc, throwsTag.inlineTags()); + pw.println(""); + } + } + + /** + * Prints the see tag documentation. + * + * @param pw the writer to print the see tag documentation to + * @param memberDoc the member to document the see tags for + */ + private static void printSeeTags(PrintWriter pw, ProgramElementDoc memberDoc) { + SeeTag[] seeTags = memberDoc.seeTags(); + + for (SeeTag seeTag : seeTags) { + printSeeTag(pw, memberDoc, seeTag, true); + } + } + + /** + * Prints the specified see tag. + * + * @param pw the writer to print the see tag to + * @param memberDoc the member to document the see tag for + * @param seeTag the see tags to print + * @param asSeeAlso true if a "seealso" tag should be printed; + * false if a "see" tag should be printed + */ + private static void printSeeTag(PrintWriter pw, ProgramElementDoc memberDoc, SeeTag seeTag, boolean asSeeAlso) { + String label = seeTag.label(); + String text = seeTag.text(); + boolean isAnchor = (text.startsWith("")); + int endIndex = -1; + ProgramElementDoc referencedMemberDoc = seeTag.referencedMember(); + + if (isAnchor) { + endIndex = text.indexOf('>') + 1; + + if (endIndex == text.length()) { + ERROR_REPORTER.printError("Invalid anchor '" + text + "' for '" + memberDoc.qualifiedName() + "'"); + + printText(pw, text); + return; + } + } else { + // If the member reference is null, attempt to use the referenced class + if (referencedMemberDoc == null) { + referencedMemberDoc = seeTag.referencedClass(); + } + + if (referencedMemberDoc == null) { + ERROR_REPORTER.printError("Unable to locate reference '" + text + "' for '" + memberDoc.qualifiedName() + "'"); + + if (label == null || label.trim().length() == 0) { + printText(pw, text); + } else { + printText(pw, label); + } + + return; + } + } + + String type = (asSeeAlso) ? "seealso" : "see"; + + if (asSeeAlso) { + printIndent(pw, 3); + } + + pw.print("<"); + pw.print(type); + + if (isAnchor) { + pw.print(text.substring(2, endIndex)); + printText(pw, text.substring(endIndex, text.length() - 4)); + } else { + pw.print(" cref=\""); + printReference(pw, referencedMemberDoc, true); + pw.print("\">"); + + if (label == null || label.trim().length() == 0) { + printReference(pw, referencedMemberDoc, false); + } else { + printText(pw, label); + } + } + + pw.print(""); + + if (asSeeAlso) { + pw.println(); + } + } + + /** + * Prints the documentation for the specified tag. + * + * @param pw the writer to print the tag documentation to + * @param referenceDoc the member to document the tags for + * @param label the label to print for the tag documentation + * @param tagName the name of the tags to print the documentation for + */ + private static void printTags(PrintWriter pw, ProgramElementDoc referenceDoc, String label, String tagName) { + Tag[] tags = referenceDoc.tags(tagName); + + for (Tag tag : tags) { + pw.print(""); + pw.print(label); + pw.print(" "); + printComment(pw, referenceDoc, tag.inlineTags()); + pw.println(""); + } + } + + /** + * Prints the specified reference. + * + * @param pw the writer to print the reference to + * @param referenceDoc the reference to print + * @param includeType true if the type identifier should be included; + * false if the type identifier should be omitted + */ + private static void printReference(PrintWriter pw, ProgramElementDoc referenceDoc, boolean includeType) { + ClassDoc classDoc = (referenceDoc.isClass() || referenceDoc.isInterface()) ? (ClassDoc) referenceDoc : referenceDoc.containingClass(); + + if (includeType) { + if (referenceDoc.isField()) { + if (referenceDoc.isFinal() && !classDoc.isInterface()) { + pw.print("P:"); + } else { + pw.print("F:"); + } + } else if (referenceDoc.isConstructor() || referenceDoc.isMethod()) { + pw.print("M:"); + } else { + pw.print("T:"); + } + } + + pw.print(classDoc.qualifiedName()); + + if (referenceDoc.isField()) { + if (classDoc.isInterface()) { + pw.print(".__Fields."); + } else { + pw.print("."); + } + + pw.print(referenceDoc.name()); + } else if (referenceDoc.isConstructor()) { + pw.print(".#ctor"); + printParameters(pw, (ConstructorDoc) referenceDoc); + } else if (referenceDoc.isMethod()){ + pw.print("."); + pw.print(referenceDoc.name()); + printParameters(pw, (MethodDoc) referenceDoc); + } + } + + /** + * Prints comment tags. + * + * @param pw the writer to print the comment tags to + * @param memberDoc the member to print the comment tags for + * @param commentTags the comment tags to print + */ + private static void printComment(PrintWriter pw, ProgramElementDoc memberDoc, Tag[] commentTags) { + for (Tag tag : commentTags) { + if (tag instanceof SeeTag) { + SeeTag seeTag = (SeeTag) tag; + + printSeeTag(pw, memberDoc, seeTag, false); + } else { + String text = tag.text(); + + printText(pw, memberDoc, text); + } + } + } + + /** + * Prints the specified javadoc text in a .NET XML documentation format. + * + * @param pw the writer to print the comment tags to + * @param memberDoc the member to print the comment tags for + * @param text the text to print + */ + private static void printText(PrintWriter pw, ProgramElementDoc memberDoc, String text) { + char[] characters = text.toCharArray(); + + for (int index = 0; index < characters.length; index++) { + char character = characters[index]; + + switch (character) { + case '<': + int x = Character.offsetByCodePoints(text, 0, index); + if (x != index) { + System.out.println("x = " + x); + } + + int endIndex = text.indexOf('>', index); + + // Handle invalid HTML (use of "<" or "<>" in text) + if (endIndex == -1 || endIndex - index < 2) { + pw.print("<"); + continue; + } + + String tag = text.substring(index + 1, endIndex).trim().toLowerCase(); + boolean isEndTag = false; + boolean isStandAloneTag = false; + + if (tag.length() > 1) { + if (tag.startsWith("/")) { + tag = tag.substring(1); + isEndTag = true; + } else if (tag.endsWith("/")) { + tag = tag.substring(0, tag.length() - 1); + isStandAloneTag = true; + } + } + + /* + * Process/convert HTML tags to .NET XML + */ + + if ("p".equals(tag)) { + // Translate

to ; ignore end tags + if (!isEndTag) { + pw.print(""); + } + + index = endIndex; + } else if ("br".equals(tag) || "hr".equals(tag) || "img".equals(tag)) { + if (!isEndTag) { + pw.print("<"); + pw.print(tag); + pw.print("/>"); + } + + index = endIndex; + } else if (OUTPUT_HTML) { + if ("code".equals(tag)) { + // Translate "code" tags to "c" tags + tag = "c"; + } else if ("li".equals(tag)) { + // Translate "li" tags to "item" tags + tag = "item"; + } else if ("ol".equals(tag)) { + // Translate "ol" tags to "list" tags + tag = "list"; + + if (!isEndTag) { + tag += " type=\"number\""; + } + } else if ("pre".equals(tag)) { + // Translate "pre" tags to "code" tags + tag = "code"; + } else if ("ul".equals(tag)) { + // Translate "ul" tags to "list" tags + tag = "list"; + + if (!isEndTag) { + tag += " type=\"bullet\""; + } + } + + pw.print("<"); + + if (isEndTag) { + pw.print("/"); + } + + pw.print(tag); + + if (isStandAloneTag) { + pw.print("/"); + } + + pw.print(">"); + index = endIndex; + } else { + pw.print("<"); + } + + break; + case '>': + pw.print(">"); + break; + case '&': + // TODO: Update to handle HTML escape sequences ( , &#nnnn;, etc) + pw.print("&"); + break; + case '\'': + pw.print("'"); + break; + case '"': + pw.print("""); + break; + default: + pw.print(character); + } + } + } + + /** + * Prints the specified text and escapes any XML characters. + * + * @param pw the writer to print the text to + * @param text the text to print + */ + private static void printText(PrintWriter pw, String text) { + char[] characters = text.toCharArray(); + + for (int index = 0; index < characters.length; index++) { + char character = characters[index]; + + switch (character) { + case '<': + pw.print("<"); + break; + case '>': + pw.print(">"); + break; + case '&': + // TODO: Update to handle HTML escape sequences ( , &#nnnn;, etc) + pw.print("&"); + break; + case '\'': + pw.print("'"); + break; + case '"': + pw.print("""); + break; + default: + pw.print(character); + } + } + } + + /** + * Prints an indentation a specified number of times. + * + * @param pw the writer to print the indentations to + * @param indentations the number of indentations to print + */ + public static void printIndent(PrintWriter pw, int indentations) { + for (int i = 0; i < indentations; i++) { + pw.write("\t"); + } + } + + /** + * Validates the specified file is well formed XML. + * + * @param file the file to validate + * @throws Exception if a failure occurs while validating the file + */ + private static void validate(File file) throws Exception { + SAXParserFactory factory = SAXParserFactory.newInstance(); + SAXParser parser = factory.newSAXParser(); + + parser.parse(file, new DefaultHandler() { + public void error(SAXParseException e) throws SAXException { + fatalError(e); + } + + public void fatalError(SAXParseException e) throws SAXException { + ERROR_REPORTER.printError(e.getMessage()); + ERROR_REPORTER.printError("Line: " + e.getLineNumber() + ", Column: " + e.getColumnNumber()); + throw e; + } + }); + } + + /** + * Execute IKVMDoc without the use of the javadoc executable. + * + * @param args the program arguments + */ + public static void main(String[] args) { + Main.execute("ikvmdoc", IKVMDoc.class.getName(), args); + } + + /** + * Check for ikvmdoc specific options. Returns the number of arguments that must be specified on the command + * line for the given option. For example, "-assembly IKVM.OpenJDK.ClassLibrary.dll" would return 2. + * + * @param option the option to evaluate and return the number of arguments for + * @return number of arguments on the command line for an option including the option name itself. + * Zero return means option not known. Negative value means error occurred. + */ + public static int optionLength(String option) { + if (ASSEMBLY_PARAMETER.equals(option)) { + return 2; + } else if (STRICT_FINAL_FIELD_SEMANTICS_PARAMETER.equals(option)) { + return 1; + } else if (HTML_PARAMETER.equals(option)) { + return 1; + } else if (AUTHOR_PARAMETER.equals(option)) { + return 1; + } else if (DEPRECATED_PARAMETER.equals(option)) { + return 1; + } else if (SINCE_PARAMETER.equals(option)) { + return 1; + } else if (VERSION_PARAMETER.equals(option)) { + return 1; + } + + return 0; + } + + /** + * Check that ikvmdoc options have the correct arguments. + * + * @param options the options to check + * @param reporter the error reported used to report any failures to + * @return true if the options are valid; + * false if the options are invalid + */ + public static boolean validOptions(String[][] options, DocErrorReporter reporter) { + ERROR_REPORTER = reporter; + + for (String[] option : options) { + if (ASSEMBLY_PARAMETER.equals(option[0])) { + ASSEMBLY_FILE = new File(option[1]); + + if (!ASSEMBLY_FILE.isFile() || !ASSEMBLY_FILE.exists()) { + reporter.printError("The assembly file specified '" + ASSEMBLY_FILE.getAbsolutePath() + "' is invalid."); + return false; + } + } else if (HTML_PARAMETER.equals(option[0])) { + OUTPUT_HTML = false; + } else if (AUTHOR_PARAMETER.equals(option[0])) { + OUTPUT_AUTHOR = true; + } else if (DEPRECATED_PARAMETER.equals(option[0])) { + OUTPUT_DEPRECATED = false; + } else if (SINCE_PARAMETER.equals(option[0])) { + OUTPUT_SINCE = false; + } else if (VERSION_PARAMETER.equals(option[0])) { + OUTPUT_VERSION = true; + } + } + + return true; + } +} diff --git a/ikvmdoc/ikvmdoc.build b/ikvmdoc/ikvmdoc.build new file mode 100644 index 0000000..43f5671 --- /dev/null +++ b/ikvmdoc/ikvmdoc.build @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ikvmstub/AssemblyInfo.cs b/ikvmstub/AssemblyInfo.cs new file mode 100644 index 0000000..1926bff --- /dev/null +++ b/ikvmstub/AssemblyInfo.cs @@ -0,0 +1,32 @@ +/* + Copyright (C) 2002, 2003, 2004, 2005, 2006 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System.Reflection; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("IKVM.NET Stub Generator")] +[assembly: AssemblyDescription("")] diff --git a/ikvmstub/ikvmstub.8.csproj b/ikvmstub/ikvmstub.8.csproj new file mode 100644 index 0000000..b1998f9 --- /dev/null +++ b/ikvmstub/ikvmstub.8.csproj @@ -0,0 +1,121 @@ + + + Local + 9.0.30729 + 2.0 + {D2A9434D-59E4-43E9-8D9C-332AA138CEAD} + Debug + AnyCPU + + + + + ikvmstub + + + JScript + Grid + IE50 + false + Exe + + + OnBuildSuccess + + + + + + + 2.0 + + + bin\Debug\ + false + 285212672 + false + + + TRACE;DEBUG;IKVM_REF_EMIT;STUB_GENERATOR + + + true + 4096 + false + + + false + false + false + false + 4 + full + prompt + + + + False + ..\bin\ICSharpCode.SharpZipLib.dll + + + System + + + + + Code + + + Code + + + + Code + + + + + Code + + + Code + + + Code + + + + Code + + + Code + + + Code + + + + + + Code + + + Code + + + + + + + {4CB170EF-DFE6-4A56-9E1B-A85449E827A7} + IKVM.Reflection + + + + + + + + + + \ No newline at end of file diff --git a/ikvmstub/ikvmstub.build b/ikvmstub/ikvmstub.build new file mode 100644 index 0000000..6d0dd99 --- /dev/null +++ b/ikvmstub/ikvmstub.build @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ikvmstub/ikvmstub.cs b/ikvmstub/ikvmstub.cs new file mode 100644 index 0000000..955eb27 --- /dev/null +++ b/ikvmstub/ikvmstub.cs @@ -0,0 +1,615 @@ +/* + Copyright (C) 2002-2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.IO; +using System.Collections.Generic; +using ICSharpCode.SharpZipLib.Zip; +using IKVM.Attributes; +using IKVM.Internal; +using IKVM.Reflection; +using Type = IKVM.Reflection.Type; + +static class NetExp +{ + private static int zipCount; + private static ZipOutputStream zipFile; + private static Dictionary done = new Dictionary(); + private static Dictionary todo = new Dictionary(); + private static FileInfo file; + private static bool includeSerialVersionUID; + private static bool includeNonPublicInterfaces; + private static bool includeNonPublicMembers; + private static bool includeParameterNames; + private static List namespaces = new List(); + + static int Main(string[] args) + { + IKVM.Internal.Tracer.EnableTraceConsoleListener(); + IKVM.Internal.Tracer.EnableTraceForDebug(); + string assemblyNameOrPath = null; + bool continueOnError = false; + bool autoLoadSharedClassLoaderAssemblies = false; + List references = new List(); + List libpaths = new List(); + bool nostdlib = false; + bool bootstrap = false; + string outputFile = null; + bool forwarders = false; + foreach(string s in args) + { + if(s.StartsWith("-") || assemblyNameOrPath != null) + { + if(s == "-serialver") + { + Console.Error.WriteLine("The -serialver option is deprecated and will be removed in the future. Use -japi instead."); + includeSerialVersionUID = true; + } + else if(s == "-japi") + { + includeSerialVersionUID = true; + includeNonPublicInterfaces = true; + includeNonPublicMembers = true; + } + else if(s == "-skiperror") + { + continueOnError = true; + } + else if(s == "-shared") + { + autoLoadSharedClassLoaderAssemblies = true; + } + else if(s.StartsWith("-r:") || s.StartsWith("-reference:")) + { + references.Add(s.Substring(s.IndexOf(':') + 1)); + } + else if(s == "-nostdlib") + { + nostdlib = true; + } + else if(s.StartsWith("-lib:")) + { + libpaths.Add(s.Substring(5)); + } + else if(s == "-bootstrap") + { + bootstrap = true; + } + else if(s.StartsWith("-out:")) + { + outputFile = s.Substring(5); + } + else if(s.StartsWith("-namespace:")) + { + namespaces.Add(s.Substring(11) + "."); + } + else if(s == "-forwarders") + { + forwarders = true; + } + else if(s == "-parameters") + { + includeParameterNames = true; + } + else + { + // unrecognized option, or multiple assemblies, print usage message and exit + assemblyNameOrPath = null; + break; + } + } + else + { + assemblyNameOrPath = s; + } + } + if(assemblyNameOrPath == null) + { + Console.Error.WriteLine(GetVersionAndCopyrightInfo()); + Console.Error.WriteLine(); + Console.Error.WriteLine("usage: ikvmstub [-options] "); + Console.Error.WriteLine(); + Console.Error.WriteLine("options:"); + Console.Error.WriteLine(" -out: Specify the output filename"); + Console.Error.WriteLine(" -reference: Reference an assembly (short form -r:)"); + Console.Error.WriteLine(" -japi Generate jar suitable for comparison with japitools"); + Console.Error.WriteLine(" -skiperror Continue when errors are encountered"); + Console.Error.WriteLine(" -shared Process all assemblies in shared group"); + Console.Error.WriteLine(" -nostdlib Do not reference standard libraries"); + Console.Error.WriteLine(" -lib:

Additional directories to search for references"); + Console.Error.WriteLine(" -namespace: Only include types from specified namespace"); + Console.Error.WriteLine(" -forwarders Export forwarded types too"); + Console.Error.WriteLine(" -parameters Emit Java 8 classes with parameter names"); + return 1; + } + if(File.Exists(assemblyNameOrPath) && nostdlib) + { + // Add the target assembly to the references list, to allow it to be considered as "mscorlib". + // This allows "ikvmstub -nostdlib \...\mscorlib.dll" to work. + references.Add(assemblyNameOrPath); + } + StaticCompiler.Resolver.Warning += new AssemblyResolver.WarningEvent(Resolver_Warning); + StaticCompiler.Resolver.Init(StaticCompiler.Universe, nostdlib, references, libpaths); + Dictionary cache = new Dictionary(); + foreach (string reference in references) + { + Assembly[] dummy = null; + if (!StaticCompiler.Resolver.ResolveReference(cache, ref dummy, reference)) + { + Console.Error.WriteLine("Error: reference not found {0}", reference); + return 1; + } + } + Assembly assembly = null; + try + { + file = new FileInfo(assemblyNameOrPath); + } + catch(System.Exception x) + { + Console.Error.WriteLine("Error: unable to load \"{0}\"\n {1}", assemblyNameOrPath, x.Message); + return 1; + } + if(file != null && file.Exists) + { + assembly = StaticCompiler.LoadFile(assemblyNameOrPath); + } + else + { + assembly = StaticCompiler.Resolver.LoadWithPartialName(assemblyNameOrPath); + } + int rc = 0; + if(assembly == null) + { + Console.Error.WriteLine("Error: Assembly \"{0}\" not found", assemblyNameOrPath); + } + else + { + if (bootstrap) + { + StaticCompiler.runtimeAssembly = StaticCompiler.LoadFile(typeof(NetExp).Assembly.Location); + ClassLoaderWrapper.SetBootstrapClassLoader(new BootstrapBootstrapClassLoader()); + } + else + { + StaticCompiler.LoadFile(typeof(NetExp).Assembly.Location); + StaticCompiler.runtimeAssembly = StaticCompiler.LoadFile(Path.Combine(typeof(NetExp).Assembly.Location, "../IKVM.Runtime.dll")); + JVM.CoreAssembly = StaticCompiler.LoadFile(Path.Combine(typeof(NetExp).Assembly.Location, "../IKVM.OpenJDK.Core.dll")); + } + if (AttributeHelper.IsJavaModule(assembly.ManifestModule)) + { + Console.Error.WriteLine("Warning: Running ikvmstub on ikvmc compiled assemblies is not supported."); + } + if (outputFile == null) + { + outputFile = assembly.GetName().Name + ".jar"; + } + try + { + using (zipFile = new ZipOutputStream(new FileStream(outputFile, FileMode.Create))) + { + zipFile.SetComment(GetVersionAndCopyrightInfo()); + try + { + List assemblies = new List(); + assemblies.Add(assembly); + if (autoLoadSharedClassLoaderAssemblies) + { + LoadSharedClassLoaderAssemblies(assembly, assemblies); + } + foreach (Assembly asm in assemblies) + { + if (ProcessTypes(asm.GetTypes(), continueOnError) != 0) + { + rc = 1; + if (!continueOnError) + { + break; + } + } + if (forwarders && ProcessTypes(asm.ManifestModule.__GetExportedTypes(), continueOnError) != 0) + { + rc = 1; + if (!continueOnError) + { + break; + } + } + } + } + catch (System.Exception x) + { + Console.Error.WriteLine(x); + + if (!continueOnError) + { + Console.Error.WriteLine("Warning: Assembly reflection encountered an error. Resultant JAR may be incomplete."); + } + + rc = 1; + } + } + } + catch (ZipException x) + { + rc = 1; + if (zipCount == 0) + { + Console.Error.WriteLine("Error: Assembly contains no public IKVM.NET compatible types"); + } + else + { + Console.Error.WriteLine("Error: {0}", x.Message); + } + } + } + return rc; + } + + static void Resolver_Warning(AssemblyResolver.WarningId warning, string message, string[] parameters) + { + if (warning != AssemblyResolver.WarningId.HigherVersion) + { + Console.Error.WriteLine("Warning: " + message, parameters); + } + } + + private static string GetVersionAndCopyrightInfo() + { + System.Reflection.Assembly asm = System.Reflection.Assembly.GetEntryAssembly(); + object[] desc = asm.GetCustomAttributes(typeof(System.Reflection.AssemblyTitleAttribute), false); + if (desc.Length == 1) + { + object[] copyright = asm.GetCustomAttributes(typeof(System.Reflection.AssemblyCopyrightAttribute), false); + if (copyright.Length == 1) + { + return string.Format("{0} version {1}{2}{3}{2}http://www.ikvm.net/", + ((System.Reflection.AssemblyTitleAttribute)desc[0]).Title, + asm.GetName().Version, + Environment.NewLine, + ((System.Reflection.AssemblyCopyrightAttribute)copyright[0]).Copyright); + } + } + return ""; + } + + private static void LoadSharedClassLoaderAssemblies(Assembly assembly, List assemblies) + { + if (assembly.GetManifestResourceInfo("ikvm.exports") != null) + { + using (Stream stream = assembly.GetManifestResourceStream("ikvm.exports")) + { + BinaryReader rdr = new BinaryReader(stream); + int assemblyCount = rdr.ReadInt32(); + for (int i = 0; i < assemblyCount; i++) + { + string name = rdr.ReadString(); + int typeCount = rdr.ReadInt32(); + if (typeCount > 0) + { + for (int j = 0; j < typeCount; j++) + { + rdr.ReadInt32(); + } + try + { + assemblies.Add(StaticCompiler.Load(name)); + } + catch + { + Console.WriteLine("Warning: Unable to load shared class loader assembly: {0}", name); + } + } + } + } + } + } + + private static void WriteClass(TypeWrapper tw) + { + zipCount++; + MemoryStream mem = new MemoryStream(); + IKVM.StubGen.StubGenerator.WriteClass(mem, tw, includeNonPublicInterfaces, includeNonPublicMembers, includeSerialVersionUID, includeParameterNames); + ZipEntry entry = new ZipEntry(tw.Name.Replace('.', '/') + ".class"); + entry.Size = mem.Position; + zipFile.PutNextEntry(entry); + mem.WriteTo(zipFile); + } + + private static bool ExportNamespace(Type type) + { + if (namespaces.Count == 0) + { + return true; + } + string name = type.FullName; + foreach (string ns in namespaces) + { + if (name.StartsWith(ns, StringComparison.Ordinal)) + { + return true; + } + } + return false; + } + + private static int ProcessTypes(Type[] types, bool continueOnError) + { + int rc = 0; + foreach (Type t in types) + { + if (t.IsPublic + && ExportNamespace(t) + && !t.IsGenericTypeDefinition + && !AttributeHelper.IsHideFromJava(t) + && (!t.IsGenericType || !AttributeHelper.IsJavaModule(t.Module))) + { + TypeWrapper c; + if (ClassLoaderWrapper.IsRemappedType(t) || t.IsPrimitive || t == Types.Void) + { + c = DotNetTypeWrapper.GetWrapperFromDotNetType(t); + } + else + { + c = ClassLoaderWrapper.GetWrapperFromType(t); + } + if (c != null) + { + AddToExportList(c); + } + } + } + bool keepGoing; + do + { + keepGoing = false; + foreach (TypeWrapper c in new List(todo.Values)) + { + if(!done.ContainsKey(c.Name)) + { + keepGoing = true; + done.Add(c.Name, null); + + try + { + ProcessClass(c); + WriteClass(c); + } + catch (Exception x) + { + if (continueOnError) + { + rc = 1; + Console.WriteLine(x); + } + else + { + throw; + } + } + } + } + } while(keepGoing); + return rc; + } + + private static void AddToExportList(TypeWrapper c) + { + todo[c.Name] = c; + } + + private static bool IsNonVectorArray(TypeWrapper tw) + { + return !tw.IsArray && tw.TypeAsBaseType.IsArray; + } + + private static void AddToExportListIfNeeded(TypeWrapper tw) + { + while (tw.IsArray) + { + tw = tw.ElementTypeWrapper; + } + if (tw.IsUnloadable && tw.Name.StartsWith("Missing/")) + { + Console.Error.WriteLine("Error: unable to find assembly '{0}'", tw.Name.Substring(8)); + Environment.Exit(1); + return; + } + if (tw is StubTypeWrapper) + { + // skip + } + else if ((tw.TypeAsTBD != null && tw.TypeAsTBD.IsGenericType) || IsNonVectorArray(tw) || !tw.IsPublic) + { + AddToExportList(tw); + } + } + + private static void AddToExportListIfNeeded(TypeWrapper[] types) + { + foreach (TypeWrapper tw in types) + { + AddToExportListIfNeeded(tw); + } + } + + private static void ProcessClass(TypeWrapper tw) + { + TypeWrapper superclass = tw.BaseTypeWrapper; + if (superclass != null) + { + AddToExportListIfNeeded(superclass); + } + AddToExportListIfNeeded(tw.Interfaces); + TypeWrapper outerClass = tw.DeclaringTypeWrapper; + if (outerClass != null) + { + AddToExportList(outerClass); + } + foreach (TypeWrapper innerClass in tw.InnerClasses) + { + if (innerClass.IsPublic) + { + AddToExportList(innerClass); + } + } + foreach (MethodWrapper mw in tw.GetMethods()) + { + if (mw.IsPublic || mw.IsProtected) + { + mw.Link(); + AddToExportListIfNeeded(mw.ReturnType); + AddToExportListIfNeeded(mw.GetParameters()); + } + } + foreach (FieldWrapper fw in tw.GetFields()) + { + if (fw.IsPublic || fw.IsProtected) + { + fw.Link(); + AddToExportListIfNeeded(fw.FieldTypeWrapper); + } + } + } +} + +static class Intrinsics +{ + internal static bool IsIntrinsic(MethodWrapper methodWrapper) + { + return false; + } +} + +static class StaticCompiler +{ + internal static readonly Universe Universe = new Universe(UniverseOptions.EnableFunctionPointers); + internal static readonly AssemblyResolver Resolver = new AssemblyResolver(); + internal static Assembly runtimeAssembly; + + internal static Type GetRuntimeType(string typeName) + { + return runtimeAssembly.GetType(typeName, true); + } + + internal static Assembly LoadFile(string fileName) + { + return Resolver.LoadFile(fileName); + } + + internal static Assembly Load(string name) + { + return Universe.Load(name); + } +} + +static class FakeTypes +{ + private static readonly Type genericType; + + class Holder { } + + static FakeTypes() + { + genericType = StaticCompiler.Universe.Import(typeof(Holder<>)); + } + + internal static Type GetAttributeType(Type type) + { + return genericType.MakeGenericType(type); + } + + internal static Type GetAttributeReturnValueType(Type type) + { + return genericType.MakeGenericType(type); + } + + internal static Type GetAttributeMultipleType(Type type) + { + return genericType.MakeGenericType(type); + } + + internal static Type GetDelegateType(Type type) + { + return genericType.MakeGenericType(type); + } + + internal static Type GetEnumType(Type type) + { + return genericType.MakeGenericType(type); + } +} + +sealed class BootstrapBootstrapClassLoader : ClassLoaderWrapper +{ + internal BootstrapBootstrapClassLoader() + : base(CodeGenOptions.None, null) + { + TypeWrapper javaLangObject = new StubTypeWrapper(Modifiers.Public, "java.lang.Object", null, true); + SetRemappedType(JVM.Import(typeof(object)), javaLangObject); + SetRemappedType(JVM.Import(typeof(string)), new StubTypeWrapper(Modifiers.Public | Modifiers.Final, "java.lang.String", javaLangObject, true)); + SetRemappedType(JVM.Import(typeof(Exception)), new StubTypeWrapper(Modifiers.Public, "java.lang.Throwable", javaLangObject, true)); + SetRemappedType(JVM.Import(typeof(IComparable)), new StubTypeWrapper(Modifiers.Public | Modifiers.Abstract | Modifiers.Interface, "java.lang.Comparable", null, true)); + TypeWrapper tw = new StubTypeWrapper(Modifiers.Public | Modifiers.Abstract | Modifiers.Interface, "java.lang.AutoCloseable", null, true); + tw.SetMethods(new MethodWrapper[] { new SimpleCallMethodWrapper(tw, "close", "()V", JVM.Import(typeof(IDisposable)).GetMethod("Dispose"), PrimitiveTypeWrapper.VOID, TypeWrapper.EmptyArray, Modifiers.Public | Modifiers.Abstract, MemberFlags.None, SimpleOpCode.Callvirt, SimpleOpCode.Callvirt) }); + SetRemappedType(JVM.Import(typeof(IDisposable)), tw); + + RegisterInitiatingLoader(new StubTypeWrapper(Modifiers.Public, "java.lang.Enum", javaLangObject, false)); + RegisterInitiatingLoader(new StubTypeWrapper(Modifiers.Public | Modifiers.Abstract | Modifiers.Interface, "java.lang.annotation.Annotation", null, false)); + RegisterInitiatingLoader(new StubTypeWrapper(Modifiers.Public | Modifiers.Final, "java.lang.Class", javaLangObject, false)); + RegisterInitiatingLoader(new StubTypeWrapper(Modifiers.Public | Modifiers.Abstract, "java.lang.invoke.MethodHandle", javaLangObject, false)); + } +} + +sealed class StubTypeWrapper : TypeWrapper +{ + private readonly bool remapped; + private readonly TypeWrapper baseWrapper; + + internal StubTypeWrapper(Modifiers modifiers, string name, TypeWrapper baseWrapper, bool remapped) + : base(TypeFlags.None, modifiers, name) + { + this.remapped = remapped; + this.baseWrapper = baseWrapper; + } + + internal override TypeWrapper BaseTypeWrapper + { + get { return baseWrapper; } + } + + internal override ClassLoaderWrapper GetClassLoader() + { + return ClassLoaderWrapper.GetBootstrapClassLoader(); + } + + internal override Type TypeAsTBD + { + get { throw new NotSupportedException(); } + } + + internal override bool IsRemapped + { + get { return remapped; } + } +} diff --git a/japi/japi-status.build b/japi/japi-status.build new file mode 100644 index 0000000..0f42c46 --- /dev/null +++ b/japi/japi-status.build @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jvm/jvm.build b/jvm/jvm.build new file mode 100644 index 0000000..7ca0f05 --- /dev/null +++ b/jvm/jvm.build @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jvm/jvm.def b/jvm/jvm.def new file mode 100644 index 0000000..e8f2546 --- /dev/null +++ b/jvm/jvm.def @@ -0,0 +1,5 @@ +LIBRARY JVM.DLL +EXPORTS + JNI_CreateJavaVM=[IKVM.Runtime.JNI]IKVM.Runtime.JNI::CreateJavaVM @2164 + JNI_GetCreatedJavaVMs=[IKVM.Runtime.JNI]IKVM.Runtime.JNI::GetCreatedJavaVMs @2165 + JNI_GetDefaultJavaVMInitArgs=[IKVM.Runtime.JNI]IKVM.Runtime.JNI::GetDefaultJavaVMInitArgs @2166 diff --git a/msbuild/AssemblyInfo.cs b/msbuild/AssemblyInfo.cs new file mode 100644 index 0000000..ba304af --- /dev/null +++ b/msbuild/AssemblyInfo.cs @@ -0,0 +1,40 @@ +/* + Copyright (C) 2007, 2008, 2010 Jeroen Frijters + Copyright (C) 2009 - 2012 Volker Berlin (i-net software) + Copyright (C) 2010 Karsten Heinrich (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +#region Using directives + +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +#endregion + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("IKVM.MSBuild")] +[assembly: AssemblyDescription("Java build task for .NET")] + +//[assembly: System.Security.AllowPartiallyTrustedCallers] diff --git a/msbuild/IKVM.MSBuild.Java.Targets b/msbuild/IKVM.MSBuild.Java.Targets new file mode 100644 index 0000000..b9de8f1 --- /dev/null +++ b/msbuild/IKVM.MSBuild.Java.Targets @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/msbuild/IKVM.MSBuild.csproj b/msbuild/IKVM.MSBuild.csproj new file mode 100644 index 0000000..0fcdaf4 --- /dev/null +++ b/msbuild/IKVM.MSBuild.csproj @@ -0,0 +1,52 @@ + + + + {D7FF23BC-49C2-490D-B702-8EEE8F5AF296} + Debug + AnyCPU + 9.0.30729 + 2.0 + Library + IKVM.MSBuild + IKVM.MSBuild + v2.0 + 512 + + + bin\Debug\ + True + Full + False + True + DEBUG;TRACE + 4 + + + + ..\bin\IKVM.OpenJDK.Core.dll + + + ..\bin\IKVM.OpenJDK.Tools.dll + + + + + + + + + + + + + Always + + + + + {4CB170EF-DFE6-4A56-9E1B-A85449E827A7} + IKVM.Reflection + + + + \ No newline at end of file diff --git a/msbuild/JavaTask.cs b/msbuild/JavaTask.cs new file mode 100644 index 0000000..afa20f9 --- /dev/null +++ b/msbuild/JavaTask.cs @@ -0,0 +1,532 @@ +/* + Copyright (C) 2012 Volker Berlin (i-net software) + Copyright (C) 2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Reflection.Emit; +using System.Runtime.Versioning; +using System.Text; + +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using Javac = com.sun.tools.javac.Main; +using PrintWriter = java.io.PrintWriter; +using System.Diagnostics; + +namespace IKVM.MSBuild +{ + /// + /// Java compiler task. + /// + public sealed class JavaTask : ToolTask + { + private ITaskItem[] sources; + private string[] references; + private ITaskItem[] resources; + private string configuration = "Debug"; + private string targetType; + private string outputPath; + private string mainFile; + private string outputAssembly; + private bool emitDebugInformation; + private string platform = "x86"; + + /// + /// Gets or sets the source files that will be compiled. Is called from script. + /// + public ITaskItem[] Sources + { + get { return sources; } + set { sources = value; } + } + + /// + /// Gets or sets the resources to be compiled. Is called from script. + /// + public ITaskItem[] Resources + { + get { return resources; } + set { resources = value; } + } + + /// + /// Gets or sets the output assembly type. Is called from script. + /// + public string Configuration + { + get { return configuration; } + set { configuration = value; } + } + + /// + /// Gets or sets the output assembly type. Is called from script. + /// + public string TargetType + { + get { return targetType; } + set { targetType = value; } + } + + /// + /// Gets or sets the output path. Is called from script. + /// + public string OutputPath + { + get { return outputPath; } + set { outputPath = value; } + } + + /// + /// Gets or sets the output assembly filename. Is called from script. + /// + public string OutputAssembly + { + get { return outputAssembly; } + set { outputAssembly = value; } + } + + /// + /// Gets or sets the class with the main method. Is called from script. + /// + public string MainFile + { + get { return mainFile; } + set { mainFile = value; } + } + + /// + /// Gets or sets the platform that will be targeted by the compiler (e.g. x86). Is called from script. + /// + public string Platform + { + get { return platform; } + set { platform = value; } + } + + /// + /// Gets or sets whether the compiler should include debug. Is called from script. + /// information in the created assembly. + /// + public bool EmitDebugInformation + { + get { return emitDebugInformation; } + set { emitDebugInformation = value; } + } + + /// + /// Gets or sets the assembly references. Is called from script. + /// + public string[] References + { + get { return references; } + set { references = value; } + } + + protected override string ToolName + { + get { return "ikvmc.exe"; } + } + + protected override string GenerateFullPathToTool() + { + return Path.Combine(GetAssemblyPath(), ToolName); + } + + private static string GetAssemblyPath() + { + return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + } + + private string GetIntermediatePath() + { + return Path.GetFullPath(Path.Combine(Path.Combine("obj", platform), configuration)); + } + + protected override string GenerateCommandLineCommands() + { + CommandLineBuilder commandLine = new CommandLineBuilder(); + + commandLine.AppendSwitch("-nologo"); + + if (EmitDebugInformation) + { + commandLine.AppendSwitch("-debug"); + } + + commandLine.AppendSwitch("-nostdlib"); + + if (((outputAssembly == null) && (sources != null)) && ((sources.Length > 0))) + { + outputAssembly = Path.GetFileNameWithoutExtension(sources[0].ItemSpec); + } + if (string.Equals(this.TargetType, "library", StringComparison.OrdinalIgnoreCase)) + { + outputAssembly += ".dll"; + } + else + { + outputAssembly += ".exe"; + } + + if (references != null) + { + foreach (string reference in references) + { + if (IsIkvmStandardLibrary(reference)) + { + continue; + } + commandLine.AppendSwitchIfNotNull("-reference:", reference); + } + } + + if (resources != null) + { + foreach (ITaskItem item in resources) + { + commandLine.AppendSwitch("-resource:" + item.ItemSpec + "=" + Path.GetFullPath(item.ItemSpec)); + } + } + + commandLine.AppendSwitchIfNotNull("-out:", Path.Combine(GetIntermediatePath(), OutputAssembly)); + + if (TargetType != null) + { + commandLine.AppendSwitch("-target:" + TargetType.ToLower()); + } + + commandLine.AppendSwitch("-recurse:" + GetClassesPath()); + //Log.LogWarning(commandLine.ToString(), null); + return commandLine.ToString(); + } + + /// + /// Executes the compiler. + /// + public override bool Execute() + { + if (!GenerateStubs()) + { + return false; + } + + Stopwatch sw = Stopwatch.StartNew(); + if (!RunJavac()) + { + return false; + } + sw.Stop(); + Log.LogMessage("Javac compilation time was {0} ms", sw.ElapsedMilliseconds); + + CopyIkvm(); + + return base.Execute(); // run IKVMC + } + + private string GetStubPath() + { + return Path.Combine("obj", "stubs"); + } + + private bool GenerateStubs() + { + // we start by creating the stubs for the boot classes + string stubpath = GetStubPath(); + Directory.CreateDirectory(stubpath); + // note that File.GetLastWriteTime() returns Jan 1st, 1601 for non-existing files, so that works out nicely + if (File.GetLastWriteTime(Path.Combine(stubpath, "rt.jar")) < File.GetLastWriteTime(Path.Combine(GetAssemblyPath(), "IKVM.OpenJDK.Core.dll"))) + { + if (!GenerateStub("IKVM.OpenJDK.Core", Path.Combine(stubpath, "rt.jar"))) + { + return false; + } + } + // now generate stubs for the referenced assemblies + Dictionary stubs = new Dictionary(); + using (IKVM.Reflection.Universe universe = new IKVM.Reflection.Universe(IKVM.Reflection.UniverseOptions.MetadataOnly)) + { + foreach (string reference in references) + { + using (IKVM.Reflection.RawModule module = universe.OpenRawModule(reference)) + { + string fileName = Path.Combine(stubpath, module.GetAssemblyName().Name + "__" + module.ModuleVersionId.ToString("N") + ".jar"); + stubs.Add(fileName, null); + if (!File.Exists(fileName)) + { + if (!GenerateStub(reference, fileName)) + { + return false; + } + } + } + } + } + // clean up any left-over stubs + foreach (string file in Directory.GetFiles(stubpath, "*.jar")) + { + if (!stubs.ContainsKey(file) && Path.GetFileName(file) != "rt.jar") + { + File.Delete(file); + } + } + return true; + } + + private static bool GenerateStub(string assemblyFile, string outputFile) + { + ProcessStartInfo psi = new ProcessStartInfo(Path.Combine(GetAssemblyPath(), "ikvmstub.exe"), "-shared \"-out:" + outputFile + "\" \"-lib:" + GetAssemblyPath() + "\" \"" + assemblyFile + "\""); + psi.UseShellExecute = false; + using (Process p = Process.Start(psi)) + { + p.WaitForExit(); + return p.ExitCode == 0; + } + } + + private string GetClassesPath() + { + return Path.Combine(Path.Combine("obj", "classes"), configuration); + } + + private bool RunJavac() + { + List paramList = new List(); + + paramList.Add("-bootclasspath"); + paramList.Add(Path.Combine(GetStubPath(), "rt.jar")); + + string stubpath = GetStubPath(); + StringBuilder sb = new StringBuilder(); + foreach (string file in Directory.GetFiles(stubpath, "*.jar")) + { + if (Path.GetFileName(file) != "rt.jar") + { + if (sb.Length != 0) + { + sb.Append(Path.PathSeparator); + } + sb.Append(file); + } + } + if (sb.Length != 0) + { + paramList.Add("-classpath"); + paramList.Add(sb.ToString()); + } + + string classes = GetClassesPath(); + Directory.CreateDirectory(classes); + paramList.Add("-d"); + paramList.Add(classes); + + if (emitDebugInformation) + { + paramList.Add("-g"); + } + + if (sources != null) + { + for (int i = 0; i < sources.Length; i++) + { + string sourceFile = Path.GetFullPath(sources[i].ItemSpec); + RemoveBOM(sourceFile); + paramList.Add(sourceFile); + } + } + + using (PrintWriter pw = new PrintWriter(new LogWriter(Log), true)) + { + //StringBuilder sb = new StringBuilder(); + //foreach (string str in paramList) + //{ + // sb.Append('"').Append(str).Append("\" "); + //} + //ProcessStartInfo psi = new ProcessStartInfo(Path.Combine(GetAssemblyPath(), "javac.exe"), sb.ToString()); + //psi.UseShellExecute = false; + //using (Process p = Process.Start(psi)) + //{ + // p.WaitForExit(); + // if (p.ExitCode != 0) + // { + // return false; + // } + //} + //return true; + return Javac.compile(paramList.ToArray(), pw) == 0; + } + } + + /// + /// Copy the DLLs of IKVM in the output + /// + private void CopyIkvm() + { + foreach (FileInfo file in new DirectoryInfo(GetAssemblyPath()).GetFiles("*.dll")) + { + string name = file.Name; + if (IsIkvmStandardLibrary(name)) + { + FileInfo target = new FileInfo(Path.Combine(outputPath, name)); + if (!target.Exists || file.Length != target.Length || file.CreationTime != target.CreationTime) + { + try + { + File.Copy(file.FullName, target.FullName, true); + target.CreationTime = file.CreationTime; + } + catch (Exception ex) + { + Log.LogWarningFromException(ex, true); + } + } + } + } + } + + /// + /// Check if the name the name of a library is a standard IKVM library which should not add as reference. + /// + /// The name of an assambly library + /// + private bool IsIkvmStandardLibrary(string fileName) + { + string name = Path.GetFileNameWithoutExtension(fileName); + if (name == "IKVM.Runtime") + { + return true; + } + if (name == "IKVM.OpenJDK.Tools") + { + return false; + } + if (name.StartsWith("IKVM.OpenJDK.")) + { + return true; + } + return false; + } + + /// + /// Java does not like a BOM at start of UTF8 coded files that we remove it + /// + /// The name of a Java source file + private void RemoveBOM(string fileName) + { + using (FileStream original = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.Read)) + { + if (original.ReadByte() == 0xef && original.ReadByte() == 0xbb && original.ReadByte() == 0xbf) + { + //BOM detected + string copyName = fileName + ".nobom"; + using (FileStream copy = File.OpenWrite(copyName)) + { + byte[] buffer = new byte[4096]; + int count; + while ((count = original.Read(buffer, 0, buffer.Length)) > 0) + { + copy.Write(buffer, 0, count); + } + } + File.Delete(fileName + ".withbom"); + File.Move(fileName, fileName + ".withbom"); + File.Move(copyName, fileName); + File.Delete(fileName + ".withbom"); + } + } + } + + /// + /// Redirect the output of the Java Compiler to the MSBUILD output + /// + private sealed class LogWriter : java.io.Writer + { + private readonly StringBuilder builder = new StringBuilder(); + private readonly TaskLoggingHelper log; + + internal LogWriter(TaskLoggingHelper log) + { + this.log = log; + } + + public override void write(char[] buf, int off, int len) + { + builder.Append(buf, off, len); + } + + public override void flush() + { + if (builder.Length > 0) + { + string msg = builder.ToString(); + if (msg.EndsWith("\r\n")) + { + msg = msg.Substring(0, msg.Length - 2); + } + // parsing the Java error line + if (msg.Length > 2 && msg[1] == ':') + { + int idx = msg.IndexOf(':', 2); + if (idx > 0) + { + string fileName = msg.Substring(0, idx); + idx++; + int idx2 = msg.IndexOf(':', idx); + if (idx2 > 0) + { + int lineNr; + if (Int32.TryParse(msg.Substring(idx, idx2 - idx), out lineNr)) + { + msg = msg.Substring(idx2 + 1); + idx = msg.IndexOf("error:"); + if (idx >= 0) + { + msg = msg.Substring(idx + 6).Trim(); + log.LogError(null, null, null, fileName, lineNr, 0, lineNr, 0, msg); + } + else + { + idx = msg.IndexOf("warning:"); + if (idx >= 0) + { + msg = msg.Substring(idx + 8).Trim(); + log.LogWarning(null, null, null, fileName, lineNr, 0, lineNr, 0, msg); + } + } + } + } + } + } + builder.Length = 0; + } + } + + public override void close() + { + flush(); + } + } + } +} diff --git a/msbuild/msbuild.build b/msbuild/msbuild.build new file mode 100644 index 0000000..53444d4 --- /dev/null +++ b/msbuild/msbuild.build @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/native/ikvm-native.rc b/native/ikvm-native.rc new file mode 100644 index 0000000..3eaffd4 --- /dev/null +++ b/native/ikvm-native.rc @@ -0,0 +1,30 @@ +//#include "winres.h" + +1 VERSIONINFO + FILEVERSION 8,1,5717,0 + PRODUCTVERSION 8,1,5717,0 + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "CompanyName", "Jeroen Frijters" + VALUE "FileDescription", "IKVM.NET OpenJDK Library for .NET" + VALUE "FileVersion", "8.1.5717.0" + VALUE "InternalName", "ikvm-native" + VALUE "LegalCopyright", "Copyright (C) 2002-2011 Jeroen Frijters" + VALUE "OriginalFilename", "ikvm-native-win32-x86.dll" + VALUE "ProductName", "IKVM.NET" + VALUE "ProductVersion", "8.1.5717.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END diff --git a/native/ikvm-native.rc.in b/native/ikvm-native.rc.in new file mode 100644 index 0000000..db04210 --- /dev/null +++ b/native/ikvm-native.rc.in @@ -0,0 +1,30 @@ +//#include "winres.h" + +1 VERSIONINFO + FILEVERSION @VERSIONLIST@ + PRODUCTVERSION @VERSIONLIST@ + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "CompanyName", "Jeroen Frijters" + VALUE "FileDescription", "IKVM.NET OpenJDK Library for .NET" + VALUE "FileVersion", "@VERSION@" + VALUE "InternalName", "ikvm-native" + VALUE "LegalCopyright", "Copyright (C) 2002-2011 Jeroen Frijters" + VALUE "OriginalFilename", "ikvm-native-win32-@ARCH@.dll" + VALUE "ProductName", "IKVM.NET" + VALUE "ProductVersion", "@VERSION@" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END diff --git a/native/jni.c b/native/jni.c new file mode 100644 index 0000000..146a45c --- /dev/null +++ b/native/jni.c @@ -0,0 +1,504 @@ +/* + Copyright (C) 2004 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +#include +#include "jni.h" + +#ifdef _WIN32 +#include +#define ALLOCA _alloca +#else +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +#include +#else +#include +#endif +#define ALLOCA alloca +#endif + +static jobject JNICALL NewObject(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...) +{ + jobject o; + va_list args; + va_start(args, methodID); + o = (*pEnv)->NewObjectV(pEnv, clazz, methodID, args); + va_end(args); + return o; +} + +#define MAKE_ARG_ARRAY(pEnv, args, argarray) \ +do { \ + jbyte sig[257];\ + int argc = (*pEnv)->GetMethodArgs(pEnv, methodID, sig);\ + int i;\ + argarray = (jvalue*)ALLOCA(argc * sizeof(jvalue));\ + for(i = 0; i < argc; i++)\ + {\ + switch(sig[i])\ + {\ + case 'Z':\ + case 'B':\ + case 'S':\ + case 'C':\ + case 'I':\ + argarray[i].i = va_arg(args, jint);\ + break;\ + case 'J':\ + argarray[i].j = va_arg(args, jlong);\ + break;\ + case 'L':\ + argarray[i].l = va_arg(args, jobject);\ + break;\ + case 'D':\ + argarray[i].d = va_arg(args, double);\ + break;\ + case 'F':\ + argarray[i].f = (float)va_arg(args, double);\ + break;\ + }\ + }\ +} while(0); + +static jobject JNICALL NewObjectV(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args) +{ + jvalue* argarray; + MAKE_ARG_ARRAY(pEnv, args, argarray); + return (*pEnv)->NewObjectA(pEnv, clazz, methodID, argarray); +} + +#define MAKE_METHOD(Type, type) \ +static type JNICALL Call##Type##Method(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...)\ +{\ + type ret;\ + va_list args;\ + va_start(args, methodID);\ + ret = (*pEnv)->Call##Type##MethodV(pEnv, obj, methodID, args);\ + va_end(args);\ + return ret;\ +}\ +static type JNICALL Call##Type##MethodV(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args)\ +{\ + jvalue* argarray;\ + MAKE_ARG_ARRAY(pEnv, args, argarray);\ + return (*pEnv)->Call##Type##MethodA(pEnv, obj, methodID, argarray);\ +}\ +static type JNICALL CallNonvirtual##Type##Method(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...)\ +{\ + type ret;\ + va_list args;\ + va_start(args, methodID);\ + ret = (*pEnv)->CallNonvirtual##Type##MethodV(pEnv, obj, clazz, methodID, args);\ + va_end(args);\ + return ret;\ +}\ +static type JNICALL CallNonvirtual##Type##MethodV(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args)\ +{\ + jvalue* argarray;\ + MAKE_ARG_ARRAY(pEnv, args, argarray);\ + return (*pEnv)->CallNonvirtual##Type##MethodA(pEnv, obj, clazz, methodID, argarray);\ +}\ +static type JNICALL CallStatic##Type##Method(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...)\ +{\ + type ret;\ + va_list args;\ + va_start(args, methodID);\ + ret = (*pEnv)->CallStatic##Type##MethodV(pEnv, clazz, methodID, args);\ + va_end(args);\ + return ret;\ +}\ +static type JNICALL CallStatic##Type##MethodV(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args)\ +{\ + jvalue* argarray;\ + MAKE_ARG_ARRAY(pEnv, args, argarray);\ + return (*pEnv)->CallStatic##Type##MethodA(pEnv, clazz, methodID, argarray);\ +} + +MAKE_METHOD(Object, jobject) +MAKE_METHOD(Boolean, jboolean) +MAKE_METHOD(Byte, jbyte) +MAKE_METHOD(Char, jchar) +MAKE_METHOD(Short, jshort) +MAKE_METHOD(Int, jint) +MAKE_METHOD(Long, jlong) +MAKE_METHOD(Float, jfloat) +MAKE_METHOD(Double, jdouble) + +static void JNICALL CallVoidMethod(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...) +{ + va_list args; + va_start(args, methodID); + (*pEnv)->CallVoidMethodV(pEnv, obj, methodID, args); + va_end(args); +} +static void JNICALL CallVoidMethodV(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args) +{ + jvalue* argarray; + MAKE_ARG_ARRAY(pEnv, args, argarray); + (*pEnv)->CallVoidMethodA(pEnv, obj, methodID, argarray); +} +static void JNICALL CallNonvirtualVoidMethod(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...) +{ + va_list args; + va_start(args, methodID); + (*pEnv)->CallNonvirtualVoidMethodV(pEnv, obj, clazz, methodID, args); + va_end(args); +} +static void JNICALL CallNonvirtualVoidMethodV(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args) +{ + jvalue* argarray; + MAKE_ARG_ARRAY(pEnv, args, argarray); + (*pEnv)->CallNonvirtualVoidMethodA(pEnv, obj, clazz, methodID, argarray); +} +static void JNICALL CallStaticVoidMethod(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...) +{ + va_list args; + va_start(args, methodID); + (*pEnv)->CallStaticVoidMethodV(pEnv, clazz, methodID, args); + va_end(args); +} +static void JNICALL CallStaticVoidMethodV(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args) +{ + jvalue* argarray; + MAKE_ARG_ARRAY(pEnv, args, argarray); + (*pEnv)->CallStaticVoidMethodA(pEnv, clazz, methodID, argarray); +} + +static void* JNIEnv_vtable[] = +{ + 0, // void JNICALL reserved0(); + 0, // void JNICALL reserved1(); + 0, // void JNICALL reserved2(); + 0, // void JNICALL reserved3(); + + 0, // jint JNICALL GetVersion(); + + 0, // jclass JNICALL DefineClass(const char *name, jobject loader, const jbyte *buf, jsize len); + 0, // jclass JNICALL FindClass(const char *name); + + 0, // jmethodID JNICALL FromReflectedMethod(jobject method); + 0, // jfieldID JNICALL FromReflectedField(jobject field); + 0, // jobject JNICALL ToReflectedMethod(jclass clazz, jmethodID methodID, jboolean isStatic); + + 0, // jclass JNICALL GetSuperclass(jclass sub); + 0, // jboolean JNICALL IsAssignableFrom(jclass sub, jclass sup); + + 0, // jobject JNICALL ToReflectedField(jclass clazz, jfieldID fieldID, jboolean isStatic); + + 0, // jint JNICALL Throw(jthrowable obj); + 0, // jint JNICALL ThrowNew(jclass clazz, const char *msg); + 0, // jthrowable JNICALL ExceptionOccurred(); + 0, // void JNICALL ExceptionDescribe(); + 0, // void JNICALL ExceptionClear(); + 0, // void JNICALL FatalError(const char *msg); + + 0, // jint JNICALL PushLocalFrame(jint capacity); + 0, // jobject JNICALL PopLocalFrame(jobject result); + + 0, // jobject JNICALL NewGlobalRef(jobject lobj); + 0, // void JNICALL DeleteGlobalRef(jobject gref); + 0, // void JNICALL DeleteLocalRef(jobject obj); + 0, // jboolean JNICALL IsSameObject(jobject obj1, jobject obj2); + + 0, // jobject JNICALL NewLocalRef(jobject ref); + 0, // jint JNICALL EnsureLocalCapacity(jint capacity); + + 0, // jobject JNICALL AllocObject(jclass clazz); + NewObject, // jobject JNICALL NewObject(jclass clazz, jmethodID methodID, ...); + NewObjectV, // jobject JNICALL NewObjectV(jclass clazz, jmethodID methodID, va_list args); + 0, // jobject JNICALL NewObjectA(jclass clazz, jmethodID methodID, jvalue *args); + + 0, // jclass JNICALL GetObjectClass(jobject obj); + 0, // jboolean JNICALL IsInstanceOf(jobject obj, jclass clazz); + + 0, // jmethodID JNICALL GetMethodID(jclass clazz, const char *name, const char *sig); + + CallObjectMethod, // jobject JNICALL CallObjectMethod(jobject obj, jmethodID methodID, ...); + CallObjectMethodV, // jobject JNICALL CallObjectMethodV(jobject obj, jmethodID methodID, va_list args); + 0, // jobject JNICALL CallObjectMethodA(jobject obj, jmethodID methodID, jvalue * args); + + CallBooleanMethod, // jboolean JNICALL CallBooleanMethod(jobject obj, jmethodID methodID, ...); + CallBooleanMethodV, // jboolean JNICALL CallBooleanMethodV(jobject obj, jmethodID methodID, va_list args); + 0, // jboolean JNICALL CallBooleanMethodA(jobject obj, jmethodID methodID, jvalue * args); + + CallByteMethod, // jbyte JNICALL CallByteMethod(jobject obj, jmethodID methodID, ...); + CallByteMethodV, // jbyte JNICALL CallByteMethodV(jobject obj, jmethodID methodID, va_list args); + 0, // jbyte JNICALL CallByteMethodA(jobject obj, jmethodID methodID, jvalue *args); + + CallCharMethod, // jchar JNICALL CallCharMethod(jobject obj, jmethodID methodID, ...); + CallCharMethodV, // jchar JNICALL CallCharMethodV(jobject obj, jmethodID methodID, va_list args); + 0, // jchar JNICALL CallCharMethodA(jobject obj, jmethodID methodID, jvalue *args); + + CallShortMethod, // jshort JNICALL CallShortMethod(jobject obj, jmethodID methodID, ...); + CallShortMethodV, // jshort JNICALL CallShortMethodV(jobject obj, jmethodID methodID, va_list args); + 0, // jshort JNICALL CallShortMethodA(jobject obj, jmethodID methodID, jvalue *args); + + CallIntMethod, // jint JNICALL CallIntMethod(jobject obj, jmethodID methodID, ...); + CallIntMethodV, // jint JNICALL CallIntMethodV(jobject obj, jmethodID methodID, va_list args); + 0, // jint JNICALL CallIntMethodA(jobject obj, jmethodID methodID, jvalue *args); + + CallLongMethod, // jlong JNICALL CallLongMethod(jobject obj, jmethodID methodID, ...); + CallLongMethodV, // jlong JNICALL CallLongMethodV(jobject obj, jmethodID methodID, va_list args); + 0, // jlong JNICALL CallLongMethodA(jobject obj, jmethodID methodID, jvalue *args); + + CallFloatMethod, // jfloat JNICALL CallFloatMethod(jobject obj, jmethodID methodID, ...); + CallFloatMethodV, // jfloat JNICALL CallFloatMethodV(jobject obj, jmethodID methodID, va_list args); + 0, // jfloat JNICALL CallFloatMethodA(jobject obj, jmethodID methodID, jvalue *args); + + CallDoubleMethod, // jdouble JNICALL CallDoubleMethod(jobject obj, jmethodID methodID, ...); + CallDoubleMethodV, // jdouble JNICALL CallDoubleMethodV(jobject obj, jmethodID methodID, va_list args); + 0, // jdouble JNICALL CallDoubleMethodA(jobject obj, jmethodID methodID, jvalue *args); + + CallVoidMethod, // void JNICALL CallVoidMethod(jobject obj, jmethodID methodID, ...); + CallVoidMethodV, // void JNICALL CallVoidMethodV(jobject obj, jmethodID methodID, va_list args); + 0, // void JNICALL CallVoidMethodA(jobject obj, jmethodID methodID, jvalue * args); + + CallNonvirtualObjectMethod, // jobject JNICALL CallNonvirtualObjectMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + CallNonvirtualObjectMethodV, // jobject JNICALL CallNonvirtualObjectMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + 0, // jobject JNICALL CallNonvirtualObjectMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args); + + CallNonvirtualBooleanMethod, // jboolean JNICALL CallNonvirtualBooleanMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + CallNonvirtualBooleanMethodV, // jboolean JNICALL CallNonvirtualBooleanMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + 0, // jboolean JNICALL CallNonvirtualBooleanMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args); + + CallNonvirtualByteMethod, // jbyte JNICALL CallNonvirtualByteMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + CallNonvirtualByteMethodV, // jbyte JNICALL CallNonvirtualByteMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + 0, // jbyte JNICALL CallNonvirtualByteMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + CallNonvirtualCharMethod, // jchar JNICALL CallNonvirtualCharMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + CallNonvirtualCharMethodV, // jchar JNICALL CallNonvirtualCharMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + 0, // jchar JNICALL CallNonvirtualCharMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + CallNonvirtualShortMethod, // jshort JNICALL CallNonvirtualShortMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + CallNonvirtualShortMethodV, // jshort JNICALL CallNonvirtualShortMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + 0, // jshort JNICALL CallNonvirtualShortMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + CallNonvirtualIntMethod, // jint JNICALL CallNonvirtualIntMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + CallNonvirtualIntMethodV, // jint JNICALL CallNonvirtualIntMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + 0, // jint JNICALL CallNonvirtualIntMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + CallNonvirtualLongMethod, // jlong JNICALL CallNonvirtualLongMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + CallNonvirtualLongMethodV, // jlong JNICALL CallNonvirtualLongMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + 0, // jlong JNICALL CallNonvirtualLongMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + CallNonvirtualFloatMethod, // jfloat JNICALL CallNonvirtualFloatMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + CallNonvirtualFloatMethodV, // jfloat JNICALL CallNonvirtualFloatMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + 0, // jfloat JNICALL CallNonvirtualFloatMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + CallNonvirtualDoubleMethod, // jdouble JNICALL CallNonvirtualDoubleMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + CallNonvirtualDoubleMethodV, // jdouble JNICALL CallNonvirtualDoubleMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + 0, // jdouble JNICALL CallNonvirtualDoubleMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + CallNonvirtualVoidMethod, // void JNICALL CallNonvirtualVoidMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + CallNonvirtualVoidMethodV, // void JNICALL CallNonvirtualVoidMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + 0, // void JNICALL CallNonvirtualVoidMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args); + + 0, // jfieldID JNICALL GetFieldID(jclass clazz, const char *name, const char *sig); + + 0, // jobject JNICALL GetObjectField(jobject obj, jfieldID fieldID); + 0, // jboolean JNICALL GetBooleanField(jobject obj, jfieldID fieldID); + 0, // jbyte JNICALL GetByteField(jobject obj, jfieldID fieldID); + 0, // jchar JNICALL GetCharField(jobject obj, jfieldID fieldID); + 0, // jshort JNICALL GetShortField(jobject obj, jfieldID fieldID); + 0, // jint JNICALL GetIntField(jobject obj, jfieldID fieldID); + 0, // jlong JNICALL GetLongField(jobject obj, jfieldID fieldID); + 0, // jfloat JNICALL GetFloatField(jobject obj, jfieldID fieldID); + 0, // jdouble JNICALL GetDoubleField(jobject obj, jfieldID fieldID); + + 0, // void JNICALL SetObjectField(jobject obj, jfieldID fieldID, jobject val); + 0, // void JNICALL SetBooleanField(jobject obj, jfieldID fieldID, jboolean val); + 0, // void JNICALL SetByteField(jobject obj, jfieldID fieldID, jbyte val); + 0, // void JNICALL SetCharField(jobject obj, jfieldID fieldID, jchar val); + 0, // void JNICALL SetShortField(jobject obj, jfieldID fieldID, jshort val); + 0, // void JNICALL SetIntField(jobject obj, jfieldID fieldID, jint val); + 0, // void JNICALL SetLongField(jobject obj, jfieldID fieldID, jlong val); + 0, // void JNICALL SetFloatField(jobject obj, jfieldID fieldID, jfloat val); + 0, // void JNICALL SetDoubleField(jobject obj, jfieldID fieldID, jdouble val); + + 0, // jmethodID JNICALL GetStaticMethodID(jclass clazz, const char *name, const char *sig); + + CallStaticObjectMethod, // jobject JNICALL CallStaticObjectMethod(jclass clazz, jmethodID methodID, ...); + CallStaticObjectMethodV, // jobject JNICALL CallStaticObjectMethodV(jclass clazz, jmethodID methodID, va_list args); + 0, // jobject JNICALL CallStaticObjectMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + CallStaticBooleanMethod, // jboolean JNICALL CallStaticBooleanMethod(jclass clazz, jmethodID methodID, ...); + CallStaticBooleanMethodV, // jboolean JNICALL CallStaticBooleanMethodV(jclass clazz, jmethodID methodID, va_list args); + 0, // jboolean JNICALL CallStaticBooleanMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + CallStaticByteMethod, // jbyte JNICALL CallStaticByteMethod(jclass clazz, jmethodID methodID, ...); + CallStaticByteMethodV, // jbyte JNICALL CallStaticByteMethodV(jclass clazz, jmethodID methodID, va_list args); + 0, // jbyte JNICALL CallStaticByteMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + CallStaticCharMethod, // jchar JNICALL CallStaticCharMethod(jclass clazz, jmethodID methodID, ...); + CallStaticCharMethodV, // jchar JNICALL CallStaticCharMethodV(jclass clazz, jmethodID methodID, va_list args); + 0, // jchar JNICALL CallStaticCharMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + CallStaticShortMethod, // jshort JNICALL CallStaticShortMethod(jclass clazz, jmethodID methodID, ...); + CallStaticShortMethodV, // jshort JNICALL CallStaticShortMethodV(jclass clazz, jmethodID methodID, va_list args); + 0, // jshort JNICALL CallStaticShortMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + CallStaticIntMethod, // jint JNICALL CallStaticIntMethod(jclass clazz, jmethodID methodID, ...); + CallStaticIntMethodV, // jint JNICALL CallStaticIntMethodV(jclass clazz, jmethodID methodID, va_list args); + 0, // jint JNICALL CallStaticIntMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + CallStaticLongMethod, // jlong JNICALL CallStaticLongMethod(jclass clazz, jmethodID methodID, ...); + CallStaticLongMethodV, // jlong JNICALL CallStaticLongMethodV(jclass clazz, jmethodID methodID, va_list args); + 0, // jlong JNICALL CallStaticLongMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + CallStaticFloatMethod, // jfloat JNICALL CallStaticFloatMethod(jclass clazz, jmethodID methodID, ...); + CallStaticFloatMethodV, // jfloat JNICALL CallStaticFloatMethodV(jclass clazz, jmethodID methodID, va_list args); + 0, // jfloat JNICALL CallStaticFloatMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + CallStaticDoubleMethod, // jdouble JNICALL CallStaticDoubleMethod(jclass clazz, jmethodID methodID, ...); + CallStaticDoubleMethodV, // jdouble JNICALL CallStaticDoubleMethodV(jclass clazz, jmethodID methodID, va_list args); + 0, // jdouble JNICALL CallStaticDoubleMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + CallStaticVoidMethod, // void JNICALL CallStaticVoidMethod(jclass cls, jmethodID methodID, ...); + CallStaticVoidMethodV, // void JNICALL CallStaticVoidMethodV(jclass cls, jmethodID methodID, va_list args); + 0, // void JNICALL CallStaticVoidMethodA(jclass cls, jmethodID methodID, jvalue * args); + + 0, // jfieldID JNICALL GetStaticFieldID(jclass clazz, const char *name, const char *sig); + + 0, // jobject JNICALL GetObjectField(jobject obj, jfieldID fieldID); + 0, // jboolean JNICALL GetBooleanField(jobject obj, jfieldID fieldID); + 0, // jbyte JNICALL GetByteField(jobject obj, jfieldID fieldID); + 0, // jchar JNICALL GetCharField(jobject obj, jfieldID fieldID); + 0, // jshort JNICALL GetShortField(jobject obj, jfieldID fieldID); + 0, // jint JNICALL GetIntField(jobject obj, jfieldID fieldID); + 0, // jlong JNICALL GetLongField(jobject obj, jfieldID fieldID); + 0, // jfloat JNICALL GetFloatField(jobject obj, jfieldID fieldID); + 0, // jdouble JNICALL GetDoubleField(jobject obj, jfieldID fieldID); + + 0, // void JNICALL SetObjectField(jobject obj, jfieldID fieldID, jobject val); + 0, // void JNICALL SetBooleanField(jobject obj, jfieldID fieldID, jboolean val); + 0, // void JNICALL SetByteField(jobject obj, jfieldID fieldID, jbyte val); + 0, // void JNICALL SetCharField(jobject obj, jfieldID fieldID, jchar val); + 0, // void JNICALL SetShortField(jobject obj, jfieldID fieldID, jshort val); + 0, // void JNICALL SetIntField(jobject obj, jfieldID fieldID, jint val); + 0, // void JNICALL SetLongField(jobject obj, jfieldID fieldID, jlong val); + 0, // void JNICALL SetFloatField(jobject obj, jfieldID fieldID, jfloat val); + 0, // void JNICALL SetDoubleField(jobject obj, jfieldID fieldID, jdouble val); + + 0, // jstring JNICALL NewString(const jchar *unicode, jsize len); + 0, // jsize JNICALL GetStringLength(jstring str); + 0, // const jchar *JNICALL GetStringChars(jstring str, jboolean *isCopy); + 0, // void JNICALL ReleaseStringChars(jstring str, const jchar *chars); + + 0, // jstring JNICALL NewStringUTF(const char *utf); + 0, // jsize JNICALL GetStringUTFLength(jstring str); + 0, // const char* JNICALL GetStringUTFChars(jstring str, jboolean *isCopy); + 0, // void JNICALL ReleaseStringUTFChars(jstring str, const char* chars); + + 0, // jsize JNICALL GetArrayLength(jarray array); + + 0, // jobjectArray JNICALL NewObjectArray(jsize len, jclass clazz, jobject init); + 0, // jobject JNICALL GetObjectArrayElement(jobjectArray array, jsize index); + 0, // void JNICALL SetObjectArrayElement(jobjectArray array, jsize index, jobject val); + + 0, // jbooleanArray JNICALL NewBooleanArray(jsize len); + 0, // jbyteArray JNICALL NewByteArray(jsize len); + 0, // jcharArray JNICALL NewCharArray(jsize len); + 0, // jshortArray JNICALL NewShortArray(jsize len); + 0, // jintArray JNICALL NewIntArray(jsize len); + 0, // jlongArray JNICALL NewLongArray(jsize len); + 0, // jfloatArray JNICALL NewFloatArray(jsize len); + 0, // jdoubleArray JNICALL NewDoubleArray(jsize len); + + 0, // jboolean * JNICALL GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy); + 0, // jbyte * JNICALL GetByteArrayElements(jbyteArray array, jboolean *isCopy); + 0, // jchar * JNICALL GetCharArrayElements(jcharArray array, jboolean *isCopy); + 0, // jshort * JNICALL GetShortArrayElements(jshortArray array, jboolean *isCopy); + 0, // jint * JNICALL GetIntArrayElements(jintArray array, jboolean *isCopy); + 0, // jlong * JNICALL GetLongArrayElements(jlongArray array, jboolean *isCopy); + 0, // jfloat * JNICALL GetFloatArrayElements(jfloatArray array, jboolean *isCopy); + 0, // jdouble * JNICALL GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy); + + 0, // void JNICALL ReleaseBooleanArrayElements(jbooleanArray array, jboolean *elems, jint mode); + 0, // void JNICALL ReleaseByteArrayElements(jbyteArray array, jbyte *elems, jint mode); + 0, // void JNICALL ReleaseCharArrayElements(jcharArray array, jchar *elems, jint mode); + 0, // void JNICALL ReleaseShortArrayElements(jshortArray array, jshort *elems, jint mode); + 0, // void JNICALL ReleaseIntArrayElements(jintArray array, jint *elems, jint mode); + 0, // void JNICALL ReleaseLongArrayElements(jlongArray array, jlong *elems, jint mode); + 0, // void JNICALL ReleaseFloatArrayElements(jfloatArray array, jfloat *elems, jint mode); + 0, // void JNICALL ReleaseDoubleArrayElements(jdoubleArray array, jdouble *elems, jint mode); + + 0, // void JNICALL GetBooleanArrayRegion(jbooleanArray array, jsize start, jsize l, jboolean *buf); + 0, // void JNICALL GetByteArrayRegion(jbyteArray array, jsize start, jsize len, jbyte *buf); + 0, // void JNICALL GetCharArrayRegion(jcharArray array, jsize start, jsize len, jchar *buf); + 0, // void JNICALL GetShortArrayRegion(jshortArray array, jsize start, jsize len, jshort *buf); + 0, // void JNICALL GetIntArrayRegion(jintArray array, jsize start, jsize len, jint *buf); + 0, // void JNICALL GetLongArrayRegion(jlongArray array, jsize start, jsize len, jlong *buf); + 0, // void JNICALL GetFloatArrayRegion(jfloatArray array, jsize start, jsize len, jfloat *buf); + 0, // void JNICALL GetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, jdouble *buf); + + 0, // void JNICALL SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize l, jboolean *buf); + 0, // void JNICALL SetByteArrayRegion(jbyteArray array, jsize start, jsize len, jbyte *buf); + 0, // void JNICALL SetCharArrayRegion(jcharArray array, jsize start, jsize len, jchar *buf); + 0, // void JNICALL SetShortArrayRegion(jshortArray array, jsize start, jsize len, jshort *buf); + 0, // void JNICALL SetIntArrayRegion(jintArray array, jsize start, jsize len, jint *buf); + 0, // void JNICALL SetLongArrayRegion(jlongArray array, jsize start, jsize len, jlong *buf); + 0, // void JNICALL SetFloatArrayRegion(jfloatArray array, jsize start, jsize len, jfloat *buf); + 0, // void JNICALL SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, jdouble *buf); + + 0, // jint JNICALL RegisterNatives(jclass clazz, const JNINativeMethod *methods, jint nMethods); + 0, // jint JNICALL UnregisterNatives(jclass clazz); + + 0, // jint JNICALL MonitorEnter(jobject obj); + 0, // jint JNICALL MonitorExit(jobject obj); + + 0, // jint JNICALL GetJavaVM(JavaVM **vm); + + 0, // void JNICALL GetStringRegion(jstring str, jsize start, jsize len, jchar *buf); + 0, // void JNICALL GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf); + + 0, // void* JNICALL GetPrimitiveArrayCritical(jarray array, jboolean *isCopy); + 0, // void JNICALL ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode); + + 0, // const jchar* JNICALL GetStringCritical(jstring string, jboolean *isCopy); + 0, // void JNICALL ReleaseStringCritical(jstring string, const jchar *cstring); + + 0, // jweak JNICALL NewWeakGlobalRef(jobject obj); + 0, // void JNICALL DeleteWeakGlobalRef(jweak ref); + + 0, // jboolean JNICALL ExceptionCheck(); + + 0, // jobject JNICALL NewDirectByteBuffer(void* address, jlong capacity); + 0, // void* JNICALL GetDirectBufferAddress(jobject buf); + 0 // jlong JNICALL GetDirectBufferCapacity(jobject buf); +}; + +JNIEXPORT void** JNICALL ikvm_GetJNIEnvVTable() +{ + return JNIEnv_vtable; +} + +JNIEXPORT void* JNICALL ikvm_MarshalDelegate(void* p) +{ + return p; +} + +typedef jint (JNICALL *PJNI_ONLOAD)(JavaVM* vm, void* reserved); + +JNIEXPORT jint JNICALL ikvm_CallOnLoad(PJNI_ONLOAD method, JavaVM* vm, void* reserved) +{ + return method(vm, reserved); +} diff --git a/native/jni.h b/native/jni.h new file mode 100644 index 0000000..5ad3d2c --- /dev/null +++ b/native/jni.h @@ -0,0 +1,406 @@ +/* + Copyright (C) 2004, 2005 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +#ifndef __JNI_H__ +#define __JNI_H__ + +#include + +#ifdef _WIN32 + #define JNICALL __stdcall + #ifdef __cplusplus + #define JNIEXPORT extern "C" __declspec(dllexport) + #else + #define JNIEXPORT __declspec(dllexport) + #endif +#else + #define JNICALL + #ifdef __cplusplus + #define JNIEXPORT extern "C" + #else + #define JNIEXPORT + #endif + #include +#endif + +typedef void* jobject; +typedef void* jstring; +typedef void* jweak; +typedef void* jthrowable; +typedef void* jclass; +typedef void* jmethodID; +typedef void* jfieldID; +typedef void* jarray; +typedef void* jobjectArray; +typedef void* jbooleanArray; +typedef void* jbyteArray; +typedef void* jcharArray; +typedef void* jshortArray; +typedef void* jintArray; +typedef void* jlongArray; +typedef void* jfloatArray; +typedef void* jdoubleArray; + +typedef unsigned char jboolean; +typedef signed char jbyte; +typedef unsigned short jchar; +typedef short jshort; +typedef int jint; +#ifdef _MSC_VER + typedef __int64 jlong; +#else + typedef long long int jlong; +#endif +typedef float jfloat; +typedef double jdouble; +typedef jint jsize; + +#define JNI_FALSE 0 +#define JNI_TRUE 1 + +typedef struct +{ + char *name; + char *signature; + void *fnPtr; +} JNINativeMethod; + +typedef union jvalue +{ + jboolean z; + jbyte b; + jchar c; + jshort s; + jint i; + jlong j; + jfloat f; + jdouble d; + jobject l; +} jvalue; + +typedef void* JavaVM; +typedef struct JNIEnv_methods *JNIEnv; + +struct JNIEnv_methods +{ + jint (JNICALL *GetMethodArgs)(JNIEnv* pEnv, jmethodID method, jbyte* sig); + void (JNICALL *reserved1)(JNIEnv* pEnv); + void (JNICALL *reserved2)(JNIEnv* pEnv); + void (JNICALL *reserved3)(JNIEnv* pEnv); + + jint (JNICALL *GetVersion)(JNIEnv* pEnv); + + jclass (JNICALL *DefineClass)(JNIEnv* pEnv, const char *name, jobject loader, const jbyte *buf, jsize len); + jclass (JNICALL *FindClass)(JNIEnv* pEnv, const char *name); + + jmethodID (JNICALL *FromReflectedMethod)(JNIEnv* pEnv, jobject method); + jfieldID (JNICALL *FromReflectedField)(JNIEnv* pEnv, jobject field); + jobject (JNICALL *ToReflectedMethod)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jboolean isStatic); + + jclass (JNICALL *GetSuperclass)(JNIEnv* pEnv, jclass sub); + jboolean (JNICALL *IsAssignableFrom)(JNIEnv* pEnv, jclass sub, jclass sup); + + jobject (JNICALL *ToReflectedField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jboolean isStatic); + + jint (JNICALL *Throw)(JNIEnv* pEnv, jthrowable obj); + jint (JNICALL *ThrowNew)(JNIEnv* pEnv, jclass clazz, const char *msg); + jthrowable (JNICALL *ExceptionOccurred)(JNIEnv* pEnv); + void (JNICALL *ExceptionDescribe)(JNIEnv* pEnv); + void (JNICALL *ExceptionClear)(JNIEnv* pEnv); + void (JNICALL *FatalError)(JNIEnv* pEnv, const char *msg); + + jint (JNICALL *PushLocalFrame)(JNIEnv* pEnv, jint capacity); + jobject (JNICALL *PopLocalFrame)(JNIEnv* pEnv, jobject result); + + jobject (JNICALL *NewGlobalRef)(JNIEnv* pEnv, jobject lobj); + void (JNICALL *DeleteGlobalRef)(JNIEnv* pEnv, jobject gref); + void (JNICALL *DeleteLocalRef)(JNIEnv* pEnv, jobject obj); + jboolean (JNICALL *IsSameObject)(JNIEnv* pEnv, jobject obj1, jobject obj2); + + jobject (JNICALL *NewLocalRef)(JNIEnv* pEnv, jobject ref); + jint (JNICALL *EnsureLocalCapacity)(JNIEnv* pEnv, jint capacity); + + jobject (JNICALL *AllocObject)(JNIEnv* pEnv, jclass clazz); + jobject (JNICALL *NewObject)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...); + jobject (JNICALL *NewObjectV)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args); + jobject (JNICALL *NewObjectA)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args); + + jclass (JNICALL *GetObjectClass)(JNIEnv* pEnv, jobject obj); + jboolean (JNICALL *IsInstanceOf)(JNIEnv* pEnv, jobject obj, jclass clazz); + + jmethodID (JNICALL *GetMethodID)(JNIEnv* pEnv, jclass clazz, const char *name, const char *sig); + + jobject (JNICALL *CallObjectMethod)(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...); + jobject (JNICALL *CallObjectMethodV)(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args); + jobject (JNICALL *CallObjectMethodA)(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue * args); + + jboolean (JNICALL *CallBooleanMethod)(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...); + jboolean (JNICALL *CallBooleanMethodV)(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args); + jboolean (JNICALL *CallBooleanMethodA)(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue * args); + + jbyte (JNICALL *CallByteMethod)(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...); + jbyte (JNICALL *CallByteMethodV)(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args); + jbyte (JNICALL *CallByteMethodA)(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue *args); + + jchar (JNICALL *CallCharMethod)(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...); + jchar (JNICALL *CallCharMethodV)(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args); + jchar (JNICALL *CallCharMethodA)(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue *args); + + jshort (JNICALL *CallShortMethod)(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...); + jshort (JNICALL *CallShortMethodV)(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args); + jshort (JNICALL *CallShortMethodA)(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue *args); + + jint (JNICALL *CallIntMethod)(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...); + jint (JNICALL *CallIntMethodV)(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args); + jint (JNICALL *CallIntMethodA)(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue *args); + + jlong (JNICALL *CallLongMethod)(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...); + jlong (JNICALL *CallLongMethodV)(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args); + jlong (JNICALL *CallLongMethodA)(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue *args); + + jfloat (JNICALL *CallFloatMethod)(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...); + jfloat (JNICALL *CallFloatMethodV)(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args); + jfloat (JNICALL *CallFloatMethodA)(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue *args); + + jdouble (JNICALL *CallDoubleMethod)(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...); + jdouble (JNICALL *CallDoubleMethodV)(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args); + jdouble (JNICALL *CallDoubleMethodA)(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue *args); + + void (JNICALL *CallVoidMethod)(JNIEnv* pEnv, jobject obj, jmethodID methodID, ...); + void (JNICALL *CallVoidMethodV)(JNIEnv* pEnv, jobject obj, jmethodID methodID, va_list args); + void (JNICALL *CallVoidMethodA)(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue * args); + + jobject (JNICALL *CallNonvirtualObjectMethod)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...); + jobject (JNICALL *CallNonvirtualObjectMethodV)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args); + jobject (JNICALL *CallNonvirtualObjectMethodA)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue * args); + + jboolean (JNICALL *CallNonvirtualBooleanMethod)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...); + jboolean (JNICALL *CallNonvirtualBooleanMethodV)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args); + jboolean (JNICALL *CallNonvirtualBooleanMethodA)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue * args); + + jbyte (JNICALL *CallNonvirtualByteMethod)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...); + jbyte (JNICALL *CallNonvirtualByteMethodV)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args); + jbyte (JNICALL *CallNonvirtualByteMethodA)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + jchar (JNICALL *CallNonvirtualCharMethod)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...); + jchar (JNICALL *CallNonvirtualCharMethodV)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args); + jchar (JNICALL *CallNonvirtualCharMethodA)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + jshort (JNICALL *CallNonvirtualShortMethod)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...); + jshort (JNICALL *CallNonvirtualShortMethodV)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args); + jshort (JNICALL *CallNonvirtualShortMethodA)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + jint (JNICALL *CallNonvirtualIntMethod)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...); + jint (JNICALL *CallNonvirtualIntMethodV)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args); + jint (JNICALL *CallNonvirtualIntMethodA)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + jlong (JNICALL *CallNonvirtualLongMethod)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...); + jlong (JNICALL *CallNonvirtualLongMethodV)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args); + jlong (JNICALL *CallNonvirtualLongMethodA)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + jfloat (JNICALL *CallNonvirtualFloatMethod)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...); + jfloat (JNICALL *CallNonvirtualFloatMethodV)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args); + jfloat (JNICALL *CallNonvirtualFloatMethodA)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + jdouble (JNICALL *CallNonvirtualDoubleMethod)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...); + jdouble (JNICALL *CallNonvirtualDoubleMethodV)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args); + jdouble (JNICALL *CallNonvirtualDoubleMethodA)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + void (JNICALL *CallNonvirtualVoidMethod)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, ...); + void (JNICALL *CallNonvirtualVoidMethodV)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, va_list args); + void (JNICALL *CallNonvirtualVoidMethodA)(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue * args); + + jfieldID (JNICALL *GetFieldID)(JNIEnv* pEnv, jclass clazz, const char *name, const char *sig); + + jobject (JNICALL *GetObjectField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID); + jboolean (JNICALL *GetBooleanField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID); + jbyte (JNICALL *GetByteField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID); + jchar (JNICALL *GetCharField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID); + jshort (JNICALL *GetShortField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID); + jint (JNICALL *GetIntField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID); + jlong (JNICALL *GetLongField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID); + jfloat (JNICALL *GetFloatField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID); + jdouble (JNICALL *GetDoubleField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID); + + void (JNICALL *SetObjectField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jobject val); + void (JNICALL *SetBooleanField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jboolean val); + void (JNICALL *SetByteField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jbyte val); + void (JNICALL *SetCharField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jchar val); + void (JNICALL *SetShortField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jshort val); + void (JNICALL *SetIntField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jint val); + void (JNICALL *SetLongField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jlong val); + void (JNICALL *SetFloatField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jfloat val); + void (JNICALL *SetDoubleField)(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jdouble val); + + jmethodID (JNICALL *GetStaticMethodID)(JNIEnv* pEnv, jclass clazz, const char *name, const char *sig); + + jobject (JNICALL *CallStaticObjectMethod)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...); + jobject (JNICALL *CallStaticObjectMethodV)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args); + jobject (JNICALL *CallStaticObjectMethodA)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args); + + jboolean (JNICALL *CallStaticBooleanMethod)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...); + jboolean (JNICALL *CallStaticBooleanMethodV)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args); + jboolean (JNICALL *CallStaticBooleanMethodA)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args); + + jbyte (JNICALL *CallStaticByteMethod)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...); + jbyte (JNICALL *CallStaticByteMethodV)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args); + jbyte (JNICALL *CallStaticByteMethodA)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args); + + jchar (JNICALL *CallStaticCharMethod)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...); + jchar (JNICALL *CallStaticCharMethodV)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args); + jchar (JNICALL *CallStaticCharMethodA)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args); + + jshort (JNICALL *CallStaticShortMethod)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...); + jshort (JNICALL *CallStaticShortMethodV)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args); + jshort (JNICALL *CallStaticShortMethodA)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args); + + jint (JNICALL *CallStaticIntMethod)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...); + jint (JNICALL *CallStaticIntMethodV)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args); + jint (JNICALL *CallStaticIntMethodA)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args); + + jlong (JNICALL *CallStaticLongMethod)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...); + jlong (JNICALL *CallStaticLongMethodV)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args); + jlong (JNICALL *CallStaticLongMethodA)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args); + + jfloat (JNICALL *CallStaticFloatMethod)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...); + jfloat (JNICALL *CallStaticFloatMethodV)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args); + jfloat (JNICALL *CallStaticFloatMethodA)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args); + + jdouble (JNICALL *CallStaticDoubleMethod)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, ...); + jdouble (JNICALL *CallStaticDoubleMethodV)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, va_list args); + jdouble (JNICALL *CallStaticDoubleMethodA)(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args); + + void (JNICALL *CallStaticVoidMethod)(JNIEnv* pEnv, jclass cls, jmethodID methodID, ...); + void (JNICALL *CallStaticVoidMethodV)(JNIEnv* pEnv, jclass cls, jmethodID methodID, va_list args); + void (JNICALL *CallStaticVoidMethodA)(JNIEnv* pEnv, jclass cls, jmethodID methodID, jvalue * args); + + jfieldID (JNICALL *GetStaticFieldID)(JNIEnv* pEnv, jclass clazz, const char *name, const char *sig); + jobject (JNICALL *GetStaticObjectField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID); + jboolean (JNICALL *GetStaticBooleanField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID); + jbyte (JNICALL *GetStaticByteField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID); + jchar (JNICALL *GetStaticCharField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID); + jshort (JNICALL *GetStaticShortField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID); + jint (JNICALL *GetStaticIntField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID); + jlong (JNICALL *GetStaticLongField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID); + jfloat (JNICALL *GetStaticFloatField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID); + jdouble (JNICALL *GetStaticDoubleField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID); + + void (JNICALL *SetStaticObjectField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jobject value); + void (JNICALL *SetStaticBooleanField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jboolean value); + void (JNICALL *SetStaticByteField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jbyte value); + void (JNICALL *SetStaticCharField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jchar value); + void (JNICALL *SetStaticShortField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jshort value); + void (JNICALL *SetStaticIntField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jint value); + void (JNICALL *SetStaticLongField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jlong value); + void (JNICALL *SetStaticFloatField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jfloat value); + void (JNICALL *SetStaticDoubleField)(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jdouble value); + + jstring (JNICALL *NewString)(JNIEnv* pEnv, const jchar *unicode, jsize len); + jsize (JNICALL *GetStringLength)(JNIEnv* pEnv, jstring str); + const jchar *(JNICALL *GetStringChars)(JNIEnv* pEnv, jstring str, jboolean *isCopy); + void (JNICALL *ReleaseStringChars)(JNIEnv* pEnv, jstring str, const jchar *chars); + + jstring (JNICALL *NewStringUTF)(JNIEnv* pEnv, const char *utf); + jsize (JNICALL *GetStringUTFLength)(JNIEnv* pEnv, jstring str); + const char* (JNICALL *GetStringUTFChars)(JNIEnv* pEnv, jstring str, jboolean *isCopy); + void (JNICALL *ReleaseStringUTFChars)(JNIEnv* pEnv, jstring str, const char* chars); + + jsize (JNICALL *GetArrayLength)(JNIEnv* pEnv, jarray array); + + jobjectArray (JNICALL *NewObjectArray)(JNIEnv* pEnv, jsize len, jclass clazz, jobject init); + jobject (JNICALL *GetObjectArrayElement)(JNIEnv* pEnv, jobjectArray array, jsize index); + void (JNICALL *SetObjectArrayElement)(JNIEnv* pEnv, jobjectArray array, jsize index, jobject val); + + jbooleanArray (JNICALL *NewBooleanArray)(JNIEnv* pEnv, jsize len); + jbyteArray (JNICALL *NewByteArray)(JNIEnv* pEnv, jsize len); + jcharArray (JNICALL *NewCharArray)(JNIEnv* pEnv, jsize len); + jshortArray (JNICALL *NewShortArray)(JNIEnv* pEnv, jsize len); + jintArray (JNICALL *NewIntArray)(JNIEnv* pEnv, jsize len); + jlongArray (JNICALL *NewLongArray)(JNIEnv* pEnv, jsize len); + jfloatArray (JNICALL *NewFloatArray)(JNIEnv* pEnv, jsize len); + jdoubleArray (JNICALL *NewDoubleArray)(JNIEnv* pEnv, jsize len); + + jboolean * (JNICALL *GetBooleanArrayElements)(JNIEnv* pEnv, jbooleanArray array, jboolean *isCopy); + jbyte * (JNICALL *GetByteArrayElements)(JNIEnv* pEnv, jbyteArray array, jboolean *isCopy); + jchar * (JNICALL *GetCharArrayElements)(JNIEnv* pEnv, jcharArray array, jboolean *isCopy); + jshort * (JNICALL *GetShortArrayElements)(JNIEnv* pEnv, jshortArray array, jboolean *isCopy); + jint * (JNICALL *GetIntArrayElements)(JNIEnv* pEnv, jintArray array, jboolean *isCopy); + jlong * (JNICALL *GetLongArrayElements)(JNIEnv* pEnv, jlongArray array, jboolean *isCopy); + jfloat * (JNICALL *GetFloatArrayElements)(JNIEnv* pEnv, jfloatArray array, jboolean *isCopy); + jdouble * (JNICALL *GetDoubleArrayElements)(JNIEnv* pEnv, jdoubleArray array, jboolean *isCopy); + + void (JNICALL *ReleaseBooleanArrayElements)(JNIEnv* pEnv, jbooleanArray array, jboolean *elems, jint mode); + void (JNICALL *ReleaseByteArrayElements)(JNIEnv* pEnv, jbyteArray array, jbyte *elems, jint mode); + void (JNICALL *ReleaseCharArrayElements)(JNIEnv* pEnv, jcharArray array, jchar *elems, jint mode); + void (JNICALL *ReleaseShortArrayElements)(JNIEnv* pEnv, jshortArray array, jshort *elems, jint mode); + void (JNICALL *ReleaseIntArrayElements)(JNIEnv* pEnv, jintArray array, jint *elems, jint mode); + void (JNICALL *ReleaseLongArrayElements)(JNIEnv* pEnv, jlongArray array, jlong *elems, jint mode); + void (JNICALL *ReleaseFloatArrayElements)(JNIEnv* pEnv, jfloatArray array, jfloat *elems, jint mode); + void (JNICALL *ReleaseDoubleArrayElements)(JNIEnv* pEnv, jdoubleArray array, jdouble *elems, jint mode); + + void (JNICALL *GetBooleanArrayRegion)(JNIEnv* pEnv, jbooleanArray array, jsize start, jsize l, jboolean *buf); + void (JNICALL *GetByteArrayRegion)(JNIEnv* pEnv, jbyteArray array, jsize start, jsize len, jbyte *buf); + void (JNICALL *GetCharArrayRegion)(JNIEnv* pEnv, jcharArray array, jsize start, jsize len, jchar *buf); + void (JNICALL *GetShortArrayRegion)(JNIEnv* pEnv, jshortArray array, jsize start, jsize len, jshort *buf); + void (JNICALL *GetIntArrayRegion)(JNIEnv* pEnv, jintArray array, jsize start, jsize len, jint *buf); + void (JNICALL *GetLongArrayRegion)(JNIEnv* pEnv, jlongArray array, jsize start, jsize len, jlong *buf); + void (JNICALL *GetFloatArrayRegion)(JNIEnv* pEnv, jfloatArray array, jsize start, jsize len, jfloat *buf); + void (JNICALL *GetDoubleArrayRegion)(JNIEnv* pEnv, jdoubleArray array, jsize start, jsize len, jdouble *buf); + + void (JNICALL *SetBooleanArrayRegion)(JNIEnv* pEnv, jbooleanArray array, jsize start, jsize l, jboolean *buf); + void (JNICALL *SetByteArrayRegion)(JNIEnv* pEnv, jbyteArray array, jsize start, jsize len, jbyte *buf); + void (JNICALL *SetCharArrayRegion)(JNIEnv* pEnv, jcharArray array, jsize start, jsize len, jchar *buf); + void (JNICALL *SetShortArrayRegion)(JNIEnv* pEnv, jshortArray array, jsize start, jsize len, jshort *buf); + void (JNICALL *SetIntArrayRegion)(JNIEnv* pEnv, jintArray array, jsize start, jsize len, jint *buf); + void (JNICALL *SetLongArrayRegion)(JNIEnv* pEnv, jlongArray array, jsize start, jsize len, jlong *buf); + void (JNICALL *SetFloatArrayRegion)(JNIEnv* pEnv, jfloatArray array, jsize start, jsize len, jfloat *buf); + void (JNICALL *SetDoubleArrayRegion)(JNIEnv* pEnv, jdoubleArray array, jsize start, jsize len, jdouble *buf); + + jint (JNICALL *RegisterNatives)(JNIEnv* pEnv, jclass clazz, const JNINativeMethod *methods, jint nMethods); + jint (JNICALL *UnregisterNatives)(JNIEnv* pEnv, jclass clazz); + + jint (JNICALL *MonitorEnter)(JNIEnv* pEnv, jobject obj); + jint (JNICALL *MonitorExit)(JNIEnv* pEnv, jobject obj); + + jint (JNICALL *GetJavaVM)(JNIEnv* pEnv, JavaVM **vm); + + void (JNICALL *GetStringRegion)(JNIEnv* pEnv, jstring str, jsize start, jsize len, jchar *buf); + void (JNICALL *GetStringUTFRegion)(JNIEnv* pEnv, jstring str, jsize start, jsize len, char *buf); + + void* (JNICALL *GetPrimitiveArrayCritical)(JNIEnv* pEnv, jarray array, jboolean *isCopy); + void (JNICALL *ReleasePrimitiveArrayCritical)(JNIEnv* pEnv, jarray array, void *carray, jint mode); + + const jchar* (JNICALL *GetStringCritical)(JNIEnv* pEnv, jstring string, jboolean *isCopy); + void (JNICALL *ReleaseStringCritical)(JNIEnv* pEnv, jstring string, const jchar *cstring); + + jweak (JNICALL *NewWeakGlobalRef)(JNIEnv* pEnv, jobject obj); + void (JNICALL *DeleteWeakGlobalRef)(JNIEnv* pEnv, jweak ref); + + jboolean (JNICALL *ExceptionCheck)(JNIEnv* pEnv); + + jobject (JNICALL *NewDirectByteBuffer)(JNIEnv* pEnv, void* address, jlong capacity); + void* (JNICALL *GetDirectBufferAddress)(JNIEnv* pEnv, jobject buf); + jlong (JNICALL *GetDirectBufferCapacity)(JNIEnv* pEnv, jobject buf); +}; + +#endif //__JNI_H__ diff --git a/native/native.8.vcproj b/native/native.8.vcproj new file mode 100644 index 0000000..0e032a5 --- /dev/null +++ b/native/native.8.vcproj @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/native/native.9.vcproj b/native/native.9.vcproj new file mode 100644 index 0000000..4ab4dc4 --- /dev/null +++ b/native/native.9.vcproj @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/native/native.build b/native/native.build new file mode 100644 index 0000000..473ea19 --- /dev/null +++ b/native/native.build @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/native/os.c b/native/os.c new file mode 100644 index 0000000..65d49e2 --- /dev/null +++ b/native/os.c @@ -0,0 +1,100 @@ +/* + Copyright (C) 2004, 2005 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +#ifdef _WIN32 + #include + #include "jni.h" + + JNIEXPORT void* JNICALL ikvm_LoadLibrary(char* psz) + { + return LoadLibrary(psz); + } + + JNIEXPORT void JNICALL ikvm_FreeLibrary(HMODULE handle) + { + FreeLibrary(handle); + } + + JNIEXPORT void* JNICALL ikvm_GetProcAddress(HMODULE handle, char* name, jint argc) + { +#ifdef _WIN64 + return GetProcAddress(handle, name); +#else + void* pfunc; + char buf[512]; + if(strlen(name) > sizeof(buf) - 11) + { + return 0; + } + wsprintf(buf, "_%s@%d", name, argc); + pfunc = GetProcAddress(handle, buf); + if (pfunc) + return pfunc; + // If we didn't find the mangled name, try the unmangled name (this happens if you have an + // explicit EXPORT in the linker def). + return GetProcAddress(handle, name); +#endif + } +#else + #include + #include + #include + #include "jni.h" + + JNIEXPORT void* JNICALL ikvm_LoadLibrary(char* psz) + { + return g_module_open(psz, 0); + } + + JNIEXPORT void JNICALL ikvm_FreeLibrary(GModule* handle) + { + g_module_close(handle); + } + + JNIEXPORT void* JNICALL ikvm_GetProcAddress(GModule* handle, char* name, jint argc) + { + void *symbol; + + gboolean res = g_module_symbol(handle, name, &symbol); + + if (res) + return symbol; + else + return NULL; + } + + JNIEXPORT void* JNICALL ikvm_mmap(int fd, jboolean writeable, jboolean copy_on_write, jlong position, jint size) + { + return mmap(0, size, writeable ? PROT_WRITE | PROT_READ : PROT_READ, copy_on_write ? MAP_PRIVATE : MAP_SHARED, fd, position); + } + + JNIEXPORT int JNICALL ikvm_munmap(void* address, jint size) + { + return munmap(address, size); + } + + JNIEXPORT int JNICALL ikvm_msync(void* address, jint size) + { + return msync(address, size, MS_SYNC); + } +#endif diff --git a/nuget/IKVM.nuspec.in b/nuget/IKVM.nuspec.in new file mode 100644 index 0000000..3ed9ce0 --- /dev/null +++ b/nuget/IKVM.nuspec.in @@ -0,0 +1,16 @@ + + + + @VERSION@ + Jeroen Frijters + + http://sourceforge.net/apps/mediawiki/ikvm/index.php?title=License + http://www.ikvm.net/ + IKVM + IKVM.NET + false + IKVM.NET is an implementation of Java for Mono and the Microsoft .NET Framework. + IKVM.NET, Java, .NET + The release notes can be found here: http://ikvm.net/release/@VERSION@ + + diff --git a/nuget/nupkg.build b/nuget/nupkg.build new file mode 100644 index 0000000..8545ee6 --- /dev/null +++ b/nuget/nupkg.build @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openjdk/AssemblyInfo.java b/openjdk/AssemblyInfo.java new file mode 100644 index 0000000..1da4f52 --- /dev/null +++ b/openjdk/AssemblyInfo.java @@ -0,0 +1,75 @@ +/* + Copyright (C) 2006-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +@cli.System.Reflection.AssemblyCopyrightAttribute.Annotation( + "This software is licensed under the GNU General Public License version 2 + \"Classpath\" exception.\r\n" + + "See http://www.gnu.org/software/classpath/license.html for details.\r\n" + + "1988 AT&T\r\n" + + "2009-2014 Attila Szegedi\r\n" + + "1995 Colin Plumb\r\n" + + "1999-2014 Free Software Foundation\r\n" + + "2001-2005 freebxml.org\r\n" + + "1998 FundsXpress, INC.\r\n" + + "2009 Google Inc.\r\n" + + "2008-2013 i-net software\r\n" + + "2000-2013 INRIA, France Telecom\r\n" + + "1993-2013 International Business Machines, Inc.\r\n" + + "2002-2015 Jeroen Frijters\r\n" + + "1994-2015 Oracle and/or its affiliates\r\n" + + "2007 Red Hat, Inc.\r\n" + + "2007-2013 Stephen Colebourne & Michael Nascimento Santos\r\n" + + "1993-1997 Sun Microsystems, Inc.\r\n" + + "1996-1998 Taligent, Inc.\r\n" + + "2001-2002 Thai Open Source Software Center Ltd\r\n" + + "1999-2006 The Apache Software Foundation\r\n" + + "1995-2000 The Cryptix Foundation Limited\r\n" + + "1997 The Open Group Research Institute\r\n" + + "1991-2012 Unicode, Inc.\r\n" + + "1999 Visual Numerics Inc.\r\n" + + "2003 Wily Technology, Inc.\r\n" + + "2000-2004 World Wide Web Consortium" +) + +@cli.System.Reflection.AssemblyTitleAttribute.Annotation("IKVM.NET OpenJDK Library for .NET") +@cli.System.Reflection.AssemblyProductAttribute.Annotation("IKVM.NET") +@cli.System.Reflection.AssemblyCompanyAttribute.Annotation("Jeroen Frijters") +@cli.System.Reflection.AssemblyInformationalVersionAttribute.Annotation("8.1.5717.0") + +@cli.System.Runtime.CompilerServices.InternalsVisibleToAttribute.Annotation.__Multiple({ + @cli.System.Runtime.CompilerServices.InternalsVisibleToAttribute.Annotation("IKVM.Runtime, PublicKey=0024000004800000940000000602000000240000525341310004000001000100DD6B140E5209CAE3D1C710030021EF589D0F00D05ACA8771101A7E99E10EE063E66040DF96E6F842F717BFC5B62D2EC2B62CEB0282E4649790DACB424DB29B68ADC7EAEAB0356FCE04702379F84400B8427EDBB33DAB8720B9F16A42E2CDB87F885EF413DBC4229F2BD157C9B8DC2CD14866DEC5F31C764BFB9394CC3C60E6C0"), + @cli.System.Runtime.CompilerServices.InternalsVisibleToAttribute.Annotation("IKVM.AWT.WinForms, PublicKey=0024000004800000940000000602000000240000525341310004000001000100DD6B140E5209CAE3D1C710030021EF589D0F00D05ACA8771101A7E99E10EE063E66040DF96E6F842F717BFC5B62D2EC2B62CEB0282E4649790DACB424DB29B68ADC7EAEAB0356FCE04702379F84400B8427EDBB33DAB8720B9F16A42E2CDB87F885EF413DBC4229F2BD157C9B8DC2CD14866DEC5F31C764BFB9394CC3C60E6C0") +}) + +@cli.System.Security.AllowPartiallyTrustedCallersAttribute.Annotation + +// type to collect Assembly attributes applicable to all core library assemblies +interface commonAttributes {} + +///////////////////////////////////////////////////////////////////////////// + +// Roslyn requires that assemblies that contain types that define extension methods have the attribute on the assembly as well +@cli.System.Runtime.CompilerServices.ExtensionAttribute.Annotation + +// type to collect Assembly attributes specific to IKVM.OpenJDK.Core +interface coreAttributes {} diff --git a/openjdk/AssemblyInfo.java.in b/openjdk/AssemblyInfo.java.in new file mode 100644 index 0000000..d582c2b --- /dev/null +++ b/openjdk/AssemblyInfo.java.in @@ -0,0 +1,51 @@ +/* + Copyright (C) 2006-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +@cli.System.Reflection.AssemblyCopyrightAttribute.Annotation( + "This software is licensed under the GNU General Public License version 2 + \"Classpath\" exception.\r\n" + + "See http://www.gnu.org/software/classpath/license.html for details.\r\n" + +@COPYRIGHT@) + +@cli.System.Reflection.AssemblyTitleAttribute.Annotation("IKVM.NET OpenJDK Library for .NET") +@cli.System.Reflection.AssemblyProductAttribute.Annotation("IKVM.NET") +@cli.System.Reflection.AssemblyCompanyAttribute.Annotation("Jeroen Frijters") +@cli.System.Reflection.AssemblyInformationalVersionAttribute.Annotation("@VERSION@") + +@cli.System.Runtime.CompilerServices.InternalsVisibleToAttribute.Annotation.__Multiple({ + @cli.System.Runtime.CompilerServices.InternalsVisibleToAttribute.Annotation("@RUNTIME@"), + @cli.System.Runtime.CompilerServices.InternalsVisibleToAttribute.Annotation("@AWTWINFORMS@") +}) + +@cli.System.Security.AllowPartiallyTrustedCallersAttribute.Annotation + +// type to collect Assembly attributes applicable to all core library assemblies +interface commonAttributes {} + +///////////////////////////////////////////////////////////////////////////// + +// Roslyn requires that assemblies that contain types that define extension methods have the attribute on the assembly as well +@cli.System.Runtime.CompilerServices.ExtensionAttribute.Annotation + +// type to collect Assembly attributes specific to IKVM.OpenJDK.Core +interface coreAttributes {} diff --git a/openjdk/ExtensionAttribute.java b/openjdk/ExtensionAttribute.java new file mode 100644 index 0000000..acf5cc7 --- /dev/null +++ b/openjdk/ExtensionAttribute.java @@ -0,0 +1,39 @@ +/* + Copyright (C) 2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package cli.System.Runtime.CompilerServices; + +import java.lang.annotation.*; + +// +// This is a dummy ExtensionAttribute class to enable building without +// introducing a dependency on System.Core.dll +// +// To build without System.Core.dll dependency use this: +// nant -t:net-2.0 -D:SkipSystemCoreDependency=true +// +public class ExtensionAttribute +{ + @Retention(RetentionPolicy.SOURCE) + public @interface Annotation { } +} diff --git a/openjdk/FORKED b/openjdk/FORKED new file mode 100644 index 0000000..74fcc71 --- /dev/null +++ b/openjdk/FORKED @@ -0,0 +1,108 @@ +# +# IKVM.NET Forked OpenJDK Files +# +# This file list all forked OpenJDK files in their original OpenJDK location and their forked ikvm/openjdk location. +# Each line not starting with # contains a mapping: = +# +build/linux-x86_64-normal-server-release/jdk/gensrc/sun/misc/Version.java=sun/misc/Version.java +build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/ch/SocketOptionRegistry.java=sun/nio/ch/SocketOptionRegistry.java +build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/StandardCharsets.java=sun/nio/cs/StandardCharsets.java +jdk/src/macosx/classes/java/lang/ClassLoaderHelper.java=java/lang/ClassLoaderHelper.java +jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java=com/sun/imageio/plugins/jpeg/JPEGImageReader.java +jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java=com/sun/imageio/plugins/jpeg/JPEGImageWriter.java +jdk/src/share/classes/java/awt/Font.java=java/awt/Font.java +jdk/src/share/classes/java/awt/GraphicsConfiguration.java=java/awt/GraphicsConfiguration.java +jdk/src/share/classes/java/awt/Image.java=java/awt/Image.java +jdk/src/share/classes/java/awt/image/BufferedImage.java=java/awt/image/BufferedImage.java +jdk/src/share/classes/java/awt/image/DataBuffer.java=java/awt/image/DataBuffer.java +jdk/src/share/classes/java/awt/image/DataBufferByte.java=java/awt/image/DataBufferByte.java +jdk/src/share/classes/java/awt/image/DataBufferDouble.java=java/awt/image/DataBufferDouble.java +jdk/src/share/classes/java/awt/image/DataBufferFloat.java=java/awt/image/DataBufferFloat.java +jdk/src/share/classes/java/awt/image/DataBufferInt.java=java/awt/image/DataBufferInt.java +jdk/src/share/classes/java/awt/image/DataBufferShort.java=java/awt/image/DataBufferShort.java +jdk/src/share/classes/java/awt/image/DataBufferUShort.java=java/awt/image/DataBufferUShort.java +jdk/src/share/classes/java/awt/image/IndexColorModel.java=java/awt/image/IndexColorModel.java +jdk/src/share/classes/java/io/ObjectStreamClass.java=java/io/ObjectStreamClass.java +jdk/src/share/classes/java/io/ObjectStreamField.java=java/io/ObjectStreamField.java +jdk/src/share/classes/java/lang/Class.java=java/lang/Class.java +jdk/src/share/classes/java/lang/ClassLoader.java=java/lang/ClassLoader.java +jdk/src/share/classes/java/lang/Enum.java=java/lang/Enum.java +jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java=../runtime/openjdk/NativeInvokerBytecodeGenerator.cs +jdk/src/share/classes/java/lang/management/PlatformComponent.java=java/lang/management/PlatformComponent.java +jdk/src/share/classes/java/lang/ref/SoftReference.java=java/lang/ref/SoftReference.java +jdk/src/share/classes/java/lang/reflect/Constructor.java=java/lang/reflect/Constructor.java +jdk/src/share/classes/java/lang/reflect/Executable.java=java/lang/reflect/Executable.java +jdk/src/share/classes/java/lang/reflect/Field.java=java/lang/reflect/Field.java +jdk/src/share/classes/java/lang/reflect/Method.java=java/lang/reflect/Method.java +jdk/src/share/classes/java/lang/reflect/Proxy.java=java/lang/reflect/Proxy.java +jdk/src/share/classes/java/lang/Shutdown.java=java/lang/Shutdown.java +jdk/src/share/classes/java/lang/String.java=java/lang/StringHelper.java +jdk/src/share/classes/java/lang/System.java=java/lang/System.java +jdk/src/share/classes/java/lang/Thread.java=java/lang/Thread.java +jdk/src/share/classes/java/lang/Throwable.java=java/lang/ThrowableHelper.java +jdk/src/share/classes/java/nio/Bits.java=java/nio/Bits.java +jdk/src/share/classes/java/security/AccessController.java=java/security/AccessController.java +jdk/src/share/classes/java/security/ProtectionDomain.java=java/security/ProtectionDomain.java +jdk/src/share/classes/java/util/concurrent/atomic/AtomicBoolean.java=../classpath/java/util/concurrent/atomic/AtomicBoolean.java +jdk/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java=../classpath/java/util/concurrent/atomic/AtomicInteger.java +jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java=../classpath/java/util/concurrent/atomic/AtomicIntegerArray.java +jdk/src/share/classes/java/util/concurrent/atomic/AtomicLong.java=../classpath/java/util/concurrent/atomic/AtomicLong.java +jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java=../classpath/java/util/concurrent/atomic/AtomicLongArray.java +jdk/src/share/classes/java/util/concurrent/atomic/AtomicReference.java=../classpath/java/util/concurrent/atomic/AtomicReference.java +jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java=../classpath/java/util/concurrent/atomic/AtomicReferenceArray.java +jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java=java/util/concurrent/locks/AbstractQueuedSynchronizer.java +jdk/src/share/classes/java/util/concurrent/locks/LockSupport.java=java/util/concurrent/locks/LockSupport.java +jdk/src/share/classes/sun/awt/EmbeddedFrame.java=sun/awt/EmbeddedFrame.java +jdk/src/share/classes/sun/awt/image/ByteInterleavedRaster.java=sun/awt/image/ByteInterleavedRaster.java +jdk/src/share/classes/sun/awt/image/ImagingLib.java=sun/awt/image/ImagingLib.java +jdk/src/share/classes/sun/awt/image/IntegerInterleavedRaster.java=sun/awt/image/IntegerInterleavedRaster.java +jdk/src/share/classes/sun/awt/image/SunWritableRaster.java=sun/awt/image/SunWritableRaster.java +jdk/src/share/classes/sun/awt/image/ToolkitImage.java=sun/awt/image/ToolkitImage.java +jdk/src/share/classes/sun/font/FontManager.java=sun/font/FontManager.java +jdk/src/share/classes/sun/font/StrikeCache.java=sun/font/StrikeCache.java +jdk/src/share/classes/sun/management/ManagementFactoryHelper.java=sun/management/ManagementFactoryHelper.java +jdk/src/share/classes/sun/management/VMManagementImpl.java=sun/management/VMManagementImpl.java +jdk/src/share/classes/sun/misc/SharedSecrets.java=sun/misc/SharedSecrets.java +jdk/src/share/classes/sun/misc/VM.java=sun/misc/VM.java +jdk/src/share/classes/sun/net/sdp/SdpSupport.java=sun/net/sdp/SdpSupport.java +jdk/src/share/classes/sun/net/www/protocol/file/FileURLConnection.java=sun/net/www/protocol/file/FileURLConnection.java +jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java=sun/nio/ch/DatagramChannelImpl.java +jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java=sun/nio/ch/FileChannelImpl.java +jdk/src/share/classes/sun/nio/ch/IOUtil.java=sun/nio/ch/IOUtil.java +jdk/src/share/classes/sun/nio/ch/NativeDispatcher.java=sun/nio/ch/NativeDispatcher.java +jdk/src/share/classes/sun/nio/ch/Net.java=sun/nio/ch/Net.java +jdk/src/share/classes/sun/nio/ch/Util.java=sun/nio/ch/Util.java +jdk/src/share/classes/sun/reflect/annotation/AnnotationType.java=sun/reflect/annotation/AnnotationType.java +jdk/src/share/classes/sun/reflect/MethodAccessor.java=sun/reflect/MethodAccessor.java +jdk/src/share/classes/sun/reflect/Reflection.java=sun/reflect/Reflection.java +jdk/src/share/classes/sun/reflect/ReflectionFactory.java=sun/reflect/ReflectionFactory.java +jdk/src/solaris/classes/sun/nio/fs/UnixUriUtils.java=sun/nio/fs/UnixUriUtils.java +jdk/src/windows/classes/java/io/FileDescriptor.java=java/io/FileDescriptor.java +jdk/src/windows/classes/java/lang/ProcessImpl.java=java/lang/ProcessImpl.java +jdk/src/windows/classes/java/net/DefaultDatagramSocketImplFactory.java=java/net/DefaultDatagramSocketImplFactory.java +jdk/src/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java=java/net/DualStackPlainDatagramSocketImpl.java +jdk/src/windows/classes/java/net/DualStackPlainSocketImpl.java=java/net/DualStackPlainSocketImpl.java +jdk/src/windows/classes/java/net/PlainSocketImpl.java=java/net/PlainSocketImpl.java +jdk/src/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java=java/net/TwoStacksPlainDatagramSocketImpl.java +jdk/src/windows/classes/java/net/TwoStacksPlainSocketImpl.java=java/net/TwoStacksPlainSocketImpl.java +jdk/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java=sun/awt/shell/Win32ShellFolder2.java +jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java=sun/awt/shell/Win32ShellFolderManager2.java +jdk/src/windows/classes/sun/misc/FileURLMapper.java=sun/misc/FileURLMapper.java +jdk/src/windows/classes/sun/net/dns/ResolverConfigurationImpl.java=sun/net/dns/ResolverConfigurationImpl.java +jdk/src/windows/classes/sun/net/www/protocol/file/Handler.java=sun/net/www/protocol/file/Handler.java +jdk/src/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java=sun/net/www/protocol/jar/JarFileFactory.java +jdk/src/windows/classes/sun/nio/ch/DefaultSelectorProvider.java=sun/nio/ch/DefaultSelectorProvider.java +jdk/src/windows/classes/sun/nio/ch/FileDispatcherImpl.java=sun/nio/ch/FileDispatcherImpl.java +jdk/src/windows/classes/sun/nio/ch/Iocp.java=sun/nio/ch/Iocp.java +jdk/src/windows/classes/sun/nio/ch/SocketDispatcher.java=sun/nio/ch/SocketDispatcher.java +jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java=sun/nio/ch/WindowsAsynchronousFileChannelImpl.java +jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java=sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java +jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java=sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java +jdk/src/windows/classes/sun/nio/fs/WindowsUriSupport.java=sun/nio/fs/WindowsUriSupport.java +jdk/src/windows/classes/sun/print/Win32PrintJob.java=sun/print/Win32PrintJob.java +jdk/src/windows/classes/sun/print/Win32PrintService.java=sun/print/Win32PrintService.java +jdk/src/windows/native/java/net/DualStackPlainDatagramSocketImpl.c=java/net/DualStackPlainDatagramSocketImpl_c.java +jdk/src/windows/native/java/net/DualStackPlainSocketImpl.c=java/net/DualStackPlainSocketImpl_c.java +jdk/src/windows/native/java/net/net_util_md.c=java/net/net_util_md.java +jdk/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c=java/net/TwoStacksPlainDatagramSocketImpl_c.java +jdk/src/windows/native/java/net/TwoStacksPlainSocketImpl.c=java/net/TwoStacksPlainSocketImpl_c.java diff --git a/openjdk/GenerateSystemCore.cs b/openjdk/GenerateSystemCore.cs new file mode 100644 index 0000000..265a030 --- /dev/null +++ b/openjdk/GenerateSystemCore.cs @@ -0,0 +1,44 @@ +/* + Copyright (C) 2010 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; + +class GenerateSystemCore +{ + static void Main(string[] args) + { + Universe universe = new Universe(); + AssemblyName name = new AssemblyName("System.Core"); + name.Version = new Version(3, 5); + name.SetPublicKey(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); + AssemblyBuilder ab = universe.DefineDynamicAssembly(name, AssemblyBuilderAccess.Save); + ModuleBuilder modb = ab.DefineDynamicModule("System.Core", "System.Core.dll"); + TypeBuilder tb = modb.DefineType("System.Runtime.CompilerServices.ExtensionAttribute", TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed, universe.Import(typeof(Attribute))); + tb.DefineDefaultConstructor(MethodAttributes.Public); + tb.CreateType(); + ab.Save("System.Core.dll"); + } +} diff --git a/openjdk/MANIFEST.MF b/openjdk/MANIFEST.MF new file mode 100644 index 0000000..de8dd88 --- /dev/null +++ b/openjdk/MANIFEST.MF @@ -0,0 +1,8 @@ +Manifest-Version: 1.0 +Implementation-Vendor: Oracle Corporation & others +Implementation-Title: IKVM.NET OpenJDK +Implementation-Version: 1.8.0 +Specification-Vendor: Oracle Corporation +Specification-Title: Java Platform API Specification +Specification-Version: 1.8 + diff --git a/openjdk/MANIFEST.MF.in b/openjdk/MANIFEST.MF.in new file mode 100644 index 0000000..c20d3cb --- /dev/null +++ b/openjdk/MANIFEST.MF.in @@ -0,0 +1,8 @@ +Manifest-Version: 1.0 +Implementation-Vendor: Oracle Corporation & others +Implementation-Title: IKVM.NET OpenJDK +Implementation-Version: @IMPLEMENTATION_VERSION@ +Specification-Vendor: Oracle Corporation +Specification-Title: Java Platform API Specification +Specification-Version: @SPECIFICATION_VERSION@ + diff --git a/openjdk/allsources.lst b/openjdk/allsources.lst new file mode 100644 index 0000000..935b3a9 --- /dev/null +++ b/openjdk/allsources.lst @@ -0,0 +1,16203 @@ +../classpath/gnu/java/net/protocol/ikvmres/Handler.java +../classpath/ikvm/extensions/ExtensionMethods.java +../classpath/ikvm/internal/__unspecified.java +../classpath/ikvm/internal/AssemblyClassLoader.java +../classpath/ikvm/internal/CallerID.java +../classpath/ikvm/internal/Formatter.java +../classpath/ikvm/internal/JMath.java +../classpath/ikvm/internal/MonoUtils.java +../classpath/ikvm/internal/Util.java +../classpath/ikvm/internal/WeakIdentityMap.java +../classpath/ikvm/io/InputStreamWrapper.java +../classpath/ikvm/lang/CIL.java +../classpath/ikvm/lang/DllExport.java +../classpath/ikvm/lang/Internal.java +../classpath/ikvm/lang/IterableEnumerator.java +../classpath/ikvm/lang/MapEnumerator.java +../classpath/ikvm/lang/Property.java +../classpath/ikvm/runtime/AppDomainAssemblyClassLoader.java +../classpath/ikvm/runtime/ClassPathAssemblyClassLoader.java +../classpath/ikvm/runtime/Delegates.java +../classpath/ikvm/runtime/EnumerationWrapper.java +../classpath/ikvm/runtime/Startup.java +../classpath/ikvm/runtime/Util.java +../classpath/java/util/concurrent/atomic/AtomicBoolean.java +../classpath/java/util/concurrent/atomic/AtomicInteger.java +../classpath/java/util/concurrent/atomic/AtomicIntegerArray.java +../classpath/java/util/concurrent/atomic/AtomicLong.java +../classpath/java/util/concurrent/atomic/AtomicLongArray.java +../classpath/java/util/concurrent/atomic/AtomicReference.java +../classpath/java/util/concurrent/atomic/AtomicReferenceArray.java +../classpath/java/util/concurrent/atomic/Striped64.java +../classpath/sun/misc/Ref.java +AssemblyInfo.java +com/sun/imageio/plugins/jpeg/JPEGImageReader.java +com/sun/imageio/plugins/jpeg/JPEGImageWriter.java +com/sun/java/util/jar/pack/PackageReader.java +gnu/java/awt/Buffers.java +gnu/java/awt/color/CieXyzConverter.java +gnu/java/awt/color/ClutProfileConverter.java +gnu/java/awt/color/ColorLookUpTable.java +gnu/java/awt/color/ColorSpaceConverter.java +gnu/java/awt/color/GrayProfileConverter.java +gnu/java/awt/color/GrayScaleConverter.java +gnu/java/awt/color/ProfileHeader.java +gnu/java/awt/color/RgbProfileConverter.java +gnu/java/awt/color/SrgbConverter.java +gnu/java/awt/color/TagEntry.java +gnu/java/awt/color/ToneReproductionCurve.java +gnu/java/util/EmptyEnumeration.java +ikvm/awt/IkvmToolkit.java +ikvm/internal/AnnotationAttributeBase.java +ikvm/internal/FieldReflectorBase.java +ikvm/internal/InterlockedCompareAndSet.java +ikvm/internal/IntrinsicAtomicReferenceFieldUpdater.java +ikvm/internal/IntrinsicThreadLocal.java +ikvm/internal/JNI.java +ikvm/internal/NotYetImplementedError.java +ikvm/internal/Serialization.java +ikvm/internal/Winsock.java +java/awt/color/ICC_ColorSpace.java +java/awt/Font.java +java/awt/GraphicsConfiguration.java +java/awt/Image.java +java/awt/image/AffineTransformOp.java +java/awt/image/BandCombineOp.java +java/awt/image/BufferedImage.java +java/awt/image/ConvolveOp.java +java/awt/image/ColorConvertOp.java +java/awt/image/DataBuffer.java +java/awt/image/DataBufferByte.java +java/awt/image/DataBufferDouble.java +java/awt/image/DataBufferFloat.java +java/awt/image/DataBufferInt.java +java/awt/image/DataBufferShort.java +java/awt/image/DataBufferUShort.java +java/awt/image/IndexColorModel.java +java/awt/image/LookupOp.java +java/awt/image/RescaleOp.java +java/io/DefaultFileSystem.java +java/io/FileDescriptor.java +java/io/InteropObjectInputStream.java +java/io/InteropObjectOutputStream.java +java/io/ObjectStreamClass.java +java/io/ObjectStreamField.java +java/lang/Class.java +java/lang/ClassLoader.java +java/lang/ClassLoaderHelper.java +java/lang/ClassSerializationProxy.java +java/lang/Enum.java +java/lang/invoke/LightWeightMethodHandle.java +java/lang/LangHelper.java +java/lang/management/PlatformComponent.java +java/lang/ProcessImpl.java +java/lang/PropertyConstants.java +java/lang/ref/Reference.java +java/lang/ref/ReferenceQueue.java +java/lang/ref/SoftReference.java +java/lang/reflect/Constructor.java +java/lang/reflect/Executable.java +java/lang/reflect/Field.java +java/lang/reflect/Method.java +java/lang/reflect/Proxy.java +java/lang/Shutdown.java +java/lang/StringHelper.java +java/lang/System.java +java/lang/Thread.java +java/lang/ThrowableHelper.java +java/lang/VMSystemProperties.java +java/net/DefaultDatagramSocketImplFactory.java +java/net/DualStackPlainDatagramSocketImpl.java +java/net/DualStackPlainDatagramSocketImpl_c.java +java/net/DualStackPlainSocketImpl.java +java/net/DualStackPlainSocketImpl_c.java +java/net/net_util_md.java +java/net/PlainSocketImpl.java +java/net/SocketUtil.java +java/net/TwoStacksPlainDatagramSocketImpl.java +java/net/TwoStacksPlainDatagramSocketImpl_c.java +java/net/TwoStacksPlainSocketImpl.java +java/net/TwoStacksPlainSocketImpl_c.java +java/nio/Bits.java +java/security/AccessController.java +java/security/ProtectionDomain.java +java/util/concurrent/locks/AbstractQueuedSynchronizer.java +java/util/concurrent/locks/LockSupport.java +java/util/zip/Adler32.java +java/util/zip/ClassStubZipEntry.java +java/util/zip/CRC32.java +java/util/zip/Deflater.java +java/util/zip/DeflaterConstants.java +java/util/zip/DeflaterEngine.java +java/util/zip/DeflaterHuffman.java +java/util/zip/DeflaterPending.java +java/util/zip/Inflater.java +java/util/zip/InflaterDynHeader.java +java/util/zip/InflaterHuffmanTree.java +java/util/zip/OutputWindow.java +java/util/zip/PendingBuffer.java +java/util/zip/StreamManipulator.java +java/util/zip/ZipEntry.java +java/util/zip/ZipFile.java +sun/awt/EmbeddedFrame.java +sun/awt/IkvmDataTransferer.java +sun/awt/image/ByteInterleavedRaster.java +sun/awt/image/GifImageDecoder.java +sun/awt/image/IkvmImageDecoder.java +sun/awt/image/ImageRepresentation.java +sun/awt/image/ImagingLib.java +sun/awt/image/IntegerInterleavedRaster.java +sun/awt/image/JPEGImageDecoder.java +sun/awt/image/SunWritableRaster.java +sun/awt/image/ToolkitImage.java +sun/awt/shell/Win32ShellFolder2.java +sun/awt/shell/Win32ShellFolderManager2.java +sun/awt/DebugSettings.java +sun/awt/Win32FontManager.java +sun/awt/X11FontManager.java +sun/awt/windows/WPrinterJob.java +sun/font/CompositeFont.java +sun/font/Font2D.java +sun/font/GlyphLayout.java +sun/font/PhysicalFont.java +sun/font/PhysicalStrike.java +sun/font/StandardGlyphVector.java +sun/font/StrikeCache.java +sun/font/SunFontManager.java +sun/font/TrueTypeFont.java +sun/java2d/cmm/lcms/LCMS.java +sun/java2d/HeadlessGraphicsEnvironment.java +sun/java2d/loops/TransformHelper.java +sun/java2d/pipe/ShapeSpanIterator.java +sun/java2d/SunCompositeContext.java +sun/java2d/SunGraphics2D.java +sun/java2d/SunGraphicsEnvironment.java +sun/java2d/SurfaceData.java +sun/jdbc/odbc/JdbcOdbcCallableStatement.java +sun/jdbc/odbc/JdbcOdbcConnection.java +sun/jdbc/odbc/JdbcOdbcDatabaseMetaData.java +sun/jdbc/odbc/JdbcOdbcDriver.java +sun/jdbc/odbc/JdbcOdbcDTResultSet.java +sun/jdbc/odbc/JdbcOdbcDTResultSetMetaData.java +sun/jdbc/odbc/JdbcOdbcObject.java +sun/jdbc/odbc/JdbcOdbcPreparedStatement.java +sun/jdbc/odbc/JdbcOdbcResultSet.java +sun/jdbc/odbc/JdbcOdbcResultSetMetaData.java +sun/jdbc/odbc/JdbcOdbcStatement.java +sun/jdbc/odbc/JdbcOdbcUpdateableResultSet.java +sun/jdbc/odbc/JdbcOdbcUtils.java +sun/management/ManagementFactoryHelper.java +sun/management/VMManagementImpl.java +sun/misc/FileURLMapper.java +sun/misc/MiscHelper.java +sun/misc/OSEnvironment.java +sun/misc/SharedSecrets.java +sun/misc/Unsafe.java +sun/misc/Version.java +sun/misc/VM.java +sun/net/dns/ResolverConfigurationImpl.java +sun/net/sdp/SdpSupport.java +sun/net/www/protocol/file/FileURLConnection.java +sun/net/www/protocol/file/Handler.java +sun/net/www/protocol/ikvmres/Handler.java +sun/net/www/protocol/jar/JarFileFactory.java +sun/nio/ch/DatagramChannelImpl.java +sun/nio/ch/DefaultSelectorProvider.java +sun/nio/ch/DotNetSelectorImpl.java +sun/nio/ch/FileChannelImpl.java +sun/nio/ch/FileDispatcherImpl.java +sun/nio/ch/FileKey.java +sun/nio/ch/Iocp.java +sun/nio/ch/IOUtil.java +sun/nio/ch/NativeDispatcher.java +sun/nio/ch/Net.java +sun/nio/ch/SelectionKeyImpl.java +sun/nio/ch/SocketDispatcher.java +sun/nio/ch/SocketOptionRegistry.java +sun/nio/ch/Util.java +sun/nio/ch/WindowsAsynchronousFileChannelImpl.java +sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java +sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java +sun/nio/cs/StandardCharsets.java +sun/nio/fs/DefaultFileSystemProvider.java +sun/nio/fs/DefaultFileTypeDetector.java +sun/nio/fs/NetFileSystem.java +sun/nio/fs/NetFileSystemProvider.java +sun/nio/fs/NetPath.java +sun/nio/fs/UnixUriUtils.java +sun/nio/fs/WindowsUriSupport.java +sun/print/PrintPeer.java +sun/print/UnixPrintServiceLookup.java +sun/print/Win32PrintJob.java +sun/print/Win32PrintService.java +sun/print/Win32PrintServiceLookup.java +sun/reflect/annotation/AnnotationType.java +sun/reflect/MethodAccessor.java +sun/reflect/Reflection.java +sun/reflect/ReflectionFactory.java +sun/security/jgss/wrapper/NativeGSSFactory.java +sun/security/jgss/wrapper/SunNativeProvider.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/_ActivatorImplBase.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/_ActivatorStub.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/_InitialNameServiceImplBase.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/_InitialNameServiceStub.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/_LocatorImplBase.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/_LocatorStub.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/_RepositoryImplBase.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/_RepositoryStub.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/_ServerImplBase.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/_ServerManagerImplBase.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/_ServerManagerStub.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/_ServerStub.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/Activator.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ActivatorHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ActivatorHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ActivatorOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/BadServerDefinition.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/BadServerDefinitionHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/BadServerDefinitionHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/EndPointInfo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/EndPointInfoHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/EndPointInfoHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/EndpointInfoListHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/EndpointInfoListHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/IIOP_CLEAR_TEXT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/InitialNameService.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/InitialNameServiceHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/InitialNameServiceHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/InitialNameServiceOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/InitialNameServicePackage/NameAlreadyBound.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/InitialNameServicePackage/NameAlreadyBoundHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/InitialNameServicePackage/NameAlreadyBoundHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/InvalidORBid.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/InvalidORBidHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/InvalidORBidHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/Locator.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/LocatorHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/LocatorHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/LocatorOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/LocatorPackage/ServerLocation.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/LocatorPackage/ServerLocationHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/LocatorPackage/ServerLocationHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/LocatorPackage/ServerLocationPerORB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/LocatorPackage/ServerLocationPerORBHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/LocatorPackage/ServerLocationPerORBHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/NoSuchEndPoint.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/NoSuchEndPointHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/NoSuchEndPointHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ORBAlreadyRegistered.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ORBAlreadyRegisteredHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ORBAlreadyRegisteredHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ORBidHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ORBidListHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ORBidListHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ORBPortInfo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ORBPortInfoHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ORBPortInfoHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ORBPortInfoListHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ORBPortInfoListHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/POANameHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/POANameHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/Repository.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/RepositoryHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/RepositoryHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/RepositoryOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/RepositoryPackage/ServerDef.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/RepositoryPackage/ServerDefHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/RepositoryPackage/ServerDefHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/RepositoryPackage/StringSeqHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/RepositoryPackage/StringSeqHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/Server.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerAlreadyActive.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerAlreadyActiveHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerAlreadyActiveHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerAlreadyInstalled.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerAlreadyInstalledHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerAlreadyInstalledHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerAlreadyRegistered.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerAlreadyRegisteredHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerAlreadyRegisteredHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerAlreadyUninstalled.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerAlreadyUninstalledHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerAlreadyUninstalledHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerHeldDown.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerHeldDownHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerHeldDownHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerIdHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerIdsHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerIdsHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerManager.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerManagerHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerManagerHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerManagerOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerNotActive.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerNotActiveHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerNotActiveHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerNotRegistered.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerNotRegisteredHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerNotRegisteredHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/ServerOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/TCPPortHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CORBA/ParameterMode.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CORBA/ParameterModeHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CORBA/ParameterModeHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CORBA/PolicyErrorCodeHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CORBA/PolicyErrorHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CORBA/PolicyErrorHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CORBA/StringSeqHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CORBA/StringSeqHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CORBA/WStringSeqHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CORBA/WStringSeqHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/Binding.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/BindingHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/BindingHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/BindingIterator.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/BindingIteratorHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/BindingIteratorHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/BindingIteratorOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/BindingIteratorPOA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/BindingListHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/BindingListHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/BindingType.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/BindingTypeHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/BindingTypeHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/IstringHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NameComponent.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NameComponentHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NameComponentHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NameHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NameHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContext.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextExt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextExtHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextExtHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextExtOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextExtPOA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextPOA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/_BindingIteratorStub.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/_NamingContextExtStub.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/_NamingContextStub.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextExtPackage/AddressHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextExtPackage/InvalidAddress.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextExtPackage/InvalidAddressHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextExtPackage/InvalidAddressHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextExtPackage/StringNameHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextExtPackage/URLStringHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextPackage/AlreadyBound.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextPackage/AlreadyBoundHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextPackage/AlreadyBoundHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextPackage/CannotProceed.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextPackage/CannotProceedHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextPackage/CannotProceedHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextPackage/InvalidName.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextPackage/InvalidNameHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextPackage/InvalidNameHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextPackage/NotEmpty.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextPackage/NotEmptyHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextPackage/NotEmptyHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextPackage/NotFound.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextPackage/NotFoundHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextPackage/NotFoundHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextPackage/NotFoundReason.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextPackage/NotFoundReasonHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextPackage/NotFoundReasonHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/Dynamic/Parameter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/AnySeqHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynAny.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynAnyFactory.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynAnyFactoryHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynAnyFactoryOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynAnyHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynAnyOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynAnySeqHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynArray.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynArrayHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynArrayOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynEnum.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynEnumHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynEnumOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynFixed.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynFixedHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynFixedOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynSequence.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynSequenceHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynSequenceOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynStruct.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynStructHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynStructOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynUnion.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynUnionHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynUnionOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynValue.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynValueBox.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynValueBoxOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynValueCommon.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynValueCommonOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynValueHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynValueOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/FieldNameHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/NameDynAnyPair.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/NameDynAnyPairHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/NameDynAnyPairSeqHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/NameValuePair.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/NameValuePairHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/NameValuePairSeqHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/_DynAnyFactoryStub.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/_DynAnyStub.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/_DynArrayStub.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/_DynEnumStub.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/_DynFixedStub.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/_DynSequenceStub.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/_DynStructStub.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/_DynUnionStub.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/_DynValueStub.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynAnyFactoryPackage/InconsistentTypeCode.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynAnyFactoryPackage/InconsistentTypeCodeHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynAnyPackage/InvalidValue.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynAnyPackage/InvalidValueHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynAnyPackage/TypeMismatch.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynAnyPackage/TypeMismatchHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/Codec.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/CodecFactory.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/CodecFactoryHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/CodecFactoryOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/CodecOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/CodeSets.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/ComponentIdHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/Encoding.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/ENCODING_CDR_ENCAPS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/ExceptionDetailMessage.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/IOR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/IORHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/IORHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/MultipleComponentProfileHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/MultipleComponentProfileHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/ProfileIdHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/RMICustomMaxStreamFormat.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/ServiceContext.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/ServiceContextHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/ServiceContextHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/ServiceContextListHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/ServiceContextListHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/ServiceIdHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/TaggedComponent.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/TaggedComponentHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/TaggedComponentHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/TaggedProfile.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/TaggedProfileHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/TaggedProfileHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/TAG_ALTERNATE_IIOP_ADDRESS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/TAG_CODE_SETS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/TAG_INTERNET_IOP.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/TAG_JAVA_CODEBASE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/TAG_MULTIPLE_COMPONENTS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/TAG_ORB_TYPE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/TAG_POLICIES.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/TAG_RMI_CUSTOM_MAX_STREAM_FORMAT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/TransactionService.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/CodecFactoryPackage/UnknownEncoding.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/CodecFactoryPackage/UnknownEncodingHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/CodecPackage/FormatMismatch.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/CodecPackage/FormatMismatchHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/CodecPackage/InvalidTypeForEncoding.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/CodecPackage/InvalidTypeForEncodingHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/CodecPackage/TypeMismatch.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/CodecPackage/TypeMismatchHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/Messaging/SyncScopeHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/Messaging/SYNC_WITH_TRANSPORT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ACTIVE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/AdapterManagerIdHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/AdapterNameHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/AdapterStateHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ClientRequestInfo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ClientRequestInfoOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ClientRequestInterceptor.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ClientRequestInterceptorOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/Current.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/CurrentHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/CurrentOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/DISCARDING.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ForwardRequest.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ForwardRequestHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/HOLDING.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/INACTIVE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/Interceptor.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/InterceptorOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/InvalidSlot.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/InvalidSlotHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/IORInfo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/IORInfoOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/IORInterceptor.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/IORInterceptorOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/IORInterceptor_3_0.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/IORInterceptor_3_0Helper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/IORInterceptor_3_0Holder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/IORInterceptor_3_0Operations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/LOCATION_FORWARD.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/NON_EXISTENT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ObjectIdHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ObjectReferenceFactory.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ObjectReferenceFactoryHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ObjectReferenceFactoryHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ObjectReferenceTemplate.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ObjectReferenceTemplateHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ObjectReferenceTemplateHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ObjectReferenceTemplateSeqHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ObjectReferenceTemplateSeqHolder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ORBIdHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ORBInitializer.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ORBInitializerOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ORBInitInfo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ORBInitInfoOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/PolicyFactory.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/PolicyFactoryOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/RequestInfo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/RequestInfoOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ServerIdHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ServerRequestInfo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ServerRequestInfoOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ServerRequestInterceptor.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ServerRequestInterceptorOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/SUCCESSFUL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/SYSTEM_EXCEPTION.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/TRANSPORT_RETRY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/USER_EXCEPTION.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ORBInitInfoPackage/DuplicateName.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ORBInitInfoPackage/DuplicateNameHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ORBInitInfoPackage/InvalidName.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ORBInitInfoPackage/InvalidNameHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ORBInitInfoPackage/ObjectIdHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/AdapterActivator.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/AdapterActivatorOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/Current.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/CurrentOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ForwardRequest.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ForwardRequestHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/IdAssignmentPolicy.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/IdAssignmentPolicyOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/IdAssignmentPolicyValue.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/IdUniquenessPolicy.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/IdUniquenessPolicyOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/IdUniquenessPolicyValue.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ID_ASSIGNMENT_POLICY_ID.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ID_UNIQUENESS_POLICY_ID.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ImplicitActivationPolicy.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ImplicitActivationPolicyOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ImplicitActivationPolicyValue.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/IMPLICIT_ACTIVATION_POLICY_ID.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/LifespanPolicy.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/LifespanPolicyOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/LifespanPolicyValue.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/LIFESPAN_POLICY_ID.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAManager.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAManagerOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/RequestProcessingPolicy.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/RequestProcessingPolicyOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/RequestProcessingPolicyValue.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/REQUEST_PROCESSING_POLICY_ID.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ServantActivator.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ServantActivatorHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ServantActivatorOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ServantActivatorPOA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ServantLocator.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ServantLocatorHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ServantLocatorOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ServantLocatorPOA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ServantManager.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ServantManagerOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ServantRetentionPolicy.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ServantRetentionPolicyOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ServantRetentionPolicyValue.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/SERVANT_RETENTION_POLICY_ID.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ThreadPolicy.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ThreadPolicyOperations.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/ThreadPolicyValue.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/THREAD_POLICY_ID.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/_ServantActivatorStub.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/_ServantLocatorStub.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/CurrentPackage/NoContext.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/CurrentPackage/NoContextHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAManagerPackage/AdapterInactive.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAManagerPackage/AdapterInactiveHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAManagerPackage/State.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAPackage/AdapterAlreadyExists.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAPackage/AdapterAlreadyExistsHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAPackage/AdapterNonExistent.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAPackage/AdapterNonExistentHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAPackage/InvalidPolicy.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAPackage/InvalidPolicyHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAPackage/NoServant.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAPackage/NoServantHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAPackage/ObjectAlreadyActive.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAPackage/ObjectAlreadyActiveHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAPackage/ObjectNotActive.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAPackage/ObjectNotActiveHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAPackage/ServantAlreadyActive.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAPackage/ServantAlreadyActiveHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAPackage/ServantNotActive.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAPackage/ServantNotActiveHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAPackage/WrongAdapter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAPackage/WrongAdapterHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAPackage/WrongPolicy.java +@OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAPackage/WrongPolicyHelper.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/accessibility/internal/resources/accessibility.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/accessibility/internal/resources/accessibility_de.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/accessibility/internal/resources/accessibility_en.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/accessibility/internal/resources/accessibility_es.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/accessibility/internal/resources/accessibility_fr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/accessibility/internal/resources/accessibility_it.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/accessibility/internal/resources/accessibility_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/accessibility/internal/resources/accessibility_ko.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/accessibility/internal/resources/accessibility_pt_BR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/accessibility/internal/resources/accessibility_sv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/accessibility/internal/resources/accessibility_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/accessibility/internal/resources/accessibility_zh_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/accessibility/internal/resources/accessibility_zh_TW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/motif/resources/motif.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/motif/resources/motif_de.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/motif/resources/motif_es.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/motif/resources/motif_fr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/motif/resources/motif_it.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/motif/resources/motif_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/motif/resources/motif_ko.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/motif/resources/motif_pt_BR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/motif/resources/motif_sv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/motif/resources/motif_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/motif/resources/motif_zh_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/motif/resources/motif_zh_TW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/windows/resources/windows.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/windows/resources/windows_de.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/windows/resources/windows_es.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/windows/resources/windows_fr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/windows/resources/windows_it.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/windows/resources/windows_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/windows/resources/windows_ko.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/windows/resources/windows_pt_BR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/windows/resources/windows_sv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/windows/resources/windows_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/windows/resources/windows_zh_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/windows/resources/windows_zh_TW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/basic/resources/basic.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/basic/resources/basic_de.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/basic/resources/basic_es.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/basic/resources/basic_fr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/basic/resources/basic_it.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/basic/resources/basic_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/basic/resources/basic_ko.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/basic/resources/basic_pt_BR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/basic/resources/basic_sv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/basic/resources/basic_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/basic/resources/basic_zh_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/basic/resources/basic_zh_TW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/metal/resources/metal.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/metal/resources/metal_de.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/metal/resources/metal_es.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/metal/resources/metal_fr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/metal/resources/metal_it.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/metal/resources/metal_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/metal/resources/metal_ko.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/metal/resources/metal_pt_BR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/metal/resources/metal_sv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/metal/resources/metal_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/metal/resources/metal_zh_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/metal/resources/metal_zh_TW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/synth/resources/synth.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/synth/resources/synth_de.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/synth/resources/synth_es.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/synth/resources/synth_fr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/synth/resources/synth_it.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/synth/resources/synth_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/synth/resources/synth_ko.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/synth/resources/synth_pt_BR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/synth/resources/synth_sv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/synth/resources/synth_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/synth/resources/synth_zh_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/synth/resources/synth_zh_TW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/tools/jdi/JDWP.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/tools/jdi/resources/jdi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/tools/jdi/resources/jdi_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/tools/jdi/resources/jdi_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/lang/CharacterData00.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/lang/CharacterData01.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/lang/CharacterData02.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/lang/CharacterData0E.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/lang/CharacterDataLatin1.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/lang/CharacterDataPrivateUse.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/lang/CharacterDataUndefined.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/BufferOverflowException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/BufferUnderflowException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBuffer.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsCharBufferB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsCharBufferL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsCharBufferRB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsCharBufferRL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsDoubleBufferB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsDoubleBufferL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsDoubleBufferRB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsDoubleBufferRL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsFloatBufferB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsFloatBufferL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsFloatBufferRB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsFloatBufferRL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsIntBufferB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsIntBufferL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsIntBufferRB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsIntBufferRL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsLongBufferB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsLongBufferL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsLongBufferRB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsLongBufferRL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsShortBufferB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsShortBufferL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsShortBufferRB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ByteBufferAsShortBufferRL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/CharBuffer.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectByteBuffer.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectByteBufferR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectCharBufferRS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectCharBufferRU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectCharBufferS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectCharBufferU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectDoubleBufferRS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectDoubleBufferRU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectDoubleBufferS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectDoubleBufferU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectFloatBufferRS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectFloatBufferRU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectFloatBufferS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectFloatBufferU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectIntBufferRS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectIntBufferRU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectIntBufferS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectIntBufferU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectLongBufferRS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectLongBufferRU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectLongBufferS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectLongBufferU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectShortBufferRS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectShortBufferRU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectShortBufferS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DirectShortBufferU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/DoubleBuffer.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/FloatBuffer.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/HeapByteBuffer.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/HeapByteBufferR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/HeapCharBuffer.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/HeapCharBufferR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/HeapDoubleBuffer.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/HeapDoubleBufferR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/HeapFloatBuffer.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/HeapFloatBufferR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/HeapIntBuffer.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/HeapIntBufferR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/HeapLongBuffer.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/HeapLongBufferR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/HeapShortBuffer.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/HeapShortBufferR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/IntBuffer.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/InvalidMarkException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/LongBuffer.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ReadOnlyBufferException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/ShortBuffer.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/AcceptPendingException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/AlreadyBoundException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/AlreadyConnectedException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/AsynchronousCloseException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/CancelledKeyException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/ClosedByInterruptException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/ClosedChannelException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/ClosedSelectorException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/ConnectionPendingException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/FileLockInterruptionException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/IllegalBlockingModeException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/IllegalChannelGroupException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/IllegalSelectorException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/InterruptedByTimeoutException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/NoConnectionPendingException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/NonReadableChannelException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/NonWritableChannelException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/NotYetBoundException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/NotYetConnectedException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/OverlappingFileLockException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/ReadPendingException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/ShutdownChannelGroupException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/UnresolvedAddressException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/UnsupportedAddressTypeException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/WritePendingException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/charset/CharacterCodingException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/charset/CharsetDecoder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/charset/CharsetEncoder.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/charset/IllegalCharsetNameException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/charset/UnsupportedCharsetException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ArrowButtonPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ButtonPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/CheckBoxMenuItemPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/CheckBoxPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ComboBoxArrowButtonEditableState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ComboBoxArrowButtonPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ComboBoxEditableState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ComboBoxPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ComboBoxTextFieldPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/DesktopIconPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/DesktopPanePainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/EditorPanePainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/FileChooserPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/FormattedTextFieldPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/InternalFramePainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/InternalFrameTitlePaneCloseButtonPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/InternalFrameTitlePaneCloseButtonWindowNotFocusedState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/InternalFrameTitlePaneIconifyButtonPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/InternalFrameTitlePaneIconifyButtonWindowNotFocusedState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/InternalFrameTitlePaneMaximizeButtonPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/InternalFrameTitlePaneMaximizeButtonWindowMaximizedState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/InternalFrameTitlePaneMaximizeButtonWindowNotFocusedState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/InternalFrameTitlePaneMenuButtonPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/InternalFrameTitlePaneMenuButtonWindowNotFocusedState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/InternalFrameTitlePanePainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/InternalFrameTitlePaneWindowFocusedState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/InternalFrameWindowFocusedState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/MenuBarMenuPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/MenuBarPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/MenuItemPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/MenuPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/NimbusDefaults.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/OptionPaneMessageAreaOptionPaneLabelPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/OptionPaneMessageAreaPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/OptionPanePainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/PasswordFieldPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/PopupMenuPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/PopupMenuSeparatorPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ProgressBarFinishedState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ProgressBarIndeterminateState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ProgressBarPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/RadioButtonMenuItemPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/RadioButtonPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ScrollBarButtonPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ScrollBarPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ScrollBarThumbPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ScrollBarTrackPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ScrollPanePainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/SeparatorPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/SliderArrowShapeState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/SliderPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/SliderThumbArrowShapeState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/SliderThumbPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/SliderTrackArrowShapeState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/SliderTrackPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/SpinnerNextButtonPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/SpinnerPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/SpinnerPanelSpinnerFormattedTextFieldPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/SpinnerPreviousButtonPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/SplitPaneDividerPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/SplitPaneDividerVerticalState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/SplitPanePainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/SplitPaneVerticalState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/TabbedPanePainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/TabbedPaneTabAreaPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/TabbedPaneTabPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/TableEditorPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/TableHeaderPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/TableHeaderRendererPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/TableHeaderRendererSortedState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/TextAreaNotInScrollPaneState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/TextAreaPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/TextFieldPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/TextPanePainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ToggleButtonPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ToolBarButtonPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ToolBarEastState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ToolBarNorthState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ToolBarPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ToolBarSouthState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ToolBarToggleButtonPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ToolBarWestState.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/ToolTipPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/TreeCellEditorPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/TreeCellPainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/TreePainter.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/awt/resources/awt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/awt/resources/awt_de.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/awt/resources/awt_es.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/awt/resources/awt_fr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/awt/resources/awt_it.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/awt/resources/awt_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/awt/resources/awt_ko.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/awt/resources/awt_pt_BR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/awt/resources/awt_sv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/awt/resources/awt_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/awt/resources/awt_zh_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/awt/resources/awt_zh_TW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/management/resources/agent.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/management/resources/agent_de.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/management/resources/agent_es.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/management/resources/agent_fr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/management/resources/agent_it.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/management/resources/agent_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/management/resources/agent_ko.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/management/resources/agent_pt_BR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/management/resources/agent_sv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/management/resources/agent_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/management/resources/agent_zh_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/management/resources/agent_zh_TW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/misc/resources/Messages_zh_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/IBM437.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/IBM737.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/IBM775.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/IBM850.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/IBM852.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/IBM855.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/IBM857.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/IBM858.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/IBM862.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/IBM866.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/IBM874.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ISO_8859_13.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ISO_8859_15.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ISO_8859_2.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ISO_8859_4.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ISO_8859_5.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ISO_8859_7.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ISO_8859_9.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/KOI8_R.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/KOI8_U.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/MS1250.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/MS1251.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/MS1252.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/MS1253.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/MS1254.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/MS1257.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/Big5.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/EUC_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/EUC_KR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/EUC_TWMapping.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/GBK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/HKSCS2001Mapping.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/HKSCSMapping.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/HKSCS_XPMapping.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM037.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1006.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1025.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1026.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1046.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1047.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1097.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1098.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1112.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1122.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1123.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1124.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1140.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1141.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1142.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1143.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1144.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1145.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1146.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1147.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1148.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1149.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1364.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1381.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM1383.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM273.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM277.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM278.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM280.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM284.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM285.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM290.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM297.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM300.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM420.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM424.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM500.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM833.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM838.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM856.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM860.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM861.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM863.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM864.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM865.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM868.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM869.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM870.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM871.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM875.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM918.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM921.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM922.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM930.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM933.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM935.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM937.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM939.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM942.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM943.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM948.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM949.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM950.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/IBM970.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/ISO_8859_11.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/ISO_8859_3.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/ISO_8859_6.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/ISO_8859_8.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/JIS_X_0201.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/JIS_X_0208.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/JIS_X_0208_MS5022X.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/JIS_X_0208_MS932.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/JIS_X_0208_Solaris.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/JIS_X_0212.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/JIS_X_0212_MS5022X.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/JIS_X_0212_Solaris.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/Johab.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MacArabic.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MacCentralEurope.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MacCroatian.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MacCyrillic.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MacDingbat.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MacGreek.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MacHebrew.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MacIceland.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MacRoman.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MacRomania.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MacSymbol.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MacThai.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MacTurkish.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MacUkraine.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MS1255.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MS1256.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MS1258.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MS874.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MS932.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MS936.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MS949.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/MS950.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/PCK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/SJIS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/TIS_620.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/print/resources/serviceui.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/print/resources/serviceui_de.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/print/resources/serviceui_es.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/print/resources/serviceui_fr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/print/resources/serviceui_it.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/print/resources/serviceui_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/print/resources/serviceui_ko.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/print/resources/serviceui_pt_BR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/print/resources/serviceui_sv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/print/resources/serviceui_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/print/resources/serviceui_zh_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/print/resources/serviceui_zh_TW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/security/util/AuthResources_zh_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/security/util/Resources_zh_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/FormatData.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/aa/FormatData_aa.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/af/FormatData_af.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/af/FormatData_af_NA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/agq/FormatData_agq.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ak/FormatData_ak.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/am/FormatData_am.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ar/FormatData_ar.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ar/FormatData_ar_DZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ar/FormatData_ar_JO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ar/FormatData_ar_LB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ar/FormatData_ar_MA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ar/FormatData_ar_QA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ar/FormatData_ar_SA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ar/FormatData_ar_SY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ar/FormatData_ar_TN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ar/FormatData_ar_YE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/as/FormatData_as.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/asa/FormatData_asa.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/az/FormatData_az.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/az/FormatData_az_Cyrl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/bas/FormatData_bas.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/be/FormatData_be.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/bem/FormatData_bem.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/bez/FormatData_bez.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/bg/FormatData_bg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/bm/FormatData_bm.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/bn/FormatData_bn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/bn/FormatData_bn_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/bo/FormatData_bo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/br/FormatData_br.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/brx/FormatData_brx.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/bs/FormatData_bs.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/byn/FormatData_byn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ca/FormatData_ca.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/cgg/FormatData_cgg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/chr/FormatData_chr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/cs/FormatData_cs.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/cy/FormatData_cy.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/da/FormatData_da.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/dav/FormatData_dav.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/de/FormatData_de.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/de/FormatData_de_AT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/de/FormatData_de_CH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/de/FormatData_de_LI.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/dje/FormatData_dje.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/dua/FormatData_dua.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/dyo/FormatData_dyo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/dz/FormatData_dz.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ebu/FormatData_ebu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ee/FormatData_ee.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/el/FormatData_el.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/el/FormatData_el_CY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/FormatData_en.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/FormatData_en_AU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/FormatData_en_BE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/FormatData_en_BW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/FormatData_en_BZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/FormatData_en_CA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/FormatData_en_Dsrt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/FormatData_en_GB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/FormatData_en_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/FormatData_en_IE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/FormatData_en_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/FormatData_en_JM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/FormatData_en_MT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/FormatData_en_NA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/FormatData_en_NZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/FormatData_en_PK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/FormatData_en_SG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/FormatData_en_TT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/FormatData_en_US_POSIX.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/FormatData_en_ZA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/FormatData_en_ZW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/eo/FormatData_eo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/es/FormatData_es.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/es/FormatData_es_419.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/es/FormatData_es_AR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/es/FormatData_es_BO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/es/FormatData_es_CL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/es/FormatData_es_CO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/es/FormatData_es_CR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/es/FormatData_es_EC.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/es/FormatData_es_GQ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/es/FormatData_es_GT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/es/FormatData_es_HN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/es/FormatData_es_PA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/es/FormatData_es_PE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/es/FormatData_es_PR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/es/FormatData_es_PY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/es/FormatData_es_US.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/es/FormatData_es_UY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/es/FormatData_es_VE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/et/FormatData_et.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/eu/FormatData_eu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ewo/FormatData_ewo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/fa/FormatData_fa.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/fa/FormatData_fa_AF.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ff/FormatData_ff.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/fi/FormatData_fi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/fil/FormatData_fil.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/fo/FormatData_fo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/fr/FormatData_fr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/fr/FormatData_fr_BE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/fr/FormatData_fr_CA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/fr/FormatData_fr_CH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/fr/FormatData_fr_LU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/fur/FormatData_fur.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ga/FormatData_ga.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/gd/FormatData_gd.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/gl/FormatData_gl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/gsw/FormatData_gsw.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/gu/FormatData_gu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/guz/FormatData_guz.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/gv/FormatData_gv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ha/FormatData_ha.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/haw/FormatData_haw.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/he/FormatData_he.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/hi/FormatData_hi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/hr/FormatData_hr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/hu/FormatData_hu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/hy/FormatData_hy.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ia/FormatData_ia.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/id/FormatData_id.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ig/FormatData_ig.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ii/FormatData_ii.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/is/FormatData_is.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/it/FormatData_it.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/it/FormatData_it_CH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ja/FormatData_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/jmc/FormatData_jmc.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ka/FormatData_ka.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/kab/FormatData_kab.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/kam/FormatData_kam.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/kde/FormatData_kde.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/kea/FormatData_kea.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/khq/FormatData_khq.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ki/FormatData_ki.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/kk/FormatData_kk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/kl/FormatData_kl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/kln/FormatData_kln.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/km/FormatData_km.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/kn/FormatData_kn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ko/FormatData_ko.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/kok/FormatData_kok.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ksb/FormatData_ksb.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ksf/FormatData_ksf.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ksh/FormatData_ksh.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/kw/FormatData_kw.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/lag/FormatData_lag.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/lg/FormatData_lg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ln/FormatData_ln.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/lo/FormatData_lo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/lt/FormatData_lt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/lu/FormatData_lu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/luo/FormatData_luo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/luy/FormatData_luy.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/lv/FormatData_lv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/mas/FormatData_mas.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/mer/FormatData_mer.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/mfe/FormatData_mfe.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/mg/FormatData_mg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/mgh/FormatData_mgh.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/mk/FormatData_mk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ml/FormatData_ml.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/mr/FormatData_mr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ms/FormatData_ms.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ms/FormatData_ms_BN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/mt/FormatData_mt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/mua/FormatData_mua.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/my/FormatData_my.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/naq/FormatData_naq.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/nb/FormatData_nb.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/nd/FormatData_nd.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ne/FormatData_ne.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ne/FormatData_ne_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/nl/FormatData_nl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/nl/FormatData_nl_BE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/nmg/FormatData_nmg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/nn/FormatData_nn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/nr/FormatData_nr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/nso/FormatData_nso.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/nus/FormatData_nus.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/nyn/FormatData_nyn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/om/FormatData_om.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/or/FormatData_or.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/pa/FormatData_pa.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/pa/FormatData_pa_Arab.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/pl/FormatData_pl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ps/FormatData_ps.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/pt/FormatData_pt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/pt/FormatData_pt_PT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/rm/FormatData_rm.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/rn/FormatData_rn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ro/FormatData_ro.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/rof/FormatData_rof.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ru/FormatData_ru.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ru/FormatData_ru_UA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/rw/FormatData_rw.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/rwk/FormatData_rwk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/saq/FormatData_saq.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sbp/FormatData_sbp.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/se/FormatData_se.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/seh/FormatData_seh.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ses/FormatData_ses.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sg/FormatData_sg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/shi/FormatData_shi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/shi/FormatData_shi_Tfng.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/si/FormatData_si.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sk/FormatData_sk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sl/FormatData_sl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sn/FormatData_sn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/so/FormatData_so.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sq/FormatData_sq.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sr/FormatData_sr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sr/FormatData_sr_Cyrl_BA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sr/FormatData_sr_Latn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sr/FormatData_sr_Latn_ME.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ss/FormatData_ss.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ssy/FormatData_ssy.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/st/FormatData_st.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sv/FormatData_sv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sv/FormatData_sv_FI.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sw/FormatData_sw.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sw/FormatData_sw_KE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/swc/FormatData_swc.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ta/FormatData_ta.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/te/FormatData_te.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/teo/FormatData_teo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/th/FormatData_th.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ti/FormatData_ti.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ti/FormatData_ti_ER.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/tig/FormatData_tig.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/tn/FormatData_tn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/to/FormatData_to.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/tr/FormatData_tr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ts/FormatData_ts.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/twq/FormatData_twq.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/tzm/FormatData_tzm.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/uk/FormatData_uk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ur/FormatData_ur.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ur/FormatData_ur_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/uz/FormatData_uz.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/uz/FormatData_uz_Arab.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/uz/FormatData_uz_Latn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/vai/FormatData_vai.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/vai/FormatData_vai_Latn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ve/FormatData_ve.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/vi/FormatData_vi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/vun/FormatData_vun.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/wae/FormatData_wae.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/wal/FormatData_wal.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/xh/FormatData_xh.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/xog/FormatData_xog.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/yav/FormatData_yav.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/yo/FormatData_yo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/zh/FormatData_zh.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/zh/FormatData_zh_Hans_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/zh/FormatData_zh_Hans_MO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/zh/FormatData_zh_Hans_SG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/zh/FormatData_zh_Hant.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/zh/FormatData_zh_Hant_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/zh/FormatData_zh_Hant_MO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/zu/FormatData_zu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/tools/jar/resources/jar.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/tools/jar/resources/jar_de.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/tools/jar/resources/jar_es.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/tools/jar/resources/jar_fr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/tools/jar/resources/jar_it.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/tools/jar/resources/jar_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/tools/jar/resources/jar_ko.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/tools/jar/resources/jar_pt_BR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/tools/jar/resources/jar_sv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/tools/jar/resources/jar_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/tools/jar/resources/jar_zh_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/tools/jar/resources/jar_zh_TW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/CoreResourceBundleControl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/cldr/CLDRLocaleDataMetaInfo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/locale/provider/LocaleDataMetaInfo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/logging/resources/logging.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/logging/resources/logging_de.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/logging/resources/logging_es.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/logging/resources/logging_fr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/logging/resources/logging_it.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/logging/resources/logging_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/logging/resources/logging_ko.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/logging/resources/logging_pt_BR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/logging/resources/logging_sv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/logging/resources/logging_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/logging/resources/logging_zh_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/logging/resources/logging_zh_TW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/CalendarData.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/CurrencyNames.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/LocaleNames.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/CalendarData_ar.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/CurrencyNames_ar_AE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/CurrencyNames_ar_BH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/CurrencyNames_ar_DZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/CurrencyNames_ar_EG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/CurrencyNames_ar_IQ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/CurrencyNames_ar_JO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/CurrencyNames_ar_KW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/CurrencyNames_ar_LB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/CurrencyNames_ar_LY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/CurrencyNames_ar_MA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/CurrencyNames_ar_OM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/CurrencyNames_ar_QA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/CurrencyNames_ar_SA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/CurrencyNames_ar_SD.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/CurrencyNames_ar_SY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/CurrencyNames_ar_TN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/CurrencyNames_ar_YE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/LocaleNames_ar.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/be/CalendarData_be.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/be/CurrencyNames_be_BY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/be/LocaleNames_be.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/bg/CalendarData_bg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/bg/CurrencyNames_bg_BG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/bg/LocaleNames_bg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ca/CalendarData_ca.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ca/CurrencyNames_ca_ES.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ca/LocaleNames_ca.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/CalendarData.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/CurrencyNames.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/LocaleNames.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/TimeZoneNames.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/aa/CalendarData_aa_DJ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/aa/CalendarData_aa_ER.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/aa/CalendarData_aa_ET.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/aa/CurrencyNames_aa.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/aa/CurrencyNames_aa_DJ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/aa/CurrencyNames_aa_ER.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/af/CalendarData_af_NA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/af/CalendarData_af_ZA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/af/CurrencyNames_af.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/af/CurrencyNames_af_NA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/af/LocaleNames_af.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/af/TimeZoneNames_af.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/agq/CalendarData_agq_CM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/agq/CurrencyNames_agq.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/agq/LocaleNames_agq.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ak/CalendarData_ak_GH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ak/CurrencyNames_ak.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ak/LocaleNames_ak.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/am/CalendarData_am_ET.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/am/CurrencyNames_am.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/am/LocaleNames_am.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/am/TimeZoneNames_am.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ar/CalendarData_ar_AE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ar/CalendarData_ar_BH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ar/CalendarData_ar_DZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ar/CalendarData_ar_EG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ar/CalendarData_ar_IQ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ar/CalendarData_ar_JO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ar/CalendarData_ar_KW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ar/CalendarData_ar_LB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ar/CalendarData_ar_LY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ar/CalendarData_ar_MA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ar/CalendarData_ar_OM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ar/CalendarData_ar_QA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ar/CalendarData_ar_SA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ar/CalendarData_ar_SD.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ar/CalendarData_ar_SY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ar/CalendarData_ar_TN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ar/CalendarData_ar_YE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ar/CurrencyNames_ar.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ar/LocaleNames_ar.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ar/TimeZoneNames_ar.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/as/CalendarData_as_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/as/LocaleNames_as.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/as/TimeZoneNames_as.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/asa/CalendarData_asa_TZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/asa/CurrencyNames_asa.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/asa/LocaleNames_asa.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/az/CalendarData_az_Cyrl_AZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/az/CalendarData_az_Latn_AZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/az/CurrencyNames_az.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/az/CurrencyNames_az_Cyrl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/az/LocaleNames_az.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/az/LocaleNames_az_Cyrl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/az/TimeZoneNames_az.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bas/CalendarData_bas_CM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bas/CurrencyNames_bas.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bas/LocaleNames_bas.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/be/CalendarData_be_BY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/be/CurrencyNames_be.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/be/LocaleNames_be.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/be/TimeZoneNames_be.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bem/CalendarData_bem_ZM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bem/CurrencyNames_bem.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bem/LocaleNames_bem.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bez/CalendarData_bez_TZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bez/CurrencyNames_bez.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bez/LocaleNames_bez.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bg/CalendarData_bg_BG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bg/CurrencyNames_bg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bg/LocaleNames_bg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bg/TimeZoneNames_bg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bm/CalendarData_bm_ML.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bm/CurrencyNames_bm.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bm/LocaleNames_bm.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bn/CalendarData_bn_BD.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bn/CalendarData_bn_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bn/CurrencyNames_bn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bn/LocaleNames_bn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bn/LocaleNames_bn_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bn/TimeZoneNames_bn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bo/CalendarData_bo_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bo/CalendarData_bo_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bo/CurrencyNames_bo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bo/LocaleNames_bo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/br/CalendarData_br_FR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/br/CurrencyNames_br.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/br/LocaleNames_br.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/brx/CalendarData_brx_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/brx/CurrencyNames_brx.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/brx/LocaleNames_brx.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/brx/TimeZoneNames_brx.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bs/CalendarData_bs_BA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bs/CurrencyNames_bs.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bs/LocaleNames_bs.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bs/TimeZoneNames_bs.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/byn/CalendarData_byn_ER.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/byn/CurrencyNames_byn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ca/CalendarData_ca_ES.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ca/CurrencyNames_ca.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ca/LocaleNames_ca.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ca/TimeZoneNames_ca.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/cgg/CalendarData_cgg_UG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/cgg/CurrencyNames_cgg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/cgg/LocaleNames_cgg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/chr/CalendarData_chr_US.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/chr/CurrencyNames_chr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/chr/LocaleNames_chr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/chr/TimeZoneNames_chr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/cs/CalendarData_cs_CZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/cs/CurrencyNames_cs.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/cs/LocaleNames_cs.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/cs/TimeZoneNames_cs.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/cy/CalendarData_cy_GB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/cy/CurrencyNames_cy.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/cy/LocaleNames_cy.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/da/CalendarData_da_DK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/da/CurrencyNames_da.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/da/LocaleNames_da.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/da/TimeZoneNames_da.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/dav/CalendarData_dav_KE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/dav/CurrencyNames_dav.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/dav/LocaleNames_dav.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/de/CalendarData_de_AT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/de/CalendarData_de_BE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/de/CalendarData_de_CH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/de/CalendarData_de_DE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/de/CalendarData_de_LI.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/de/CalendarData_de_LU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/de/CurrencyNames_de.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/de/CurrencyNames_de_LU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/de/LocaleNames_de.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/de/LocaleNames_de_CH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/de/TimeZoneNames_de.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/dje/CalendarData_dje_NE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/dje/CurrencyNames_dje.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/dje/LocaleNames_dje.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/dua/CalendarData_dua_CM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/dua/LocaleNames_dua.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/dyo/CalendarData_dyo_SN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/dyo/CurrencyNames_dyo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/dyo/LocaleNames_dyo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/dz/CalendarData_dz_BT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/dz/CurrencyNames_dz.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ebu/CalendarData_ebu_KE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ebu/CurrencyNames_ebu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ebu/LocaleNames_ebu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ee/CalendarData_ee_GH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ee/CalendarData_ee_TG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ee/CurrencyNames_ee.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ee/LocaleNames_ee.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ee/TimeZoneNames_ee.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/el/CalendarData_el_CY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/el/CalendarData_el_GR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/el/CurrencyNames_el.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/el/LocaleNames_el.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/el/TimeZoneNames_el.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_AS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_AU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_BB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_BE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_BM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_BW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_BZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_CA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_Dsrt_US.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_GB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_GU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_GY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_IE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_JM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_MH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_MP.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_MT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_MU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_NA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_NZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_PH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_PK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_SG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_TT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_UM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_US.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_US_POSIX.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_VI.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_ZA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CalendarData_en_ZW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CurrencyNames_en.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CurrencyNames_en_AU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CurrencyNames_en_BB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CurrencyNames_en_BM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CurrencyNames_en_BW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CurrencyNames_en_BZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CurrencyNames_en_CA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CurrencyNames_en_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CurrencyNames_en_JM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CurrencyNames_en_MT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CurrencyNames_en_NA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CurrencyNames_en_NZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CurrencyNames_en_PH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CurrencyNames_en_PK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CurrencyNames_en_SG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CurrencyNames_en_TT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/CurrencyNames_en_ZA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/LocaleNames_en.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/LocaleNames_en_Dsrt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/TimeZoneNames_en.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/TimeZoneNames_en_AU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/TimeZoneNames_en_CA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/TimeZoneNames_en_Dsrt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/TimeZoneNames_en_GB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/TimeZoneNames_en_GU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/TimeZoneNames_en_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/TimeZoneNames_en_IE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/TimeZoneNames_en_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/TimeZoneNames_en_NZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/TimeZoneNames_en_PK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/TimeZoneNames_en_SG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/TimeZoneNames_en_ZA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/TimeZoneNames_en_ZW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/eo/LocaleNames_eo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CalendarData_es_AR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CalendarData_es_BO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CalendarData_es_CL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CalendarData_es_CO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CalendarData_es_CR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CalendarData_es_DO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CalendarData_es_EC.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CalendarData_es_ES.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CalendarData_es_GQ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CalendarData_es_GT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CalendarData_es_HN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CalendarData_es_MX.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CalendarData_es_NI.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CalendarData_es_PA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CalendarData_es_PE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CalendarData_es_PR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CalendarData_es_PY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CalendarData_es_SV.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CalendarData_es_US.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CalendarData_es_UY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CalendarData_es_VE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CurrencyNames_es.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CurrencyNames_es_AR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CurrencyNames_es_BO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CurrencyNames_es_CL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CurrencyNames_es_CO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CurrencyNames_es_CR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CurrencyNames_es_DO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CurrencyNames_es_EC.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CurrencyNames_es_GT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CurrencyNames_es_HN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CurrencyNames_es_MX.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CurrencyNames_es_NI.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CurrencyNames_es_PA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CurrencyNames_es_PE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CurrencyNames_es_PR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CurrencyNames_es_PY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CurrencyNames_es_US.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CurrencyNames_es_UY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/CurrencyNames_es_VE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/LocaleNames_es.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/LocaleNames_es_CL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/TimeZoneNames_es.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/TimeZoneNames_es_419.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/TimeZoneNames_es_AR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/et/CalendarData_et_EE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/et/CurrencyNames_et.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/et/LocaleNames_et.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/et/TimeZoneNames_et.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/eu/CalendarData_eu_ES.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/eu/CurrencyNames_eu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/eu/LocaleNames_eu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/eu/TimeZoneNames_eu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ewo/CalendarData_ewo_CM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ewo/CurrencyNames_ewo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ewo/LocaleNames_ewo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fa/CalendarData_fa_AF.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fa/CalendarData_fa_IR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fa/CurrencyNames_fa.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fa/CurrencyNames_fa_AF.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fa/LocaleNames_fa.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fa/LocaleNames_fa_AF.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fa/TimeZoneNames_fa.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ff/CalendarData_ff_SN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ff/CurrencyNames_ff.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ff/LocaleNames_ff.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fi/CalendarData_fi_FI.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fi/CurrencyNames_fi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fi/LocaleNames_fi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fi/TimeZoneNames_fi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fil/CalendarData_fil_PH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fil/CurrencyNames_fil.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fil/LocaleNames_fil.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fil/TimeZoneNames_fil.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fo/CalendarData_fo_FO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fo/CurrencyNames_fo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fo/LocaleNames_fo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_BE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_BF.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_BI.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_BJ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_BL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_CA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_CD.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_CF.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_CG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_CH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_CI.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_CM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_DJ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_FR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_GA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_GF.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_GN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_GP.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_GQ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_KM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_LU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_MC.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_MF.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_MG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_ML.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_MQ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_NE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_RE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_RW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_SN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_TD.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_TG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CalendarData_fr_YT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CurrencyNames_fr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CurrencyNames_fr_BI.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CurrencyNames_fr_CA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CurrencyNames_fr_DJ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CurrencyNames_fr_GN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CurrencyNames_fr_KM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/CurrencyNames_fr_LU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/LocaleNames_fr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/TimeZoneNames_fr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/TimeZoneNames_fr_CA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fur/CalendarData_fur_IT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ga/CalendarData_ga_IE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ga/CurrencyNames_ga.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ga/LocaleNames_ga.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ga/TimeZoneNames_ga.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/gd/CalendarData_gd_GB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/gl/CalendarData_gl_ES.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/gl/CurrencyNames_gl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/gl/LocaleNames_gl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/gl/TimeZoneNames_gl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/gsw/CalendarData_gsw_CH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/gsw/CurrencyNames_gsw.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/gsw/LocaleNames_gsw.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/gsw/TimeZoneNames_gsw.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/gu/CalendarData_gu_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/gu/CurrencyNames_gu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/gu/LocaleNames_gu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/gu/TimeZoneNames_gu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/guz/CalendarData_guz_KE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/guz/CurrencyNames_guz.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/guz/LocaleNames_guz.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/gv/CalendarData_gv_GB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/gv/LocaleNames_gv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ha/CalendarData_ha_Latn_GH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ha/CalendarData_ha_Latn_NE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ha/CalendarData_ha_Latn_NG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ha/CurrencyNames_ha.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ha/LocaleNames_ha.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/haw/CalendarData_haw_US.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/haw/LocaleNames_haw.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/he/CalendarData_he_IL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/he/CurrencyNames_he.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/he/LocaleNames_he.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/he/TimeZoneNames_he.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/hi/CalendarData_hi_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/hi/CurrencyNames_hi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/hi/LocaleNames_hi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/hi/TimeZoneNames_hi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/hr/CalendarData_hr_HR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/hr/CurrencyNames_hr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/hr/LocaleNames_hr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/hr/TimeZoneNames_hr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/hu/CalendarData_hu_HU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/hu/CurrencyNames_hu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/hu/LocaleNames_hu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/hu/TimeZoneNames_hu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/hy/CalendarData_hy_AM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/hy/CurrencyNames_hy.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/hy/LocaleNames_hy.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/id/CalendarData_id_ID.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/id/CurrencyNames_id.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/id/LocaleNames_id.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/id/TimeZoneNames_id.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ig/CalendarData_ig_NG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ig/CurrencyNames_ig.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ig/LocaleNames_ig.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ii/CalendarData_ii_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ii/CurrencyNames_ii.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ii/LocaleNames_ii.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/is/CalendarData_is_IS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/is/CurrencyNames_is.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/is/LocaleNames_is.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/is/TimeZoneNames_is.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/it/CalendarData_it_CH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/it/CalendarData_it_IT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/it/CurrencyNames_it.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/it/LocaleNames_it.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/it/TimeZoneNames_it.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ja/CalendarData_ja_JP.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ja/CurrencyNames_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ja/LocaleNames_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ja/TimeZoneNames_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/jmc/CalendarData_jmc_TZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/jmc/CurrencyNames_jmc.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/jmc/LocaleNames_jmc.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ka/CalendarData_ka_GE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ka/CurrencyNames_ka.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ka/LocaleNames_ka.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kab/CalendarData_kab_DZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kab/CurrencyNames_kab.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kab/LocaleNames_kab.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kam/CalendarData_kam_KE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kam/CurrencyNames_kam.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kam/LocaleNames_kam.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kde/CalendarData_kde_TZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kde/CurrencyNames_kde.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kde/LocaleNames_kde.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kea/CalendarData_kea_CV.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kea/CurrencyNames_kea.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kea/LocaleNames_kea.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kea/TimeZoneNames_kea.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/khq/CalendarData_khq_ML.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/khq/CurrencyNames_khq.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/khq/LocaleNames_khq.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ki/CalendarData_ki_KE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ki/CurrencyNames_ki.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ki/LocaleNames_ki.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kk/CalendarData_kk_Cyrl_KZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kk/CurrencyNames_kk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kk/LocaleNames_kk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kk/TimeZoneNames_kk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kl/CalendarData_kl_GL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kl/CurrencyNames_kl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kl/LocaleNames_kl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kln/CalendarData_kln_KE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kln/CurrencyNames_kln.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kln/LocaleNames_kln.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/km/CalendarData_km_KH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/km/CurrencyNames_km.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/km/LocaleNames_km.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kn/CalendarData_kn_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kn/CurrencyNames_kn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kn/LocaleNames_kn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kn/TimeZoneNames_kn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ko/CalendarData_ko_KR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ko/CurrencyNames_ko.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ko/LocaleNames_ko.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ko/TimeZoneNames_ko.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kok/CalendarData_kok_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kok/LocaleNames_kok.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kok/TimeZoneNames_kok.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ksb/CalendarData_ksb_TZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ksb/CurrencyNames_ksb.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ksb/LocaleNames_ksb.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ksf/CalendarData_ksf_CM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ksf/CurrencyNames_ksf.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ksf/LocaleNames_ksf.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ksh/CalendarData_ksh_DE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ksh/TimeZoneNames_ksh.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kw/CalendarData_kw_GB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kw/LocaleNames_kw.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lag/CalendarData_lag_TZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lag/CurrencyNames_lag.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lag/LocaleNames_lag.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lg/CalendarData_lg_UG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lg/CurrencyNames_lg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lg/LocaleNames_lg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ln/CalendarData_ln_CD.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ln/CalendarData_ln_CG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ln/CurrencyNames_ln.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ln/LocaleNames_ln.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lo/CalendarData_lo_LA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lo/CurrencyNames_lo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lt/CalendarData_lt_LT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lt/CurrencyNames_lt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lt/LocaleNames_lt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lt/TimeZoneNames_lt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lu/CalendarData_lu_CD.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lu/CurrencyNames_lu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lu/LocaleNames_lu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/luo/CalendarData_luo_KE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/luo/CurrencyNames_luo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/luo/LocaleNames_luo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/luy/CalendarData_luy_KE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/luy/CurrencyNames_luy.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/luy/LocaleNames_luy.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lv/CalendarData_lv_LV.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lv/CurrencyNames_lv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lv/LocaleNames_lv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lv/TimeZoneNames_lv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mas/CalendarData_mas_KE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mas/CalendarData_mas_TZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mas/CurrencyNames_mas.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mas/CurrencyNames_mas_TZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mas/LocaleNames_mas.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mer/CalendarData_mer_KE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mer/CurrencyNames_mer.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mer/LocaleNames_mer.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mfe/CalendarData_mfe_MU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mfe/CurrencyNames_mfe.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mfe/LocaleNames_mfe.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mg/CalendarData_mg_MG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mg/CurrencyNames_mg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mg/LocaleNames_mg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mgh/CalendarData_mgh_MZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mgh/CurrencyNames_mgh.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mgh/LocaleNames_mgh.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mk/CalendarData_mk_MK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mk/CurrencyNames_mk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mk/LocaleNames_mk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mk/TimeZoneNames_mk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ml/CalendarData_ml_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ml/CurrencyNames_ml.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ml/LocaleNames_ml.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ml/TimeZoneNames_ml.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mr/CalendarData_mr_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mr/CurrencyNames_mr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mr/LocaleNames_mr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mr/TimeZoneNames_mr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ms/CalendarData_ms_BN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ms/CalendarData_ms_MY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ms/CurrencyNames_ms.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ms/CurrencyNames_ms_BN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ms/LocaleNames_ms.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ms/TimeZoneNames_ms.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mt/CalendarData_mt_MT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mt/CurrencyNames_mt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mt/LocaleNames_mt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mt/TimeZoneNames_mt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mua/CalendarData_mua_CM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mua/CurrencyNames_mua.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mua/LocaleNames_mua.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/my/CalendarData_my_MM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/my/CurrencyNames_my.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/my/LocaleNames_my.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/my/TimeZoneNames_my.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/naq/CalendarData_naq_NA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/naq/CurrencyNames_naq.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/naq/LocaleNames_naq.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nb/CalendarData_nb_NO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nb/CurrencyNames_nb.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nb/LocaleNames_nb.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nb/TimeZoneNames_nb.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nd/CalendarData_nd_ZW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nd/CurrencyNames_nd.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nd/LocaleNames_nd.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ne/CalendarData_ne_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ne/CalendarData_ne_NP.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ne/CurrencyNames_ne.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ne/CurrencyNames_ne_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ne/LocaleNames_ne.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ne/TimeZoneNames_ne.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nl/CalendarData_nl_AW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nl/CalendarData_nl_BE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nl/CalendarData_nl_CW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nl/CalendarData_nl_NL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nl/CalendarData_nl_SX.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nl/CurrencyNames_nl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nl/CurrencyNames_nl_AW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nl/CurrencyNames_nl_CW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nl/CurrencyNames_nl_SX.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nl/LocaleNames_nl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nl/LocaleNames_nl_BE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nl/TimeZoneNames_nl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nmg/CalendarData_nmg_CM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nmg/CurrencyNames_nmg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nmg/LocaleNames_nmg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nn/CalendarData_nn_NO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nn/CurrencyNames_nn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nn/LocaleNames_nn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nn/TimeZoneNames_nn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nr/CalendarData_nr_ZA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nr/CurrencyNames_nr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nso/CalendarData_nso_ZA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nso/CurrencyNames_nso.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nus/CalendarData_nus_SD.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nus/LocaleNames_nus.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nyn/CalendarData_nyn_UG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nyn/CurrencyNames_nyn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nyn/LocaleNames_nyn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/om/CalendarData_om_ET.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/om/CalendarData_om_KE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/om/CurrencyNames_om.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/om/CurrencyNames_om_KE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/om/LocaleNames_om.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/or/CalendarData_or_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/or/CurrencyNames_or.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/or/LocaleNames_or.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/or/TimeZoneNames_or.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pa/CalendarData_pa_Arab_PK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pa/CalendarData_pa_Guru_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pa/CurrencyNames_pa.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pa/CurrencyNames_pa_Arab.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pa/LocaleNames_pa.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pa/LocaleNames_pa_Arab.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pa/TimeZoneNames_pa.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pl/CalendarData_pl_PL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pl/CurrencyNames_pl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pl/LocaleNames_pl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pl/TimeZoneNames_pl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ps/CalendarData_ps_AF.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ps/CurrencyNames_ps.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ps/LocaleNames_ps.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pt/CalendarData_pt_AO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pt/CalendarData_pt_BR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pt/CalendarData_pt_GW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pt/CalendarData_pt_MZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pt/CalendarData_pt_PT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pt/CalendarData_pt_ST.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pt/CurrencyNames_pt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pt/CurrencyNames_pt_AO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pt/CurrencyNames_pt_MZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pt/CurrencyNames_pt_PT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pt/CurrencyNames_pt_ST.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pt/LocaleNames_pt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pt/LocaleNames_pt_PT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pt/TimeZoneNames_pt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pt/TimeZoneNames_pt_PT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/rm/CalendarData_rm_CH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/rm/CurrencyNames_rm.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/rm/LocaleNames_rm.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/rn/CalendarData_rn_BI.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/rn/CurrencyNames_rn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/rn/LocaleNames_rn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ro/CalendarData_ro_MD.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ro/CalendarData_ro_RO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ro/CurrencyNames_ro.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ro/LocaleNames_ro.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ro/TimeZoneNames_ro.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/rof/CalendarData_rof_TZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/rof/CurrencyNames_rof.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/rof/LocaleNames_rof.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ru/CalendarData_ru_MD.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ru/CalendarData_ru_RU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ru/CalendarData_ru_UA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ru/CurrencyNames_ru.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ru/LocaleNames_ru.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ru/LocaleNames_ru_UA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ru/TimeZoneNames_ru.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/rw/CalendarData_rw_RW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/rw/CurrencyNames_rw.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/rw/LocaleNames_rw.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/rwk/CalendarData_rwk_TZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/rwk/CurrencyNames_rwk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/rwk/LocaleNames_rwk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sah/CalendarData_sah_RU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sah/LocaleNames_sah.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/saq/CalendarData_saq_KE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/saq/CurrencyNames_saq.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/saq/LocaleNames_saq.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sbp/CalendarData_sbp_TZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sbp/CurrencyNames_sbp.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sbp/LocaleNames_sbp.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/se/CalendarData_se_FI.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/se/CalendarData_se_NO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/se/CurrencyNames_se.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/se/LocaleNames_se.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/seh/CalendarData_seh_MZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/seh/CurrencyNames_seh.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/seh/LocaleNames_seh.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ses/CalendarData_ses_ML.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ses/CurrencyNames_ses.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ses/LocaleNames_ses.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sg/CalendarData_sg_CF.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sg/CurrencyNames_sg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sg/LocaleNames_sg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/shi/CalendarData_shi_Latn_MA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/shi/CalendarData_shi_Tfng_MA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/shi/CurrencyNames_shi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/shi/CurrencyNames_shi_Tfng.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/shi/LocaleNames_shi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/shi/LocaleNames_shi_Tfng.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/si/CalendarData_si_LK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/si/CurrencyNames_si.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/si/LocaleNames_si.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sk/CalendarData_sk_SK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sk/CurrencyNames_sk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sk/LocaleNames_sk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sk/TimeZoneNames_sk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sl/CalendarData_sl_SI.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sl/CurrencyNames_sl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sl/LocaleNames_sl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sl/TimeZoneNames_sl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sn/CalendarData_sn_ZW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sn/CurrencyNames_sn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sn/LocaleNames_sn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/so/CalendarData_so_DJ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/so/CalendarData_so_ET.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/so/CalendarData_so_KE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/so/CalendarData_so_SO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/so/CurrencyNames_so.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/so/CurrencyNames_so_DJ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/so/CurrencyNames_so_ET.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/so/CurrencyNames_so_KE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/so/LocaleNames_so.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sq/CalendarData_sq_AL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sq/CurrencyNames_sq.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sq/LocaleNames_sq.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sq/TimeZoneNames_sq.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sr/CalendarData_sr_Cyrl_BA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sr/CalendarData_sr_Cyrl_ME.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sr/CalendarData_sr_Cyrl_RS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sr/CalendarData_sr_Latn_BA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sr/CalendarData_sr_Latn_ME.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sr/CalendarData_sr_Latn_RS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sr/CurrencyNames_sr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sr/CurrencyNames_sr_Cyrl_BA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sr/CurrencyNames_sr_Latn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sr/LocaleNames_sr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sr/LocaleNames_sr_Latn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sr/TimeZoneNames_sr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sr/TimeZoneNames_sr_Latn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ss/CalendarData_ss_SZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ss/CalendarData_ss_ZA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ss/CurrencyNames_ss.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ssy/CalendarData_ssy_ER.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ssy/CurrencyNames_ssy.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/st/CalendarData_st_LS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/st/CalendarData_st_ZA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/st/CurrencyNames_st.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/st/CurrencyNames_st_LS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/st/LocaleNames_st.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sv/CalendarData_sv_FI.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sv/CalendarData_sv_SE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sv/CurrencyNames_sv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sv/LocaleNames_sv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sv/TimeZoneNames_sv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sw/CalendarData_sw_KE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sw/CalendarData_sw_TZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sw/CurrencyNames_sw.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sw/LocaleNames_sw.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sw/TimeZoneNames_sw.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/swc/CalendarData_swc_CD.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/swc/CurrencyNames_swc.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/swc/LocaleNames_swc.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ta/CalendarData_ta_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ta/CalendarData_ta_LK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ta/CurrencyNames_ta.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ta/CurrencyNames_ta_LK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ta/LocaleNames_ta.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ta/TimeZoneNames_ta.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/te/CalendarData_te_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/te/CurrencyNames_te.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/te/LocaleNames_te.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/te/TimeZoneNames_te.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/teo/CalendarData_teo_KE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/teo/CalendarData_teo_UG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/teo/CurrencyNames_teo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/teo/CurrencyNames_teo_KE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/teo/LocaleNames_teo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/tg/CalendarData_tg_Cyrl_TJ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/tg/LocaleNames_tg.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/th/CalendarData_th_TH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/th/CurrencyNames_th.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/th/LocaleNames_th.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/th/TimeZoneNames_th.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ti/CalendarData_ti_ER.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ti/CalendarData_ti_ET.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ti/CurrencyNames_ti.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ti/CurrencyNames_ti_ER.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ti/LocaleNames_ti.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/tig/CalendarData_tig_ER.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/tig/CurrencyNames_tig.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/tn/CalendarData_tn_ZA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/tn/CurrencyNames_tn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/to/CalendarData_to_TO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/to/CurrencyNames_to.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/to/LocaleNames_to.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/to/TimeZoneNames_to.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/tr/CalendarData_tr_TR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/tr/CurrencyNames_tr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/tr/LocaleNames_tr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/tr/TimeZoneNames_tr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ts/CalendarData_ts_ZA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ts/CurrencyNames_ts.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/twq/CalendarData_twq_NE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/twq/CurrencyNames_twq.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/twq/LocaleNames_twq.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/tzm/CalendarData_tzm_Latn_MA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/tzm/CurrencyNames_tzm.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/tzm/LocaleNames_tzm.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/uk/CalendarData_uk_UA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/uk/CurrencyNames_uk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/uk/LocaleNames_uk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/uk/TimeZoneNames_uk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ur/CalendarData_ur_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ur/CalendarData_ur_PK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ur/CurrencyNames_ur.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ur/LocaleNames_ur.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ur/TimeZoneNames_ur.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/uz/CalendarData_uz_Arab_AF.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/uz/CalendarData_uz_Cyrl_UZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/uz/CalendarData_uz_Latn_UZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/uz/CurrencyNames_uz_Arab.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/uz/LocaleNames_uz.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/uz/LocaleNames_uz_Arab.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/uz/LocaleNames_uz_Latn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/vai/CalendarData_vai_Latn_LR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/vai/CalendarData_vai_Vaii_LR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/vai/CurrencyNames_vai.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/vai/CurrencyNames_vai_Latn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/vai/LocaleNames_vai.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/vai/LocaleNames_vai_Latn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ve/CalendarData_ve_ZA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ve/CurrencyNames_ve.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/vi/CalendarData_vi_VN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/vi/CurrencyNames_vi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/vi/LocaleNames_vi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/vi/TimeZoneNames_vi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/vun/CalendarData_vun_TZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/vun/CurrencyNames_vun.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/vun/LocaleNames_vun.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/wae/CalendarData_wae_CH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/wae/LocaleNames_wae.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/wal/CalendarData_wal_ET.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/wal/CurrencyNames_wal.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/xh/CalendarData_xh_ZA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/xh/CurrencyNames_xh.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/xog/CalendarData_xog_UG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/xog/CurrencyNames_xog.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/xog/LocaleNames_xog.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/yav/CalendarData_yav_CM.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/yav/CurrencyNames_yav.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/yav/LocaleNames_yav.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/yo/CalendarData_yo_NG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/yo/CurrencyNames_yo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/yo/LocaleNames_yo.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/CalendarData_zh_Hans_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/CalendarData_zh_Hans_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/CalendarData_zh_Hans_MO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/CalendarData_zh_Hans_SG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/CalendarData_zh_Hant_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/CalendarData_zh_Hant_MO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/CalendarData_zh_Hant_TW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/CurrencyNames_zh.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/CurrencyNames_zh_Hans_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/CurrencyNames_zh_Hans_MO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/CurrencyNames_zh_Hans_SG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/CurrencyNames_zh_Hant.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/CurrencyNames_zh_Hant_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/LocaleNames_zh.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/LocaleNames_zh_Hans_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/LocaleNames_zh_Hans_MO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/LocaleNames_zh_Hans_SG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/LocaleNames_zh_Hant.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/LocaleNames_zh_Hant_HK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/TimeZoneNames_zh.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/TimeZoneNames_zh_Hant.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zu/CalendarData_zu_ZA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zu/CurrencyNames_zu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zu/LocaleNames_zu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zu/TimeZoneNames_zu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cs/CalendarData_cs.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cs/CurrencyNames_cs_CZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cs/LocaleNames_cs.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/da/CalendarData_da.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/da/CurrencyNames_da_DK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/da/LocaleNames_da.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/de/CalendarData_de.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/de/CurrencyNames_de.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/de/CurrencyNames_de_AT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/de/CurrencyNames_de_CH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/de/CurrencyNames_de_DE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/de/CurrencyNames_de_GR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/de/CurrencyNames_de_LU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/de/LocaleNames_de.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/el/CalendarData_el.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/el/CalendarData_el_CY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/el/CurrencyNames_el_CY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/el/CurrencyNames_el_GR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/el/LocaleNames_el.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/el/LocaleNames_el_CY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/en/CalendarData_en.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/en/CalendarData_en_GB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/en/CalendarData_en_IE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/en/CalendarData_en_MT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/en/CurrencyNames_en_AU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/en/CurrencyNames_en_CA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/en/CurrencyNames_en_GB.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/en/CurrencyNames_en_IE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/en/CurrencyNames_en_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/en/CurrencyNames_en_MT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/en/CurrencyNames_en_NZ.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/en/CurrencyNames_en_PH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/en/CurrencyNames_en_SG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/en/CurrencyNames_en_US.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/en/CurrencyNames_en_ZA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/en/LocaleNames_en.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/en/LocaleNames_en_MT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/en/LocaleNames_en_PH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/en/LocaleNames_en_SG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CalendarData_es.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CalendarData_es_ES.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CalendarData_es_US.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es_AR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es_BO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es_CL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es_CO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es_CR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es_CU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es_DO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es_EC.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es_ES.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es_GT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es_HN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es_MX.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es_NI.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es_PA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es_PE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es_PR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es_PY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es_SV.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es_US.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es_UY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/CurrencyNames_es_VE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/LocaleNames_es.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/LocaleNames_es_US.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/et/CalendarData_et.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/et/CurrencyNames_et_EE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/et/LocaleNames_et.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/fi/CalendarData_fi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/fi/CurrencyNames_fi_FI.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/fi/LocaleNames_fi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/fr/CalendarData_fr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/fr/CalendarData_fr_CA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/fr/CurrencyNames_fr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/fr/CurrencyNames_fr_BE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/fr/CurrencyNames_fr_CA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/fr/CurrencyNames_fr_CH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/fr/CurrencyNames_fr_FR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/fr/CurrencyNames_fr_LU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/fr/LocaleNames_fr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ga/CurrencyNames_ga_IE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ga/LocaleNames_ga.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/hi/CalendarData_hi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/hi/CurrencyNames_hi_IN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/hi/LocaleNames_hi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/hr/CalendarData_hr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/hr/CurrencyNames_hr_HR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/hr/LocaleNames_hr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/hu/CalendarData_hu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/hu/CurrencyNames_hu_HU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/hu/LocaleNames_hu.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/in/CalendarData_in_ID.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/in/CurrencyNames_in_ID.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/in/LocaleNames_in.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/is/CalendarData_is.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/is/CurrencyNames_is_IS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/is/LocaleNames_is.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/it/CalendarData_it.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/it/CurrencyNames_it.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/it/CurrencyNames_it_CH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/it/CurrencyNames_it_IT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/it/LocaleNames_it.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/iw/CalendarData_iw.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/iw/CurrencyNames_iw_IL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/iw/LocaleNames_iw.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ja/CalendarData_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ja/CurrencyNames_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ja/CurrencyNames_ja_JP.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ja/LocaleNames_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ko/CalendarData_ko.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ko/CurrencyNames_ko.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ko/CurrencyNames_ko_KR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ko/LocaleNames_ko.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/lt/CalendarData_lt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/lt/CurrencyNames_lt_LT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/lt/LocaleNames_lt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/lv/CalendarData_lv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/lv/CurrencyNames_lv_LV.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/lv/LocaleNames_lv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/mk/CalendarData_mk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/mk/CurrencyNames_mk_MK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/mk/LocaleNames_mk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ms/CalendarData_ms_MY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ms/CurrencyNames_ms_MY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ms/LocaleNames_ms.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/mt/CalendarData_mt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/mt/CalendarData_mt_MT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/mt/CurrencyNames_mt_MT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/mt/LocaleNames_mt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/nl/CalendarData_nl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/nl/CurrencyNames_nl_BE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/nl/CurrencyNames_nl_NL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/nl/LocaleNames_nl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/no/CalendarData_no.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/no/CurrencyNames_no_NO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/no/LocaleNames_no.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/no/LocaleNames_no_NO_NY.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/pl/CalendarData_pl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/pl/CurrencyNames_pl_PL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/pl/LocaleNames_pl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/pt/CalendarData_pt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/pt/CalendarData_pt_BR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/pt/CalendarData_pt_PT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/pt/CurrencyNames_pt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/pt/CurrencyNames_pt_BR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/pt/CurrencyNames_pt_PT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/pt/LocaleNames_pt.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/pt/LocaleNames_pt_PT.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ro/CalendarData_ro.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ro/CurrencyNames_ro_RO.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ro/LocaleNames_ro.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ru/CalendarData_ru.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ru/CurrencyNames_ru_RU.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ru/LocaleNames_ru.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sk/CalendarData_sk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sk/CurrencyNames_sk_SK.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sk/LocaleNames_sk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sl/CalendarData_sl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sl/CurrencyNames_sl_SI.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sl/LocaleNames_sl.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sq/CalendarData_sq.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sq/CurrencyNames_sq_AL.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sq/LocaleNames_sq.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sr/CalendarData_sr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sr/CalendarData_sr_Latn_BA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sr/CalendarData_sr_Latn_ME.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sr/CalendarData_sr_Latn_RS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sr/CurrencyNames_sr_BA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sr/CurrencyNames_sr_CS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sr/CurrencyNames_sr_Latn_BA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sr/CurrencyNames_sr_Latn_ME.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sr/CurrencyNames_sr_Latn_RS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sr/CurrencyNames_sr_ME.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sr/CurrencyNames_sr_RS.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sr/LocaleNames_sr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sr/LocaleNames_sr_Latn.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sv/CalendarData_sv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sv/CurrencyNames_sv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sv/CurrencyNames_sv_SE.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sv/LocaleNames_sv.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/th/CalendarData_th.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/th/CurrencyNames_th_TH.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/th/LocaleNames_th.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/tr/CalendarData_tr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/tr/CurrencyNames_tr_TR.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/tr/LocaleNames_tr.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/uk/CalendarData_uk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/uk/CurrencyNames_uk_UA.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/uk/LocaleNames_uk.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/vi/CalendarData_vi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/vi/CurrencyNames_vi_VN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/vi/LocaleNames_vi.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/zh/CalendarData_zh.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/zh/CurrencyNames_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/zh/CurrencyNames_zh_TW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/zh/LocaleNames_zh.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/zh/LocaleNames_zh_SG.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/zh/LocaleNames_zh_TW.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/impsrc/com/sun/corba/se/impl/logging/ActivationSystemException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/impsrc/com/sun/corba/se/impl/logging/InterceptorsSystemException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/impsrc/com/sun/corba/se/impl/logging/IORSystemException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/impsrc/com/sun/corba/se/impl/logging/NamingSystemException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/impsrc/com/sun/corba/se/impl/logging/OMGSystemException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/impsrc/com/sun/corba/se/impl/logging/ORBUtilSystemException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/impsrc/com/sun/corba/se/impl/logging/POASystemException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/impsrc/com/sun/corba/se/impl/logging/UtilSystemException.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/doclets/formats/html/resources/standard.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/doclets/formats/html/resources/standard_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/doclets/formats/html/resources/standard_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/doclets/internal/toolkit/resources/doclets.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/doclets/internal/toolkit/resources/doclets_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/doclets/internal/toolkit/resources/doclets_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/doclint/resources/doclint.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/doclint/resources/doclint_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/doclint/resources/doclint_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javac/resources/compiler.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javac/resources/compiler_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javac/resources/compiler_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javac/resources/javac.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javac/resources/javac_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javac/resources/javac_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javac/resources/legacy.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javac/resources/version.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javadoc/resources/javadoc.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javadoc/resources/javadoc_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javadoc/resources/javadoc_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javadoc/resources/version.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javah/resources/l10n.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javah/resources/l10n_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javah/resources/l10n_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javah/resources/version.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javap/resources/javap.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javap/resources/javap_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javap/resources/javap_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javap/resources/version.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/jdeps/resources/jdeps.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/jdeps/resources/jdeps_ja.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/jdeps/resources/jdeps_zh_CN.java +@OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/jdeps/resources/version.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/activation/CommandHandler.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/activation/NameServiceStartThread.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/activation/ORBD.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/activation/ProcessMonitorThread.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/activation/RepositoryImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/activation/ServerMain.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/activation/ServerManagerImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/activation/ServerTableEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/activation/ServerTool.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/copyobject/CopierManagerImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/copyobject/FallbackObjectCopierImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/copyobject/JavaStreamObjectCopierImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/copyobject/ORBStreamObjectCopierImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/copyobject/ReferenceObjectCopierImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/corba/AnyImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/corba/AnyImplHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/corba/AsynchInvoke.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/corba/ContextImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/corba/ContextListImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/corba/CORBAObjectImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/corba/EnvironmentImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/corba/ExceptionListImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/corba/NamedValueImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/corba/NVListImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/corba/PrincipalImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/corba/RequestImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/corba/ServerRequestImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/corba/TCUtility.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/corba/TypeCodeFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/corba/TypeCodeImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/corba/TypeCodeImplHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/dynamicany/DynAnyBasicImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/dynamicany/DynAnyCollectionImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/dynamicany/DynAnyComplexImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/dynamicany/DynAnyConstructedImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/dynamicany/DynAnyFactoryImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/dynamicany/DynAnyImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/dynamicany/DynAnyUtil.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/dynamicany/DynArrayImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/dynamicany/DynEnumImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/dynamicany/DynFixedImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/dynamicany/DynSequenceImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/dynamicany/DynStructImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/dynamicany/DynUnionImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/dynamicany/DynValueBoxImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/dynamicany/DynValueCommonImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/dynamicany/DynValueImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/BufferManagerFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/BufferManagerRead.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/BufferManagerReadGrow.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/BufferManagerReadStream.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/BufferManagerWrite.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/BufferManagerWriteCollect.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/BufferManagerWriteGrow.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/BufferManagerWriteStream.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/BufferQueue.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/ByteBufferWithInfo.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/CachedCodeBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/CDRInputObject.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/CDRInputStream.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/CDRInputStream_1_0.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/CDRInputStream_1_1.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/CDRInputStream_1_2.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/CDRInputStreamBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/CDROutputObject.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/CDROutputStream.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/CDROutputStream_1_0.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/CDROutputStream_1_1.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/CDROutputStream_1_2.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/CDROutputStreamBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/CodeSetCache.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/CodeSetComponentInfo.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/CodeSetConversion.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/EncapsInputStream.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/EncapsOutputStream.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/IDLJavaSerializationInputStream.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/IDLJavaSerializationOutputStream.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/MarkAndResetHandler.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/MarshalInputStream.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/MarshalOutputStream.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/OSFCodeSetRegistry.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/RestorableInputStream.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/TypeCodeInputStream.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/TypeCodeOutputStream.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/TypeCodeReader.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/WrapperInputStream.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/interceptors/CDREncapsCodec.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/interceptors/ClientRequestInfoImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/interceptors/CodecFactoryImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/interceptors/InterceptorInvoker.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/interceptors/InterceptorList.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/interceptors/IORInfoImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/interceptors/ORBInitInfoImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/interceptors/PICurrent.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/interceptors/PIHandlerImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/interceptors/PINoOpHandlerImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/interceptors/RequestInfoImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/interceptors/ServerRequestInfoImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/interceptors/SlotTable.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/interceptors/SlotTableStack.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/io/FVDCodeBaseImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/io/IIOPOutputStream.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/io/InputStreamHook.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/io/ObjectStreamClassCorbaExt.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/io/ObjectStreamField.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/io/OptionalDataException.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/io/OutputStreamHook.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/io/TypeMismatchException.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/io/ValueHandlerImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/io/ValueUtility.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/ByteBuffer.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/EncapsulationUtility.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/FreezableList.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/GenericIdentifiable.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/GenericTaggedComponent.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/GenericTaggedProfile.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/IdentifiableFactoryFinderBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/iiop/AlternateIIOPAddressComponentImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/iiop/CodeSetsComponentImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/iiop/IIOPAddressBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/iiop/IIOPAddressClosureImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/iiop/IIOPAddressImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/iiop/IIOPProfileImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/iiop/IIOPProfileTemplateImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/iiop/JavaCodebaseComponentImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/iiop/JavaSerializationComponent.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/iiop/MaxStreamFormatVersionComponentImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/iiop/ORBTypeComponentImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/iiop/RequestPartitioningComponentImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/IORImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/IORTemplateImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/IORTemplateListImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/JIDLObjectKeyTemplate.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/NewObjectKeyTemplateBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/ObjectAdapterIdArray.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/ObjectAdapterIdBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/ObjectAdapterIdNumber.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/ObjectIdImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/ObjectKeyFactoryImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/ObjectKeyImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/ObjectKeyTemplateBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/ObjectReferenceFactoryImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/ObjectReferenceProducerBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/ObjectReferenceTemplateImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/OldJIDLObjectKeyTemplate.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/OldObjectKeyTemplateBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/OldPOAObjectKeyTemplate.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/POAObjectKeyTemplate.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/StubIORImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/TaggedComponentFactoryFinderImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/TaggedProfileFactoryFinderImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/TaggedProfileTemplateFactoryFinderImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/WireObjectKeyTemplate.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/StubDelegateImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/javax/rmi/PortableRemoteObject.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/legacy/connection/DefaultSocketFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/legacy/connection/EndPointInfoImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/legacy/connection/LegacyServerSocketManagerImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/legacy/connection/SocketFactoryAcceptorImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/legacy/connection/SocketFactoryConnectionImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/legacy/connection/SocketFactoryContactInfoImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/legacy/connection/SocketFactoryContactInfoListImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/legacy/connection/SocketFactoryContactInfoListIteratorImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/legacy/connection/USLPort.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/monitoring/MonitoredAttributeInfoFactoryImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/monitoring/MonitoredAttributeInfoImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/monitoring/MonitoredObjectFactoryImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/monitoring/MonitoredObjectImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/monitoring/MonitoringManagerFactoryImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/monitoring/MonitoringManagerImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/cosnaming/BindingIteratorImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/cosnaming/InternalBindingKey.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/cosnaming/InternalBindingValue.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/cosnaming/InterOperableNamingImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/cosnaming/NamingContextDataStore.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/cosnaming/NamingContextImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/cosnaming/NamingUtils.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/cosnaming/TransientBindingIterator.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/cosnaming/TransientNameServer.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/cosnaming/TransientNameService.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/cosnaming/TransientNamingContext.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/namingutil/CorbalocURL.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/namingutil/CorbanameURL.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/namingutil/IIOPEndpointInfo.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/namingutil/INSURL.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/namingutil/INSURLBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/namingutil/INSURLHandler.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/namingutil/NamingConstants.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/namingutil/Utility.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/pcosnaming/InternalBindingKey.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/pcosnaming/InternalBindingValue.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/pcosnaming/NameServer.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/pcosnaming/NameService.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/pcosnaming/NamingContextImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/pcosnaming/PersistentBindingIterator.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/pcosnaming/ServantManagerImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/NullServantImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/ActiveObjectMap.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/AOMEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/BadServerIdHandler.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/DelegateImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/IdAssignmentPolicyImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/IdUniquenessPolicyImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/ImplicitActivationPolicyImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/LifespanPolicyImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POACurrent.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediator.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorBase_R.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_NR_UDS.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_NR_USM.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_AOM.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_UDS.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/Policies.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/RequestProcessingPolicyImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/ServantRetentionPolicyImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/ThreadPolicyImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/toa/TOA.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/toa/TOAFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/toa/TOAImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/toa/TransientObjectManager.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orb/AppletDataCollector.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orb/DataCollectorBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orb/DataCollectorFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orb/NormalDataCollector.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orb/NormalParserAction.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orb/NormalParserData.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orb/ORBConfiguratorImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orb/ORBDataParserImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orb/ORBSingleton.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orb/ORBVersionImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orb/ParserAction.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orb/ParserActionBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orb/ParserActionFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orb/ParserDataBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orb/ParserTable.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orb/PrefixParserAction.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orb/PrefixParserData.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orb/PropertyOnlyDataCollector.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/CacheTable.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/closure/Constant.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/closure/Future.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/concurrent/CondVar.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/concurrent/DebugMutex.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/concurrent/Mutex.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/concurrent/ReentrantMutex.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/concurrent/Sync.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/concurrent/SyncUtil.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/CorbaResourceUtil.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/DenseIntMapImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/fsm/GuardedAction.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/fsm/NameBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/fsm/StateEngineImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/GetPropertyAction.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/graph/Graph.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/graph/GraphImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/graph/Node.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/graph/NodeData.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/HexOutputStream.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/LegacyHookGetFields.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/LegacyHookPutFields.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/LogKeywords.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectStreamClass_1_3_1.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectStreamClassUtil_1_3.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectStreamField.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectUtility.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectWriter.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ORBConstants.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ORBUtility.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/RepIdDelegator.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/RepositoryIdFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/RepositoryIdInterface.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/RepositoryIdStrings.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/RepositoryIdUtility.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/StackImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolManagerImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/threadpool/TimeoutException.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/threadpool/WorkQueueImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/DynamicAccessPermission.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/DynamicMethodMarshallerImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/DynamicStubImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/ExceptionHandler.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/ExceptionHandlerImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/IDLNameTranslatorImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/IDLType.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/IDLTypeException.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/IDLTypesUtil.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/InvocationHandlerFactoryImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/JNDIStateFactoryImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/PresentationManagerImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/ReflectiveTie.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/StubConnectImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/StubFactoryBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/StubFactoryDynamicBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/StubFactoryFactoryBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/StubFactoryFactoryDynamicBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/StubFactoryFactoryProxyImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/StubFactoryFactoryStaticImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/StubFactoryProxyImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/StubFactoryStaticImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/StubInvocationHandlerImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/AddressingDispositionException.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/BootstrapServerRequestDispatcher.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaClientDelegateImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaClientRequestDispatcherImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaInvocationInfo.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaMessageMediatorImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaServerRequestDispatcherImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/FullServantCacheLocalCRDImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/AddressingDispositionHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/CancelRequestMessage.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/CancelRequestMessage_1_0.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/CancelRequestMessage_1_1.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/CancelRequestMessage_1_2.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/FragmentMessage.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/FragmentMessage_1_1.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/FragmentMessage_1_2.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/IORAddressingInfo.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/IORAddressingInfoHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/KeyAddr.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/LocateReplyMessage.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/LocateReplyMessage_1_0.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/LocateReplyMessage_1_1.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/LocateReplyMessage_1_2.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/LocateReplyOrReplyMessage.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/LocateRequestMessage.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/LocateRequestMessage_1_0.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/LocateRequestMessage_1_1.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/LocateRequestMessage_1_2.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/Message.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/Message_1_0.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/Message_1_1.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/Message_1_2.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/MessageBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/MessageHandler.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/ProfileAddr.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/ReferenceAddr.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/ReplyMessage.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/ReplyMessage_1_0.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/ReplyMessage_1_1.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/ReplyMessage_1_2.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/RequestMessage.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/RequestMessage_1_0.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/RequestMessage_1_1.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/RequestMessage_1_2.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/TargetAddress.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/TargetAddressHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/InfoOnlyServantCacheLocalCRDImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/INSServerRequestDispatcher.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/JIDLLocalCRDImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/LocalClientRequestDispatcherBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/MinimalServantCacheLocalCRDImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/NotLocalLocalCRDImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/POALocalCRDImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/RequestCanceledException.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/RequestDispatcherRegistryImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/ServantCacheLocalCRDBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/SharedCDRClientRequestDispatcherImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/SpecialMethod.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/resolver/BootstrapResolverImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/resolver/CompositeResolverImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/resolver/FileResolverImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/resolver/INSURLOperationImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/resolver/LocalResolverImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/resolver/ORBDefaultInitRefResolverImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/resolver/ORBInitRefResolverImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/resolver/SplitLocalResolverImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/transport/ByteBufferPoolImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaConnectionCacheBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaContactInfoBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaContactInfoListImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaContactInfoListIteratorImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaInboundConnectionCacheImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaOutboundConnectionCacheImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaResponseWaitingRoomImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaTransportManagerImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/transport/DefaultIORToSocketInfoImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/transport/DefaultSocketFactoryImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/transport/EventHandlerBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/transport/ListenerThreadImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/transport/ReaderThreadImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/transport/ReadTCPTimeoutsImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/transport/SharedCDRContactInfoImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelAcceptorImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelConnectionImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelContactInfoImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/util/IdentityHashtable.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/util/IdentityHashtableEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/util/IdentityHashtableEnumerator.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/util/JDKBridge.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/util/JDKClassLoader.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/util/ORBProperties.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/util/PackagePrefixChecker.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/util/RepositoryId.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/util/RepositoryIdCache.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/util/SUNVMCID.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/util/Utility.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/util/Version.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/internal/corba/ORBSingleton.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/internal/CosNaming/BootstrapServer.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/internal/iiop/ORB.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/internal/Interceptors/PIORB.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/internal/POA/POAORB.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/org/omg/CORBA/ORB.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/broker/Broker.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/encoding/InputObject.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/encoding/OutputObject.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/protocol/ClientDelegate.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/protocol/ClientInvocationInfo.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/protocol/ClientRequestDispatcher.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/protocol/MessageMediator.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/protocol/ProtocolHandler.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/protocol/ServerRequestDispatcher.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/transport/Acceptor.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/transport/ByteBufferPool.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/transport/Connection.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/transport/ConnectionCache.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/transport/ContactInfo.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/transport/ContactInfoList.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/transport/ContactInfoListIterator.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/transport/EventHandler.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/transport/InboundConnectionCache.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/transport/ListenerThread.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/transport/OutboundConnectionCache.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/transport/ReaderThread.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/transport/ResponseWaitingRoom.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/transport/Selector.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/transport/TransportManager.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/copyobject/CopierManager.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/copyobject/CopyobjectDefaults.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/copyobject/ObjectCopier.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/copyobject/ObjectCopierFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/copyobject/ReflectiveCopyException.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/encoding/CorbaInputObject.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/encoding/CorbaOutputObject.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/extension/CopyObjectPolicy.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/extension/RequestPartitioningPolicy.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/extension/ServantCachingPolicy.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/extension/ZeroPortPolicy.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/EncapsulationFactoryBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/Identifiable.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/IdentifiableBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/IdentifiableContainerBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/IdentifiableFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/IdentifiableFactoryFinder.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/iiop/AlternateIIOPAddressComponent.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/iiop/CodeSetsComponent.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/iiop/GIOPVersion.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/iiop/IIOPAddress.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/iiop/IIOPFactories.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/iiop/IIOPProfile.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/iiop/IIOPProfileTemplate.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/iiop/JavaCodebaseComponent.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/iiop/MaxStreamFormatVersionComponent.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/iiop/ORBTypeComponent.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/iiop/RequestPartitioningComponent.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/IOR.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/IORFactories.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/IORFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/IORTemplate.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/IORTemplateList.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/MakeImmutable.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/ObjectAdapterId.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/ObjectId.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/ObjectKey.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/ObjectKeyFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/ObjectKeyTemplate.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/TaggedComponent.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/TaggedComponentBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/TaggedComponentFactoryFinder.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/TaggedProfile.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/TaggedProfileTemplate.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/TaggedProfileTemplateBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/Writeable.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/WriteContents.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/legacy/connection/Connection.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/legacy/connection/GetEndPointInfoAgainException.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/legacy/connection/LegacyServerSocketEndPointInfo.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/legacy/connection/LegacyServerSocketManager.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/legacy/connection/ORBSocketFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/legacy/interceptor/IORInfoExt.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/legacy/interceptor/ORBInitInfoExt.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/legacy/interceptor/RequestInfoExt.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/legacy/interceptor/UnknownType.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/logging/CORBALogDomains.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/logging/LogWrapperBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/logging/LogWrapperFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/monitoring/LongMonitoredAttributeBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/monitoring/MonitoredAttribute.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/monitoring/MonitoredAttributeBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/monitoring/MonitoredAttributeInfo.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/monitoring/MonitoredAttributeInfoFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/monitoring/MonitoredObject.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/monitoring/MonitoredObjectFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/monitoring/MonitoringConstants.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/monitoring/MonitoringFactories.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/monitoring/MonitoringManager.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/monitoring/MonitoringManagerFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/monitoring/StatisticMonitoredAttribute.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/monitoring/StatisticsAccumulator.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/monitoring/StringMonitoredAttributeBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/oa/NullServant.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/oa/OADefault.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/oa/OADestroyed.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/oa/OAInvocationInfo.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/oa/ObjectAdapter.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/oa/ObjectAdapterBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/oa/ObjectAdapterFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orb/DataCollector.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orb/Operation.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orb/OperationFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orb/ORB.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orb/ORBConfigurator.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orb/ORBData.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orb/ORBVersion.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orb/ORBVersionFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orb/ParserData.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orb/ParserDataFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orb/ParserImplBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orb/ParserImplTableBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orb/PropertyParser.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orb/StringPair.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/closure/Closure.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/closure/ClosureFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/fsm/Action.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/fsm/ActionBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/fsm/FSM.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/fsm/FSMImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/fsm/FSMTest.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/fsm/Guard.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/fsm/GuardBase.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/fsm/Input.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/fsm/InputImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/fsm/State.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/fsm/StateEngine.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/fsm/StateEngineFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/fsm/StateImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/proxy/CompositeInvocationHandler.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/proxy/CompositeInvocationHandlerImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/proxy/DelegateInvocationHandlerImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/proxy/InvocationHandlerFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/proxy/LinkedInvocationHandler.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/threadpool/NoSuchThreadPoolException.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/threadpool/NoSuchWorkQueueException.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/threadpool/ThreadPool.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/threadpool/ThreadPoolChooser.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/threadpool/ThreadPoolManager.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/threadpool/Work.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/threadpool/WorkQueue.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/presentation/rmi/DynamicMethodMarshaller.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/presentation/rmi/DynamicStub.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/presentation/rmi/IDLNameTranslator.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/presentation/rmi/PresentationDefaults.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/presentation/rmi/PresentationManager.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/presentation/rmi/StubAdapter.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/presentation/rmi/StubWrapper.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/protocol/ClientDelegateFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/protocol/CorbaClientDelegate.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/protocol/CorbaMessageMediator.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/protocol/CorbaProtocolHandler.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/protocol/CorbaServerRequestDispatcher.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/protocol/ForwardException.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/protocol/InitialServerRequestDispatcher.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/protocol/LocalClientRequestDispatcher.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/protocol/LocalClientRequestDispatcherFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/protocol/PIHandler.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/protocol/RequestDispatcherDefault.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/protocol/RequestDispatcherRegistry.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/protocol/RetryType.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/resolver/LocalResolver.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/resolver/Resolver.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/resolver/ResolverDefault.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/servicecontext/CodeSetServiceContext.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/servicecontext/MaxStreamFormatVersionServiceContext.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/servicecontext/ORBVersionServiceContext.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/servicecontext/SendingContextServiceContext.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/servicecontext/ServiceContext.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/servicecontext/ServiceContextData.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/servicecontext/ServiceContextRegistry.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/servicecontext/ServiceContexts.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/servicecontext/UEInfoServiceContext.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/servicecontext/UnknownServiceContext.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/transport/CorbaAcceptor.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/transport/CorbaConnection.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/transport/CorbaConnectionCache.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/transport/CorbaContactInfo.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/transport/CorbaContactInfoList.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/transport/CorbaContactInfoListFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/transport/CorbaContactInfoListIterator.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/transport/CorbaResponseWaitingRoom.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/transport/CorbaTransportManager.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/transport/IIOPPrimaryToContactInfo.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/transport/IORToSocketInfo.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/transport/IORTransformer.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/transport/ORBSocketFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/transport/ReadTimeouts.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/transport/ReadTimeoutsFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/transport/SocketInfo.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/transport/SocketOrChannelAcceptor.java +@OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/transport/TransportDefault.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/_IDLTypeStub.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/AttrDescriptionSeqHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/AttributeDescription.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/AttributeDescriptionHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/AttributeMode.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/AttributeModeHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/ContextIdentifierHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/ContextIdSeqHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/DefinitionKindHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/ExcDescriptionSeqHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/ExceptionDescription.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/ExceptionDescriptionHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/IdentifierHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/IDLTypeHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/IDLTypeOperations.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/Initializer.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/InitializerHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/InitializerSeqHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/IRObjectOperations.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/OpDescriptionSeqHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/OperationDescription.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/OperationDescriptionHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/OperationMode.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/OperationModeHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/ParameterDescription.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/ParameterDescriptionHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/ParameterMode.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/ParameterModeHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/ParDescriptionSeqHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/portable/ValueHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/Repository.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/RepositoryHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/RepositoryIdHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/RepositoryIdSeqHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/StructMemberHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/StructMemberSeqHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/ValueDefPackage/FullValueDescription.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/ValueDefPackage/FullValueDescriptionHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/ValueMemberHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/ValueMemberSeqHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/VersionSpecHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/VisibilityHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/SendingContext/_CodeBaseImplBase.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/SendingContext/_CodeBaseStub.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/SendingContext/CodeBase.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/SendingContext/CodeBaseHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/SendingContext/CodeBaseOperations.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/SendingContext/CodeBasePackage/URLHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/SendingContext/CodeBasePackage/URLSeqHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/org/omg/SendingContext/CodeBasePackage/ValueDescSeqHelper.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/Arguments.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/AttributeEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/AttributeGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/Comment.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/Compile.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/ConstEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/And.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/BinaryExpr.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/BooleanAnd.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/BooleanNot.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/BooleanOr.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/DefaultExprFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/Divide.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/Equal.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/EvaluationException.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/Expression.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/ExprFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/GreaterEqual.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/GreaterThan.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/LessEqual.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/LessThan.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/Minus.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/Modulo.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/Negative.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/Not.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/NotEqual.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/Or.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/Plus.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/Positive.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/ShiftLeft.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/ShiftRight.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/Terminal.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/Times.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/UnaryExpr.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/Xor.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/ConstGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/DefaultSymtabFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/EnumEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/EnumGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/ExceptionEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/ExceptionGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/Factories.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/ForwardEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/ForwardGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/ForwardValueEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/ForwardValueGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/Generator.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/GenFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/GenFileStream.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/IDLID.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/IncludeEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/IncludeGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/InterfaceEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/InterfaceGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/InterfaceState.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/InterfaceType.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/InvalidArgument.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/InvalidCharacter.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/MethodEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/MethodGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/ModuleEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/ModuleGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/NativeEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/NativeGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/Noop.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/NoPragma.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/ParameterEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/ParameterGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/ParseException.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/Parser.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/PragmaEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/PragmaGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/PragmaHandler.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/Preprocessor.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/PrimitiveEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/PrimitiveGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/RepositoryID.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/ResourceBundleUtil.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/Scanner.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/SequenceEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/SequenceGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/som/cff/FileLocator.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/som/cff/Messages.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/som/idlemit/MetaPragma.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/StringEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/StringGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/StructEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/StructGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/SymtabEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/SymtabFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Arguments.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/AttributeGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/AttributeGen24.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/AuxGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Compile.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/ConstGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/DefaultFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/EnumGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/ExceptionGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Factories.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/ForwardValueGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/GenFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Helper.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Helper24.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Holder.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/InterfaceGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/JavaGenerator.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/MethodGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/MethodGen24.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/MethodGenClone24.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/ModuleGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/NameModifier.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/NameModifierImpl.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/NativeGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/PrimitiveGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/SequenceGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Skeleton.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/StringGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/StructGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Stub.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/TCOffsets.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/TypedefGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/UnionGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Util.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/ValueBoxGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/ValueBoxGen24.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/ValueFactory.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/ValueGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/ValueGen24.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/Token.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/TokenBuffer.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/TypedefEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/TypedefGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/UnionBranch.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/UnionEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/UnionGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/Util.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/ValueBoxEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/ValueBoxGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/ValueEntry.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/ValueGen.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/ValueRepositoryId.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/logutil/IndentingPrintWriter.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/logutil/Input.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/logutil/InputCode.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/logutil/InputException.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/logutil/MC.java +@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/logutil/StringUtil.java +@OPENJDK@/corba/src/share/classes/javax/activity/ActivityCompletedException.java +@OPENJDK@/corba/src/share/classes/javax/activity/ActivityRequiredException.java +@OPENJDK@/corba/src/share/classes/javax/activity/InvalidActivityException.java +@OPENJDK@/corba/src/share/classes/javax/rmi/CORBA/ClassDesc.java +@OPENJDK@/corba/src/share/classes/javax/rmi/CORBA/GetORBPropertiesFileAction.java +@OPENJDK@/corba/src/share/classes/javax/rmi/CORBA/PortableRemoteObjectDelegate.java +@OPENJDK@/corba/src/share/classes/javax/rmi/CORBA/Stub.java +@OPENJDK@/corba/src/share/classes/javax/rmi/CORBA/StubDelegate.java +@OPENJDK@/corba/src/share/classes/javax/rmi/CORBA/Tie.java +@OPENJDK@/corba/src/share/classes/javax/rmi/CORBA/Util.java +@OPENJDK@/corba/src/share/classes/javax/rmi/CORBA/UtilDelegate.java +@OPENJDK@/corba/src/share/classes/javax/rmi/CORBA/ValueHandler.java +@OPENJDK@/corba/src/share/classes/javax/rmi/CORBA/ValueHandlerMultiFormat.java +@OPENJDK@/corba/src/share/classes/javax/rmi/PortableRemoteObject.java +@OPENJDK@/corba/src/share/classes/javax/transaction/InvalidTransactionException.java +@OPENJDK@/corba/src/share/classes/javax/transaction/TransactionRequiredException.java +@OPENJDK@/corba/src/share/classes/javax/transaction/TransactionRolledbackException.java +@OPENJDK@/corba/src/share/classes/javax/transaction/xa/XAException.java +@OPENJDK@/corba/src/share/classes/javax/transaction/xa/XAResource.java +@OPENJDK@/corba/src/share/classes/javax/transaction/xa/Xid.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/_IDLTypeStub.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/_PolicyStub.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ACTIVITY_COMPLETED.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ACTIVITY_REQUIRED.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/Any.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/AnyHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/AnySeqHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/AnySeqHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ARG_IN.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ARG_INOUT.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ARG_OUT.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/BAD_CONTEXT.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/BAD_INV_ORDER.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/BAD_OPERATION.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/BAD_PARAM.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/BAD_POLICY.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/BAD_POLICY_TYPE.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/BAD_POLICY_VALUE.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/BAD_QOS.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/BAD_TYPECODE.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/BooleanHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/BooleanSeqHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/BooleanSeqHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/Bounds.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ByteHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/CharHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/CharSeqHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/CharSeqHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/CODESET_INCOMPATIBLE.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/COMM_FAILURE.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/CompletionStatus.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/CompletionStatusHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/Context.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ContextList.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/CTX_RESTRICT_SCOPE.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/Current.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/CurrentHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/CurrentHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/CurrentOperations.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/CustomMarshal.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DATA_CONVERSION.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DataInputStream.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DataOutputStream.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DefinitionKind.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DefinitionKindHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DomainManager.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DomainManagerOperations.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DoubleHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DoubleSeqHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DoubleSeqHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DynamicImplementation.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DynAny.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DynAnyPackage/Invalid.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DynAnyPackage/InvalidSeq.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DynAnyPackage/InvalidValue.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DynAnyPackage/TypeMismatch.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DynArray.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DynEnum.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DynFixed.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DynSequence.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DynStruct.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DynUnion.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/DynValue.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/Environment.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ExceptionList.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/FieldNameHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/FixedHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/FloatHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/FloatSeqHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/FloatSeqHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/FREE_MEM.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/IdentifierHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/IDLType.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/IDLTypeHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/IDLTypeOperations.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/IMP_LIMIT.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/INITIALIZE.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/INTERNAL.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/INTF_REPOS.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/IntHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/INV_FLAG.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/INV_IDENT.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/INV_OBJREF.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/INV_POLICY.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/INVALID_ACTIVITY.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/INVALID_TRANSACTION.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/IRObject.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/IRObjectOperations.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/LocalObject.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/LongHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/LongLongSeqHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/LongLongSeqHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/LongSeqHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/LongSeqHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/MARSHAL.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/NamedValue.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/NameValuePair.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/NameValuePairHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/NO_IMPLEMENT.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/NO_MEMORY.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/NO_PERMISSION.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/NO_RESOURCES.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/NO_RESPONSE.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/NVList.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/OBJ_ADAPTER.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/Object.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/OBJECT_NOT_EXIST.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ObjectHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ObjectHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/OctetSeqHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/OctetSeqHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/OMGVMCID.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ORB.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ORBPackage/InconsistentTypeCode.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ORBPackage/InvalidName.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/PERSIST_STORE.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/Policy.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/PolicyError.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/PolicyHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/PolicyHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/PolicyListHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/PolicyListHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/PolicyOperations.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/PolicyTypeHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/portable/ApplicationException.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/portable/BoxedValueHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/portable/CustomValue.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/portable/Delegate.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/portable/IDLEntity.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/portable/IndirectionException.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/portable/InputStream.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/portable/InvokeHandler.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/portable/ObjectImpl.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/portable/OutputStream.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/portable/RemarshalException.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/portable/ResponseHandler.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/portable/ServantObject.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/portable/Streamable.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/portable/StreamableValue.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/portable/UnknownException.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/portable/ValueBase.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/portable/ValueFactory.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/portable/ValueInputStream.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/portable/ValueOutputStream.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/Principal.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/PrincipalHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/PRIVATE_MEMBER.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/PUBLIC_MEMBER.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/REBIND.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/RepositoryIdHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/Request.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ServerRequest.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ServiceDetail.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ServiceDetailHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ServiceInformation.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ServiceInformationHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ServiceInformationHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/SetOverrideType.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/SetOverrideTypeHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ShortHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ShortSeqHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ShortSeqHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/StringHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/StringValueHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/StructMember.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/StructMemberHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/SystemException.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/TCKind.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/TIMEOUT.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/TRANSACTION_MODE.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/TRANSACTION_REQUIRED.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/TRANSACTION_ROLLEDBACK.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/TRANSACTION_UNAVAILABLE.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/TRANSIENT.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/TypeCode.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/TypeCodeHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/TypeCodePackage/BadKind.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/TypeCodePackage/Bounds.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ULongLongSeqHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ULongLongSeqHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ULongSeqHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ULongSeqHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/UnionMember.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/UnionMemberHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/UNKNOWN.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/UnknownUserException.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/UnknownUserExceptionHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/UnknownUserExceptionHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/UNSUPPORTED_POLICY.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/UNSUPPORTED_POLICY_VALUE.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/UserException.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/UShortSeqHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/UShortSeqHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ValueBaseHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ValueBaseHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ValueMember.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/ValueMemberHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/VersionSpecHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/VisibilityHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/VM_ABSTRACT.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/VM_CUSTOM.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/VM_NONE.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/VM_TRUNCATABLE.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/WCharSeqHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/WCharSeqHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/WrongTransaction.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/WrongTransactionHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/WrongTransactionHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA/WStringValueHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA_2_3/ORB.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA_2_3/portable/Delegate.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA_2_3/portable/InputStream.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA_2_3/portable/ObjectImpl.java +@OPENJDK@/corba/src/share/classes/org/omg/CORBA_2_3/portable/OutputStream.java +@OPENJDK@/corba/src/share/classes/org/omg/CosNaming/_BindingIteratorImplBase.java +@OPENJDK@/corba/src/share/classes/org/omg/CosNaming/_NamingContextImplBase.java +@OPENJDK@/corba/src/share/classes/org/omg/PortableServer/CurrentHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/PortableServer/DynamicImplementation.java +@OPENJDK@/corba/src/share/classes/org/omg/PortableServer/POAHelper.java +@OPENJDK@/corba/src/share/classes/org/omg/PortableServer/portable/Delegate.java +@OPENJDK@/corba/src/share/classes/org/omg/PortableServer/Servant.java +@OPENJDK@/corba/src/share/classes/org/omg/PortableServer/ServantLocatorPackage/CookieHolder.java +@OPENJDK@/corba/src/share/classes/org/omg/SendingContext/RunTime.java +@OPENJDK@/corba/src/share/classes/org/omg/SendingContext/RunTimeOperations.java +@OPENJDK@/corba/src/share/classes/org/omg/stub/java/rmi/_Remote_Stub.java +@OPENJDK@/corba/src/share/classes/sun/corba/Bridge.java +@OPENJDK@/corba/src/share/classes/sun/corba/BridgePermission.java +@OPENJDK@/corba/src/share/classes/sun/corba/EncapsInputStreamFactory.java +@OPENJDK@/corba/src/share/classes/sun/corba/JavaCorbaAccess.java +@OPENJDK@/corba/src/share/classes/sun/corba/OutputStreamFactory.java +@OPENJDK@/corba/src/share/classes/sun/corba/SharedSecrets.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/AbstractType.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/ArrayType.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/BatchEnvironment.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/ClassPathLoader.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/ClassType.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/CompoundType.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/Constants.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/ContextElement.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/ContextStack.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/DirectoryLoader.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/Generator.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/IDLGenerator.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/IDLNames.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/ImplementationType.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/InterfaceType.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/NameContext.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/NCClassType.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/NCInterfaceType.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/PrimitiveType.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/PrintGenerator.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/RemoteType.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/SpecialClassType.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/SpecialInterfaceType.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/StaticStringsHash.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/StubGenerator.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/Type.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/Util.java +@OPENJDK@/corba/src/share/classes/sun/rmi/rmic/iiop/ValueType.java +@OPENJDK@/jaxp/src/com/sun/java_cup/internal/runtime/lr_parser.java +@OPENJDK@/jaxp/src/com/sun/java_cup/internal/runtime/Scanner.java +@OPENJDK@/jaxp/src/com/sun/java_cup/internal/runtime/Symbol.java +@OPENJDK@/jaxp/src/com/sun/java_cup/internal/runtime/virtual_parse_stack.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/AccessFlags.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Attribute.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/AttributeReader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/ClassFormatException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/ClassParser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Code.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/CodeException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Constant.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/ConstantClass.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/ConstantCP.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/ConstantFieldref.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/ConstantInteger.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/ConstantInterfaceMethodref.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/ConstantLong.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/ConstantMethodref.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/ConstantNameAndType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/ConstantObject.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/ConstantString.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/ConstantUtf8.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/ConstantValue.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Deprecated.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/ExceptionTable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Field.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/FieldOrMethod.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/InnerClass.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/InnerClasses.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/JavaClass.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/LineNumber.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/LineNumberTable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/LocalVariable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/LocalVariableTable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Method.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Node.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/PMGClass.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Signature.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/SourceFile.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/StackMap.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/StackMapEntry.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/StackMapType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Synthetic.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Unknown.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Utility.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Visitor.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/Constants.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/ExceptionConstants.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/AALOAD.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/AASTORE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ACONST_NULL.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/AllocationInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ALOAD.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ANEWARRAY.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ARETURN.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ArithmeticInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ArrayInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ARRAYLENGTH.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ArrayType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ASTORE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ATHROW.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/BALOAD.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/BasicType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/BASTORE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/BIPUSH.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/BranchHandle.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/BranchInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/BREAKPOINT.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/CALOAD.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/CASTORE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/CHECKCAST.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ClassGen.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ClassGenException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ClassObserver.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/CompoundInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ConstantPoolGen.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ConstantPushInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ConversionInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/CPInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/D2F.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/D2I.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/D2L.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/DADD.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/DALOAD.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/DASTORE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/DCMPG.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/DCMPL.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/DCONST.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/DDIV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/DLOAD.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/DMUL.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/DNEG.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/DREM.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/DRETURN.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/DSTORE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/DSUB.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/DUP.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/DUP_X1.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/DUP_X2.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/DUP2.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/DUP2_X1.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/DUP2_X2.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/EmptyVisitor.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ExceptionThrower.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/F2D.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/F2I.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/F2L.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/FADD.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/FALOAD.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/FASTORE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/FCMPG.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/FCMPL.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/FCONST.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/FDIV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/FieldGen.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/FieldGenOrMethodGen.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/FieldInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/FieldObserver.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/FieldOrMethod.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/FLOAD.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/FMUL.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/FNEG.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/FREM.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/FRETURN.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/FSTORE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/FSUB.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/GETFIELD.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/GETSTATIC.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/GOTO.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/GOTO_W.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/GotoInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/I2B.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/I2C.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/I2D.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/I2F.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/I2L.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/I2S.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IADD.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IALOAD.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IAND.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IASTORE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ICONST.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IDIV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IF_ACMPEQ.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IF_ACMPNE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IF_ICMPEQ.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IF_ICMPGE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IF_ICMPGT.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IF_ICMPLE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IF_ICMPLT.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IF_ICMPNE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IFEQ.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IFGE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IFGT.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IfInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IFLE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IFLT.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IFNE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IFNONNULL.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IFNULL.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IINC.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ILOAD.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IMPDEP1.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IMPDEP2.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IMUL.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IndexedInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/INEG.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/INSTANCEOF.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/Instruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/InstructionComparator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/InstructionConstants.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/InstructionList.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/InstructionListObserver.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/InstructionTargeter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/InvokeInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/INVOKEINTERFACE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/INVOKESPECIAL.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/INVOKESTATIC.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/INVOKEVIRTUAL.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IOR.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IREM.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IRETURN.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ISHL.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ISHR.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ISTORE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ISUB.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IUSHR.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/IXOR.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/JSR.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/JSR_W.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/JsrInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/L2D.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/L2F.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/L2I.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LADD.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LALOAD.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LAND.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LASTORE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LCMP.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LCONST.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LDC.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LDC_W.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LDC2_W.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LDIV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LLOAD.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LMUL.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LNEG.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LoadClass.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LoadInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LOOKUPSWITCH.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LOR.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LREM.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LRETURN.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LSHL.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LSHR.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LSTORE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LSUB.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LUSHR.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/LXOR.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/MethodGen.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/MethodObserver.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/MONITORENTER.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/MONITOREXIT.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/MULTIANEWARRAY.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/NamedAndTyped.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/NEW.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/NEWARRAY.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/NOP.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ObjectType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/POP.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/POP2.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/PopInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/PUSH.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/PushInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/PUTFIELD.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/PUTSTATIC.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ReferenceType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/RET.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/RETURN.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ReturnaddressType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/ReturnInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/SALOAD.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/SASTORE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/Select.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/SIPUSH.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/StackConsumer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/StackInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/StackProducer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/StoreInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/SWAP.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/SWITCH.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/TABLESWITCH.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/TargetLostException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/Type.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/TypedInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/UnconditionalBranch.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/VariableLengthInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/Visitor.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/Repository.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/AttributeHTML.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/BCELFactory.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/BCELifier.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/ByteSequence.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/Class2HTML.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/ClassLoader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/ClassLoaderRepository.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/ClassPath.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/ClassQueue.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/ClassSet.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/ClassStack.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/ClassVector.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/CodeHTML.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/ConstantHTML.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/InstructionFinder.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/JavaWrapper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/MethodHTML.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/Repository.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/SecuritySupport.java +@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/SyntheticRepository.java +@OPENJDK@/jaxp/src/com/sun/org/apache/regexp/internal/CharacterArrayCharacterIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/regexp/internal/CharacterIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/regexp/internal/RE.java +@OPENJDK@/jaxp/src/com/sun/org/apache/regexp/internal/ReaderCharacterIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/regexp/internal/recompile.java +@OPENJDK@/jaxp/src/com/sun/org/apache/regexp/internal/RECompiler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/regexp/internal/REDebugCompiler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/regexp/internal/REProgram.java +@OPENJDK@/jaxp/src/com/sun/org/apache/regexp/internal/RESyntaxException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/regexp/internal/RETest.java +@OPENJDK@/jaxp/src/com/sun/org/apache/regexp/internal/REUtil.java +@OPENJDK@/jaxp/src/com/sun/org/apache/regexp/internal/StreamCharacterIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/regexp/internal/StringCharacterIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/extensions/ExpressionContext.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/lib/ExsltBase.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/lib/ExsltCommon.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/lib/ExsltDatetime.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/lib/ExsltDynamic.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/lib/ExsltMath.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/lib/ExsltSets.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/lib/ExsltStrings.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/lib/Extensions.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/lib/NodeInfo.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/res/XSLMessages.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_de.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_en.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_es.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_fr.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_it.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_ja.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_ko.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_pt_BR.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_sv.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_zh_CN.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_zh_TW.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/templates/Constants.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/utils/ConfigurationError.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/utils/FactoryImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/utils/FeatureManager.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/utils/FeaturePropertyBase.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/utils/ObjectFactory.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/utils/SecuritySupport.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/utils/XMLSecurityManager.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/utils/XMLSecurityPropertyManager.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/Version.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/XalanConstants.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xslt/EnvironmentCheck.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xslt/Process.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/cmdline/Compile.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/cmdline/getopt/GetOpt.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/cmdline/getopt/GetOptsException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/cmdline/getopt/IllegalArgumentException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/cmdline/getopt/MissingOptArgException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/cmdline/Transform.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/CollatorFactory.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/AbsoluteLocationPath.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/AbsolutePathPattern.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/AlternativePattern.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/AncestorPattern.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/ApplyImports.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/ApplyTemplates.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/ArgumentList.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Attribute.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/AttributeSet.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/AttributeValue.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/AttributeValueTemplate.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/BinOpExpr.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/BooleanCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/BooleanExpr.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/CallTemplate.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/CastCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/CastExpr.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/CeilingCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Choose.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Closure.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Comment.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/CompilerException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/ConcatCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Constants.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/ContainsCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Copy.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/CopyOf.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/CurrentCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/DecimalFormatting.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/DocumentCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/ElementAvailableCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/EqualityExpr.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Expression.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Fallback.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/FilteredAbsoluteLocationPath.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/FilterExpr.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/FilterParentPath.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/FloorCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/FlowList.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/ForEach.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/FormatNumberCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/FunctionAvailableCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/FunctionCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/GenerateIdCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/IdKeyPattern.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/IdPattern.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/If.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/IllegalCharException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Import.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Include.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Instruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/IntExpr.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Key.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/KeyCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/KeyPattern.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/LangCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/LastCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/LiteralAttribute.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/LiteralElement.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/LiteralExpr.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/LocalNameCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/LocationPathPattern.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/LogicalExpr.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Message.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Mode.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/NameBase.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/NameCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/NamespaceAlias.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/NamespaceUriCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/NodeTest.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/NotCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Number.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/NumberCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Otherwise.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Output.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Param.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/ParameterRef.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/ParentLocationPath.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/ParentPattern.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Pattern.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/PositionCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Predicate.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/ProcessingInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/ProcessingInstructionPattern.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/QName.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/RealExpr.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/RelationalExpr.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/RelativeLocationPath.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/RelativePathPattern.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/RoundCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/SimpleAttributeValue.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Sort.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/SourceLoader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/StartsWithCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Step.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/StepPattern.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/StringCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/StringLengthCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Stylesheet.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/sym.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/SymbolTable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/SyntaxTreeNode.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Template.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/TestSeq.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Text.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/TopLevelElement.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/TransletOutput.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/UnaryOpExpr.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/UnionPathExpr.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/UnparsedEntityUriCall.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/UnresolvedRef.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/UnsupportedElement.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/UseAttributeSets.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/AttributeSetMethodGenerator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/BooleanType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ClassGenerator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/CompareGenerator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ca.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_cs.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_de.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_es.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_fr.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_it.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ja.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ko.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_pt_BR.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_sk.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_sv.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_zh_CN.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_zh_TW.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/FilterGenerator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/InternalError.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/IntType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/MarkerInstruction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/MatchGenerator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/MethodGenerator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/MethodType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/MultiHashtable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/NamedMethodGenerator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/NodeCounterGenerator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/NodeSetType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/NodeSortRecordFactGenerator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/NodeSortRecordGenerator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/NodeType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/NumberType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ObjectType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/OutlineableChunkEnd.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/OutlineableChunkStart.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/RealType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ReferenceType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ResultTreeType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/RtMethodGenerator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/SlotAllocator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/StringStack.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/StringType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/TestGenerator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/Type.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/TypeCheckError.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/Util.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/VoidType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/ValueOf.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Variable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/VariableBase.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/VariableRef.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/VariableRefBase.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/When.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Whitespace.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/WithParam.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XPathLexer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XPathParser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XslAttribute.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XslElement.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/DOM.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/AbsoluteIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/AdaptiveResultTreeImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/AnyNodeCounter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/ArrayNodeListIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/BitArray.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/CachedNodeListIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/ClonedNodeListIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/CollatorFactoryBase.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/CurrentNodeListFilter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/CurrentNodeListIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/DocumentCache.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/DOMAdapter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/DOMBuilder.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/DOMWSFilter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/DupFilterIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/EmptyFilter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/ExtendedSAX.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/Filter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/FilteredStepIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/FilterIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/ForwardPositionIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/KeyIndex.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/LoadDocument.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/MatchingIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/MultiDOM.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/MultipleNodeCounter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/MultiValuedNodeHeapIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/NodeCounter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/NodeIteratorBase.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/NodeSortRecord.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/NodeSortRecordFactory.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/NthIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/SAXImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/SimpleResultTreeImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/SingleNodeCounter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/SingletonIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/SortingIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/SortSettings.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/StepIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/StripWhitespaceFilter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/UnionIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/XSLTCDTMManager.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/DOMCache.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/DOMEnhancedForDTM.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/NodeIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/ProcessorVersion.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/AbstractTranslet.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/Attributes.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/Constants.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_ca.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_cs.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_de.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_es.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_fr.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_it.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_ja.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_ko.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_pt_BR.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_sk.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_sv.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_zh_CN.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_zh_TW.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/Hashtable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/InternalRuntimeError.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/MessageHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/Node.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/Operators.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/output/OutputBuffer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/output/StringOutputBuffer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/output/TransletOutputHandlerFactory.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/output/WriterOutputBuffer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/Parameter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/StringValueHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/StripFilter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/Translet.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/TransletException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/DOM2SAX.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/DOM2TO.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/OutputSettings.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/SAX2DOM.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/SAX2StAXBaseWriter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/SAX2StAXEventWriter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/SAX2StAXStreamWriter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/SmartTransformerFactoryImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/StAXEvent2SAX.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/StAXStream2SAX.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesHandlerImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerHandlerImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TrAXFilter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/Util.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/XSLTCSource.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/util/IntegerArray.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/AttributeMap.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/AttrImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/AttrNSImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/CDATASectionImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/CharacterDataImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/ChildNode.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/CommentImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/CoreDocumentImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/CoreDOMImplementationImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DeepNodeListImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DeferredAttrImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DeferredAttrNSImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DeferredCDATASectionImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DeferredCommentImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DeferredDocumentImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DeferredDocumentTypeImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DeferredDOMImplementationImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DeferredElementDefinitionImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DeferredElementImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DeferredElementNSImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DeferredEntityImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DeferredEntityReferenceImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DeferredNode.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DeferredNotationImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DeferredProcessingInstructionImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DeferredTextImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DocumentFragmentImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DocumentImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DocumentTypeImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DOMConfigurationImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DOMErrorImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DOMImplementationImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DOMImplementationListImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DOMImplementationSourceImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DOMInputImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DOMLocatorImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DOMMessageFormatter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DOMNormalizer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DOMOutputImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DOMStringListImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/DOMXSImplementationSourceImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/ElementDefinitionImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/ElementImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/ElementNSImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/EntityImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/EntityReferenceImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/events/EventImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/events/MutationEventImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/LCount.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/NamedNodeMapImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/NodeImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/NodeIteratorImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/NodeListCache.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/NotationImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/ParentNode.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/ProcessingInstructionImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/PSVIAttrNSImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/PSVIDocumentImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/PSVIDOMImplementationImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/PSVIElementNSImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/RangeExceptionImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/RangeImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/TextImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/TreeWalkerImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/Constants.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/BalancedDTDGrammar.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/DTDGrammar.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/DTDGrammarBucket.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/models/CMAny.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/models/CMBinOp.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/models/CMLeaf.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/models/CMNode.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/models/CMStateSet.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/models/CMUniOp.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/models/ContentModelValidator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/models/DFAContentModel.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/models/MixedContentModel.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/models/SimpleContentModel.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/XML11DTDProcessor.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/XML11DTDValidator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/XML11NSDTDValidator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/XMLAttributeDecl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/XMLContentSpec.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/XMLDTDDescription.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/XMLDTDLoader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/XMLDTDProcessor.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/XMLDTDValidator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/XMLDTDValidatorFilter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/XMLElementDecl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/XMLEntityDecl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/XMLNotationDecl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/XMLNSDTDValidator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/XMLSimpleType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/DatatypeException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/DatatypeValidator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/dtd/DTDDVFactoryImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/dtd/ENTITYDatatypeValidator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/dtd/IDDatatypeValidator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/dtd/IDREFDatatypeValidator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/dtd/ListDatatypeValidator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/dtd/NMTOKENDatatypeValidator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/dtd/NOTATIONDatatypeValidator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/dtd/StringDatatypeValidator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/dtd/XML11DTDDVFactoryImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/dtd/XML11IDDatatypeValidator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/dtd/XML11IDREFDatatypeValidator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/dtd/XML11NMTOKENDatatypeValidator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/DTDDVFactory.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/DVFactoryException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/InvalidDatatypeFacetException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/InvalidDatatypeValueException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/SchemaDVFactory.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/util/Base64.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/util/ByteListImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/util/HexBin.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/ValidatedInfo.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/ValidationContext.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/AbstractDateTimeDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/AnyAtomicDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/AnySimpleDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/AnyURIDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/Base64BinaryDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/BaseDVFactory.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/BaseSchemaDVFactory.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/BooleanDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/DateDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/DateTimeDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/DayDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/DayTimeDurationDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/DecimalDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/DoubleDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/DurationDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/EntityDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/ExtendedSchemaDVFactoryImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/FloatDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/FullDVFactory.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/HexBinaryDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/IDDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/IDREFDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/IntegerDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/ListDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/MonthDayDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/MonthDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/PrecisionDecimalDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/QNameDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/SchemaDateTimeException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/SchemaDVFactoryImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/StringDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/TimeDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/TypeValidator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/UnionDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/XSSimpleTypeDecl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/XSSimpleTypeDelegate.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/YearDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/YearMonthDurationDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/YearMonthDV.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/XSFacets.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/XSSimpleType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/ExternalSubsetResolver.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/io/ASCIIReader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/io/MalformedByteSequenceException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/io/UCSReader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/io/UTF8Reader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessageFormatter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessageFormatter_de.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessageFormatter_es.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessageFormatter_fr.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessageFormatter_it.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessageFormatter_ja.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessageFormatter_ko.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessageFormatter_pt_BR.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessageFormatter_sv.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessageFormatter_zh_CN.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessageFormatter_zh_TW.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/PropertyManager.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/RevalidationHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/validation/EntityState.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/validation/ValidationManager.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/validation/ValidationState.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/Version.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/XML11DocumentScannerImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/XML11NamespaceBinder.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/XML11NSDocumentScannerImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLEntityDescription.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLEntityHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLErrorReporter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLNamespaceBinder.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLScanner.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLStreamFilterImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLStreamReaderImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLVersionDetector.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xpath/regex/BMPattern.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xpath/regex/CaseInsensitiveMap.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xpath/regex/Match.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xpath/regex/Op.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xpath/regex/ParseException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xpath/regex/ParserForXMLSchema.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xpath/regex/RangeToken.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xpath/regex/RegexParser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xpath/regex/RegularExpression.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xpath/regex/REUtil.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xpath/regex/Token.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xpath/XPath.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xpath/XPathException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/AttributePSVImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/ElementPSVImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/identity/Field.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/identity/FieldActivator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/identity/IdentityConstraint.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/identity/KeyRef.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/identity/Selector.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/identity/UniqueOrKey.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/identity/ValueStore.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/identity/XPathMatcher.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/models/CMBuilder.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/models/CMNodeFactory.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/models/XSAllCM.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/models/XSCMBinOp.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/models/XSCMLeaf.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/models/XSCMRepeatingLeaf.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/models/XSCMUniOp.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/models/XSCMValidator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/models/XSDFACM.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/models/XSEmptyCM.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/opti/AttrImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/opti/DefaultDocument.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/opti/DefaultElement.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/opti/DefaultNode.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/opti/DefaultText.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/opti/DefaultXMLDocumentHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/opti/ElementImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/opti/NamedNodeMapImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/opti/NodeImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/opti/SchemaDOM.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/opti/SchemaDOMImplementation.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/opti/SchemaDOMParser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/opti/SchemaParsingConfig.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/opti/TextImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/SchemaGrammar.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/SchemaNamespaceSupport.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/SchemaSymbols.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/SubstitutionGroupHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/SchemaContentHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/StAXSchemaParser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSAnnotationInfo.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSAttributeChecker.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDAbstractIDConstraintTraverser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDAbstractParticleTraverser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDAbstractTraverser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDAttributeGroupTraverser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDAttributeTraverser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDComplexTypeTraverser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDElementTraverser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDGroupTraverser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDKeyrefTraverser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDNotationTraverser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDocumentInfo.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDSimpleTypeTraverser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDUniqueOrKeyTraverser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDWildcardTraverser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/util/LSInputListImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/util/ObjectListImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/util/ShortListImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/util/SimpleLocator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/util/StringListImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/util/XInt.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/util/XIntPool.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/util/XSGrammarPool.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/util/XSInputSource.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/util/XSNamedMap4Types.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/util/XSNamedMapImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/util/XSObjectListImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaLoader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaValidator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSAnnotationImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSAttributeDecl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSAttributeGroupDecl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSAttributeUseImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSComplexTypeDecl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSConstraints.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSDDescription.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSDeclarationPool.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSElementDecl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSGrammarBucket.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSGroupDecl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSImplementationImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSLoaderImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSMessageFormatter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSModelGroupImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSModelImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSNotationDecl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSParticleDecl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSWildcardDecl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/DatatypeFactoryImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/DurationDayTimeImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/DurationImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/DurationYearMonthImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/XMLGregorianCalendarImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/DefaultValidationErrorHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/JAXPConstants.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/JAXPValidatorComponent.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/SAXParserFactoryImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/SAXParserImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/SchemaValidatorConfiguration.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/TeeXMLDocumentFilterImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/UnparsedEntityHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/AbstractXMLSchema.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/DOMDocumentHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/DOMResultAugmentor.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/DOMResultBuilder.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/DOMValidatorHelper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/DraconianErrorHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/EmptyXMLSchema.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/ErrorHandlerAdaptor.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/JAXPValidationMessageFormatter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/ReadOnlyGrammarPool.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/SimpleXMLSchema.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/SoftReferenceGrammarPool.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/StAXValidatorHelper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/StreamValidatorHelper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/Util.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/ValidatorHandlerImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/ValidatorHelper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/ValidatorImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/WeakReferenceXMLSchema.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/WrappedSAXException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchema.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaValidatorComponentManager.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/XSGrammarPoolContainer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/AbstractDOMParser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/AbstractSAXParser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/AbstractXMLDocumentParser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/BasicParserConfiguration.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/CachingParserPool.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/DOMParser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/DOMParserImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/DTDConfiguration.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/DTDParser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/IntegratedParserConfiguration.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/NonValidatingConfiguration.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/SAXParser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/SecurityConfiguration.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/StandardParserConfiguration.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/XIncludeAwareParserConfiguration.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/XIncludeParserConfiguration.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/XML11Configurable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/XML11DTDConfiguration.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/XML11NonValidatingConfiguration.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/XMLDocumentParser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/XMLGrammarCachingConfiguration.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/XMLGrammarParser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/XMLGrammarPreparser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/XMLParser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/XPointerParserConfiguration.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/AttributesProxy.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/AugmentationsImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/DatatypeMessageFormatter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/DefaultErrorHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/DOMEntityResolverWrapper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/DOMErrorHandlerWrapper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/DOMInputSource.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/DOMUtil.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/DraconianErrorHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/EncodingMap.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/EntityResolver2Wrapper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/EntityResolverWrapper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/ErrorHandlerProxy.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/ErrorHandlerWrapper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/FeatureState.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/IntStack.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/JAXPNamespaceContextWrapper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/LocatorProxy.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/LocatorWrapper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/MessageFormatter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/NamespaceContextWrapper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/NamespaceSupport.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/ParserConfigurationSettings.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/PropertyState.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/SAX2XNI.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/SAXInputSource.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/SAXLocatorWrapper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/SAXMessageFormatter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/SecurityManager.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/ShadowedSymbolTable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/Status.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/StAXInputSource.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/StAXLocationWrapper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/SymbolHash.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/SymbolTable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/SynchronizedSymbolTable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/TeeXMLDocumentFilterImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/TypeInfoImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/URI.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/XML11Char.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/XMLAttributesImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/XMLAttributesIteratorImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/XMLCatalogResolver.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/XMLChar.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/XMLDocumentFilterImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/XMLEntityDescriptionImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/XMLErrorCode.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/XMLGrammarPoolImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/XMLInputSourceAdaptor.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/XMLResourceIdentifierImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/XMLStringBuffer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/XMLSymbols.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/utils/ConfigurationError.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/utils/ObjectFactory.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/utils/SecuritySupport.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/utils/XMLLimitAnalyzer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/utils/XMLSecurityManager.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/utils/XMLSecurityPropertyManager.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xinclude/MultipleScopeNamespaceSupport.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xinclude/SecuritySupport.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xinclude/XInclude11TextReader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xinclude/XIncludeHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xinclude/XIncludeMessageFormatter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xinclude/XIncludeNamespaceSupport.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xinclude/XIncludeTextReader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xinclude/XPointerElementHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xinclude/XPointerFramework.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xinclude/XPointerSchema.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/Augmentations.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/grammars/Grammar.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/grammars/XMLDTDDescription.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/grammars/XMLGrammarDescription.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/grammars/XMLGrammarLoader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/grammars/XMLGrammarPool.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/grammars/XMLSchemaDescription.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/grammars/XSGrammar.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/NamespaceContext.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/parser/XMLComponent.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/parser/XMLComponentManager.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/parser/XMLConfigurationException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/parser/XMLDocumentFilter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/parser/XMLDocumentScanner.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/parser/XMLDocumentSource.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/parser/XMLDTDContentModelFilter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/parser/XMLDTDContentModelSource.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/parser/XMLDTDFilter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/parser/XMLDTDScanner.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/parser/XMLDTDSource.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/parser/XMLEntityResolver.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/parser/XMLErrorHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/parser/XMLInputSource.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/parser/XMLParseException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/parser/XMLParserConfiguration.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/parser/XMLPullParserConfiguration.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/QName.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/XMLAttributes.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/XMLDocumentFragmentHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/XMLDocumentHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/XMLDTDContentModelHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/XMLDTDHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/XMLLocator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/XMLResourceIdentifier.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/XMLString.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/XNIException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/ElementSchemePointer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/ShortHandPointer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/XPointerErrorHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/XPointerHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/XPointerMessageFormatter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/XPointerPart.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/XPointerProcessor.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/AttributePSVI.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/datatypes/ByteList.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/datatypes/ObjectList.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/datatypes/XSDateTime.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/datatypes/XSDecimal.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/datatypes/XSDouble.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/datatypes/XSFloat.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/datatypes/XSQName.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/ElementPSVI.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/ItemPSVI.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/LSInputList.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/PSVIProvider.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/ShortList.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/StringList.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSAnnotation.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSAttributeDeclaration.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSAttributeGroupDefinition.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSAttributeUse.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSComplexTypeDefinition.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSConstants.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSElementDeclaration.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSFacet.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSIDCDefinition.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSImplementation.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSLoader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSModel.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSModelGroup.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSModelGroupDefinition.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSMultiValueFacet.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSNamedMap.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSNamespaceItem.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSNamespaceItemList.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSNotationDeclaration.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSObject.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSObjectList.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSParticle.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSSimpleTypeDefinition.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSTerm.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSTypeDefinition.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/XSWildcard.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/Axis.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/DTM.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/DTMAxisIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/DTMAxisTraverser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/DTMConfigurationException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/DTMDOMException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/DTMException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/DTMFilter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/DTMIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/DTMManager.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/DTMWSFilter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/ChunkedIntArray.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/CoroutineManager.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/CoroutineParser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/CustomStringPool.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/dom2dtm/DOM2DTM.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/dom2dtm/DOM2DTMdefaultNamespaceDeclarationNode.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMAxisIteratorBase.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMAxisIterNodeList.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMChildIterNodeList.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMDefaultBase.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMDefaultBaseIterators.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMDefaultBaseTraversers.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMDocumentImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMManagerDefault.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMNamedNodeMap.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMNodeIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMNodeList.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMNodeListBase.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMNodeProxy.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMSafeStringPool.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMStringPool.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMTreeWalker.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/EmptyIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/ExpandedNameTable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/ExtendedType.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/IncrementalSAXSource.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/IncrementalSAXSource_Filter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/IncrementalSAXSource_Xerces.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/NodeLocator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/sax2dtm/SAX2DTM.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/sax2dtm/SAX2DTM2.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/sax2dtm/SAX2RTFDTM.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/res/XMLErrorResources.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/res/XMLErrorResources_ca.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/res/XMLErrorResources_cs.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/res/XMLErrorResources_de.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/res/XMLErrorResources_en.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/res/XMLErrorResources_es.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/res/XMLErrorResources_fr.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/res/XMLErrorResources_it.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/res/XMLErrorResources_ja.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/res/XMLErrorResources_ko.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/res/XMLErrorResources_pt_BR.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/res/XMLErrorResources_sk.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/res/XMLErrorResources_sv.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/res/XMLErrorResources_tr.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/res/XMLErrorResources_zh_CN.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/res/XMLErrorResources_zh_HK.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/res/XMLErrorResources_zh_TW.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/res/XMLMessages.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/Catalog.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/CatalogEntry.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/CatalogException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/CatalogManager.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/helpers/BootstrapResolver.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/helpers/Debug.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/helpers/FileURL.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/helpers/Namespaces.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/helpers/PublicId.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/readers/CatalogReader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/readers/DOMCatalogParser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/readers/DOMCatalogReader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/readers/ExtendedXMLCatalogReader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/readers/OASISXMLCatalogReader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/readers/SAXCatalogParser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/readers/SAXCatalogReader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/readers/SAXParserHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/readers/TextCatalogReader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/readers/TR9401CatalogReader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/readers/XCatalogReader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/Resolver.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/tools/CatalogResolver.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/tools/ResolvingParser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/tools/ResolvingXMLFilter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/tools/ResolvingXMLReader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/BaseMarkupSerializer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/DOMSerializer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/DOMSerializerImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/ElementState.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/EncodingInfo.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/Encodings.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/HTMLdtd.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/HTMLSerializer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/IndentPrinter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/LineSeparator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/Method.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/OutputFormat.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/Printer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/SecuritySupport.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/Serializer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/SerializerFactory.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/SerializerFactoryImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/TextSerializer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/XHTMLSerializer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/XML11Serializer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/XMLSerializer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/AttributesImplSerializer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/CharInfo.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/DOMSerializer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/ElemContext.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/ElemDesc.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/EmptySerializer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/EncodingInfo.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/Encodings.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/ExtendedContentHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/ExtendedLexicalHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/Method.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/NamespaceMappings.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/OutputPropertiesFactory.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/OutputPropertyUtils.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/SerializationHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/Serializer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/SerializerBase.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/SerializerConstants.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/SerializerFactory.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/SerializerTrace.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/SerializerTraceWriter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/ToHTMLSAXHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/ToHTMLStream.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/ToSAXHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/ToStream.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/ToTextSAXHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/ToTextStream.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/ToUnknownStream.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/ToXMLSAXHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/ToXMLStream.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/TransformStateSetter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/TreeWalker.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/Utils.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/AttList.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/BoolStack.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/DOM2Helper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/Messages.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/MsgKey.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages_ca.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages_cs.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages_de.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages_en.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages_es.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages_fr.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages_it.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages_ja.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages_ko.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages_pt_BR.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages_sv.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages_zh_CN.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages_zh_TW.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/StringToIntTable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/SystemIDResolver.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/URI.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/Utils.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/WrappedRuntimeException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/Version.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/WriterChain.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/WriterToASCI.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/WriterToUTF8Buffered.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/XSLOutputAttributes.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/AttList.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/BoolStack.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/CharKey.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/Constants.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/DefaultErrorHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/DOM2Helper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/DOMBuilder.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/DOMHelper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/DOMOrder.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/ElemDesc.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/FastStringBuffer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/Hashtree2Node.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/IntStack.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/IntVector.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/ListingErrorHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/LocaleUtility.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/MutableAttrListImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/NameSpace.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/NamespaceSupport2.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/NodeConsumer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/NodeVector.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/NSInfo.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/ObjectPool.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/ObjectStack.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/ObjectVector.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/PrefixResolver.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/PrefixResolverDefault.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/QName.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/RawCharacterHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/res/CharArrayWrapper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/res/IntArrayWrapper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/res/LongArrayWrapper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/res/StringArrayWrapper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/res/XResourceBundle.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/res/XResourceBundleBase.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/res/XResources_de.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/res/XResources_en.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/res/XResources_es.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/res/XResources_fr.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/res/XResources_it.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/res/XResources_ja_JP_A.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/res/XResources_ja_JP_HA.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/res/XResources_ja_JP_HI.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/res/XResources_ja_JP_I.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/res/XResources_ko.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/res/XResources_sv.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/res/XResources_zh_CN.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/res/XResources_zh_TW.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/SAXSourceLocator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/SerializableLocatorImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/StopParseException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/StringBufferPool.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/StringComparable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/StringToIntTable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/StringToStringTable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/StringToStringTableVector.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/StringVector.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/StylesheetPIHandler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/SuballocatedByteVector.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/SuballocatedIntVector.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/SystemIDResolver.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/ThreadControllerWrapper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/TreeWalker.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/Trie.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/UnImplNode.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/URI.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/WrappedRuntimeException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/WrongParserException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/XML11Char.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/XMLChar.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/XMLCharacterRecognizer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/XMLString.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/XMLStringDefault.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/XMLStringFactory.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/XMLStringFactoryDefault.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/Arg.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/AttributeIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/AxesWalker.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/BasicTestIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/ChildIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/ChildTestIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/ContextNodeList.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/DescendantIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/FilterExprIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/FilterExprIteratorSimple.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/FilterExprWalker.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/HasPositionalPredChecker.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/IteratorPool.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/LocPathIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/MatchPatternIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/NodeSequence.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/OneStepIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/OneStepIteratorForward.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/PathComponent.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/PredicatedNodeTest.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/ReverseAxesWalker.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/RTFIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/SelfIteratorNoPredicate.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/SubContextList.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/UnionChildIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/UnionPathIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/WalkerFactory.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/WalkingIterator.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/WalkingIteratorSorted.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/CachedXPathAPI.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/compiler/Compiler.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/compiler/FuncLoader.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/compiler/FunctionTable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/compiler/Keywords.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/compiler/Lexer.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/compiler/OpCodes.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/compiler/OpMap.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/compiler/OpMapVector.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/compiler/PsuedoNames.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/compiler/XPathDumper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/compiler/XPathParser.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/domapi/XPathEvaluatorImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/domapi/XPathExpressionImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/domapi/XPathNamespaceImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/domapi/XPathNSResolverImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/domapi/XPathResultImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/domapi/XPathStylesheetDOM3Exception.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/Expression.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/ExpressionNode.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/ExpressionOwner.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/ExtensionsProvider.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/FoundIndex.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncBoolean.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncCeiling.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncConcat.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncContains.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncCount.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncCurrent.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncDoclocation.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncExtElementAvailable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncExtFunction.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncExtFunctionAvailable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncFalse.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncFloor.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncGenerateId.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncId.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncLang.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncLast.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncLocalPart.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncNamespace.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncNormalizeSpace.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncNot.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncNumber.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncPosition.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncQname.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncRound.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncStartsWith.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncString.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncStringLength.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncSubstring.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncSubstringAfter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncSubstringBefore.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncSum.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncSystemProperty.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/Function.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/Function2Args.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/Function3Args.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FunctionDef1Arg.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FunctionMultiArgs.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FunctionOneArg.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncTranslate.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncTrue.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/FuncUnparsedEntityURI.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/WrongNumberArgsException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/jaxp/JAXPExtensionsProvider.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/jaxp/JAXPPrefixResolver.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/jaxp/JAXPVariableStack.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/jaxp/XPathExpressionImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/NodeSet.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/NodeSetDTM.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/objects/DTMXRTreeFrag.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/objects/XBoolean.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/objects/XBooleanStatic.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/objects/XMLStringFactoryImpl.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/objects/XNodeSet.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/objects/XNodeSetForDOM.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/objects/XNull.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/objects/XNumber.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/objects/XObject.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/objects/XObjectFactory.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/objects/XRTreeFrag.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/objects/XRTreeFragSelectWrapper.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/objects/XString.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/objects/XStringForChars.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/objects/XStringForFSB.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/And.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/Bool.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/Div.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/Equals.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/Gt.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/Gte.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/Lt.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/Lte.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/Minus.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/Mod.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/Mult.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/Neg.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/NotEquals.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/Number.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/Operation.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/Or.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/Plus.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/Quo.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/String.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/UnaryOperation.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/Variable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/VariableSafeAbsRef.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/patterns/ContextMatchStepPattern.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/patterns/FunctionPattern.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/patterns/NodeTest.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/patterns/NodeTestFilter.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/patterns/StepPattern.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/patterns/UnionPattern.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/res/XPATHErrorResources.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_de.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_en.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_es.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_fr.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_it.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_ja.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_ko.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_pt_BR.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_sv.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_zh_CN.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_zh_TW.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/res/XPATHMessages.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/SourceTree.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/SourceTreeManager.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/VariableStack.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/WhitespaceStrippingElementMatcher.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/XPath.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/XPathAPI.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/XPathContext.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/XPathException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/XPathFactory.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/XPathProcessorException.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/XPathVisitable.java +@OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/XPathVisitor.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/dtd/DTDGrammarUtil.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/dtd/nonvalidating/DTDGrammar.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/dtd/nonvalidating/XMLAttributeDecl.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/dtd/nonvalidating/XMLElementDecl.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/dtd/nonvalidating/XMLNotationDecl.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/dtd/nonvalidating/XMLSimpleType.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/Entity.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/EventFilterSupport.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/events/AttributeImpl.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/events/CharacterEvent.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/events/CommentEvent.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/events/DTDEvent.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/events/DummyEvent.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/events/EndDocumentEvent.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/events/EndElementEvent.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/events/EntityDeclarationImpl.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/events/EntityReferenceEvent.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/events/LocationImpl.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/events/NamedEvent.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/events/NamespaceImpl.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/events/NotationDeclarationImpl.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/events/ProcessingInstructionEvent.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/events/StartDocumentEvent.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/events/StartElementEvent.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/events/XMLEventAllocatorImpl.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/events/XMLEventFactoryImpl.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/StaxEntityResolverWrapper.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/StaxErrorReporter.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/StaxXMLInputSource.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/util/BufferAllocator.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/util/ReadOnlyIterator.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/util/ThreadLocalBufferAllocator.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/writers/UTF8OutputStreamWriter.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/writers/WriterUtility.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/writers/XMLDOMWriterImpl.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/writers/XMLEventWriterImpl.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/writers/XMLOutputSource.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/writers/XMLStreamWriterImpl.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/writers/XMLWriter.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/XMLBufferListener.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/XMLEntityReader.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/XMLEntityStorage.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/XMLEventReaderImpl.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/XMLInputFactoryImpl.java +@OPENJDK@/jaxp/src/com/sun/xml/internal/stream/XMLOutputFactoryImpl.java +@OPENJDK@/jaxp/src/javax/xml/datatype/DatatypeConfigurationException.java +@OPENJDK@/jaxp/src/javax/xml/datatype/DatatypeConstants.java +@OPENJDK@/jaxp/src/javax/xml/datatype/DatatypeFactory.java +@OPENJDK@/jaxp/src/javax/xml/datatype/Duration.java +@OPENJDK@/jaxp/src/javax/xml/datatype/FactoryFinder.java +@OPENJDK@/jaxp/src/javax/xml/datatype/SecuritySupport.java +@OPENJDK@/jaxp/src/javax/xml/datatype/XMLGregorianCalendar.java +@OPENJDK@/jaxp/src/javax/xml/namespace/NamespaceContext.java +@OPENJDK@/jaxp/src/javax/xml/namespace/QName.java +@OPENJDK@/jaxp/src/javax/xml/parsers/DocumentBuilder.java +@OPENJDK@/jaxp/src/javax/xml/parsers/DocumentBuilderFactory.java +@OPENJDK@/jaxp/src/javax/xml/parsers/FactoryConfigurationError.java +@OPENJDK@/jaxp/src/javax/xml/parsers/FactoryFinder.java +@OPENJDK@/jaxp/src/javax/xml/parsers/ParserConfigurationException.java +@OPENJDK@/jaxp/src/javax/xml/parsers/SAXParser.java +@OPENJDK@/jaxp/src/javax/xml/parsers/SAXParserFactory.java +@OPENJDK@/jaxp/src/javax/xml/parsers/SecuritySupport.java +@OPENJDK@/jaxp/src/javax/xml/stream/EventFilter.java +@OPENJDK@/jaxp/src/javax/xml/stream/events/Attribute.java +@OPENJDK@/jaxp/src/javax/xml/stream/events/Characters.java +@OPENJDK@/jaxp/src/javax/xml/stream/events/Comment.java +@OPENJDK@/jaxp/src/javax/xml/stream/events/DTD.java +@OPENJDK@/jaxp/src/javax/xml/stream/events/EndDocument.java +@OPENJDK@/jaxp/src/javax/xml/stream/events/EndElement.java +@OPENJDK@/jaxp/src/javax/xml/stream/events/EntityDeclaration.java +@OPENJDK@/jaxp/src/javax/xml/stream/events/EntityReference.java +@OPENJDK@/jaxp/src/javax/xml/stream/events/Namespace.java +@OPENJDK@/jaxp/src/javax/xml/stream/events/NotationDeclaration.java +@OPENJDK@/jaxp/src/javax/xml/stream/events/ProcessingInstruction.java +@OPENJDK@/jaxp/src/javax/xml/stream/events/StartDocument.java +@OPENJDK@/jaxp/src/javax/xml/stream/events/StartElement.java +@OPENJDK@/jaxp/src/javax/xml/stream/events/XMLEvent.java +@OPENJDK@/jaxp/src/javax/xml/stream/FactoryConfigurationError.java +@OPENJDK@/jaxp/src/javax/xml/stream/FactoryFinder.java +@OPENJDK@/jaxp/src/javax/xml/stream/Location.java +@OPENJDK@/jaxp/src/javax/xml/stream/SecuritySupport.java +@OPENJDK@/jaxp/src/javax/xml/stream/StreamFilter.java +@OPENJDK@/jaxp/src/javax/xml/stream/util/EventReaderDelegate.java +@OPENJDK@/jaxp/src/javax/xml/stream/util/StreamReaderDelegate.java +@OPENJDK@/jaxp/src/javax/xml/stream/util/XMLEventAllocator.java +@OPENJDK@/jaxp/src/javax/xml/stream/util/XMLEventConsumer.java +@OPENJDK@/jaxp/src/javax/xml/stream/XMLEventFactory.java +@OPENJDK@/jaxp/src/javax/xml/stream/XMLEventReader.java +@OPENJDK@/jaxp/src/javax/xml/stream/XMLEventWriter.java +@OPENJDK@/jaxp/src/javax/xml/stream/XMLInputFactory.java +@OPENJDK@/jaxp/src/javax/xml/stream/XMLOutputFactory.java +@OPENJDK@/jaxp/src/javax/xml/stream/XMLReporter.java +@OPENJDK@/jaxp/src/javax/xml/stream/XMLResolver.java +@OPENJDK@/jaxp/src/javax/xml/stream/XMLStreamConstants.java +@OPENJDK@/jaxp/src/javax/xml/stream/XMLStreamException.java +@OPENJDK@/jaxp/src/javax/xml/stream/XMLStreamReader.java +@OPENJDK@/jaxp/src/javax/xml/stream/XMLStreamWriter.java +@OPENJDK@/jaxp/src/javax/xml/transform/dom/DOMLocator.java +@OPENJDK@/jaxp/src/javax/xml/transform/dom/DOMResult.java +@OPENJDK@/jaxp/src/javax/xml/transform/dom/DOMSource.java +@OPENJDK@/jaxp/src/javax/xml/transform/ErrorListener.java +@OPENJDK@/jaxp/src/javax/xml/transform/FactoryFinder.java +@OPENJDK@/jaxp/src/javax/xml/transform/OutputKeys.java +@OPENJDK@/jaxp/src/javax/xml/transform/Result.java +@OPENJDK@/jaxp/src/javax/xml/transform/sax/SAXResult.java +@OPENJDK@/jaxp/src/javax/xml/transform/sax/SAXSource.java +@OPENJDK@/jaxp/src/javax/xml/transform/sax/SAXTransformerFactory.java +@OPENJDK@/jaxp/src/javax/xml/transform/sax/TemplatesHandler.java +@OPENJDK@/jaxp/src/javax/xml/transform/sax/TransformerHandler.java +@OPENJDK@/jaxp/src/javax/xml/transform/SecuritySupport.java +@OPENJDK@/jaxp/src/javax/xml/transform/Source.java +@OPENJDK@/jaxp/src/javax/xml/transform/SourceLocator.java +@OPENJDK@/jaxp/src/javax/xml/transform/stax/StAXResult.java +@OPENJDK@/jaxp/src/javax/xml/transform/stax/StAXSource.java +@OPENJDK@/jaxp/src/javax/xml/transform/stream/StreamResult.java +@OPENJDK@/jaxp/src/javax/xml/transform/stream/StreamSource.java +@OPENJDK@/jaxp/src/javax/xml/transform/Templates.java +@OPENJDK@/jaxp/src/javax/xml/transform/Transformer.java +@OPENJDK@/jaxp/src/javax/xml/transform/TransformerConfigurationException.java +@OPENJDK@/jaxp/src/javax/xml/transform/TransformerException.java +@OPENJDK@/jaxp/src/javax/xml/transform/TransformerFactory.java +@OPENJDK@/jaxp/src/javax/xml/transform/TransformerFactoryConfigurationError.java +@OPENJDK@/jaxp/src/javax/xml/transform/URIResolver.java +@OPENJDK@/jaxp/src/javax/xml/validation/Schema.java +@OPENJDK@/jaxp/src/javax/xml/validation/SchemaFactory.java +@OPENJDK@/jaxp/src/javax/xml/validation/SchemaFactoryConfigurationError.java +@OPENJDK@/jaxp/src/javax/xml/validation/SchemaFactoryFinder.java +@OPENJDK@/jaxp/src/javax/xml/validation/SchemaFactoryLoader.java +@OPENJDK@/jaxp/src/javax/xml/validation/SecuritySupport.java +@OPENJDK@/jaxp/src/javax/xml/validation/TypeInfoProvider.java +@OPENJDK@/jaxp/src/javax/xml/validation/Validator.java +@OPENJDK@/jaxp/src/javax/xml/validation/ValidatorHandler.java +@OPENJDK@/jaxp/src/javax/xml/XMLConstants.java +@OPENJDK@/jaxp/src/javax/xml/xpath/SecuritySupport.java +@OPENJDK@/jaxp/src/javax/xml/xpath/XPath.java +@OPENJDK@/jaxp/src/javax/xml/xpath/XPathConstants.java +@OPENJDK@/jaxp/src/javax/xml/xpath/XPathException.java +@OPENJDK@/jaxp/src/javax/xml/xpath/XPathExpression.java +@OPENJDK@/jaxp/src/javax/xml/xpath/XPathExpressionException.java +@OPENJDK@/jaxp/src/javax/xml/xpath/XPathFactory.java +@OPENJDK@/jaxp/src/javax/xml/xpath/XPathFactoryConfigurationException.java +@OPENJDK@/jaxp/src/javax/xml/xpath/XPathFactoryFinder.java +@OPENJDK@/jaxp/src/javax/xml/xpath/XPathFunction.java +@OPENJDK@/jaxp/src/javax/xml/xpath/XPathFunctionException.java +@OPENJDK@/jaxp/src/javax/xml/xpath/XPathFunctionResolver.java +@OPENJDK@/jaxp/src/javax/xml/xpath/XPathVariableResolver.java +@OPENJDK@/jaxp/src/org/w3c/dom/Attr.java +@OPENJDK@/jaxp/src/org/w3c/dom/bootstrap/DOMImplementationRegistry.java +@OPENJDK@/jaxp/src/org/w3c/dom/CDATASection.java +@OPENJDK@/jaxp/src/org/w3c/dom/CharacterData.java +@OPENJDK@/jaxp/src/org/w3c/dom/Comment.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/Counter.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/CSS2Properties.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/CSSCharsetRule.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/CSSFontFaceRule.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/CSSImportRule.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/CSSMediaRule.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/CSSPageRule.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/CSSPrimitiveValue.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/CSSRule.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/CSSRuleList.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/CSSStyleDeclaration.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/CSSStyleRule.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/CSSStyleSheet.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/CSSUnknownRule.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/CSSValue.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/CSSValueList.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/DocumentCSS.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/DOMImplementationCSS.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/ElementCSSInlineStyle.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/Rect.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/RGBColor.java +@OPENJDK@/jaxp/src/org/w3c/dom/css/ViewCSS.java +@OPENJDK@/jaxp/src/org/w3c/dom/Document.java +@OPENJDK@/jaxp/src/org/w3c/dom/DocumentFragment.java +@OPENJDK@/jaxp/src/org/w3c/dom/DocumentType.java +@OPENJDK@/jaxp/src/org/w3c/dom/DOMConfiguration.java +@OPENJDK@/jaxp/src/org/w3c/dom/DOMError.java +@OPENJDK@/jaxp/src/org/w3c/dom/DOMErrorHandler.java +@OPENJDK@/jaxp/src/org/w3c/dom/DOMException.java +@OPENJDK@/jaxp/src/org/w3c/dom/DOMImplementation.java +@OPENJDK@/jaxp/src/org/w3c/dom/DOMImplementationList.java +@OPENJDK@/jaxp/src/org/w3c/dom/DOMImplementationSource.java +@OPENJDK@/jaxp/src/org/w3c/dom/DOMLocator.java +@OPENJDK@/jaxp/src/org/w3c/dom/DOMStringList.java +@OPENJDK@/jaxp/src/org/w3c/dom/Element.java +@OPENJDK@/jaxp/src/org/w3c/dom/Entity.java +@OPENJDK@/jaxp/src/org/w3c/dom/EntityReference.java +@OPENJDK@/jaxp/src/org/w3c/dom/events/DocumentEvent.java +@OPENJDK@/jaxp/src/org/w3c/dom/events/Event.java +@OPENJDK@/jaxp/src/org/w3c/dom/events/EventException.java +@OPENJDK@/jaxp/src/org/w3c/dom/events/EventListener.java +@OPENJDK@/jaxp/src/org/w3c/dom/events/EventTarget.java +@OPENJDK@/jaxp/src/org/w3c/dom/events/MouseEvent.java +@OPENJDK@/jaxp/src/org/w3c/dom/events/MutationEvent.java +@OPENJDK@/jaxp/src/org/w3c/dom/events/UIEvent.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLAnchorElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLAppletElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLAreaElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLBaseElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLBaseFontElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLBodyElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLBRElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLButtonElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLCollection.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLDirectoryElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLDivElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLDListElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLDocument.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLDOMImplementation.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLFieldSetElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLFontElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLFormElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLFrameElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLFrameSetElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLHeadElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLHeadingElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLHRElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLHtmlElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLIFrameElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLImageElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLInputElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLIsIndexElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLLabelElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLLegendElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLLIElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLLinkElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLMapElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLMenuElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLMetaElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLModElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLObjectElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLOListElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLOptGroupElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLOptionElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLParagraphElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLParamElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLPreElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLQuoteElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLScriptElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLSelectElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLStyleElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLTableCaptionElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLTableCellElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLTableColElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLTableElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLTableRowElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLTableSectionElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLTextAreaElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLTitleElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/html/HTMLUListElement.java +@OPENJDK@/jaxp/src/org/w3c/dom/ls/DOMImplementationLS.java +@OPENJDK@/jaxp/src/org/w3c/dom/ls/LSException.java +@OPENJDK@/jaxp/src/org/w3c/dom/ls/LSInput.java +@OPENJDK@/jaxp/src/org/w3c/dom/ls/LSLoadEvent.java +@OPENJDK@/jaxp/src/org/w3c/dom/ls/LSOutput.java +@OPENJDK@/jaxp/src/org/w3c/dom/ls/LSParser.java +@OPENJDK@/jaxp/src/org/w3c/dom/ls/LSParserFilter.java +@OPENJDK@/jaxp/src/org/w3c/dom/ls/LSProgressEvent.java +@OPENJDK@/jaxp/src/org/w3c/dom/ls/LSResourceResolver.java +@OPENJDK@/jaxp/src/org/w3c/dom/ls/LSSerializer.java +@OPENJDK@/jaxp/src/org/w3c/dom/ls/LSSerializerFilter.java +@OPENJDK@/jaxp/src/org/w3c/dom/NamedNodeMap.java +@OPENJDK@/jaxp/src/org/w3c/dom/NameList.java +@OPENJDK@/jaxp/src/org/w3c/dom/Node.java +@OPENJDK@/jaxp/src/org/w3c/dom/NodeList.java +@OPENJDK@/jaxp/src/org/w3c/dom/Notation.java +@OPENJDK@/jaxp/src/org/w3c/dom/ProcessingInstruction.java +@OPENJDK@/jaxp/src/org/w3c/dom/ranges/DocumentRange.java +@OPENJDK@/jaxp/src/org/w3c/dom/ranges/Range.java +@OPENJDK@/jaxp/src/org/w3c/dom/ranges/RangeException.java +@OPENJDK@/jaxp/src/org/w3c/dom/stylesheets/DocumentStyle.java +@OPENJDK@/jaxp/src/org/w3c/dom/stylesheets/LinkStyle.java +@OPENJDK@/jaxp/src/org/w3c/dom/stylesheets/MediaList.java +@OPENJDK@/jaxp/src/org/w3c/dom/stylesheets/StyleSheet.java +@OPENJDK@/jaxp/src/org/w3c/dom/stylesheets/StyleSheetList.java +@OPENJDK@/jaxp/src/org/w3c/dom/Text.java +@OPENJDK@/jaxp/src/org/w3c/dom/traversal/DocumentTraversal.java +@OPENJDK@/jaxp/src/org/w3c/dom/traversal/NodeFilter.java +@OPENJDK@/jaxp/src/org/w3c/dom/traversal/NodeIterator.java +@OPENJDK@/jaxp/src/org/w3c/dom/traversal/TreeWalker.java +@OPENJDK@/jaxp/src/org/w3c/dom/TypeInfo.java +@OPENJDK@/jaxp/src/org/w3c/dom/UserDataHandler.java +@OPENJDK@/jaxp/src/org/w3c/dom/views/AbstractView.java +@OPENJDK@/jaxp/src/org/w3c/dom/views/DocumentView.java +@OPENJDK@/jaxp/src/org/w3c/dom/xpath/XPathEvaluator.java +@OPENJDK@/jaxp/src/org/w3c/dom/xpath/XPathException.java +@OPENJDK@/jaxp/src/org/w3c/dom/xpath/XPathExpression.java +@OPENJDK@/jaxp/src/org/w3c/dom/xpath/XPathNamespace.java +@OPENJDK@/jaxp/src/org/w3c/dom/xpath/XPathNSResolver.java +@OPENJDK@/jaxp/src/org/w3c/dom/xpath/XPathResult.java +@OPENJDK@/jaxp/src/org/xml/sax/AttributeList.java +@OPENJDK@/jaxp/src/org/xml/sax/Attributes.java +@OPENJDK@/jaxp/src/org/xml/sax/ContentHandler.java +@OPENJDK@/jaxp/src/org/xml/sax/DocumentHandler.java +@OPENJDK@/jaxp/src/org/xml/sax/DTDHandler.java +@OPENJDK@/jaxp/src/org/xml/sax/EntityResolver.java +@OPENJDK@/jaxp/src/org/xml/sax/ErrorHandler.java +@OPENJDK@/jaxp/src/org/xml/sax/ext/Attributes2.java +@OPENJDK@/jaxp/src/org/xml/sax/ext/Attributes2Impl.java +@OPENJDK@/jaxp/src/org/xml/sax/ext/DeclHandler.java +@OPENJDK@/jaxp/src/org/xml/sax/ext/DefaultHandler2.java +@OPENJDK@/jaxp/src/org/xml/sax/ext/EntityResolver2.java +@OPENJDK@/jaxp/src/org/xml/sax/ext/LexicalHandler.java +@OPENJDK@/jaxp/src/org/xml/sax/ext/Locator2.java +@OPENJDK@/jaxp/src/org/xml/sax/ext/Locator2Impl.java +@OPENJDK@/jaxp/src/org/xml/sax/HandlerBase.java +@OPENJDK@/jaxp/src/org/xml/sax/helpers/AttributeListImpl.java +@OPENJDK@/jaxp/src/org/xml/sax/helpers/AttributesImpl.java +@OPENJDK@/jaxp/src/org/xml/sax/helpers/DefaultHandler.java +@OPENJDK@/jaxp/src/org/xml/sax/helpers/LocatorImpl.java +@OPENJDK@/jaxp/src/org/xml/sax/helpers/NamespaceSupport.java +@OPENJDK@/jaxp/src/org/xml/sax/helpers/NewInstance.java +@OPENJDK@/jaxp/src/org/xml/sax/helpers/ParserAdapter.java +@OPENJDK@/jaxp/src/org/xml/sax/helpers/ParserFactory.java +@OPENJDK@/jaxp/src/org/xml/sax/helpers/SecuritySupport.java +@OPENJDK@/jaxp/src/org/xml/sax/helpers/XMLFilterImpl.java +@OPENJDK@/jaxp/src/org/xml/sax/helpers/XMLReaderAdapter.java +@OPENJDK@/jaxp/src/org/xml/sax/helpers/XMLReaderFactory.java +@OPENJDK@/jaxp/src/org/xml/sax/InputSource.java +@OPENJDK@/jaxp/src/org/xml/sax/Locator.java +@OPENJDK@/jaxp/src/org/xml/sax/Parser.java +@OPENJDK@/jaxp/src/org/xml/sax/SAXException.java +@OPENJDK@/jaxp/src/org/xml/sax/SAXNotRecognizedException.java +@OPENJDK@/jaxp/src/org/xml/sax/SAXNotSupportedException.java +@OPENJDK@/jaxp/src/org/xml/sax/SAXParseException.java +@OPENJDK@/jaxp/src/org/xml/sax/XMLFilter.java +@OPENJDK@/jaxp/src/org/xml/sax/XMLReader.java +@OPENJDK@/jaxws/src/share/jaf_classes/com/sun/activation/registries/LogSupport.java +@OPENJDK@/jaxws/src/share/jaf_classes/com/sun/activation/registries/MailcapFile.java +@OPENJDK@/jaxws/src/share/jaf_classes/com/sun/activation/registries/MailcapParseException.java +@OPENJDK@/jaxws/src/share/jaf_classes/com/sun/activation/registries/MailcapTokenizer.java +@OPENJDK@/jaxws/src/share/jaf_classes/com/sun/activation/registries/MimeTypeEntry.java +@OPENJDK@/jaxws/src/share/jaf_classes/com/sun/activation/registries/MimeTypeFile.java +@OPENJDK@/jaxws/src/share/jaf_classes/javax/activation/ActivationDataFlavor.java +@OPENJDK@/jaxws/src/share/jaf_classes/javax/activation/CommandInfo.java +@OPENJDK@/jaxws/src/share/jaf_classes/javax/activation/CommandMap.java +@OPENJDK@/jaxws/src/share/jaf_classes/javax/activation/CommandObject.java +@OPENJDK@/jaxws/src/share/jaf_classes/javax/activation/DataContentHandler.java +@OPENJDK@/jaxws/src/share/jaf_classes/javax/activation/DataContentHandlerFactory.java +@OPENJDK@/jaxws/src/share/jaf_classes/javax/activation/DataHandler.java +@OPENJDK@/jaxws/src/share/jaf_classes/javax/activation/DataSource.java +@OPENJDK@/jaxws/src/share/jaf_classes/javax/activation/FileDataSource.java +@OPENJDK@/jaxws/src/share/jaf_classes/javax/activation/FileTypeMap.java +@OPENJDK@/jaxws/src/share/jaf_classes/javax/activation/MailcapCommandMap.java +@OPENJDK@/jaxws/src/share/jaf_classes/javax/activation/MimeType.java +@OPENJDK@/jaxws/src/share/jaf_classes/javax/activation/MimeTypeParameterList.java +@OPENJDK@/jaxws/src/share/jaf_classes/javax/activation/MimeTypeParseException.java +@OPENJDK@/jaxws/src/share/jaf_classes/javax/activation/MimetypesFileTypeMap.java +@OPENJDK@/jaxws/src/share/jaf_classes/javax/activation/SecuritySupport.java +@OPENJDK@/jaxws/src/share/jaf_classes/javax/activation/UnsupportedDataTypeException.java +@OPENJDK@/jaxws/src/share/jaf_classes/javax/activation/URLDataSource.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/databinding/Databinding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/databinding/DatabindingFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/databinding/DatabindingMode.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/databinding/DatabindingModeFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/databinding/ExternalMetadataFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/databinding/JavaCallInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/databinding/WSDLGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/databinding/WSDLResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/EnvelopeStyle.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/EnvelopeStyleFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/message/BaseDistributedPropertySet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/message/BasePropertySet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/message/ContentType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/message/DistributedPropertySet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/message/MessageContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/message/MessageContextFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/message/PropertySet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/message/ReadOnlyPropertyException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/impl/encoding/StreamDecoderImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/impl/internalspi/encoding/StreamDecoder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/ExistingAnnotationsType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/JavaMethod.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/JavaParam.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/JavaWsdlMappingType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/ObjectFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/SoapBindingParameterStyle.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/SoapBindingStyle.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/SoapBindingUse.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/Util.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/WebParamMode.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/XmlAction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/XmlAddressing.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/XmlBindingType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/XmlFaultAction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/XmlHandlerChain.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/XmlMTOM.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/XmlOneway.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/XmlRequestWrapper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/XmlResponseWrapper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/XmlServiceMode.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/XmlSOAPBinding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/XmlWebEndpoint.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/XmlWebFault.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/XmlWebMethod.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/XmlWebParam.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/XmlWebResult.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/XmlWebService.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/XmlWebServiceClient.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/XmlWebServiceProvider.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/XmlWebServiceRef.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/ClassType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/CodeWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JBinaryFile.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JPropertyFile.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JSerializedObject.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JStaticFile.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JStaticJavaFile.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JTextFile.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/SecureLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotatable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotationArrayMember.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotationStringValue.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotationUse.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotationValue.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotationWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnonymousClass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JArray.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JArrayClass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JArrayCompRef.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAssignment.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAssignmentTarget.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAtom.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JBlock.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JBreak.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JCase.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JCast.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JCatchBlock.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JClass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JClassAlreadyExistsException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JClassContainer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JCodeModel.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JCommentPart.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JConditional.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JContinue.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDeclaration.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDefinedClass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDirectClass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDocComment.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDocCommentable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDoLoop.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JEnumConstant.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JExpr.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JExpression.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JExpressionImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JFieldRef.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JFieldVar.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JForEach.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JForLoop.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JFormatter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JGenerable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JGenerifiable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JGenerifiableImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JInvocation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JJavaName.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JLabel.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JMethod.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JMod.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JMods.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JNarrowedClass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JNullType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JOp.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JPackage.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JPrimitiveType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JResourceFile.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JReturn.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JStatement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JStringLiteral.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JSwitch.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JThrow.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JTryBlock.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JTypeVar.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JTypeWildcard.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JVar.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JWhileLoop.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/SecureLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/TypedAnnotationWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/ClassNameComparator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/EncoderFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/JavadocEscapeWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/MS1252Encoder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/SingleByteEncoder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/Surrogate.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/UnicodeEscapeWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/FileCodeWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/FilterCodeWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/ProgressCodeWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/PrologCodeWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/SingleStreamCodeWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/ZipCodeWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/Builder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/ByteArrayDataSource.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/FinalArrayList.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/FragmentContentHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/Interned.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/localization/Localizable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/localization/LocalizableMessage.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/localization/LocalizableMessageFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/localization/Localizer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/localization/NullLocalizable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/logging/Logger.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/NotNull.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/Nullable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/Pool.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/SAXException2.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/SAXParseException2.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/tools/DefaultAuthenticator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/tools/MaskingClassLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/tools/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/tools/ParallelWorldClassLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/tools/SecureLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/XMLStreamException2.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/XMLStreamReaderToContentHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/amx/AMX.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/amx/AMXGlassfish.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/amx/AMXUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/amx/BootAMXMBean.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/amx/MBeanListener.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/arc/Stability.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/arc/Taxonomy.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/probe/provider/annotations/Probe.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/probe/provider/annotations/ProbeListener.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/probe/provider/annotations/ProbeParam.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/probe/provider/annotations/ProbeProvider.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/probe/provider/PluginPoint.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/probe/provider/StatsProvider.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/probe/provider/StatsProviderInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/probe/provider/StatsProviderManager.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/probe/provider/StatsProviderManagerDelegate.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/annotations/Reset.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/AverageRangeStatistic.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/BoundaryStatistic.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/BoundedRangeStatistic.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/CountStatistic.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/impl/AverageRangeStatisticImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/impl/BoundaryStatisticImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/impl/BoundedRangeStatisticImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/impl/CountStatisticImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/impl/RangeStatisticImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/impl/StatisticImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/impl/StatsImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/impl/StringStatisticImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/impl/TimeStatisticImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/RangeStatistic.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/Statistic.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/Stats.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/StringStatistic.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/TimeStatistic.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/AMXClient.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/AMXMBeanInterface.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/AMXMetadata.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/Description.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/DescriptorFields.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/DescriptorKey.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/GmbalException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/GmbalMBean.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/GmbalMBeanNOPImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/Impact.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/IncludeSubclass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/InheritedAttribute.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/InheritedAttributes.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/ManagedAttribute.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/ManagedData.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/ManagedObject.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/ManagedObjectManager.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/ManagedObjectManagerFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/ManagedObjectManagerNOPImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/ManagedOperation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/NameValue.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/ParameterNames.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/util/GenericConstructor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/ap/AnnotationParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/ap/Const.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/ap/ErrorReceiverImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/ap/InlineAnnotationReaderImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/ap/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/ap/Options.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/ap/SchemaGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/ap/SecureLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/api/impl/j2s/JavaCompilerImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/api/impl/j2s/JAXBModelImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/api/JXC.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/ConfigReader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/gen/config/AttributesImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/gen/config/Classes.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/gen/config/Config.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/gen/config/NGCCEventReceiver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/gen/config/NGCCEventSource.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/gen/config/NGCCHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/gen/config/NGCCInterleaveFilter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/gen/config/NGCCRuntime.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/gen/config/Schema.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/model/nav/ApNavigator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/NGCCRuntimeEx.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/SchemaGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/SchemaGeneratorFacade.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/SecureLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/api/TJavaGeneratorExtension.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/api/wsdl/TWSDLExtensible.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/api/wsdl/TWSDLExtension.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/api/wsdl/TWSDLExtensionHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/api/wsdl/TWSDLOperation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/api/wsdl/TWSDLParserContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/api/WsgenExtension.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/api/WsgenProtocol.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/Invoker.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/generator/CustomExceptionGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/generator/GeneratorBase.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/generator/GeneratorConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/generator/GeneratorException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/generator/GeneratorExtension.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/generator/GeneratorUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/generator/JavaGeneratorExtensionFacade.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/generator/JwsImplGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/generator/Names.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/generator/SeiGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/generator/ServiceGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/generator/W3CAddressingJavaGeneratorExtension.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/AbstractType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/AsyncOperation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/AsyncOperationType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/Block.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/exporter/ExternalObject.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/ExtendedModelVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/Fault.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/HeaderFault.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/java/JavaArrayType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/java/JavaException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/java/JavaInterface.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/java/JavaMethod.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/java/JavaParameter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/java/JavaSimpleType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/java/JavaStructureMember.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/java/JavaStructureType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/java/JavaType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/jaxb/JAXBElementMember.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/jaxb/JAXBMapping.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/jaxb/JAXBModel.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/jaxb/JAXBProperty.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/jaxb/JAXBStructuredType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/jaxb/JAXBType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/jaxb/JAXBTypeAndAnnotation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/jaxb/JAXBTypeVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/jaxb/RpcLitMember.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/jaxb/RpcLitStructure.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/jaxb/Util.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/Message.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/Model.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/ModelException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/ModelObject.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/ModelProperties.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/ModelVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/Operation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/Parameter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/Port.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/Request.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/Response.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/Service.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/annotation/AnnotationProcessorContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/annotation/FaultInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/annotation/MakeSafeTypeVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/annotation/MemberInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/annotation/ModelBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/annotation/TypeModeler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/annotation/TypeMoniker.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/annotation/TypeMonikerFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/annotation/WebServiceAp.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/annotation/WebServiceConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/annotation/WebServiceVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/annotation/WebServiceWrapperGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/annotation/WrapperInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/JavaSimpleTypeCreator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/Modeler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/ModelerConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/ModelerException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/wsdl/AccessorElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/wsdl/ClassNameAllocatorImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/wsdl/ConsoleErrorReporter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/wsdl/JAXBModelBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/wsdl/ModelerUtils.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/wsdl/PseudoSchemaBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/wsdl/WSDLModeler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/wsdl/WSDLModelerBase.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/ProcessorException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/util/ClassNameCollector.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/util/DirectoryUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/util/IndentingWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/resources/ConfigurationMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/resources/GeneratorMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/resources/JavacompilerMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/resources/ModelerMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/resources/ModelMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/resources/ProcessorMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/resources/UtilMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/resources/WebserviceapMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/resources/WscompileMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/resources/WsdlMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/spi/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/spi/WSToolsObjectFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/ToolVersion.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/util/ClassNameInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/util/ForkEntityResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/util/WSDLFetcher.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/util/WSDLParseException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/util/WSToolsObjectFactoryImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/util/xml/XmlUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/AbortException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/AuthInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/BadCommandLineException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/ErrorReceiver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/ErrorReceiverFilter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/FilerCodeWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/JavaCompilerHelper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/Options.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/Plugin.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/plugin/at_generated/PluginImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/WSCodeWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/WsgenOptions.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/WsgenTool.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/WsimportListener.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/WsimportOptions.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/WsimportTool.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/Binding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/BindingFault.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/BindingInput.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/BindingOperation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/BindingOutput.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/Definitions.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/Documentation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/Fault.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/http/HTTPAddress.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/http/HTTPBinding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/http/HTTPConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/http/HTTPOperation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/http/HTTPUrlEncoded.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/http/HTTPUrlReplacement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/Import.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/Input.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/jaxws/CustomName.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/jaxws/Exception.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/jaxws/JAXWSBinding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/jaxws/JAXWSBindingsConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/jaxws/Parameter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/Kinds.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/Message.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/MessagePart.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/mime/MIMEConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/mime/MIMEContent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/mime/MIMEMultipartRelated.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/mime/MIMEPart.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/mime/MIMEXml.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/Operation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/OperationStyle.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/Output.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/Port.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/PortType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/schema/SchemaConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/schema/SchemaKinds.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/Service.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/soap/SOAP12Binding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/soap/SOAP12Constants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/soap/SOAPAddress.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/soap/SOAPBinding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/soap/SOAPBody.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/soap/SOAPConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/soap/SOAPFault.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/soap/SOAPHeader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/soap/SOAPHeaderFault.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/soap/SOAPOperation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/soap/SOAPStyle.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/soap/SOAPUse.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/Types.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/WSDLConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/WSDLDocument.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/WSDLDocumentVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/WSDLDocumentVisitorBase.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/AbstractDocument.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/Defining.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/DuplicateEntityException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/Elemental.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/Entity.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/EntityAction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/EntityReferenceAction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/EntityReferenceValidator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/ExtensibilityHelper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/ExtensionImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/ExtensionVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/ExtensionVisitorBase.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/ExternalEntityReference.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/GlobalEntity.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/GloballyKnown.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/Identifiable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/Kind.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/NoSuchEntityException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/ParseException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/ParserListener.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/QNameAction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/TWSDLParserContextImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/ValidationException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/WSDLLocation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/AbstractExtensionHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/AbstractReferenceFinderImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/Constants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/ContextClassloaderLocal.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/DOMBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/DOMForest.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/DOMForestParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/DOMForestScanner.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/HTTPExtensionHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/InternalizationLogic.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/Internalizer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/JAXWSBindingExtensionHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/MemberSubmissionAddressingExtensionHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/MetadataFinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/MIMEExtensionHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/NamespaceContextImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/Policy12ExtensionHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/Policy15ExtensionHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/SOAP12ExtensionHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/SOAPEntityReferenceValidator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/SOAPExtensionHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/Util.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/VersionChecker.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/W3CAddressingExtensionHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/W3CAddressingMetadataExtensionHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/WhitespaceStripper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/WSDLInternalizationLogic.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/WSDLParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/WsGen.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/WsImport.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/AbortException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/addon/accessors/PluginImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/addon/at_generated/PluginImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/addon/code_injector/Const.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/addon/code_injector/PluginImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/addon/episode/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/addon/episode/PluginImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/addon/locator/SourceLocationAddOn.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/addon/sync/SynchronizedMethodAddOn.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/ClassNameAllocator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/ErrorListener.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/impl/s2j/AbstractMappingImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/impl/s2j/BeanMappingImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/impl/s2j/DowngradingErrorHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/impl/s2j/ElementAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/impl/s2j/ElementCollectionAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/impl/s2j/ElementMappingImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/impl/s2j/ElementSingleAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/impl/s2j/JAXBModelImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/impl/s2j/PropertyImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/impl/s2j/SchemaCompilerImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/impl/s2j/TypeAndAnnotationImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/J2SJAXBModel.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/JavaCompiler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/JAXBModel.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/Mapping.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/Property.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/Reference.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/S2JJAXBModel.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/SchemaCompiler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/SpecVersion.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/TypeAndAnnotation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/util/ApClassLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/util/FilerCodeWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/util/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/util/ToolsJarNotFoundException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/XJC.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/BadCommandLineException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/ClassLoaderBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/ConsoleErrorReporter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/Driver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/ErrorReceiver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlAccessorOrderWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlAccessorTypeWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlAnyAttributeWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlAnyElementWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlAttachmentRefWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlAttributeWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlElementDeclWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlElementRefsWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlElementRefWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlElementsWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlElementWrapperWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlElementWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlEnumValueWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlEnumWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlIDREFWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlIDWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlInlineBinaryDataWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlJavaTypeAdapterWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlListWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlMimeTypeWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlMixedWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlNsWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlRegistryWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlRootElementWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlSchemaTypesWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlSchemaTypeWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlSchemaWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlSeeAlsoWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlTransientWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlTypeWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/XmlValueWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/BeanGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/ClassOutlineImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/DualObjectFactoryGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/ElementOutlineImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/AbstractField.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/AbstractFieldWithVar.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/AbstractListField.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/ArrayField.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/ConstField.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/ConstFieldRenderer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/ContentListField.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/DefaultFieldRenderer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/DummyListField.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/FieldRenderer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/FieldRendererFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/GenericFieldRenderer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/IsSetField.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/IsSetFieldRenderer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/NoExtendedContentField.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/SingleField.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/SinglePrimitiveAccessField.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/UnboxedField.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/UntypedListField.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/UntypedListFieldRenderer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/ImplStructureStrategy.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/MethodWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/ObjectFactoryGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/ObjectFactoryGeneratorImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/PackageOutlineImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/PrivateObjectFactoryGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/PublicObjectFactoryGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/util/BlockReference.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/util/ExistingBlockReference.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/util/LazyBlockReference.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/util/WhitespaceNormalizer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/Language.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/AbstractCElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/AbstractCTypeInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/AutoClassNameAllocator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CArrayInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CAttributePropertyInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CBuiltinLeafInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CClass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CClassInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CClassInfoParent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CClassRef.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CCustomizable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CCustomizations.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CDefaultValue.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CElementInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CElementPropertyInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CEnumConstant.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CEnumLeafInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/ClassNameAllocatorWrapper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CNonElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/Constructor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CPluginCustomization.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CPropertyInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CPropertyVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CReferencePropertyInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CSingleTypePropertyInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CTypeInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CTypeRef.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CValuePropertyInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/CWildcardTypeInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/Model.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/Multiplicity.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/nav/EagerNClass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/nav/EagerNType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/nav/NavigatorImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/nav/NClass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/nav/NClassByJClass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/nav/NParameterizedType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/nav/NType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/nav/Utils.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/Populatable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/SymbolSpace.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/TypeUse.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/TypeUseFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/TypeUseImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/ModelLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/Options.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/outline/Aspect.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/outline/ClassOutline.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/outline/ElementOutline.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/outline/EnumConstantOutline.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/outline/EnumOutline.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/outline/FieldAccessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/outline/FieldOutline.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/outline/Outline.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/outline/PackageOutline.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/Plugin.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/ProgressCodeWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/AbstractExtensionBindingChecker.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/Const.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/bindinfo/BIAttribute.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/bindinfo/BIConstructor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/bindinfo/BIContent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/bindinfo/BIConversion.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/bindinfo/BIElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/bindinfo/BIEnumeration.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/bindinfo/BIInterface.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/bindinfo/BindInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/bindinfo/BIUserConversion.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/bindinfo/DOMBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/bindinfo/DOMLocator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/bindinfo/DOMUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/bindinfo/DTDExtensionBindingChecker.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/bindinfo/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/Block.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/Element.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/ModelGroup.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/Occurence.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/TDTDReader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/Term.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/ExtensionBindingChecker.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/gbind/Choice.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/gbind/ConnectedComponent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/gbind/Element.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/gbind/ElementSet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/gbind/ElementSets.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/gbind/Expression.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/gbind/Graph.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/gbind/OneOrMore.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/gbind/Sequence.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/gbind/SinkNode.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/gbind/SourceNode.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/AbstractReferenceFinderImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/ContentHandlerNamespacePrefixAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/ContextClassloaderLocal.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/DOMBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/DOMForest.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/DOMForestParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/DOMForestScanner.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/InternalizationLogic.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/Internalizer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/LocatorTable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/NamespaceContextImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/SCDBasedBindingSet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/VersionChecker.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/WhitespaceStripper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/ModelChecker.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/RawTypeSet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/relaxng/BindStyle.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/relaxng/ContentModelBinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/relaxng/DatatypeLib.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/relaxng/DefineFinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/relaxng/NameCalculator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/relaxng/RawTypeSetBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/relaxng/RELAXNGCompiler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/relaxng/RELAXNGInternalizationLogic.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/relaxng/TypePatternBinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/relaxng/TypeUseBinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/Ring.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/TypeUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/Util.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/Abstractifier.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/BGMBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/BindBlue.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/BindGreen.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/AbstractDeclarationImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/AnnotationParserFactoryImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BIClass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BIConversion.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BIDeclaration.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BIDom.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BIEnum.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BIEnumMember.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BIFactoryMethod.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BIGlobalBinding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BIInlineBinaryData.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BindInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BIProperty.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BISchemaBinding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BISerializable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BIXDom.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BIXPluginCustomization.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BIXSubstitutable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/CollectionTypeAttribute.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/DomHandlerEx.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/EnumMemberMode.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/ForkingFilter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/LocalScoping.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/OptionalPropertyMode.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/BindingComponent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/BindPurple.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/BindRed.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/BindYellow.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ClassBinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ClassBinderFilter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ClassSelector.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/CollisionInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ColorBinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ct/AbstractExtendedComplexTypeBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ct/ChoiceContentComplexTypeBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ct/ComplexTypeBindingMode.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ct/ComplexTypeFieldBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ct/CTBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ct/ExtendedComplexTypeBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ct/FreshComplexTypeBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ct/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ct/MixedComplexTypeBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ct/MixedExtendedComplexTypeBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ct/MultiWildcardComplexTypeBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ct/RestrictedComplexTypeBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ct/STDerivedComplexTypeBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/DefaultClassBinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/DefaultParticleBinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ErrorReporter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ExpressionBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ExpressionParticleBinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/GElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/GElementImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/GWildcardElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/MultiplicityCounter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/parser/CustomizationContextChecker.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/parser/IncorrectNamespaceURIChecker.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/parser/LSInputSAXWrapper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/parser/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/parser/SchemaConstraintChecker.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/parser/XMLSchemaInternalizationLogic.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ParticleBinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/RawTypeSetBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/RefererFinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/SimpleTypeBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/UnusedCustomizationChecker.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/WildcardNameClassBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/runtime/JAXBContextFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/runtime/ZeroOneBooleanAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/SchemaCache.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/SecureLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/util/CodeModelClassFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/util/DOMUtils.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/util/ErrorReceiverFilter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/util/ForkContentHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/util/ForkEntityResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/util/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/util/MimeTypeRange.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/util/NamespaceContextAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/util/NullStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/util/ReadOnlyAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/util/StringCutter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/util/SubtreeCutter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/util/Util.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/writer/SignatureWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/XJCFacade.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/XJCListener.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/AccessorFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/AccessorFactoryImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/annotation/OverrideAnnotationOf.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/annotation/XmlIsSet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/annotation/XmlLocation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/AnyTypeAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/api/AccessorException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/api/Bridge.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/api/BridgeContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/api/ClassResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/api/CompositeStructure.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/api/ErrorListener.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/api/impl/NameConverter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/api/impl/NameUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/api/JAXBRIContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/api/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/api/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/api/RawAccessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/api/TypeReference.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/api/Utils.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/CycleRecoverable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/DatatypeConverterImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/IDResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/InternalAccessorFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/Locatable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/marshaller/CharacterEscapeHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/marshaller/DataWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/marshaller/DumbEscapeHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/marshaller/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/marshaller/MinimumEscapeHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/marshaller/NamespacePrefixMapper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/marshaller/NioEscapeHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/marshaller/SAX2DOMEx.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/marshaller/XMLWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/unmarshaller/DOMScanner.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/unmarshaller/InfosetScanner.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/unmarshaller/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/unmarshaller/Patcher.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/Util.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/util/AttributesImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/util/SecureLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/util/ValidationEventLocatorExImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/util/Which.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/bytecode/ClassTailor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/bytecode/SecureLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/ClassFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/ContextFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/AbstractInlineAnnotationReaderImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/AnnotationReader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/AnnotationSource.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/ClassLocatable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/FieldLocatable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/Init.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/Locatable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/LocatableAnnotation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/MethodLocatable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/Quick.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/RuntimeAnnotationReader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/RuntimeInlineAnnotationReader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/SecureLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/XmlAttributeQuick.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/XmlElementDeclQuick.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/XmlElementQuick.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/XmlElementRefQuick.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/XmlElementRefsQuick.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/XmlEnumQuick.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/XmlRootElementQuick.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/XmlSchemaQuick.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/XmlSchemaTypeQuick.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/XmlTransientQuick.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/XmlTypeQuick.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/XmlValueQuick.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/Adapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/ArrayInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/AttributePropertyInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/BuiltinLeafInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/ClassInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/Element.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/ElementInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/ElementPropertyInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/EnumConstant.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/EnumLeafInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/ErrorHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/ID.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/LeafInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/MapPropertyInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/MaybeElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/NonElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/NonElementRef.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/PropertyInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/PropertyKind.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/Ref.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/ReferencePropertyInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/RegistryInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/TypeInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/TypeInfoSet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/TypeRef.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/ValuePropertyInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/WildcardMode.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/WildcardTypeInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/AnyTypeImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/ArrayInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/AttributePropertyInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/BuiltinLeafInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/ClassInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/DummyPropertyInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/ElementInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/ElementPropertyInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/EnumConstantImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/EnumLeafInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/ERPropertyInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/FieldPropertySeed.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/GetterSetterPropertySeed.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/LeafInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/MapPropertyInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/ModelBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/ModelBuilderI.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/PropertyInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/PropertySeed.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/ReferencePropertyInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/RegistryInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeAnyTypeImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeArrayInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeAttributePropertyInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeBuiltinLeafInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeClassInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeElementInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeElementPropertyInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeEnumConstantImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeEnumLeafInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeMapPropertyInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeModelBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeReferencePropertyInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeTypeInfoSetImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeTypeRefImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeValuePropertyInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/SecureLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/SingleTypePropertyInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/TypeInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/TypeInfoSetImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/TypeRefImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/Util.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/Utils.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/ValuePropertyInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/nav/GenericArrayTypeImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/nav/Navigator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/nav/ParameterizedTypeImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/nav/ReflectionNavigator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/nav/SecureLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/nav/TypeVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/nav/WildcardTypeImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/runtime/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/runtime/RuntimeArrayInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/runtime/RuntimeAttributePropertyInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/runtime/RuntimeBuiltinLeafInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/runtime/RuntimeClassInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/runtime/RuntimeElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/runtime/RuntimeElementInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/runtime/RuntimeElementPropertyInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/runtime/RuntimeEnumLeafInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/runtime/RuntimeLeafInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/runtime/RuntimeMapPropertyInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/runtime/RuntimeNonElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/runtime/RuntimeNonElementRef.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/runtime/RuntimePropertyInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/runtime/RuntimeReferencePropertyInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/runtime/RuntimeTypeInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/runtime/RuntimeTypeInfoSet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/runtime/RuntimeTypeRef.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/runtime/RuntimeValuePropertyInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/util/ArrayInfoUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/AnyTypeBeanInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/ArrayBeanInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/AssociationMap.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/AttributeAccessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/BinderImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/BridgeAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/BridgeContextImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/BridgeImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/ClassBeanInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/CompositeStructureBeanInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/ContentHandlerAdaptor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/Coordinator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/DomPostInitAction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/ElementBeanInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/FilterTransducer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/IllegalAnnotationException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/IllegalAnnotationsException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/InlineBinaryTransducer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/InternalBridge.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/JAXBContextImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/JaxBeanInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/LeafBeanInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/LifecycleMethods.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/Location.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/MarshallerImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/MimeTypedTransducer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/Name.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/NameBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/NameList.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/NamespaceContext2.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/C14nXmlOutput.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/DOMOutput.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/Encoded.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/FastInfosetStreamWriterOutput.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/ForkXmlOutput.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/IndentingUTF8XmlOutput.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/MTOMXmlOutput.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/NamespaceContextImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/Pcdata.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/SAXOutput.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/SecureLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/StAXExStreamWriterOutput.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/UTF8XmlOutput.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/XMLEventWriterOutput.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/XmlOutput.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/XmlOutputAbstractImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/XMLStreamWriterOutput.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/ArrayElementLeafProperty.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/ArrayElementNodeProperty.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/ArrayElementProperty.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/ArrayERProperty.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/ArrayProperty.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/ArrayReferenceNodeProperty.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/AttributeProperty.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/ListElementProperty.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/Property.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/PropertyFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/PropertyImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/SingleElementLeafProperty.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/SingleElementNodeProperty.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/SingleMapNodeProperty.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/SingleReferenceNodeProperty.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/StructureLoaderBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/TagAndType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/UnmarshallerChain.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/Utils.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/ValueProperty.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/Accessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/AdaptedAccessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/AdaptedLister.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/DefaultTransducedAccessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/Lister.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/ListIterator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/ListTransducedAccessorImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/NullSafeAccessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/AccessorInjector.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/Bean.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/Const.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/FieldAccessor_Boolean.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/FieldAccessor_Byte.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/FieldAccessor_Character.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/FieldAccessor_Double.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/FieldAccessor_Float.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/FieldAccessor_Integer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/FieldAccessor_Long.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/FieldAccessor_Ref.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/FieldAccessor_Short.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/Injector.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/MethodAccessor_Boolean.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/MethodAccessor_Byte.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/MethodAccessor_Character.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/MethodAccessor_Double.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/MethodAccessor_Float.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/MethodAccessor_Integer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/MethodAccessor_Long.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/MethodAccessor_Ref.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/MethodAccessor_Short.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/OptimizedAccessorFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/OptimizedTransducedAccessorFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/Ref.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/SecureLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/TransducedAccessor_field_Boolean.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/TransducedAccessor_field_Byte.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/TransducedAccessor_field_Double.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/TransducedAccessor_field_Float.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/TransducedAccessor_field_Integer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/TransducedAccessor_field_Long.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/TransducedAccessor_field_Short.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/TransducedAccessor_method_Boolean.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/TransducedAccessor_method_Byte.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/TransducedAccessor_method_Double.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/TransducedAccessor_method_Float.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/TransducedAccessor_method_Integer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/TransducedAccessor_method_Long.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/TransducedAccessor_method_Short.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/PrimitiveArrayListerBoolean.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/PrimitiveArrayListerByte.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/PrimitiveArrayListerCharacter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/PrimitiveArrayListerDouble.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/PrimitiveArrayListerFloat.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/PrimitiveArrayListerInteger.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/PrimitiveArrayListerLong.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/PrimitiveArrayListerShort.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/TransducedAccessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/Utils.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/RuntimeUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/SchemaTypeTransducer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/StAXPostInitAction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/SwaRefAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/SwaRefAdapterMarker.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/Transducer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/AttributesEx.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/AttributesExImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/Base64Data.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/ChildLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/DefaultIDResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/DefaultValueLoaderDecorator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/Discarder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/DomLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/FastInfosetConnector.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/IntArrayData.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/IntData.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/Intercepter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/InterningXmlVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/LeafPropertyLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/LeafPropertyXsiLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/Loader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/LocatorEx.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/LocatorExWrapper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/MTOMDecorator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/Patcher.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/ProxyLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/Receiver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/SAXConnector.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/Scope.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/SecureLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/StAXConnector.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/StAXEventConnector.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/StAXExConnector.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/StAXStreamConnector.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/StructureLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/TagName.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/TextLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/UnmarshallerImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/UnmarshallingContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/ValidatingUnmarshaller.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/ValuePropertyLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/WildcardLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/XmlVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/XsiNilLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/XsiTypeLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/Utils.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/ValueListBeanInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/XMLSerializer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/episode/Bindings.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/episode/Klass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/episode/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/episode/Package.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/episode/SchemaBindings.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/FoolProofResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/Form.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/GroupKind.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/MultiMap.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/Tree.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/Util.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/Annotated.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/Annotation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/Any.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/Appinfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/AttrDecls.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/AttributeType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/ComplexContent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/ComplexExtension.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/ComplexRestriction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/ComplexType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/ComplexTypeHost.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/ComplexTypeModel.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/ContentModelContainer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/Documentation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/Element.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/ExplicitGroup.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/ExtensionType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/FixedOrDefault.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/Import.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/List.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/LocalAttribute.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/LocalElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/NestedParticle.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/NoFixedFacet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/Occurs.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/Particle.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/Redefinable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/Schema.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/SchemaTop.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/SimpleContent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/SimpleDerivation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/SimpleExtension.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/SimpleRestriction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/SimpleRestrictionModel.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/SimpleType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/SimpleTypeHost.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/TopLevelAttribute.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/TopLevelElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/TypeDefParticle.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/TypeHost.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/Union.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/Wildcard.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/XmlSchemaGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/TODO.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/util/ByteArrayOutputStreamEx.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/util/CollisionCheckStack.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/util/DataSourceSource.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/util/EditDistance.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/util/FatalAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/util/FlattenIterator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/util/QNameMap.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/util/StackRecorder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/util/TypeCast.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/util/XmlFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/WellKnownNamespace.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/ValidationEventLocatorEx.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/WhiteSpaceProcessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/XmlAccessorFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/dtdparser/DTDEventListener.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/dtdparser/DTDHandlerBase.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/dtdparser/DTDParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/dtdparser/EndOfInputException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/dtdparser/EntityDecl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/dtdparser/ExternalEntity.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/dtdparser/InputEntity.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/dtdparser/InternalEntity.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/dtdparser/MessageCatalog.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/dtdparser/Resolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/dtdparser/SimpleHashtable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/dtdparser/XmlChars.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/dtdparser/XmlNames.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/dtdparser/XmlReader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/AbstractResourceBundle.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/algorithm/BASE64EncodingAlgorithm.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/algorithm/BooleanEncodingAlgorithm.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/algorithm/BuiltInEncodingAlgorithm.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/algorithm/BuiltInEncodingAlgorithmFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/algorithm/BuiltInEncodingAlgorithmState.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/algorithm/DoubleEncodingAlgorithm.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/algorithm/FloatEncodingAlgorithm.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/algorithm/HexadecimalEncodingAlgorithm.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/algorithm/IEEE754FloatingPointEncodingAlgorithm.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/algorithm/IntegerEncodingAlgorithm.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/algorithm/IntEncodingAlgorithm.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/algorithm/LongEncodingAlgorithm.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/algorithm/ShortEncodingAlgorithm.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/algorithm/UUIDEncodingAlgorithm.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/alphabet/BuiltInRestrictedAlphabets.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/CommonResourceBundle.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/Decoder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/DecoderStateTables.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/dom/DOMDocumentParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/dom/DOMDocumentSerializer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/Encoder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/EncodingConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/Notation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/OctetBufferListener.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/org/apache/xerces/util/XMLChar.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/QualifiedName.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/sax/AttributesHolder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/sax/Features.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/sax/Properties.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/sax/SAXDocumentParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/sax/SAXDocumentSerializer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/sax/SAXDocumentSerializerWithPrefixMapping.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/sax/SystemIdResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/EventLocation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/AttributeBase.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/CharactersEvent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/CommentEvent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/DTDEvent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/EmptyIterator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/EndDocumentEvent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/EndElementEvent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/EntityDeclarationImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/EntityReferenceEvent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/EventBase.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/NamespaceBase.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/ProcessingInstructionEvent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/ReadIterator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/StartDocumentEvent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/StartElementEvent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/StAXEventAllocatorBase.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/StAXEventReader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/StAXEventWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/StAXFilteredEvent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/Util.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/XMLConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/factory/StAXEventFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/factory/StAXInputFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/factory/StAXOutputFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/StAXDocumentParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/StAXDocumentSerializer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/StAXManager.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/util/StAXFilteredParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/util/StAXParserWrapper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/tools/FI_DOM_Or_XML_DOM_SAX_SAXEvent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/tools/FI_SAX_Or_XML_SAX_DOM_SAX_SAXEvent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/tools/FI_SAX_Or_XML_SAX_SAXEvent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/tools/FI_SAX_XML.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/tools/FI_StAX_SAX_Or_XML_SAX_SAXEvent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/tools/PrintTable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/tools/SAX2StAXWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/tools/SAXEventSerializer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/tools/StAX2SAXReader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/tools/TransformInputOutput.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/tools/VocabularyGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/tools/XML_DOM_FI.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/tools/XML_DOM_SAX_FI.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/tools/XML_SAX_FI.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/tools/XML_SAX_StAX_FI.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/UnparsedEntity.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/util/CharArray.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/util/CharArrayArray.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/util/CharArrayIntMap.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/util/CharArrayString.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/util/ContiguousCharArrayArray.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/util/DuplicateAttributeVerifier.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/util/FixedEntryStringIntMap.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/util/KeyIntMap.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/util/LocalNameQualifiedNamesMap.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/util/NamespaceContextImplementation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/util/PrefixArray.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/util/QualifiedNameArray.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/util/StringArray.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/util/StringIntMap.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/util/ValueArray.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/util/ValueArrayResourceException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/vocab/ParserVocabulary.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/vocab/SerializerVocabulary.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/vocab/Vocabulary.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/client/p2p/HttpSOAPConnection.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/client/p2p/HttpSOAPConnectionFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/Header.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/BMMimeMultipart.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/ContentDisposition.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/ContentType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/HeaderTokenizer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/InternetHeaders.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/MimeBodyPart.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/MimeMultipart.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/MimePartDataSource.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/MimePullMultipart.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/MimeUtility.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/ParameterList.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/ParseException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/SharedInputStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/UniqueValue.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/MessagingException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/MultipartDataSource.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/util/ASCIIUtility.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/util/BASE64DecoderStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/util/BASE64EncoderStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/util/BEncoderStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/util/LineInputStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/util/OutputUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/util/QDecoderStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/util/QEncoderStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/util/QPDecoderStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/util/QPEncoderStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/util/UUDecoderStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/util/UUEncoderStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/AttachmentPartImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ContextClassloaderLocal.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/dynamic/SOAPFactoryDynamicImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/dynamic/SOAPMessageFactoryDynamicImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/Envelope.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/EnvelopeFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/FastInfosetDataContentHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/GifDataContentHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ImageDataContentHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/impl/BodyElementImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/impl/BodyImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/impl/CDATAImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/impl/CommentImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/impl/DetailEntryImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/impl/DetailImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/impl/ElementFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/impl/ElementImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/impl/EnvelopeImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/impl/FaultElementImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/impl/FaultImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/impl/HeaderElementImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/impl/HeaderImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/impl/TextImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/impl/TreeException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/JpegDataContentHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/MessageFactoryImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/MessageImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/MultipartDataContentHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/name/NameImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/SAAJMetaFactoryImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/SOAPDocument.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/SOAPDocumentFragment.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/SOAPDocumentImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/SOAPFactoryImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/SOAPIOException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/SOAPPartImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/SOAPVersionMismatchException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/StringDataContentHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_1/Body1_1Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_1/BodyElement1_1Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_1/Detail1_1Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_1/DetailEntry1_1Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_1/Envelope1_1Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_1/Fault1_1Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_1/FaultElement1_1Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_1/Header1_1Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_1/HeaderElement1_1Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_1/Message1_1Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_1/SOAPFactory1_1Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_1/SOAPMessageFactory1_1Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_1/SOAPPart1_1Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_2/Body1_2Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_2/BodyElement1_2Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_2/Detail1_2Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_2/DetailEntry1_2Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_2/Envelope1_2Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_2/Fault1_2Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_2/FaultElement1_2Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_2/Header1_2Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_2/HeaderElement1_2Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_2/Message1_2Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_2/SOAPFactory1_2Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_2/SOAPMessageFactory1_2Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_2/SOAPPart1_2Impl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/XmlDataContentHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/SOAPExceptionImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/Base64.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/ByteInputStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/ByteOutputStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/CharReader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/CharWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/FastInfosetReflection.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/FinalArrayList.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/JAXMStreamSource.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/JaxmURI.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/LogDomainConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/MimeHeadersUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/NamespaceContextIterator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/ParserPool.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/ParseUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/RejectDoctypeSaxFilter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/SAAJUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/TeeInputStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/transform/EfficientStreamingTransformer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/XMLDeclarationParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/EncodingAlgorithm.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/EncodingAlgorithmException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/EncodingAlgorithmIndexes.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/ExternalVocabulary.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/FastInfosetException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/FastInfosetParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/FastInfosetResult.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/FastInfosetSerializer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/FastInfosetSource.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/RestrictedAlphabet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/sax/EncodingAlgorithmAttributes.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/sax/EncodingAlgorithmContentHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/sax/ExtendedContentHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/sax/FastInfosetReader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/sax/FastInfosetWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/sax/helpers/EncodingAlgorithmAttributesImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/sax/helpers/FastInfosetDefaultHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/sax/PrimitiveTypeContentHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/sax/RestrictedAlphabetContentHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/stax/FastInfosetStreamReader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/stax/LowLevelFastInfosetStreamWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/Vocabulary.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/VocabularyApplicationData.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/ASCIIUtility.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/BASE64DecoderStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/Chunk.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/ChunkInputStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/CleanUpExecutorFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/Data.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/DataFile.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/DataHead.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/DecodingException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/FactoryFinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/FileData.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/FinalArrayList.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/Header.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/InternetHeaders.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/LineInputStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/MemoryData.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/MIMEConfig.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/MIMEEvent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/MIMEMessage.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/MIMEParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/MIMEParsingException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/MIMEPart.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/MimeUtility.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/PropUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/QPDecoderStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/TempFiles.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/UUDecoderStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/WeakDataFile.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/staxex/Base64Data.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/staxex/Base64Encoder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/staxex/Base64EncoderStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/staxex/ByteArrayOutputStreamEx.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/staxex/NamespaceContextEx.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/staxex/StreamingDataHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/staxex/XMLStreamReaderEx.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/staxex/XMLStreamWriterEx.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/builder/Annotations.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/builder/BuildException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/builder/CommentList.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/builder/DataPatternBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/builder/Div.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/builder/ElementAnnotationBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/builder/Grammar.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/builder/GrammarSection.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/builder/Include.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/builder/IncludedGrammar.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/builder/NameClassBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/builder/SchemaBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/builder/Scope.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/om/Location.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/om/ParsedElementAnnotation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/om/ParsedNameClass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/om/ParsedPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/util/CheckingSchemaBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/util/LocatorImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/AfterPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/Alphabet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/AttributePattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/BinaryPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/ChoicePattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/DataExceptPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/DataPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/DuplicateAttributeDetector.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/ElementPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/EmptyPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/ErrorPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/GroupPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/InterleavePattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/ListPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/NotAllowedPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/OneOrMorePattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/Pattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/PatternBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/PatternInterner.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/RefPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/RestrictionViolationException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/SchemaBuilderImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/SchemaPatternBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/StringPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/TextPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/ValuePattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/visitor/ChildElementFinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/visitor/PatternFunction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/visitor/PatternVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/visitor/PatternWalker.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/Annotation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/CommentListImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DAnnotation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DataPatternBuilderImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DAttributePattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DChoicePattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DContainerPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DDataPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DDefine.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DElementPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DEmptyPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DGrammarPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DGroupPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DInterleavePattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DListPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DMixedPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DNotAllowedPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DOMPrinter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DOneOrMorePattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DOptionalPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DPatternVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DPatternWalker.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DRefPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DSchemaBuilderImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DTextPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DUnaryPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DValuePattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DXMLPrinter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DXmlTokenPattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/DZeroOrMorePattern.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/ElementAnnotationBuilderImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/ElementWrapper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/GrammarBuilderImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/IncludeImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/Main.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/PatternParseable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/dt/builtin/BuiltinDatatypeBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/dt/builtin/BuiltinDatatypeLibrary.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/dt/builtin/BuiltinDatatypeLibraryFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/dt/builtin/CompatibilityDatatypeLibrary.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/dt/CachedDatatypeLibraryFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/dt/CascadingDatatypeLibraryFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/dt/DoNothingDatatypeLibraryFactoryImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/nc/AnyNameClass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/nc/AnyNameExceptNameClass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/nc/ChoiceNameClass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/nc/NameClass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/nc/NameClassBuilderImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/nc/NameClassVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/nc/NameClassWalker.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/nc/NsNameClass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/nc/NsNameExceptNameClass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/nc/NullNameClass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/nc/OverlapDetector.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/nc/SimpleNameClass.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/compact/CompactParseable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/compact/CompactSyntax.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/compact/CompactSyntaxConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/compact/CompactSyntaxTokenManager.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/compact/EOFException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/compact/EscapeSyntaxException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/compact/JavaCharStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/compact/ParseException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/compact/Token.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/compact/TokenMgrError.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/compact/UCode_UCodeESC_CharStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/Context.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/host/AnnotationsHost.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/host/Base.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/host/CommentListHost.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/host/DataPatternBuilderHost.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/host/DivHost.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/host/ElementAnnotationBuilderHost.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/host/GrammarHost.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/host/GrammarSectionHost.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/host/IncludeHost.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/host/LocationHost.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/host/NameClassBuilderHost.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/host/ParsedElementAnnotationHost.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/host/ParsedNameClassHost.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/host/ParsedPatternHost.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/host/SchemaBuilderHost.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/host/ScopeHost.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/IllegalSchemaException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/Parseable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/xml/DtdContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/xml/SAXParseable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/xml/SchemaParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/util/Localizer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/util/Uri.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/util/Utf16.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/xml/sax/AbstractLexicalHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/xml/sax/JAXPXMLReaderCreator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/xml/sax/XmlBaseHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/xml/sax/XMLReaderCreator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/xml/util/EncodingMap.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/xml/util/Naming.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/xml/util/WellKnownNamespaces.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/AbstractCreator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/AbstractCreatorProcessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/AbstractProcessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/AttributesHolder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/ContextClassloaderLocal.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/FragmentedArray.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/MutableXMLStreamBuffer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/sax/DefaultWithLexicalHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/sax/Features.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/sax/Properties.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/sax/SAXBufferCreator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/sax/SAXBufferProcessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/stax/NamespaceContexHelper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/stax/StreamBufferCreator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/stax/StreamReaderBufferCreator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/stax/StreamReaderBufferProcessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/stax/StreamWriterBufferCreator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/stax/StreamWriterBufferProcessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/XMLStreamBuffer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/XMLStreamBufferException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/XMLStreamBufferMark.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/XMLStreamBufferResult.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/XMLStreamBufferSource.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/annotation/XmlAttribute.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/annotation/XmlCDATA.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/annotation/XmlElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/annotation/XmlNamespace.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/annotation/XmlValue.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/Attribute.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/Cdata.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/Comment.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/ContainerElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/Content.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/ContentVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/DatatypeWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/Document.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/EndDocument.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/EndTag.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/IllegalAnnotationException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/IllegalSignatureException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/NamespaceDecl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/NamespaceResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/NamespaceSupport.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/output/CharacterEscapeHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/output/DataWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/output/DelegatingXMLStreamWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/output/DomSerializer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/output/DumbEscapeHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/output/DumpSerializer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/output/IndentingXMLFilter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/output/IndentingXMLStreamWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/output/ResultFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/output/SaxSerializer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/output/StaxSerializer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/output/StreamSerializer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/output/TXWResult.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/output/TXWSerializer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/output/XmlSerializer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/output/XMLWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/Pcdata.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/StartDocument.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/StartTag.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/Text.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/TXW.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/TxwException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/TypedXmlWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/EndpointReferenceUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/EPRSDDocumentFilter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/model/ActionNotSupportedException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/model/InvalidAddressingHeaderException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/model/MissingAddressingHeaderException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/policy/AddressingFeatureConfigurator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/policy/AddressingPolicyMapConfigurator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/policy/AddressingPolicyValidator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/policy/AddressingPrefixMapper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/ProblemAction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/ProblemHeaderQName.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/v200408/MemberSubmissionAddressingConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/v200408/MemberSubmissionWsaClientTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/v200408/MemberSubmissionWsaServerTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/v200408/ProblemAction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/v200408/ProblemHeaderQName.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/v200408/WsaTubeHelperImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/W3CAddressingConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/W3CAddressingMetadataConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/W3CWsaClientTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/W3CWsaServerTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/WsaActionUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/WsaClientTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/WsaPropertyBag.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/WsaServerTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/WsaTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/WsaTubeHelper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/WsaTubeHelperImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/WSEPRExtension.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/addressing/AddressingPropertySet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/addressing/AddressingVersion.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/addressing/EPRHeader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/addressing/NonAnonymousResponseProcessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/addressing/OneWayFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/addressing/OutboundReferenceParameterHeader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/addressing/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/addressing/WSEndpointReference.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/BindingID.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/BindingIDFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/Cancelable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/client/ClientPipelineHook.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/client/SelectOptimalEncodingFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/client/ServiceInterceptor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/client/ServiceInterceptorFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/client/ThrowableInPacketCompletionFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/client/WSPortInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/Component.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/ComponentEx.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/ComponentFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/ComponentRegistry.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/ComponentsFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/config/management/EndpointCreationAttributes.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/config/management/ManagedEndpointFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/config/management/policy/ManagedClientAssertion.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/config/management/policy/ManagedServiceAssertion.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/config/management/policy/ManagementAssertion.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/config/management/Reconfigurable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/databinding/ClientCallBridge.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/databinding/Databinding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/databinding/DatabindingConfig.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/databinding/DatabindingFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/databinding/EndpointCallBridge.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/databinding/JavaCallInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/databinding/MappingInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/databinding/MetadataReader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/databinding/SoapBodyStyle.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/databinding/WSDLGenInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/DistributedPropertySet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/EndpointAddress.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/fastinfoset/FastInfosetFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/FeatureConstructor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/FeatureListValidator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/FeatureListValidatorAnnotation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/ha/HaInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/ha/StickyFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/handler/MessageHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/handler/MessageHandlerContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/ImpliesWebServiceFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/AddressingUtils.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/Attachment.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/AttachmentEx.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/AttachmentSet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/ExceptionHasMessage.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/FilterMessageImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/Header.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/HeaderList.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/Headers.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/Message.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/MessageContextFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/MessageHeaders.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/MessageMetadata.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/MessageWrapper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/MessageWritable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/Packet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/saaj/SAAJFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/saaj/SAAJMessageHeaders.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/saaj/SaajStaxWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/stream/InputStreamMessage.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/stream/StreamBasedMessage.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/stream/XMLStreamReaderMessage.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/StreamingSOAP.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/SuppressAutomaticWSARequestHeadersFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/CheckedException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/ExceptionType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/JavaMethod.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/MEP.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/Parameter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/ParameterBinding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/SEIModel.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/soap/SOAPBinding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/editable/EditableWSDLBoundFault.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/editable/EditableWSDLBoundOperation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/editable/EditableWSDLBoundPortType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/editable/EditableWSDLFault.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/editable/EditableWSDLInput.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/editable/EditableWSDLMessage.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/editable/EditableWSDLModel.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/editable/EditableWSDLOperation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/editable/EditableWSDLOutput.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/editable/EditableWSDLPart.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/editable/EditableWSDLPort.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/editable/EditableWSDLPortType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/editable/EditableWSDLService.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/WSDLBoundFault.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/WSDLBoundOperation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/WSDLBoundPortType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/WSDLDescriptorKind.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/WSDLExtensible.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/WSDLExtension.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/WSDLFault.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/WSDLFeaturedObject.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/WSDLInput.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/WSDLMessage.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/WSDLModel.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/WSDLObject.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/WSDLOperation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/WSDLOutput.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/WSDLPart.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/WSDLPartDescriptor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/WSDLPort.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/WSDLPortType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/WSDLService.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/WSDLOperationMapping.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/ClientPipeAssemblerContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/ClientTubeAssemblerContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/Codec.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/Codecs.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/ContentType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/Engine.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/Fiber.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/FiberContextSwitchInterceptor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/FiberContextSwitchInterceptorFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/helper/AbstractFilterPipeImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/helper/AbstractFilterTubeImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/helper/AbstractPipeImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/helper/AbstractTubeImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/helper/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/helper/PipeAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/NextAction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/Pipe.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/PipeCloner.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/PipeClonerImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/PipelineAssembler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/PipelineAssemblerFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/ServerPipeAssemblerContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/ServerTubeAssemblerContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/SOAPBindingCodec.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/StreamSOAPCodec.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/Stubs.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/SyncStartForAsyncFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/ThrowableContainerPropertySet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/TransportPipeFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/TransportTubeFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/Tube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/TubeCloner.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/TubelineAssembler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/TubelineAssemblerFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/policy/AlternativeSelector.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/policy/ModelGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/policy/ModelTranslator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/policy/ModelUnmarshaller.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/policy/PolicyResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/policy/PolicyResolverFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/policy/SourceModel.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/policy/subject/BindingSubject.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/policy/ValidationProcessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/PropertySet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/ResourceLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/AbstractInstanceResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/AbstractServerAsyncTransport.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/Adapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/AsyncProvider.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/AsyncProviderCallback.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/BoundEndpoint.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/Container.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/ContainerResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/DocumentAddressResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/EndpointAwareCodec.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/EndpointComponent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/EndpointData.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/EndpointReferenceExtensionContributor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/HttpEndpoint.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/InstanceResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/InstanceResolverAnnotation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/Invoker.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/LazyMOMProvider.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/MethodUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/Module.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/PortAddressResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/ProviderInvokerTubeFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/ResourceInjector.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/SDDocument.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/SDDocumentFilter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/SDDocumentSource.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/ServerPipelineHook.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/ServiceDefinition.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/ThreadLocalContainerResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/TransportBackChannel.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/WebModule.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/WebServiceContextDelegate.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/WSEndpoint.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/WSWebServiceContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/ServiceSharedFeatureMarker.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/SOAPVersion.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/streaming/ContextClassloaderLocal.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/streaming/XMLStreamReaderFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/streaming/XMLStreamWriterFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/WebServiceFeatureFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/WSBinding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/wsdl/parser/MetaDataResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/wsdl/parser/MetadataResolverFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/wsdl/parser/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/wsdl/parser/PolicyWSDLParserExtension.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/wsdl/parser/ServiceDescriptor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/wsdl/parser/WSDLParserExtension.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/wsdl/parser/WSDLParserExtensionContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/wsdl/parser/XMLEntityResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/wsdl/writer/WSDLGeneratorExtension.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/wsdl/writer/WSDLGenExtnContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/WSDLLocator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/WSFeatureList.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/WSService.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/DefaultClientTubelineAssemblyContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/DefaultServerTubelineAssemblyContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/dev/ClientTubelineAssemblyContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/dev/ServerTubelineAssemblyContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/dev/TubeFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/dev/TubelineAssemblyContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/dev/TubelineAssemblyContextUpdater.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/dev/TubelineAssemblyDecorator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/jaxws/AddressingTubeFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/jaxws/BasicTransportTubeFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/jaxws/HandlerTubeFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/jaxws/MonitoringTubeFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/jaxws/MustUnderstandTubeFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/jaxws/TerminalTubeFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/jaxws/ValidationTubeFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/MetroConfigLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/MetroConfigName.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/MetroConfigNameImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/MetroTubelineAssembler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/TubeCreator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/TubelineAssemblyContextImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/TubelineAssemblyController.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/binding/BindingImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/binding/FeatureListUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/binding/HTTPBindingImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/binding/SOAPBindingImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/binding/WebServiceFeatureList.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/AsyncInvoker.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/AsyncResponseImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/BindingProviderProperties.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/ClientContainer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/ClientSchemaValidationTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/ClientTransportException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/ContentNegotiation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/dispatch/DataSourceDispatch.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/dispatch/DispatchImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/dispatch/JAXBDispatch.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/dispatch/MessageDispatch.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/dispatch/PacketDispatch.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/dispatch/RESTSourceDispatch.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/dispatch/SOAPMessageDispatch.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/dispatch/SOAPSourceDispatch.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/HandlerConfiguration.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/HandlerConfigurator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/MonitorRootClient.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/PortInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/RequestContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/ResponseContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/ResponseContextReceiver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/SCAnnotations.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/AsyncMethodHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/BodyBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/CallbackMethodHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/MessageFiller.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/MethodHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/MethodUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/pacakge-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/PollingMethodHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/ResponseBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/SEIMethodHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/SEIStub.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/StubAsyncHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/StubHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/SyncMethodHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/ValueGetter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/ValueGetterFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/ValueSetter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/ValueSetterFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/SEIPortInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/SenderException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/Stub.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/WSServiceDelegate.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/Closeable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/commons/xmlutil/ContextClassloaderLocal.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/commons/xmlutil/Converter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/config/management/policy/ManagementAssertionCreator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/config/management/policy/ManagementPolicyValidator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/config/management/policy/ManagementPrefixMapper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/config/metro/dev/FeatureReader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/config/metro/util/ParserUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/db/DatabindingFactoryImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/db/DatabindingImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/db/DatabindingProviderImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/db/glassfish/BridgeWrapper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/db/glassfish/JAXBRIContextFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/db/glassfish/JAXBRIContextWrapper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/db/glassfish/MarshallerBridge.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/db/glassfish/RawAccessorWrapper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/db/glassfish/WrapperBridge.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/BindingTypeFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/ContextClassloaderLocal.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/EPRRecipe.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/HttpConfigFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/JAXBContextFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/JAXWSProperties.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/MemberSubmissionAddressing.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/MemberSubmissionAddressingFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/MemberSubmissionEndpointReference.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/SchemaValidation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/SchemaValidationFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/Serialization.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/SerializationFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/ServerSideException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/StreamingAttachment.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/StreamingAttachmentFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/StreamingDataHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/UsesJAXBContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/UsesJAXBContextFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/ValidationErrorHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/WSBindingProvider.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/dump/LoggingDumpTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/dump/MessageDumper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/dump/MessageDumping.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/dump/MessageDumpingFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/dump/MessageDumpingTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/dump/MessageDumpingTubeFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/ContentType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/ContentTypeImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/DataHandlerDataSource.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/DataSourceStreamingDataHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/fastinfoset/FastInfosetCodec.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/fastinfoset/FastInfosetMIMETypes.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/fastinfoset/FastInfosetStreamReaderFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/fastinfoset/FastInfosetStreamReaderRecyclable.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/fastinfoset/FastInfosetStreamSOAP11Codec.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/fastinfoset/FastInfosetStreamSOAP12Codec.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/fastinfoset/FastInfosetStreamSOAPCodec.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/HasEncoding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/HeaderTokenizer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/ImageDataContentHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/MimeCodec.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/MimeMultipartParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/MIMEPartStreamingDataHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/MtomCodec.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/ParameterList.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/policy/EncodingConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/policy/EncodingPolicyValidator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/policy/EncodingPrefixMapper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/policy/FastInfosetFeatureConfigurator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/policy/MtomFeatureConfigurator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/policy/MtomPolicyMapConfigurator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/policy/SelectOptimalEncodingFeatureConfigurator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/RootOnlyCodec.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/soap/DeserializationException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/soap/SerializationException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/soap/SerializerConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/soap/SOAP12Constants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/soap/SOAPConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/soap/streaming/SOAP12NamespaceConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/soap/streaming/SOAPNamespaceConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/SOAPBindingCodec.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/StreamSOAP11Codec.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/StreamSOAP12Codec.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/StreamSOAPCodec.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/StringDataContentHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/SwACodec.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/TagInfoset.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/xml/XMLCodec.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/xml/XMLConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/xml/XMLMessage.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/xml/XMLPropertyBag.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/XmlDataContentHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/XMLHTTPBindingCodec.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/fault/CodeType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/fault/DetailType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/fault/ExceptionBean.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/fault/ReasonType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/fault/ServerSOAPFaultException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/fault/SOAP11Fault.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/fault/SOAP12Fault.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/fault/SOAPFaultBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/fault/SubcodeType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/fault/TextType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/handler/ClientLogicalHandlerTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/handler/ClientMessageHandlerTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/handler/ClientSOAPHandlerTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/handler/HandlerChainsModel.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/handler/HandlerException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/handler/HandlerProcessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/handler/HandlerTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/handler/LogicalMessageContextImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/handler/LogicalMessageImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/handler/MessageContextImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/handler/MessageHandlerContextImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/handler/MessageUpdatableContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/handler/PortInfoImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/handler/ServerLogicalHandlerTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/handler/ServerMessageHandlerTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/handler/ServerSOAPHandlerTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/handler/SOAPHandlerProcessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/handler/SOAPMessageContextImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/handler/XMLHandlerProcessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/AbstractHeaderImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/AbstractMessageImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/AttachmentSetImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/AttachmentUnmarshallerImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/ByteArrayAttachment.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/DataHandlerAttachment.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/DOMHeader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/DOMMessage.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/EmptyMessageImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/FaultDetailHeader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/FaultMessage.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/jaxb/AttachmentMarshallerImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/jaxb/JAXBBridgeSource.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/jaxb/JAXBDispatchMessage.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/jaxb/JAXBHeader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/jaxb/JAXBMessage.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/jaxb/MarshallerBridge.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/jaxb/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/JAXBAttachment.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/MimeAttachmentSet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/PayloadElementSniffer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/ProblemActionHeader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/RelatesToHeader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/RootElementSniffer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/saaj/SAAJHeader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/saaj/SAAJMessage.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/source/PayloadSourceMessage.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/source/ProtocolSourceMessage.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/source/SourceUtils.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/stream/OutboundStreamHeader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/stream/PayloadStreamReaderMessage.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/stream/StreamAttachment.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/stream/StreamHeader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/stream/StreamHeader11.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/stream/StreamHeader12.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/stream/StreamMessage.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/StringHeader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/Util.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/XMLReaderImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/AbstractSEIModelImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/AbstractWrapperBeanGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/CheckedExceptionImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/ExternalMetadataReader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/FieldSignature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/Injector.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/JavaMethodImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/ParameterImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/ReflectAnnotationReader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/RuntimeModeler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/RuntimeModelerException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/soap/SOAPBindingImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/SOAPSEIModel.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/Utils.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/WrapperBeanGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/WrapperParameter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/wsdl/AbstractExtensibleImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/wsdl/AbstractFeaturedObjectImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/wsdl/AbstractObjectImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/wsdl/WSDLBoundFaultImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/wsdl/WSDLBoundOperationImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/wsdl/WSDLBoundPortTypeImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/wsdl/WSDLDirectProperties.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/wsdl/WSDLFaultImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/wsdl/WSDLInputImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/wsdl/WSDLMessageImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/wsdl/WSDLModelImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/wsdl/WSDLOperationImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/wsdl/WSDLOutputImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/wsdl/WSDLPartDescriptorImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/wsdl/WSDLPartImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/wsdl/WSDLPortImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/wsdl/WSDLPortProperties.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/wsdl/WSDLPortTypeImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/wsdl/WSDLProperties.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/wsdl/WSDLServiceImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/AnnotationVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/AnnotationWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/Attribute.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/ByteVector.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/ClassAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/ClassReader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/ClassVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/ClassWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/Edge.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/FieldVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/FieldWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/Frame.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/Handler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/Item.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/Label.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/MethodAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/MethodVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/MethodWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/Opcodes.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/Type.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/AssertionSet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/AssertionValidationProcessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/ComplexAssertion.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/EffectiveAlternativeSelector.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/EffectivePolicyModifier.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/jaxws/BuilderHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/jaxws/BuilderHandlerEndpointScope.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/jaxws/BuilderHandlerMessageScope.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/jaxws/BuilderHandlerOperationScope.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/jaxws/BuilderHandlerServiceScope.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/jaxws/DefaultPolicyResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/jaxws/PolicyMapBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/jaxws/PolicyUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/jaxws/PolicyWSDLGeneratorExtension.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/jaxws/PolicyWSDLParserExtension.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/jaxws/SafePolicyReader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/jaxws/spi/PolicyFeatureConfigurator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/jaxws/spi/PolicyMapConfigurator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/jaxws/WSDLBoundFaultContainer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/NestedPolicy.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/Policy.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/PolicyAssertion.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/PolicyConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/PolicyException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/PolicyIntersector.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/PolicyMap.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/PolicyMapExtender.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/PolicyMapKey.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/PolicyMapKeyHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/PolicyMapMutator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/PolicyMapUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/PolicyMerger.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/PolicyScope.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/PolicySubject.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/privateutil/LocalizationMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/privateutil/MethodUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/privateutil/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/privateutil/PolicyLogger.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/privateutil/PolicyUtils.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/privateutil/RuntimePolicyUtilsException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/privateutil/ServiceConfigurationError.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/privateutil/ServiceFinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/SimpleAssertion.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/AssertionData.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/attach/ContextClassloaderLocal.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/attach/ExternalAttachmentsUnmarshaller.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/attach/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/CompactModelGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/DefaultPolicyAssertionCreator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/ModelNode.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/NormalizedModelGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/PolicyModelGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/PolicyModelMarshaller.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/PolicyModelTranslator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/PolicyModelUnmarshaller.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/PolicyReferenceData.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/PolicySourceModel.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/PolicySourceModelContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/wspolicy/NamespaceVersion.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/wspolicy/XmlToken.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/XmlPolicyModelMarshaller.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/XmlPolicyModelUnmarshaller.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/spi/AbstractQNameValidator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/spi/AssertionCreationException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/spi/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/spi/PolicyAssertionCreator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/spi/PolicyAssertionValidator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/spi/PrefixMapper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/subject/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/subject/PolicyMapKeyConverter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/subject/WsdlBindingSubject.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/protocol/soap/ClientMUTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/protocol/soap/MessageCreationException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/protocol/soap/MUTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/protocol/soap/ServerMUTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/protocol/soap/VersionMismatchException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/protocol/xml/XMLMessageException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/resources/AddressingMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/resources/BindingApiMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/resources/ClientMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/resources/DispatchMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/resources/EncodingMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/resources/HandlerMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/resources/HttpserverMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/resources/ManagementMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/resources/ModelerMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/resources/PolicyMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/resources/ProviderApiMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/resources/SenderMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/resources/ServerMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/resources/SoapMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/resources/StreamingMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/resources/TubelineassemblyMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/resources/UtilMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/resources/WsdlmodelMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/resources/WsservletMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/resources/XmlmessageMessages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/runtime/config/MetroConfig.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/runtime/config/ObjectFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/runtime/config/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/runtime/config/TubeFactoryConfig.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/runtime/config/TubeFactoryList.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/runtime/config/TubelineDefinition.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/runtime/config/TubelineFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/runtime/config/TubelineFeatureReader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/runtime/config/TubelineMapping.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/runtime/config/Tubelines.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/AbstractMultiInstanceResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/AbstractWebServiceContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/DefaultResourceInjector.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/DraconianValidationErrorHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/EndpointAwareTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/EndpointFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/EndpointMessageContextImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/InvokerTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/MonitorBase.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/MonitorRootService.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/provider/AsyncProviderInvokerTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/provider/MessageProviderArgumentBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/provider/ProviderArgumentsBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/provider/ProviderEndpointModel.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/provider/ProviderInvokerTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/provider/SOAPProviderArgumentBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/provider/SyncProviderInvokerTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/provider/XMLProviderArgumentBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/SDDocumentImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/sei/EndpointArgumentsBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/sei/EndpointResponseMessageBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/sei/EndpointValueSetter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/sei/Invoker.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/sei/InvokerSource.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/sei/InvokerTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/sei/MessageFiller.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/sei/SEIInvokerTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/sei/TieHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/sei/ValueGetter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/ServerPropertyConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/ServerRtException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/ServerSchemaValidationTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/ServiceDefinitionImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/SingletonResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/UnsupportedMediaException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/WSDLGenResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/WSEndpointImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/WSEndpointMOMProxy.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/BindingContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/BindingContextFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/BindingHelper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/BindingInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/DatabindingException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/DatabindingProvider.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/FieldGetter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/FieldSetter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/JAXBWrapperAccessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/MethodGetter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/MethodSetter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/OldBridge.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/PropertyAccessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/PropertyGetter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/PropertyGetterBase.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/PropertySetter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/PropertySetterBase.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/RepeatedElementBridge.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/TypeInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/Utils.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/WrapperAccessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/WrapperBridge.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/WrapperComposite.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/XMLBridge.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/ContextClassloaderLocal.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/ProviderImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/streaming/Attributes.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/streaming/DOMStreamReader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/streaming/MtomStreamWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/streaming/PrefixFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/streaming/PrefixFactoryImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/streaming/SourceReaderFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/streaming/TidyXMLStreamReader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/streaming/XMLReaderException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/streaming/XMLStreamReaderException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/streaming/XMLStreamReaderUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/streaming/XMLStreamWriterException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/streaming/XMLStreamWriterUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/DeferredTransportPipe.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/Headers.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/client/HttpClientTransport.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/client/HttpResponseProperties.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/client/HttpTransportPipe.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/DeploymentDescriptorParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/HttpAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/HttpAdapterList.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/HttpMetadataPublisher.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/ResourceLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/server/EndpointImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/server/HttpEndpoint.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/server/PortableConnectionImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/server/PortableHttpHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/server/ServerAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/server/ServerAdapterList.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/server/ServerConnectionImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/server/ServerContainer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/server/ServerMgr.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/server/WSHttpHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/WSHTTPConnection.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/ASCIIUtility.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/ByteArrayBuffer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/ByteArrayDataSource.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/CompletedFuture.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/Constants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/DOMUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/exception/JAXWSExceptionBase.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/exception/LocatableWebServiceException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/FastInfosetReflection.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/FastInfosetUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/HandlerAnnotationInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/HandlerAnnotationProcessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/InjectionPlan.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/JAXWSUtils.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/MetadataUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/NamespaceSupport.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/NoCloseInputStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/NoCloseOutputStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/pipe/AbstractSchemaValidationTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/pipe/DumpTube.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/pipe/StandalonePipeAssembler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/pipe/StandaloneTubeAssembler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/Pool.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/QNameMap.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/ReadAllStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/RuntimeVersion.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/ServiceConfigurationError.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/ServiceFinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/StreamUtils.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/StringUtils.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/UtilException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/Version.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/VersionUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/CDATA.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/ContentHandlerToXMLStreamWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/ContextClassloaderLocal.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/DummyLocation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/NamedNodeMapIterator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/NamespaceContextExAdaper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/NodeListIterator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/StAXResult.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/StAXSource.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/XMLReaderComposite.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/XMLStreamReaderFilter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/XMLStreamReaderToXMLStreamWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/XMLStreamWriterFilter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/ActionBasedOperationFinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/ActionBasedOperationSignature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/DispatchException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/OperationDispatcher.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/parser/DelegatingParserExtension.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/parser/EntityResolverWrapper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/parser/ErrorHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/parser/FoolProofParserExtension.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/parser/InaccessibleWSDLException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/parser/MemberSubmissionAddressingWSDLParserExtension.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/parser/MexEntityResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/parser/MIMEConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/parser/ParserUtil.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/parser/RuntimeWSDLParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/parser/SOAPConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/parser/W3CAddressingMetadataWSDLParserExtension.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/parser/W3CAddressingWSDLParserExtension.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/parser/WSDLConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/parser/WSDLParserExtensionContextImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/parser/WSDLParserExtensionFacade.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/PayloadQNameBasedOperationFinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/SDDocumentResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/SOAPActionBasedOperationFinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/Binding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/BindingOperationType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/Definitions.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/Documented.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/Fault.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/FaultType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/http/Address.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/http/Binding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/http/Operation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/http/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/Import.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/Message.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/OpenAtts.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/Operation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/ParamType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/Part.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/Port.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/PortType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/Service.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/soap/Body.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/soap/BodyType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/soap/Header.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/soap/HeaderFault.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/soap/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/soap/SOAPAddress.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/soap/SOAPBinding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/soap/SOAPFault.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/soap/SOAPOperation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/soap12/Body.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/soap12/BodyType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/soap12/Header.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/soap12/HeaderFault.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/soap12/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/soap12/SOAPAddress.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/soap12/SOAPBinding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/soap12/SOAPFault.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/soap12/SOAPOperation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/StartWithExtensionsType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/Types.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/xsd/Import.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/xsd/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/xsd/Schema.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/DocumentLocationResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/TXWContentHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/UsingAddressing.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/W3CAddressingMetadataWSDLGeneratorExtension.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/W3CAddressingWSDLGeneratorExtension.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/WSDLGenerator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/WSDLGeneratorExtensionFacade.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/WSDLPatcher.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/WSDLResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/WSDLOperationFinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/ForeignAttributes.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/AnnotationImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/AttGroupDeclImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/AttributeDeclImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/AttributesHolder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/AttributeUseImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/ComplexTypeImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/ComponentImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/Const.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/ContentTypeImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/DeclarationImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/ElementDecl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/EmptyImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/FacetImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/ForeignAttributesImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/IdentityConstraintImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/ListSimpleTypeImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/ModelGroupDeclImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/ModelGroupImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/NotationImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/BaseContentRef.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/DefaultAnnotationParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/DelayedRef.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/NGCCRuntimeEx.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/ParserContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/Patch.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/PatcherManager.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/SAXParserFactoryAdaptor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/SchemaDocumentImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/annotation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/attributeDeclBody.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/attributeGroupDecl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/AttributesImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/attributeUses.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/complexType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/complexType_complexContent_body.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/elementDeclBody.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/erSet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/ersSet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/facet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/foreignAttributes.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/group.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/identityConstraint.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/importDecl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/includeDecl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/modelGroupBody.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/NGCCEventReceiver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/NGCCEventSource.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/NGCCHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/NGCCInterleaveFilter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/NGCCRuntime.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/notation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/occurs.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/particle.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/qname.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/qualification.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/redefine.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/Schema.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/simpleType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/SimpleType_List.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/SimpleType_Restriction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/SimpleType_Union.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/wildcardBody.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/xpath.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/SubstGroupBaseTypeRef.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/ParticleImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/Ref.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/RestrictionSimpleTypeImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/scd/AbstractAxisImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/scd/Axis.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/scd/Iterators.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/scd/ParseException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/scd/SCDImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/scd/SCDParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/scd/SCDParserConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/scd/SCDParserTokenManager.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/scd/SimpleCharStream.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/scd/Step.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/scd/Token.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/scd/TokenMgrError.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/SchemaImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/SchemaSetImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/SimpleTypeImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/UName.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/UnionSimpleTypeImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/Util.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/util/DraconianErrorHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/util/ResourceEntityResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/util/SchemaTreeTraverser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/util/SchemaWriter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/util/Uri.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/WildcardImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/XPathImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/parser/AnnotationContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/parser/AnnotationParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/parser/AnnotationParserFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/parser/JAXPParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/parser/SchemaDocument.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/parser/XMLParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/parser/XSOMParser.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/SCD.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/ComponentNameFunction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/ContextClassloaderLocal.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/DeferedCollection.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/DomAnnotationParserFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/NameGetter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/SimpleTypeSet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/TypeClosure.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/TypeSet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/XSFinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/XSFunctionFilter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/visitor/XSContentTypeFunction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/visitor/XSContentTypeVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/visitor/XSFunction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/visitor/XSSimpleTypeFunction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/visitor/XSSimpleTypeVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/visitor/XSTermFunction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/visitor/XSTermFunctionWithParam.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/visitor/XSTermVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/visitor/XSVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/visitor/XSWildcardFunction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/visitor/XSWildcardVisitor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XmlString.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSAnnotation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSAttContainer.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSAttGroupDecl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSAttributeDecl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSAttributeUse.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSComplexType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSComponent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSContentType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSDeclaration.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSElementDecl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSFacet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSIdentityConstraint.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSListSimpleType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSModelGroup.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSModelGroupDecl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSNotation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSParticle.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSRestrictionSimpleType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSSchema.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSSchemaSet.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSSimpleType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSTerm.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSUnionSimpleType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSVariety.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSWildcard.java +@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/XSXPath.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/annotation/Generated.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/annotation/PostConstruct.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/annotation/PreDestroy.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/annotation/Resource.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/annotation/Resources.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/jws/HandlerChain.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/jws/Oneway.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/jws/soap/InitParam.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/jws/soap/SOAPBinding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/jws/soap/SOAPMessageHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/jws/soap/SOAPMessageHandlers.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/jws/WebMethod.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/jws/WebParam.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/jws/WebResult.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/jws/WebService.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/adapters/CollapsedStringAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/adapters/HexBinaryAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/adapters/NormalizedStringAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/adapters/XmlAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/adapters/XmlJavaTypeAdapter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/adapters/XmlJavaTypeAdapters.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/DomHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/W3CDomHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlAccessOrder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlAccessorOrder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlAccessorType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlAccessType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlAnyAttribute.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlAnyElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlAttachmentRef.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlAttribute.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlElementDecl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlElementRef.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlElementRefs.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlElements.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlElementWrapper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlEnum.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlEnumValue.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlID.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlIDREF.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlInlineBinaryData.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlList.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlMimeType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlMixed.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlNs.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlNsForm.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlRegistry.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlRootElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlSchema.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlSchemaType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlSchemaTypes.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlSeeAlso.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlTransient.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/XmlValue.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/attachment/AttachmentMarshaller.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/attachment/AttachmentUnmarshaller.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/Binder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/ContextFinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/DataBindingException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/DatatypeConverter.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/DatatypeConverterImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/DatatypeConverterInterface.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/Element.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/GetPropertyAction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/helpers/AbstractMarshallerImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/helpers/AbstractUnmarshallerImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/helpers/DefaultValidationEventHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/helpers/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/helpers/NotIdentifiableEventImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/helpers/ParseConversionEventImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/helpers/PrintConversionEventImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/helpers/ValidationEventImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/helpers/ValidationEventLocatorImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/JAXB.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/JAXBContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/JAXBElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/JAXBException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/JAXBIntrospector.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/JAXBPermission.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/MarshalException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/Marshaller.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/NotIdentifiableEvent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/ParseConversionEvent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/PrintConversionEvent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/PropertyException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/SchemaOutputResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/TypeConstraintException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/UnmarshalException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/Unmarshaller.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/UnmarshallerHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/util/JAXBResult.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/util/JAXBSource.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/util/Messages.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/util/ValidationEventCollector.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/ValidationEvent.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/ValidationEventHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/ValidationEventLocator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/ValidationException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/Validator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/WhiteSpaceProcessor.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/AttachmentPart.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/Detail.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/DetailEntry.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/FactoryFinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/MessageFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/MimeHeader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/MimeHeaders.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/Name.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/Node.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/SAAJMetaFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/SAAJResult.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/SOAPBody.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/SOAPBodyElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/SOAPConnection.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/SOAPConnectionFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/SOAPConstants.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/SOAPElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/SOAPElementFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/SOAPEnvelope.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/SOAPException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/SOAPFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/SOAPFault.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/SOAPFaultElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/SOAPHeader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/SOAPHeaderElement.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/SOAPMessage.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/SOAPPart.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/Text.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/Action.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/AsyncHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/Binding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/BindingProvider.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/BindingType.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/Dispatch.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/Endpoint.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/EndpointContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/EndpointReference.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/FaultAction.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/handler/Handler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/handler/HandlerResolver.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/handler/LogicalHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/handler/LogicalMessageContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/handler/MessageContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/handler/PortInfo.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/handler/soap/SOAPHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/handler/soap/SOAPMessageContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/Holder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/http/HTTPBinding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/http/HTTPException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/LogicalMessage.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/ProtocolException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/Provider.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/RequestWrapper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/RespectBinding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/RespectBindingFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/Response.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/ResponseWrapper.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/Service.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/ServiceMode.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/soap/Addressing.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/soap/AddressingFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/soap/MTOM.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/soap/MTOMFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/soap/SOAPBinding.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/soap/SOAPFaultException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/spi/FactoryFinder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/spi/http/HttpContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/spi/http/HttpExchange.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/spi/http/HttpHandler.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/spi/http/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/spi/Invoker.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/spi/Provider.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/spi/ServiceDelegate.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/spi/WebServiceFeatureAnnotation.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/WebEndpoint.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/WebFault.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/WebServiceClient.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/WebServiceContext.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/WebServiceException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/WebServiceFeature.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/WebServicePermission.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/WebServiceProvider.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/WebServiceRef.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/WebServiceRefs.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/wsaddressing/package-info.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/wsaddressing/W3CEndpointReference.java +@OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/wsaddressing/W3CEndpointReferenceBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/org/relaxng/datatype/Datatype.java +@OPENJDK@/jaxws/src/share/jaxws_classes/org/relaxng/datatype/DatatypeBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/org/relaxng/datatype/DatatypeException.java +@OPENJDK@/jaxws/src/share/jaxws_classes/org/relaxng/datatype/DatatypeLibrary.java +@OPENJDK@/jaxws/src/share/jaxws_classes/org/relaxng/datatype/DatatypeLibraryFactory.java +@OPENJDK@/jaxws/src/share/jaxws_classes/org/relaxng/datatype/DatatypeStreamingValidator.java +@OPENJDK@/jaxws/src/share/jaxws_classes/org/relaxng/datatype/helpers/DatatypeLibraryLoader.java +@OPENJDK@/jaxws/src/share/jaxws_classes/org/relaxng/datatype/helpers/ParameterlessDatatypeBuilder.java +@OPENJDK@/jaxws/src/share/jaxws_classes/org/relaxng/datatype/helpers/StreamingValidatorImpl.java +@OPENJDK@/jaxws/src/share/jaxws_classes/org/relaxng/datatype/ValidationContext.java +@OPENJDK@/jdk/src/share/classes/com/sun/awt/AWTUtilities.java +@OPENJDK@/jdk/src/share/classes/com/sun/awt/SecurityWarning.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/AccessorElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/ArrayElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/BooleanElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/ByteElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/CharElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/ClassElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/DocumentHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/DoubleElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/ElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/FalseElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/FieldElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/FloatElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/IntElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/JavaElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/LongElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/MethodElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/NewElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/NullElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/ObjectElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/PropertyElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/ShortElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/StringElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/TrueElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/ValueObject.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/ValueObjectImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/VarElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/VoidElementHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/editors/BooleanEditor.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/editors/ByteEditor.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/editors/ColorEditor.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/editors/DoubleEditor.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/editors/EnumEditor.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/editors/FloatEditor.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/editors/FontEditor.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/editors/IntegerEditor.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/editors/LongEditor.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/editors/NumberEditor.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/editors/ShortEditor.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/editors/StringEditor.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/finder/AbstractFinder.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/finder/BeanInfoFinder.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/finder/ClassFinder.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/finder/ConstructorFinder.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/finder/FieldFinder.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/finder/InstanceFinder.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/finder/PersistenceDelegateFinder.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/finder/PrimitiveTypeMap.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/finder/PrimitiveWrapperMap.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/finder/PropertyEditorFinder.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/finder/Signature.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/finder/SignatureException.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/infos/ComponentBeanInfo.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/TypeResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/util/Cache.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/WeakCache.java +@OPENJDK@/jdk/src/share/classes/com/sun/beans/WildcardTypeImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/AESCipher.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/AESConstants.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/AESCrypt.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/AESKeyGenerator.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/AESParameters.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/AESWrapCipher.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/ai.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/ARCFOURCipher.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/BlockCipherParamsCore.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/BlowfishCipher.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/BlowfishConstants.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/BlowfishCrypt.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/BlowfishKeyGenerator.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/BlowfishParameters.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/CipherBlockChaining.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/CipherCore.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/CipherFeedback.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/CipherTextStealing.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/CipherWithWrappingSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/ConstructKeys.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/CounterMode.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/DESCipher.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/DESConstants.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/DESCrypt.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/DESedeCipher.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/DESedeCrypt.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/DESedeKey.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/DESedeKeyFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/DESedeKeyGenerator.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/DESedeParameters.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/DESKey.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/DESKeyFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/DESKeyGenerator.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/DESParameters.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/DHKeyFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/DHParameterGenerator.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/DHParameters.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/DHPrivateKey.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/DHPublicKey.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/EncryptedPrivateKeyInfo.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/FeedbackCipher.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/GaloisCounterMode.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/GCMParameters.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/GCTR.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/GHASH.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/HmacCore.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/HmacMD5.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/HmacMD5KeyGenerator.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/HmacPKCS12PBESHA1.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/HmacSHA1.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/HmacSHA1KeyGenerator.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/ISO10126Padding.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/JceKeyStore.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/KeyGeneratorCore.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/KeyProtector.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/OAEPParameters.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/OutputFeedback.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/Padding.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/PBECipherCore.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/PBEKey.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/PBEKeyFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/PBEParameters.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/PBES1Core.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/PBES2Core.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/PBES2Parameters.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/PBEWithMD5AndDESCipher.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/PBEWithMD5AndTripleDESCipher.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/PBKDF2Core.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/PBKDF2HmacSHA1Factory.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/PBMAC1Core.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/PCBC.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/PKCS5Padding.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/PrivateKeyInfo.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/RC2Cipher.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/RC2Crypt.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/RC2Parameters.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/RSACipher.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/SslMacCore.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/SunJCE.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/SymmetricCipher.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/TlsKeyMaterialGenerator.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/TlsMasterSecretGenerator.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/TlsPrfGenerator.java +@OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/TlsRsaPremasterSecretGenerator.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPCompressionTypes.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPConstants.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageReaderSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriter.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriterSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPMetadataFormat.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPMetadataFormatResources.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/common/BitFile.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/common/BogusColorSpace.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/common/I18N.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/common/I18NImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/common/ImageUtil.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/common/InputStreamAdapter.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/common/LZWCompressor.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/common/LZWStringTable.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/common/PaletteBuilder.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/common/ReaderUtil.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/common/StandardMetadataFormat.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/common/StandardMetadataFormatResources.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/common/SubImageInputStream.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadata.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadataFormat.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadataFormatResources.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReaderSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageWriter.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageWriterSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFMetadata.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFStreamMetadata.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFStreamMetadataFormat.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFStreamMetadataFormatResources.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFWritableImageMetadata.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFWritableStreamMetadata.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReaderSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReaderSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriterSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGMetadataFormat.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGMetadataFormatResources.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/png/RowFilter.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageWriter.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageWriterSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPMetadata.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPMetadataFormat.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/spi/FileImageInputStreamSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/spi/FileImageOutputStreamSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/spi/InputStreamImageInputStreamSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/spi/OutputStreamImageOutputStreamSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/spi/RAFImageInputStreamSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/spi/RAFImageOutputStreamSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/stream/CloseableDisposerRecord.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/stream/StreamCloser.java +@OPENJDK@/jdk/src/share/classes/com/sun/imageio/stream/StreamFinalizer.java +@OPENJDK@/jdk/src/share/classes/com/sun/jarsigner/ContentSigner.java +@OPENJDK@/jdk/src/share/classes/com/sun/jarsigner/ContentSignerParameters.java +@OPENJDK@/jdk/src/share/classes/com/sun/jarsigner/package-info.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/browser/dom/DOMAccessException.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/browser/dom/DOMAccessor.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/browser/dom/DOMAction.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/browser/dom/DOMService.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/browser/dom/DOMServiceProvider.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/browser/dom/DOMUnsupportedException.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/browser/net/ProxyInfo.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/browser/net/ProxyService.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/browser/net/ProxyServiceProvider.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/Painter.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifBorders.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifButtonListener.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifButtonUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifCheckBoxMenuItemUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifCheckBoxUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifComboBoxUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifDesktopIconUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifDesktopPaneUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifEditorPaneUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifGraphicsUtils.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifIconFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameTitlePane.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifLabelUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifLookAndFeel.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifMenuBarUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifMenuItemUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifMenuMouseListener.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifMenuMouseMotionListener.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifMenuUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifOptionPaneUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifPasswordFieldUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifPopupMenuSeparatorUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifPopupMenuUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifProgressBarUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifRadioButtonMenuItemUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifRadioButtonUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifScrollBarButton.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifScrollBarUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifScrollPaneUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifSeparatorUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifSliderUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifSplitPaneDivider.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifSplitPaneUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifTabbedPaneUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifTextAreaUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifTextFieldUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifTextPaneUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifTextUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifToggleButtonUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifTreeCellRenderer.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifTreeUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/nimbus/AbstractRegionPainter.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/nimbus/NimbusLookAndFeel.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/AnimationController.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/DesktopProperty.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/TMSchema.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsBorders.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsButtonListener.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsButtonUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsClassicLookAndFeel.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsComboBoxUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsDesktopIconUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsDesktopManager.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsDesktopPaneUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsEditorPaneUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsGraphicsUtils.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLabelUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsMenuBarUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUIAccessor.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsOptionPaneUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsPasswordFieldUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuSeparatorUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsPopupWindow.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsProgressBarUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsRootPaneUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsScrollBarUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsScrollPaneUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsSeparatorUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsSliderUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsSpinnerUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsSplitPaneDivider.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsSplitPaneUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsTabbedPaneUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsTableHeaderUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsTextAreaUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsTextFieldUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsTextPaneUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsTextUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsToggleButtonUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsToolBarSeparatorUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsToolBarUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsTreeUI.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/XPStyle.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/swing/SwingUtilities3.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/AdaptiveCoding.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassWriter.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/Code.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/Coding.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/CodingChooser.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/CodingMethod.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/Driver.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/DriverResource.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/DriverResource_ja.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/DriverResource_zh_CN.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/FixedList.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/Fixups.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/Histogram.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/Package.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/PopulationCoding.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/PropMap.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/TLGlobals.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/AbsentInformationException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/Accessible.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/ArrayReference.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/ArrayType.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/BooleanType.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/BooleanValue.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/Bootstrap.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/ByteType.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/ByteValue.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/CharType.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/CharValue.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/ClassLoaderReference.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/ClassNotLoadedException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/ClassNotPreparedException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/ClassObjectReference.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/ClassType.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/connect/AttachingConnector.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/connect/Connector.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/connect/IllegalConnectorArgumentsException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/connect/LaunchingConnector.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/connect/ListeningConnector.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/connect/spi/ClosedConnectionException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/connect/spi/Connection.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/connect/spi/TransportService.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/connect/Transport.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/connect/TransportTimeoutException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/connect/VMStartException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/DoubleType.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/DoubleValue.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/AccessWatchpointEvent.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/BreakpointEvent.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/ClassPrepareEvent.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/ClassUnloadEvent.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/Event.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/EventIterator.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/EventQueue.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/EventSet.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/ExceptionEvent.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/LocatableEvent.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/MethodEntryEvent.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/MethodExitEvent.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/ModificationWatchpointEvent.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/MonitorContendedEnteredEvent.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/MonitorContendedEnterEvent.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/MonitorWaitedEvent.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/MonitorWaitEvent.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/StepEvent.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/ThreadDeathEvent.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/ThreadStartEvent.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/VMDeathEvent.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/VMDisconnectEvent.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/VMStartEvent.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/WatchpointEvent.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/Field.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/FloatType.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/FloatValue.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/IncompatibleThreadStateException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/InconsistentDebugInfoException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/IntegerType.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/IntegerValue.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/InterfaceType.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/InternalException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/InvalidCodeIndexException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/InvalidLineNumberException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/InvalidStackFrameException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/InvalidTypeException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/InvocationException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/JDIPermission.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/LocalVariable.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/Locatable.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/Location.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/LongType.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/LongValue.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/Method.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/Mirror.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/MonitorInfo.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/NativeMethodException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/ObjectCollectedException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/ObjectReference.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/PathSearchingVirtualMachine.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/PrimitiveType.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/PrimitiveValue.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/ReferenceType.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/AccessWatchpointRequest.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/BreakpointRequest.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/ClassPrepareRequest.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/ClassUnloadRequest.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/DuplicateRequestException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/EventRequest.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/EventRequestManager.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/ExceptionRequest.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/InvalidRequestStateException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/MethodEntryRequest.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/MethodExitRequest.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/ModificationWatchpointRequest.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/MonitorContendedEnteredRequest.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/MonitorContendedEnterRequest.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/MonitorWaitedRequest.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/MonitorWaitRequest.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/StepRequest.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/ThreadDeathRequest.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/ThreadStartRequest.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/VMDeathRequest.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/WatchpointRequest.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/ShortType.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/ShortValue.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/StackFrame.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/StringReference.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/ThreadGroupReference.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/ThreadReference.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/Type.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/TypeComponent.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/Value.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/VirtualMachine.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/VirtualMachineManager.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/VMCannotBeModifiedException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/VMDisconnectedException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/VMMismatchException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/VMOutOfMemoryException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/VoidType.java +@OPENJDK@/jdk/src/share/classes/com/sun/jdi/VoidValue.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/defaults/JmxProperties.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/defaults/ServiceName.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/interceptor/MBeanServerInterceptor.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/ConvertingMethod.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/DescriptorCache.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/DynamicMBean2.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/GetPropertyAction.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServerBuilder.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanServerDelegateImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/ModifiableClassLoaderRepository.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanLookup.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanMapping.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanMappingFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanProxy.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanSupport.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/NamedObject.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/ObjectInputStreamWithLoader.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/PerInterface.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/Repository.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/SecureClassLoaderRepository.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanIntrospector.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanSupport.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/SunJmxMBeanServer.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/Util.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/WeakIdentityHashMap.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/internal/ArrayNotificationBuffer.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/internal/ArrayQueue.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/internal/ClientCommunicatorAdmin.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/internal/ClientListenerInfo.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/internal/IIOPHelper.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/internal/IIOPProxy.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/internal/NotificationBuffer.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/internal/NotificationBufferFilter.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/internal/ProxyRef.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/internal/RMIExporter.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/internal/ServerCommunicatorAdmin.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/internal/Unmarshal.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/protocol/iiop/ClientProvider.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/protocol/iiop/IIOPProxyImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/protocol/iiop/ProxyInputStream.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/protocol/iiop/ServerProvider.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/protocol/rmi/ClientProvider.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/protocol/rmi/ServerProvider.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/security/FileLoginModule.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/security/JMXPluggableAuthenticator.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/security/JMXSubjectDomainCombiner.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/security/MBeanServerAccessController.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/security/MBeanServerFileAccessController.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/security/NotificationAccessController.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/security/SubjectDelegator.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/util/ClassLoaderWithRepository.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/util/ClassLogger.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java +@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/util/OrderClassLoaders.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/cosnaming/CNBindingEnumeration.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/cosnaming/CNCtx.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/cosnaming/CNCtxFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/cosnaming/CNNameParser.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/cosnaming/CorbanameUrl.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/cosnaming/ExceptionMapper.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/cosnaming/IiopUrl.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/cosnaming/OrbReuseTracker.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/cosnaming/RemoteToCorba.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/dns/DnsClient.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/dns/DnsContext.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/dns/DnsContextFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/dns/DnsName.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/dns/DnsNameParser.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/dns/DnsUrl.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/dns/Header.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/dns/NameNode.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/dns/Resolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/dns/ResourceRecord.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/dns/ResourceRecords.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/dns/ZoneNode.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/AbstractLdapNamingEnumeration.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/BasicControl.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/Ber.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/BerDecoder.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/BerEncoder.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/BindingWithControls.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/ClientId.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/Connection.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/DefaultResponseControlFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/DigestClientId.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/EntryChangeResponseControl.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/EventQueue.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/EventSupport.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/Filter.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/LdapAttribute.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/LdapBindingEnumeration.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/LdapClient.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/LdapClientFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/LdapCtx.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/LdapCtxFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/LdapEntry.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/LdapName.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/LdapNameParser.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/LdapNamingEnumeration.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/LdapPoolManager.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/LdapReferralContext.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/LdapReferralException.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/LdapRequest.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/LdapResult.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/LdapSchemaCtx.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/LdapSchemaParser.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/LdapSearchEnumeration.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/LdapURL.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/ManageReferralControl.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/NameClassPairWithControls.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/NamingEventNotifier.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/NotifierArgs.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/Obj.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/PersistentSearchControl.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/pool/ConnectionDesc.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/pool/Connections.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/pool/ConnectionsRef.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/pool/ConnectionsWeakRef.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/pool/Pool.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/pool/PoolCallback.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/pool/PoolCleaner.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/pool/PooledConnection.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/pool/PooledConnectionFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/ReferralEnumeration.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/sasl/DefaultCallbackHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/sasl/LdapSasl.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/sasl/SaslInputStream.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/sasl/SaslOutputStream.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/SearchResultWithControls.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/ServiceLocator.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/SimpleClientId.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/UnsolicitedResponseImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/VersionHelper.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/VersionHelper12.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/rmi/registry/ReferenceWrapper.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/rmi/registry/RegistryContextFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/rmi/registry/RemoteReference.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/AtomicContext.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/AtomicDirContext.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/ComponentContext.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/ComponentDirContext.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/Continuation.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/HeadTail.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/PartialCompositeContext.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/PartialCompositeDirContext.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/StringHeadTail.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/dir/AttrFilter.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/dir/ContainmentFilter.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/dir/ContextEnumerator.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/dir/DirSearch.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/dir/HierMemDirCtx.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/dir/LazySearchEnumerationImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/dir/SearchFilter.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/url/GenericURLContext.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/url/GenericURLDirContext.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/url/Uri.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/url/UrlUtil.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/url/corbaname/corbanameURLContextFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/url/dns/dnsURLContext.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/url/dns/dnsURLContextFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/url/iiop/iiopURLContext.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/url/iiop/iiopURLContextFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/url/iiopname/iiopnameURLContextFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/url/ldap/ldapURLContext.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/url/ldap/ldapURLContextFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/url/ldaps/ldapsURLContextFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/url/rmi/rmiURLContext.java +@OPENJDK@/jdk/src/share/classes/com/sun/jndi/url/rmi/rmiURLContextFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/management/DiagnosticCommandMBean.java +@OPENJDK@/jdk/src/share/classes/com/sun/management/GarbageCollectionNotificationInfo.java +@OPENJDK@/jdk/src/share/classes/com/sun/management/GarbageCollectorMXBean.java +@OPENJDK@/jdk/src/share/classes/com/sun/management/GcInfo.java +@OPENJDK@/jdk/src/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java +@OPENJDK@/jdk/src/share/classes/com/sun/management/OperatingSystemMXBean.java +@OPENJDK@/jdk/src/share/classes/com/sun/management/package-info.java +@OPENJDK@/jdk/src/share/classes/com/sun/management/ThreadMXBean.java +@OPENJDK@/jdk/src/share/classes/com/sun/management/UnixOperatingSystemMXBean.java +@OPENJDK@/jdk/src/share/classes/com/sun/management/VMOption.java +@OPENJDK@/jdk/src/share/classes/com/sun/media/sound/MidiDeviceReceiverEnvelope.java +@OPENJDK@/jdk/src/share/classes/com/sun/media/sound/MidiDeviceTransmitterEnvelope.java +@OPENJDK@/jdk/src/share/classes/com/sun/naming/internal/FactoryEnumeration.java +@OPENJDK@/jdk/src/share/classes/com/sun/naming/internal/NamedWeakReference.java +@OPENJDK@/jdk/src/share/classes/com/sun/naming/internal/ResourceManager.java +@OPENJDK@/jdk/src/share/classes/com/sun/naming/internal/VersionHelper.java +@OPENJDK@/jdk/src/share/classes/com/sun/naming/internal/VersionHelper12.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/httpserver/Authenticator.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/httpserver/BasicAuthenticator.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/httpserver/Filter.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/httpserver/Headers.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/httpserver/HttpContext.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/httpserver/HttpExchange.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/httpserver/HttpHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/httpserver/HttpPrincipal.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/httpserver/HttpsConfigurator.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/httpserver/HttpServer.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/httpserver/HttpsExchange.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/httpserver/HttpsParameters.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/httpserver/HttpsServer.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/httpserver/package-info.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/httpserver/spi/HttpServerProvider.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/httpserver/spi/package-info.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/HostnameVerifier.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/HttpsURLConnection.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/internal/ssl/Provider.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/internal/ssl/X509ExtendedTrustManager.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/internal/www/protocol/https/DelegateHttpsURLConnection.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/internal/www/protocol/https/Handler.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/KeyManager.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/KeyManagerFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/KeyManagerFactorySpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/SSLContext.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/SSLContextSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/SSLPermission.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/SSLSecurity.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/TrustManager.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/TrustManagerFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/TrustManagerFactorySpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/X509KeyManager.java +@OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/X509TrustManager.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/file/ExtendedCopyOption.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/file/ExtendedOpenOption.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/file/ExtendedWatchEventModifier.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/file/SensitivityWatchEventModifier.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/sctp/AbstractNotificationHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/sctp/Association.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/sctp/AssociationChangeNotification.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/sctp/HandlerResult.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/sctp/IllegalReceiveException.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/sctp/IllegalUnbindException.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/sctp/InvalidStreamException.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/sctp/MessageInfo.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/sctp/Notification.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/sctp/NotificationHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/sctp/package-info.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/sctp/PeerAddressChangeNotification.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/sctp/SctpChannel.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/sctp/SctpMultiChannel.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/sctp/SctpServerChannel.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/sctp/SctpSocketOption.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/sctp/SctpStandardSocketOptions.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/sctp/SendFailedNotification.java +@OPENJDK@/jdk/src/share/classes/com/sun/nio/sctp/ShutdownNotification.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/Algorithm.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/ClassLoaderUtils.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureBaseRSA.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureDSA.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/JCEMapper.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/MessageDigestAlgorithm.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithmSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/CanonicalizationException.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/CanonicalizerSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/helper/AttrCompare.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/helper/C14nHelper.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer11.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer11_OmitComments.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer11_WithComments.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315Excl.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315ExclOmitComments.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315ExclWithComments.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315OmitComments.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315WithComments.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerBase.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerPhysical.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/NameSpaceSymbTable.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/UtfHelpper.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/InvalidCanonicalizerException.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/encryption/AbstractSerializer.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/encryption/AgreementMethod.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/encryption/CipherData.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/encryption/CipherReference.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/encryption/CipherValue.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/encryption/DocumentSerializer.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/encryption/EncryptedData.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/encryption/EncryptedKey.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/encryption/EncryptedType.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/encryption/EncryptionMethod.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/encryption/EncryptionProperties.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/encryption/EncryptionProperty.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/encryption/Reference.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/encryption/ReferenceList.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/encryption/Serializer.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/encryption/Transforms.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/encryption/XMLCipher.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/encryption/XMLCipherInput.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/encryption/XMLCipherParameters.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/encryption/XMLEncryptionException.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/exceptions/AlgorithmAlreadyRegisteredException.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/exceptions/Base64DecodingException.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/exceptions/XMLSecurityException.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/exceptions/XMLSecurityRuntimeException.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/Init.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/DEREncodedKeyValue.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/KeyInfoContent.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/KeyInfoReference.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/KeyName.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/KeyValue.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/keyvalues/DSAKeyValue.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/keyvalues/KeyValueContent.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/keyvalues/RSAKeyValue.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/MgmtData.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/PGPData.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/RetrievalMethod.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/SPKIData.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/XMLX509Certificate.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/XMLX509CRL.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/XMLX509DataContent.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/XMLX509Digest.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/XMLX509IssuerSerial.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/XMLX509SKI.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/XMLX509SubjectName.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/X509Data.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/ContentHandlerAlreadyRegisteredException.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/KeyInfo.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/DEREncodedKeyValueResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/DSAKeyValueResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/EncryptedKeyResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/KeyInfoReferenceResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/PrivateKeyResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/RetrievalMethodResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/RSAKeyValueResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/SecretKeyResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/SingleKeyResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/X509CertificateResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/X509DigestResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/X509IssuerSerialResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/X509SKIResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/X509SubjectNameResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/InvalidKeyResolverException.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolverException.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolverSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/KeyUtils.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/CertsInFilesystemDirectoryResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/KeyStoreResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/SingleCertificateResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/StorageResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/StorageResolverException.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/StorageResolverSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/signature/InvalidDigestValueException.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/signature/InvalidSignatureValueException.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/signature/Manifest.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/signature/MissingResourceFailureException.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/signature/NodeFilter.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/signature/ObjectContainer.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/signature/Reference.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/signature/reference/ReferenceData.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/signature/reference/ReferenceNodeSetData.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/signature/reference/ReferenceOctetStreamData.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/signature/reference/ReferenceSubTreeData.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/signature/ReferenceNotInitializedException.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/signature/SignatureProperties.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/signature/SignatureProperty.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/signature/SignedInfo.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignature.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignatureException.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignatureInput.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignatureInputDebugger.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/ClassLoaderUtils.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/FuncHere.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformBase64Decode.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14N.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14N11.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14N11_WithComments.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14NExclusive.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14NExclusiveWithComments.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14NWithComments.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformEnvelopedSignature.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXPath.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXPath2Filter.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXPointer.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXSLT.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/InvalidTransformException.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/params/InclusiveNamespaces.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/params/XPath2FilterContainer.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/params/XPath2FilterContainer04.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/params/XPathContainer.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/params/XPathFilterCHGPContainer.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/Transform.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/TransformationException.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/TransformParam.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/Transforms.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/TransformSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/Base64.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/ClassLoaderUtils.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/Constants.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/DigesterOutputStream.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/DOMNamespaceContext.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementChecker.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementCheckerImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementProxy.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/EncryptionConstants.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/EncryptionElementProxy.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/HelperNodeList.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/I18n.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/IdResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/IgnoreAllErrorHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/JavaUtils.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/JDKXPathAPI.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/JDKXPathFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverAnonymous.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverDirectHTTP.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverFragment.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverLocalFilesystem.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverXPointer.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolverContext.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolverException.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolverSpi.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/RFC2253Parser.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/Signature11ElementProxy.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/SignatureElementProxy.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/SignerOutputStream.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/UnsyncBufferedOutputStream.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/UnsyncByteArrayOutputStream.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/XalanXPathAPI.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/XalanXPathFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/XPathAPI.java +@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/XPathFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/pept/Delegate.java +@OPENJDK@/jdk/src/share/classes/com/sun/pept/encoding/Decoder.java +@OPENJDK@/jdk/src/share/classes/com/sun/pept/encoding/Encoder.java +@OPENJDK@/jdk/src/share/classes/com/sun/pept/ept/Acceptor.java +@OPENJDK@/jdk/src/share/classes/com/sun/pept/ept/ContactInfo.java +@OPENJDK@/jdk/src/share/classes/com/sun/pept/ept/ContactInfoList.java +@OPENJDK@/jdk/src/share/classes/com/sun/pept/ept/ContactInfoListIterator.java +@OPENJDK@/jdk/src/share/classes/com/sun/pept/ept/EPTFactory.java +@OPENJDK@/jdk/src/share/classes/com/sun/pept/ept/MessageInfo.java +@OPENJDK@/jdk/src/share/classes/com/sun/pept/presentation/MessageStruct.java +@OPENJDK@/jdk/src/share/classes/com/sun/pept/presentation/Stub.java +@OPENJDK@/jdk/src/share/classes/com/sun/pept/presentation/TargetFinder.java +@OPENJDK@/jdk/src/share/classes/com/sun/pept/presentation/Tie.java +@OPENJDK@/jdk/src/share/classes/com/sun/pept/protocol/Interceptors.java +@OPENJDK@/jdk/src/share/classes/com/sun/pept/protocol/MessageDispatcher.java +@OPENJDK@/jdk/src/share/classes/com/sun/pept/transport/Connection.java +@OPENJDK@/jdk/src/share/classes/com/sun/rmi/rmid/ExecOptionPermission.java +@OPENJDK@/jdk/src/share/classes/com/sun/rmi/rmid/ExecPermission.java +@OPENJDK@/jdk/src/share/classes/com/sun/rowset/CachedRowSetImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/rowset/FilteredRowSetImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/rowset/internal/BaseRow.java +@OPENJDK@/jdk/src/share/classes/com/sun/rowset/internal/CachedRowSetReader.java +@OPENJDK@/jdk/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java +@OPENJDK@/jdk/src/share/classes/com/sun/rowset/internal/InsertRow.java +@OPENJDK@/jdk/src/share/classes/com/sun/rowset/internal/Row.java +@OPENJDK@/jdk/src/share/classes/com/sun/rowset/internal/SyncResolverImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/rowset/internal/WebRowSetXmlReader.java +@OPENJDK@/jdk/src/share/classes/com/sun/rowset/internal/WebRowSetXmlWriter.java +@OPENJDK@/jdk/src/share/classes/com/sun/rowset/internal/XmlErrorHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/rowset/internal/XmlReaderContentHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/rowset/internal/XmlResolver.java +@OPENJDK@/jdk/src/share/classes/com/sun/rowset/JdbcRowSetImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/rowset/JdbcRowSetResourceBundle.java +@OPENJDK@/jdk/src/share/classes/com/sun/rowset/JoinRowSetImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/rowset/providers/RIOptimisticProvider.java +@OPENJDK@/jdk/src/share/classes/com/sun/rowset/providers/RIXMLProvider.java +@OPENJDK@/jdk/src/share/classes/com/sun/rowset/RowSetFactoryImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/rowset/WebRowSetImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/callback/DialogCallbackHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/callback/package-info.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/callback/TextCallbackHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/LdapPrincipal.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/login/ConfigFile.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/login/package-info.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/module/Crypt.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/module/JndiLoginModule.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/module/KeyStoreLoginModule.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/module/LdapLoginModule.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/module/NTLoginModule.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/module/NTSystem.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/module/package-info.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/NTDomainPrincipal.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/NTNumericCredential.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/NTSid.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/NTSidDomainPrincipal.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/NTSidGroupPrincipal.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/NTSidPrimaryGroupPrincipal.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/NTSidUserPrincipal.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/NTUserPrincipal.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/package-info.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/PolicyFile.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/PrincipalComparator.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/SolarisNumericGroupPrincipal.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/SolarisNumericUserPrincipal.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/SolarisPrincipal.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/UnixNumericGroupPrincipal.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/UnixNumericUserPrincipal.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/UnixPrincipal.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/UserPrincipal.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/auth/X500Principal.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/cert/internal/x509/X509V1CertImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/jgss/AuthorizationDataEntry.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/jgss/ExtendedGSSContext.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/jgss/ExtendedGSSCredential.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/jgss/GSSUtil.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/jgss/InquireSecContextPermission.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/jgss/InquireType.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/jgss/package-info.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/ntlm/Client.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/ntlm/NTLM.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/ntlm/NTLMException.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/ntlm/Server.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/ntlm/Version.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/ClientFactoryImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/CramMD5Base.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/CramMD5Client.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/CramMD5Server.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/digest/DigestMD5Base.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/digest/DigestMD5Client.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/digest/DigestMD5Server.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/digest/FactoryImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/digest/SecurityCtx.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/ExternalClient.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/gsskerb/FactoryImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Base.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Client.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Server.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/ntlm/FactoryImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/ntlm/NTLMClient.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/ntlm/NTLMServer.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/PlainClient.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/Provider.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/ServerFactoryImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/util/AbstractSaslImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/util/PolicyUtils.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/attach/AgentInitializationException.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/attach/AgentLoadException.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/attach/AttachNotSupportedException.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/attach/AttachOperationFailedException.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/attach/AttachPermission.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/attach/spi/AttachProvider.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/attach/VirtualMachine.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/attach/VirtualMachineDescriptor.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/AbstractLauncher.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/ArrayReferenceImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/ArrayTypeImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/BaseLineInfo.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/BooleanTypeImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/BooleanValueImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/ByteTypeImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/ByteValueImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/CharTypeImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/CharValueImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/ClassLoaderReferenceImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/ClassObjectReferenceImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/ClassTypeImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/CommandSender.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/ConcreteMethodImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/ConnectorImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/DoubleTypeImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/DoubleValueImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/EventQueueImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/EventRequestManagerImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/EventSetImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/FieldImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/FloatTypeImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/FloatValueImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/GenericAttachingConnector.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/GenericListeningConnector.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/IntegerTypeImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/IntegerValueImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/InternalEventHandler.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/InvokableTypeImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/JDWPException.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/JNITypeParser.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/LineInfo.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/LocalVariableImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/LocationImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/LockObject.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/LongTypeImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/LongValueImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/MethodImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/MirrorImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/MonitorInfoImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/NonConcreteMethodImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/ObsoleteMethodImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/Packet.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/PacketStream.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/PrimitiveTypeImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/PrimitiveValueImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/ProcessAttachingConnector.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/RawCommandLineLauncher.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/ReferenceTypeImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/SDE.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/ShortTypeImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/ShortValueImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/SocketAttachingConnector.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/SocketListeningConnector.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/SocketTransportService.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/StackFrameImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/StratumLineInfo.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/StringReferenceImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/SunCommandLineLauncher.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/TargetVM.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/ThreadAction.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/ThreadGroupReferenceImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/ThreadListener.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/ThreadReferenceImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/TypeComponentImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/TypeImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/ValueContainer.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/ValueImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/VirtualMachineManagerService.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/VMAction.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/VMListener.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/VMModifiers.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/VMState.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/VoidTypeImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/VoidValueImpl.java +@OPENJDK@/jdk/src/share/classes/com/sun/tools/script/shell/Main.java +@OPENJDK@/jdk/src/share/classes/java/applet/Applet.java +@OPENJDK@/jdk/src/share/classes/java/applet/AppletContext.java +@OPENJDK@/jdk/src/share/classes/java/applet/AppletStub.java +@OPENJDK@/jdk/src/share/classes/java/applet/AudioClip.java +@OPENJDK@/jdk/src/share/classes/java/awt/ActiveEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/Adjustable.java +@OPENJDK@/jdk/src/share/classes/java/awt/AlphaComposite.java +@OPENJDK@/jdk/src/share/classes/java/awt/AttributeValue.java +@OPENJDK@/jdk/src/share/classes/java/awt/AWTError.java +@OPENJDK@/jdk/src/share/classes/java/awt/AWTEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/AWTEventMulticaster.java +@OPENJDK@/jdk/src/share/classes/java/awt/AWTException.java +@OPENJDK@/jdk/src/share/classes/java/awt/AWTKeyStroke.java +@OPENJDK@/jdk/src/share/classes/java/awt/AWTPermission.java +@OPENJDK@/jdk/src/share/classes/java/awt/BasicStroke.java +@OPENJDK@/jdk/src/share/classes/java/awt/BorderLayout.java +@OPENJDK@/jdk/src/share/classes/java/awt/BufferCapabilities.java +@OPENJDK@/jdk/src/share/classes/java/awt/Button.java +@OPENJDK@/jdk/src/share/classes/java/awt/Canvas.java +@OPENJDK@/jdk/src/share/classes/java/awt/CardLayout.java +@OPENJDK@/jdk/src/share/classes/java/awt/Checkbox.java +@OPENJDK@/jdk/src/share/classes/java/awt/CheckboxGroup.java +@OPENJDK@/jdk/src/share/classes/java/awt/CheckboxMenuItem.java +@OPENJDK@/jdk/src/share/classes/java/awt/Choice.java +@OPENJDK@/jdk/src/share/classes/java/awt/Color.java +@OPENJDK@/jdk/src/share/classes/java/awt/color/CMMException.java +@OPENJDK@/jdk/src/share/classes/java/awt/color/ColorSpace.java +@OPENJDK@/jdk/src/share/classes/java/awt/color/ICC_Profile.java +@OPENJDK@/jdk/src/share/classes/java/awt/color/ICC_ProfileGray.java +@OPENJDK@/jdk/src/share/classes/java/awt/color/ICC_ProfileRGB.java +@OPENJDK@/jdk/src/share/classes/java/awt/color/ProfileDataException.java +@OPENJDK@/jdk/src/share/classes/java/awt/ColorPaintContext.java +@OPENJDK@/jdk/src/share/classes/java/awt/Component.java +@OPENJDK@/jdk/src/share/classes/java/awt/ComponentOrientation.java +@OPENJDK@/jdk/src/share/classes/java/awt/Composite.java +@OPENJDK@/jdk/src/share/classes/java/awt/CompositeContext.java +@OPENJDK@/jdk/src/share/classes/java/awt/Conditional.java +@OPENJDK@/jdk/src/share/classes/java/awt/Container.java +@OPENJDK@/jdk/src/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java +@OPENJDK@/jdk/src/share/classes/java/awt/Cursor.java +@OPENJDK@/jdk/src/share/classes/java/awt/datatransfer/Clipboard.java +@OPENJDK@/jdk/src/share/classes/java/awt/datatransfer/ClipboardOwner.java +@OPENJDK@/jdk/src/share/classes/java/awt/datatransfer/DataFlavor.java +@OPENJDK@/jdk/src/share/classes/java/awt/datatransfer/FlavorEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/datatransfer/FlavorListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/datatransfer/FlavorMap.java +@OPENJDK@/jdk/src/share/classes/java/awt/datatransfer/FlavorTable.java +@OPENJDK@/jdk/src/share/classes/java/awt/datatransfer/MimeType.java +@OPENJDK@/jdk/src/share/classes/java/awt/datatransfer/MimeTypeParameterList.java +@OPENJDK@/jdk/src/share/classes/java/awt/datatransfer/MimeTypeParseException.java +@OPENJDK@/jdk/src/share/classes/java/awt/datatransfer/StringSelection.java +@OPENJDK@/jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java +@OPENJDK@/jdk/src/share/classes/java/awt/datatransfer/Transferable.java +@OPENJDK@/jdk/src/share/classes/java/awt/datatransfer/UnsupportedFlavorException.java +@OPENJDK@/jdk/src/share/classes/java/awt/DefaultFocusTraversalPolicy.java +@OPENJDK@/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java +@OPENJDK@/jdk/src/share/classes/java/awt/Desktop.java +@OPENJDK@/jdk/src/share/classes/java/awt/Dialog.java +@OPENJDK@/jdk/src/share/classes/java/awt/Dimension.java +@OPENJDK@/jdk/src/share/classes/java/awt/DisplayMode.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/Autoscroll.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/DnDConstants.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/DnDEventMulticaster.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/DragGestureEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/DragGestureListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/DragGestureRecognizer.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/DragSource.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/DragSourceAdapter.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/DragSourceContext.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/DragSourceDragEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/DragSourceDropEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/DragSourceEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/DragSourceListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/DragSourceMotionListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/DropTarget.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/DropTargetAdapter.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/DropTargetContext.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/DropTargetDragEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/DropTargetDropEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/DropTargetEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/DropTargetListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/InvalidDnDOperationException.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/MouseDragGestureRecognizer.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/peer/DragSourceContextPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/peer/DropTargetContextPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/peer/DropTargetPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/dnd/SerializationTester.java +@OPENJDK@/jdk/src/share/classes/java/awt/Event.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/ActionEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/ActionListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/AdjustmentEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/AdjustmentListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/AWTEventListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/AWTEventListenerProxy.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/ComponentAdapter.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/ComponentEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/ComponentListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/ContainerAdapter.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/ContainerEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/ContainerListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/FocusAdapter.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/FocusEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/FocusListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/HierarchyBoundsAdapter.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/HierarchyBoundsListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/HierarchyEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/HierarchyListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/InputEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/InputMethodEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/InputMethodListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/InvocationEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/ItemEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/ItemListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/KeyAdapter.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/KeyEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/KeyListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/MouseAdapter.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/MouseEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/MouseListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/MouseMotionAdapter.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/MouseMotionListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/MouseWheelEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/MouseWheelListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/NativeLibLoader.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/PaintEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/TextEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/TextListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/WindowAdapter.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/WindowEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/WindowFocusListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/WindowListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/event/WindowStateListener.java +@OPENJDK@/jdk/src/share/classes/java/awt/EventDispatchThread.java +@OPENJDK@/jdk/src/share/classes/java/awt/EventFilter.java +@OPENJDK@/jdk/src/share/classes/java/awt/EventQueue.java +@OPENJDK@/jdk/src/share/classes/java/awt/FileDialog.java +@OPENJDK@/jdk/src/share/classes/java/awt/FlowLayout.java +@OPENJDK@/jdk/src/share/classes/java/awt/FocusTraversalPolicy.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/CharArrayIterator.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/FontRenderContext.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/GlyphJustificationInfo.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/GlyphMetrics.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/GlyphVector.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/GraphicAttribute.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/ImageGraphicAttribute.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/LayoutPath.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/LineBreakMeasurer.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/LineMetrics.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/MultipleMaster.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/NumericShaper.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/OpenType.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/ShapeGraphicAttribute.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/StyledParagraph.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/TextAttribute.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/TextHitInfo.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/TextJustifier.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/TextLayout.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/TextLine.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/TextMeasurer.java +@OPENJDK@/jdk/src/share/classes/java/awt/font/TransformAttribute.java +@OPENJDK@/jdk/src/share/classes/java/awt/FontFormatException.java +@OPENJDK@/jdk/src/share/classes/java/awt/FontMetrics.java +@OPENJDK@/jdk/src/share/classes/java/awt/Frame.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/AffineTransform.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/Arc2D.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/ArcIterator.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/Area.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/CubicCurve2D.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/CubicIterator.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/Dimension2D.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/Ellipse2D.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/EllipseIterator.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/FlatteningPathIterator.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/GeneralPath.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/IllegalPathStateException.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/Line2D.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/LineIterator.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/NoninvertibleTransformException.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/Path2D.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/PathIterator.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/Point2D.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/QuadCurve2D.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/QuadIterator.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/Rectangle2D.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/RectangularShape.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/RectIterator.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/RoundRectangle2D.java +@OPENJDK@/jdk/src/share/classes/java/awt/geom/RoundRectIterator.java +@OPENJDK@/jdk/src/share/classes/java/awt/GradientPaint.java +@OPENJDK@/jdk/src/share/classes/java/awt/GradientPaintContext.java +@OPENJDK@/jdk/src/share/classes/java/awt/Graphics.java +@OPENJDK@/jdk/src/share/classes/java/awt/Graphics2D.java +@OPENJDK@/jdk/src/share/classes/java/awt/GraphicsCallback.java +@OPENJDK@/jdk/src/share/classes/java/awt/GraphicsConfigTemplate.java +@OPENJDK@/jdk/src/share/classes/java/awt/GraphicsDevice.java +@OPENJDK@/jdk/src/share/classes/java/awt/GraphicsEnvironment.java +@OPENJDK@/jdk/src/share/classes/java/awt/GridBagConstraints.java +@OPENJDK@/jdk/src/share/classes/java/awt/GridBagLayout.java +@OPENJDK@/jdk/src/share/classes/java/awt/GridBagLayoutInfo.java +@OPENJDK@/jdk/src/share/classes/java/awt/GridLayout.java +@OPENJDK@/jdk/src/share/classes/java/awt/HeadlessException.java +@OPENJDK@/jdk/src/share/classes/java/awt/IllegalComponentStateException.java +@OPENJDK@/jdk/src/share/classes/java/awt/im/InputContext.java +@OPENJDK@/jdk/src/share/classes/java/awt/im/InputMethodHighlight.java +@OPENJDK@/jdk/src/share/classes/java/awt/im/InputMethodRequests.java +@OPENJDK@/jdk/src/share/classes/java/awt/im/InputSubset.java +@OPENJDK@/jdk/src/share/classes/java/awt/im/spi/InputMethod.java +@OPENJDK@/jdk/src/share/classes/java/awt/im/spi/InputMethodContext.java +@OPENJDK@/jdk/src/share/classes/java/awt/im/spi/InputMethodDescriptor.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/AreaAveragingScaleFilter.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/BandedSampleModel.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/BufferedImageFilter.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/BufferedImageOp.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/BufferStrategy.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/ByteLookupTable.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/ColorModel.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/ComponentColorModel.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/ComponentSampleModel.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/CropImageFilter.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/DirectColorModel.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/FilteredImageSource.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/ImageConsumer.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/ImageFilter.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/ImageObserver.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/ImageProducer.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/ImagingOpException.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/Kernel.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/LookupTable.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/MemoryImageSource.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/MultiPixelPackedSampleModel.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/PackedColorModel.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/PixelGrabber.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/PixelInterleavedSampleModel.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/Raster.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/RasterFormatException.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/RasterOp.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/renderable/ContextualRenderedImageFactory.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/renderable/ParameterBlock.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/renderable/RenderableImage.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/renderable/RenderableImageOp.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/renderable/RenderableImageProducer.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/renderable/RenderContext.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/renderable/RenderedImageFactory.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/RenderedImage.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/ReplicateScaleFilter.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/RGBImageFilter.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/SampleModel.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/ShortLookupTable.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/SinglePixelPackedSampleModel.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/TileObserver.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/VolatileImage.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/WritableRaster.java +@OPENJDK@/jdk/src/share/classes/java/awt/image/WritableRenderedImage.java +@OPENJDK@/jdk/src/share/classes/java/awt/ImageCapabilities.java +@OPENJDK@/jdk/src/share/classes/java/awt/Insets.java +@OPENJDK@/jdk/src/share/classes/java/awt/ItemSelectable.java +@OPENJDK@/jdk/src/share/classes/java/awt/JobAttributes.java +@OPENJDK@/jdk/src/share/classes/java/awt/KeyboardFocusManager.java +@OPENJDK@/jdk/src/share/classes/java/awt/KeyEventDispatcher.java +@OPENJDK@/jdk/src/share/classes/java/awt/KeyEventPostProcessor.java +@OPENJDK@/jdk/src/share/classes/java/awt/Label.java +@OPENJDK@/jdk/src/share/classes/java/awt/LayoutManager.java +@OPENJDK@/jdk/src/share/classes/java/awt/LayoutManager2.java +@OPENJDK@/jdk/src/share/classes/java/awt/LinearGradientPaint.java +@OPENJDK@/jdk/src/share/classes/java/awt/LinearGradientPaintContext.java +@OPENJDK@/jdk/src/share/classes/java/awt/List.java +@OPENJDK@/jdk/src/share/classes/java/awt/MediaTracker.java +@OPENJDK@/jdk/src/share/classes/java/awt/Menu.java +@OPENJDK@/jdk/src/share/classes/java/awt/MenuBar.java +@OPENJDK@/jdk/src/share/classes/java/awt/MenuComponent.java +@OPENJDK@/jdk/src/share/classes/java/awt/MenuContainer.java +@OPENJDK@/jdk/src/share/classes/java/awt/MenuItem.java +@OPENJDK@/jdk/src/share/classes/java/awt/MenuShortcut.java +@OPENJDK@/jdk/src/share/classes/java/awt/ModalEventFilter.java +@OPENJDK@/jdk/src/share/classes/java/awt/MouseInfo.java +@OPENJDK@/jdk/src/share/classes/java/awt/MultipleGradientPaint.java +@OPENJDK@/jdk/src/share/classes/java/awt/MultipleGradientPaintContext.java +@OPENJDK@/jdk/src/share/classes/java/awt/PageAttributes.java +@OPENJDK@/jdk/src/share/classes/java/awt/Paint.java +@OPENJDK@/jdk/src/share/classes/java/awt/PaintContext.java +@OPENJDK@/jdk/src/share/classes/java/awt/Panel.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/ButtonPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/CanvasPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/CheckboxMenuItemPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/CheckboxPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/ChoicePeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/ComponentPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/ContainerPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/DesktopPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/DialogPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/FileDialogPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/FontPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/FramePeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/KeyboardFocusManagerPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/LabelPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/LightweightPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/ListPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/MenuBarPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/MenuComponentPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/MenuItemPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/MenuPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/MouseInfoPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/PanelPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/PopupMenuPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/RobotPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/ScrollbarPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/ScrollPanePeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/SystemTrayPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/TextAreaPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/TextComponentPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/TextFieldPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/TrayIconPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/peer/WindowPeer.java +@OPENJDK@/jdk/src/share/classes/java/awt/Point.java +@OPENJDK@/jdk/src/share/classes/java/awt/PointerInfo.java +@OPENJDK@/jdk/src/share/classes/java/awt/Polygon.java +@OPENJDK@/jdk/src/share/classes/java/awt/PopupMenu.java +@OPENJDK@/jdk/src/share/classes/java/awt/print/Book.java +@OPENJDK@/jdk/src/share/classes/java/awt/print/Pageable.java +@OPENJDK@/jdk/src/share/classes/java/awt/print/PageFormat.java +@OPENJDK@/jdk/src/share/classes/java/awt/print/Paper.java +@OPENJDK@/jdk/src/share/classes/java/awt/print/Printable.java +@OPENJDK@/jdk/src/share/classes/java/awt/print/PrinterAbortException.java +@OPENJDK@/jdk/src/share/classes/java/awt/print/PrinterException.java +@OPENJDK@/jdk/src/share/classes/java/awt/print/PrinterGraphics.java +@OPENJDK@/jdk/src/share/classes/java/awt/print/PrinterIOException.java +@OPENJDK@/jdk/src/share/classes/java/awt/print/PrinterJob.java +@OPENJDK@/jdk/src/share/classes/java/awt/PrintGraphics.java +@OPENJDK@/jdk/src/share/classes/java/awt/PrintJob.java +@OPENJDK@/jdk/src/share/classes/java/awt/RadialGradientPaint.java +@OPENJDK@/jdk/src/share/classes/java/awt/RadialGradientPaintContext.java +@OPENJDK@/jdk/src/share/classes/java/awt/Rectangle.java +@OPENJDK@/jdk/src/share/classes/java/awt/RenderingHints.java +@OPENJDK@/jdk/src/share/classes/java/awt/Robot.java +@OPENJDK@/jdk/src/share/classes/java/awt/Scrollbar.java +@OPENJDK@/jdk/src/share/classes/java/awt/ScrollPane.java +@OPENJDK@/jdk/src/share/classes/java/awt/ScrollPaneAdjustable.java +@OPENJDK@/jdk/src/share/classes/java/awt/SecondaryLoop.java +@OPENJDK@/jdk/src/share/classes/java/awt/SentEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/SequencedEvent.java +@OPENJDK@/jdk/src/share/classes/java/awt/Shape.java +@OPENJDK@/jdk/src/share/classes/java/awt/SplashScreen.java +@OPENJDK@/jdk/src/share/classes/java/awt/Stroke.java +@OPENJDK@/jdk/src/share/classes/java/awt/SystemColor.java +@OPENJDK@/jdk/src/share/classes/java/awt/SystemTray.java +@OPENJDK@/jdk/src/share/classes/java/awt/TextArea.java +@OPENJDK@/jdk/src/share/classes/java/awt/TextComponent.java +@OPENJDK@/jdk/src/share/classes/java/awt/TextField.java +@OPENJDK@/jdk/src/share/classes/java/awt/TexturePaint.java +@OPENJDK@/jdk/src/share/classes/java/awt/TexturePaintContext.java +@OPENJDK@/jdk/src/share/classes/java/awt/Toolkit.java +@OPENJDK@/jdk/src/share/classes/java/awt/Transparency.java +@OPENJDK@/jdk/src/share/classes/java/awt/TrayIcon.java +@OPENJDK@/jdk/src/share/classes/java/awt/WaitDispatchSupport.java +@OPENJDK@/jdk/src/share/classes/java/awt/Window.java +@OPENJDK@/jdk/src/share/classes/java/beans/AppletInitializer.java +@OPENJDK@/jdk/src/share/classes/java/beans/beancontext/BeanContext.java +@OPENJDK@/jdk/src/share/classes/java/beans/beancontext/BeanContextChild.java +@OPENJDK@/jdk/src/share/classes/java/beans/beancontext/BeanContextChildComponentProxy.java +@OPENJDK@/jdk/src/share/classes/java/beans/beancontext/BeanContextChildSupport.java +@OPENJDK@/jdk/src/share/classes/java/beans/beancontext/BeanContextContainerProxy.java +@OPENJDK@/jdk/src/share/classes/java/beans/beancontext/BeanContextEvent.java +@OPENJDK@/jdk/src/share/classes/java/beans/beancontext/BeanContextMembershipEvent.java +@OPENJDK@/jdk/src/share/classes/java/beans/beancontext/BeanContextMembershipListener.java +@OPENJDK@/jdk/src/share/classes/java/beans/beancontext/BeanContextProxy.java +@OPENJDK@/jdk/src/share/classes/java/beans/beancontext/BeanContextServiceAvailableEvent.java +@OPENJDK@/jdk/src/share/classes/java/beans/beancontext/BeanContextServiceProvider.java +@OPENJDK@/jdk/src/share/classes/java/beans/beancontext/BeanContextServiceProviderBeanInfo.java +@OPENJDK@/jdk/src/share/classes/java/beans/beancontext/BeanContextServiceRevokedEvent.java +@OPENJDK@/jdk/src/share/classes/java/beans/beancontext/BeanContextServiceRevokedListener.java +@OPENJDK@/jdk/src/share/classes/java/beans/beancontext/BeanContextServices.java +@OPENJDK@/jdk/src/share/classes/java/beans/beancontext/BeanContextServicesListener.java +@OPENJDK@/jdk/src/share/classes/java/beans/beancontext/BeanContextServicesSupport.java +@OPENJDK@/jdk/src/share/classes/java/beans/beancontext/BeanContextSupport.java +@OPENJDK@/jdk/src/share/classes/java/beans/BeanDescriptor.java +@OPENJDK@/jdk/src/share/classes/java/beans/BeanInfo.java +@OPENJDK@/jdk/src/share/classes/java/beans/Beans.java +@OPENJDK@/jdk/src/share/classes/java/beans/ChangeListenerMap.java +@OPENJDK@/jdk/src/share/classes/java/beans/ConstructorProperties.java +@OPENJDK@/jdk/src/share/classes/java/beans/Customizer.java +@OPENJDK@/jdk/src/share/classes/java/beans/DefaultPersistenceDelegate.java +@OPENJDK@/jdk/src/share/classes/java/beans/DesignMode.java +@OPENJDK@/jdk/src/share/classes/java/beans/Encoder.java +@OPENJDK@/jdk/src/share/classes/java/beans/EventHandler.java +@OPENJDK@/jdk/src/share/classes/java/beans/EventSetDescriptor.java +@OPENJDK@/jdk/src/share/classes/java/beans/ExceptionListener.java +@OPENJDK@/jdk/src/share/classes/java/beans/Expression.java +@OPENJDK@/jdk/src/share/classes/java/beans/FeatureDescriptor.java +@OPENJDK@/jdk/src/share/classes/java/beans/IndexedPropertyChangeEvent.java +@OPENJDK@/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java +@OPENJDK@/jdk/src/share/classes/java/beans/IntrospectionException.java +@OPENJDK@/jdk/src/share/classes/java/beans/Introspector.java +@OPENJDK@/jdk/src/share/classes/java/beans/MetaData.java +@OPENJDK@/jdk/src/share/classes/java/beans/MethodDescriptor.java +@OPENJDK@/jdk/src/share/classes/java/beans/MethodRef.java +@OPENJDK@/jdk/src/share/classes/java/beans/NameGenerator.java +@OPENJDK@/jdk/src/share/classes/java/beans/ParameterDescriptor.java +@OPENJDK@/jdk/src/share/classes/java/beans/PersistenceDelegate.java +@OPENJDK@/jdk/src/share/classes/java/beans/PropertyChangeEvent.java +@OPENJDK@/jdk/src/share/classes/java/beans/PropertyChangeListener.java +@OPENJDK@/jdk/src/share/classes/java/beans/PropertyChangeListenerProxy.java +@OPENJDK@/jdk/src/share/classes/java/beans/PropertyChangeSupport.java +@OPENJDK@/jdk/src/share/classes/java/beans/PropertyDescriptor.java +@OPENJDK@/jdk/src/share/classes/java/beans/PropertyEditor.java +@OPENJDK@/jdk/src/share/classes/java/beans/PropertyEditorManager.java +@OPENJDK@/jdk/src/share/classes/java/beans/PropertyEditorSupport.java +@OPENJDK@/jdk/src/share/classes/java/beans/PropertyVetoException.java +@OPENJDK@/jdk/src/share/classes/java/beans/SimpleBeanInfo.java +@OPENJDK@/jdk/src/share/classes/java/beans/Statement.java +@OPENJDK@/jdk/src/share/classes/java/beans/ThreadGroupContext.java +@OPENJDK@/jdk/src/share/classes/java/beans/Transient.java +@OPENJDK@/jdk/src/share/classes/java/beans/VetoableChangeListener.java +@OPENJDK@/jdk/src/share/classes/java/beans/VetoableChangeListenerProxy.java +@OPENJDK@/jdk/src/share/classes/java/beans/VetoableChangeSupport.java +@OPENJDK@/jdk/src/share/classes/java/beans/Visibility.java +@OPENJDK@/jdk/src/share/classes/java/beans/WeakIdentityMap.java +@OPENJDK@/jdk/src/share/classes/java/beans/XMLDecoder.java +@OPENJDK@/jdk/src/share/classes/java/beans/XMLEncoder.java +@OPENJDK@/jdk/src/share/classes/java/io/Bits.java +@OPENJDK@/jdk/src/share/classes/java/io/BufferedInputStream.java +@OPENJDK@/jdk/src/share/classes/java/io/BufferedOutputStream.java +@OPENJDK@/jdk/src/share/classes/java/io/BufferedReader.java +@OPENJDK@/jdk/src/share/classes/java/io/BufferedWriter.java +@OPENJDK@/jdk/src/share/classes/java/io/ByteArrayInputStream.java +@OPENJDK@/jdk/src/share/classes/java/io/ByteArrayOutputStream.java +@OPENJDK@/jdk/src/share/classes/java/io/CharArrayReader.java +@OPENJDK@/jdk/src/share/classes/java/io/CharArrayWriter.java +@OPENJDK@/jdk/src/share/classes/java/io/CharConversionException.java +@OPENJDK@/jdk/src/share/classes/java/io/Closeable.java +@OPENJDK@/jdk/src/share/classes/java/io/Console.java +@OPENJDK@/jdk/src/share/classes/java/io/DataInput.java +@OPENJDK@/jdk/src/share/classes/java/io/DataInputStream.java +@OPENJDK@/jdk/src/share/classes/java/io/DataOutput.java +@OPENJDK@/jdk/src/share/classes/java/io/DataOutputStream.java +@OPENJDK@/jdk/src/share/classes/java/io/DeleteOnExitHook.java +@OPENJDK@/jdk/src/share/classes/java/io/EOFException.java +@OPENJDK@/jdk/src/share/classes/java/io/ExpiringCache.java +@OPENJDK@/jdk/src/share/classes/java/io/Externalizable.java +@OPENJDK@/jdk/src/share/classes/java/io/File.java +@OPENJDK@/jdk/src/share/classes/java/io/FileFilter.java +@OPENJDK@/jdk/src/share/classes/java/io/FileInputStream.java +@OPENJDK@/jdk/src/share/classes/java/io/FilenameFilter.java +@OPENJDK@/jdk/src/share/classes/java/io/FileNotFoundException.java +@OPENJDK@/jdk/src/share/classes/java/io/FileOutputStream.java +@OPENJDK@/jdk/src/share/classes/java/io/FilePermission.java +@OPENJDK@/jdk/src/share/classes/java/io/FileReader.java +@OPENJDK@/jdk/src/share/classes/java/io/FileSystem.java +@OPENJDK@/jdk/src/share/classes/java/io/FileWriter.java +@OPENJDK@/jdk/src/share/classes/java/io/FilterInputStream.java +@OPENJDK@/jdk/src/share/classes/java/io/FilterOutputStream.java +@OPENJDK@/jdk/src/share/classes/java/io/FilterReader.java +@OPENJDK@/jdk/src/share/classes/java/io/FilterWriter.java +@OPENJDK@/jdk/src/share/classes/java/io/Flushable.java +@OPENJDK@/jdk/src/share/classes/java/io/InputStream.java +@OPENJDK@/jdk/src/share/classes/java/io/InputStreamReader.java +@OPENJDK@/jdk/src/share/classes/java/io/InterruptedIOException.java +@OPENJDK@/jdk/src/share/classes/java/io/InvalidClassException.java +@OPENJDK@/jdk/src/share/classes/java/io/InvalidObjectException.java +@OPENJDK@/jdk/src/share/classes/java/io/IOError.java +@OPENJDK@/jdk/src/share/classes/java/io/IOException.java +@OPENJDK@/jdk/src/share/classes/java/io/LineNumberInputStream.java +@OPENJDK@/jdk/src/share/classes/java/io/LineNumberReader.java +@OPENJDK@/jdk/src/share/classes/java/io/NotActiveException.java +@OPENJDK@/jdk/src/share/classes/java/io/NotSerializableException.java +@OPENJDK@/jdk/src/share/classes/java/io/ObjectInput.java +@OPENJDK@/jdk/src/share/classes/java/io/ObjectInputStream.java +@OPENJDK@/jdk/src/share/classes/java/io/ObjectInputValidation.java +@OPENJDK@/jdk/src/share/classes/java/io/ObjectOutput.java +@OPENJDK@/jdk/src/share/classes/java/io/ObjectOutputStream.java +@OPENJDK@/jdk/src/share/classes/java/io/ObjectStreamConstants.java +@OPENJDK@/jdk/src/share/classes/java/io/ObjectStreamException.java +@OPENJDK@/jdk/src/share/classes/java/io/OptionalDataException.java +@OPENJDK@/jdk/src/share/classes/java/io/OutputStream.java +@OPENJDK@/jdk/src/share/classes/java/io/OutputStreamWriter.java +@OPENJDK@/jdk/src/share/classes/java/io/PipedInputStream.java +@OPENJDK@/jdk/src/share/classes/java/io/PipedOutputStream.java +@OPENJDK@/jdk/src/share/classes/java/io/PipedReader.java +@OPENJDK@/jdk/src/share/classes/java/io/PipedWriter.java +@OPENJDK@/jdk/src/share/classes/java/io/PrintStream.java +@OPENJDK@/jdk/src/share/classes/java/io/PrintWriter.java +@OPENJDK@/jdk/src/share/classes/java/io/PushbackInputStream.java +@OPENJDK@/jdk/src/share/classes/java/io/PushbackReader.java +@OPENJDK@/jdk/src/share/classes/java/io/RandomAccessFile.java +@OPENJDK@/jdk/src/share/classes/java/io/Reader.java +@OPENJDK@/jdk/src/share/classes/java/io/SequenceInputStream.java +@OPENJDK@/jdk/src/share/classes/java/io/SerialCallbackContext.java +@OPENJDK@/jdk/src/share/classes/java/io/Serializable.java +@OPENJDK@/jdk/src/share/classes/java/io/SerializablePermission.java +@OPENJDK@/jdk/src/share/classes/java/io/StreamCorruptedException.java +@OPENJDK@/jdk/src/share/classes/java/io/StreamTokenizer.java +@OPENJDK@/jdk/src/share/classes/java/io/StringBufferInputStream.java +@OPENJDK@/jdk/src/share/classes/java/io/StringReader.java +@OPENJDK@/jdk/src/share/classes/java/io/StringWriter.java +@OPENJDK@/jdk/src/share/classes/java/io/SyncFailedException.java +@OPENJDK@/jdk/src/share/classes/java/io/UncheckedIOException.java +@OPENJDK@/jdk/src/share/classes/java/io/UnsupportedEncodingException.java +@OPENJDK@/jdk/src/share/classes/java/io/UTFDataFormatException.java +@OPENJDK@/jdk/src/share/classes/java/io/WriteAbortedException.java +@OPENJDK@/jdk/src/share/classes/java/io/Writer.java +@OPENJDK@/jdk/src/share/classes/java/lang/AbstractMethodError.java +@OPENJDK@/jdk/src/share/classes/java/lang/AbstractStringBuilder.java +@OPENJDK@/jdk/src/share/classes/java/lang/annotation/Annotation.java +@OPENJDK@/jdk/src/share/classes/java/lang/annotation/AnnotationFormatError.java +@OPENJDK@/jdk/src/share/classes/java/lang/annotation/AnnotationTypeMismatchException.java +@OPENJDK@/jdk/src/share/classes/java/lang/annotation/Documented.java +@OPENJDK@/jdk/src/share/classes/java/lang/annotation/ElementType.java +@OPENJDK@/jdk/src/share/classes/java/lang/annotation/IncompleteAnnotationException.java +@OPENJDK@/jdk/src/share/classes/java/lang/annotation/Inherited.java +@OPENJDK@/jdk/src/share/classes/java/lang/annotation/Native.java +@OPENJDK@/jdk/src/share/classes/java/lang/annotation/package-info.java +@OPENJDK@/jdk/src/share/classes/java/lang/annotation/Repeatable.java +@OPENJDK@/jdk/src/share/classes/java/lang/annotation/Retention.java +@OPENJDK@/jdk/src/share/classes/java/lang/annotation/RetentionPolicy.java +@OPENJDK@/jdk/src/share/classes/java/lang/annotation/Target.java +@OPENJDK@/jdk/src/share/classes/java/lang/Appendable.java +@OPENJDK@/jdk/src/share/classes/java/lang/ApplicationShutdownHooks.java +@OPENJDK@/jdk/src/share/classes/java/lang/ArithmeticException.java +@OPENJDK@/jdk/src/share/classes/java/lang/ArrayIndexOutOfBoundsException.java +@OPENJDK@/jdk/src/share/classes/java/lang/ArrayStoreException.java +@OPENJDK@/jdk/src/share/classes/java/lang/AssertionError.java +@OPENJDK@/jdk/src/share/classes/java/lang/AssertionStatusDirectives.java +@OPENJDK@/jdk/src/share/classes/java/lang/AutoCloseable.java +@OPENJDK@/jdk/src/share/classes/java/lang/Boolean.java +@OPENJDK@/jdk/src/share/classes/java/lang/BootstrapMethodError.java +@OPENJDK@/jdk/src/share/classes/java/lang/Byte.java +@OPENJDK@/jdk/src/share/classes/java/lang/Character.java +@OPENJDK@/jdk/src/share/classes/java/lang/CharacterData.java +@OPENJDK@/jdk/src/share/classes/java/lang/CharacterName.java +@OPENJDK@/jdk/src/share/classes/java/lang/CharSequence.java +@OPENJDK@/jdk/src/share/classes/java/lang/ClassCastException.java +@OPENJDK@/jdk/src/share/classes/java/lang/ClassCircularityError.java +@OPENJDK@/jdk/src/share/classes/java/lang/ClassFormatError.java +@OPENJDK@/jdk/src/share/classes/java/lang/ClassNotFoundException.java +@OPENJDK@/jdk/src/share/classes/java/lang/ClassValue.java +@OPENJDK@/jdk/src/share/classes/java/lang/Cloneable.java +@OPENJDK@/jdk/src/share/classes/java/lang/CloneNotSupportedException.java +@OPENJDK@/jdk/src/share/classes/java/lang/Comparable.java +@OPENJDK@/jdk/src/share/classes/java/lang/Compiler.java +@OPENJDK@/jdk/src/share/classes/java/lang/ConditionalSpecialCasing.java +@OPENJDK@/jdk/src/share/classes/java/lang/Deprecated.java +@OPENJDK@/jdk/src/share/classes/java/lang/Double.java +@OPENJDK@/jdk/src/share/classes/java/lang/EnumConstantNotPresentException.java +@OPENJDK@/jdk/src/share/classes/java/lang/Error.java +@OPENJDK@/jdk/src/share/classes/java/lang/Exception.java +@OPENJDK@/jdk/src/share/classes/java/lang/ExceptionInInitializerError.java +@OPENJDK@/jdk/src/share/classes/java/lang/Float.java +@OPENJDK@/jdk/src/share/classes/java/lang/FunctionalInterface.java +@OPENJDK@/jdk/src/share/classes/java/lang/IllegalAccessError.java +@OPENJDK@/jdk/src/share/classes/java/lang/IllegalAccessException.java +@OPENJDK@/jdk/src/share/classes/java/lang/IllegalArgumentException.java +@OPENJDK@/jdk/src/share/classes/java/lang/IllegalMonitorStateException.java +@OPENJDK@/jdk/src/share/classes/java/lang/IllegalStateException.java +@OPENJDK@/jdk/src/share/classes/java/lang/IllegalThreadStateException.java +@OPENJDK@/jdk/src/share/classes/java/lang/IncompatibleClassChangeError.java +@OPENJDK@/jdk/src/share/classes/java/lang/IndexOutOfBoundsException.java +@OPENJDK@/jdk/src/share/classes/java/lang/InheritableThreadLocal.java +@OPENJDK@/jdk/src/share/classes/java/lang/InstantiationError.java +@OPENJDK@/jdk/src/share/classes/java/lang/InstantiationException.java +@OPENJDK@/jdk/src/share/classes/java/lang/instrument/ClassDefinition.java +@OPENJDK@/jdk/src/share/classes/java/lang/instrument/ClassFileTransformer.java +@OPENJDK@/jdk/src/share/classes/java/lang/instrument/IllegalClassFormatException.java +@OPENJDK@/jdk/src/share/classes/java/lang/instrument/Instrumentation.java +@OPENJDK@/jdk/src/share/classes/java/lang/instrument/UnmodifiableClassException.java +@OPENJDK@/jdk/src/share/classes/java/lang/Integer.java +@OPENJDK@/jdk/src/share/classes/java/lang/InternalError.java +@OPENJDK@/jdk/src/share/classes/java/lang/InterruptedException.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/CallSite.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/ConstantCallSite.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/DelegatingMethodHandle.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/DontInline.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/ForceInline.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/InfoFromMemberName.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/InvokeDynamic.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/Invokers.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/LambdaConversionException.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/LambdaForm.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/LambdaFormBuffer.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/LambdaFormEditor.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/MemberName.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/MethodHandle.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/MethodHandleInfo.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/MethodHandles.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/MethodHandleStatics.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/MethodType.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/MutableCallSite.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/package-info.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/ProxyClassesDumper.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/SerializedLambda.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/SimpleMethodHandle.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/Stable.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/SwitchPoint.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/VolatileCallSite.java +@OPENJDK@/jdk/src/share/classes/java/lang/invoke/WrongMethodTypeException.java +@OPENJDK@/jdk/src/share/classes/java/lang/Iterable.java +@OPENJDK@/jdk/src/share/classes/java/lang/LinkageError.java +@OPENJDK@/jdk/src/share/classes/java/lang/Long.java +@OPENJDK@/jdk/src/share/classes/java/lang/management/BufferPoolMXBean.java +@OPENJDK@/jdk/src/share/classes/java/lang/management/ClassLoadingMXBean.java +@OPENJDK@/jdk/src/share/classes/java/lang/management/CompilationMXBean.java +@OPENJDK@/jdk/src/share/classes/java/lang/management/GarbageCollectorMXBean.java +@OPENJDK@/jdk/src/share/classes/java/lang/management/LockInfo.java +@OPENJDK@/jdk/src/share/classes/java/lang/management/ManagementFactory.java +@OPENJDK@/jdk/src/share/classes/java/lang/management/ManagementPermission.java +@OPENJDK@/jdk/src/share/classes/java/lang/management/MemoryManagerMXBean.java +@OPENJDK@/jdk/src/share/classes/java/lang/management/MemoryMXBean.java +@OPENJDK@/jdk/src/share/classes/java/lang/management/MemoryNotificationInfo.java +@OPENJDK@/jdk/src/share/classes/java/lang/management/MemoryPoolMXBean.java +@OPENJDK@/jdk/src/share/classes/java/lang/management/MemoryType.java +@OPENJDK@/jdk/src/share/classes/java/lang/management/MemoryUsage.java +@OPENJDK@/jdk/src/share/classes/java/lang/management/MonitorInfo.java +@OPENJDK@/jdk/src/share/classes/java/lang/management/OperatingSystemMXBean.java +@OPENJDK@/jdk/src/share/classes/java/lang/management/PlatformLoggingMXBean.java +@OPENJDK@/jdk/src/share/classes/java/lang/management/PlatformManagedObject.java +@OPENJDK@/jdk/src/share/classes/java/lang/management/RuntimeMXBean.java +@OPENJDK@/jdk/src/share/classes/java/lang/management/ThreadInfo.java +@OPENJDK@/jdk/src/share/classes/java/lang/management/ThreadMXBean.java +@OPENJDK@/jdk/src/share/classes/java/lang/Math.java +@OPENJDK@/jdk/src/share/classes/java/lang/NegativeArraySizeException.java +@OPENJDK@/jdk/src/share/classes/java/lang/NoClassDefFoundError.java +@OPENJDK@/jdk/src/share/classes/java/lang/NoSuchFieldError.java +@OPENJDK@/jdk/src/share/classes/java/lang/NoSuchFieldException.java +@OPENJDK@/jdk/src/share/classes/java/lang/NoSuchMethodError.java +@OPENJDK@/jdk/src/share/classes/java/lang/NoSuchMethodException.java +@OPENJDK@/jdk/src/share/classes/java/lang/NullPointerException.java +@OPENJDK@/jdk/src/share/classes/java/lang/Number.java +@OPENJDK@/jdk/src/share/classes/java/lang/NumberFormatException.java +@OPENJDK@/jdk/src/share/classes/java/lang/Object.java +@OPENJDK@/jdk/src/share/classes/java/lang/OutOfMemoryError.java +@OPENJDK@/jdk/src/share/classes/java/lang/Override.java +@OPENJDK@/jdk/src/share/classes/java/lang/package-info.java +@OPENJDK@/jdk/src/share/classes/java/lang/Package.java +@OPENJDK@/jdk/src/share/classes/java/lang/Process.java +@OPENJDK@/jdk/src/share/classes/java/lang/ProcessBuilder.java +@OPENJDK@/jdk/src/share/classes/java/lang/Readable.java +@OPENJDK@/jdk/src/share/classes/java/lang/ref/FinalReference.java +@OPENJDK@/jdk/src/share/classes/java/lang/ref/PhantomReference.java +@OPENJDK@/jdk/src/share/classes/java/lang/ref/WeakReference.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/AnnotatedArrayType.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/AnnotatedParameterizedType.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/AnnotatedType.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/AnnotatedTypeVariable.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/AnnotatedWildcardType.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/Array.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/GenericArrayType.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/GenericDeclaration.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/GenericSignatureFormatError.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/InvocationHandler.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/InvocationTargetException.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/MalformedParameterizedTypeException.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/MalformedParametersException.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/Member.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/Modifier.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/package-info.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/Parameter.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/ParameterizedType.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/ReflectAccess.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/ReflectPermission.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/Type.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/TypeVariable.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/UndeclaredThrowableException.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/WeakCache.java +@OPENJDK@/jdk/src/share/classes/java/lang/reflect/WildcardType.java +@OPENJDK@/jdk/src/share/classes/java/lang/ReflectiveOperationException.java +@OPENJDK@/jdk/src/share/classes/java/lang/Runnable.java +@OPENJDK@/jdk/src/share/classes/java/lang/Runtime.java +@OPENJDK@/jdk/src/share/classes/java/lang/RuntimeException.java +@OPENJDK@/jdk/src/share/classes/java/lang/RuntimePermission.java +@OPENJDK@/jdk/src/share/classes/java/lang/SafeVarargs.java +@OPENJDK@/jdk/src/share/classes/java/lang/SecurityException.java +@OPENJDK@/jdk/src/share/classes/java/lang/SecurityManager.java +@OPENJDK@/jdk/src/share/classes/java/lang/Short.java +@OPENJDK@/jdk/src/share/classes/java/lang/StackOverflowError.java +@OPENJDK@/jdk/src/share/classes/java/lang/StackTraceElement.java +@OPENJDK@/jdk/src/share/classes/java/lang/StrictMath.java +@OPENJDK@/jdk/src/share/classes/java/lang/String.java +@OPENJDK@/jdk/src/share/classes/java/lang/StringBuffer.java +@OPENJDK@/jdk/src/share/classes/java/lang/StringBuilder.java +@OPENJDK@/jdk/src/share/classes/java/lang/StringCoding.java +@OPENJDK@/jdk/src/share/classes/java/lang/StringIndexOutOfBoundsException.java +@OPENJDK@/jdk/src/share/classes/java/lang/SuppressWarnings.java +@OPENJDK@/jdk/src/share/classes/java/lang/ThreadDeath.java +@OPENJDK@/jdk/src/share/classes/java/lang/ThreadGroup.java +@OPENJDK@/jdk/src/share/classes/java/lang/ThreadLocal.java +@OPENJDK@/jdk/src/share/classes/java/lang/Throwable.java +@OPENJDK@/jdk/src/share/classes/java/lang/TypeNotPresentException.java +@OPENJDK@/jdk/src/share/classes/java/lang/UnknownError.java +@OPENJDK@/jdk/src/share/classes/java/lang/UnsatisfiedLinkError.java +@OPENJDK@/jdk/src/share/classes/java/lang/UnsupportedClassVersionError.java +@OPENJDK@/jdk/src/share/classes/java/lang/UnsupportedOperationException.java +@OPENJDK@/jdk/src/share/classes/java/lang/VerifyError.java +@OPENJDK@/jdk/src/share/classes/java/lang/VirtualMachineError.java +@OPENJDK@/jdk/src/share/classes/java/lang/Void.java +@OPENJDK@/jdk/src/share/classes/java/math/BigDecimal.java +@OPENJDK@/jdk/src/share/classes/java/math/BigInteger.java +@OPENJDK@/jdk/src/share/classes/java/math/BitSieve.java +@OPENJDK@/jdk/src/share/classes/java/math/MathContext.java +@OPENJDK@/jdk/src/share/classes/java/math/MutableBigInteger.java +@OPENJDK@/jdk/src/share/classes/java/math/package-info.java +@OPENJDK@/jdk/src/share/classes/java/math/RoundingMode.java +@OPENJDK@/jdk/src/share/classes/java/math/SignedMutableBigInteger.java +@OPENJDK@/jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java +@OPENJDK@/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java +@OPENJDK@/jdk/src/share/classes/java/net/Authenticator.java +@OPENJDK@/jdk/src/share/classes/java/net/BindException.java +@OPENJDK@/jdk/src/share/classes/java/net/CacheRequest.java +@OPENJDK@/jdk/src/share/classes/java/net/CacheResponse.java +@OPENJDK@/jdk/src/share/classes/java/net/ConnectException.java +@OPENJDK@/jdk/src/share/classes/java/net/ContentHandler.java +@OPENJDK@/jdk/src/share/classes/java/net/ContentHandlerFactory.java +@OPENJDK@/jdk/src/share/classes/java/net/CookieHandler.java +@OPENJDK@/jdk/src/share/classes/java/net/CookieManager.java +@OPENJDK@/jdk/src/share/classes/java/net/CookiePolicy.java +@OPENJDK@/jdk/src/share/classes/java/net/CookieStore.java +@OPENJDK@/jdk/src/share/classes/java/net/DatagramPacket.java +@OPENJDK@/jdk/src/share/classes/java/net/DatagramSocket.java +@OPENJDK@/jdk/src/share/classes/java/net/DatagramSocketImpl.java +@OPENJDK@/jdk/src/share/classes/java/net/DatagramSocketImplFactory.java +@OPENJDK@/jdk/src/share/classes/java/net/FileNameMap.java +@OPENJDK@/jdk/src/share/classes/java/net/HostPortrange.java +@OPENJDK@/jdk/src/share/classes/java/net/HttpConnectSocketImpl.java +@OPENJDK@/jdk/src/share/classes/java/net/HttpCookie.java +@OPENJDK@/jdk/src/share/classes/java/net/HttpRetryException.java +@OPENJDK@/jdk/src/share/classes/java/net/HttpURLConnection.java +@OPENJDK@/jdk/src/share/classes/java/net/IDN.java +@OPENJDK@/jdk/src/share/classes/java/net/Inet4Address.java +@OPENJDK@/jdk/src/share/classes/java/net/Inet4AddressImpl.java +@OPENJDK@/jdk/src/share/classes/java/net/Inet6Address.java +@OPENJDK@/jdk/src/share/classes/java/net/Inet6AddressImpl.java +@OPENJDK@/jdk/src/share/classes/java/net/InetAddress.java +@OPENJDK@/jdk/src/share/classes/java/net/InetAddressContainer.java +@OPENJDK@/jdk/src/share/classes/java/net/InetAddressImpl.java +@OPENJDK@/jdk/src/share/classes/java/net/InetSocketAddress.java +@OPENJDK@/jdk/src/share/classes/java/net/InMemoryCookieStore.java +@OPENJDK@/jdk/src/share/classes/java/net/InterfaceAddress.java +@OPENJDK@/jdk/src/share/classes/java/net/JarURLConnection.java +@OPENJDK@/jdk/src/share/classes/java/net/MalformedURLException.java +@OPENJDK@/jdk/src/share/classes/java/net/MulticastSocket.java +@OPENJDK@/jdk/src/share/classes/java/net/NetPermission.java +@OPENJDK@/jdk/src/share/classes/java/net/NetworkInterface.java +@OPENJDK@/jdk/src/share/classes/java/net/NoRouteToHostException.java +@OPENJDK@/jdk/src/share/classes/java/net/PasswordAuthentication.java +@OPENJDK@/jdk/src/share/classes/java/net/PortUnreachableException.java +@OPENJDK@/jdk/src/share/classes/java/net/ProtocolException.java +@OPENJDK@/jdk/src/share/classes/java/net/ProtocolFamily.java +@OPENJDK@/jdk/src/share/classes/java/net/Proxy.java +@OPENJDK@/jdk/src/share/classes/java/net/ProxySelector.java +@OPENJDK@/jdk/src/share/classes/java/net/ResponseCache.java +@OPENJDK@/jdk/src/share/classes/java/net/SdpSocketImpl.java +@OPENJDK@/jdk/src/share/classes/java/net/SecureCacheResponse.java +@OPENJDK@/jdk/src/share/classes/java/net/ServerSocket.java +@OPENJDK@/jdk/src/share/classes/java/net/Socket.java +@OPENJDK@/jdk/src/share/classes/java/net/SocketAddress.java +@OPENJDK@/jdk/src/share/classes/java/net/SocketException.java +@OPENJDK@/jdk/src/share/classes/java/net/SocketImpl.java +@OPENJDK@/jdk/src/share/classes/java/net/SocketImplFactory.java +@OPENJDK@/jdk/src/share/classes/java/net/SocketInputStream.java +@OPENJDK@/jdk/src/share/classes/java/net/SocketOption.java +@OPENJDK@/jdk/src/share/classes/java/net/SocketOptions.java +@OPENJDK@/jdk/src/share/classes/java/net/SocketOutputStream.java +@OPENJDK@/jdk/src/share/classes/java/net/SocketPermission.java +@OPENJDK@/jdk/src/share/classes/java/net/SocketSecrets.java +@OPENJDK@/jdk/src/share/classes/java/net/SocketTimeoutException.java +@OPENJDK@/jdk/src/share/classes/java/net/SocksConsts.java +@OPENJDK@/jdk/src/share/classes/java/net/SocksSocketImpl.java +@OPENJDK@/jdk/src/share/classes/java/net/StandardProtocolFamily.java +@OPENJDK@/jdk/src/share/classes/java/net/StandardSocketOptions.java +@OPENJDK@/jdk/src/share/classes/java/net/UnknownHostException.java +@OPENJDK@/jdk/src/share/classes/java/net/UnknownServiceException.java +@OPENJDK@/jdk/src/share/classes/java/net/URI.java +@OPENJDK@/jdk/src/share/classes/java/net/URISyntaxException.java +@OPENJDK@/jdk/src/share/classes/java/net/URL.java +@OPENJDK@/jdk/src/share/classes/java/net/URLClassLoader.java +@OPENJDK@/jdk/src/share/classes/java/net/URLConnection.java +@OPENJDK@/jdk/src/share/classes/java/net/URLDecoder.java +@OPENJDK@/jdk/src/share/classes/java/net/URLEncoder.java +@OPENJDK@/jdk/src/share/classes/java/net/URLPermission.java +@OPENJDK@/jdk/src/share/classes/java/net/URLStreamHandler.java +@OPENJDK@/jdk/src/share/classes/java/net/URLStreamHandlerFactory.java +@OPENJDK@/jdk/src/share/classes/java/nio/Buffer.java +@OPENJDK@/jdk/src/share/classes/java/nio/ByteOrder.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/AsynchronousByteChannel.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/AsynchronousChannel.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/AsynchronousChannelGroup.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/AsynchronousFileChannel.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/AsynchronousServerSocketChannel.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/ByteChannel.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/Channel.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/Channels.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/CompletionHandler.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/DatagramChannel.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/FileChannel.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/FileLock.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/GatheringByteChannel.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/InterruptibleChannel.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/MembershipKey.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/MulticastChannel.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/NetworkChannel.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/package-info.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/Pipe.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/ReadableByteChannel.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/ScatteringByteChannel.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/SeekableByteChannel.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/SelectableChannel.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/SelectionKey.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/Selector.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/ServerSocketChannel.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/SocketChannel.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/spi/AbstractInterruptibleChannel.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/spi/AbstractSelectableChannel.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/spi/AbstractSelectionKey.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/spi/AbstractSelector.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/spi/SelectorProvider.java +@OPENJDK@/jdk/src/share/classes/java/nio/channels/WritableByteChannel.java +@OPENJDK@/jdk/src/share/classes/java/nio/CharBufferSpliterator.java +@OPENJDK@/jdk/src/share/classes/java/nio/charset/Charset.java +@OPENJDK@/jdk/src/share/classes/java/nio/charset/CoderMalfunctionError.java +@OPENJDK@/jdk/src/share/classes/java/nio/charset/CoderResult.java +@OPENJDK@/jdk/src/share/classes/java/nio/charset/CodingErrorAction.java +@OPENJDK@/jdk/src/share/classes/java/nio/charset/MalformedInputException.java +@OPENJDK@/jdk/src/share/classes/java/nio/charset/spi/CharsetProvider.java +@OPENJDK@/jdk/src/share/classes/java/nio/charset/StandardCharsets.java +@OPENJDK@/jdk/src/share/classes/java/nio/charset/UnmappableCharacterException.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/AccessDeniedException.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/AccessMode.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/AtomicMoveNotSupportedException.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/AclEntry.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/AclEntryFlag.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/AclEntryPermission.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/AclEntryType.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/AclFileAttributeView.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/AttributeView.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributes.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributeView.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/DosFileAttributes.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/DosFileAttributeView.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/FileAttribute.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/FileAttributeView.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/FileOwnerAttributeView.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/FileStoreAttributeView.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/FileTime.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/GroupPrincipal.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/package-info.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributes.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributeView.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/PosixFilePermission.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/PosixFilePermissions.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/UserDefinedFileAttributeView.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/UserPrincipal.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/UserPrincipalLookupService.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/UserPrincipalNotFoundException.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/ClosedDirectoryStreamException.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/ClosedFileSystemException.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/ClosedWatchServiceException.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/CopyMoveHelper.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/CopyOption.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/DirectoryIteratorException.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/DirectoryNotEmptyException.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/DirectoryStream.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/FileAlreadyExistsException.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/Files.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/FileStore.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/FileSystem.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/FileSystemAlreadyExistsException.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/FileSystemException.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/FileSystemLoopException.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/FileSystemNotFoundException.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/FileSystems.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/FileTreeIterator.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/FileTreeWalker.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/FileVisitOption.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/FileVisitor.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/FileVisitResult.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/InvalidPathException.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/LinkOption.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/LinkPermission.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/NoSuchFileException.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/NotDirectoryException.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/NotLinkException.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/OpenOption.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/package-info.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/Path.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/PathMatcher.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/Paths.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/ProviderMismatchException.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/ProviderNotFoundException.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/ReadOnlyFileSystemException.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/SecureDirectoryStream.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/SimpleFileVisitor.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/spi/FileTypeDetector.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/spi/package-info.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/StandardCopyOption.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/StandardOpenOption.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/StandardWatchEventKinds.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/TempFileHelper.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/Watchable.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/WatchEvent.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/WatchKey.java +@OPENJDK@/jdk/src/share/classes/java/nio/file/WatchService.java +@OPENJDK@/jdk/src/share/classes/java/nio/MappedByteBuffer.java +@OPENJDK@/jdk/src/share/classes/java/nio/StringCharBuffer.java +@OPENJDK@/jdk/src/share/classes/java/rmi/AccessException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/activation/Activatable.java +@OPENJDK@/jdk/src/share/classes/java/rmi/activation/ActivateFailedException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/activation/ActivationDesc.java +@OPENJDK@/jdk/src/share/classes/java/rmi/activation/ActivationException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/activation/ActivationGroup.java +@OPENJDK@/jdk/src/share/classes/java/rmi/activation/ActivationGroupDesc.java +@OPENJDK@/jdk/src/share/classes/java/rmi/activation/ActivationGroupID.java +@OPENJDK@/jdk/src/share/classes/java/rmi/activation/ActivationID.java +@OPENJDK@/jdk/src/share/classes/java/rmi/activation/ActivationInstantiator.java +@OPENJDK@/jdk/src/share/classes/java/rmi/activation/ActivationMonitor.java +@OPENJDK@/jdk/src/share/classes/java/rmi/activation/ActivationSystem.java +@OPENJDK@/jdk/src/share/classes/java/rmi/activation/Activator.java +@OPENJDK@/jdk/src/share/classes/java/rmi/activation/UnknownGroupException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/activation/UnknownObjectException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/AlreadyBoundException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/ConnectException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/ConnectIOException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/dgc/DGC.java +@OPENJDK@/jdk/src/share/classes/java/rmi/dgc/Lease.java +@OPENJDK@/jdk/src/share/classes/java/rmi/dgc/VMID.java +@OPENJDK@/jdk/src/share/classes/java/rmi/MarshalException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/MarshalledObject.java +@OPENJDK@/jdk/src/share/classes/java/rmi/Naming.java +@OPENJDK@/jdk/src/share/classes/java/rmi/NoSuchObjectException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/NotBoundException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/registry/LocateRegistry.java +@OPENJDK@/jdk/src/share/classes/java/rmi/registry/Registry.java +@OPENJDK@/jdk/src/share/classes/java/rmi/registry/RegistryHandler.java +@OPENJDK@/jdk/src/share/classes/java/rmi/Remote.java +@OPENJDK@/jdk/src/share/classes/java/rmi/RemoteException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/RMISecurityException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/RMISecurityManager.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/ExportException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/LoaderHandler.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/LogStream.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/ObjID.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/Operation.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/RemoteCall.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/RemoteObject.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/RemoteObjectInvocationHandler.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/RemoteRef.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/RemoteServer.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/RemoteStub.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/RMIClassLoader.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/RMIClassLoaderSpi.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/RMIClientSocketFactory.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/RMIFailureHandler.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/RMIServerSocketFactory.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/RMISocketFactory.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/ServerCloneException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/ServerNotActiveException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/ServerRef.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/Skeleton.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/SkeletonMismatchException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/SkeletonNotFoundException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/SocketSecurityException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/UID.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/UnicastRemoteObject.java +@OPENJDK@/jdk/src/share/classes/java/rmi/server/Unreferenced.java +@OPENJDK@/jdk/src/share/classes/java/rmi/ServerError.java +@OPENJDK@/jdk/src/share/classes/java/rmi/ServerException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/ServerRuntimeException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/StubNotFoundException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/UnexpectedException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/UnknownHostException.java +@OPENJDK@/jdk/src/share/classes/java/rmi/UnmarshalException.java +@OPENJDK@/jdk/src/share/classes/java/security/AccessControlContext.java +@OPENJDK@/jdk/src/share/classes/java/security/AccessControlException.java +@OPENJDK@/jdk/src/share/classes/java/security/acl/Acl.java +@OPENJDK@/jdk/src/share/classes/java/security/acl/AclEntry.java +@OPENJDK@/jdk/src/share/classes/java/security/acl/AclNotFoundException.java +@OPENJDK@/jdk/src/share/classes/java/security/acl/Group.java +@OPENJDK@/jdk/src/share/classes/java/security/acl/LastOwnerException.java +@OPENJDK@/jdk/src/share/classes/java/security/acl/NotOwnerException.java +@OPENJDK@/jdk/src/share/classes/java/security/acl/Owner.java +@OPENJDK@/jdk/src/share/classes/java/security/acl/Permission.java +@OPENJDK@/jdk/src/share/classes/java/security/AlgorithmConstraints.java +@OPENJDK@/jdk/src/share/classes/java/security/AlgorithmParameterGenerator.java +@OPENJDK@/jdk/src/share/classes/java/security/AlgorithmParameterGeneratorSpi.java +@OPENJDK@/jdk/src/share/classes/java/security/AlgorithmParameters.java +@OPENJDK@/jdk/src/share/classes/java/security/AlgorithmParametersSpi.java +@OPENJDK@/jdk/src/share/classes/java/security/AllPermission.java +@OPENJDK@/jdk/src/share/classes/java/security/AuthProvider.java +@OPENJDK@/jdk/src/share/classes/java/security/BasicPermission.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/Certificate.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertificateEncodingException.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertificateException.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertificateExpiredException.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertificateFactory.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertificateFactorySpi.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertificateNotYetValidException.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertificateParsingException.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertificateRevokedException.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertPath.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertPathBuilder.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertPathBuilderException.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertPathBuilderResult.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertPathBuilderSpi.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertPathChecker.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertPathHelperImpl.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertPathParameters.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertPathValidator.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertPathValidatorException.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertPathValidatorResult.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertPathValidatorSpi.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertSelector.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertStore.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertStoreException.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertStoreParameters.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CertStoreSpi.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CollectionCertStoreParameters.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CRL.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CRLException.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CRLReason.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/CRLSelector.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/Extension.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/LDAPCertStoreParameters.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/PKIXBuilderParameters.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/PKIXCertPathBuilderResult.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/PKIXCertPathChecker.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/PKIXCertPathValidatorResult.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/PKIXParameters.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/PKIXReason.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/PKIXRevocationChecker.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/PolicyNode.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/PolicyQualifierInfo.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/TrustAnchor.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/X509Certificate.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/X509CertSelector.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/X509CRL.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/X509CRLEntry.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/X509CRLSelector.java +@OPENJDK@/jdk/src/share/classes/java/security/cert/X509Extension.java +@OPENJDK@/jdk/src/share/classes/java/security/Certificate.java +@OPENJDK@/jdk/src/share/classes/java/security/CodeSigner.java +@OPENJDK@/jdk/src/share/classes/java/security/CodeSource.java +@OPENJDK@/jdk/src/share/classes/java/security/CryptoPrimitive.java +@OPENJDK@/jdk/src/share/classes/java/security/DigestException.java +@OPENJDK@/jdk/src/share/classes/java/security/DigestInputStream.java +@OPENJDK@/jdk/src/share/classes/java/security/DigestOutputStream.java +@OPENJDK@/jdk/src/share/classes/java/security/DomainCombiner.java +@OPENJDK@/jdk/src/share/classes/java/security/DomainLoadStoreParameter.java +@OPENJDK@/jdk/src/share/classes/java/security/GeneralSecurityException.java +@OPENJDK@/jdk/src/share/classes/java/security/Guard.java +@OPENJDK@/jdk/src/share/classes/java/security/GuardedObject.java +@OPENJDK@/jdk/src/share/classes/java/security/Identity.java +@OPENJDK@/jdk/src/share/classes/java/security/IdentityScope.java +@OPENJDK@/jdk/src/share/classes/java/security/interfaces/DSAKey.java +@OPENJDK@/jdk/src/share/classes/java/security/interfaces/DSAKeyPairGenerator.java +@OPENJDK@/jdk/src/share/classes/java/security/interfaces/DSAParams.java +@OPENJDK@/jdk/src/share/classes/java/security/interfaces/DSAPrivateKey.java +@OPENJDK@/jdk/src/share/classes/java/security/interfaces/DSAPublicKey.java +@OPENJDK@/jdk/src/share/classes/java/security/interfaces/ECKey.java +@OPENJDK@/jdk/src/share/classes/java/security/interfaces/ECPrivateKey.java +@OPENJDK@/jdk/src/share/classes/java/security/interfaces/ECPublicKey.java +@OPENJDK@/jdk/src/share/classes/java/security/interfaces/RSAKey.java +@OPENJDK@/jdk/src/share/classes/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java +@OPENJDK@/jdk/src/share/classes/java/security/interfaces/RSAPrivateCrtKey.java +@OPENJDK@/jdk/src/share/classes/java/security/interfaces/RSAPrivateKey.java +@OPENJDK@/jdk/src/share/classes/java/security/interfaces/RSAPublicKey.java +@OPENJDK@/jdk/src/share/classes/java/security/InvalidAlgorithmParameterException.java +@OPENJDK@/jdk/src/share/classes/java/security/InvalidKeyException.java +@OPENJDK@/jdk/src/share/classes/java/security/InvalidParameterException.java +@OPENJDK@/jdk/src/share/classes/java/security/Key.java +@OPENJDK@/jdk/src/share/classes/java/security/KeyException.java +@OPENJDK@/jdk/src/share/classes/java/security/KeyFactory.java +@OPENJDK@/jdk/src/share/classes/java/security/KeyFactorySpi.java +@OPENJDK@/jdk/src/share/classes/java/security/KeyManagementException.java +@OPENJDK@/jdk/src/share/classes/java/security/KeyPair.java +@OPENJDK@/jdk/src/share/classes/java/security/KeyPairGenerator.java +@OPENJDK@/jdk/src/share/classes/java/security/KeyPairGeneratorSpi.java +@OPENJDK@/jdk/src/share/classes/java/security/KeyRep.java +@OPENJDK@/jdk/src/share/classes/java/security/KeyStore.java +@OPENJDK@/jdk/src/share/classes/java/security/KeyStoreException.java +@OPENJDK@/jdk/src/share/classes/java/security/KeyStoreSpi.java +@OPENJDK@/jdk/src/share/classes/java/security/MessageDigest.java +@OPENJDK@/jdk/src/share/classes/java/security/MessageDigestSpi.java +@OPENJDK@/jdk/src/share/classes/java/security/NoSuchAlgorithmException.java +@OPENJDK@/jdk/src/share/classes/java/security/NoSuchProviderException.java +@OPENJDK@/jdk/src/share/classes/java/security/Permission.java +@OPENJDK@/jdk/src/share/classes/java/security/PermissionCollection.java +@OPENJDK@/jdk/src/share/classes/java/security/Permissions.java +@OPENJDK@/jdk/src/share/classes/java/security/PKCS12Attribute.java +@OPENJDK@/jdk/src/share/classes/java/security/Policy.java +@OPENJDK@/jdk/src/share/classes/java/security/PolicySpi.java +@OPENJDK@/jdk/src/share/classes/java/security/Principal.java +@OPENJDK@/jdk/src/share/classes/java/security/PrivateKey.java +@OPENJDK@/jdk/src/share/classes/java/security/PrivilegedAction.java +@OPENJDK@/jdk/src/share/classes/java/security/PrivilegedActionException.java +@OPENJDK@/jdk/src/share/classes/java/security/PrivilegedExceptionAction.java +@OPENJDK@/jdk/src/share/classes/java/security/Provider.java +@OPENJDK@/jdk/src/share/classes/java/security/ProviderException.java +@OPENJDK@/jdk/src/share/classes/java/security/PublicKey.java +@OPENJDK@/jdk/src/share/classes/java/security/SecureClassLoader.java +@OPENJDK@/jdk/src/share/classes/java/security/SecureRandom.java +@OPENJDK@/jdk/src/share/classes/java/security/SecureRandomSpi.java +@OPENJDK@/jdk/src/share/classes/java/security/Security.java +@OPENJDK@/jdk/src/share/classes/java/security/SecurityPermission.java +@OPENJDK@/jdk/src/share/classes/java/security/Signature.java +@OPENJDK@/jdk/src/share/classes/java/security/SignatureException.java +@OPENJDK@/jdk/src/share/classes/java/security/SignatureSpi.java +@OPENJDK@/jdk/src/share/classes/java/security/SignedObject.java +@OPENJDK@/jdk/src/share/classes/java/security/Signer.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/AlgorithmParameterSpec.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/DSAGenParameterSpec.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/DSAParameterSpec.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/DSAPrivateKeySpec.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/DSAPublicKeySpec.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/ECField.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/ECFieldF2m.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/ECFieldFp.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/ECGenParameterSpec.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/ECParameterSpec.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/ECPoint.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/ECPrivateKeySpec.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/ECPublicKeySpec.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/EllipticCurve.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/EncodedKeySpec.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/InvalidKeySpecException.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/InvalidParameterSpecException.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/KeySpec.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/MGF1ParameterSpec.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/PKCS8EncodedKeySpec.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/PSSParameterSpec.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/RSAKeyGenParameterSpec.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/RSAOtherPrimeInfo.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/RSAPrivateCrtKeySpec.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/RSAPrivateKeySpec.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/RSAPublicKeySpec.java +@OPENJDK@/jdk/src/share/classes/java/security/spec/X509EncodedKeySpec.java +@OPENJDK@/jdk/src/share/classes/java/security/Timestamp.java +@OPENJDK@/jdk/src/share/classes/java/security/UnrecoverableEntryException.java +@OPENJDK@/jdk/src/share/classes/java/security/UnrecoverableKeyException.java +@OPENJDK@/jdk/src/share/classes/java/security/UnresolvedPermission.java +@OPENJDK@/jdk/src/share/classes/java/security/UnresolvedPermissionCollection.java +@OPENJDK@/jdk/src/share/classes/java/security/URIParameter.java +@OPENJDK@/jdk/src/share/classes/java/sql/Array.java +@OPENJDK@/jdk/src/share/classes/java/sql/BatchUpdateException.java +@OPENJDK@/jdk/src/share/classes/java/sql/Blob.java +@OPENJDK@/jdk/src/share/classes/java/sql/CallableStatement.java +@OPENJDK@/jdk/src/share/classes/java/sql/ClientInfoStatus.java +@OPENJDK@/jdk/src/share/classes/java/sql/Clob.java +@OPENJDK@/jdk/src/share/classes/java/sql/Connection.java +@OPENJDK@/jdk/src/share/classes/java/sql/DatabaseMetaData.java +@OPENJDK@/jdk/src/share/classes/java/sql/DataTruncation.java +@OPENJDK@/jdk/src/share/classes/java/sql/Date.java +@OPENJDK@/jdk/src/share/classes/java/sql/Driver.java +@OPENJDK@/jdk/src/share/classes/java/sql/DriverAction.java +@OPENJDK@/jdk/src/share/classes/java/sql/DriverManager.java +@OPENJDK@/jdk/src/share/classes/java/sql/DriverPropertyInfo.java +@OPENJDK@/jdk/src/share/classes/java/sql/JDBCType.java +@OPENJDK@/jdk/src/share/classes/java/sql/NClob.java +@OPENJDK@/jdk/src/share/classes/java/sql/ParameterMetaData.java +@OPENJDK@/jdk/src/share/classes/java/sql/PreparedStatement.java +@OPENJDK@/jdk/src/share/classes/java/sql/PseudoColumnUsage.java +@OPENJDK@/jdk/src/share/classes/java/sql/Ref.java +@OPENJDK@/jdk/src/share/classes/java/sql/ResultSet.java +@OPENJDK@/jdk/src/share/classes/java/sql/ResultSetMetaData.java +@OPENJDK@/jdk/src/share/classes/java/sql/RowId.java +@OPENJDK@/jdk/src/share/classes/java/sql/RowIdLifetime.java +@OPENJDK@/jdk/src/share/classes/java/sql/Savepoint.java +@OPENJDK@/jdk/src/share/classes/java/sql/SQLClientInfoException.java +@OPENJDK@/jdk/src/share/classes/java/sql/SQLData.java +@OPENJDK@/jdk/src/share/classes/java/sql/SQLDataException.java +@OPENJDK@/jdk/src/share/classes/java/sql/SQLException.java +@OPENJDK@/jdk/src/share/classes/java/sql/SQLFeatureNotSupportedException.java +@OPENJDK@/jdk/src/share/classes/java/sql/SQLInput.java +@OPENJDK@/jdk/src/share/classes/java/sql/SQLIntegrityConstraintViolationException.java +@OPENJDK@/jdk/src/share/classes/java/sql/SQLInvalidAuthorizationSpecException.java +@OPENJDK@/jdk/src/share/classes/java/sql/SQLNonTransientConnectionException.java +@OPENJDK@/jdk/src/share/classes/java/sql/SQLNonTransientException.java +@OPENJDK@/jdk/src/share/classes/java/sql/SQLOutput.java +@OPENJDK@/jdk/src/share/classes/java/sql/SQLPermission.java +@OPENJDK@/jdk/src/share/classes/java/sql/SQLRecoverableException.java +@OPENJDK@/jdk/src/share/classes/java/sql/SQLSyntaxErrorException.java +@OPENJDK@/jdk/src/share/classes/java/sql/SQLTimeoutException.java +@OPENJDK@/jdk/src/share/classes/java/sql/SQLTransactionRollbackException.java +@OPENJDK@/jdk/src/share/classes/java/sql/SQLTransientConnectionException.java +@OPENJDK@/jdk/src/share/classes/java/sql/SQLTransientException.java +@OPENJDK@/jdk/src/share/classes/java/sql/SQLType.java +@OPENJDK@/jdk/src/share/classes/java/sql/SQLWarning.java +@OPENJDK@/jdk/src/share/classes/java/sql/SQLXML.java +@OPENJDK@/jdk/src/share/classes/java/sql/Statement.java +@OPENJDK@/jdk/src/share/classes/java/sql/Struct.java +@OPENJDK@/jdk/src/share/classes/java/sql/Time.java +@OPENJDK@/jdk/src/share/classes/java/sql/Timestamp.java +@OPENJDK@/jdk/src/share/classes/java/sql/Types.java +@OPENJDK@/jdk/src/share/classes/java/sql/Wrapper.java +@OPENJDK@/jdk/src/share/classes/java/text/Annotation.java +@OPENJDK@/jdk/src/share/classes/java/text/AttributedCharacterIterator.java +@OPENJDK@/jdk/src/share/classes/java/text/AttributedString.java +@OPENJDK@/jdk/src/share/classes/java/text/Bidi.java +@OPENJDK@/jdk/src/share/classes/java/text/BreakIterator.java +@OPENJDK@/jdk/src/share/classes/java/text/CalendarBuilder.java +@OPENJDK@/jdk/src/share/classes/java/text/CharacterIterator.java +@OPENJDK@/jdk/src/share/classes/java/text/CharacterIteratorFieldDelegate.java +@OPENJDK@/jdk/src/share/classes/java/text/ChoiceFormat.java +@OPENJDK@/jdk/src/share/classes/java/text/CollationElementIterator.java +@OPENJDK@/jdk/src/share/classes/java/text/CollationKey.java +@OPENJDK@/jdk/src/share/classes/java/text/Collator.java +@OPENJDK@/jdk/src/share/classes/java/text/DateFormat.java +@OPENJDK@/jdk/src/share/classes/java/text/DateFormatSymbols.java +@OPENJDK@/jdk/src/share/classes/java/text/DecimalFormat.java +@OPENJDK@/jdk/src/share/classes/java/text/DecimalFormatSymbols.java +@OPENJDK@/jdk/src/share/classes/java/text/DigitList.java +@OPENJDK@/jdk/src/share/classes/java/text/DontCareFieldPosition.java +@OPENJDK@/jdk/src/share/classes/java/text/EntryPair.java +@OPENJDK@/jdk/src/share/classes/java/text/FieldPosition.java +@OPENJDK@/jdk/src/share/classes/java/text/Format.java +@OPENJDK@/jdk/src/share/classes/java/text/MergeCollation.java +@OPENJDK@/jdk/src/share/classes/java/text/MessageFormat.java +@OPENJDK@/jdk/src/share/classes/java/text/Normalizer.java +@OPENJDK@/jdk/src/share/classes/java/text/NumberFormat.java +@OPENJDK@/jdk/src/share/classes/java/text/ParseException.java +@OPENJDK@/jdk/src/share/classes/java/text/ParsePosition.java +@OPENJDK@/jdk/src/share/classes/java/text/PatternEntry.java +@OPENJDK@/jdk/src/share/classes/java/text/RBCollationTables.java +@OPENJDK@/jdk/src/share/classes/java/text/RBTableBuilder.java +@OPENJDK@/jdk/src/share/classes/java/text/RuleBasedCollationKey.java +@OPENJDK@/jdk/src/share/classes/java/text/RuleBasedCollator.java +@OPENJDK@/jdk/src/share/classes/java/text/SimpleDateFormat.java +@OPENJDK@/jdk/src/share/classes/java/text/spi/BreakIteratorProvider.java +@OPENJDK@/jdk/src/share/classes/java/text/spi/CollatorProvider.java +@OPENJDK@/jdk/src/share/classes/java/text/spi/DateFormatProvider.java +@OPENJDK@/jdk/src/share/classes/java/text/spi/DateFormatSymbolsProvider.java +@OPENJDK@/jdk/src/share/classes/java/text/spi/DecimalFormatSymbolsProvider.java +@OPENJDK@/jdk/src/share/classes/java/text/spi/NumberFormatProvider.java +@OPENJDK@/jdk/src/share/classes/java/text/StringCharacterIterator.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/AbstractChronology.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/ChronoLocalDate.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/ChronoLocalDateImpl.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/ChronoLocalDateTime.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/ChronoLocalDateTimeImpl.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/Chronology.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/ChronoPeriod.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/ChronoPeriodImpl.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/ChronoZonedDateTime.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/ChronoZonedDateTimeImpl.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/Era.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/HijrahChronology.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/HijrahDate.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/HijrahEra.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/IsoChronology.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/IsoEra.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/JapaneseChronology.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/JapaneseDate.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/JapaneseEra.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/MinguoChronology.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/MinguoDate.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/MinguoEra.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/Ser.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/ThaiBuddhistChronology.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/ThaiBuddhistDate.java +@OPENJDK@/jdk/src/share/classes/java/time/chrono/ThaiBuddhistEra.java +@OPENJDK@/jdk/src/share/classes/java/time/Clock.java +@OPENJDK@/jdk/src/share/classes/java/time/DateTimeException.java +@OPENJDK@/jdk/src/share/classes/java/time/DayOfWeek.java +@OPENJDK@/jdk/src/share/classes/java/time/Duration.java +@OPENJDK@/jdk/src/share/classes/java/time/format/DateTimeFormatter.java +@OPENJDK@/jdk/src/share/classes/java/time/format/DateTimeFormatterBuilder.java +@OPENJDK@/jdk/src/share/classes/java/time/format/DateTimeParseContext.java +@OPENJDK@/jdk/src/share/classes/java/time/format/DateTimeParseException.java +@OPENJDK@/jdk/src/share/classes/java/time/format/DateTimePrintContext.java +@OPENJDK@/jdk/src/share/classes/java/time/format/DateTimeTextProvider.java +@OPENJDK@/jdk/src/share/classes/java/time/format/DecimalStyle.java +@OPENJDK@/jdk/src/share/classes/java/time/format/FormatStyle.java +@OPENJDK@/jdk/src/share/classes/java/time/format/Parsed.java +@OPENJDK@/jdk/src/share/classes/java/time/format/ResolverStyle.java +@OPENJDK@/jdk/src/share/classes/java/time/format/SignStyle.java +@OPENJDK@/jdk/src/share/classes/java/time/format/TextStyle.java +@OPENJDK@/jdk/src/share/classes/java/time/format/ZoneName.java +@OPENJDK@/jdk/src/share/classes/java/time/Instant.java +@OPENJDK@/jdk/src/share/classes/java/time/LocalDate.java +@OPENJDK@/jdk/src/share/classes/java/time/LocalDateTime.java +@OPENJDK@/jdk/src/share/classes/java/time/LocalTime.java +@OPENJDK@/jdk/src/share/classes/java/time/Month.java +@OPENJDK@/jdk/src/share/classes/java/time/MonthDay.java +@OPENJDK@/jdk/src/share/classes/java/time/OffsetDateTime.java +@OPENJDK@/jdk/src/share/classes/java/time/OffsetTime.java +@OPENJDK@/jdk/src/share/classes/java/time/Period.java +@OPENJDK@/jdk/src/share/classes/java/time/Ser.java +@OPENJDK@/jdk/src/share/classes/java/time/temporal/ChronoField.java +@OPENJDK@/jdk/src/share/classes/java/time/temporal/ChronoUnit.java +@OPENJDK@/jdk/src/share/classes/java/time/temporal/IsoFields.java +@OPENJDK@/jdk/src/share/classes/java/time/temporal/JulianFields.java +@OPENJDK@/jdk/src/share/classes/java/time/temporal/Temporal.java +@OPENJDK@/jdk/src/share/classes/java/time/temporal/TemporalAccessor.java +@OPENJDK@/jdk/src/share/classes/java/time/temporal/TemporalAdjuster.java +@OPENJDK@/jdk/src/share/classes/java/time/temporal/TemporalAdjusters.java +@OPENJDK@/jdk/src/share/classes/java/time/temporal/TemporalAmount.java +@OPENJDK@/jdk/src/share/classes/java/time/temporal/TemporalField.java +@OPENJDK@/jdk/src/share/classes/java/time/temporal/TemporalQueries.java +@OPENJDK@/jdk/src/share/classes/java/time/temporal/TemporalQuery.java +@OPENJDK@/jdk/src/share/classes/java/time/temporal/TemporalUnit.java +@OPENJDK@/jdk/src/share/classes/java/time/temporal/UnsupportedTemporalTypeException.java +@OPENJDK@/jdk/src/share/classes/java/time/temporal/ValueRange.java +@OPENJDK@/jdk/src/share/classes/java/time/temporal/WeekFields.java +@OPENJDK@/jdk/src/share/classes/java/time/Year.java +@OPENJDK@/jdk/src/share/classes/java/time/YearMonth.java +@OPENJDK@/jdk/src/share/classes/java/time/zone/Ser.java +@OPENJDK@/jdk/src/share/classes/java/time/zone/TzdbZoneRulesProvider.java +@OPENJDK@/jdk/src/share/classes/java/time/zone/ZoneOffsetTransition.java +@OPENJDK@/jdk/src/share/classes/java/time/zone/ZoneOffsetTransitionRule.java +@OPENJDK@/jdk/src/share/classes/java/time/zone/ZoneRules.java +@OPENJDK@/jdk/src/share/classes/java/time/zone/ZoneRulesException.java +@OPENJDK@/jdk/src/share/classes/java/time/zone/ZoneRulesProvider.java +@OPENJDK@/jdk/src/share/classes/java/time/ZonedDateTime.java +@OPENJDK@/jdk/src/share/classes/java/time/ZoneId.java +@OPENJDK@/jdk/src/share/classes/java/time/ZoneOffset.java +@OPENJDK@/jdk/src/share/classes/java/time/ZoneRegion.java +@OPENJDK@/jdk/src/share/classes/java/util/AbstractCollection.java +@OPENJDK@/jdk/src/share/classes/java/util/AbstractList.java +@OPENJDK@/jdk/src/share/classes/java/util/AbstractMap.java +@OPENJDK@/jdk/src/share/classes/java/util/AbstractQueue.java +@OPENJDK@/jdk/src/share/classes/java/util/AbstractSequentialList.java +@OPENJDK@/jdk/src/share/classes/java/util/AbstractSet.java +@OPENJDK@/jdk/src/share/classes/java/util/ArrayDeque.java +@OPENJDK@/jdk/src/share/classes/java/util/ArrayList.java +@OPENJDK@/jdk/src/share/classes/java/util/ArrayPrefixHelpers.java +@OPENJDK@/jdk/src/share/classes/java/util/Arrays.java +@OPENJDK@/jdk/src/share/classes/java/util/ArraysParallelSortHelpers.java +@OPENJDK@/jdk/src/share/classes/java/util/Base64.java +@OPENJDK@/jdk/src/share/classes/java/util/BitSet.java +@OPENJDK@/jdk/src/share/classes/java/util/Calendar.java +@OPENJDK@/jdk/src/share/classes/java/util/Collection.java +@OPENJDK@/jdk/src/share/classes/java/util/Collections.java +@OPENJDK@/jdk/src/share/classes/java/util/ComparableTimSort.java +@OPENJDK@/jdk/src/share/classes/java/util/Comparator.java +@OPENJDK@/jdk/src/share/classes/java/util/Comparators.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/AbstractExecutorService.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ArrayBlockingQueue.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/atomic/DoubleAdder.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/atomic/LongAccumulator.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/atomic/LongAdder.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/atomic/package-info.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/BlockingDeque.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/BlockingQueue.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/BrokenBarrierException.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/Callable.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/CancellationException.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/CompletableFuture.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/CompletionException.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/CompletionService.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/CompletionStage.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ConcurrentHashMap.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ConcurrentMap.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ConcurrentNavigableMap.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListSet.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/CopyOnWriteArraySet.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/CountDownLatch.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/CountedCompleter.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/CyclicBarrier.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/Delayed.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/DelayQueue.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/Exchanger.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ExecutionException.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/Executor.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ExecutorCompletionService.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/Executors.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ExecutorService.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/Future.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/FutureTask.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/LinkedTransferQueue.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/locks/AbstractOwnableSynchronizer.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/locks/Condition.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/locks/Lock.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/locks/package-info.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/locks/ReadWriteLock.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/locks/ReentrantLock.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/locks/StampedLock.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/package-info.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/Phaser.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/RecursiveAction.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/RecursiveTask.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/RejectedExecutionException.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/RejectedExecutionHandler.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/RunnableFuture.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/RunnableScheduledFuture.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ScheduledExecutorService.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ScheduledFuture.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/Semaphore.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/SynchronousQueue.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ThreadFactory.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ThreadLocalRandom.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/TimeoutException.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/TimeUnit.java +@OPENJDK@/jdk/src/share/classes/java/util/concurrent/TransferQueue.java +@OPENJDK@/jdk/src/share/classes/java/util/ConcurrentModificationException.java +@OPENJDK@/jdk/src/share/classes/java/util/Currency.java +@OPENJDK@/jdk/src/share/classes/java/util/Date.java +@OPENJDK@/jdk/src/share/classes/java/util/Deque.java +@OPENJDK@/jdk/src/share/classes/java/util/Dictionary.java +@OPENJDK@/jdk/src/share/classes/java/util/DoubleSummaryStatistics.java +@OPENJDK@/jdk/src/share/classes/java/util/DualPivotQuicksort.java +@OPENJDK@/jdk/src/share/classes/java/util/DuplicateFormatFlagsException.java +@OPENJDK@/jdk/src/share/classes/java/util/EmptyStackException.java +@OPENJDK@/jdk/src/share/classes/java/util/Enumeration.java +@OPENJDK@/jdk/src/share/classes/java/util/EnumMap.java +@OPENJDK@/jdk/src/share/classes/java/util/EnumSet.java +@OPENJDK@/jdk/src/share/classes/java/util/EventListener.java +@OPENJDK@/jdk/src/share/classes/java/util/EventListenerProxy.java +@OPENJDK@/jdk/src/share/classes/java/util/EventObject.java +@OPENJDK@/jdk/src/share/classes/java/util/FormatFlagsConversionMismatchException.java +@OPENJDK@/jdk/src/share/classes/java/util/Formattable.java +@OPENJDK@/jdk/src/share/classes/java/util/FormattableFlags.java +@OPENJDK@/jdk/src/share/classes/java/util/Formatter.java +@OPENJDK@/jdk/src/share/classes/java/util/FormatterClosedException.java +@OPENJDK@/jdk/src/share/classes/java/util/function/BiConsumer.java +@OPENJDK@/jdk/src/share/classes/java/util/function/BiFunction.java +@OPENJDK@/jdk/src/share/classes/java/util/function/BinaryOperator.java +@OPENJDK@/jdk/src/share/classes/java/util/function/BiPredicate.java +@OPENJDK@/jdk/src/share/classes/java/util/function/BooleanSupplier.java +@OPENJDK@/jdk/src/share/classes/java/util/function/Consumer.java +@OPENJDK@/jdk/src/share/classes/java/util/function/DoubleBinaryOperator.java +@OPENJDK@/jdk/src/share/classes/java/util/function/DoubleConsumer.java +@OPENJDK@/jdk/src/share/classes/java/util/function/DoubleFunction.java +@OPENJDK@/jdk/src/share/classes/java/util/function/DoublePredicate.java +@OPENJDK@/jdk/src/share/classes/java/util/function/DoubleSupplier.java +@OPENJDK@/jdk/src/share/classes/java/util/function/DoubleToIntFunction.java +@OPENJDK@/jdk/src/share/classes/java/util/function/DoubleToLongFunction.java +@OPENJDK@/jdk/src/share/classes/java/util/function/DoubleUnaryOperator.java +@OPENJDK@/jdk/src/share/classes/java/util/function/Function.java +@OPENJDK@/jdk/src/share/classes/java/util/function/IntBinaryOperator.java +@OPENJDK@/jdk/src/share/classes/java/util/function/IntConsumer.java +@OPENJDK@/jdk/src/share/classes/java/util/function/IntFunction.java +@OPENJDK@/jdk/src/share/classes/java/util/function/IntPredicate.java +@OPENJDK@/jdk/src/share/classes/java/util/function/IntSupplier.java +@OPENJDK@/jdk/src/share/classes/java/util/function/IntToDoubleFunction.java +@OPENJDK@/jdk/src/share/classes/java/util/function/IntToLongFunction.java +@OPENJDK@/jdk/src/share/classes/java/util/function/IntUnaryOperator.java +@OPENJDK@/jdk/src/share/classes/java/util/function/LongBinaryOperator.java +@OPENJDK@/jdk/src/share/classes/java/util/function/LongConsumer.java +@OPENJDK@/jdk/src/share/classes/java/util/function/LongFunction.java +@OPENJDK@/jdk/src/share/classes/java/util/function/LongPredicate.java +@OPENJDK@/jdk/src/share/classes/java/util/function/LongSupplier.java +@OPENJDK@/jdk/src/share/classes/java/util/function/LongToDoubleFunction.java +@OPENJDK@/jdk/src/share/classes/java/util/function/LongToIntFunction.java +@OPENJDK@/jdk/src/share/classes/java/util/function/LongUnaryOperator.java +@OPENJDK@/jdk/src/share/classes/java/util/function/ObjDoubleConsumer.java +@OPENJDK@/jdk/src/share/classes/java/util/function/ObjIntConsumer.java +@OPENJDK@/jdk/src/share/classes/java/util/function/ObjLongConsumer.java +@OPENJDK@/jdk/src/share/classes/java/util/function/Predicate.java +@OPENJDK@/jdk/src/share/classes/java/util/function/Supplier.java +@OPENJDK@/jdk/src/share/classes/java/util/function/ToDoubleBiFunction.java +@OPENJDK@/jdk/src/share/classes/java/util/function/ToDoubleFunction.java +@OPENJDK@/jdk/src/share/classes/java/util/function/ToIntBiFunction.java +@OPENJDK@/jdk/src/share/classes/java/util/function/ToIntFunction.java +@OPENJDK@/jdk/src/share/classes/java/util/function/ToLongBiFunction.java +@OPENJDK@/jdk/src/share/classes/java/util/function/ToLongFunction.java +@OPENJDK@/jdk/src/share/classes/java/util/function/UnaryOperator.java +@OPENJDK@/jdk/src/share/classes/java/util/GregorianCalendar.java +@OPENJDK@/jdk/src/share/classes/java/util/HashMap.java +@OPENJDK@/jdk/src/share/classes/java/util/HashSet.java +@OPENJDK@/jdk/src/share/classes/java/util/Hashtable.java +@OPENJDK@/jdk/src/share/classes/java/util/IdentityHashMap.java +@OPENJDK@/jdk/src/share/classes/java/util/IllegalFormatCodePointException.java +@OPENJDK@/jdk/src/share/classes/java/util/IllegalFormatConversionException.java +@OPENJDK@/jdk/src/share/classes/java/util/IllegalFormatException.java +@OPENJDK@/jdk/src/share/classes/java/util/IllegalFormatFlagsException.java +@OPENJDK@/jdk/src/share/classes/java/util/IllegalFormatPrecisionException.java +@OPENJDK@/jdk/src/share/classes/java/util/IllegalFormatWidthException.java +@OPENJDK@/jdk/src/share/classes/java/util/IllformedLocaleException.java +@OPENJDK@/jdk/src/share/classes/java/util/InputMismatchException.java +@OPENJDK@/jdk/src/share/classes/java/util/IntSummaryStatistics.java +@OPENJDK@/jdk/src/share/classes/java/util/InvalidPropertiesFormatException.java +@OPENJDK@/jdk/src/share/classes/java/util/Iterator.java +@OPENJDK@/jdk/src/share/classes/java/util/JapaneseImperialCalendar.java +@OPENJDK@/jdk/src/share/classes/java/util/jar/Attributes.java +@OPENJDK@/jdk/src/share/classes/java/util/jar/JarEntry.java +@OPENJDK@/jdk/src/share/classes/java/util/jar/JarException.java +@OPENJDK@/jdk/src/share/classes/java/util/jar/JarFile.java +@OPENJDK@/jdk/src/share/classes/java/util/jar/JarInputStream.java +@OPENJDK@/jdk/src/share/classes/java/util/jar/JarOutputStream.java +@OPENJDK@/jdk/src/share/classes/java/util/jar/JarVerifier.java +@OPENJDK@/jdk/src/share/classes/java/util/jar/JavaUtilJarAccessImpl.java +@OPENJDK@/jdk/src/share/classes/java/util/jar/Manifest.java +@OPENJDK@/jdk/src/share/classes/java/util/jar/Pack200.java +@OPENJDK@/jdk/src/share/classes/java/util/JumboEnumSet.java +@OPENJDK@/jdk/src/share/classes/java/util/LinkedHashMap.java +@OPENJDK@/jdk/src/share/classes/java/util/LinkedHashSet.java +@OPENJDK@/jdk/src/share/classes/java/util/LinkedList.java +@OPENJDK@/jdk/src/share/classes/java/util/List.java +@OPENJDK@/jdk/src/share/classes/java/util/ListIterator.java +@OPENJDK@/jdk/src/share/classes/java/util/ListResourceBundle.java +@OPENJDK@/jdk/src/share/classes/java/util/Locale.java +@OPENJDK@/jdk/src/share/classes/java/util/LocaleISOData.java +@OPENJDK@/jdk/src/share/classes/java/util/logging/ConsoleHandler.java +@OPENJDK@/jdk/src/share/classes/java/util/logging/ErrorManager.java +@OPENJDK@/jdk/src/share/classes/java/util/logging/FileHandler.java +@OPENJDK@/jdk/src/share/classes/java/util/logging/Filter.java +@OPENJDK@/jdk/src/share/classes/java/util/logging/Formatter.java +@OPENJDK@/jdk/src/share/classes/java/util/logging/Handler.java +@OPENJDK@/jdk/src/share/classes/java/util/logging/Level.java +@OPENJDK@/jdk/src/share/classes/java/util/logging/Logger.java +@OPENJDK@/jdk/src/share/classes/java/util/logging/Logging.java +@OPENJDK@/jdk/src/share/classes/java/util/logging/LoggingMXBean.java +@OPENJDK@/jdk/src/share/classes/java/util/logging/LoggingPermission.java +@OPENJDK@/jdk/src/share/classes/java/util/logging/LoggingProxyImpl.java +@OPENJDK@/jdk/src/share/classes/java/util/logging/LogManager.java +@OPENJDK@/jdk/src/share/classes/java/util/logging/LogRecord.java +@OPENJDK@/jdk/src/share/classes/java/util/logging/MemoryHandler.java +@OPENJDK@/jdk/src/share/classes/java/util/logging/SimpleFormatter.java +@OPENJDK@/jdk/src/share/classes/java/util/logging/SocketHandler.java +@OPENJDK@/jdk/src/share/classes/java/util/logging/StreamHandler.java +@OPENJDK@/jdk/src/share/classes/java/util/logging/XMLFormatter.java +@OPENJDK@/jdk/src/share/classes/java/util/LongSummaryStatistics.java +@OPENJDK@/jdk/src/share/classes/java/util/Map.java +@OPENJDK@/jdk/src/share/classes/java/util/MissingFormatArgumentException.java +@OPENJDK@/jdk/src/share/classes/java/util/MissingFormatWidthException.java +@OPENJDK@/jdk/src/share/classes/java/util/MissingResourceException.java +@OPENJDK@/jdk/src/share/classes/java/util/NavigableMap.java +@OPENJDK@/jdk/src/share/classes/java/util/NavigableSet.java +@OPENJDK@/jdk/src/share/classes/java/util/NoSuchElementException.java +@OPENJDK@/jdk/src/share/classes/java/util/Objects.java +@OPENJDK@/jdk/src/share/classes/java/util/Observable.java +@OPENJDK@/jdk/src/share/classes/java/util/Observer.java +@OPENJDK@/jdk/src/share/classes/java/util/Optional.java +@OPENJDK@/jdk/src/share/classes/java/util/OptionalDouble.java +@OPENJDK@/jdk/src/share/classes/java/util/OptionalInt.java +@OPENJDK@/jdk/src/share/classes/java/util/OptionalLong.java +@OPENJDK@/jdk/src/share/classes/java/util/prefs/AbstractPreferences.java +@OPENJDK@/jdk/src/share/classes/java/util/prefs/BackingStoreException.java +@OPENJDK@/jdk/src/share/classes/java/util/prefs/Base64.java +@OPENJDK@/jdk/src/share/classes/java/util/prefs/InvalidPreferencesFormatException.java +@OPENJDK@/jdk/src/share/classes/java/util/prefs/NodeChangeEvent.java +@OPENJDK@/jdk/src/share/classes/java/util/prefs/NodeChangeListener.java +@OPENJDK@/jdk/src/share/classes/java/util/prefs/PreferenceChangeEvent.java +@OPENJDK@/jdk/src/share/classes/java/util/prefs/PreferenceChangeListener.java +@OPENJDK@/jdk/src/share/classes/java/util/prefs/Preferences.java +@OPENJDK@/jdk/src/share/classes/java/util/prefs/PreferencesFactory.java +@OPENJDK@/jdk/src/share/classes/java/util/prefs/XmlSupport.java +@OPENJDK@/jdk/src/share/classes/java/util/PrimitiveIterator.java +@OPENJDK@/jdk/src/share/classes/java/util/PriorityQueue.java +@OPENJDK@/jdk/src/share/classes/java/util/Properties.java +@OPENJDK@/jdk/src/share/classes/java/util/PropertyPermission.java +@OPENJDK@/jdk/src/share/classes/java/util/PropertyResourceBundle.java +@OPENJDK@/jdk/src/share/classes/java/util/Queue.java +@OPENJDK@/jdk/src/share/classes/java/util/Random.java +@OPENJDK@/jdk/src/share/classes/java/util/RandomAccess.java +@OPENJDK@/jdk/src/share/classes/java/util/regex/ASCII.java +@OPENJDK@/jdk/src/share/classes/java/util/regex/Matcher.java +@OPENJDK@/jdk/src/share/classes/java/util/regex/MatchResult.java +@OPENJDK@/jdk/src/share/classes/java/util/regex/Pattern.java +@OPENJDK@/jdk/src/share/classes/java/util/regex/PatternSyntaxException.java +@OPENJDK@/jdk/src/share/classes/java/util/regex/UnicodeProp.java +@OPENJDK@/jdk/src/share/classes/java/util/RegularEnumSet.java +@OPENJDK@/jdk/src/share/classes/java/util/ResourceBundle.java +@OPENJDK@/jdk/src/share/classes/java/util/Scanner.java +@OPENJDK@/jdk/src/share/classes/java/util/ServiceConfigurationError.java +@OPENJDK@/jdk/src/share/classes/java/util/ServiceLoader.java +@OPENJDK@/jdk/src/share/classes/java/util/Set.java +@OPENJDK@/jdk/src/share/classes/java/util/SimpleTimeZone.java +@OPENJDK@/jdk/src/share/classes/java/util/SortedMap.java +@OPENJDK@/jdk/src/share/classes/java/util/SortedSet.java +@OPENJDK@/jdk/src/share/classes/java/util/spi/CalendarDataProvider.java +@OPENJDK@/jdk/src/share/classes/java/util/spi/CalendarNameProvider.java +@OPENJDK@/jdk/src/share/classes/java/util/spi/CurrencyNameProvider.java +@OPENJDK@/jdk/src/share/classes/java/util/spi/LocaleNameProvider.java +@OPENJDK@/jdk/src/share/classes/java/util/spi/LocaleServiceProvider.java +@OPENJDK@/jdk/src/share/classes/java/util/spi/ResourceBundleControlProvider.java +@OPENJDK@/jdk/src/share/classes/java/util/spi/TimeZoneNameProvider.java +@OPENJDK@/jdk/src/share/classes/java/util/Spliterator.java +@OPENJDK@/jdk/src/share/classes/java/util/Spliterators.java +@OPENJDK@/jdk/src/share/classes/java/util/SplittableRandom.java +@OPENJDK@/jdk/src/share/classes/java/util/Stack.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/AbstractPipeline.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/AbstractShortCircuitTask.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/AbstractSpinedBuffer.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/AbstractTask.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/BaseStream.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/Collector.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/Collectors.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/DistinctOps.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/DoublePipeline.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/DoubleStream.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/FindOps.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/ForEachOps.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/IntPipeline.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/IntStream.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/LongPipeline.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/LongStream.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/MatchOps.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/Node.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/Nodes.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/PipelineHelper.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/ReduceOps.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/ReferencePipeline.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/Sink.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/SliceOps.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/SortedOps.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/SpinedBuffer.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/Stream.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/StreamOpFlag.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/Streams.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/StreamShape.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/StreamSpliterators.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/StreamSupport.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/TerminalOp.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/TerminalSink.java +@OPENJDK@/jdk/src/share/classes/java/util/stream/Tripwire.java +@OPENJDK@/jdk/src/share/classes/java/util/StringJoiner.java +@OPENJDK@/jdk/src/share/classes/java/util/StringTokenizer.java +@OPENJDK@/jdk/src/share/classes/java/util/Timer.java +@OPENJDK@/jdk/src/share/classes/java/util/TimerTask.java +@OPENJDK@/jdk/src/share/classes/java/util/TimeZone.java +@OPENJDK@/jdk/src/share/classes/java/util/TimSort.java +@OPENJDK@/jdk/src/share/classes/java/util/TooManyListenersException.java +@OPENJDK@/jdk/src/share/classes/java/util/TreeMap.java +@OPENJDK@/jdk/src/share/classes/java/util/TreeSet.java +@OPENJDK@/jdk/src/share/classes/java/util/Tripwire.java +@OPENJDK@/jdk/src/share/classes/java/util/UnknownFormatConversionException.java +@OPENJDK@/jdk/src/share/classes/java/util/UnknownFormatFlagsException.java +@OPENJDK@/jdk/src/share/classes/java/util/UUID.java +@OPENJDK@/jdk/src/share/classes/java/util/Vector.java +@OPENJDK@/jdk/src/share/classes/java/util/WeakHashMap.java +@OPENJDK@/jdk/src/share/classes/java/util/zip/CheckedInputStream.java +@OPENJDK@/jdk/src/share/classes/java/util/zip/CheckedOutputStream.java +@OPENJDK@/jdk/src/share/classes/java/util/zip/Checksum.java +@OPENJDK@/jdk/src/share/classes/java/util/zip/DataFormatException.java +@OPENJDK@/jdk/src/share/classes/java/util/zip/DeflaterInputStream.java +@OPENJDK@/jdk/src/share/classes/java/util/zip/DeflaterOutputStream.java +@OPENJDK@/jdk/src/share/classes/java/util/zip/GZIPInputStream.java +@OPENJDK@/jdk/src/share/classes/java/util/zip/GZIPOutputStream.java +@OPENJDK@/jdk/src/share/classes/java/util/zip/InflaterInputStream.java +@OPENJDK@/jdk/src/share/classes/java/util/zip/InflaterOutputStream.java +@OPENJDK@/jdk/src/share/classes/java/util/zip/ZipCoder.java +@OPENJDK@/jdk/src/share/classes/java/util/zip/ZipConstants.java +@OPENJDK@/jdk/src/share/classes/java/util/zip/ZipConstants64.java +@OPENJDK@/jdk/src/share/classes/java/util/zip/ZipError.java +@OPENJDK@/jdk/src/share/classes/java/util/zip/ZipException.java +@OPENJDK@/jdk/src/share/classes/java/util/zip/ZipInputStream.java +@OPENJDK@/jdk/src/share/classes/java/util/zip/ZipOutputStream.java +@OPENJDK@/jdk/src/share/classes/java/util/zip/ZipUtils.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/Accessible.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleAction.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleAttributeSequence.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleBundle.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleComponent.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleContext.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleEditableText.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleExtendedComponent.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleExtendedTable.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleExtendedText.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleHyperlink.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleHypertext.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleIcon.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleKeyBinding.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleRelation.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleRelationSet.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleResourceBundle.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleRole.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleSelection.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleState.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleStateSet.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleStreamable.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleTable.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleTableModelChange.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleText.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleTextSequence.java +@OPENJDK@/jdk/src/share/classes/javax/accessibility/AccessibleValue.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/AEADBadTagException.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/BadPaddingException.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/Cipher.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/CipherInputStream.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/CipherOutputStream.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/CipherSpi.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/CryptoAllPermission.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/CryptoPermission.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/CryptoPermissions.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/CryptoPolicyParser.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/EncryptedPrivateKeyInfo.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/ExemptionMechanism.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/ExemptionMechanismException.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/ExemptionMechanismSpi.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/IllegalBlockSizeException.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/interfaces/DHKey.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/interfaces/DHPrivateKey.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/interfaces/DHPublicKey.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/interfaces/PBEKey.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/JarVerifier.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/JceSecurity.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/JceSecurityManager.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/KeyAgreement.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/KeyAgreementSpi.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/KeyGenerator.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/KeyGeneratorSpi.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/Mac.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/MacSpi.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/NoSuchPaddingException.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/NullCipher.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/NullCipherSpi.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/SealedObject.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/SecretKey.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/SecretKeyFactory.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/SecretKeyFactorySpi.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/ShortBufferException.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/spec/DESedeKeySpec.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/spec/DESKeySpec.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/spec/DHGenParameterSpec.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/spec/DHParameterSpec.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/spec/DHPrivateKeySpec.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/spec/DHPublicKeySpec.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/spec/GCMParameterSpec.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/spec/IvParameterSpec.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/spec/OAEPParameterSpec.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/spec/PBEKeySpec.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/spec/PBEParameterSpec.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/spec/PSource.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/spec/RC2ParameterSpec.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/spec/RC5ParameterSpec.java +@OPENJDK@/jdk/src/share/classes/javax/crypto/spec/SecretKeySpec.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/event/IIOReadProgressListener.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/event/IIOReadUpdateListener.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/event/IIOReadWarningListener.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/event/IIOWriteProgressListener.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/event/IIOWriteWarningListener.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/IIOException.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/IIOImage.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/IIOParam.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/IIOParamController.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/ImageIO.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/ImageReader.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/ImageReadParam.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/ImageTranscoder.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/ImageTypeSpecifier.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/ImageWriteParam.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/ImageWriter.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/metadata/IIOInvalidTreeException.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/metadata/IIOMetadata.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/metadata/IIOMetadataController.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/metadata/IIOMetadataFormat.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/metadata/IIOMetadataFormatImpl.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/metadata/IIOMetadataNode.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/plugins/bmp/BMPImageWriteParam.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/plugins/jpeg/JPEGHuffmanTable.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/plugins/jpeg/JPEGImageReadParam.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/plugins/jpeg/JPEGImageWriteParam.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/plugins/jpeg/JPEGQTable.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/spi/DigraphNode.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/spi/IIORegistry.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/spi/IIOServiceProvider.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/spi/ImageInputStreamSpi.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/spi/ImageOutputStreamSpi.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/spi/ImageReaderSpi.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/spi/ImageReaderWriterSpi.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/spi/ImageTranscoderSpi.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/spi/ImageWriterSpi.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/spi/PartiallyOrderedSet.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/spi/RegisterableService.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/spi/ServiceRegistry.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/stream/FileCacheImageInputStream.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/stream/FileCacheImageOutputStream.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/stream/FileImageInputStream.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/stream/FileImageOutputStream.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/stream/IIOByteBuffer.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/stream/ImageInputStream.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/stream/ImageInputStreamImpl.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/stream/ImageOutputStream.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/stream/ImageOutputStreamImpl.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/stream/MemoryCache.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/stream/MemoryCacheImageInputStream.java +@OPENJDK@/jdk/src/share/classes/javax/imageio/stream/MemoryCacheImageOutputStream.java +@OPENJDK@/jdk/src/share/classes/javax/management/AndQueryExp.java +@OPENJDK@/jdk/src/share/classes/javax/management/Attribute.java +@OPENJDK@/jdk/src/share/classes/javax/management/AttributeChangeNotification.java +@OPENJDK@/jdk/src/share/classes/javax/management/AttributeChangeNotificationFilter.java +@OPENJDK@/jdk/src/share/classes/javax/management/AttributeList.java +@OPENJDK@/jdk/src/share/classes/javax/management/AttributeNotFoundException.java +@OPENJDK@/jdk/src/share/classes/javax/management/AttributeValueExp.java +@OPENJDK@/jdk/src/share/classes/javax/management/BadAttributeValueExpException.java +@OPENJDK@/jdk/src/share/classes/javax/management/BadBinaryOpValueExpException.java +@OPENJDK@/jdk/src/share/classes/javax/management/BadStringOperationException.java +@OPENJDK@/jdk/src/share/classes/javax/management/BetweenQueryExp.java +@OPENJDK@/jdk/src/share/classes/javax/management/BinaryOpValueExp.java +@OPENJDK@/jdk/src/share/classes/javax/management/BinaryRelQueryExp.java +@OPENJDK@/jdk/src/share/classes/javax/management/BooleanValueExp.java +@OPENJDK@/jdk/src/share/classes/javax/management/ClassAttributeValueExp.java +@OPENJDK@/jdk/src/share/classes/javax/management/DefaultLoaderRepository.java +@OPENJDK@/jdk/src/share/classes/javax/management/Descriptor.java +@OPENJDK@/jdk/src/share/classes/javax/management/DescriptorAccess.java +@OPENJDK@/jdk/src/share/classes/javax/management/DescriptorKey.java +@OPENJDK@/jdk/src/share/classes/javax/management/DescriptorRead.java +@OPENJDK@/jdk/src/share/classes/javax/management/DynamicMBean.java +@OPENJDK@/jdk/src/share/classes/javax/management/ImmutableDescriptor.java +@OPENJDK@/jdk/src/share/classes/javax/management/InQueryExp.java +@OPENJDK@/jdk/src/share/classes/javax/management/InstanceAlreadyExistsException.java +@OPENJDK@/jdk/src/share/classes/javax/management/InstanceNotFoundException.java +@OPENJDK@/jdk/src/share/classes/javax/management/InstanceOfQueryExp.java +@OPENJDK@/jdk/src/share/classes/javax/management/IntrospectionException.java +@OPENJDK@/jdk/src/share/classes/javax/management/InvalidApplicationException.java +@OPENJDK@/jdk/src/share/classes/javax/management/InvalidAttributeValueException.java +@OPENJDK@/jdk/src/share/classes/javax/management/JMException.java +@OPENJDK@/jdk/src/share/classes/javax/management/JMRuntimeException.java +@OPENJDK@/jdk/src/share/classes/javax/management/JMX.java +@OPENJDK@/jdk/src/share/classes/javax/management/ListenerNotFoundException.java +@OPENJDK@/jdk/src/share/classes/javax/management/loading/ClassLoaderRepository.java +@OPENJDK@/jdk/src/share/classes/javax/management/loading/DefaultLoaderRepository.java +@OPENJDK@/jdk/src/share/classes/javax/management/loading/MLet.java +@OPENJDK@/jdk/src/share/classes/javax/management/loading/MLetContent.java +@OPENJDK@/jdk/src/share/classes/javax/management/loading/MLetMBean.java +@OPENJDK@/jdk/src/share/classes/javax/management/loading/MLetObjectInputStream.java +@OPENJDK@/jdk/src/share/classes/javax/management/loading/MLetParser.java +@OPENJDK@/jdk/src/share/classes/javax/management/loading/PrivateClassLoader.java +@OPENJDK@/jdk/src/share/classes/javax/management/loading/PrivateMLet.java +@OPENJDK@/jdk/src/share/classes/javax/management/MalformedObjectNameException.java +@OPENJDK@/jdk/src/share/classes/javax/management/MatchQueryExp.java +@OPENJDK@/jdk/src/share/classes/javax/management/MBeanAttributeInfo.java +@OPENJDK@/jdk/src/share/classes/javax/management/MBeanConstructorInfo.java +@OPENJDK@/jdk/src/share/classes/javax/management/MBeanException.java +@OPENJDK@/jdk/src/share/classes/javax/management/MBeanFeatureInfo.java +@OPENJDK@/jdk/src/share/classes/javax/management/MBeanInfo.java +@OPENJDK@/jdk/src/share/classes/javax/management/MBeanNotificationInfo.java +@OPENJDK@/jdk/src/share/classes/javax/management/MBeanOperationInfo.java +@OPENJDK@/jdk/src/share/classes/javax/management/MBeanParameterInfo.java +@OPENJDK@/jdk/src/share/classes/javax/management/MBeanPermission.java +@OPENJDK@/jdk/src/share/classes/javax/management/MBeanRegistration.java +@OPENJDK@/jdk/src/share/classes/javax/management/MBeanRegistrationException.java +@OPENJDK@/jdk/src/share/classes/javax/management/MBeanServer.java +@OPENJDK@/jdk/src/share/classes/javax/management/MBeanServerBuilder.java +@OPENJDK@/jdk/src/share/classes/javax/management/MBeanServerConnection.java +@OPENJDK@/jdk/src/share/classes/javax/management/MBeanServerDelegate.java +@OPENJDK@/jdk/src/share/classes/javax/management/MBeanServerDelegateMBean.java +@OPENJDK@/jdk/src/share/classes/javax/management/MBeanServerFactory.java +@OPENJDK@/jdk/src/share/classes/javax/management/MBeanServerInvocationHandler.java +@OPENJDK@/jdk/src/share/classes/javax/management/MBeanServerNotification.java +@OPENJDK@/jdk/src/share/classes/javax/management/MBeanServerPermission.java +@OPENJDK@/jdk/src/share/classes/javax/management/MBeanTrustPermission.java +@OPENJDK@/jdk/src/share/classes/javax/management/modelmbean/DescriptorSupport.java +@OPENJDK@/jdk/src/share/classes/javax/management/modelmbean/InvalidTargetObjectTypeException.java +@OPENJDK@/jdk/src/share/classes/javax/management/modelmbean/ModelMBean.java +@OPENJDK@/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanAttributeInfo.java +@OPENJDK@/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanConstructorInfo.java +@OPENJDK@/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanInfo.java +@OPENJDK@/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanInfoSupport.java +@OPENJDK@/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationBroadcaster.java +@OPENJDK@/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationInfo.java +@OPENJDK@/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanOperationInfo.java +@OPENJDK@/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java +@OPENJDK@/jdk/src/share/classes/javax/management/modelmbean/XMLParseException.java +@OPENJDK@/jdk/src/share/classes/javax/management/monitor/CounterMonitor.java +@OPENJDK@/jdk/src/share/classes/javax/management/monitor/CounterMonitorMBean.java +@OPENJDK@/jdk/src/share/classes/javax/management/monitor/GaugeMonitor.java +@OPENJDK@/jdk/src/share/classes/javax/management/monitor/GaugeMonitorMBean.java +@OPENJDK@/jdk/src/share/classes/javax/management/monitor/Monitor.java +@OPENJDK@/jdk/src/share/classes/javax/management/monitor/MonitorMBean.java +@OPENJDK@/jdk/src/share/classes/javax/management/monitor/MonitorNotification.java +@OPENJDK@/jdk/src/share/classes/javax/management/monitor/MonitorSettingException.java +@OPENJDK@/jdk/src/share/classes/javax/management/monitor/StringMonitor.java +@OPENJDK@/jdk/src/share/classes/javax/management/monitor/StringMonitorMBean.java +@OPENJDK@/jdk/src/share/classes/javax/management/MXBean.java +@OPENJDK@/jdk/src/share/classes/javax/management/NotCompliantMBeanException.java +@OPENJDK@/jdk/src/share/classes/javax/management/Notification.java +@OPENJDK@/jdk/src/share/classes/javax/management/NotificationBroadcaster.java +@OPENJDK@/jdk/src/share/classes/javax/management/NotificationBroadcasterSupport.java +@OPENJDK@/jdk/src/share/classes/javax/management/NotificationEmitter.java +@OPENJDK@/jdk/src/share/classes/javax/management/NotificationFilter.java +@OPENJDK@/jdk/src/share/classes/javax/management/NotificationFilterSupport.java +@OPENJDK@/jdk/src/share/classes/javax/management/NotificationListener.java +@OPENJDK@/jdk/src/share/classes/javax/management/NotQueryExp.java +@OPENJDK@/jdk/src/share/classes/javax/management/NumericValueExp.java +@OPENJDK@/jdk/src/share/classes/javax/management/ObjectInstance.java +@OPENJDK@/jdk/src/share/classes/javax/management/ObjectName.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/ArrayType.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/CompositeData.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/CompositeDataInvocationHandler.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/CompositeDataSupport.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/CompositeDataView.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/CompositeType.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/InvalidKeyException.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/InvalidOpenTypeException.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/KeyAlreadyExistsException.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/OpenDataException.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/OpenMBeanAttributeInfo.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/OpenMBeanAttributeInfoSupport.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/OpenMBeanConstructorInfo.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/OpenMBeanConstructorInfoSupport.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/OpenMBeanInfo.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/OpenMBeanInfoSupport.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/OpenMBeanOperationInfo.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/OpenMBeanOperationInfoSupport.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/OpenMBeanParameterInfo.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/OpenMBeanParameterInfoSupport.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/OpenType.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/SimpleType.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/TabularData.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/TabularDataSupport.java +@OPENJDK@/jdk/src/share/classes/javax/management/openmbean/TabularType.java +@OPENJDK@/jdk/src/share/classes/javax/management/OperationsException.java +@OPENJDK@/jdk/src/share/classes/javax/management/OrQueryExp.java +@OPENJDK@/jdk/src/share/classes/javax/management/PersistentMBean.java +@OPENJDK@/jdk/src/share/classes/javax/management/QualifiedAttributeValueExp.java +@OPENJDK@/jdk/src/share/classes/javax/management/Query.java +@OPENJDK@/jdk/src/share/classes/javax/management/QueryEval.java +@OPENJDK@/jdk/src/share/classes/javax/management/QueryExp.java +@OPENJDK@/jdk/src/share/classes/javax/management/ReflectionException.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/InvalidRelationIdException.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/InvalidRelationServiceException.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/InvalidRelationTypeException.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/InvalidRoleInfoException.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/InvalidRoleValueException.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/MBeanServerNotificationFilter.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/Relation.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/RelationException.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/RelationNotFoundException.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/RelationNotification.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/RelationService.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/RelationServiceMBean.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/RelationServiceNotRegisteredException.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/RelationSupport.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/RelationSupportMBean.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/RelationType.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/RelationTypeNotFoundException.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/RelationTypeSupport.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/Role.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/RoleInfo.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/RoleInfoNotFoundException.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/RoleList.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/RoleNotFoundException.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/RoleResult.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/RoleStatus.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/RoleUnresolved.java +@OPENJDK@/jdk/src/share/classes/javax/management/relation/RoleUnresolvedList.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/JMXAddressable.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/JMXAuthenticator.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/JMXConnectionNotification.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/JMXConnector.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/JMXConnectorFactory.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/JMXConnectorProvider.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/JMXConnectorServer.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/JMXConnectorServerFactory.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/JMXConnectorServerMBean.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/JMXConnectorServerProvider.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/JMXPrincipal.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/JMXProviderException.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/JMXServerErrorException.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/JMXServiceURL.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/MBeanServerForwarder.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/NotificationResult.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/rmi/NoCallStackClassLoader.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/rmi/RMIConnection.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/rmi/RMIConnector.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/rmi/RMIIIOPServerImpl.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/rmi/RMIServer.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/rmi/RMIServerImpl.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/SubjectDelegationPermission.java +@OPENJDK@/jdk/src/share/classes/javax/management/remote/TargetedNotification.java +@OPENJDK@/jdk/src/share/classes/javax/management/RuntimeErrorException.java +@OPENJDK@/jdk/src/share/classes/javax/management/RuntimeMBeanException.java +@OPENJDK@/jdk/src/share/classes/javax/management/RuntimeOperationsException.java +@OPENJDK@/jdk/src/share/classes/javax/management/ServiceNotFoundException.java +@OPENJDK@/jdk/src/share/classes/javax/management/StandardEmitterMBean.java +@OPENJDK@/jdk/src/share/classes/javax/management/StandardMBean.java +@OPENJDK@/jdk/src/share/classes/javax/management/StringValueExp.java +@OPENJDK@/jdk/src/share/classes/javax/management/timer/Timer.java +@OPENJDK@/jdk/src/share/classes/javax/management/timer/TimerAlarmClock.java +@OPENJDK@/jdk/src/share/classes/javax/management/timer/TimerAlarmClockNotification.java +@OPENJDK@/jdk/src/share/classes/javax/management/timer/TimerMBean.java +@OPENJDK@/jdk/src/share/classes/javax/management/timer/TimerNotification.java +@OPENJDK@/jdk/src/share/classes/javax/management/ValueExp.java +@OPENJDK@/jdk/src/share/classes/javax/naming/AuthenticationException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/AuthenticationNotSupportedException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/BinaryRefAddr.java +@OPENJDK@/jdk/src/share/classes/javax/naming/Binding.java +@OPENJDK@/jdk/src/share/classes/javax/naming/CannotProceedException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/CommunicationException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/CompositeName.java +@OPENJDK@/jdk/src/share/classes/javax/naming/CompoundName.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ConfigurationException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/Context.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ContextNotEmptyException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/directory/Attribute.java +@OPENJDK@/jdk/src/share/classes/javax/naming/directory/AttributeInUseException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/directory/AttributeModificationException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/directory/Attributes.java +@OPENJDK@/jdk/src/share/classes/javax/naming/directory/BasicAttribute.java +@OPENJDK@/jdk/src/share/classes/javax/naming/directory/BasicAttributes.java +@OPENJDK@/jdk/src/share/classes/javax/naming/directory/DirContext.java +@OPENJDK@/jdk/src/share/classes/javax/naming/directory/InitialDirContext.java +@OPENJDK@/jdk/src/share/classes/javax/naming/directory/InvalidAttributeIdentifierException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/directory/InvalidAttributesException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/directory/InvalidAttributeValueException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/directory/InvalidSearchControlsException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/directory/InvalidSearchFilterException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/directory/ModificationItem.java +@OPENJDK@/jdk/src/share/classes/javax/naming/directory/NoSuchAttributeException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/directory/SchemaViolationException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/directory/SearchControls.java +@OPENJDK@/jdk/src/share/classes/javax/naming/directory/SearchResult.java +@OPENJDK@/jdk/src/share/classes/javax/naming/event/EventContext.java +@OPENJDK@/jdk/src/share/classes/javax/naming/event/EventDirContext.java +@OPENJDK@/jdk/src/share/classes/javax/naming/event/NamespaceChangeListener.java +@OPENJDK@/jdk/src/share/classes/javax/naming/event/NamingEvent.java +@OPENJDK@/jdk/src/share/classes/javax/naming/event/NamingExceptionEvent.java +@OPENJDK@/jdk/src/share/classes/javax/naming/event/NamingListener.java +@OPENJDK@/jdk/src/share/classes/javax/naming/event/ObjectChangeListener.java +@OPENJDK@/jdk/src/share/classes/javax/naming/InitialContext.java +@OPENJDK@/jdk/src/share/classes/javax/naming/InsufficientResourcesException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/InterruptedNamingException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/InvalidNameException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/BasicControl.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/Control.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/ControlFactory.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/ExtendedRequest.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/ExtendedResponse.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/HasControls.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/InitialLdapContext.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/LdapContext.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/LdapName.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/LdapReferralException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/ManageReferralControl.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/PagedResultsControl.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/PagedResultsResponseControl.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/Rdn.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/Rfc2253Parser.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/SortControl.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/SortKey.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/SortResponseControl.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/StartTlsRequest.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/StartTlsResponse.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/UnsolicitedNotification.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/UnsolicitedNotificationEvent.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ldap/UnsolicitedNotificationListener.java +@OPENJDK@/jdk/src/share/classes/javax/naming/LimitExceededException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/LinkException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/LinkLoopException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/LinkRef.java +@OPENJDK@/jdk/src/share/classes/javax/naming/MalformedLinkException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/Name.java +@OPENJDK@/jdk/src/share/classes/javax/naming/NameAlreadyBoundException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/NameClassPair.java +@OPENJDK@/jdk/src/share/classes/javax/naming/NameImpl.java +@OPENJDK@/jdk/src/share/classes/javax/naming/NameNotFoundException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/NameParser.java +@OPENJDK@/jdk/src/share/classes/javax/naming/NamingEnumeration.java +@OPENJDK@/jdk/src/share/classes/javax/naming/NamingException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/NamingSecurityException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/NoInitialContextException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/NoPermissionException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/NotContextException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/OperationNotSupportedException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/PartialResultException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/RefAddr.java +@OPENJDK@/jdk/src/share/classes/javax/naming/Reference.java +@OPENJDK@/jdk/src/share/classes/javax/naming/Referenceable.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ReferralException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/ServiceUnavailableException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/SizeLimitExceededException.java +@OPENJDK@/jdk/src/share/classes/javax/naming/spi/ContinuationContext.java +@OPENJDK@/jdk/src/share/classes/javax/naming/spi/ContinuationDirContext.java +@OPENJDK@/jdk/src/share/classes/javax/naming/spi/DirectoryManager.java +@OPENJDK@/jdk/src/share/classes/javax/naming/spi/DirObjectFactory.java +@OPENJDK@/jdk/src/share/classes/javax/naming/spi/DirStateFactory.java +@OPENJDK@/jdk/src/share/classes/javax/naming/spi/InitialContextFactory.java +@OPENJDK@/jdk/src/share/classes/javax/naming/spi/InitialContextFactoryBuilder.java +@OPENJDK@/jdk/src/share/classes/javax/naming/spi/NamingManager.java +@OPENJDK@/jdk/src/share/classes/javax/naming/spi/ObjectFactory.java +@OPENJDK@/jdk/src/share/classes/javax/naming/spi/ObjectFactoryBuilder.java +@OPENJDK@/jdk/src/share/classes/javax/naming/spi/Resolver.java +@OPENJDK@/jdk/src/share/classes/javax/naming/spi/ResolveResult.java +@OPENJDK@/jdk/src/share/classes/javax/naming/spi/StateFactory.java +@OPENJDK@/jdk/src/share/classes/javax/naming/StringRefAddr.java +@OPENJDK@/jdk/src/share/classes/javax/naming/TimeLimitExceededException.java +@OPENJDK@/jdk/src/share/classes/javax/net/ServerSocketFactory.java +@OPENJDK@/jdk/src/share/classes/javax/net/SocketFactory.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/CertPathTrustManagerParameters.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/ExtendedSSLSession.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/HandshakeCompletedEvent.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/HandshakeCompletedListener.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/HostnameVerifier.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/HttpsURLConnection.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/KeyManager.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/KeyManagerFactory.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/KeyManagerFactorySpi.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/KeyStoreBuilderParameters.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/ManagerFactoryParameters.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SNIHostName.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SNIMatcher.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SNIServerName.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SSLContext.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SSLContextSpi.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SSLEngine.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SSLEngineResult.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SSLException.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SSLHandshakeException.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SSLKeyException.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SSLParameters.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SSLPeerUnverifiedException.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SSLPermission.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SSLProtocolException.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SSLServerSocket.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SSLServerSocketFactory.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SSLSession.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SSLSessionBindingEvent.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SSLSessionBindingListener.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SSLSessionContext.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SSLSocket.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/SSLSocketFactory.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/StandardConstants.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/TrustManager.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/TrustManagerFactory.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/TrustManagerFactorySpi.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/X509ExtendedKeyManager.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/X509ExtendedTrustManager.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/X509KeyManager.java +@OPENJDK@/jdk/src/share/classes/javax/net/ssl/X509TrustManager.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/Attribute.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/AttributeSet.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/AttributeSetUtilities.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/DateTimeSyntax.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/DocAttribute.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/DocAttributeSet.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/EnumSyntax.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/HashAttributeSet.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/HashDocAttributeSet.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/HashPrintJobAttributeSet.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/HashPrintRequestAttributeSet.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/HashPrintServiceAttributeSet.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/IntegerSyntax.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/PrintJobAttribute.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/PrintJobAttributeSet.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/PrintRequestAttribute.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/PrintRequestAttributeSet.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/PrintServiceAttribute.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/PrintServiceAttributeSet.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/ResolutionSyntax.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/SetOfIntegerSyntax.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/Size2DSyntax.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/Chromaticity.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/ColorSupported.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/Compression.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/Copies.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/CopiesSupported.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/DateTimeAtCompleted.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/DateTimeAtCreation.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/DateTimeAtProcessing.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/Destination.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/DialogTypeSelection.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/DocumentName.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/Fidelity.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/Finishings.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/JobHoldUntil.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/JobImpressions.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/JobImpressionsCompleted.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/JobImpressionsSupported.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/JobKOctets.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/JobKOctetsProcessed.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/JobKOctetsSupported.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/JobMediaSheets.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/JobMediaSheetsCompleted.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/JobMediaSheetsSupported.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/JobMessageFromOperator.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/JobName.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/JobOriginatingUserName.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/JobPriority.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/JobPrioritySupported.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/JobSheets.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/JobState.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/JobStateReason.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/JobStateReasons.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/Media.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/MediaName.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/MediaPrintableArea.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/MediaSize.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/MediaSizeName.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/MediaTray.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/MultipleDocumentHandling.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/NumberOfDocuments.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/NumberOfInterveningJobs.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/NumberUp.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/NumberUpSupported.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/OrientationRequested.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/OutputDeviceAssigned.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/PageRanges.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/PagesPerMinute.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/PagesPerMinuteColor.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/PDLOverrideSupported.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/PresentationDirection.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/PrinterInfo.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/PrinterIsAcceptingJobs.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/PrinterLocation.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/PrinterMakeAndModel.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/PrinterMessageFromOperator.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/PrinterMoreInfo.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/PrinterMoreInfoManufacturer.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/PrinterName.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/PrinterResolution.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/PrinterState.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/PrinterStateReason.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/PrinterStateReasons.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/PrinterURI.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/PrintQuality.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/QueuedJobCount.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/ReferenceUriSchemesSupported.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/RequestingUserName.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/Severity.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/SheetCollate.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/Sides.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/SupportedValuesAttribute.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/TextSyntax.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/UnmodifiableSetException.java +@OPENJDK@/jdk/src/share/classes/javax/print/attribute/URISyntax.java +@OPENJDK@/jdk/src/share/classes/javax/print/AttributeException.java +@OPENJDK@/jdk/src/share/classes/javax/print/CancelablePrintJob.java +@OPENJDK@/jdk/src/share/classes/javax/print/Doc.java +@OPENJDK@/jdk/src/share/classes/javax/print/DocFlavor.java +@OPENJDK@/jdk/src/share/classes/javax/print/DocPrintJob.java +@OPENJDK@/jdk/src/share/classes/javax/print/event/PrintEvent.java +@OPENJDK@/jdk/src/share/classes/javax/print/event/PrintJobAdapter.java +@OPENJDK@/jdk/src/share/classes/javax/print/event/PrintJobAttributeEvent.java +@OPENJDK@/jdk/src/share/classes/javax/print/event/PrintJobAttributeListener.java +@OPENJDK@/jdk/src/share/classes/javax/print/event/PrintJobEvent.java +@OPENJDK@/jdk/src/share/classes/javax/print/event/PrintJobListener.java +@OPENJDK@/jdk/src/share/classes/javax/print/event/PrintServiceAttributeEvent.java +@OPENJDK@/jdk/src/share/classes/javax/print/event/PrintServiceAttributeListener.java +@OPENJDK@/jdk/src/share/classes/javax/print/FlavorException.java +@OPENJDK@/jdk/src/share/classes/javax/print/MimeType.java +@OPENJDK@/jdk/src/share/classes/javax/print/MultiDoc.java +@OPENJDK@/jdk/src/share/classes/javax/print/MultiDocPrintJob.java +@OPENJDK@/jdk/src/share/classes/javax/print/MultiDocPrintService.java +@OPENJDK@/jdk/src/share/classes/javax/print/PrintException.java +@OPENJDK@/jdk/src/share/classes/javax/print/PrintService.java +@OPENJDK@/jdk/src/share/classes/javax/print/PrintServiceLookup.java +@OPENJDK@/jdk/src/share/classes/javax/print/ServiceUI.java +@OPENJDK@/jdk/src/share/classes/javax/print/ServiceUIFactory.java +@OPENJDK@/jdk/src/share/classes/javax/print/SimpleDoc.java +@OPENJDK@/jdk/src/share/classes/javax/print/StreamPrintService.java +@OPENJDK@/jdk/src/share/classes/javax/print/StreamPrintServiceFactory.java +@OPENJDK@/jdk/src/share/classes/javax/print/URIException.java +@OPENJDK@/jdk/src/share/classes/javax/rmi/ssl/SslRMIClientSocketFactory.java +@OPENJDK@/jdk/src/share/classes/javax/rmi/ssl/SslRMIServerSocketFactory.java +@OPENJDK@/jdk/src/share/classes/javax/script/AbstractScriptEngine.java +@OPENJDK@/jdk/src/share/classes/javax/script/Bindings.java +@OPENJDK@/jdk/src/share/classes/javax/script/Compilable.java +@OPENJDK@/jdk/src/share/classes/javax/script/CompiledScript.java +@OPENJDK@/jdk/src/share/classes/javax/script/Invocable.java +@OPENJDK@/jdk/src/share/classes/javax/script/ScriptContext.java +@OPENJDK@/jdk/src/share/classes/javax/script/ScriptEngine.java +@OPENJDK@/jdk/src/share/classes/javax/script/ScriptEngineFactory.java +@OPENJDK@/jdk/src/share/classes/javax/script/ScriptEngineManager.java +@OPENJDK@/jdk/src/share/classes/javax/script/ScriptException.java +@OPENJDK@/jdk/src/share/classes/javax/script/SimpleBindings.java +@OPENJDK@/jdk/src/share/classes/javax/script/SimpleScriptContext.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/AuthPermission.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/callback/Callback.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/callback/CallbackHandler.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/callback/ChoiceCallback.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/callback/ConfirmationCallback.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/callback/LanguageCallback.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/callback/NameCallback.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/callback/PasswordCallback.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/callback/TextInputCallback.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/callback/TextOutputCallback.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/callback/UnsupportedCallbackException.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/Destroyable.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/DestroyFailedException.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/kerberos/DelegationPermission.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/kerberos/JavaxSecurityAuthKerberosAccessImpl.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/kerberos/KerberosKey.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/kerberos/KerberosPrincipal.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/kerberos/KeyImpl.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/kerberos/KeyTab.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/kerberos/ServicePermission.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/login/AccountException.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/login/AccountExpiredException.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/login/AccountLockedException.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/login/AccountNotFoundException.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/login/AppConfigurationEntry.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/login/Configuration.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/login/ConfigurationSpi.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/login/CredentialException.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/login/CredentialExpiredException.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/login/CredentialNotFoundException.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/login/FailedLoginException.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/login/LoginContext.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/login/LoginException.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/Policy.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/PrivateCredentialPermission.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/Refreshable.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/RefreshFailedException.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/spi/LoginModule.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/Subject.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/SubjectDomainCombiner.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/x500/X500Principal.java +@OPENJDK@/jdk/src/share/classes/javax/security/auth/x500/X500PrivateCredential.java +@OPENJDK@/jdk/src/share/classes/javax/security/cert/Certificate.java +@OPENJDK@/jdk/src/share/classes/javax/security/cert/CertificateEncodingException.java +@OPENJDK@/jdk/src/share/classes/javax/security/cert/CertificateException.java +@OPENJDK@/jdk/src/share/classes/javax/security/cert/CertificateExpiredException.java +@OPENJDK@/jdk/src/share/classes/javax/security/cert/CertificateNotYetValidException.java +@OPENJDK@/jdk/src/share/classes/javax/security/cert/CertificateParsingException.java +@OPENJDK@/jdk/src/share/classes/javax/security/cert/X509Certificate.java +@OPENJDK@/jdk/src/share/classes/javax/security/sasl/AuthenticationException.java +@OPENJDK@/jdk/src/share/classes/javax/security/sasl/AuthorizeCallback.java +@OPENJDK@/jdk/src/share/classes/javax/security/sasl/RealmCallback.java +@OPENJDK@/jdk/src/share/classes/javax/security/sasl/RealmChoiceCallback.java +@OPENJDK@/jdk/src/share/classes/javax/security/sasl/Sasl.java +@OPENJDK@/jdk/src/share/classes/javax/security/sasl/SaslClient.java +@OPENJDK@/jdk/src/share/classes/javax/security/sasl/SaslClientFactory.java +@OPENJDK@/jdk/src/share/classes/javax/security/sasl/SaslException.java +@OPENJDK@/jdk/src/share/classes/javax/security/sasl/SaslServer.java +@OPENJDK@/jdk/src/share/classes/javax/security/sasl/SaslServerFactory.java +@OPENJDK@/jdk/src/share/classes/javax/smartcardio/ATR.java +@OPENJDK@/jdk/src/share/classes/javax/smartcardio/Card.java +@OPENJDK@/jdk/src/share/classes/javax/smartcardio/CardChannel.java +@OPENJDK@/jdk/src/share/classes/javax/smartcardio/CardException.java +@OPENJDK@/jdk/src/share/classes/javax/smartcardio/CardNotPresentException.java +@OPENJDK@/jdk/src/share/classes/javax/smartcardio/CardPermission.java +@OPENJDK@/jdk/src/share/classes/javax/smartcardio/CardTerminal.java +@OPENJDK@/jdk/src/share/classes/javax/smartcardio/CardTerminals.java +@OPENJDK@/jdk/src/share/classes/javax/smartcardio/CommandAPDU.java +@OPENJDK@/jdk/src/share/classes/javax/smartcardio/ResponseAPDU.java +@OPENJDK@/jdk/src/share/classes/javax/smartcardio/TerminalFactory.java +@OPENJDK@/jdk/src/share/classes/javax/smartcardio/TerminalFactorySpi.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/ControllerEventListener.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/Instrument.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/InvalidMidiDataException.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/MetaEventListener.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/MetaMessage.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/MidiChannel.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/MidiDevice.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/MidiDeviceReceiver.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/MidiDeviceTransmitter.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/MidiEvent.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/MidiFileFormat.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/MidiMessage.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/MidiSystem.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/MidiUnavailableException.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/Patch.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/Receiver.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/Sequence.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/Sequencer.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/ShortMessage.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/Soundbank.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/SoundbankResource.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/spi/MidiDeviceProvider.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/spi/MidiFileReader.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/spi/MidiFileWriter.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/spi/SoundbankReader.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/Synthesizer.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/SysexMessage.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/Track.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/Transmitter.java +@OPENJDK@/jdk/src/share/classes/javax/sound/midi/VoiceStatus.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/AudioFileFormat.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/AudioFormat.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/AudioInputStream.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/AudioPermission.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/AudioSystem.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/BooleanControl.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/Clip.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/CompoundControl.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/Control.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/DataLine.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/EnumControl.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/FloatControl.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/Line.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/LineEvent.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/LineListener.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/LineUnavailableException.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/Mixer.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/Port.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/ReverbType.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/SourceDataLine.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/spi/AudioFileReader.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/spi/AudioFileWriter.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/spi/FormatConversionProvider.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/spi/MixerProvider.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/TargetDataLine.java +@OPENJDK@/jdk/src/share/classes/javax/sound/sampled/UnsupportedAudioFileException.java +@OPENJDK@/jdk/src/share/classes/javax/sql/CommonDataSource.java +@OPENJDK@/jdk/src/share/classes/javax/sql/ConnectionEvent.java +@OPENJDK@/jdk/src/share/classes/javax/sql/ConnectionEventListener.java +@OPENJDK@/jdk/src/share/classes/javax/sql/ConnectionPoolDataSource.java +@OPENJDK@/jdk/src/share/classes/javax/sql/DataSource.java +@OPENJDK@/jdk/src/share/classes/javax/sql/PooledConnection.java +@OPENJDK@/jdk/src/share/classes/javax/sql/RowSet.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/BaseRowSet.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/CachedRowSet.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/FilteredRowSet.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/JdbcRowSet.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/Joinable.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/JoinRowSet.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/Predicate.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/RowSetFactory.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/RowSetMetaDataImpl.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/RowSetProvider.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/RowSetWarning.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/serial/SerialArray.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/serial/SerialBlob.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/serial/SerialClob.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/serial/SerialDatalink.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/serial/SerialException.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/serial/SerialJavaObject.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/serial/SerialRef.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/serial/SerialStruct.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/serial/SQLInputImpl.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/serial/SQLOutputImpl.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/spi/SyncFactory.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/spi/SyncFactoryException.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/spi/SyncProvider.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/spi/SyncProviderException.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/spi/SyncResolver.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/spi/TransactionalWriter.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/spi/XmlReader.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/spi/XmlWriter.java +@OPENJDK@/jdk/src/share/classes/javax/sql/rowset/WebRowSet.java +@OPENJDK@/jdk/src/share/classes/javax/sql/RowSetEvent.java +@OPENJDK@/jdk/src/share/classes/javax/sql/RowSetInternal.java +@OPENJDK@/jdk/src/share/classes/javax/sql/RowSetListener.java +@OPENJDK@/jdk/src/share/classes/javax/sql/RowSetMetaData.java +@OPENJDK@/jdk/src/share/classes/javax/sql/RowSetReader.java +@OPENJDK@/jdk/src/share/classes/javax/sql/RowSetWriter.java +@OPENJDK@/jdk/src/share/classes/javax/sql/StatementEvent.java +@OPENJDK@/jdk/src/share/classes/javax/sql/StatementEventListener.java +@OPENJDK@/jdk/src/share/classes/javax/sql/XAConnection.java +@OPENJDK@/jdk/src/share/classes/javax/sql/XADataSource.java +@OPENJDK@/jdk/src/share/classes/javax/swing/AbstractAction.java +@OPENJDK@/jdk/src/share/classes/javax/swing/AbstractButton.java +@OPENJDK@/jdk/src/share/classes/javax/swing/AbstractCellEditor.java +@OPENJDK@/jdk/src/share/classes/javax/swing/AbstractListModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/AbstractSpinnerModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/Action.java +@OPENJDK@/jdk/src/share/classes/javax/swing/ActionMap.java +@OPENJDK@/jdk/src/share/classes/javax/swing/ActionPropertyChangeListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/AncestorNotifier.java +@OPENJDK@/jdk/src/share/classes/javax/swing/ArrayTable.java +@OPENJDK@/jdk/src/share/classes/javax/swing/Autoscroller.java +@OPENJDK@/jdk/src/share/classes/javax/swing/border/AbstractBorder.java +@OPENJDK@/jdk/src/share/classes/javax/swing/border/BevelBorder.java +@OPENJDK@/jdk/src/share/classes/javax/swing/border/Border.java +@OPENJDK@/jdk/src/share/classes/javax/swing/border/CompoundBorder.java +@OPENJDK@/jdk/src/share/classes/javax/swing/border/EmptyBorder.java +@OPENJDK@/jdk/src/share/classes/javax/swing/border/EtchedBorder.java +@OPENJDK@/jdk/src/share/classes/javax/swing/border/LineBorder.java +@OPENJDK@/jdk/src/share/classes/javax/swing/border/MatteBorder.java +@OPENJDK@/jdk/src/share/classes/javax/swing/border/SoftBevelBorder.java +@OPENJDK@/jdk/src/share/classes/javax/swing/border/StrokeBorder.java +@OPENJDK@/jdk/src/share/classes/javax/swing/border/TitledBorder.java +@OPENJDK@/jdk/src/share/classes/javax/swing/BorderFactory.java +@OPENJDK@/jdk/src/share/classes/javax/swing/BoundedRangeModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/Box.java +@OPENJDK@/jdk/src/share/classes/javax/swing/BoxLayout.java +@OPENJDK@/jdk/src/share/classes/javax/swing/BufferStrategyPaintManager.java +@OPENJDK@/jdk/src/share/classes/javax/swing/ButtonGroup.java +@OPENJDK@/jdk/src/share/classes/javax/swing/ButtonModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/CellEditor.java +@OPENJDK@/jdk/src/share/classes/javax/swing/CellRendererPane.java +@OPENJDK@/jdk/src/share/classes/javax/swing/ClientPropertyKey.java +@OPENJDK@/jdk/src/share/classes/javax/swing/colorchooser/AbstractColorChooserPanel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/colorchooser/CenterLayout.java +@OPENJDK@/jdk/src/share/classes/javax/swing/colorchooser/ColorChooserComponentFactory.java +@OPENJDK@/jdk/src/share/classes/javax/swing/colorchooser/ColorChooserPanel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/colorchooser/ColorModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/colorchooser/ColorModelCMYK.java +@OPENJDK@/jdk/src/share/classes/javax/swing/colorchooser/ColorModelHSL.java +@OPENJDK@/jdk/src/share/classes/javax/swing/colorchooser/ColorModelHSV.java +@OPENJDK@/jdk/src/share/classes/javax/swing/colorchooser/ColorPanel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/colorchooser/ColorSelectionModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/colorchooser/DefaultColorSelectionModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/colorchooser/DefaultPreviewPanel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/colorchooser/DefaultSwatchChooserPanel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/colorchooser/DiagramComponent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/colorchooser/SlidingSpinner.java +@OPENJDK@/jdk/src/share/classes/javax/swing/colorchooser/SmartGridLayout.java +@OPENJDK@/jdk/src/share/classes/javax/swing/colorchooser/ValueFormatter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/ComboBoxEditor.java +@OPENJDK@/jdk/src/share/classes/javax/swing/ComboBoxModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/ComponentInputMap.java +@OPENJDK@/jdk/src/share/classes/javax/swing/DebugGraphics.java +@OPENJDK@/jdk/src/share/classes/javax/swing/DebugGraphicsFilter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/DebugGraphicsInfo.java +@OPENJDK@/jdk/src/share/classes/javax/swing/DebugGraphicsObserver.java +@OPENJDK@/jdk/src/share/classes/javax/swing/DefaultBoundedRangeModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/DefaultButtonModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/DefaultCellEditor.java +@OPENJDK@/jdk/src/share/classes/javax/swing/DefaultComboBoxModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java +@OPENJDK@/jdk/src/share/classes/javax/swing/DefaultFocusManager.java +@OPENJDK@/jdk/src/share/classes/javax/swing/DefaultListCellRenderer.java +@OPENJDK@/jdk/src/share/classes/javax/swing/DefaultListModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/DefaultListSelectionModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/DefaultRowSorter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/DefaultSingleSelectionModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/DelegatingDefaultFocusManager.java +@OPENJDK@/jdk/src/share/classes/javax/swing/DesktopManager.java +@OPENJDK@/jdk/src/share/classes/javax/swing/DropMode.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/AncestorEvent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/AncestorListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/CaretEvent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/CaretListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/CellEditorListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/ChangeEvent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/ChangeListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/DocumentEvent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/DocumentListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/EventListenerList.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/HyperlinkEvent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/HyperlinkListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/InternalFrameAdapter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/InternalFrameEvent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/InternalFrameListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/ListDataEvent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/ListDataListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/ListSelectionEvent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/ListSelectionListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/MenuDragMouseEvent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/MenuDragMouseListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/MenuEvent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/MenuKeyEvent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/MenuKeyListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/MenuListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/MouseInputAdapter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/MouseInputListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/PopupMenuEvent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/PopupMenuListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/RowSorterEvent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/RowSorterListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/SwingPropertyChangeSupport.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/TableColumnModelEvent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/TableColumnModelListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/TableModelEvent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/TableModelListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/TreeExpansionEvent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/TreeExpansionListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/TreeModelEvent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/TreeModelListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/TreeSelectionEvent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/TreeSelectionListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/TreeWillExpandListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/UndoableEditEvent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/event/UndoableEditListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/filechooser/FileFilter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/filechooser/FileNameExtensionFilter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/filechooser/FileSystemView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/filechooser/FileView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/FocusManager.java +@OPENJDK@/jdk/src/share/classes/javax/swing/GraphicsWrapper.java +@OPENJDK@/jdk/src/share/classes/javax/swing/GrayFilter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/GroupLayout.java +@OPENJDK@/jdk/src/share/classes/javax/swing/Icon.java +@OPENJDK@/jdk/src/share/classes/javax/swing/ImageIcon.java +@OPENJDK@/jdk/src/share/classes/javax/swing/InputMap.java +@OPENJDK@/jdk/src/share/classes/javax/swing/InputVerifier.java +@OPENJDK@/jdk/src/share/classes/javax/swing/InternalFrameFocusTraversalPolicy.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JApplet.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JButton.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JCheckBox.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JCheckBoxMenuItem.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JColorChooser.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JComboBox.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JComponent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JDesktopPane.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JDialog.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JEditorPane.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JFileChooser.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JFormattedTextField.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JFrame.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JInternalFrame.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JLabel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JLayer.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JLayeredPane.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JList.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JMenu.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JMenuBar.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JMenuItem.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JOptionPane.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JPanel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JPasswordField.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JPopupMenu.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JProgressBar.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JRadioButton.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JRadioButtonMenuItem.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JRootPane.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JScrollBar.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JScrollPane.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JSeparator.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JSlider.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JSpinner.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JSplitPane.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JTabbedPane.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JTable.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JTextArea.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JTextField.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JTextPane.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JToggleButton.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JToolBar.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JToolTip.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JTree.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JViewport.java +@OPENJDK@/jdk/src/share/classes/javax/swing/JWindow.java +@OPENJDK@/jdk/src/share/classes/javax/swing/KeyboardManager.java +@OPENJDK@/jdk/src/share/classes/javax/swing/KeyStroke.java +@OPENJDK@/jdk/src/share/classes/javax/swing/LayoutComparator.java +@OPENJDK@/jdk/src/share/classes/javax/swing/LayoutFocusTraversalPolicy.java +@OPENJDK@/jdk/src/share/classes/javax/swing/LayoutStyle.java +@OPENJDK@/jdk/src/share/classes/javax/swing/LegacyGlueFocusTraversalPolicy.java +@OPENJDK@/jdk/src/share/classes/javax/swing/ListCellRenderer.java +@OPENJDK@/jdk/src/share/classes/javax/swing/ListModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/ListSelectionModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/LookAndFeel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/MenuElement.java +@OPENJDK@/jdk/src/share/classes/javax/swing/MenuSelectionManager.java +@OPENJDK@/jdk/src/share/classes/javax/swing/MultiUIDefaults.java +@OPENJDK@/jdk/src/share/classes/javax/swing/MutableComboBoxModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/OverlayLayout.java +@OPENJDK@/jdk/src/share/classes/javax/swing/Painter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/ActionMapUIResource.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicArrowButton.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicBorders.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicButtonListener.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicButtonUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicCheckBoxUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicColorChooserUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicComboBoxEditor.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicComboBoxRenderer.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicComboPopup.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicDesktopIconUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicDesktopPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicEditorPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicGraphicsUtils.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicHTML.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicIconFactory.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicInternalFrameUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicLabelUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicListUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicMenuBarUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicMenuUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicPanelUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicPasswordFieldUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicPopupMenuSeparatorUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicProgressBarUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicRadioButtonUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicRootPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicSeparatorUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicSliderUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicSpinnerUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicSplitPaneDivider.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicSplitPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicTableHeaderUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicTableUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicTextAreaUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicTextFieldUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicTextPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicTextUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicToggleButtonUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicToolBarUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicToolTipUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicTransferable.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicTreeUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/BasicViewportUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/CenterLayout.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/ComboPopup.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/DefaultMenuLayout.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/DragRecognitionSupport.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/LazyActionMap.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/BorderUIResource.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/ButtonUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/ColorChooserUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/ColorUIResource.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/ComboBoxUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/ComponentInputMapUIResource.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/ComponentUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/DesktopIconUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/DesktopPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/DimensionUIResource.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/FileChooserUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/FontUIResource.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/IconUIResource.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/InputMapUIResource.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/InsetsUIResource.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/InternalFrameUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/LabelUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/LayerUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/ListUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/MenuBarUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/MenuItemUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/DefaultMetalTheme.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalBorders.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalBumps.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalButtonUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalCheckBoxIcon.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalCheckBoxUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalComboBoxButton.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalComboBoxEditor.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalComboBoxIcon.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalComboBoxUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalDesktopIconUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalFontDesktopProperty.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalHighContrastTheme.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalIconFactory.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalInternalFrameUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalLabelUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalMenuBarUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalProgressBarUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalRadioButtonUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalRootPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalScrollBarUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalScrollButton.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalScrollPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalSeparatorUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalSliderUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalSplitPaneDivider.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalSplitPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalTabbedPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalTextFieldUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalTheme.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalTitlePane.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalToggleButtonUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalToolBarUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalToolTipUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalTreeUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/MetalUtils.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/OceanTheme.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiButtonUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiColorChooserUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiComboBoxUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiDesktopIconUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiDesktopPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiFileChooserUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiInternalFrameUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiLabelUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiListUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiLookAndFeel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiMenuBarUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiMenuItemUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiOptionPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiPanelUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiPopupMenuUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiProgressBarUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiRootPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiScrollBarUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiScrollPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiSeparatorUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiSliderUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiSpinnerUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiSplitPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiTabbedPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiTableHeaderUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiTableUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiTextUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiToolBarUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiToolTipUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiTreeUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/MultiViewportUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/nimbus/AbstractRegionPainter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/nimbus/DerivedColor.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/nimbus/DropShadowEffect.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/nimbus/Effect.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/nimbus/EffectUtils.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/nimbus/ImageCache.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/nimbus/ImageScalingHelper.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/nimbus/InnerGlowEffect.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/nimbus/InnerShadowEffect.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/nimbus/LoweredBorder.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/nimbus/NimbusIcon.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/nimbus/NimbusStyle.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/nimbus/OuterGlowEffect.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/nimbus/ShadowEffect.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/nimbus/State.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/nimbus/TableScrollPaneCorner.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/nimbus/ToolBarSeparatorPainter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/OptionPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/PanelUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/PopupMenuUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/ProgressBarUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/RootPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/ScrollBarUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/ScrollPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/SeparatorUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/SliderUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/SpinnerUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/SplitPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/ColorType.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/DefaultSynthStyleFactory.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/ImagePainter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/ParsedSynthStyle.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/Region.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthArrowButton.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthBorder.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthButtonUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthCheckBoxMenuItemUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthCheckBoxUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthColorChooserUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthComboPopup.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthConstants.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthContext.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthDefaultLookup.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthDesktopIconUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthEditorPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthFormattedTextFieldUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthGraphicsUtils.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthInternalFrameTitlePane.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthInternalFrameUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthLabelUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthListUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthMenuBarUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthMenuItemLayoutHelper.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthMenuItemUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthMenuLayout.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthMenuUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthOptionPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthPainter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthPanelUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthParser.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthPasswordFieldUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthPopupMenuUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthRadioButtonMenuItemUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthRadioButtonUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthRootPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthScrollBarUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthScrollPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthSeparatorUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthSpinnerUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthSplitPaneDivider.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthStyle.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthStyleFactory.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthTableUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthTextAreaUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthTextFieldUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthTextPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthToggleButtonUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthToolTipUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthTreeUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/SynthViewportUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/TabbedPaneUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/TableHeaderUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/TableUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/TextUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/ToolBarUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/ToolTipUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/TreeUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/UIResource.java +@OPENJDK@/jdk/src/share/classes/javax/swing/plaf/ViewportUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/Popup.java +@OPENJDK@/jdk/src/share/classes/javax/swing/PopupFactory.java +@OPENJDK@/jdk/src/share/classes/javax/swing/ProgressMonitor.java +@OPENJDK@/jdk/src/share/classes/javax/swing/ProgressMonitorInputStream.java +@OPENJDK@/jdk/src/share/classes/javax/swing/Renderer.java +@OPENJDK@/jdk/src/share/classes/javax/swing/RepaintManager.java +@OPENJDK@/jdk/src/share/classes/javax/swing/RootPaneContainer.java +@OPENJDK@/jdk/src/share/classes/javax/swing/RowFilter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/RowSorter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/Scrollable.java +@OPENJDK@/jdk/src/share/classes/javax/swing/ScrollPaneConstants.java +@OPENJDK@/jdk/src/share/classes/javax/swing/ScrollPaneLayout.java +@OPENJDK@/jdk/src/share/classes/javax/swing/SingleSelectionModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/SizeRequirements.java +@OPENJDK@/jdk/src/share/classes/javax/swing/SizeSequence.java +@OPENJDK@/jdk/src/share/classes/javax/swing/SortingFocusTraversalPolicy.java +@OPENJDK@/jdk/src/share/classes/javax/swing/SortOrder.java +@OPENJDK@/jdk/src/share/classes/javax/swing/SpinnerDateModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/SpinnerListModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/SpinnerModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/SpinnerNumberModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/Spring.java +@OPENJDK@/jdk/src/share/classes/javax/swing/SpringLayout.java +@OPENJDK@/jdk/src/share/classes/javax/swing/SwingConstants.java +@OPENJDK@/jdk/src/share/classes/javax/swing/SwingHeavyWeight.java +@OPENJDK@/jdk/src/share/classes/javax/swing/SwingPaintEventDispatcher.java +@OPENJDK@/jdk/src/share/classes/javax/swing/SwingUtilities.java +@OPENJDK@/jdk/src/share/classes/javax/swing/SwingWorker.java +@OPENJDK@/jdk/src/share/classes/javax/swing/table/AbstractTableModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/table/DefaultTableCellRenderer.java +@OPENJDK@/jdk/src/share/classes/javax/swing/table/DefaultTableColumnModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/table/DefaultTableModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/table/JTableHeader.java +@OPENJDK@/jdk/src/share/classes/javax/swing/table/TableCellEditor.java +@OPENJDK@/jdk/src/share/classes/javax/swing/table/TableCellRenderer.java +@OPENJDK@/jdk/src/share/classes/javax/swing/table/TableColumn.java +@OPENJDK@/jdk/src/share/classes/javax/swing/table/TableColumnModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/table/TableModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/table/TableRowSorter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/table/TableStringConverter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/TablePrintable.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/AbstractDocument.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/AbstractWriter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/AsyncBoxView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/AttributeSet.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/BadLocationException.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/BoxView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/Caret.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/ChangedCharSetException.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/ComponentView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/CompositeView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/DateFormatter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/DefaultCaret.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/DefaultEditorKit.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/DefaultFormatter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/DefaultFormatterFactory.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/DefaultHighlighter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/DefaultStyledDocument.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/DefaultTextUI.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/Document.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/DocumentFilter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/EditorKit.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/Element.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/ElementIterator.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/FieldView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/FlowView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/GapContent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/GapVector.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/GlyphPainter1.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/GlyphPainter2.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/GlyphView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/Highlighter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/AccessibleHTML.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/BlockView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/BRView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/CommentView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/CSS.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/CSSBorder.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/CSSParser.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/EditableView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/FormSubmitEvent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/FormView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/FrameSetView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/FrameView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/HiddenTagView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/HRuleView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/HTML.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/HTMLDocument.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/HTMLEditorKit.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/HTMLFrameHyperlinkEvent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/HTMLWriter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/ImageView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/InlineView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/IsindexView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/LineView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/ListView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/Map.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/MinimalHTMLWriter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/MuxingAttributeSet.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/NoFramesView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/ObjectView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/Option.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/OptionComboBoxModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/OptionListModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/ParagraphView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/parser/AttributeList.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/parser/ContentModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/parser/ContentModelState.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/parser/DocumentParser.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/parser/DTD.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/parser/DTDConstants.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/parser/Element.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/parser/Entity.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/parser/Parser.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/parser/ParserDelegator.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/parser/TagElement.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/parser/TagStack.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/StyleSheet.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/TableView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/TextAreaDocument.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/IconView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/InternationalFormatter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/JTextComponent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/Keymap.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/LabelView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/LayeredHighlighter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/LayoutQueue.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/MaskFormatter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/MutableAttributeSet.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/NavigationFilter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/NumberFormatter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/ParagraphView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/PasswordView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/PlainDocument.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/PlainView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/Position.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/rtf/AbstractFilter.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/rtf/Constants.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/rtf/MockAttributeSet.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/rtf/RTFAttribute.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/rtf/RTFAttributes.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/rtf/RTFEditorKit.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/rtf/RTFGenerator.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/rtf/RTFParser.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/rtf/RTFReader.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/Segment.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/SegmentCache.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/SimpleAttributeSet.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/StateInvariantError.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/StringContent.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/Style.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/StyleConstants.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/StyleContext.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/StyledDocument.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/StyledEditorKit.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/TabableView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/TabExpander.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/TableView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/TabSet.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/TabStop.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/TextAction.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/TextLayoutStrategy.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/Utilities.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/View.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/ViewFactory.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/WhitespaceBasedBreakIterator.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/WrappedPlainView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/text/ZoneView.java +@OPENJDK@/jdk/src/share/classes/javax/swing/Timer.java +@OPENJDK@/jdk/src/share/classes/javax/swing/TimerQueue.java +@OPENJDK@/jdk/src/share/classes/javax/swing/ToolTipManager.java +@OPENJDK@/jdk/src/share/classes/javax/swing/TransferHandler.java +@OPENJDK@/jdk/src/share/classes/javax/swing/tree/AbstractLayoutCache.java +@OPENJDK@/jdk/src/share/classes/javax/swing/tree/DefaultMutableTreeNode.java +@OPENJDK@/jdk/src/share/classes/javax/swing/tree/DefaultTreeCellEditor.java +@OPENJDK@/jdk/src/share/classes/javax/swing/tree/DefaultTreeCellRenderer.java +@OPENJDK@/jdk/src/share/classes/javax/swing/tree/DefaultTreeModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/tree/DefaultTreeSelectionModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/tree/ExpandVetoException.java +@OPENJDK@/jdk/src/share/classes/javax/swing/tree/FixedHeightLayoutCache.java +@OPENJDK@/jdk/src/share/classes/javax/swing/tree/MutableTreeNode.java +@OPENJDK@/jdk/src/share/classes/javax/swing/tree/RowMapper.java +@OPENJDK@/jdk/src/share/classes/javax/swing/tree/TreeCellEditor.java +@OPENJDK@/jdk/src/share/classes/javax/swing/tree/TreeCellRenderer.java +@OPENJDK@/jdk/src/share/classes/javax/swing/tree/TreeModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/tree/TreeNode.java +@OPENJDK@/jdk/src/share/classes/javax/swing/tree/TreePath.java +@OPENJDK@/jdk/src/share/classes/javax/swing/tree/TreeSelectionModel.java +@OPENJDK@/jdk/src/share/classes/javax/swing/tree/VariableHeightLayoutCache.java +@OPENJDK@/jdk/src/share/classes/javax/swing/UIDefaults.java +@OPENJDK@/jdk/src/share/classes/javax/swing/UIManager.java +@OPENJDK@/jdk/src/share/classes/javax/swing/undo/AbstractUndoableEdit.java +@OPENJDK@/jdk/src/share/classes/javax/swing/undo/CannotRedoException.java +@OPENJDK@/jdk/src/share/classes/javax/swing/undo/CannotUndoException.java +@OPENJDK@/jdk/src/share/classes/javax/swing/undo/CompoundEdit.java +@OPENJDK@/jdk/src/share/classes/javax/swing/undo/StateEdit.java +@OPENJDK@/jdk/src/share/classes/javax/swing/undo/StateEditable.java +@OPENJDK@/jdk/src/share/classes/javax/swing/undo/UndoableEdit.java +@OPENJDK@/jdk/src/share/classes/javax/swing/undo/UndoableEditSupport.java +@OPENJDK@/jdk/src/share/classes/javax/swing/undo/UndoManager.java +@OPENJDK@/jdk/src/share/classes/javax/swing/UnsupportedLookAndFeelException.java +@OPENJDK@/jdk/src/share/classes/javax/swing/ViewportLayout.java +@OPENJDK@/jdk/src/share/classes/javax/swing/WindowConstants.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/AlgorithmMethod.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/Data.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dom/DOMCryptoContext.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dom/DOMStructure.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dom/DOMURIReference.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/CanonicalizationMethod.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/DigestMethod.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/dom/DOMSignContext.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/dom/DOMValidateContext.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/keyinfo/KeyInfo.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/keyinfo/KeyInfoFactory.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/keyinfo/KeyName.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/keyinfo/KeyValue.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/keyinfo/PGPData.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/keyinfo/RetrievalMethod.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/keyinfo/X509Data.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/keyinfo/X509IssuerSerial.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/Manifest.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/Reference.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/SignatureMethod.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/SignatureProperties.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/SignatureProperty.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/SignedInfo.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/spec/C14NMethodParameterSpec.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/spec/DigestMethodParameterSpec.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/spec/ExcC14NParameterSpec.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/spec/HMACParameterSpec.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/spec/SignatureMethodParameterSpec.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/spec/TransformParameterSpec.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/spec/XPathFilter2ParameterSpec.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/spec/XPathFilterParameterSpec.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/spec/XPathType.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/spec/XSLTTransformParameterSpec.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/Transform.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/TransformException.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/TransformService.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/XMLObject.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/XMLSignature.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/XMLSignatureException.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/XMLSignatureFactory.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/XMLSignContext.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/XMLValidateContext.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/KeySelector.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/KeySelectorException.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/KeySelectorResult.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/MarshalException.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/NodeSetData.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/NoSuchMechanismException.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/OctetStreamData.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/URIDereferencer.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/URIReference.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/URIReferenceException.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/XMLCryptoContext.java +@OPENJDK@/jdk/src/share/classes/javax/xml/crypto/XMLStructure.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/AnnotationVisitor.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/AnnotationWriter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Attribute.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassVisitor.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/Method.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingAnnotationAdapter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingClassAdapter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingFieldAdapter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingSignatureAdapter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/SimpleRemapper.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/TableSwitchGenerator.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Context.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Edge.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/FieldVisitor.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/FieldWriter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Frame.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Handle.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Handler.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Item.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Label.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureReader.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureVisitor.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureWriter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/AbstractInsnNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Analyzer.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/AnalyzerException.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicInterpreter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicValue.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicVerifier.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Interpreter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SimpleVerifier.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SmallSet.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceInterpreter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceValue.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Subroutine.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Value.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/FieldInsnNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/FrameNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/IincInsnNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/InnerClassNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/InsnNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/IntInsnNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/InvokeDynamicInsnNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/JumpInsnNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/LabelNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/LdcInsnNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/LineNumberNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableAnnotationNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/LookupSwitchInsnNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodInsnNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/MultiANewArrayInsnNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/ParameterNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/TableSwitchInsnNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/TryCatchBlockNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/TypeAnnotationNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/TypeInsnNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/VarInsnNode.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Type.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/TypePath.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/TypeReference.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifiable.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckAnnotationAdapter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckSignatureAdapter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/Printer.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/Textifiable.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceAnnotationVisitor.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceFieldVisitor.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceMethodVisitor.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/TraceSignatureVisitor.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/xml/sax/Attributes.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/xml/sax/ContentHandler.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/xml/sax/DTDHandler.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/xml/sax/EntityResolver.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/xml/sax/ErrorHandler.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/xml/sax/helpers/DefaultHandler.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/xml/sax/InputSource.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/xml/sax/Locator.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/xml/sax/SAXException.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/xml/sax/SAXNotRecognizedException.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/xml/sax/SAXNotSupportedException.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/xml/sax/SAXParseException.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/org/xml/sax/XMLReader.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/BasicXmlPropertiesProvider.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/impl/Attrs.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/impl/Input.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/impl/Pair.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/impl/Parser.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/impl/ParserSAX.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/impl/ReaderUTF16.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/impl/ReaderUTF8.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/impl/SAXParserImpl.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/impl/XMLStreamWriterImpl.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/impl/XMLWriter.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/PropertiesDefaultHandler.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/SAXParser.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/XMLStreamException.java +@OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/XMLStreamWriter.java +@OPENJDK@/jdk/src/share/classes/jdk/net/ExtendedSocketOptions.java +@OPENJDK@/jdk/src/share/classes/jdk/net/NetworkPermission.java +@OPENJDK@/jdk/src/share/classes/jdk/net/package-info.java +@OPENJDK@/jdk/src/share/classes/jdk/net/SocketFlow.java +@OPENJDK@/jdk/src/share/classes/jdk/net/Sockets.java +@OPENJDK@/jdk/src/share/classes/org/ietf/jgss/ChannelBinding.java +@OPENJDK@/jdk/src/share/classes/org/ietf/jgss/GSSContext.java +@OPENJDK@/jdk/src/share/classes/org/ietf/jgss/GSSCredential.java +@OPENJDK@/jdk/src/share/classes/org/ietf/jgss/GSSException.java +@OPENJDK@/jdk/src/share/classes/org/ietf/jgss/GSSManager.java +@OPENJDK@/jdk/src/share/classes/org/ietf/jgss/GSSName.java +@OPENJDK@/jdk/src/share/classes/org/ietf/jgss/MessageProp.java +@OPENJDK@/jdk/src/share/classes/org/ietf/jgss/Oid.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/DigesterOutputStream.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/AbstractDOMSignatureMethod.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/ApacheCanonicalizer.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/ApacheData.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/ApacheNodeSetData.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/ApacheOctetStreamData.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMBase64Transform.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMCanonicalizationMethod.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMCanonicalXMLC14N11Method.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMCanonicalXMLC14NMethod.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMCryptoBinary.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMDigestMethod.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMEnvelopedTransform.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMExcC14NMethod.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMHMACSignatureMethod.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfo.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfoFactory.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyName.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyValue.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMPGPData.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureProperties.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureProperty.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMStructure.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSubTreeData.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMTransform.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMUtils.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMX509Data.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMX509IssuerSerial.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLObject.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignature.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMXPathFilter2Transform.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMXPathTransform.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMXSLTTransform.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/Utils.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/MacOutputStream.java +@OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/SignerOutputStream.java +@OPENJDK@/jdk/src/share/classes/sun/applet/AppletAudioClip.java +@OPENJDK@/jdk/src/share/classes/sun/awt/AppContext.java +@OPENJDK@/jdk/src/share/classes/sun/awt/AWTAccessor.java +@OPENJDK@/jdk/src/share/classes/sun/awt/AWTAutoShutdown.java +@OPENJDK@/jdk/src/share/classes/sun/awt/AWTCharset.java +@OPENJDK@/jdk/src/share/classes/sun/awt/AWTPermissionFactory.java +@OPENJDK@/jdk/src/share/classes/sun/awt/AWTSecurityManager.java +@OPENJDK@/jdk/src/share/classes/sun/awt/CausedFocusEvent.java +@OPENJDK@/jdk/src/share/classes/sun/awt/CharsetString.java +@OPENJDK@/jdk/src/share/classes/sun/awt/ComponentFactory.java +@OPENJDK@/jdk/src/share/classes/sun/awt/ConstrainableGraphics.java +@OPENJDK@/jdk/src/share/classes/sun/awt/CustomCursor.java +@OPENJDK@/jdk/src/share/classes/sun/awt/datatransfer/ClipboardTransferable.java +@OPENJDK@/jdk/src/share/classes/sun/awt/datatransfer/DataTransferer.java +@OPENJDK@/jdk/src/share/classes/sun/awt/datatransfer/SunClipboard.java +@OPENJDK@/jdk/src/share/classes/sun/awt/datatransfer/ToolkitThreadBlockedHandler.java +@OPENJDK@/jdk/src/share/classes/sun/awt/datatransfer/TransferableProxy.java +@OPENJDK@/jdk/src/share/classes/sun/awt/DefaultMouseInfoPeer.java +@OPENJDK@/jdk/src/share/classes/sun/awt/DesktopBrowse.java +@OPENJDK@/jdk/src/share/classes/sun/awt/DisplayChangedListener.java +@OPENJDK@/jdk/src/share/classes/sun/awt/dnd/SunDragSourceContextPeer.java +@OPENJDK@/jdk/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java +@OPENJDK@/jdk/src/share/classes/sun/awt/dnd/SunDropTargetEvent.java +@OPENJDK@/jdk/src/share/classes/sun/awt/event/IgnorePaintEvent.java +@OPENJDK@/jdk/src/share/classes/sun/awt/EventListenerAggregate.java +@OPENJDK@/jdk/src/share/classes/sun/awt/EventQueueDelegate.java +@OPENJDK@/jdk/src/share/classes/sun/awt/EventQueueItem.java +@OPENJDK@/jdk/src/share/classes/sun/awt/ExtendedKeyCodes.java +@OPENJDK@/jdk/src/share/classes/sun/awt/FontConfiguration.java +@OPENJDK@/jdk/src/share/classes/sun/awt/FontDescriptor.java +@OPENJDK@/jdk/src/share/classes/sun/awt/FwDispatcher.java +@OPENJDK@/jdk/src/share/classes/sun/awt/geom/AreaOp.java +@OPENJDK@/jdk/src/share/classes/sun/awt/geom/ChainEnd.java +@OPENJDK@/jdk/src/share/classes/sun/awt/geom/Crossings.java +@OPENJDK@/jdk/src/share/classes/sun/awt/geom/Curve.java +@OPENJDK@/jdk/src/share/classes/sun/awt/geom/CurveLink.java +@OPENJDK@/jdk/src/share/classes/sun/awt/geom/Edge.java +@OPENJDK@/jdk/src/share/classes/sun/awt/geom/Order0.java +@OPENJDK@/jdk/src/share/classes/sun/awt/geom/Order1.java +@OPENJDK@/jdk/src/share/classes/sun/awt/geom/Order2.java +@OPENJDK@/jdk/src/share/classes/sun/awt/geom/Order3.java +@OPENJDK@/jdk/src/share/classes/sun/awt/geom/PathConsumer2D.java +@OPENJDK@/jdk/src/share/classes/sun/awt/GlobalCursorManager.java +@OPENJDK@/jdk/src/share/classes/sun/awt/Graphics2Delegate.java +@OPENJDK@/jdk/src/share/classes/sun/awt/HeadlessToolkit.java +@OPENJDK@/jdk/src/share/classes/sun/awt/HKSCS.java +@OPENJDK@/jdk/src/share/classes/sun/awt/IconInfo.java +@OPENJDK@/jdk/src/share/classes/sun/awt/im/CompositionArea.java +@OPENJDK@/jdk/src/share/classes/sun/awt/im/CompositionAreaHandler.java +@OPENJDK@/jdk/src/share/classes/sun/awt/im/ExecutableInputMethodManager.java +@OPENJDK@/jdk/src/share/classes/sun/awt/im/InputContext.java +@OPENJDK@/jdk/src/share/classes/sun/awt/im/InputMethodAdapter.java +@OPENJDK@/jdk/src/share/classes/sun/awt/im/InputMethodContext.java +@OPENJDK@/jdk/src/share/classes/sun/awt/im/InputMethodJFrame.java +@OPENJDK@/jdk/src/share/classes/sun/awt/im/InputMethodLocator.java +@OPENJDK@/jdk/src/share/classes/sun/awt/im/InputMethodManager.java +@OPENJDK@/jdk/src/share/classes/sun/awt/im/InputMethodPopupMenu.java +@OPENJDK@/jdk/src/share/classes/sun/awt/im/InputMethodWindow.java +@OPENJDK@/jdk/src/share/classes/sun/awt/im/SimpleInputMethodWindow.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/AbstractMultiResolutionImage.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/BufferedImageDevice.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/BufferedImageGraphicsConfig.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/ByteArrayImageSource.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/ByteBandedRaster.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/BytePackedRaster.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/FileImageSource.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/ImageCache.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/ImageConsumerQueue.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/ImageDecoder.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/ImageFetchable.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/ImageFetcher.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/ImageFormatException.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/ImageWatched.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/InputStreamImageSource.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/IntegerComponentRaster.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/MultiResolutionCachedImage.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/MultiResolutionImage.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/MultiResolutionToolkitImage.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/NativeLibLoader.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/OffScreenImageSource.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/PixelConverter.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/PNGImageDecoder.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/ShortBandedRaster.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/ShortComponentRaster.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/ShortInterleavedRaster.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/URLImageSource.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/VSyncedBSManager.java +@OPENJDK@/jdk/src/share/classes/sun/awt/image/XbmImageDecoder.java +@OPENJDK@/jdk/src/share/classes/sun/awt/InputMethodSupport.java +@OPENJDK@/jdk/src/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java +@OPENJDK@/jdk/src/share/classes/sun/awt/KeyboardFocusManagerPeerProvider.java +@OPENJDK@/jdk/src/share/classes/sun/awt/LightweightFrame.java +@OPENJDK@/jdk/src/share/classes/sun/awt/ModalExclude.java +@OPENJDK@/jdk/src/share/classes/sun/awt/ModalityEvent.java +@OPENJDK@/jdk/src/share/classes/sun/awt/ModalityListener.java +@OPENJDK@/jdk/src/share/classes/sun/awt/Mutex.java +@OPENJDK@/jdk/src/share/classes/sun/awt/NativeLibLoader.java +@OPENJDK@/jdk/src/share/classes/sun/awt/NullComponentPeer.java +@OPENJDK@/jdk/src/share/classes/sun/awt/OSInfo.java +@OPENJDK@/jdk/src/share/classes/sun/awt/PaintEventDispatcher.java +@OPENJDK@/jdk/src/share/classes/sun/awt/PeerEvent.java +@OPENJDK@/jdk/src/share/classes/sun/awt/RepaintArea.java +@OPENJDK@/jdk/src/share/classes/sun/awt/RequestFocusController.java +@OPENJDK@/jdk/src/share/classes/sun/awt/ScrollPaneWheelScroller.java +@OPENJDK@/jdk/src/share/classes/sun/awt/shell/DefaultShellFolder.java +@OPENJDK@/jdk/src/share/classes/sun/awt/shell/ShellFolder.java +@OPENJDK@/jdk/src/share/classes/sun/awt/shell/ShellFolderColumnInfo.java +@OPENJDK@/jdk/src/share/classes/sun/awt/shell/ShellFolderManager.java +@OPENJDK@/jdk/src/share/classes/sun/awt/SubRegionShowable.java +@OPENJDK@/jdk/src/share/classes/sun/awt/SunDisplayChanger.java +@OPENJDK@/jdk/src/share/classes/sun/awt/SunGraphicsCallback.java +@OPENJDK@/jdk/src/share/classes/sun/awt/SunHints.java +@OPENJDK@/jdk/src/share/classes/sun/awt/SunToolkit.java +@OPENJDK@/jdk/src/share/classes/sun/awt/Symbol.java +@OPENJDK@/jdk/src/share/classes/sun/awt/TimedWindowEvent.java +@OPENJDK@/jdk/src/share/classes/sun/awt/TracedEventQueue.java +@OPENJDK@/jdk/src/share/classes/sun/awt/UngrabEvent.java +@OPENJDK@/jdk/src/share/classes/sun/awt/util/IdentityArrayList.java +@OPENJDK@/jdk/src/share/classes/sun/awt/util/IdentityLinkedList.java +@OPENJDK@/jdk/src/share/classes/sun/awt/WindowClosingListener.java +@OPENJDK@/jdk/src/share/classes/sun/awt/WindowClosingSupport.java +@OPENJDK@/jdk/src/share/classes/sun/awt/WindowIDProvider.java +@OPENJDK@/jdk/src/share/classes/sun/font/AttributeMap.java +@OPENJDK@/jdk/src/share/classes/sun/font/AttributeValues.java +@OPENJDK@/jdk/src/share/classes/sun/font/BidiUtils.java +@OPENJDK@/jdk/src/share/classes/sun/font/CharToGlyphMapper.java +@OPENJDK@/jdk/src/share/classes/sun/font/CompositeFontDescriptor.java +@OPENJDK@/jdk/src/share/classes/sun/font/CoreMetrics.java +@OPENJDK@/jdk/src/share/classes/sun/font/CreatedFontTracker.java +@OPENJDK@/jdk/src/share/classes/sun/font/Decoration.java +@OPENJDK@/jdk/src/share/classes/sun/font/EAttribute.java +@OPENJDK@/jdk/src/share/classes/sun/font/ExtendedTextLabel.java +@OPENJDK@/jdk/src/share/classes/sun/font/ExtendedTextSourceLabel.java +@OPENJDK@/jdk/src/share/classes/sun/font/Font2DHandle.java +@OPENJDK@/jdk/src/share/classes/sun/font/FontAccess.java +@OPENJDK@/jdk/src/share/classes/sun/font/FontDesignMetrics.java +@OPENJDK@/jdk/src/share/classes/sun/font/FontLineMetrics.java +@OPENJDK@/jdk/src/share/classes/sun/font/FontManager.java +@OPENJDK@/jdk/src/share/classes/sun/font/FontManagerFactory.java +@OPENJDK@/jdk/src/share/classes/sun/font/FontManagerForSGE.java +@OPENJDK@/jdk/src/share/classes/sun/font/FontResolver.java +@OPENJDK@/jdk/src/share/classes/sun/font/FontStrike.java +@OPENJDK@/jdk/src/share/classes/sun/font/FontStrikeDesc.java +@OPENJDK@/jdk/src/share/classes/sun/font/FontStrikeDisposer.java +@OPENJDK@/jdk/src/share/classes/sun/font/FontUtilities.java +@OPENJDK@/jdk/src/share/classes/sun/font/GraphicComponent.java +@OPENJDK@/jdk/src/share/classes/sun/font/LayoutPathImpl.java +@OPENJDK@/jdk/src/share/classes/sun/font/StandardTextSource.java +@OPENJDK@/jdk/src/share/classes/sun/font/StrikeMetrics.java +@OPENJDK@/jdk/src/share/classes/sun/font/TextLabel.java +@OPENJDK@/jdk/src/share/classes/sun/font/TextLabelFactory.java +@OPENJDK@/jdk/src/share/classes/sun/font/TextLineComponent.java +@OPENJDK@/jdk/src/share/classes/sun/font/TextSource.java +@OPENJDK@/jdk/src/share/classes/sun/font/TextSourceLabel.java +@OPENJDK@/jdk/src/share/classes/sun/font/Underline.java +@OPENJDK@/jdk/src/share/classes/sun/invoke/anon/AnonymousClassLoader.java +@OPENJDK@/jdk/src/share/classes/sun/invoke/anon/ConstantPoolParser.java +@OPENJDK@/jdk/src/share/classes/sun/invoke/anon/ConstantPoolPatch.java +@OPENJDK@/jdk/src/share/classes/sun/invoke/anon/ConstantPoolVisitor.java +@OPENJDK@/jdk/src/share/classes/sun/invoke/anon/InvalidConstantPoolFormatException.java +@OPENJDK@/jdk/src/share/classes/sun/invoke/empty/Empty.java +@OPENJDK@/jdk/src/share/classes/sun/invoke/package-info.java +@OPENJDK@/jdk/src/share/classes/sun/invoke/util/BytecodeDescriptor.java +@OPENJDK@/jdk/src/share/classes/sun/invoke/util/BytecodeName.java +@OPENJDK@/jdk/src/share/classes/sun/invoke/util/package-info.java +@OPENJDK@/jdk/src/share/classes/sun/invoke/util/ValueConversions.java +@OPENJDK@/jdk/src/share/classes/sun/invoke/util/VerifyAccess.java +@OPENJDK@/jdk/src/share/classes/sun/invoke/util/VerifyType.java +@OPENJDK@/jdk/src/share/classes/sun/invoke/util/Wrapper.java +@OPENJDK@/jdk/src/share/classes/sun/invoke/WrapperInstance.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/cmm/CMMServiceProvider.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/cmm/CMSManager.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/cmm/ColorTransform.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/cmm/lcms/LcmsServiceProvider.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/cmm/PCMM.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/cmm/Profile.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/cmm/ProfileActivator.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/cmm/ProfileDataVerifier.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/cmm/ProfileDeferralInfo.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/cmm/ProfileDeferralMgr.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/DefaultDisposerRecord.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/Disposer.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/DisposerRecord.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/DisposerTarget.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/FontSupport.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/InvalidPipeException.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pipe/AATileGenerator.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pipe/BufferedOpCodes.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pipe/CompositePipe.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pipe/DrawImagePipe.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pipe/hw/ExtendedBufferCapabilities.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pipe/NullPipe.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pipe/PixelDrawPipe.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pipe/PixelFillPipe.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pipe/PixelToShapeConverter.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pipe/Region.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pipe/RegionClipSpanIterator.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pipe/RegionIterator.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pipe/RegionSpanIterator.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pipe/RenderingEngine.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pipe/ShapeDrawPipe.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pipe/SpanIterator.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pipe/TextPipe.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pisces/Curve.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pisces/Dasher.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pisces/Helpers.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pisces/PiscesCache.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pisces/PiscesTileGenerator.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pisces/Renderer.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pisces/Stroker.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/pisces/TransformingPathConsumer2D.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/Spans.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/StateTrackable.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/StateTrackableDelegate.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/StateTracker.java +@OPENJDK@/jdk/src/share/classes/sun/java2d/Surface.java +@OPENJDK@/jdk/src/share/classes/sun/launcher/LauncherHelper.java +@OPENJDK@/jdk/src/share/classes/sun/management/Agent.java +@OPENJDK@/jdk/src/share/classes/sun/management/AgentConfigurationError.java +@OPENJDK@/jdk/src/share/classes/sun/management/BaseOperatingSystemImpl.java +@OPENJDK@/jdk/src/share/classes/sun/management/ClassLoadingImpl.java +@OPENJDK@/jdk/src/share/classes/sun/management/CompilationImpl.java +@OPENJDK@/jdk/src/share/classes/sun/management/CompilerThreadStat.java +@OPENJDK@/jdk/src/share/classes/sun/management/ConnectorAddressLink.java +@OPENJDK@/jdk/src/share/classes/sun/management/counter/AbstractCounter.java +@OPENJDK@/jdk/src/share/classes/sun/management/counter/ByteArrayCounter.java +@OPENJDK@/jdk/src/share/classes/sun/management/counter/Counter.java +@OPENJDK@/jdk/src/share/classes/sun/management/counter/LongArrayCounter.java +@OPENJDK@/jdk/src/share/classes/sun/management/counter/LongCounter.java +@OPENJDK@/jdk/src/share/classes/sun/management/counter/perf/ByteArrayCounterSnapshot.java +@OPENJDK@/jdk/src/share/classes/sun/management/counter/perf/InstrumentationException.java +@OPENJDK@/jdk/src/share/classes/sun/management/counter/perf/LongArrayCounterSnapshot.java +@OPENJDK@/jdk/src/share/classes/sun/management/counter/perf/LongCounterSnapshot.java +@OPENJDK@/jdk/src/share/classes/sun/management/counter/perf/PerfByteArrayCounter.java +@OPENJDK@/jdk/src/share/classes/sun/management/counter/perf/PerfDataEntry.java +@OPENJDK@/jdk/src/share/classes/sun/management/counter/perf/PerfDataType.java +@OPENJDK@/jdk/src/share/classes/sun/management/counter/perf/PerfInstrumentation.java +@OPENJDK@/jdk/src/share/classes/sun/management/counter/perf/PerfLongArrayCounter.java +@OPENJDK@/jdk/src/share/classes/sun/management/counter/perf/PerfLongCounter.java +@OPENJDK@/jdk/src/share/classes/sun/management/counter/perf/PerfStringCounter.java +@OPENJDK@/jdk/src/share/classes/sun/management/counter/perf/Prologue.java +@OPENJDK@/jdk/src/share/classes/sun/management/counter/perf/StringCounterSnapshot.java +@OPENJDK@/jdk/src/share/classes/sun/management/counter/StringCounter.java +@OPENJDK@/jdk/src/share/classes/sun/management/counter/Units.java +@OPENJDK@/jdk/src/share/classes/sun/management/counter/Variability.java +@OPENJDK@/jdk/src/share/classes/sun/management/ExtendedPlatformComponent.java +@OPENJDK@/jdk/src/share/classes/sun/management/FileSystem.java +@OPENJDK@/jdk/src/share/classes/sun/management/GarbageCollectionNotifInfoCompositeData.java +@OPENJDK@/jdk/src/share/classes/sun/management/GcInfoBuilder.java +@OPENJDK@/jdk/src/share/classes/sun/management/GcInfoCompositeData.java +@OPENJDK@/jdk/src/share/classes/sun/management/HotspotClassLoading.java +@OPENJDK@/jdk/src/share/classes/sun/management/HotspotClassLoadingMBean.java +@OPENJDK@/jdk/src/share/classes/sun/management/HotspotCompilation.java +@OPENJDK@/jdk/src/share/classes/sun/management/HotspotCompilationMBean.java +@OPENJDK@/jdk/src/share/classes/sun/management/HotspotInternal.java +@OPENJDK@/jdk/src/share/classes/sun/management/HotspotInternalMBean.java +@OPENJDK@/jdk/src/share/classes/sun/management/HotspotMemory.java +@OPENJDK@/jdk/src/share/classes/sun/management/HotspotMemoryMBean.java +@OPENJDK@/jdk/src/share/classes/sun/management/HotspotRuntime.java +@OPENJDK@/jdk/src/share/classes/sun/management/HotspotRuntimeMBean.java +@OPENJDK@/jdk/src/share/classes/sun/management/HotspotThreadMBean.java +@OPENJDK@/jdk/src/share/classes/sun/management/jdp/JdpBroadcaster.java +@OPENJDK@/jdk/src/share/classes/sun/management/jdp/JdpController.java +@OPENJDK@/jdk/src/share/classes/sun/management/jdp/JdpException.java +@OPENJDK@/jdk/src/share/classes/sun/management/jdp/JdpGenericPacket.java +@OPENJDK@/jdk/src/share/classes/sun/management/jdp/JdpJmxPacket.java +@OPENJDK@/jdk/src/share/classes/sun/management/jdp/JdpPacket.java +@OPENJDK@/jdk/src/share/classes/sun/management/jdp/JdpPacketReader.java +@OPENJDK@/jdk/src/share/classes/sun/management/jdp/JdpPacketWriter.java +@OPENJDK@/jdk/src/share/classes/sun/management/jdp/package-info.java +@OPENJDK@/jdk/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java +@OPENJDK@/jdk/src/share/classes/sun/management/jmxremote/LocalRMIServerSocketFactory.java +@OPENJDK@/jdk/src/share/classes/sun/management/jmxremote/SingleEntryRegistry.java +@OPENJDK@/jdk/src/share/classes/sun/management/LazyCompositeData.java +@OPENJDK@/jdk/src/share/classes/sun/management/LockInfoCompositeData.java +@OPENJDK@/jdk/src/share/classes/sun/management/MappedMXBeanType.java +@OPENJDK@/jdk/src/share/classes/sun/management/MemoryImpl.java +@OPENJDK@/jdk/src/share/classes/sun/management/MemoryNotifInfoCompositeData.java +@OPENJDK@/jdk/src/share/classes/sun/management/MemoryUsageCompositeData.java +@OPENJDK@/jdk/src/share/classes/sun/management/MethodInfo.java +@OPENJDK@/jdk/src/share/classes/sun/management/MonitorInfoCompositeData.java +@OPENJDK@/jdk/src/share/classes/sun/management/NotificationEmitterSupport.java +@OPENJDK@/jdk/src/share/classes/sun/management/RuntimeImpl.java +@OPENJDK@/jdk/src/share/classes/sun/management/Sensor.java +@OPENJDK@/jdk/src/share/classes/sun/management/StackTraceElementCompositeData.java +@OPENJDK@/jdk/src/share/classes/sun/management/ThreadImpl.java +@OPENJDK@/jdk/src/share/classes/sun/management/ThreadInfoCompositeData.java +@OPENJDK@/jdk/src/share/classes/sun/management/Util.java +@OPENJDK@/jdk/src/share/classes/sun/management/VMManagement.java +@OPENJDK@/jdk/src/share/classes/sun/management/VMOptionCompositeData.java +@OPENJDK@/jdk/src/share/classes/sun/misc/ASCIICaseInsensitiveComparator.java +@OPENJDK@/jdk/src/share/classes/sun/misc/BASE64Decoder.java +@OPENJDK@/jdk/src/share/classes/sun/misc/BASE64Encoder.java +@OPENJDK@/jdk/src/share/classes/sun/misc/Cache.java +@OPENJDK@/jdk/src/share/classes/sun/misc/CEFormatException.java +@OPENJDK@/jdk/src/share/classes/sun/misc/CEStreamExhausted.java +@OPENJDK@/jdk/src/share/classes/sun/misc/CharacterDecoder.java +@OPENJDK@/jdk/src/share/classes/sun/misc/CharacterEncoder.java +@OPENJDK@/jdk/src/share/classes/sun/misc/ClassFileTransformer.java +@OPENJDK@/jdk/src/share/classes/sun/misc/ClassLoaderUtil.java +@OPENJDK@/jdk/src/share/classes/sun/misc/Cleaner.java +@OPENJDK@/jdk/src/share/classes/sun/misc/CompoundEnumeration.java +@OPENJDK@/jdk/src/share/classes/sun/misc/ConditionLock.java +@OPENJDK@/jdk/src/share/classes/sun/misc/Contended.java +@OPENJDK@/jdk/src/share/classes/sun/misc/CRC16.java +@OPENJDK@/jdk/src/share/classes/sun/misc/DoubleConsts.java +@OPENJDK@/jdk/src/share/classes/sun/misc/ExtensionDependency.java +@OPENJDK@/jdk/src/share/classes/sun/misc/ExtensionInfo.java +@OPENJDK@/jdk/src/share/classes/sun/misc/ExtensionInstallationException.java +@OPENJDK@/jdk/src/share/classes/sun/misc/ExtensionInstallationProvider.java +@OPENJDK@/jdk/src/share/classes/sun/misc/FDBigInteger.java +@OPENJDK@/jdk/src/share/classes/sun/misc/FloatConsts.java +@OPENJDK@/jdk/src/share/classes/sun/misc/FloatingDecimal.java +@OPENJDK@/jdk/src/share/classes/sun/misc/FormattedFloatingDecimal.java +@OPENJDK@/jdk/src/share/classes/sun/misc/FpUtils.java +@OPENJDK@/jdk/src/share/classes/sun/misc/GC.java +@OPENJDK@/jdk/src/share/classes/sun/misc/HexDumpEncoder.java +@OPENJDK@/jdk/src/share/classes/sun/misc/InnocuousThread.java +@OPENJDK@/jdk/src/share/classes/sun/misc/InvalidJarIndexException.java +@OPENJDK@/jdk/src/share/classes/sun/misc/IOUtils.java +@OPENJDK@/jdk/src/share/classes/sun/misc/JarFilter.java +@OPENJDK@/jdk/src/share/classes/sun/misc/JarIndex.java +@OPENJDK@/jdk/src/share/classes/sun/misc/JavaAWTAccess.java +@OPENJDK@/jdk/src/share/classes/sun/misc/JavaIOAccess.java +@OPENJDK@/jdk/src/share/classes/sun/misc/JavaIOFileDescriptorAccess.java +@OPENJDK@/jdk/src/share/classes/sun/misc/JavaLangAccess.java +@OPENJDK@/jdk/src/share/classes/sun/misc/JavaNetAccess.java +@OPENJDK@/jdk/src/share/classes/sun/misc/JavaNetHttpCookieAccess.java +@OPENJDK@/jdk/src/share/classes/sun/misc/JavaNioAccess.java +@OPENJDK@/jdk/src/share/classes/sun/misc/JavaSecurityAccess.java +@OPENJDK@/jdk/src/share/classes/sun/misc/JavaSecurityProtectionDomainAccess.java +@OPENJDK@/jdk/src/share/classes/sun/misc/JavaUtilJarAccess.java +@OPENJDK@/jdk/src/share/classes/sun/misc/JavaUtilZipFileAccess.java +@OPENJDK@/jdk/src/share/classes/sun/misc/Launcher.java +@OPENJDK@/jdk/src/share/classes/sun/misc/Lock.java +@OPENJDK@/jdk/src/share/classes/sun/misc/LRUCache.java +@OPENJDK@/jdk/src/share/classes/sun/misc/MessageUtils.java +@OPENJDK@/jdk/src/share/classes/sun/misc/MetaIndex.java +@OPENJDK@/jdk/src/share/classes/sun/misc/NativeSignalHandler.java +@OPENJDK@/jdk/src/share/classes/sun/misc/Perf.java +@OPENJDK@/jdk/src/share/classes/sun/misc/PerfCounter.java +@OPENJDK@/jdk/src/share/classes/sun/misc/PerformanceLogger.java +@OPENJDK@/jdk/src/share/classes/sun/misc/ProxyGenerator.java +@OPENJDK@/jdk/src/share/classes/sun/misc/Queue.java +@OPENJDK@/jdk/src/share/classes/sun/misc/REException.java +@OPENJDK@/jdk/src/share/classes/sun/misc/Regexp.java +@OPENJDK@/jdk/src/share/classes/sun/misc/RegexpPool.java +@OPENJDK@/jdk/src/share/classes/sun/misc/RegexpTarget.java +@OPENJDK@/jdk/src/share/classes/sun/misc/Request.java +@OPENJDK@/jdk/src/share/classes/sun/misc/RequestProcessor.java +@OPENJDK@/jdk/src/share/classes/sun/misc/Resource.java +@OPENJDK@/jdk/src/share/classes/sun/misc/resources/Messages.java +@OPENJDK@/jdk/src/share/classes/sun/misc/resources/Messages_de.java +@OPENJDK@/jdk/src/share/classes/sun/misc/resources/Messages_es.java +@OPENJDK@/jdk/src/share/classes/sun/misc/resources/Messages_fr.java +@OPENJDK@/jdk/src/share/classes/sun/misc/resources/Messages_it.java +@OPENJDK@/jdk/src/share/classes/sun/misc/resources/Messages_ja.java +@OPENJDK@/jdk/src/share/classes/sun/misc/resources/Messages_ko.java +@OPENJDK@/jdk/src/share/classes/sun/misc/resources/Messages_pt_BR.java +@OPENJDK@/jdk/src/share/classes/sun/misc/resources/Messages_sv.java +@OPENJDK@/jdk/src/share/classes/sun/misc/resources/Messages_zh_CN.java +@OPENJDK@/jdk/src/share/classes/sun/misc/resources/Messages_zh_TW.java +@OPENJDK@/jdk/src/share/classes/sun/misc/Service.java +@OPENJDK@/jdk/src/share/classes/sun/misc/ServiceConfigurationError.java +@OPENJDK@/jdk/src/share/classes/sun/misc/Signal.java +@OPENJDK@/jdk/src/share/classes/sun/misc/SignalHandler.java +@OPENJDK@/jdk/src/share/classes/sun/misc/SoftCache.java +@OPENJDK@/jdk/src/share/classes/sun/misc/ThreadGroupUtils.java +@OPENJDK@/jdk/src/share/classes/sun/misc/Timeable.java +@OPENJDK@/jdk/src/share/classes/sun/misc/Timer.java +@OPENJDK@/jdk/src/share/classes/sun/misc/UCDecoder.java +@OPENJDK@/jdk/src/share/classes/sun/misc/UCEncoder.java +@OPENJDK@/jdk/src/share/classes/sun/misc/URLClassPath.java +@OPENJDK@/jdk/src/share/classes/sun/misc/UUDecoder.java +@OPENJDK@/jdk/src/share/classes/sun/misc/UUEncoder.java +@OPENJDK@/jdk/src/share/classes/sun/misc/VMNotification.java +@OPENJDK@/jdk/src/share/classes/sun/misc/VMSupport.java +@OPENJDK@/jdk/src/share/classes/sun/net/ApplicationProxy.java +@OPENJDK@/jdk/src/share/classes/sun/net/ConnectionResetException.java +@OPENJDK@/jdk/src/share/classes/sun/net/dns/ResolverConfiguration.java +@OPENJDK@/jdk/src/share/classes/sun/net/ExtendedOptionsImpl.java +@OPENJDK@/jdk/src/share/classes/sun/net/ftp/FtpClient.java +@OPENJDK@/jdk/src/share/classes/sun/net/ftp/FtpClientProvider.java +@OPENJDK@/jdk/src/share/classes/sun/net/ftp/FtpDirEntry.java +@OPENJDK@/jdk/src/share/classes/sun/net/ftp/FtpDirParser.java +@OPENJDK@/jdk/src/share/classes/sun/net/ftp/FtpLoginException.java +@OPENJDK@/jdk/src/share/classes/sun/net/ftp/FtpProtocolException.java +@OPENJDK@/jdk/src/share/classes/sun/net/ftp/FtpReplyCode.java +@OPENJDK@/jdk/src/share/classes/sun/net/ftp/impl/DefaultFtpClientProvider.java +@OPENJDK@/jdk/src/share/classes/sun/net/ftp/impl/FtpClient.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/AuthFilter.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/ChunkedInputStream.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/ChunkedOutputStream.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/Code.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/ContextList.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/DefaultHttpServerProvider.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/Event.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/FixedLengthInputStream.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/FixedLengthOutputStream.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/HttpConnection.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/HttpContextImpl.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/HttpError.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/HttpExchangeImpl.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/HttpServerImpl.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/HttpsExchangeImpl.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/HttpsServerImpl.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/LeftOverInputStream.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/Request.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/ServerConfig.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/SSLStreams.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/StreamClosedException.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/TimeSource.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/UndefLengthOutputStream.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/UnmodifiableHeaders.java +@OPENJDK@/jdk/src/share/classes/sun/net/httpserver/WriteFinishedEvent.java +@OPENJDK@/jdk/src/share/classes/sun/net/idn/Punycode.java +@OPENJDK@/jdk/src/share/classes/sun/net/idn/StringPrep.java +@OPENJDK@/jdk/src/share/classes/sun/net/idn/StringPrepDataReader.java +@OPENJDK@/jdk/src/share/classes/sun/net/idn/UCharacterDirection.java +@OPENJDK@/jdk/src/share/classes/sun/net/idn/UCharacterEnums.java +@OPENJDK@/jdk/src/share/classes/sun/net/InetAddressCachePolicy.java +@OPENJDK@/jdk/src/share/classes/sun/net/NetProperties.java +@OPENJDK@/jdk/src/share/classes/sun/net/NetworkClient.java +@OPENJDK@/jdk/src/share/classes/sun/net/NetworkServer.java +@OPENJDK@/jdk/src/share/classes/sun/net/ProgressEvent.java +@OPENJDK@/jdk/src/share/classes/sun/net/ProgressListener.java +@OPENJDK@/jdk/src/share/classes/sun/net/ProgressMeteringPolicy.java +@OPENJDK@/jdk/src/share/classes/sun/net/ProgressMonitor.java +@OPENJDK@/jdk/src/share/classes/sun/net/ProgressSource.java +@OPENJDK@/jdk/src/share/classes/sun/net/RegisteredDomain.java +@OPENJDK@/jdk/src/share/classes/sun/net/ResourceManager.java +@OPENJDK@/jdk/src/share/classes/sun/net/smtp/SmtpClient.java +@OPENJDK@/jdk/src/share/classes/sun/net/smtp/SmtpProtocolException.java +@OPENJDK@/jdk/src/share/classes/sun/net/SocksProxy.java +@OPENJDK@/jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java +@OPENJDK@/jdk/src/share/classes/sun/net/spi/nameservice/dns/DNSNameService.java +@OPENJDK@/jdk/src/share/classes/sun/net/spi/nameservice/dns/DNSNameServiceDescriptor.java +@OPENJDK@/jdk/src/share/classes/sun/net/spi/nameservice/NameService.java +@OPENJDK@/jdk/src/share/classes/sun/net/spi/nameservice/NameServiceDescriptor.java +@OPENJDK@/jdk/src/share/classes/sun/net/TelnetInputStream.java +@OPENJDK@/jdk/src/share/classes/sun/net/TelnetOutputStream.java +@OPENJDK@/jdk/src/share/classes/sun/net/TelnetProtocolException.java +@OPENJDK@/jdk/src/share/classes/sun/net/TransferProtocolClient.java +@OPENJDK@/jdk/src/share/classes/sun/net/URLCanonicalizer.java +@OPENJDK@/jdk/src/share/classes/sun/net/util/IPAddressUtil.java +@OPENJDK@/jdk/src/share/classes/sun/net/util/URLUtil.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/ApplicationLaunchException.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/content/image/gif.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/content/image/jpeg.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/content/image/png.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/content/image/x_xbitmap.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/content/image/x_xpixmap.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/content/text/Generic.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/content/text/plain.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/content/text/PlainTextInputStream.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/HeaderParser.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/http/ChunkedInputStream.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/http/ChunkedOutputStream.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/http/HttpCapture.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/http/HttpCaptureInputStream.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/http/HttpCaptureOutputStream.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/http/HttpClient.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/http/Hurryable.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/http/KeepAliveCleanerEntry.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/http/KeepAliveStream.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/http/KeepAliveStreamCleaner.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/http/PosterOutputStream.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/MessageHeader.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/MeteredStream.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/MimeEntry.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/MimeLauncher.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/MimeTable.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/ParseUtil.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/ftp/Handler.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/AuthCache.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/AuthCacheImpl.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/AuthCacheValue.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/AuthScheme.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/BasicAuthentication.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/DigestAuthentication.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/Handler.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/HttpAuthenticator.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/HttpCallerInfo.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/logging/HttpLogFormatter.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/Negotiator.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/ntlm/NTLMAuthenticationCallback.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/NTLMAuthenticationProxy.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/spnego/NegotiateCallbackHandler.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/spnego/NegotiatorImpl.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/https/DefaultHostnameVerifier.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/https/DelegateHttpsURLConnection.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/https/Handler.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/jar/Handler.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/jar/JarURLConnection.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/jar/URLJarFile.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/jar/URLJarFileCallBack.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/mailto/Handler.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/mailto/MailToURLConnection.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/netdoc/Handler.java +@OPENJDK@/jdk/src/share/classes/sun/net/www/URLConnection.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ByteBuffered.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/AsynchronousFileChannelImpl.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/Cancellable.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/ChannelInputStream.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/CompletedFuture.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/DatagramSocketAdaptor.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/DirectBuffer.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/ExtendedSocketOption.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/FileDispatcher.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/FileLockImpl.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/FileLockTable.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/Groupable.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/Interruptible.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/Invoker.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/IOStatus.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/MembershipKeyImpl.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/MembershipRegistry.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/NativeThreadSet.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/OptionKey.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/PendingFuture.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/Reflect.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/sctp/MessageInfoImpl.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/sctp/SctpStdSocketOption.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/SelChImpl.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/SelectorImpl.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/SelectorProviderImpl.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/ServerSocketAdaptor.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/SocketAdaptor.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java +@OPENJDK@/jdk/src/share/classes/sun/nio/ch/ThreadPool.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/AbstractCharsetProvider.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ArrayDecoder.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ArrayEncoder.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/CESU_8.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/CharsetMapping.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/Big5_HKSCS.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/Big5_HKSCS_2001.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/Big5_Solaris.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/DelegatableDecoder.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/DoubleByte.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/DoubleByteEncoder.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/EUC_JP.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/EUC_JP_LINUX.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/EUC_JP_Open.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/EUC_TW.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/ExtendedCharsets.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/GB18030.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/HKSCS.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/IBM33722.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/IBM834.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/IBM942C.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/IBM943C.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/IBM949C.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/IBM964.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/ISCII91.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/ISO2022.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/ISO2022_CN.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/ISO2022_CN_CNS.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/ISO2022_CN_GB.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/ISO2022_JP.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/ISO2022_JP_2.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/ISO2022_KR.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/JISAutoDetect.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/MS50220.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/MS50221.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/MS932_0213.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/MS950_HKSCS.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/MS950_HKSCS_XP.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/MSISO2022JP.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/SimpleEUCEncoder.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/SJIS_0213.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/FastCharsetProvider.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/HistoricallyNamedCharset.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ISO_8859_1.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/SingleByte.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/StreamDecoder.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/StreamEncoder.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/Surrogate.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ThreadLocalCoders.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/Unicode.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/UnicodeDecoder.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/UnicodeEncoder.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/US_ASCII.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/UTF_16.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/UTF_16BE.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/UTF_16LE.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/UTF_16LE_BOM.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/UTF_32.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/UTF_32BE.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/UTF_32BE_BOM.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/UTF_32Coder.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/UTF_32LE.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/UTF_32LE_BOM.java +@OPENJDK@/jdk/src/share/classes/sun/nio/cs/UTF_8.java +@OPENJDK@/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java +@OPENJDK@/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java +@OPENJDK@/jdk/src/share/classes/sun/nio/fs/AbstractFileSystemProvider.java +@OPENJDK@/jdk/src/share/classes/sun/nio/fs/AbstractFileTypeDetector.java +@OPENJDK@/jdk/src/share/classes/sun/nio/fs/AbstractPath.java +@OPENJDK@/jdk/src/share/classes/sun/nio/fs/AbstractPoller.java +@OPENJDK@/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java +@OPENJDK@/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java +@OPENJDK@/jdk/src/share/classes/sun/nio/fs/AbstractWatchService.java +@OPENJDK@/jdk/src/share/classes/sun/nio/fs/BasicFileAttributesHolder.java +@OPENJDK@/jdk/src/share/classes/sun/nio/fs/DynamicFileAttributeView.java +@OPENJDK@/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java +@OPENJDK@/jdk/src/share/classes/sun/nio/fs/Globs.java +@OPENJDK@/jdk/src/share/classes/sun/nio/fs/PollingWatchService.java +@OPENJDK@/jdk/src/share/classes/sun/nio/fs/Reflect.java +@OPENJDK@/jdk/src/share/classes/sun/nio/fs/Util.java +@OPENJDK@/jdk/src/share/classes/sun/print/AttributeUpdater.java +@OPENJDK@/jdk/src/share/classes/sun/print/BackgroundLookupListener.java +@OPENJDK@/jdk/src/share/classes/sun/print/BackgroundServiceLookup.java +@OPENJDK@/jdk/src/share/classes/sun/print/CustomMediaSizeName.java +@OPENJDK@/jdk/src/share/classes/sun/print/CustomMediaTray.java +@OPENJDK@/jdk/src/share/classes/sun/print/DialogOwner.java +@OPENJDK@/jdk/src/share/classes/sun/print/DocumentPropertiesUI.java +@OPENJDK@/jdk/src/share/classes/sun/print/ImagePrinter.java +@OPENJDK@/jdk/src/share/classes/sun/print/OpenBook.java +@OPENJDK@/jdk/src/share/classes/sun/print/PageableDoc.java +@OPENJDK@/jdk/src/share/classes/sun/print/PathGraphics.java +@OPENJDK@/jdk/src/share/classes/sun/print/PeekGraphics.java +@OPENJDK@/jdk/src/share/classes/sun/print/PeekMetrics.java +@OPENJDK@/jdk/src/share/classes/sun/print/PrinterGraphicsConfig.java +@OPENJDK@/jdk/src/share/classes/sun/print/PrinterGraphicsDevice.java +@OPENJDK@/jdk/src/share/classes/sun/print/PrinterJobWrapper.java +@OPENJDK@/jdk/src/share/classes/sun/print/PrintJob2D.java +@OPENJDK@/jdk/src/share/classes/sun/print/PrintJobAttributeException.java +@OPENJDK@/jdk/src/share/classes/sun/print/PrintJobFlavorException.java +@OPENJDK@/jdk/src/share/classes/sun/print/ProxyGraphics.java +@OPENJDK@/jdk/src/share/classes/sun/print/ProxyGraphics2D.java +@OPENJDK@/jdk/src/share/classes/sun/print/ProxyPrintGraphics.java +@OPENJDK@/jdk/src/share/classes/sun/print/RasterPrinterJob.java +@OPENJDK@/jdk/src/share/classes/sun/print/ServiceDialog.java +@OPENJDK@/jdk/src/share/classes/sun/print/ServiceNotifier.java +@OPENJDK@/jdk/src/share/classes/sun/print/SunAlternateMedia.java +@OPENJDK@/jdk/src/share/classes/sun/print/SunMinMaxPage.java +@OPENJDK@/jdk/src/share/classes/sun/print/SunPageSelection.java +@OPENJDK@/jdk/src/share/classes/sun/print/SunPrinterJobService.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/annotation/AnnotationTypeMismatchExceptionProxy.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/annotation/EnumConstantNotPresentExceptionProxy.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/annotation/ExceptionProxy.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotation.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/annotation/TypeNotPresentExceptionProxy.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/CallerSensitive.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/ConstantPool.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/ConstructorAccessor.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/ConstructorAccessorImpl.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/FieldAccessor.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/factory/CoreReflectionFactory.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/factory/GenericsFactory.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/parser/SignatureParser.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/GenericArrayTypeImpl.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/LazyReflectiveObjectGenerator.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/NotImplementedException.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/WildcardTypeImpl.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/repository/AbstractRepository.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/repository/ClassRepository.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/repository/ConstructorRepository.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/repository/FieldRepository.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/repository/GenericDeclRepository.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/repository/MethodRepository.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/scope/AbstractScope.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/scope/ClassScope.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/scope/ConstructorScope.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/scope/DummyScope.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/scope/MethodScope.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/scope/Scope.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/ArrayTypeSignature.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/BaseType.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/BooleanSignature.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/BottomSignature.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/ByteSignature.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/CharSignature.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/ClassSignature.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/ClassTypeSignature.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/DoubleSignature.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/FieldTypeSignature.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/FloatSignature.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/FormalTypeParameter.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/IntSignature.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/LongSignature.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/MethodTypeSignature.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/ReturnType.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/ShortSignature.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/Signature.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/SimpleClassTypeSignature.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/Tree.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/TypeArgument.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/TypeSignature.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/TypeTree.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/TypeVariableSignature.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/VoidDescriptor.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/Wildcard.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/visitor/Reifier.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/visitor/TypeTreeVisitor.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/generics/visitor/Visitor.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/InstantiationExceptionConstructorAccessorImpl.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/LangReflectAccess.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/MagicAccessorImpl.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/misc/ConstructorUtil.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/misc/FieldUtil.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/misc/MethodUtil.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java +@OPENJDK@/jdk/src/share/classes/sun/reflect/SignatureIterator.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/log/LogHandler.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/log/LogInputStream.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/log/LogOutputStream.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/log/ReliableLog.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/BatchEnvironment.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/Constants.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/Generator.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/IndentingWriter.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/Main.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/Names.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/newrmic/BatchEnvironment.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/newrmic/Constants.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/newrmic/Generator.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/newrmic/IndentingWriter.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/newrmic/jrmp/Constants.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/newrmic/jrmp/JrmpGenerator.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/newrmic/jrmp/RemoteClass.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/newrmic/jrmp/StubSkeletonWriter.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/newrmic/jrmp/Util.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/newrmic/Main.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/newrmic/Resources.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/RemoteClass.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/RMIConstants.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/RMIGenerator.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/Util.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/runtime/Log.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/runtime/NewThreadAction.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/runtime/RuntimeUtil.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/server/ActivatableRef.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/server/ActivatableServerRef.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/server/Activation.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/server/ActivationGroupImpl.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/server/ActivationGroupInit.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/server/Dispatcher.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/server/InactiveGroupException.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/server/LoaderHandler.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/server/MarshalInputStream.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/server/MarshalOutputStream.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/server/UnicastRef.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/server/UnicastRef2.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/server/UnicastServerRef.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/server/UnicastServerRef2.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/server/Util.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/server/WeakClassHashMap.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/Channel.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/Connection.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/ConnectionInputStream.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/ConnectionOutputStream.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/DGCAckHandler.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/DGCClient.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/DGCImpl.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/Endpoint.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/LiveRef.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/ObjectEndpoint.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/ObjectTable.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/proxy/HttpAwareServerSocket.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/proxy/HttpInputStream.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/proxy/HttpOutputStream.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/proxy/HttpReceiveSocket.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/proxy/HttpSendInputStream.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/proxy/HttpSendOutputStream.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/proxy/RMIDirectSocketFactory.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/proxy/RMIHttpToCGISocketFactory.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/proxy/RMIHttpToPortSocketFactory.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/proxy/RMISocketInfo.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/proxy/WrappedSocket.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/StreamRemoteCall.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/Target.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/tcp/ConnectionMultiplexer.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/tcp/MultiplexConnectionInfo.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/tcp/MultiplexInputStream.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/tcp/MultiplexOutputStream.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/tcp/TCPChannel.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/tcp/TCPConnection.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/tcp/TCPEndpoint.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/tcp/TCPTransport.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/Transport.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/TransportConstants.java +@OPENJDK@/jdk/src/share/classes/sun/rmi/transport/WeakRef.java +@OPENJDK@/jdk/src/share/classes/sun/security/acl/AclEntryImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/acl/AclImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/acl/AllPermissionsImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/acl/GroupImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/acl/OwnerImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/acl/PermissionImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/acl/PrincipalImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/acl/WorldGroupImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/action/GetBooleanAction.java +@OPENJDK@/jdk/src/share/classes/sun/security/action/GetBooleanSecurityPropertyAction.java +@OPENJDK@/jdk/src/share/classes/sun/security/action/GetIntegerAction.java +@OPENJDK@/jdk/src/share/classes/sun/security/action/GetLongAction.java +@OPENJDK@/jdk/src/share/classes/sun/security/action/GetPropertyAction.java +@OPENJDK@/jdk/src/share/classes/sun/security/action/OpenFileInputStreamAction.java +@OPENJDK@/jdk/src/share/classes/sun/security/action/PutAllAction.java +@OPENJDK@/jdk/src/share/classes/sun/security/ec/CurveDB.java +@OPENJDK@/jdk/src/share/classes/sun/security/ec/ECKeyFactory.java +@OPENJDK@/jdk/src/share/classes/sun/security/ec/ECParameters.java +@OPENJDK@/jdk/src/share/classes/sun/security/ec/ECPrivateKeyImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/ec/ECPublicKeyImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/ec/NamedCurve.java +@OPENJDK@/jdk/src/share/classes/sun/security/ec/SunEC.java +@OPENJDK@/jdk/src/share/classes/sun/security/ec/SunECEntries.java +@OPENJDK@/jdk/src/share/classes/sun/security/internal/interfaces/TlsMasterSecret.java +@OPENJDK@/jdk/src/share/classes/sun/security/internal/spec/TlsKeyMaterialParameterSpec.java +@OPENJDK@/jdk/src/share/classes/sun/security/internal/spec/TlsKeyMaterialSpec.java +@OPENJDK@/jdk/src/share/classes/sun/security/internal/spec/TlsMasterSecretParameterSpec.java +@OPENJDK@/jdk/src/share/classes/sun/security/internal/spec/TlsPrfParameterSpec.java +@OPENJDK@/jdk/src/share/classes/sun/security/internal/spec/TlsRsaPremasterSecretParameterSpec.java +@OPENJDK@/jdk/src/share/classes/sun/security/jca/GetInstance.java +@OPENJDK@/jdk/src/share/classes/sun/security/jca/JCAUtil.java +@OPENJDK@/jdk/src/share/classes/sun/security/jca/ProviderConfig.java +@OPENJDK@/jdk/src/share/classes/sun/security/jca/ProviderList.java +@OPENJDK@/jdk/src/share/classes/sun/security/jca/Providers.java +@OPENJDK@/jdk/src/share/classes/sun/security/jca/ServiceId.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/GSSCaller.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/GSSContextImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/GSSCredentialImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/GSSExceptionImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/GSSHeader.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/GSSManagerImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/GSSNameImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/GSSToken.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/GSSUtil.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/HttpCaller.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/AcceptSecContextToken.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/CipherHelper.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/InitialToken.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/Krb5AcceptCredential.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/Krb5CredElement.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/Krb5NameElement.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/Krb5ProxyCredential.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Token.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Util.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/MessageToken.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/MessageToken_v2.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/MicToken.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/MicToken_v2.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/ServiceCreds.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/SubjectComber.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/WrapToken.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/WrapToken_v2.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/LoginConfigImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/ProviderList.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/spi/GSSContextSpi.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/spi/GSSCredentialSpi.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/spi/GSSNameSpi.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/spi/MechanismFactory.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/spnego/NegTokenInit.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/spnego/NegTokenTarg.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoContext.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoCredElement.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoMechFactory.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoToken.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/SunProvider.java +@OPENJDK@/jdk/src/share/classes/sun/security/jgss/TokenTracker.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/Asn1Exception.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/Checksum.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/Config.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/Confounder.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/Credentials.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/EncryptedData.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/APOptions.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/APRep.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/APReq.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/ASRep.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/ASReq.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/AuthContext.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/Authenticator.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/AuthorizationData.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/AuthorizationDataEntry.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/ccache/CCacheOutputStream.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/ccache/Credentials.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/ccache/CredentialsCache.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/ccache/FileCCacheConstants.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/ccache/MemoryCredentialsCache.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/ccache/Tag.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/CredentialsUtil.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/Aes128.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/Aes128CtsHmacSha1EType.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/Aes256.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/Aes256CtsHmacSha1EType.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/ArcFourHmac.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/ArcFourHmacEType.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/CksumType.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/crc32.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/Crc32CksumType.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/Des.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/Des3.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/Des3CbcHmacSha1KdEType.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/DesCbcCrcEType.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/DesCbcEType.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/DesCbcMd5EType.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/DesMacCksumType.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/DesMacKCksumType.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/dk/AesDkCrypto.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/dk/ArcFourCrypto.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/dk/Des3DkCrypto.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/dk/DkCrypto.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/HmacMd5ArcFourCksumType.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/HmacSha1Aes128CksumType.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/HmacSha1Aes256CksumType.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/HmacSha1Des3KdCksumType.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/KeyUsage.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/Nonce.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/NullEType.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/RsaMd5CksumType.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/RsaMd5DesCksumType.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/EncAPRepPart.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/EncASRepPart.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/EncKDCRepPart.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/EncKrbCredPart.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/EncKrbPrivPart.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/EncTGSRepPart.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/EncTicketPart.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/ETypeInfo.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/ETypeInfo2.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/HostAddress.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/HostAddresses.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/KdcErrException.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/KDCOptions.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/KDCRep.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/KDCReq.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/KDCReqBody.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/KerberosTime.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/Krb5.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/KrbApErrException.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/KRBCred.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/KrbCredInfo.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/KrbErrException.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/KRBError.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/KRBPriv.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/KRBSafe.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/KRBSafeBody.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTabConstants.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTabEntry.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTabInputStream.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTabOutputStream.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/LastReq.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/LastReqEntry.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/LocalSeqNumber.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/LoginOptions.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/MethodData.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/NetClient.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/PAData.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/PAEncTSEnc.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/PAForUserEnc.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/rcache/AuthList.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/rcache/AuthTime.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/rcache/AuthTimeWithHash.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/rcache/DflCache.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/rcache/MemoryCache.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/ReplayCache.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/SeqNumber.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/TGSRep.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/TGSReq.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/Ticket.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/TicketFlags.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/TransitedEncoding.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/util/KerberosFlags.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/util/KerberosString.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/util/KrbDataInputStream.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/util/KrbDataOutputStream.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/JavaxSecurityAuthKerberosAccess.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/KdcComm.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/KerberosSecrets.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/KrbAppMessage.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/KrbApRep.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/KrbApReq.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/KrbAsRep.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/KrbAsReq.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/KrbAsReqBuilder.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/KrbCred.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/KrbCryptoException.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/KrbException.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/KrbKdcRep.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/KrbPriv.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/KrbSafe.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/KrbServiceLocator.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/KrbTgsRep.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/KrbTgsReq.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/PrincipalName.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/Realm.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/RealmException.java +@OPENJDK@/jdk/src/share/classes/sun/security/krb5/SCDynamicStoreConfig.java +@OPENJDK@/jdk/src/share/classes/sun/security/pkcs/ContentInfo.java +@OPENJDK@/jdk/src/share/classes/sun/security/pkcs/EncryptedPrivateKeyInfo.java +@OPENJDK@/jdk/src/share/classes/sun/security/pkcs/ParsingException.java +@OPENJDK@/jdk/src/share/classes/sun/security/pkcs/PKCS7.java +@OPENJDK@/jdk/src/share/classes/sun/security/pkcs/PKCS8Key.java +@OPENJDK@/jdk/src/share/classes/sun/security/pkcs/PKCS9Attribute.java +@OPENJDK@/jdk/src/share/classes/sun/security/pkcs/PKCS9Attributes.java +@OPENJDK@/jdk/src/share/classes/sun/security/pkcs/SignerInfo.java +@OPENJDK@/jdk/src/share/classes/sun/security/pkcs/SigningCertificateInfo.java +@OPENJDK@/jdk/src/share/classes/sun/security/pkcs10/PKCS10.java +@OPENJDK@/jdk/src/share/classes/sun/security/pkcs10/PKCS10Attribute.java +@OPENJDK@/jdk/src/share/classes/sun/security/pkcs10/PKCS10Attributes.java +@OPENJDK@/jdk/src/share/classes/sun/security/pkcs12/MacData.java +@OPENJDK@/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/AuthPolicyFile.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/ByteArrayAccess.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/AdaptableX509CertSelector.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/AdjacencyList.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/BasicChecker.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/Builder.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/BuildStep.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/CertId.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/CertPathHelper.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/CollectionCertStore.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/ConstraintsChecker.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/ForwardState.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/IndexedCollectionCertStore.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/KeyChecker.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreHelper.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/OCSPRequest.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/PKIX.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/PolicyChecker.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/PolicyNodeImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/ReverseState.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/RevocationChecker.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/ssl/SSLServerCertStore.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/ssl/SSLServerCertStoreHelper.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/State.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilderException.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilderParameters.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilderResult.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/UntrustedChecker.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/Vertex.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/X509CertificatePair.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/X509CertPath.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/ConfigFile.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/DigestBase.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/DomainKeyStore.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/DSA.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/DSAKeyFactory.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/DSAKeyPairGenerator.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/DSAParameterGenerator.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/DSAParameters.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/DSAPrivateKey.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/DSAPublicKey.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/DSAPublicKeyImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/JavaKeyStore.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/KeyProtector.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/MD2.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/MD4.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/MD5.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/ParameterCache.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/PolicyFile.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/PolicyParser.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/PolicySpiFile.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/SecureRandom.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/SeedGenerator.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/SHA.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/SHA2.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/SHA5.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/SubjectCodeSource.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/Sun.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/SunEntries.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/VerificationProvider.java +@OPENJDK@/jdk/src/share/classes/sun/security/provider/X509Factory.java +@OPENJDK@/jdk/src/share/classes/sun/security/rsa/RSACore.java +@OPENJDK@/jdk/src/share/classes/sun/security/rsa/RSAKeyFactory.java +@OPENJDK@/jdk/src/share/classes/sun/security/rsa/RSAKeyPairGenerator.java +@OPENJDK@/jdk/src/share/classes/sun/security/rsa/RSAPadding.java +@OPENJDK@/jdk/src/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/rsa/RSAPrivateKeyImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/rsa/RSAPublicKeyImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/rsa/RSASignature.java +@OPENJDK@/jdk/src/share/classes/sun/security/rsa/SunRsaSign.java +@OPENJDK@/jdk/src/share/classes/sun/security/rsa/SunRsaSignEntries.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/Alerts.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/AppInputStream.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/AppOutputStream.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/Authenticator.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/BaseSSLSocketImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/ByteBufferInputStream.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/CipherBox.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/CipherSuite.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/CipherSuiteList.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/Debug.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/DHClientKeyExchange.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/DHCrypt.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/ECDHClientKeyExchange.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/ECDHCrypt.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/EngineArgs.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/EngineInputRecord.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/EngineOutputRecord.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/EngineWriter.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/EphemeralKeyManager.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/ExtensionType.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/HandshakeHash.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/HandshakeInStream.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/HandshakeOutStream.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/Handshaker.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/HelloExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/HelloExtensions.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/InputRecord.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/JsseJce.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/KerberosClientKeyExchange.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/KeyManagerFactoryImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/krb5/KerberosPreMasterSecret.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/krb5/Krb5ProxyImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/Krb5Helper.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/Krb5Proxy.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/MAC.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/OutputRecord.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/ProtocolList.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/ProtocolVersion.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/RandomCookie.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/Record.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/RenegotiationInfoExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/RSASignature.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/ServerNameExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/SessionId.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/SSLContextImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/SSLServerSocketFactoryImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/SSLServerSocketImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/SSLSessionContextImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/SSLSessionImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/SSLSocketFactoryImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/SunJSSE.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/SunX509KeyManagerImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/SupportedEllipticCurvesExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/SupportedEllipticPointFormatsExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/TrustManagerFactoryImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/UnknownExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/Utilities.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/ssl/X509TrustManagerImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/timestamp/HttpTimestamper.java +@OPENJDK@/jdk/src/share/classes/sun/security/timestamp/Timestamper.java +@OPENJDK@/jdk/src/share/classes/sun/security/timestamp/TimestampToken.java +@OPENJDK@/jdk/src/share/classes/sun/security/timestamp/TSRequest.java +@OPENJDK@/jdk/src/share/classes/sun/security/timestamp/TSResponse.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/jarsigner/Resources.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/jarsigner/Resources_ja.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/jarsigner/TimestampedSigner.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/KeyStoreUtil.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/keytool/CertAndKeyGen.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/keytool/Main.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/keytool/Resources.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/keytool/Resources_de.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/keytool/Resources_es.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/keytool/Resources_fr.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/keytool/Resources_it.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/keytool/Resources_ja.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/keytool/Resources_ko.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/keytool/Resources_pt_BR.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/keytool/Resources_sv.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/keytool/Resources_zh_CN.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/keytool/Resources_zh_HK.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/keytool/Resources_zh_TW.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/PathList.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/policytool/PolicyTool.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/policytool/Resources.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/policytool/Resources_de.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/policytool/Resources_es.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/policytool/Resources_fr.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/policytool/Resources_it.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/policytool/Resources_ja.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/policytool/Resources_ko.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/policytool/Resources_pt_BR.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/policytool/Resources_sv.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/policytool/Resources_zh_CN.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/policytool/Resources_zh_HK.java +@OPENJDK@/jdk/src/share/classes/sun/security/tools/policytool/Resources_zh_TW.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/AuthResources.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/AuthResources_de.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/AuthResources_es.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/AuthResources_fr.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/AuthResources_it.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/AuthResources_ja.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/AuthResources_ko.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/AuthResources_pt_BR.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/AuthResources_sv.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/AuthResources_zh_CN.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/AuthResources_zh_TW.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/BitArray.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/ByteArrayLexOrder.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/ByteArrayTagOrder.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/Cache.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/Debug.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/DerEncoder.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/DerIndefLenConverter.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/DerInputBuffer.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/DerInputStream.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/DerOutputStream.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/DerValue.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/ECKeySizeParameterSpec.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/ECUtil.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/HostnameChecker.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/KeyUtil.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/Length.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/ManifestDigester.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/ManifestEntryVerifier.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/ObjectIdentifier.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/Password.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/PendingException.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/PermissionFactory.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/PolicyUtil.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/PropertyExpander.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/Resources.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/Resources_de.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/Resources_es.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/Resources_fr.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/Resources_it.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/Resources_ja.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/Resources_ko.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/Resources_pt_BR.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/Resources_sv.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/Resources_zh_CN.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/Resources_zh_TW.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/ResourcesMgr.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/SecurityConstants.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java +@OPENJDK@/jdk/src/share/classes/sun/security/util/UntrustedCertificates.java +@OPENJDK@/jdk/src/share/classes/sun/security/validator/EndEntityChecker.java +@OPENJDK@/jdk/src/share/classes/sun/security/validator/KeyStores.java +@OPENJDK@/jdk/src/share/classes/sun/security/validator/PKIXValidator.java +@OPENJDK@/jdk/src/share/classes/sun/security/validator/SimpleValidator.java +@OPENJDK@/jdk/src/share/classes/sun/security/validator/Validator.java +@OPENJDK@/jdk/src/share/classes/sun/security/validator/ValidatorException.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/AccessDescription.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/AlgIdDSA.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/AlgorithmId.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/AttributeNameEnumeration.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/AuthorityInfoAccessExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/AuthorityKeyIdentifierExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/AVA.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/BasicConstraintsExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/CertAttrSet.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/CertException.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/CertificateAlgorithmId.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/CertificateExtensions.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/CertificateIssuerExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/CertificateIssuerName.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/CertificatePoliciesExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/CertificatePolicyId.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/CertificatePolicyMap.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/CertificatePolicySet.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/CertificateSerialNumber.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/CertificateSubjectName.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/CertificateValidity.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/CertificateVersion.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/CertificateX509Key.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/CertParseError.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/CRLDistributionPointsExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/CRLExtensions.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/CRLNumberExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/CRLReasonCodeExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/DeltaCRLIndicatorExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/DistributionPoint.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/DistributionPointName.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/DNSName.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/EDIPartyName.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/ExtendedKeyUsageExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/Extension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/FreshestCRLExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/GeneralName.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/GeneralNameInterface.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/GeneralNames.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/GeneralSubtree.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/GeneralSubtrees.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/InhibitAnyPolicyExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/InvalidityDateExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/IPAddressName.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/IssuerAlternativeNameExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/IssuingDistributionPointExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/KeyIdentifier.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/KeyUsageExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/NameConstraintsExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/NetscapeCertTypeExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/OCSPNoCheckExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/OIDMap.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/OIDName.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/OtherName.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/PKIXExtensions.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/PolicyConstraintsExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/PolicyInformation.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/PolicyMappingsExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/PrivateKeyUsageExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/RDN.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/ReasonFlags.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/RFC822Name.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/SerialNumber.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/SubjectAlternativeNameExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/SubjectInfoAccessExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/SubjectKeyIdentifierExtension.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/UniqueIdentity.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/URIName.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/X400Address.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/X500Name.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/X509AttributeName.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/X509CertImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/X509CertInfo.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/X509CRLEntryImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/X509CRLImpl.java +@OPENJDK@/jdk/src/share/classes/sun/security/x509/X509Key.java +@OPENJDK@/jdk/src/share/classes/sun/swing/AccumulativeRunnable.java +@OPENJDK@/jdk/src/share/classes/sun/swing/BakedArrayList.java +@OPENJDK@/jdk/src/share/classes/sun/swing/CachedPainter.java +@OPENJDK@/jdk/src/share/classes/sun/swing/DefaultLayoutStyle.java +@OPENJDK@/jdk/src/share/classes/sun/swing/DefaultLookup.java +@OPENJDK@/jdk/src/share/classes/sun/swing/FilePane.java +@OPENJDK@/jdk/src/share/classes/sun/swing/icon/SortArrowIcon.java +@OPENJDK@/jdk/src/share/classes/sun/swing/ImageCache.java +@OPENJDK@/jdk/src/share/classes/sun/swing/ImageIconUIResource.java +@OPENJDK@/jdk/src/share/classes/sun/swing/JLightweightFrame.java +@OPENJDK@/jdk/src/share/classes/sun/swing/LightweightContent.java +@OPENJDK@/jdk/src/share/classes/sun/swing/MenuItemCheckIconFactory.java +@OPENJDK@/jdk/src/share/classes/sun/swing/MenuItemLayoutHelper.java +@OPENJDK@/jdk/src/share/classes/sun/swing/plaf/GTKKeybindings.java +@OPENJDK@/jdk/src/share/classes/sun/swing/plaf/synth/DefaultSynthStyle.java +@OPENJDK@/jdk/src/share/classes/sun/swing/plaf/synth/Paint9Painter.java +@OPENJDK@/jdk/src/share/classes/sun/swing/plaf/synth/StyleAssociation.java +@OPENJDK@/jdk/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUI.java +@OPENJDK@/jdk/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java +@OPENJDK@/jdk/src/share/classes/sun/swing/plaf/synth/SynthIcon.java +@OPENJDK@/jdk/src/share/classes/sun/swing/plaf/windows/ClassicSortArrowIcon.java +@OPENJDK@/jdk/src/share/classes/sun/swing/plaf/WindowsKeybindings.java +@OPENJDK@/jdk/src/share/classes/sun/swing/PrintColorUIResource.java +@OPENJDK@/jdk/src/share/classes/sun/swing/PrintingStatus.java +@OPENJDK@/jdk/src/share/classes/sun/swing/StringUIClientPropertyKey.java +@OPENJDK@/jdk/src/share/classes/sun/swing/SwingAccessor.java +@OPENJDK@/jdk/src/share/classes/sun/swing/SwingLazyValue.java +@OPENJDK@/jdk/src/share/classes/sun/swing/SwingUtilities2.java +@OPENJDK@/jdk/src/share/classes/sun/swing/table/DefaultTableCellHeaderRenderer.java +@OPENJDK@/jdk/src/share/classes/sun/swing/text/CompoundPrintable.java +@OPENJDK@/jdk/src/share/classes/sun/swing/text/CountingPrintable.java +@OPENJDK@/jdk/src/share/classes/sun/swing/text/html/FrameEditorPaneTag.java +@OPENJDK@/jdk/src/share/classes/sun/swing/text/TextComponentPrintable.java +@OPENJDK@/jdk/src/share/classes/sun/swing/UIAction.java +@OPENJDK@/jdk/src/share/classes/sun/swing/UIClientPropertyKey.java +@OPENJDK@/jdk/src/share/classes/sun/swing/WindowsPlacesBar.java +@OPENJDK@/jdk/src/share/classes/sun/text/bidi/BidiBase.java +@OPENJDK@/jdk/src/share/classes/sun/text/bidi/BidiLine.java +@OPENJDK@/jdk/src/share/classes/sun/text/bidi/BidiRun.java +@OPENJDK@/jdk/src/share/classes/sun/text/CodePointIterator.java +@OPENJDK@/jdk/src/share/classes/sun/text/CollatorUtilities.java +@OPENJDK@/jdk/src/share/classes/sun/text/CompactByteArray.java +@OPENJDK@/jdk/src/share/classes/sun/text/ComposedCharIter.java +@OPENJDK@/jdk/src/share/classes/sun/text/IntHashtable.java +@OPENJDK@/jdk/src/share/classes/sun/text/Normalizer.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/CharacterIteratorWrapper.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/CharTrie.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/ICUBinary.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/ICUData.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/IntTrie.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/NormalizerBase.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/NormalizerDataReader.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/NormalizerImpl.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/RangeValueIterator.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/Replaceable.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/ReplaceableString.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/ReplaceableUCharacterIterator.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/RuleCharacterIterator.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/SymbolTable.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/Trie.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/TrieIterator.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/UBiDiProps.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/UCharacter.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/UCharacterIterator.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/UCharacterProperty.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/UCharacterPropertyReader.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/UnicodeMatcher.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/UnicodeSet.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/UnicodeSetIterator.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/UTF16.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/Utility.java +@OPENJDK@/jdk/src/share/classes/sun/text/normalizer/VersionInfo.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ar/CollationData_ar.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ar/FormatData_ar.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ar/FormatData_ar_JO.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ar/FormatData_ar_LB.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ar/FormatData_ar_SY.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ar/JavaTimeSupplementary_ar.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/be/CollationData_be.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/be/FormatData_be.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/be/FormatData_be_BY.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/be/JavaTimeSupplementary_be.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/bg/CollationData_bg.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/bg/FormatData_bg.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/bg/FormatData_bg_BG.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/bg/JavaTimeSupplementary_bg.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/BreakIteratorInfo.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ca/CollationData_ca.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ca/FormatData_ca.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ca/FormatData_ca_ES.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ca/JavaTimeSupplementary_ca.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/CollationData.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/cs/CollationData_cs.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/cs/FormatData_cs.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/cs/FormatData_cs_CZ.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/cs/JavaTimeSupplementary_cs.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/da/CollationData_da.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/da/FormatData_da.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/da/FormatData_da_DK.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/da/JavaTimeSupplementary_da.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/de/FormatData_de.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/de/FormatData_de_AT.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/de/FormatData_de_CH.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/de/FormatData_de_DE.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/de/FormatData_de_LU.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/de/JavaTimeSupplementary_de.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/el/CollationData_el.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/el/FormatData_el.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/el/FormatData_el_CY.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/el/FormatData_el_GR.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/el/JavaTimeSupplementary_el.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/en/FormatData_en.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/en/FormatData_en_AU.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/en/FormatData_en_CA.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/en/FormatData_en_GB.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/en/FormatData_en_IE.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/en/FormatData_en_IN.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/en/FormatData_en_MT.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/en/FormatData_en_NZ.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/en/FormatData_en_PH.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/en/FormatData_en_SG.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/en/FormatData_en_US.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/en/FormatData_en_ZA.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/en/JavaTimeSupplementary_en.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/en/JavaTimeSupplementary_en_GB.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/en/JavaTimeSupplementary_en_SG.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/CollationData_es.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/FormatData_es.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/FormatData_es_AR.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/FormatData_es_BO.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/FormatData_es_CL.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/FormatData_es_CO.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/FormatData_es_CR.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/FormatData_es_DO.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/FormatData_es_EC.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/FormatData_es_ES.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/FormatData_es_GT.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/FormatData_es_HN.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/FormatData_es_MX.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/FormatData_es_NI.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/FormatData_es_PA.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/FormatData_es_PE.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/FormatData_es_PR.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/FormatData_es_PY.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/FormatData_es_SV.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/FormatData_es_US.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/FormatData_es_UY.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/FormatData_es_VE.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/es/JavaTimeSupplementary_es.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/et/CollationData_et.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/et/FormatData_et.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/et/FormatData_et_EE.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/et/JavaTimeSupplementary_et.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/fi/CollationData_fi.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/fi/FormatData_fi.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/fi/FormatData_fi_FI.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/fi/JavaTimeSupplementary_fi.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/FormatData.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/fr/CollationData_fr.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/fr/FormatData_fr.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/fr/FormatData_fr_BE.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/fr/FormatData_fr_CA.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/fr/FormatData_fr_CH.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/fr/FormatData_fr_FR.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/fr/JavaTimeSupplementary_fr.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ga/FormatData_ga.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ga/FormatData_ga_IE.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ga/JavaTimeSupplementary_ga.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/hi/CollationData_hi.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/hi/FormatData_hi_IN.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/hi/JavaTimeSupplementary_hi_IN.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/hr/CollationData_hr.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/hr/FormatData_hr.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/hr/FormatData_hr_HR.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/hr/JavaTimeSupplementary_hr.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/hu/CollationData_hu.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/hu/FormatData_hu.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/hu/FormatData_hu_HU.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/hu/JavaTimeSupplementary_hu.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/in/FormatData_in.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/in/FormatData_in_ID.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/is/CollationData_is.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/is/FormatData_is.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/is/FormatData_is_IS.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/is/JavaTimeSupplementary_is.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/it/FormatData_it.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/it/FormatData_it_CH.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/it/FormatData_it_IT.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/it/JavaTimeSupplementary_it.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/iw/CollationData_iw.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/iw/FormatData_iw.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/iw/FormatData_iw_IL.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/iw/JavaTimeSupplementary_iw.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/iw/JavaTimeSupplementary_iw_IL.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ja/CollationData_ja.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ja/FormatData_ja.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ja/FormatData_ja_JP.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ja/JavaTimeSupplementary_ja.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/JavaTimeSupplementary.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ko/CollationData_ko.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ko/FormatData_ko.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ko/FormatData_ko_KR.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ko/JavaTimeSupplementary_ko.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/lt/CollationData_lt.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/lt/FormatData_lt.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/lt/FormatData_lt_LT.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/lt/JavaTimeSupplementary_lt.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/lv/CollationData_lv.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/lv/FormatData_lv.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/lv/FormatData_lv_LV.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/lv/JavaTimeSupplementary_lv.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/mk/CollationData_mk.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/mk/FormatData_mk.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/mk/FormatData_mk_MK.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/mk/JavaTimeSupplementary_mk.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ms/FormatData_ms.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ms/FormatData_ms_MY.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ms/JavaTimeSupplementary_ms.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/mt/FormatData_mt.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/mt/FormatData_mt_MT.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/mt/JavaTimeSupplementary_mt.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/nl/FormatData_nl.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/nl/FormatData_nl_BE.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/nl/FormatData_nl_NL.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/nl/JavaTimeSupplementary_nl.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/no/CollationData_no.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/no/FormatData_no.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/no/FormatData_no_NO.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/no/FormatData_no_NO_NY.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/no/JavaTimeSupplementary_no.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/pl/CollationData_pl.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/pl/FormatData_pl.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/pl/FormatData_pl_PL.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/pl/JavaTimeSupplementary_pl.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/pt/FormatData_pt.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/pt/FormatData_pt_BR.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/pt/FormatData_pt_PT.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/pt/JavaTimeSupplementary_pt.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/pt/JavaTimeSupplementary_pt_PT.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ro/CollationData_ro.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ro/FormatData_ro.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ro/FormatData_ro_RO.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ro/JavaTimeSupplementary_ro.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ru/CollationData_ru.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ru/FormatData_ru.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ru/FormatData_ru_RU.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/ru/JavaTimeSupplementary_ru.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sk/CollationData_sk.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sk/FormatData_sk.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sk/FormatData_sk_SK.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sk/JavaTimeSupplementary_sk.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sl/CollationData_sl.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sl/FormatData_sl.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sl/FormatData_sl_SI.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sl/JavaTimeSupplementary_sl.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sq/CollationData_sq.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sq/FormatData_sq.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sq/FormatData_sq_AL.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sq/JavaTimeSupplementary_sq.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sr/CollationData_sr.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sr/CollationData_sr_Latn.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sr/FormatData_sr.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sr/FormatData_sr_BA.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sr/FormatData_sr_CS.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sr/FormatData_sr_Latn.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sr/FormatData_sr_Latn_ME.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sr/FormatData_sr_ME.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sr/FormatData_sr_RS.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sr/JavaTimeSupplementary_sr.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sr/JavaTimeSupplementary_sr_Latn.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sv/CollationData_sv.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sv/FormatData_sv.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sv/FormatData_sv_SE.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/sv/JavaTimeSupplementary_sv.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/th/BreakIteratorInfo_th.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/th/BreakIteratorRules_th.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/th/CollationData_th.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/th/FormatData_th.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/th/FormatData_th_TH.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/th/JavaTimeSupplementary_th.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/tr/CollationData_tr.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/tr/FormatData_tr.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/tr/FormatData_tr_TR.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/tr/JavaTimeSupplementary_tr.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/uk/CollationData_uk.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/uk/FormatData_uk.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/uk/FormatData_uk_UA.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/uk/JavaTimeSupplementary_uk.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/vi/CollationData_vi.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/vi/FormatData_vi.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/vi/FormatData_vi_VN.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/vi/JavaTimeSupplementary_vi.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/zh/CollationData_zh.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/zh/CollationData_zh_HK.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/zh/CollationData_zh_TW.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/zh/FormatData_zh.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/zh/FormatData_zh_CN.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/zh/FormatData_zh_HK.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/zh/FormatData_zh_SG.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/zh/FormatData_zh_TW.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/zh/JavaTimeSupplementary_zh.java +@OPENJDK@/jdk/src/share/classes/sun/text/resources/zh/JavaTimeSupplementary_zh_TW.java +@OPENJDK@/jdk/src/share/classes/sun/text/SupplementaryCharacterData.java +@OPENJDK@/jdk/src/share/classes/sun/text/UCompactIntArray.java +@OPENJDK@/jdk/src/share/classes/sun/tools/asm/ArrayData.java +@OPENJDK@/jdk/src/share/classes/sun/tools/asm/Assembler.java +@OPENJDK@/jdk/src/share/classes/sun/tools/asm/CatchData.java +@OPENJDK@/jdk/src/share/classes/sun/tools/asm/ClassConstantData.java +@OPENJDK@/jdk/src/share/classes/sun/tools/asm/ConstantPool.java +@OPENJDK@/jdk/src/share/classes/sun/tools/asm/ConstantPoolData.java +@OPENJDK@/jdk/src/share/classes/sun/tools/asm/Cover.java +@OPENJDK@/jdk/src/share/classes/sun/tools/asm/FieldConstantData.java +@OPENJDK@/jdk/src/share/classes/sun/tools/asm/Instruction.java +@OPENJDK@/jdk/src/share/classes/sun/tools/asm/Label.java +@OPENJDK@/jdk/src/share/classes/sun/tools/asm/LocalVariable.java +@OPENJDK@/jdk/src/share/classes/sun/tools/asm/LocalVariableTable.java +@OPENJDK@/jdk/src/share/classes/sun/tools/asm/NameAndTypeConstantData.java +@OPENJDK@/jdk/src/share/classes/sun/tools/asm/NameAndTypeData.java +@OPENJDK@/jdk/src/share/classes/sun/tools/asm/NumberConstantData.java +@OPENJDK@/jdk/src/share/classes/sun/tools/asm/StringConstantData.java +@OPENJDK@/jdk/src/share/classes/sun/tools/asm/StringExpressionConstantData.java +@OPENJDK@/jdk/src/share/classes/sun/tools/asm/SwitchData.java +@OPENJDK@/jdk/src/share/classes/sun/tools/asm/TryData.java +@OPENJDK@/jdk/src/share/classes/sun/tools/jar/CommandLine.java +@OPENJDK@/jdk/src/share/classes/sun/tools/jar/JarException.java +@OPENJDK@/jdk/src/share/classes/sun/tools/jar/Main.java +@OPENJDK@/jdk/src/share/classes/sun/tools/jar/Manifest.java +@OPENJDK@/jdk/src/share/classes/sun/tools/jar/SignatureFile.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/AmbiguousClass.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/AmbiguousMember.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/ArrayType.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/BinaryAttribute.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/BinaryClass.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/BinaryCode.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/BinaryConstantPool.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/BinaryExceptionHandler.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/BinaryMember.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/ClassDeclaration.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/ClassDefinition.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/ClassFile.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/ClassNotFound.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/ClassPath.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/ClassType.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/CompilerError.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/Constants.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/Environment.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/Identifier.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/IdentifierToken.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/Imports.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/MemberDefinition.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/MethodSet.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/MethodType.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/Package.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/Parser.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/ParserActions.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/RuntimeConstants.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/Scanner.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/ScannerInputReader.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/SyntaxError.java +@OPENJDK@/jdk/src/share/classes/sun/tools/java/Type.java +@OPENJDK@/jdk/src/share/classes/sun/tools/javac/BatchEnvironment.java +@OPENJDK@/jdk/src/share/classes/sun/tools/javac/BatchParser.java +@OPENJDK@/jdk/src/share/classes/sun/tools/javac/CompilerMember.java +@OPENJDK@/jdk/src/share/classes/sun/tools/javac/ErrorConsumer.java +@OPENJDK@/jdk/src/share/classes/sun/tools/javac/ErrorMessage.java +@OPENJDK@/jdk/src/share/classes/sun/tools/javac/Main.java +@OPENJDK@/jdk/src/share/classes/sun/tools/javac/SourceClass.java +@OPENJDK@/jdk/src/share/classes/sun/tools/javac/SourceMember.java +@OPENJDK@/jdk/src/share/classes/sun/tools/native2ascii/A2NFilter.java +@OPENJDK@/jdk/src/share/classes/sun/tools/native2ascii/Main.java +@OPENJDK@/jdk/src/share/classes/sun/tools/native2ascii/N2AFilter.java +@OPENJDK@/jdk/src/share/classes/sun/tools/native2ascii/resources/MsgNative2ascii.java +@OPENJDK@/jdk/src/share/classes/sun/tools/native2ascii/resources/MsgNative2ascii_ja.java +@OPENJDK@/jdk/src/share/classes/sun/tools/native2ascii/resources/MsgNative2ascii_zh_CN.java +@OPENJDK@/jdk/src/share/classes/sun/tools/serialver/SerialVer.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/AddExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/AndExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/ArrayAccessExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/ArrayExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/AssignAddExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/AssignBitAndExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/AssignBitOrExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/AssignBitXorExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/AssignDivideExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/AssignExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/AssignMultiplyExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/AssignOpExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/AssignRemainderExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/AssignShiftLeftExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/AssignShiftRightExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/AssignSubtractExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/AssignUnsignedShiftRightExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/BinaryArithmeticExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/BinaryAssignExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/BinaryBitExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/BinaryCompareExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/BinaryEqualityExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/BinaryExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/BinaryLogicalExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/BinaryShiftExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/BitAndExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/BitNotExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/BitOrExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/BitXorExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/BooleanExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/BreakStatement.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/ByteExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/CaseStatement.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/CastExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/CatchStatement.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/CharExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/CheckContext.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/CodeContext.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/CommaExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/CompoundStatement.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/ConditionalExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/ConditionVars.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/ConstantExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/Context.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/ContinueStatement.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/ConvertExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/DeclarationStatement.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/DivideExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/DivRemExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/DoStatement.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/DoubleExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/EqualExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/Expression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/ExpressionStatement.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/ExprExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/FieldExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/FieldUpdater.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/FinallyStatement.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/FloatExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/ForStatement.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/GreaterExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/GreaterOrEqualExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/IdentifierExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/IfStatement.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/IncDecExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/InlineMethodExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/InlineNewInstanceExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/InlineReturnStatement.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/InstanceOfExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/IntegerExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/IntExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/LengthExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/LessExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/LessOrEqualExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/LocalMember.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/LongExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/MethodExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/MultiplyExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/NaryExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/NegativeExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/NewArrayExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/NewInstanceExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/Node.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/NotEqualExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/NotExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/NullExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/OrExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/PositiveExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/PostDecExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/PostIncExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/PreDecExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/PreIncExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/RemainderExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/ReturnStatement.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/ShiftLeftExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/ShiftRightExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/ShortExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/Statement.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/StringExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/SubtractExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/SuperExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/SwitchStatement.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/SynchronizedStatement.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/ThisExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/ThrowStatement.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/TryStatement.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/TypeExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/UnaryExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/UnsignedShiftRightExpression.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/UplevelReference.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/VarDeclarationStatement.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/Vset.java +@OPENJDK@/jdk/src/share/classes/sun/tools/tree/WhileStatement.java +@OPENJDK@/jdk/src/share/classes/sun/tools/util/CommandLine.java +@OPENJDK@/jdk/src/share/classes/sun/tools/util/ModifierFilter.java +@OPENJDK@/jdk/src/share/classes/sun/util/BuddhistCalendar.java +@OPENJDK@/jdk/src/share/classes/sun/util/calendar/AbstractCalendar.java +@OPENJDK@/jdk/src/share/classes/sun/util/calendar/BaseCalendar.java +@OPENJDK@/jdk/src/share/classes/sun/util/calendar/CalendarDate.java +@OPENJDK@/jdk/src/share/classes/sun/util/calendar/CalendarSystem.java +@OPENJDK@/jdk/src/share/classes/sun/util/calendar/CalendarUtils.java +@OPENJDK@/jdk/src/share/classes/sun/util/calendar/Era.java +@OPENJDK@/jdk/src/share/classes/sun/util/calendar/Gregorian.java +@OPENJDK@/jdk/src/share/classes/sun/util/calendar/ImmutableGregorianDate.java +@OPENJDK@/jdk/src/share/classes/sun/util/calendar/JulianCalendar.java +@OPENJDK@/jdk/src/share/classes/sun/util/calendar/LocalGregorianCalendar.java +@OPENJDK@/jdk/src/share/classes/sun/util/calendar/ZoneInfo.java +@OPENJDK@/jdk/src/share/classes/sun/util/calendar/ZoneInfoFile.java +@OPENJDK@/jdk/src/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/AsciiUtil.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/BaseLocale.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/Extension.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/InternalLocaleBuilder.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/LanguageTag.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/LocaleEquivalentMaps.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/LocaleExtensions.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/LocaleMatcher.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/LocaleObjectCache.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/LocaleSyntaxException.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/LocaleUtils.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/ParseStatus.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/AvailableLanguageTags.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/BreakDictionary.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/BreakIteratorProviderImpl.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/CalendarDataProviderImpl.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/CalendarDataUtility.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/CalendarNameProviderImpl.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/CalendarProviderImpl.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/CollationRules.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/CollatorProviderImpl.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/CurrencyNameProviderImpl.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/DateFormatProviderImpl.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/DateFormatSymbolsProviderImpl.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/DecimalFormatSymbolsProviderImpl.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/DictionaryBasedBreakIterator.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/FallbackLocaleProviderAdapter.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/HostLocaleProviderAdapter.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/JRELocaleConstants.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/LocaleNameProviderImpl.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/LocaleResources.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/LocaleServiceProviderPool.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/NumberFormatProviderImpl.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/ResourceBundleBasedAdapter.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/RuleBasedBreakIterator.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/TimeZoneNameProviderImpl.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/TimeZoneNameUtility.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/StringTokenIterator.java +@OPENJDK@/jdk/src/share/classes/sun/util/locale/UnicodeLocaleExtension.java +@OPENJDK@/jdk/src/share/classes/sun/util/logging/LoggingProxy.java +@OPENJDK@/jdk/src/share/classes/sun/util/logging/LoggingSupport.java +@OPENJDK@/jdk/src/share/classes/sun/util/logging/PlatformLogger.java +@OPENJDK@/jdk/src/share/classes/sun/util/PreHashedMap.java +@OPENJDK@/jdk/src/share/classes/sun/util/ResourceBundleEnumeration.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/de/TimeZoneNames_de.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/en/TimeZoneNames_en.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/en/TimeZoneNames_en_CA.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/en/TimeZoneNames_en_GB.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/en/TimeZoneNames_en_IE.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/es/TimeZoneNames_es.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/hi/TimeZoneNames_hi.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/it/TimeZoneNames_it.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/LocaleData.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/LocaleNamesBundle.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/OpenListResourceBundle.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/ParallelListResourceBundle.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/TimeZoneNamesBundle.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/zh/CurrencyNames_zh_HK.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/zh/CurrencyNames_zh_SG.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/zh/LocaleNames_zh_HK.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_HK.java +@OPENJDK@/jdk/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java +@OPENJDK@/jdk/src/share/classes/sun/util/spi/CalendarProvider.java +@OPENJDK@/jdk/src/share/classes/sun/util/spi/XmlPropertiesProvider.java +@OPENJDK@/jdk/src/share/classes/sun/util/xml/PlatformXmlPropertiesProvider.java +@OPENJDK@/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/JarFileSystemProvider.java +@OPENJDK@/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipCoder.java +@OPENJDK@/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipConstants.java +@OPENJDK@/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipDirectoryStream.java +@OPENJDK@/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileAttributes.java +@OPENJDK@/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileAttributeView.java +@OPENJDK@/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileStore.java +@OPENJDK@/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java +@OPENJDK@/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystemProvider.java +@OPENJDK@/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipInfo.java +@OPENJDK@/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipPath.java +@OPENJDK@/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipUtils.java +@OPENJDK@/jdk/src/solaris/classes/java/io/UnixFileSystem.java +@OPENJDK@/jdk/src/solaris/classes/java/util/prefs/FileSystemPreferences.java +@OPENJDK@/jdk/src/solaris/classes/java/util/prefs/FileSystemPreferencesFactory.java +@OPENJDK@/jdk/src/solaris/classes/sun/awt/windows/ThemeReader.java +@OPENJDK@/jdk/src/solaris/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java +@OPENJDK@/jdk/src/windows/classes/java/io/WinNTFileSystem.java +@OPENJDK@/jdk/src/windows/classes/java/lang/ProcessEnvironment.java +@OPENJDK@/jdk/src/windows/classes/java/lang/Terminator.java +@OPENJDK@/jdk/src/windows/classes/java/net/DefaultInterface.java +@OPENJDK@/jdk/src/windows/classes/java/util/prefs/WindowsPreferences.java +@OPENJDK@/jdk/src/windows/classes/java/util/prefs/WindowsPreferencesFactory.java +@OPENJDK@/jdk/src/windows/classes/sun/awt/Win32ColorModel24.java +@OPENJDK@/jdk/src/windows/classes/sun/management/FileSystemImpl.java +@OPENJDK@/jdk/src/windows/classes/sun/management/OperatingSystemImpl.java +@OPENJDK@/jdk/src/windows/classes/sun/net/NetHooks.java +@OPENJDK@/jdk/src/windows/classes/sun/net/PortConfig.java +@OPENJDK@/jdk/src/windows/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java +@OPENJDK@/jdk/src/windows/classes/sun/nio/ch/NativeThread.java +@OPENJDK@/jdk/src/windows/classes/sun/nio/ch/PipeImpl.java +@OPENJDK@/jdk/src/windows/classes/sun/nio/ch/sctp/SctpChannelImpl.java +@OPENJDK@/jdk/src/windows/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java +@OPENJDK@/jdk/src/windows/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java +@OPENJDK@/jdk/src/windows/classes/sun/nio/ch/SinkChannelImpl.java +@OPENJDK@/jdk/src/windows/classes/sun/nio/ch/SourceChannelImpl.java +@OPENJDK@/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousChannelProvider.java +@OPENJDK@/jdk/src/windows/classes/sun/nio/fs/WindowsPathParser.java +@OPENJDK@/jdk/src/windows/classes/sun/nio/fs/WindowsPathType.java +@OPENJDK@/jdk/src/windows/classes/sun/print/Win32MediaTray.java +@OPENJDK@/jdk/src/windows/classes/sun/security/krb5/internal/tools/Kinit.java +@OPENJDK@/jdk/src/windows/classes/sun/security/krb5/internal/tools/KinitOptions.java +@OPENJDK@/jdk/src/windows/classes/sun/security/krb5/internal/tools/Klist.java +@OPENJDK@/jdk/src/windows/classes/sun/security/krb5/internal/tools/Ktab.java +@OPENJDK@/jdk/src/windows/classes/sun/security/provider/NativePRNG.java +@OPENJDK@/jdk/src/windows/classes/sun/security/provider/NativeSeedGenerator.java +@OPENJDK@/jdk/src/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/AnnotatedType.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/AnnotationDesc.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/AnnotationTypeDoc.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/AnnotationTypeElementDoc.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/AnnotationValue.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/ClassDoc.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/ConstructorDoc.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/Doc.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/DocErrorReporter.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/Doclet.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/ExecutableMemberDoc.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/FieldDoc.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/LanguageVersion.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/MemberDoc.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/MethodDoc.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/PackageDoc.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/Parameter.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/ParameterizedType.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/ParamTag.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/ProgramElementDoc.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/RootDoc.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/SeeTag.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/SerialFieldTag.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/SourcePosition.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/Tag.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/ThrowsTag.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/Type.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/TypeVariable.java +@OPENJDK@/langtools/src/share/classes/com/sun/javadoc/WildcardType.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/AttributeTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/AuthorTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/BlockTagTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/CommentTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/DeprecatedTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/DocCommentTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/DocRootTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/DocTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/DocTreeVisitor.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/EndElementTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/EntityTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/ErroneousTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/IdentifierTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/InheritDocTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/InlineTagTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/LinkTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/LiteralTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/ParamTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/ReferenceTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/ReturnTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/SeeTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/SerialDataTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/SerialFieldTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/SerialTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/SinceTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/StartElementTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/TextTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/ThrowsTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/UnknownBlockTagTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/UnknownInlineTagTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/ValueTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/VersionTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/AnnotatedTypeTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/AnnotationTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/ArrayAccessTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/ArrayTypeTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/AssertTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/AssignmentTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/BinaryTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/BlockTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/BreakTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/CaseTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/CatchTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/ClassTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/CompilationUnitTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/CompoundAssignmentTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/ConditionalExpressionTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/ContinueTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/DoWhileLoopTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/EmptyStatementTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/EnhancedForLoopTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/ErroneousTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/ExpressionStatementTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/ExpressionTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/ForLoopTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/IdentifierTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/IfTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/ImportTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/InstanceOfTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/IntersectionTypeTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/LabeledStatementTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/LambdaExpressionTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/LineMap.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/LiteralTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/MemberReferenceTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/MemberSelectTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/MethodInvocationTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/MethodTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/ModifiersTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/NewArrayTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/NewClassTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/package-info.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/ParameterizedTypeTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/ParenthesizedTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/PrimitiveTypeTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/ReturnTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/Scope.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/StatementTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/SwitchTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/SynchronizedTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/ThrowTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/Tree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/TreeVisitor.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/TryTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/TypeCastTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/TypeParameterTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/UnaryTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/UnionTypeTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/VariableTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/WhileLoopTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/tree/WildcardTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/util/DocSourcePositions.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/util/DocTreePath.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/util/DocTreePathScanner.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/util/DocTrees.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/util/DocTreeScanner.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/util/JavacTask.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/util/package-info.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/util/Plugin.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/util/SimpleDocTreeVisitor.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/util/SourcePositions.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/util/TaskEvent.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/util/TaskListener.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/util/TreePath.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/util/TreePathScanner.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/util/Trees.java +@OPENJDK@/langtools/src/share/classes/com/sun/source/util/TreeScanner.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/AccessFlags.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/Annotation.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/AnnotationDefault_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/Attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/AttributeException.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/Attributes.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/BootstrapMethods_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/CharacterRangeTable_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/ClassFile.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/ClassReader.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/ClassTranslator.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/ClassWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/Code_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/CompilationID_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/ConstantPool.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/ConstantPoolException.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/ConstantValue_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/DefaultAttribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/Dependencies.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/Dependency.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/Deprecated_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/Descriptor.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/DescriptorException.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/EnclosingMethod_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/Exceptions_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/Field.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/InnerClasses_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/Instruction.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/LineNumberTable_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/LocalVariableTable_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/LocalVariableTypeTable_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/Method.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/MethodParameters_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/Opcode.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/ReferenceFinder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/RuntimeAnnotations_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/RuntimeInvisibleAnnotations_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/RuntimeInvisibleParameterAnnotations_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/RuntimeInvisibleTypeAnnotations_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/RuntimeParameterAnnotations_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/RuntimeTypeAnnotations_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/RuntimeVisibleAnnotations_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/RuntimeVisibleParameterAnnotations_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/RuntimeVisibleTypeAnnotations_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/Signature.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/Signature_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/SourceDebugExtension_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/SourceFile_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/SourceID_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/StackMap_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/StackMapTable_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/Synthetic_attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/Type.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/TypeAnnotation.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractExecutableMemberWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractIndexWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractMemberWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractProfileIndexWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractTreeWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AllClassesFrameWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeFieldWriterImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeWriterImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConstantsSummaryWriterImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConstructorWriterImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/DeprecatedListWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/EnumConstantWriterImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/FieldWriterImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HelpWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialFieldWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialMethodWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/LinkFactoryImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/LinkInfoImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/LinkOutputImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/Comment.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/ContentBuilder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/DocType.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlAttr.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlConstants.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocument.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlStyle.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTag.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/RawHtml.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/StringContent.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/MethodWriterImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/NestedClassWriterImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageFrameWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageTreeWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageUseWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageWriterImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ProfileIndexFrameWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageFrameWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageIndexFrameWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageWriterImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ProfileWriterImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PropertyWriterImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SectionName.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SerializedFormWriterImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SingleIndexWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SplitIndexWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SubWriterHolderWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/TagletWriterImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/TreeWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/WriterFactoryImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeFieldWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeOptionalMemberWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeRequiredMemberWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractMemberBuilder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeBuilder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeFieldBuilder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeOptionalMemberBuilder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/BuilderFactory.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ClassBuilder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ConstantsSummaryBuilder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ConstructorBuilder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/EnumConstantBuilder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/FieldBuilder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/LayoutParser.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MemberSummaryBuilder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MethodBuilder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/PackageSummaryBuilder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ProfilePackageSummaryBuilder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ProfileSummaryBuilder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/PropertyBuilder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/SerializedFormBuilder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/XMLNode.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/ClassWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/ConstantsSummaryWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/ConstructorWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Content.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/EnumConstantWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/FieldWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/MemberSummaryWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/MethodWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/NestedClassWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/PackageSummaryWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/ProfilePackageSummaryWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/ProfileSummaryWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/PropertyWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/SerializedFormWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/BaseExecutableMemberTaglet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/BaseInlineTaglet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/BasePropertyTaglet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/BaseTaglet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/CodeTaglet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/DeprecatedTaglet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/DocRootTaglet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/InheritableTaglet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/InheritDocTaglet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/LegacyTaglet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/LiteralTaglet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ParamTaglet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/PropertyGetterTaglet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/PropertySetterTaglet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ReturnTaglet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/SeeTaglet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/SimpleTaglet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/Taglet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ThrowsTaglet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ValueTaglet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/ClassDocCatalog.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/ClassTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/ClassUseMapper.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/CommentedMethodFinder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DeprecatedAPIListBuilder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFile.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFinder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocletAbortException.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocletConstants.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocLink.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocPath.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocPaths.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Extern.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Group.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/ImplementedMethods.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/IndexBuilder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/links/LinkFactory.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/links/LinkInfo.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/links/LinkOutput.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/MetaKeywords.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/MethodFinder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/MethodTypes.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/PackageListWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/PathDocFileFactory.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SimpleDocFileFactory.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/StandardDocFileFactory.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/TaggedMethodFinder.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/TextTag.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/WriterFactory.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/standard/Standard.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/Taglet.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclint/Checker.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclint/DocLint.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclint/Entity.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclint/Env.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclint/HtmlTag.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/doclint/Messages.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/api/BasicJavacTask.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/api/DiagnosticFormatter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/api/Formattable.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/api/JavacScope.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/api/JavacTool.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/api/Messages.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/api/MultiTaskListener.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/api/WrappingJavaFileManager.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/code/AnnoConstruct.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/code/Attribute.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/code/BoundKind.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/code/DeferredLintHandler.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/code/Kinds.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/code/Scope.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/code/Source.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/code/SymbolMetadata.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/code/TargetType.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/code/Type.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/code/Types.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/code/TypeTag.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/AttrContext.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/AttrContextEnv.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/CompileStates.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/ConstFold.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/Env.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/Todo.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/TypeEnvs.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/file/BaseFileObject.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/file/CacheFSInfo.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/file/FSInfo.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/file/Locations.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/file/RegularFileObject.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/file/RelativePath.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/file/SymbolArchive.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/file/ZipArchive.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndexArchive.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndexCache.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/jvm/ByteCodes.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassFile.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/jvm/CRTable.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/jvm/CRTFlags.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/jvm/Items.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/jvm/LVTRanges.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/jvm/Pool.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/jvm/Profile.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/jvm/Target.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/jvm/UninitializedType.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/Main.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/main/CommandLine.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/main/Main.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/main/Option.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/main/OptionHelper.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/model/AnnotationProxyMaker.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/model/FilteredMemberList.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/model/JavacSourcePosition.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/nio/PathFileManager.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/nio/PathFileObject.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentParser.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/parser/LazyDocCommentTable.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/parser/Lexer.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/parser/Parser.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/parser/ParserFactory.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/parser/ScannerFactory.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/parser/Tokens.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/parser/UnicodeReader.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/processing/AnnotationProcessingError.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/processing/JavacFiler.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/processing/JavacMessager.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/processing/JavacRoundEnvironment.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/processing/ServiceProxy.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/sym/CreateSymbols.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/sym/Profiles.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/tree/DCTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/tree/DocCommentTable.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/tree/DocPretty.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/tree/EndPosTable.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/Abort.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/AbstractLog.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/ArrayUtils.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/Assert.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/Bits.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/ByteBuffer.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/ClientCodeException.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/Constants.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/Context.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/Convert.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/DiagnosticSource.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/FatalError.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/Filter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/ForwardingDiagnosticFormatter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/GraphUtils.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/IntHashTable.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/JavacMessages.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/LayoutCharacters.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/List.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/ListBuffer.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/Log.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/MandatoryWarningHandler.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/Name.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/Names.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/Options.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/Pair.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/Position.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/PropagatedException.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/ServiceLoader.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/SharedNameTable.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/StringUtils.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/UnsharedNameTable.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/Warner.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/AbstractTypeImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/AnnotatedTypeImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationDescImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationTypeDocImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationTypeElementDocImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationValueImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTaskImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/Comment.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/ConstructorDocImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/DocLocale.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/FieldDocImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/JavadocEnter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTodo.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/Main.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/MemberDocImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/Messager.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/MethodDocImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/ModifierFilter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/PackageDocImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/ParameterImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/ParameterizedTypeImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/ParamTagImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/PrimitiveType.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/ProgramElementDocImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/SeeTagImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/SerialFieldTagImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/SerializedForm.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/SourcePositionImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/Start.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/TagImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/ThrowsTagImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/ToolOption.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/TypeMaker.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/TypeVariableImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/WildcardTypeImpl.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javah/Gen.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javah/InternalError.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javah/JavahFileManager.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javah/JavahTask.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javah/JavahTool.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javah/JNI.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javah/LLNI.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javah/Main.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javah/Mangle.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javah/NativeHeaderTool.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javah/TypeSignature.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javah/Util.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/AnnotationWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/BasicWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/ClassWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/CodeWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/ConstantWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/Context.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/DisassemblerTool.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/InstructionDetailWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/InternalError.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/JavapFileManager.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/JavapTask.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/LocalVariableTableWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/LocalVariableTypeTableWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/Main.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/Messages.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/Options.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/SourceWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/StackMapWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/TryBlockWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/TypeAnnotationWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/jdeps/Analyzer.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/jdeps/Archive.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/jdeps/ClassFileReader.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/jdeps/JdepsTask.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/jdeps/Main.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/jdeps/PlatformClassPath.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/jdeps/Profile.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/BuildState.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/CleanProperties.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/comp/Dependencies.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/comp/JavaCompilerWithDeps.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/comp/PubapiVisitor.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/comp/ResolveWithDeps.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/comp/SmartFileObject.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/CompileChunk.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/CompileProperties.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/CopyFile.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/JavacState.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/Log.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/Main.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/Module.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/Package.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/ProblemException.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/server/CompilerPool.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/server/CompilerThread.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/server/JavacServer.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/server/PortFile.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/server/SysInfo.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/Source.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/Transformer.java +@OPENJDK@/langtools/src/share/classes/com/sun/tools/sjavac/Util.java +@OPENJDK@/langtools/src/share/classes/javax/annotation/processing/AbstractProcessor.java +@OPENJDK@/langtools/src/share/classes/javax/annotation/processing/Completion.java +@OPENJDK@/langtools/src/share/classes/javax/annotation/processing/Completions.java +@OPENJDK@/langtools/src/share/classes/javax/annotation/processing/Filer.java +@OPENJDK@/langtools/src/share/classes/javax/annotation/processing/FilerException.java +@OPENJDK@/langtools/src/share/classes/javax/annotation/processing/Messager.java +@OPENJDK@/langtools/src/share/classes/javax/annotation/processing/ProcessingEnvironment.java +@OPENJDK@/langtools/src/share/classes/javax/annotation/processing/Processor.java +@OPENJDK@/langtools/src/share/classes/javax/annotation/processing/RoundEnvironment.java +@OPENJDK@/langtools/src/share/classes/javax/annotation/processing/SupportedAnnotationTypes.java +@OPENJDK@/langtools/src/share/classes/javax/annotation/processing/SupportedOptions.java +@OPENJDK@/langtools/src/share/classes/javax/annotation/processing/SupportedSourceVersion.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/AnnotatedConstruct.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/element/AnnotationMirror.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/element/AnnotationValue.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/element/AnnotationValueVisitor.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/element/Element.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/element/ElementKind.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/element/ElementVisitor.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/element/ExecutableElement.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/element/Modifier.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/element/Name.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/element/NestingKind.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/element/PackageElement.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/element/Parameterizable.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/element/QualifiedNameable.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/element/TypeElement.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/element/TypeParameterElement.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/element/UnknownAnnotationValueException.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/element/UnknownElementException.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/element/VariableElement.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/SourceVersion.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/type/ArrayType.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/type/DeclaredType.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/type/ErrorType.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/type/ExecutableType.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/type/IntersectionType.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/type/MirroredTypeException.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/type/MirroredTypesException.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/type/NoType.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/type/NullType.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/type/PrimitiveType.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/type/ReferenceType.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/type/TypeKind.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/type/TypeMirror.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/type/TypeVariable.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/type/TypeVisitor.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/type/UnionType.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/type/UnknownTypeException.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/type/WildcardType.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/UnknownEntityException.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor6.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor7.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor8.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor6.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor7.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor8.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor6.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor7.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor8.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/ElementFilter.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor6.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor7.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor8.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/Elements.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/ElementScanner6.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/ElementScanner7.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/ElementScanner8.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor6.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor7.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor8.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor6.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor7.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor8.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor6.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor7.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor8.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor6.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor7.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor8.java +@OPENJDK@/langtools/src/share/classes/javax/lang/model/util/Types.java +@OPENJDK@/langtools/src/share/classes/javax/tools/Diagnostic.java +@OPENJDK@/langtools/src/share/classes/javax/tools/DiagnosticCollector.java +@OPENJDK@/langtools/src/share/classes/javax/tools/DiagnosticListener.java +@OPENJDK@/langtools/src/share/classes/javax/tools/DocumentationTool.java +@OPENJDK@/langtools/src/share/classes/javax/tools/FileObject.java +@OPENJDK@/langtools/src/share/classes/javax/tools/ForwardingFileObject.java +@OPENJDK@/langtools/src/share/classes/javax/tools/ForwardingJavaFileManager.java +@OPENJDK@/langtools/src/share/classes/javax/tools/ForwardingJavaFileObject.java +@OPENJDK@/langtools/src/share/classes/javax/tools/JavaCompiler.java +@OPENJDK@/langtools/src/share/classes/javax/tools/JavaFileManager.java +@OPENJDK@/langtools/src/share/classes/javax/tools/JavaFileObject.java +@OPENJDK@/langtools/src/share/classes/javax/tools/OptionChecker.java +@OPENJDK@/langtools/src/share/classes/javax/tools/SimpleJavaFileObject.java +@OPENJDK@/langtools/src/share/classes/javax/tools/StandardJavaFileManager.java +@OPENJDK@/langtools/src/share/classes/javax/tools/StandardLocation.java +@OPENJDK@/langtools/src/share/classes/javax/tools/Tool.java +@OPENJDK@/langtools/src/share/classes/javax/tools/ToolProvider.java +@OPENJDK@/langtools/src/share/classes/jdk/Exported.java +@OPENJDK@/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java +@OPENJDK@/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java +@OPENJDK@/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/Main.java +@OPENJDK@/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java +@OPENJDK@/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java +@OPENJDK@/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/NullVisitor.java +@OPENJDK@/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java +@OPENJDK@/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java +@OPENJDK@/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java +@OPENJDK@/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java +@OPENJDK@/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/CallSiteDescriptor.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/ChainedCallSite.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/DefaultBootstrapper.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/DynamicLinker.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/DynamicLinkerFactory.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/GuardedInvocationFilter.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/MonomorphicCallSite.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/NoSuchDynamicMethodException.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/RelinkableCallSite.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/BeanIntrospector.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/BeanLinker.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/BeansLinker.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/CallerSensitiveDetector.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/CheckRestrictedPackage.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/ClassLinker.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/ClassString.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/DynamicMethod.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/DynamicMethodLinker.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/FacetIntrospector.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/GuardedInvocationComponent.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/MaximallySpecific.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/OverloadedMethod.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/StaticClass.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/StaticClassIntrospector.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/StaticClassLinker.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/linker/ConversionComparator.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/linker/GuardedInvocation.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/linker/GuardingDynamicLinker.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/linker/GuardingTypeConverterFactory.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/linker/LinkerServices.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/linker/LinkRequest.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/linker/MethodTypeConversionStrategy.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/linker/TypeBasedGuardingDynamicLinker.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/AutoDiscovery.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/BottomGuardingDynamicLinker.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/ClassLoaderGetterContextProvider.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/ClassMap.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/CompositeGuardingDynamicLinker.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/DefaultCallSiteDescriptor.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/DefaultPrelinkFilter.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/Guards.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/LinkerServicesImpl.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/LinkRequestImpl.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/Lookup.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/LookupCallSiteDescriptor.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/NameCodec.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/NamedDynCallSiteDescriptor.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/RuntimeContextLinkRequestImpl.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/TypeConverterFactory.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/TypeUtilities.java +@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/UnnamedDynCallSiteDescriptor.java +@OPENJDK@/nashorn/src/jdk/nashorn/api/scripting/AbstractJSObject.java +@OPENJDK@/nashorn/src/jdk/nashorn/api/scripting/ClassFilter.java +@OPENJDK@/nashorn/src/jdk/nashorn/api/scripting/Formatter.java +@OPENJDK@/nashorn/src/jdk/nashorn/api/scripting/JSObject.java +@OPENJDK@/nashorn/src/jdk/nashorn/api/scripting/NashornException.java +@OPENJDK@/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java +@OPENJDK@/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java +@OPENJDK@/nashorn/src/jdk/nashorn/api/scripting/package-info.java +@OPENJDK@/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java +@OPENJDK@/nashorn/src/jdk/nashorn/api/scripting/ScriptUtils.java +@OPENJDK@/nashorn/src/jdk/nashorn/api/scripting/URLReader.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/AssertsEnabled.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/IntDeque.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/ApplySpecialization.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/AssignSymbols.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/AstSerializer.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/BranchOptimizer.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/ClassEmitter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/CompilationException.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/CompilerConstants.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/CompileUnit.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/Condition.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/ConstantData.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/DumpBytecode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/Emitter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/FindScopeDepths.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/FunctionSignature.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/Label.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/LocalStateRestorationInfo.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/Lower.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/MapCreator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/MapTuple.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/Namespace.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/ObjectCreator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/ProgramPoints.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/ReplaceCompileUnits.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/RuntimeCallSite.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/SharedScopeCall.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/SplitIntoFunctions.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/Splitter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/TypeEvaluator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/TypeMap.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/WeighNodes.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/ArrayType.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/BitwiseType.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/BooleanType.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/BytecodeArrayOps.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/BytecodeBitwiseOps.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/BytecodeNumericOps.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/BytecodeOps.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/IntType.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/LongType.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/NumberType.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/NumericType.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/ObjectType.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/Type.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/AccessNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/Assignment.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/BaseNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/BinaryNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/Block.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/BlockLexicalContext.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/BlockStatement.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/BreakableNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/BreakableStatement.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/BreakNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/CallNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/CaseNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/CatchNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/CompileUnitHolder.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/ContinueNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/EmptyNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/Expression.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/ExpressionStatement.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/Flags.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/ForNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/FunctionCall.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/GetSplitState.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/IdentNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/IfNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/IndexNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/JoinPredecessor.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/JoinPredecessorExpression.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/JumpStatement.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/LabelNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/Labels.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/LexicalContext.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/LexicalContextExpression.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/LexicalContextNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/LexicalContextStatement.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/LiteralNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/LocalVariableConversion.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/LoopNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/Node.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/ObjectNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/Optimistic.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/OptimisticLexicalContext.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/PropertyKey.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/PropertyNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/ReturnNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/RuntimeNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/SetSplitState.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/SplitNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/SplitReturn.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/Statement.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/SwitchNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/Symbol.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/Terminal.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/TernaryNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/ThrowNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/TryNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/UnaryNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/VarNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/WhileNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/WithNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/annotations/Ignore.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/annotations/Immutable.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/annotations/Reference.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/debug/ASTWriter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/debug/ClassHistogramElement.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/debug/NashornClassReader.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/debug/NashornTextifier.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/lookup/Lookup.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/BoundScriptFunctionImpl.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/Global.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeArguments.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeBoolean.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeDataView.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeDebug.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeError.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeEvalError.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeJavaImporter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeJSON.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeMath.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeNumber.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeRangeError.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeReferenceError.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeStrictArguments.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeString.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeSyntaxError.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeTypeError.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeURIError.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/package-info.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/PrototypeObject.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/annotations/Attribute.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/annotations/Constructor.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/annotations/Function.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/annotations/Getter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/annotations/Optimistic.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/annotations/Property.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/annotations/ScriptClass.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/annotations/Setter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/annotations/Where.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/parser/AbstractParser.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/parser/DateParser.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/parser/JSONParser.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/parser/Lexer.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/parser/Parser.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/parser/Scanner.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/parser/Token.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/parser/TokenKind.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/parser/TokenLookup.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/parser/TokenStream.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/parser/TokenType.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/AllocationStrategy.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ArgumentSetter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/AstDeserializer.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/BitVector.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/CodeInstaller.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/CodeStore.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/CompiledFunction.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ConsString.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/Context.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/Debug.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/DebuggerSupport.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/DefaultPropertyAccess.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ECMAErrors.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ECMAException.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ErrorManager.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/FindProperty.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/FunctionInitializer.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/FunctionScope.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/GlobalConstants.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/GlobalFunctions.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/JSErrorType.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/JSObjectListAdapter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/JSType.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ListAdapter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/NashornLoader.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/NumberToString.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/OptimisticBuiltins.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ParserException.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/Property.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/PropertyAccess.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/PropertyHashMap.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/PropertyListeners.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/QuotedStringTokenizer.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/RewriteException.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/Scope.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ScriptLoader.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/Source.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/Specialization.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/SpillProperty.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/StoredScript.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/StructureLoader.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/Timing.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/Undefined.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/UnwarrantedOptimismException.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/URIUtils.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/Version.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/AnyElements.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/EmptyArrayLikeIterator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/IntElements.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/IntOrLongElements.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/InvalidArrayIndexException.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/JavaArrayIterator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/JavaListIterator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/JSObjectIterator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/LengthNotWritableFilter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/NonExtensibleArrayFilter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/NumericElements.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ReverseJavaArrayIterator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ReverseJavaListIterator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ReverseJSObjectIterator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ReverseScriptArrayIterator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ReverseScriptObjectIterator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ScriptArrayIterator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ScriptObjectIterator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/events/RecompilationEvent.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/events/RuntimeEvent.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/AdaptationException.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/AdaptationResult.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/BoundCallable.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/BoundCallableLinker.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/ClassAndLoader.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/InvokeByName.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/logging/DebugLogger.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/logging/Loggable.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/logging/Logger.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/options/KeyValueOption.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/options/LoggingOption.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/options/Option.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/options/Options.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/options/OptionTemplate.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExp.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpMatcher.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpResult.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFold.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFoldArg.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/BitStatus.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodePrinter.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/CodeRangeBuffer.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Compiler.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Config.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Lexer.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Matcher.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/MinMaxLen.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/NodeOptInfo.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/OptAnchorInfo.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/OptEnvironment.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/OptExactInfo.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Option.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/OptMapInfo.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Parser.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Region.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ScanEnvironment.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ScannerSupport.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/SearchAlgorithm.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/StackEntry.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Token.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/WarnCallback.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Warnings.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnchorNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnyCharNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/BackRefNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/CClassNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/ConsAltNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/Node.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StateNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StringNode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/AnchorType.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/Arguments.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/AsmConstants.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/CCSTATE.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/CCVALTYPE.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/EncloseType.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/MetaChar.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/NodeStatus.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/NodeType.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/OPCode.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/OPSize.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/RegexState.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/StackPopLevel.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/StackType.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/StringType.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/SyntaxProperties.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/TargetInfo.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/TokenType.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/Traverse.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/CharacterType.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/IntHolder.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/ObjPtr.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ErrorMessages.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/InternalException.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/SyntaxException.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ValueException.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/scripts/JO.java +@OPENJDK@/nashorn/src/jdk/nashorn/internal/scripts/JS.java +@OPENJDK@/nashorn/src/jdk/nashorn/tools/Shell.java +icedtea/jce/gnu/java/security/action/GetPropertyAction.java +icedtea/jce/gnu/java/security/action/GetSecurityPropertyAction.java +icedtea/jce/gnu/java/security/action/SetAccessibleAction.java +icedtea/rt/com/sun/media/sound/AbstractPlayer.java +icedtea/rt/com/sun/media/sound/AutoConnectSequencer.java +icedtea/rt/com/sun/media/sound/DataPusher.java +icedtea/rt/com/sun/media/sound/DirectAudioDevice.java +icedtea/rt/com/sun/media/sound/DirectAudioDeviceProvider.java +icedtea/rt/com/sun/media/sound/HeadspaceMixer.java +icedtea/rt/com/sun/media/sound/HeadspaceSoundbank.java +icedtea/rt/com/sun/media/sound/JavaSoundAudioClip.java +icedtea/rt/com/sun/media/sound/JDK13Services.java +icedtea/rt/com/sun/media/sound/MidiInDevice.java +icedtea/rt/com/sun/media/sound/MidiInDeviceProvider.java +icedtea/rt/com/sun/media/sound/MidiOutDevice.java +icedtea/rt/com/sun/media/sound/MidiOutDeviceProvider.java +icedtea/rt/com/sun/media/sound/MidiUtils.java +icedtea/rt/com/sun/media/sound/MixerClip.java +icedtea/rt/com/sun/media/sound/MixerMidiChannel.java +icedtea/rt/com/sun/media/sound/MixerSequencer.java +icedtea/rt/com/sun/media/sound/MixerSourceLine.java +icedtea/rt/com/sun/media/sound/MixerSynth.java +icedtea/rt/com/sun/media/sound/MixerThread.java +icedtea/rt/com/sun/media/sound/Platform.java +icedtea/rt/com/sun/media/sound/PortMixer.java +icedtea/rt/com/sun/media/sound/PortMixerProvider.java +icedtea/rt/com/sun/media/sound/ReferenceCountingDevice.java +icedtea/rt/com/sun/media/sound/SimpleInputDevice.java +icedtea/rt/com/sun/media/sound/SimpleInputDeviceProvider.java +icedtea/rt/com/sun/media/sound/Toolkit.java diff --git a/openjdk/com/sun/imageio/plugins/jpeg/JPEGImageReader.java b/openjdk/com/sun/imageio/plugins/jpeg/JPEGImageReader.java new file mode 100644 index 0000000..ee13161 --- /dev/null +++ b/openjdk/com/sun/imageio/plugins/jpeg/JPEGImageReader.java @@ -0,0 +1,145 @@ +/* + Copyright (C) 2008 - 2013 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package com.sun.imageio.plugins.jpeg; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.*; +import java.util.Iterator; + +import javax.imageio.*; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.spi.ImageReaderSpi; +import javax.imageio.stream.ImageInputStream; + +/** + * A image reader implementation that is calling the .NET API for reading the JPEG image. + */ +class JPEGImageReader extends ImageReader{ + + private BufferedImage image; + + /** + * Default constructor, Sun compatible. + */ + protected JPEGImageReader(ImageReaderSpi originatingProvider){ + super(originatingProvider); + } + + /** + * {@inheritDoc} + */ + @Override + public int getHeight(int imageIndex) throws IOException{ + return getBufferedImage().getHeight(); + } + + /** + * {@inheritDoc} + */ + @Override + public IIOMetadata getImageMetadata(int imageIndex){ + throw new Error("Not Implemented"); + } + + /** + * {@inheritDoc} + */ + @Override + public Iterator getImageTypes(int imageIndex){ + throw new Error("Not Implemented"); + } + + /** + * {@inheritDoc} + */ + @Override + public int getNumImages(boolean allowSearch){ + return 1; + } + + /** + * {@inheritDoc} + */ + @Override + public IIOMetadata getStreamMetadata(){ + throw new Error("Not Implemented"); + } + + /** + * {@inheritDoc} + */ + @Override + public int getWidth(int imageIndex) throws IOException{ + return getBufferedImage().getWidth(); + } + + /** + * {@inheritDoc} + */ + @Override + public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException{ + return getBufferedImage(); + } + + /** + * Read the image with .NET API if not already read. + */ + private BufferedImage getBufferedImage() throws IOException{ + if(image == null){ + ImageInputStream iis = (ImageInputStream)getInput(); + byte[] buffer; + try { + if( iis.length() >0){ + //If length known then it it is simple + buffer = new byte[(int)iis.length()]; + iis.readFully(buffer); + }else{ + // if the length not known then we need to read it in a loop + ByteArrayOutputStream baos = new ByteArrayOutputStream(8192); + buffer = new byte[8192]; + int count; + while((count = iis.read(buffer)) > 0){ + baos.write(buffer, 0, count); + } + buffer = baos.toByteArray(); + } + } catch (IOException ioex) { + processReadAborted(); + throw ioex; + } + processImageStarted(0); + image = (BufferedImage)Toolkit.getDefaultToolkit().createImage(buffer); + int width = image.getWidth(); + int height = image.getHeight(); + processPassStarted(image, 0, 0, 1, 0, 0, 1, 1, new int[0]); + processImageProgress(100.0F); + processImageUpdate(image, 0, 0, width, height, 1, 1, new int[0]); + processPassComplete(image); + processImageComplete(); + } + return image; + } + +} \ No newline at end of file diff --git a/openjdk/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java b/openjdk/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java new file mode 100644 index 0000000..0c7516f --- /dev/null +++ b/openjdk/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java @@ -0,0 +1,180 @@ +/* + Copyright (C) 2008, 2009 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package com.sun.imageio.plugins.jpeg; + +import javax.imageio.ImageWriter; +import javax.imageio.ImageWriteParam; +import javax.imageio.IIOException; +import javax.imageio.IIOImage; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.plugins.jpeg.JPEGImageWriteParam; +import javax.imageio.plugins.jpeg.JPEGQTable; +import javax.imageio.spi.ImageWriterSpi; +import javax.imageio.stream.ImageOutputStream; +import java.awt.image.BufferedImage; + +import java.io.IOException; + +import cli.System.Drawing.Imaging.Encoder; +import cli.System.Drawing.Imaging.EncoderParameter; +import cli.System.Drawing.Imaging.EncoderParameters; +import cli.System.Drawing.Imaging.ImageCodecFlags; +import cli.System.Drawing.Imaging.ImageCodecInfo; +import cli.System.Drawing.Imaging.ImageFormat; + +/** + * JPEGImageWriter that use .NET features to write the the JPG file. + */ +public class JPEGImageWriter extends ImageWriter { + + /** + * Default constructor, Sun compatible. + */ + protected JPEGImageWriter(ImageWriterSpi originatingProvider){ + super(originatingProvider); + } + + /** + * {@inheritDoc} + */ + @Override + public IIOMetadata convertImageMetadata(IIOMetadata inData, ImageTypeSpecifier imageType, ImageWriteParam param){ + return inData; + } + + /** + * {@inheritDoc} + */ + @Override + public IIOMetadata convertStreamMetadata(IIOMetadata inData, ImageWriteParam param){ + return inData; + } + + /** + * {@inheritDoc} + */ + @Override + public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType, ImageWriteParam param){ + return null; + } + + /** + * {@inheritDoc} + */ + @Override + public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param){ + return null; + } + + /** + * {@inheritDoc} + */ + @Override + public void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws IOException{ + + ImageCodecInfo codec = null; + for (ImageCodecInfo ici : ImageCodecInfo.GetImageEncoders()) { + if (ici.get_FormatID().equals(ImageFormat.get_Jpeg().get_Guid()) + && (ici.get_Flags().Value & ImageCodecFlags.Builtin) != 0) { + codec = ici; + break; + } + } + if (codec == null) { + throw new IIOException("JPEG codec not found"); + } + + BufferedImage img = (BufferedImage)image.getRenderedImage(); + + ImageOutputStream imgOutput = (ImageOutputStream)getOutput(); + + JPEGImageWriteParam jparam = null; + JPEGQTable[] qTables = null; + + if (param != null) { + switch (param.getCompressionMode()) { + case ImageWriteParam.MODE_DISABLED: + throw new IIOException("JPEG compression cannot be disabled"); + case ImageWriteParam.MODE_EXPLICIT: + float quality = param.getCompressionQuality(); + quality = JPEG.convertToLinearQuality(quality); + qTables = new JPEGQTable[2]; + qTables[0] = JPEGQTable.K1Luminance.getScaledInstance(quality, true); + qTables[1] = JPEGQTable.K2Chrominance.getScaledInstance(quality, true); + break; + case ImageWriteParam.MODE_DEFAULT: + qTables = new JPEGQTable[2]; + qTables[0] = JPEGQTable.K1Div2Luminance; + qTables[1] = JPEGQTable.K2Div2Chrominance; + break; + } + if (param instanceof JPEGImageWriteParam) { + jparam = (JPEGImageWriteParam)param; + } + } + + if (qTables == null) { + if (jparam != null && jparam.areTablesSet()) { + qTables = jparam.getQTables(); + } else { + qTables = JPEG.getDefaultQTables(); + } + } + + // Create a MemoryStream with publicly visible buffer + cli.System.IO.MemoryStream stream = new cli.System.IO.MemoryStream(1024); + EncoderParameters params = new EncoderParameters(2); + try { + params.get_Param()[0] = new EncoderParameter(Encoder.LuminanceTable, qTableToShortArray(qTables[0])); + params.get_Param()[1] = new EncoderParameter(Encoder.ChrominanceTable, qTableToShortArray(qTables[1])); + cli.System.Drawing.Bitmap bitmap = img.getBitmap(); + synchronized( bitmap ) { + bitmap.Save(stream, codec, params); + } + } + finally { + params.Dispose(); + } + + imgOutput.write(stream.GetBuffer(), 0, (int)stream.get_Length()); + } + + private static short[] qTableToShortArray(JPEGQTable table) { + int[] array = table.getTable(); + short[] s = new short[64]; + for (int i = 0; i < 64; i++) + s[i] = (short)array[i]; + return s; + } + + /** + * {@inheritDoc} + */ + @Override + public ImageWriteParam getDefaultWriteParam() { + return new JPEGImageWriteParam(null); + } +} diff --git a/openjdk/com/sun/java/util/jar/pack/PackageReader.java b/openjdk/com/sun/java/util/jar/pack/PackageReader.java new file mode 100644 index 0000000..27cdcd1 --- /dev/null +++ b/openjdk/com/sun/java/util/jar/pack/PackageReader.java @@ -0,0 +1,2383 @@ +/* + * Copyright (c) 2001, 2013, 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 com.sun.java.util.jar.pack; + +import com.sun.java.util.jar.pack.ConstantPool.*; +import com.sun.java.util.jar.pack.Package.Class; +import com.sun.java.util.jar.pack.Package.File; +import com.sun.java.util.jar.pack.Package.InnerClass; +import java.io.ByteArrayOutputStream; +import java.io.EOFException; +import java.io.PrintStream; +import java.io.FilterInputStream; +import java.io.BufferedInputStream; +import java.io.InputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Map; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Set; +import static com.sun.java.util.jar.pack.Constants.*; + +/** + * Reader for a package file. + * + * @see PackageWriter + * @author John Rose + */ +class PackageReader extends BandStructure { + Package pkg; + byte[] bytes; + LimitedBuffer in; + Package.Version packageVersion; + + PackageReader(Package pkg, InputStream in) throws IOException { + this.pkg = pkg; + this.in = new LimitedBuffer(in); + } + + /** A buffered input stream which is careful not to + * read its underlying stream ahead of a given mark, + * called the 'readLimit'. This property declares + * the maximum number of characters that future reads + * can consume from the underlying stream. + */ + static + class LimitedBuffer extends BufferedInputStream { + long served; // total number of charburgers served + int servedPos; // ...as of this value of super.pos + long limit; // current declared limit + long buffered; + public boolean atLimit() { + boolean z = (getBytesServed() == limit); + assert(!z || limit == buffered); + return z; + } + public long getBytesServed() { + return served + (pos - servedPos); + } + public void setReadLimit(long newLimit) { + if (newLimit == -1) + limit = -1; + else + limit = getBytesServed() + newLimit; + } + public long getReadLimit() { + if (limit == -1) + return limit; + else + return limit - getBytesServed(); + } + public int read() throws IOException { + if (pos < count) { + // fast path + return buf[pos++] & 0xFF; + } + served += (pos - servedPos); + int ch = super.read(); + servedPos = pos; + if (ch >= 0) served += 1; + assert(served <= limit || limit == -1); + return ch; + } + public int read(byte b[], int off, int len) throws IOException { + served += (pos - servedPos); + int nr = super.read(b, off, len); + servedPos = pos; + if (nr >= 0) served += nr; + //assert(served <= limit || limit == -1); + return nr; + } + public long skip(long n) throws IOException { + throw new RuntimeException("no skipping"); + } + LimitedBuffer(InputStream originalIn) { + super(null, 1<<14); + servedPos = pos; + super.in = new FilterInputStream(originalIn) { + public int read() throws IOException { + if (buffered == limit) + return -1; + ++buffered; + return super.read(); + } + public int read(byte b[], int off, int len) throws IOException { + if (buffered == limit) + return -1; + if (limit != -1) { + long remaining = limit - buffered; + if (len > remaining) + len = (int)remaining; + } + int nr = super.read(b, off, len); + if (nr >= 0) buffered += nr; + return nr; + } + }; + } + } + + void read() throws IOException { + boolean ok = false; + try { + // pack200_archive: + // file_header + // *band_headers :BYTE1 + // cp_bands + // attr_definition_bands + // ic_bands + // class_bands + // bc_bands + // file_bands + readFileHeader(); + readBandHeaders(); + readConstantPool(); // cp_bands + readAttrDefs(); + readInnerClasses(); + Class[] classes = readClasses(); + readByteCodes(); + readFiles(); // file_bands + assert(archiveSize1 == 0 || in.atLimit()); + assert(archiveSize1 == 0 || + in.getBytesServed() == archiveSize0+archiveSize1); + all_bands.doneDisbursing(); + + // As a post-pass, build constant pools and inner classes. + for (int i = 0; i < classes.length; i++) { + reconstructClass(classes[i]); + } + + ok = true; + } catch (Exception ee) { + Utils.log.warning("Error on input: "+ee, ee); + if (verbose > 0) + Utils.log.info("Stream offsets:"+ + " served="+in.getBytesServed()+ + " buffered="+in.buffered+ + " limit="+in.limit); + //if (verbose > 0) ee.printStackTrace(); + if (ee instanceof IOException) throw (IOException)ee; + if (ee instanceof RuntimeException) throw (RuntimeException)ee; + throw new Error("error unpacking", ee); + } + } + + // Temporary count values, until band decoding gets rolling. + int[] tagCount = new int[CONSTANT_Limit]; + int numFiles; + int numAttrDefs; + int numInnerClasses; + int numClasses; + + void readFileHeader() throws IOException { + // file_header: + // archive_magic archive_header + readArchiveMagic(); + readArchiveHeader(); + } + + // Local routine used to parse fixed-format scalars + // in the file_header: + private int getMagicInt32() throws IOException { + int res = 0; + for (int i = 0; i < 4; i++) { + res <<= 8; + res |= (archive_magic.getByte() & 0xFF); + } + return res; + } + + final static int MAGIC_BYTES = 4; + + void readArchiveMagic() throws IOException { + // Read a minimum of bytes in the first gulp. + in.setReadLimit(MAGIC_BYTES + AH_LENGTH_MIN); + + // archive_magic: + // #archive_magic_word :BYTE1[4] + archive_magic.expectLength(MAGIC_BYTES); + archive_magic.readFrom(in); + + // read and check magic numbers: + int magic = getMagicInt32(); + if (pkg.magic != magic) { + throw new IOException("Unexpected package magic number: got " + + magic + "; expected " + pkg.magic); + } + archive_magic.doneDisbursing(); + } + + // Fixed 6211177, converted to throw IOException + void checkArchiveVersion() throws IOException { + Package.Version versionFound = null; + for (Package.Version v : new Package.Version[] { + JAVA8_PACKAGE_VERSION, + JAVA7_PACKAGE_VERSION, + JAVA6_PACKAGE_VERSION, + JAVA5_PACKAGE_VERSION + }) { + if (packageVersion.equals(v)) { + versionFound = v; + break; + } + } + if (versionFound == null) { + String expVer = JAVA8_PACKAGE_VERSION.toString() + + "OR" + + JAVA7_PACKAGE_VERSION.toString() + + " OR " + + JAVA6_PACKAGE_VERSION.toString() + + " OR " + + JAVA5_PACKAGE_VERSION.toString(); + throw new IOException("Unexpected package minor version: got " + + packageVersion.toString() + "; expected " + expVer); + } + } + + void readArchiveHeader() throws IOException { + // archive_header: + // #archive_minver :UNSIGNED5[1] + // #archive_majver :UNSIGNED5[1] + // #archive_options :UNSIGNED5[1] + // (archive_file_counts) ** (#have_file_headers) + // (archive_special_counts) ** (#have_special_formats) + // cp_counts + // class_counts + // + // archive_file_counts: + // #archive_size_hi :UNSIGNED5[1] + // #archive_size_lo :UNSIGNED5[1] + // #archive_next_count :UNSIGNED5[1] + // #archive_modtime :UNSIGNED5[1] + // #file_count :UNSIGNED5[1] + // + // class_counts: + // #ic_count :UNSIGNED5[1] + // #default_class_minver :UNSIGNED5[1] + // #default_class_majver :UNSIGNED5[1] + // #class_count :UNSIGNED5[1] + // + // archive_special_counts: + // #band_headers_size :UNSIGNED5[1] + // #attr_definition_count :UNSIGNED5[1] + // + archive_header_0.expectLength(AH_LENGTH_0); + archive_header_0.readFrom(in); + + int minver = archive_header_0.getInt(); + int majver = archive_header_0.getInt(); + packageVersion = Package.Version.of(majver, minver); + checkArchiveVersion(); + this.initHighestClassVersion(JAVA7_MAX_CLASS_VERSION); + + archiveOptions = archive_header_0.getInt(); + archive_header_0.doneDisbursing(); + + // detect archive optional fields in archive header + boolean haveSpecial = testBit(archiveOptions, AO_HAVE_SPECIAL_FORMATS); + boolean haveFiles = testBit(archiveOptions, AO_HAVE_FILE_HEADERS); + boolean haveNumbers = testBit(archiveOptions, AO_HAVE_CP_NUMBERS); + boolean haveCPExtra = testBit(archiveOptions, AO_HAVE_CP_EXTRAS); + initAttrIndexLimit(); + + // now we are ready to use the data: + archive_header_S.expectLength(haveFiles? AH_LENGTH_S: 0); + archive_header_S.readFrom(in); + if (haveFiles) { + long sizeHi = archive_header_S.getInt(); + long sizeLo = archive_header_S.getInt(); + archiveSize1 = (sizeHi << 32) + ((sizeLo << 32) >>> 32); + // Set the limit, now, up to the file_bits. + in.setReadLimit(archiveSize1); // for debug only + } else { + archiveSize1 = 0; + in.setReadLimit(-1); // remove limitation + } + archive_header_S.doneDisbursing(); + archiveSize0 = in.getBytesServed(); + + int remainingHeaders = AH_LENGTH_MIN - AH_LENGTH_0 - AH_LENGTH_S; + if (haveFiles) remainingHeaders += AH_FILE_HEADER_LEN; + if (haveSpecial) remainingHeaders += AH_SPECIAL_FORMAT_LEN; + if (haveNumbers) remainingHeaders += AH_CP_NUMBER_LEN; + if (haveCPExtra) remainingHeaders += AH_CP_EXTRA_LEN; + archive_header_1.expectLength(remainingHeaders); + archive_header_1.readFrom(in); + + if (haveFiles) { + archiveNextCount = archive_header_1.getInt(); + pkg.default_modtime = archive_header_1.getInt(); + numFiles = archive_header_1.getInt(); + } else { + archiveNextCount = 0; + numFiles = 0; + } + + if (haveSpecial) { + band_headers.expectLength(archive_header_1.getInt()); + numAttrDefs = archive_header_1.getInt(); + } else { + band_headers.expectLength(0); + numAttrDefs = 0; + } + + readConstantPoolCounts(haveNumbers, haveCPExtra); + + numInnerClasses = archive_header_1.getInt(); + + minver = (short) archive_header_1.getInt(); + majver = (short) archive_header_1.getInt(); + pkg.defaultClassVersion = Package.Version.of(majver, minver); + numClasses = archive_header_1.getInt(); + + archive_header_1.doneDisbursing(); + + // set some derived archive bits + if (testBit(archiveOptions, AO_DEFLATE_HINT)) { + pkg.default_options |= FO_DEFLATE_HINT; + } + } + + void readBandHeaders() throws IOException { + band_headers.readFrom(in); + bandHeaderBytePos = 1; // Leave room to pushback the initial XB byte. + bandHeaderBytes = new byte[bandHeaderBytePos + band_headers.length()]; + for (int i = bandHeaderBytePos; i < bandHeaderBytes.length; i++) { + bandHeaderBytes[i] = (byte) band_headers.getByte(); + } + band_headers.doneDisbursing(); + } + + void readConstantPoolCounts(boolean haveNumbers, boolean haveCPExtra) throws IOException { + // size the constant pools: + for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) { + // cp_counts: + // #cp_Utf8_count :UNSIGNED5[1] + // (cp_number_counts) ** (#have_cp_numbers) + // #cp_String_count :UNSIGNED5[1] + // #cp_Class_count :UNSIGNED5[1] + // #cp_Signature_count :UNSIGNED5[1] + // #cp_Descr_count :UNSIGNED5[1] + // #cp_Field_count :UNSIGNED5[1] + // #cp_Method_count :UNSIGNED5[1] + // #cp_Imethod_count :UNSIGNED5[1] + // (cp_attr_counts) ** (#have_cp_attr_counts) + // + // cp_number_counts: + // #cp_Int_count :UNSIGNED5[1] + // #cp_Float_count :UNSIGNED5[1] + // #cp_Long_count :UNSIGNED5[1] + // #cp_Double_count :UNSIGNED5[1] + // + // cp_extra_counts: + // #cp_MethodHandle_count :UNSIGNED5[1] + // #cp_MethodType_count :UNSIGNED5[1] + // #cp_InvokeDynamic_count :UNSIGNED5[1] + // #cp_BootstrapMethod_count :UNSIGNED5[1] + // + byte tag = ConstantPool.TAGS_IN_ORDER[k]; + if (!haveNumbers) { + // These four counts are optional. + switch (tag) { + case CONSTANT_Integer: + case CONSTANT_Float: + case CONSTANT_Long: + case CONSTANT_Double: + continue; + } + } + if (!haveCPExtra) { + // These four counts are optional. + switch (tag) { + case CONSTANT_MethodHandle: + case CONSTANT_MethodType: + case CONSTANT_InvokeDynamic: + case CONSTANT_BootstrapMethod: + continue; + } + } + tagCount[tag] = archive_header_1.getInt(); + } + } + + protected Index getCPIndex(byte tag) { + return pkg.cp.getIndexByTag(tag); + } + Index initCPIndex(byte tag, Entry[] cpMap) { + if (verbose > 3) { + for (int i = 0; i < cpMap.length; i++) { + Utils.log.fine("cp.add "+cpMap[i]); + } + } + Index index = ConstantPool.makeIndex(ConstantPool.tagName(tag), cpMap); + if (verbose > 1) Utils.log.fine("Read "+index); + pkg.cp.initIndexByTag(tag, index); + return index; + } + + void checkLegacy(String bandname) { + if (packageVersion.lessThan(JAVA7_PACKAGE_VERSION)) { + throw new RuntimeException("unexpected band " + bandname); + } + } + void readConstantPool() throws IOException { + // cp_bands: + // cp_Utf8 + // *cp_Int :UDELTA5 + // *cp_Float :UDELTA5 + // cp_Long + // cp_Double + // *cp_String :UDELTA5 (cp_Utf8) + // *cp_Class :UDELTA5 (cp_Utf8) + // cp_Signature + // cp_Descr + // cp_Field + // cp_Method + // cp_Imethod + + if (verbose > 0) Utils.log.info("Reading CP"); + + for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) { + byte tag = ConstantPool.TAGS_IN_ORDER[k]; + int len = tagCount[tag]; + + Entry[] cpMap = new Entry[len]; + if (verbose > 0) + Utils.log.info("Reading "+cpMap.length+" "+ConstantPool.tagName(tag)+" entries..."); + + switch (tag) { + case CONSTANT_Utf8: + readUtf8Bands(cpMap); + break; + case CONSTANT_Integer: + cp_Int.expectLength(cpMap.length); + cp_Int.readFrom(in); + for (int i = 0; i < cpMap.length; i++) { + int x = cp_Int.getInt(); // coding handles signs OK + cpMap[i] = ConstantPool.getLiteralEntry(x); + } + cp_Int.doneDisbursing(); + break; + case CONSTANT_Float: + cp_Float.expectLength(cpMap.length); + cp_Float.readFrom(in); + for (int i = 0; i < cpMap.length; i++) { + int x = cp_Float.getInt(); + float fx = Float.intBitsToFloat(x); + cpMap[i] = ConstantPool.getLiteralEntry(fx); + } + cp_Float.doneDisbursing(); + break; + case CONSTANT_Long: + // cp_Long: + // *cp_Long_hi :UDELTA5 + // *cp_Long_lo :DELTA5 + cp_Long_hi.expectLength(cpMap.length); + cp_Long_hi.readFrom(in); + cp_Long_lo.expectLength(cpMap.length); + cp_Long_lo.readFrom(in); + for (int i = 0; i < cpMap.length; i++) { + long hi = cp_Long_hi.getInt(); + long lo = cp_Long_lo.getInt(); + long x = (hi << 32) + ((lo << 32) >>> 32); + cpMap[i] = ConstantPool.getLiteralEntry(x); + } + cp_Long_hi.doneDisbursing(); + cp_Long_lo.doneDisbursing(); + break; + case CONSTANT_Double: + // cp_Double: + // *cp_Double_hi :UDELTA5 + // *cp_Double_lo :DELTA5 + cp_Double_hi.expectLength(cpMap.length); + cp_Double_hi.readFrom(in); + cp_Double_lo.expectLength(cpMap.length); + cp_Double_lo.readFrom(in); + for (int i = 0; i < cpMap.length; i++) { + long hi = cp_Double_hi.getInt(); + long lo = cp_Double_lo.getInt(); + long x = (hi << 32) + ((lo << 32) >>> 32); + double dx = Double.longBitsToDouble(x); + cpMap[i] = ConstantPool.getLiteralEntry(dx); + } + cp_Double_hi.doneDisbursing(); + cp_Double_lo.doneDisbursing(); + break; + case CONSTANT_String: + cp_String.expectLength(cpMap.length); + cp_String.readFrom(in); + cp_String.setIndex(getCPIndex(CONSTANT_Utf8)); + for (int i = 0; i < cpMap.length; i++) { + cpMap[i] = ConstantPool.getLiteralEntry(cp_String.getRef().stringValue()); + } + cp_String.doneDisbursing(); + break; + case CONSTANT_Class: + cp_Class.expectLength(cpMap.length); + cp_Class.readFrom(in); + cp_Class.setIndex(getCPIndex(CONSTANT_Utf8)); + for (int i = 0; i < cpMap.length; i++) { + cpMap[i] = ConstantPool.getClassEntry(cp_Class.getRef().stringValue()); + } + cp_Class.doneDisbursing(); + break; + case CONSTANT_Signature: + readSignatureBands(cpMap); + break; + case CONSTANT_NameandType: + // cp_Descr: + // *cp_Descr_type :DELTA5 (cp_Signature) + // *cp_Descr_name :UDELTA5 (cp_Utf8) + cp_Descr_name.expectLength(cpMap.length); + cp_Descr_name.readFrom(in); + cp_Descr_name.setIndex(getCPIndex(CONSTANT_Utf8)); + cp_Descr_type.expectLength(cpMap.length); + cp_Descr_type.readFrom(in); + cp_Descr_type.setIndex(getCPIndex(CONSTANT_Signature)); + for (int i = 0; i < cpMap.length; i++) { + Entry ref = cp_Descr_name.getRef(); + Entry ref2 = cp_Descr_type.getRef(); + cpMap[i] = ConstantPool.getDescriptorEntry((Utf8Entry)ref, + (SignatureEntry)ref2); + } + cp_Descr_name.doneDisbursing(); + cp_Descr_type.doneDisbursing(); + break; + case CONSTANT_Fieldref: + readMemberRefs(tag, cpMap, cp_Field_class, cp_Field_desc); + break; + case CONSTANT_Methodref: + readMemberRefs(tag, cpMap, cp_Method_class, cp_Method_desc); + break; + case CONSTANT_InterfaceMethodref: + readMemberRefs(tag, cpMap, cp_Imethod_class, cp_Imethod_desc); + break; + case CONSTANT_MethodHandle: + if (cpMap.length > 0) { + checkLegacy(cp_MethodHandle_refkind.name()); + } + cp_MethodHandle_refkind.expectLength(cpMap.length); + cp_MethodHandle_refkind.readFrom(in); + cp_MethodHandle_member.expectLength(cpMap.length); + cp_MethodHandle_member.readFrom(in); + cp_MethodHandle_member.setIndex(getCPIndex(CONSTANT_AnyMember)); + for (int i = 0; i < cpMap.length; i++) { + byte refKind = (byte) cp_MethodHandle_refkind.getInt(); + MemberEntry memRef = (MemberEntry) cp_MethodHandle_member.getRef(); + cpMap[i] = ConstantPool.getMethodHandleEntry(refKind, memRef); + } + cp_MethodHandle_refkind.doneDisbursing(); + cp_MethodHandle_member.doneDisbursing(); + break; + case CONSTANT_MethodType: + if (cpMap.length > 0) { + checkLegacy(cp_MethodType.name()); + } + cp_MethodType.expectLength(cpMap.length); + cp_MethodType.readFrom(in); + cp_MethodType.setIndex(getCPIndex(CONSTANT_Signature)); + for (int i = 0; i < cpMap.length; i++) { + SignatureEntry typeRef = (SignatureEntry) cp_MethodType.getRef(); + cpMap[i] = ConstantPool.getMethodTypeEntry(typeRef); + } + cp_MethodType.doneDisbursing(); + break; + case CONSTANT_InvokeDynamic: + if (cpMap.length > 0) { + checkLegacy(cp_InvokeDynamic_spec.name()); + } + cp_InvokeDynamic_spec.expectLength(cpMap.length); + cp_InvokeDynamic_spec.readFrom(in); + cp_InvokeDynamic_spec.setIndex(getCPIndex(CONSTANT_BootstrapMethod)); + cp_InvokeDynamic_desc.expectLength(cpMap.length); + cp_InvokeDynamic_desc.readFrom(in); + cp_InvokeDynamic_desc.setIndex(getCPIndex(CONSTANT_NameandType)); + for (int i = 0; i < cpMap.length; i++) { + BootstrapMethodEntry bss = (BootstrapMethodEntry) cp_InvokeDynamic_spec.getRef(); + DescriptorEntry descr = (DescriptorEntry) cp_InvokeDynamic_desc.getRef(); + cpMap[i] = ConstantPool.getInvokeDynamicEntry(bss, descr); + } + cp_InvokeDynamic_spec.doneDisbursing(); + cp_InvokeDynamic_desc.doneDisbursing(); + break; + case CONSTANT_BootstrapMethod: + if (cpMap.length > 0) { + checkLegacy(cp_BootstrapMethod_ref.name()); + } + cp_BootstrapMethod_ref.expectLength(cpMap.length); + cp_BootstrapMethod_ref.readFrom(in); + cp_BootstrapMethod_ref.setIndex(getCPIndex(CONSTANT_MethodHandle)); + cp_BootstrapMethod_arg_count.expectLength(cpMap.length); + cp_BootstrapMethod_arg_count.readFrom(in); + int totalArgCount = cp_BootstrapMethod_arg_count.getIntTotal(); + cp_BootstrapMethod_arg.expectLength(totalArgCount); + cp_BootstrapMethod_arg.readFrom(in); + cp_BootstrapMethod_arg.setIndex(getCPIndex(CONSTANT_LoadableValue)); + for (int i = 0; i < cpMap.length; i++) { + MethodHandleEntry bsm = (MethodHandleEntry) cp_BootstrapMethod_ref.getRef(); + int argc = cp_BootstrapMethod_arg_count.getInt(); + Entry[] argRefs = new Entry[argc]; + for (int j = 0; j < argc; j++) { + argRefs[j] = cp_BootstrapMethod_arg.getRef(); + } + cpMap[i] = ConstantPool.getBootstrapMethodEntry(bsm, argRefs); + } + cp_BootstrapMethod_ref.doneDisbursing(); + cp_BootstrapMethod_arg_count.doneDisbursing(); + cp_BootstrapMethod_arg.doneDisbursing(); + break; + default: + throw new AssertionError("unexpected CP tag in package"); + } + + Index index = initCPIndex(tag, cpMap); + + if (optDumpBands) { + try (PrintStream ps = new PrintStream(getDumpStream(index, ".idx"))) { + printArrayTo(ps, index.cpMap, 0, index.cpMap.length); + } + } + } + + cp_bands.doneDisbursing(); + + if (optDumpBands || verbose > 1) { + for (byte tag = CONSTANT_GroupFirst; tag < CONSTANT_GroupLimit; tag++) { + Index index = pkg.cp.getIndexByTag(tag); + if (index == null || index.isEmpty()) continue; + Entry[] cpMap = index.cpMap; + if (verbose > 1) + Utils.log.info("Index group "+ConstantPool.tagName(tag)+" contains "+cpMap.length+" entries."); + if (optDumpBands) { + try (PrintStream ps = new PrintStream(getDumpStream(index.debugName, tag, ".gidx", index))) { + printArrayTo(ps, cpMap, 0, cpMap.length, true); + } + } + } + } + + setBandIndexes(); + } + + void readUtf8Bands(Entry[] cpMap) throws IOException { + // cp_Utf8: + // *cp_Utf8_prefix :DELTA5 + // *cp_Utf8_suffix :UNSIGNED5 + // *cp_Utf8_chars :CHAR3 + // *cp_Utf8_big_suffix :DELTA5 + // (*cp_Utf8_big_chars :DELTA5) + // ** length(cp_Utf8_big_suffix) + int len = cpMap.length; + if (len == 0) + return; // nothing to read + + // Bands have implicit leading zeroes, for the empty string: + final int SUFFIX_SKIP_1 = 1; + final int PREFIX_SKIP_2 = 2; + + // First band: Read lengths of shared prefixes. + cp_Utf8_prefix.expectLength(Math.max(0, len - PREFIX_SKIP_2)); + cp_Utf8_prefix.readFrom(in); + + // Second band: Read lengths of unshared suffixes: + cp_Utf8_suffix.expectLength(Math.max(0, len - SUFFIX_SKIP_1)); + cp_Utf8_suffix.readFrom(in); + + char[][] suffixChars = new char[len][]; + int bigSuffixCount = 0; + + // Third band: Read the char values in the unshared suffixes: + cp_Utf8_chars.expectLength(cp_Utf8_suffix.getIntTotal()); + cp_Utf8_chars.readFrom(in); + for (int i = 0; i < len; i++) { + int suffix = (i < SUFFIX_SKIP_1)? 0: cp_Utf8_suffix.getInt(); + if (suffix == 0 && i >= SUFFIX_SKIP_1) { + // chars are packed in cp_Utf8_big_chars + bigSuffixCount += 1; + continue; + } + suffixChars[i] = new char[suffix]; + for (int j = 0; j < suffix; j++) { + int ch = cp_Utf8_chars.getInt(); + assert(ch == (char)ch); + suffixChars[i][j] = (char)ch; + } + } + cp_Utf8_chars.doneDisbursing(); + + // Fourth band: Go back and size the specially packed strings. + int maxChars = 0; + cp_Utf8_big_suffix.expectLength(bigSuffixCount); + cp_Utf8_big_suffix.readFrom(in); + cp_Utf8_suffix.resetForSecondPass(); + for (int i = 0; i < len; i++) { + int suffix = (i < SUFFIX_SKIP_1)? 0: cp_Utf8_suffix.getInt(); + int prefix = (i < PREFIX_SKIP_2)? 0: cp_Utf8_prefix.getInt(); + if (suffix == 0 && i >= SUFFIX_SKIP_1) { + assert(suffixChars[i] == null); + suffix = cp_Utf8_big_suffix.getInt(); + } else { + assert(suffixChars[i] != null); + } + if (maxChars < prefix + suffix) + maxChars = prefix + suffix; + } + char[] buf = new char[maxChars]; + + // Fifth band(s): Get the specially packed characters. + cp_Utf8_suffix.resetForSecondPass(); + cp_Utf8_big_suffix.resetForSecondPass(); + for (int i = 0; i < len; i++) { + if (i < SUFFIX_SKIP_1) continue; + int suffix = cp_Utf8_suffix.getInt(); + if (suffix != 0) continue; // already input + suffix = cp_Utf8_big_suffix.getInt(); + suffixChars[i] = new char[suffix]; + if (suffix == 0) { + // Do not bother to add an empty "(Utf8_big_0)" band. + continue; + } + IntBand packed = cp_Utf8_big_chars.newIntBand("(Utf8_big_"+i+")"); + packed.expectLength(suffix); + packed.readFrom(in); + for (int j = 0; j < suffix; j++) { + int ch = packed.getInt(); + assert(ch == (char)ch); + suffixChars[i][j] = (char)ch; + } + packed.doneDisbursing(); + } + cp_Utf8_big_chars.doneDisbursing(); + + // Finally, sew together all the prefixes and suffixes. + cp_Utf8_prefix.resetForSecondPass(); + cp_Utf8_suffix.resetForSecondPass(); + cp_Utf8_big_suffix.resetForSecondPass(); + for (int i = 0; i < len; i++) { + int prefix = (i < PREFIX_SKIP_2)? 0: cp_Utf8_prefix.getInt(); + int suffix = (i < SUFFIX_SKIP_1)? 0: cp_Utf8_suffix.getInt(); + if (suffix == 0 && i >= SUFFIX_SKIP_1) + suffix = cp_Utf8_big_suffix.getInt(); + + // by induction, the buffer is already filled with the prefix + System.arraycopy(suffixChars[i], 0, buf, prefix, suffix); + + cpMap[i] = ConstantPool.getUtf8Entry(new String(buf, 0, prefix+suffix)); + } + + cp_Utf8_prefix.doneDisbursing(); + cp_Utf8_suffix.doneDisbursing(); + cp_Utf8_big_suffix.doneDisbursing(); + } + + Map utf8Signatures; + + void readSignatureBands(Entry[] cpMap) throws IOException { + // cp_Signature: + // *cp_Signature_form :DELTA5 (cp_Utf8) + // *cp_Signature_classes :UDELTA5 (cp_Class) + cp_Signature_form.expectLength(cpMap.length); + cp_Signature_form.readFrom(in); + cp_Signature_form.setIndex(getCPIndex(CONSTANT_Utf8)); + int[] numSigClasses = new int[cpMap.length]; + for (int i = 0; i < cpMap.length; i++) { + Utf8Entry formRef = (Utf8Entry) cp_Signature_form.getRef(); + numSigClasses[i] = ConstantPool.countClassParts(formRef); + } + cp_Signature_form.resetForSecondPass(); + cp_Signature_classes.expectLength(getIntTotal(numSigClasses)); + cp_Signature_classes.readFrom(in); + cp_Signature_classes.setIndex(getCPIndex(CONSTANT_Class)); + utf8Signatures = new HashMap<>(); + for (int i = 0; i < cpMap.length; i++) { + Utf8Entry formRef = (Utf8Entry) cp_Signature_form.getRef(); + ClassEntry[] classRefs = new ClassEntry[numSigClasses[i]]; + for (int j = 0; j < classRefs.length; j++) { + classRefs[j] = (ClassEntry) cp_Signature_classes.getRef(); + } + SignatureEntry se = ConstantPool.getSignatureEntry(formRef, classRefs); + cpMap[i] = se; + utf8Signatures.put(se.asUtf8Entry(), se); + } + cp_Signature_form.doneDisbursing(); + cp_Signature_classes.doneDisbursing(); + } + + void readMemberRefs(byte tag, Entry[] cpMap, CPRefBand cp_class, CPRefBand cp_desc) throws IOException { + // cp_Field: + // *cp_Field_class :DELTA5 (cp_Class) + // *cp_Field_desc :UDELTA5 (cp_Descr) + // cp_Method: + // *cp_Method_class :DELTA5 (cp_Class) + // *cp_Method_desc :UDELTA5 (cp_Descr) + // cp_Imethod: + // *cp_Imethod_class :DELTA5 (cp_Class) + // *cp_Imethod_desc :UDELTA5 (cp_Descr) + cp_class.expectLength(cpMap.length); + cp_class.readFrom(in); + cp_class.setIndex(getCPIndex(CONSTANT_Class)); + cp_desc.expectLength(cpMap.length); + cp_desc.readFrom(in); + cp_desc.setIndex(getCPIndex(CONSTANT_NameandType)); + for (int i = 0; i < cpMap.length; i++) { + ClassEntry mclass = (ClassEntry ) cp_class.getRef(); + DescriptorEntry mdescr = (DescriptorEntry) cp_desc.getRef(); + cpMap[i] = ConstantPool.getMemberEntry(tag, mclass, mdescr); + } + cp_class.doneDisbursing(); + cp_desc.doneDisbursing(); + } + + void readFiles() throws IOException { + // file_bands: + // *file_name :UNSIGNED5 (cp_Utf8) + // *file_size_hi :UNSIGNED5 + // *file_size_lo :UNSIGNED5 + // *file_modtime :DELTA5 + // *file_options :UNSIGNED5 + // *file_bits :BYTE1 + if (verbose > 0) + Utils.log.info(" ...building "+numFiles+" files..."); + file_name.expectLength(numFiles); + file_size_lo.expectLength(numFiles); + int options = archiveOptions; + boolean haveSizeHi = testBit(options, AO_HAVE_FILE_SIZE_HI); + boolean haveModtime = testBit(options, AO_HAVE_FILE_MODTIME); + boolean haveOptions = testBit(options, AO_HAVE_FILE_OPTIONS); + if (haveSizeHi) + file_size_hi.expectLength(numFiles); + if (haveModtime) + file_modtime.expectLength(numFiles); + if (haveOptions) + file_options.expectLength(numFiles); + + file_name.readFrom(in); + file_size_hi.readFrom(in); + file_size_lo.readFrom(in); + file_modtime.readFrom(in); + file_options.readFrom(in); + file_bits.setInputStreamFrom(in); + + Iterator nextClass = pkg.getClasses().iterator(); + + // Compute file lengths before reading any file bits. + long totalFileLength = 0; + long[] fileLengths = new long[numFiles]; + for (int i = 0; i < numFiles; i++) { + long size = ((long)file_size_lo.getInt() << 32) >>> 32; + if (haveSizeHi) + size += (long)file_size_hi.getInt() << 32; + fileLengths[i] = size; + totalFileLength += size; + } + assert(in.getReadLimit() == -1 || in.getReadLimit() == totalFileLength); + + byte[] buf = new byte[1<<16]; + for (int i = 0; i < numFiles; i++) { + // %%% Use a big temp file for file bits? + Utf8Entry name = (Utf8Entry) file_name.getRef(); + long size = fileLengths[i]; + File file = pkg.new File(name); + file.modtime = pkg.default_modtime; + file.options = pkg.default_options; + if (haveModtime) + file.modtime += file_modtime.getInt(); + if (haveOptions) + file.options |= file_options.getInt(); + if (verbose > 1) + Utils.log.fine("Reading "+size+" bytes of "+name.stringValue()); + long toRead = size; + while (toRead > 0) { + int nr = buf.length; + if (nr > toRead) nr = (int) toRead; + nr = file_bits.getInputStream().read(buf, 0, nr); + if (nr < 0) throw new EOFException(); + file.addBytes(buf, 0, nr); + toRead -= nr; + } + pkg.addFile(file); + if (file.isClassStub()) { + assert(file.getFileLength() == 0); + Class cls = nextClass.next(); + cls.initFile(file); + } + } + + // Do the rest of the classes. + while (nextClass.hasNext()) { + Class cls = nextClass.next(); + cls.initFile(null); // implicitly initialize to a trivial one + cls.file.modtime = pkg.default_modtime; + } + + file_name.doneDisbursing(); + file_size_hi.doneDisbursing(); + file_size_lo.doneDisbursing(); + file_modtime.doneDisbursing(); + file_options.doneDisbursing(); + file_bits.doneDisbursing(); + file_bands.doneDisbursing(); + + if (archiveSize1 != 0 && !in.atLimit()) { + throw new RuntimeException("Predicted archive_size "+ + archiveSize1+" != "+ + (in.getBytesServed()-archiveSize0)); + } + } + + void readAttrDefs() throws IOException { + // attr_definition_bands: + // *attr_definition_headers :BYTE1 + // *attr_definition_name :UNSIGNED5 (cp_Utf8) + // *attr_definition_layout :UNSIGNED5 (cp_Utf8) + attr_definition_headers.expectLength(numAttrDefs); + attr_definition_name.expectLength(numAttrDefs); + attr_definition_layout.expectLength(numAttrDefs); + attr_definition_headers.readFrom(in); + attr_definition_name.readFrom(in); + attr_definition_layout.readFrom(in); + try (PrintStream dump = !optDumpBands ? null + : new PrintStream(getDumpStream(attr_definition_headers, ".def"))) + { + for (int i = 0; i < numAttrDefs; i++) { + int header = attr_definition_headers.getByte(); + Utf8Entry name = (Utf8Entry) attr_definition_name.getRef(); + Utf8Entry layout = (Utf8Entry) attr_definition_layout.getRef(); + int ctype = (header & ADH_CONTEXT_MASK); + int index = (header >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB; + Attribute.Layout def = new Attribute.Layout(ctype, + name.stringValue(), + layout.stringValue()); + // Check layout string for Java 6 extensions. + String pvLayout = def.layoutForClassVersion(getHighestClassVersion()); + if (!pvLayout.equals(def.layout())) { + throw new IOException("Bad attribute layout in archive: "+def.layout()); + } + this.setAttributeLayoutIndex(def, index); + if (dump != null) dump.println(index+" "+def); + } + } + attr_definition_headers.doneDisbursing(); + attr_definition_name.doneDisbursing(); + attr_definition_layout.doneDisbursing(); + // Attribute layouts define bands, one per layout element. + // Create them now, all at once. + makeNewAttributeBands(); + attr_definition_bands.doneDisbursing(); + } + + void readInnerClasses() throws IOException { + // ic_bands: + // *ic_this_class :UDELTA5 (cp_Class) + // *ic_flags :UNSIGNED5 + // *ic_outer_class :DELTA5 (null or cp_Class) + // *ic_name :DELTA5 (null or cp_Utf8) + ic_this_class.expectLength(numInnerClasses); + ic_this_class.readFrom(in); + ic_flags.expectLength(numInnerClasses); + ic_flags.readFrom(in); + int longICCount = 0; + for (int i = 0; i < numInnerClasses; i++) { + int flags = ic_flags.getInt(); + boolean longForm = (flags & ACC_IC_LONG_FORM) != 0; + if (longForm) { + longICCount += 1; + } + } + ic_outer_class.expectLength(longICCount); + ic_outer_class.readFrom(in); + ic_name.expectLength(longICCount); + ic_name.readFrom(in); + ic_flags.resetForSecondPass(); + List icList = new ArrayList<>(numInnerClasses); + for (int i = 0; i < numInnerClasses; i++) { + int flags = ic_flags.getInt(); + boolean longForm = (flags & ACC_IC_LONG_FORM) != 0; + flags &= ~ACC_IC_LONG_FORM; + ClassEntry thisClass = (ClassEntry) ic_this_class.getRef(); + ClassEntry outerClass; + Utf8Entry thisName; + if (longForm) { + outerClass = (ClassEntry) ic_outer_class.getRef(); + thisName = (Utf8Entry) ic_name.getRef(); + } else { + String n = thisClass.stringValue(); + String[] parse = Package.parseInnerClassName(n); + assert(parse != null); + String pkgOuter = parse[0]; + //String number = parse[1]; + String name = parse[2]; + if (pkgOuter == null) + outerClass = null; + else + outerClass = ConstantPool.getClassEntry(pkgOuter); + if (name == null) + thisName = null; + else + thisName = ConstantPool.getUtf8Entry(name); + } + InnerClass ic = + new InnerClass(thisClass, outerClass, thisName, flags); + assert(longForm || ic.predictable); + icList.add(ic); + } + ic_flags.doneDisbursing(); + ic_this_class.doneDisbursing(); + ic_outer_class.doneDisbursing(); + ic_name.doneDisbursing(); + pkg.setAllInnerClasses(icList); + ic_bands.doneDisbursing(); + } + + void readLocalInnerClasses(Class cls) throws IOException { + int nc = class_InnerClasses_N.getInt(); + List localICs = new ArrayList<>(nc); + for (int i = 0; i < nc; i++) { + ClassEntry thisClass = (ClassEntry) class_InnerClasses_RC.getRef(); + int flags = class_InnerClasses_F.getInt(); + if (flags == 0) { + // A zero flag means copy a global IC here. + InnerClass ic = pkg.getGlobalInnerClass(thisClass); + assert(ic != null); // must be a valid global IC reference + localICs.add(ic); + } else { + if (flags == ACC_IC_LONG_FORM) + flags = 0; // clear the marker bit + ClassEntry outer = (ClassEntry) class_InnerClasses_outer_RCN.getRef(); + Utf8Entry name = (Utf8Entry) class_InnerClasses_name_RUN.getRef(); + localICs.add(new InnerClass(thisClass, outer, name, flags)); + } + } + cls.setInnerClasses(localICs); + // cls.expandLocalICs may add more tuples to ics also, + // or may even delete tuples. + // We cannot do that now, because we do not know the + // full contents of the local constant pool yet. + } + + static final int NO_FLAGS_YET = 0; // placeholder for later flag read-in + + Class[] readClasses() throws IOException { + // class_bands: + // *class_this :DELTA5 (cp_Class) + // *class_super :DELTA5 (cp_Class) + // *class_interface_count :DELTA5 + // *class_interface :DELTA5 (cp_Class) + // ...(member bands)... + // class_attr_bands + // code_bands + Class[] classes = new Class[numClasses]; + if (verbose > 0) + Utils.log.info(" ...building "+classes.length+" classes..."); + + class_this.expectLength(numClasses); + class_super.expectLength(numClasses); + class_interface_count.expectLength(numClasses); + + class_this.readFrom(in); + class_super.readFrom(in); + class_interface_count.readFrom(in); + class_interface.expectLength(class_interface_count.getIntTotal()); + class_interface.readFrom(in); + for (int i = 0; i < classes.length; i++) { + ClassEntry thisClass = (ClassEntry) class_this.getRef(); + ClassEntry superClass = (ClassEntry) class_super.getRef(); + ClassEntry[] interfaces = new ClassEntry[class_interface_count.getInt()]; + for (int j = 0; j < interfaces.length; j++) { + interfaces[j] = (ClassEntry) class_interface.getRef(); + } + // Packer encoded rare case of null superClass as thisClass: + if (superClass == thisClass) superClass = null; + Class cls = pkg.new Class(NO_FLAGS_YET, + thisClass, superClass, interfaces); + classes[i] = cls; + } + class_this.doneDisbursing(); + class_super.doneDisbursing(); + class_interface_count.doneDisbursing(); + class_interface.doneDisbursing(); + readMembers(classes); + countAndReadAttrs(ATTR_CONTEXT_CLASS, Arrays.asList(classes)); + pkg.trimToSize(); + readCodeHeaders(); + //code_bands.doneDisbursing(); // still need to read code attrs + //class_bands.doneDisbursing(); // still need to read code attrs + return classes; + } + + private int getOutputIndex(Entry e) { + // Output CPs do not contain signatures. + assert(e.tag != CONSTANT_Signature); + int k = pkg.cp.untypedIndexOf(e); + // In the output ordering, input signatures can serve + // in place of Utf8s. + if (k >= 0) + return k; + if (e.tag == CONSTANT_Utf8) { + Entry se = utf8Signatures.get(e); + return pkg.cp.untypedIndexOf(se); + } + return -1; + } + + Comparator entryOutputOrder = new Comparator() { + public int compare(Entry e0, Entry e1) { + int k0 = getOutputIndex(e0); + int k1 = getOutputIndex(e1); + if (k0 >= 0 && k1 >= 0) + // If both have keys, use the keys. + return k0 - k1; + if (k0 == k1) + // If neither have keys, use their native tags & spellings. + return e0.compareTo(e1); + // Otherwise, the guy with the key comes first. + return (k0 >= 0)? 0-1: 1-0; + } + }; + + void reconstructClass(Class cls) { + if (verbose > 1) Utils.log.fine("reconstruct "+cls); + + // check for local .ClassFile.version + Attribute retroVersion = cls.getAttribute(attrClassFileVersion); + if (retroVersion != null) { + cls.removeAttribute(retroVersion); + cls.version = parseClassFileVersionAttr(retroVersion); + } else { + cls.version = pkg.defaultClassVersion; + } + + // Replace null SourceFile by "obvious" string. + cls.expandSourceFile(); + + // record the local cp: + cls.setCPMap(reconstructLocalCPMap(cls)); + } + + Entry[] reconstructLocalCPMap(Class cls) { + Set ldcRefs = ldcRefMap.get(cls); + Set cpRefs = new HashSet<>(); + + // look for constant pool entries: + cls.visitRefs(VRM_CLASSIC, cpRefs); + + ArrayList bsms = new ArrayList<>(); + /* + * BootstrapMethod(BSMs) are added here before InnerClasses(ICs), + * so as to ensure the order. Noting that the BSMs may be + * removed if they are not found in the CP, after the ICs expansion. + */ + cls.addAttribute(Package.attrBootstrapMethodsEmpty.canonicalInstance()); + + // flesh out the local constant pool + ConstantPool.completeReferencesIn(cpRefs, true, bsms); + + // remove the attr previously set, otherwise add the bsm and + // references as required + if (bsms.isEmpty()) { + cls.attributes.remove(Package.attrBootstrapMethodsEmpty.canonicalInstance()); + } else { + cpRefs.add(Package.getRefString("BootstrapMethods")); + Collections.sort(bsms); + cls.setBootstrapMethods(bsms); + } + + // Now that we know all our local class references, + // compute the InnerClasses attribute. + int changed = cls.expandLocalICs(); + + if (changed != 0) { + if (changed > 0) { + // Just visit the expanded InnerClasses attr. + cls.visitInnerClassRefs(VRM_CLASSIC, cpRefs); + } else { + // Have to recompute from scratch, because of deletions. + cpRefs.clear(); + cls.visitRefs(VRM_CLASSIC, cpRefs); + } + + // flesh out the local constant pool, again + ConstantPool.completeReferencesIn(cpRefs, true, bsms); + } + + // construct a local constant pool + int numDoubles = 0; + for (Entry e : cpRefs) { + if (e.isDoubleWord()) numDoubles++; + } + Entry[] cpMap = new Entry[1+numDoubles+cpRefs.size()]; + int fillp = 1; + + // Add all ldc operands first. + if (ldcRefs != null) { + assert(cpRefs.containsAll(ldcRefs)); + for (Entry e : ldcRefs) { + cpMap[fillp++] = e; + } + assert(fillp == 1+ldcRefs.size()); + cpRefs.removeAll(ldcRefs); + ldcRefs = null; // done with it + } + + // Next add all the two-byte references. + Set wideRefs = cpRefs; + cpRefs = null; // do not use! + int narrowLimit = fillp; + for (Entry e : wideRefs) { + cpMap[fillp++] = e; + } + assert(fillp == narrowLimit+wideRefs.size()); + Arrays.sort(cpMap, 1, narrowLimit, entryOutputOrder); + Arrays.sort(cpMap, narrowLimit, fillp, entryOutputOrder); + + if (verbose > 3) { + Utils.log.fine("CP of "+this+" {"); + for (int i = 0; i < fillp; i++) { + Entry e = cpMap[i]; + Utils.log.fine(" "+((e==null)?-1:getOutputIndex(e)) + +" : "+e); + } + Utils.log.fine("}"); + } + + // Now repack backwards, introducing null elements. + int revp = cpMap.length; + for (int i = fillp; --i >= 1; ) { + Entry e = cpMap[i]; + if (e.isDoubleWord()) + cpMap[--revp] = null; + cpMap[--revp] = e; + } + assert(revp == 1); // do not process the initial null + + return cpMap; + } + + void readMembers(Class[] classes) throws IOException { + // class_bands: + // ... + // *class_field_count :DELTA5 + // *class_method_count :DELTA5 + // + // *field_descr :DELTA5 (cp_Descr) + // field_attr_bands + // + // *method_descr :MDELTA5 (cp_Descr) + // method_attr_bands + // ... + assert(classes.length == numClasses); + class_field_count.expectLength(numClasses); + class_method_count.expectLength(numClasses); + class_field_count.readFrom(in); + class_method_count.readFrom(in); + + // Make a pre-pass over field and method counts to size the descrs: + int totalNF = class_field_count.getIntTotal(); + int totalNM = class_method_count.getIntTotal(); + field_descr.expectLength(totalNF); + method_descr.expectLength(totalNM); + if (verbose > 1) Utils.log.fine("expecting #fields="+totalNF+ + " and #methods="+totalNM+" in #classes="+numClasses); + + List fields = new ArrayList<>(totalNF); + field_descr.readFrom(in); + for (int i = 0; i < classes.length; i++) { + Class c = classes[i]; + int nf = class_field_count.getInt(); + for (int j = 0; j < nf; j++) { + Class.Field f = c.new Field(NO_FLAGS_YET, (DescriptorEntry) + field_descr.getRef()); + fields.add(f); + } + } + class_field_count.doneDisbursing(); + field_descr.doneDisbursing(); + countAndReadAttrs(ATTR_CONTEXT_FIELD, fields); + fields = null; // release to GC + + List methods = new ArrayList<>(totalNM); + method_descr.readFrom(in); + for (int i = 0; i < classes.length; i++) { + Class c = classes[i]; + int nm = class_method_count.getInt(); + for (int j = 0; j < nm; j++) { + Class.Method m = c.new Method(NO_FLAGS_YET, (DescriptorEntry) + method_descr.getRef()); + methods.add(m); + } + } + class_method_count.doneDisbursing(); + method_descr.doneDisbursing(); + countAndReadAttrs(ATTR_CONTEXT_METHOD, methods); + + // Up to this point, Code attributes look like empty attributes. + // Now we start to special-case them. The empty canonical Code + // attributes stay in the method attribute lists, however. + allCodes = buildCodeAttrs(methods); + } + + Code[] allCodes; + List codesWithFlags; + Map> ldcRefMap = new HashMap<>(); + + Code[] buildCodeAttrs(List methods) { + List codes = new ArrayList<>(methods.size()); + for (Class.Method m : methods) { + if (m.getAttribute(attrCodeEmpty) != null) { + m.code = new Code(m); + codes.add(m.code); + } + } + Code[] a = new Code[codes.size()]; + codes.toArray(a); + return a; + } + + void readCodeHeaders() throws IOException { + // code_bands: + // *code_headers :BYTE1 + // + // *code_max_stack :UNSIGNED5 + // *code_max_na_locals :UNSIGNED5 + // *code_handler_count :UNSIGNED5 + // ... + // code_attr_bands + boolean attrsOK = testBit(archiveOptions, AO_HAVE_ALL_CODE_FLAGS); + code_headers.expectLength(allCodes.length); + code_headers.readFrom(in); + List longCodes = new ArrayList<>(allCodes.length / 10); + for (int i = 0; i < allCodes.length; i++) { + Code c = allCodes[i]; + int sc = code_headers.getByte(); + assert(sc == (sc & 0xFF)); + if (verbose > 2) + Utils.log.fine("codeHeader "+c+" = "+sc); + if (sc == LONG_CODE_HEADER) { + // We will read ms/ml/nh/flags from bands shortly. + longCodes.add(c); + continue; + } + // Short code header is the usual case: + c.setMaxStack( shortCodeHeader_max_stack(sc) ); + c.setMaxNALocals( shortCodeHeader_max_na_locals(sc) ); + c.setHandlerCount( shortCodeHeader_handler_count(sc) ); + assert(shortCodeHeader(c) == sc); + } + code_headers.doneDisbursing(); + code_max_stack.expectLength(longCodes.size()); + code_max_na_locals.expectLength(longCodes.size()); + code_handler_count.expectLength(longCodes.size()); + + // Do the long headers now. + code_max_stack.readFrom(in); + code_max_na_locals.readFrom(in); + code_handler_count.readFrom(in); + for (Code c : longCodes) { + c.setMaxStack( code_max_stack.getInt() ); + c.setMaxNALocals( code_max_na_locals.getInt() ); + c.setHandlerCount( code_handler_count.getInt() ); + } + code_max_stack.doneDisbursing(); + code_max_na_locals.doneDisbursing(); + code_handler_count.doneDisbursing(); + + readCodeHandlers(); + + if (attrsOK) { + // Code attributes are common (debug info not stripped). + codesWithFlags = Arrays.asList(allCodes); + } else { + // Code attributes are very sparse (debug info is stripped). + codesWithFlags = longCodes; + } + countAttrs(ATTR_CONTEXT_CODE, codesWithFlags); + // do readAttrs later, after BCs are scanned + } + + void readCodeHandlers() throws IOException { + // code_bands: + // ... + // *code_handler_start_P :BCI5 + // *code_handler_end_PO :BRANCH5 + // *code_handler_catch_PO :BRANCH5 + // *code_handler_class_RCN :UNSIGNED5 (null or cp_Class) + // ... + int nh = 0; + for (int i = 0; i < allCodes.length; i++) { + Code c = allCodes[i]; + nh += c.getHandlerCount(); + } + + ValueBand[] code_handler_bands = { + code_handler_start_P, + code_handler_end_PO, + code_handler_catch_PO, + code_handler_class_RCN + }; + + for (int i = 0; i < code_handler_bands.length; i++) { + code_handler_bands[i].expectLength(nh); + code_handler_bands[i].readFrom(in); + } + + for (int i = 0; i < allCodes.length; i++) { + Code c = allCodes[i]; + for (int j = 0, jmax = c.getHandlerCount(); j < jmax; j++) { + c.handler_class[j] = code_handler_class_RCN.getRef(); + // For now, just record the raw BCI codes. + // We must wait until we have instruction boundaries. + c.handler_start[j] = code_handler_start_P.getInt(); + c.handler_end[j] = code_handler_end_PO.getInt(); + c.handler_catch[j] = code_handler_catch_PO.getInt(); + } + } + for (int i = 0; i < code_handler_bands.length; i++) { + code_handler_bands[i].doneDisbursing(); + } + } + + void fixupCodeHandlers() { + // Actually decode (renumber) the BCIs now. + for (int i = 0; i < allCodes.length; i++) { + Code c = allCodes[i]; + for (int j = 0, jmax = c.getHandlerCount(); j < jmax; j++) { + int sum = c.handler_start[j]; + c.handler_start[j] = c.decodeBCI(sum); + sum += c.handler_end[j]; + c.handler_end[j] = c.decodeBCI(sum); + sum += c.handler_catch[j]; + c.handler_catch[j] = c.decodeBCI(sum); + } + } + } + + // Generic routines for reading attributes of + // classes, fields, methods, and codes. + // The holders is a global list, already collected, + // of attribute "customers". + void countAndReadAttrs(int ctype, Collection holders) + throws IOException { + // class_attr_bands: + // *class_flags :UNSIGNED5 + // *class_attr_count :UNSIGNED5 + // *class_attr_indexes :UNSIGNED5 + // *class_attr_calls :UNSIGNED5 + // *class_Signature_RS :UNSIGNED5 (cp_Signature) + // class_metadata_bands + // *class_SourceFile_RU :UNSIGNED5 (cp_Utf8) + // *class_EnclosingMethod_RM :UNSIGNED5 (cp_Method) + // ic_local_bands + // *class_ClassFile_version_minor_H :UNSIGNED5 + // *class_ClassFile_version_major_H :UNSIGNED5 + // class_type_metadata_bands + // + // field_attr_bands: + // *field_flags :UNSIGNED5 + // *field_attr_count :UNSIGNED5 + // *field_attr_indexes :UNSIGNED5 + // *field_attr_calls :UNSIGNED5 + // *field_Signature_RS :UNSIGNED5 (cp_Signature) + // field_metadata_bands + // *field_ConstantValue_KQ :UNSIGNED5 (cp_Int, etc.; see note) + // field_type_metadata_bands + // + // method_attr_bands: + // *method_flags :UNSIGNED5 + // *method_attr_count :UNSIGNED5 + // *method_attr_indexes :UNSIGNED5 + // *method_attr_calls :UNSIGNED5 + // *method_Signature_RS :UNSIGNED5 (cp_Signature) + // method_metadata_bands + // *method_Exceptions_N :UNSIGNED5 + // *method_Exceptions_RC :UNSIGNED5 (cp_Class) + // *method_MethodParameters_NB: BYTE1 + // *method_MethodParameters_RUN: UNSIGNED5 (cp_Utf8) + // *method_MethodParameters_FH: UNSIGNED5 (flag) + // method_type_metadata_bands + // + // code_attr_bands: + // *code_flags :UNSIGNED5 + // *code_attr_count :UNSIGNED5 + // *code_attr_indexes :UNSIGNED5 + // *code_attr_calls :UNSIGNED5 + // *code_LineNumberTable_N :UNSIGNED5 + // *code_LineNumberTable_bci_P :BCI5 + // *code_LineNumberTable_line :UNSIGNED5 + // *code_LocalVariableTable_N :UNSIGNED5 + // *code_LocalVariableTable_bci_P :BCI5 + // *code_LocalVariableTable_span_O :BRANCH5 + // *code_LocalVariableTable_name_RU :UNSIGNED5 (cp_Utf8) + // *code_LocalVariableTable_type_RS :UNSIGNED5 (cp_Signature) + // *code_LocalVariableTable_slot :UNSIGNED5 + // code_type_metadata_bands + + countAttrs(ctype, holders); + readAttrs(ctype, holders); + } + + // Read flags and count the attributes that are to be placed + // on the given holders. + void countAttrs(int ctype, Collection holders) + throws IOException { + // Here, xxx stands for one of class, field, method, code. + MultiBand xxx_attr_bands = attrBands[ctype]; + long flagMask = attrFlagMask[ctype]; + if (verbose > 1) { + Utils.log.fine("scanning flags and attrs for "+ + Attribute.contextName(ctype)+"["+holders.size()+"]"); + } + + // Fetch the attribute layout definitions which govern the bands + // we are about to read. + List defList = attrDefs.get(ctype); + Attribute.Layout[] defs = new Attribute.Layout[defList.size()]; + defList.toArray(defs); + IntBand xxx_flags_hi = getAttrBand(xxx_attr_bands, AB_FLAGS_HI); + IntBand xxx_flags_lo = getAttrBand(xxx_attr_bands, AB_FLAGS_LO); + IntBand xxx_attr_count = getAttrBand(xxx_attr_bands, AB_ATTR_COUNT); + IntBand xxx_attr_indexes = getAttrBand(xxx_attr_bands, AB_ATTR_INDEXES); + IntBand xxx_attr_calls = getAttrBand(xxx_attr_bands, AB_ATTR_CALLS); + + // Count up the number of holders which have overflow attrs. + int overflowMask = attrOverflowMask[ctype]; + int overflowHolderCount = 0; + boolean haveLongFlags = haveFlagsHi(ctype); + xxx_flags_hi.expectLength(haveLongFlags? holders.size(): 0); + xxx_flags_hi.readFrom(in); + xxx_flags_lo.expectLength(holders.size()); + xxx_flags_lo.readFrom(in); + assert((flagMask & overflowMask) == overflowMask); + for (Attribute.Holder h : holders) { + int flags = xxx_flags_lo.getInt(); + h.flags = flags; + if ((flags & overflowMask) != 0) + overflowHolderCount += 1; + } + + // For each holder with overflow attrs, read a count. + xxx_attr_count.expectLength(overflowHolderCount); + xxx_attr_count.readFrom(in); + xxx_attr_indexes.expectLength(xxx_attr_count.getIntTotal()); + xxx_attr_indexes.readFrom(in); + + // Now it's time to check flag bits that indicate attributes. + // We accumulate (a) a list of attribute types for each holder + // (class/field/method/code), and also we accumulate (b) a total + // count for each attribute type. + int[] totalCounts = new int[defs.length]; + for (Attribute.Holder h : holders) { + assert(h.attributes == null); + // System.out.println("flags="+h.flags+" using fm="+flagMask); + long attrBits = ((h.flags & flagMask) << 32) >>> 32; + // Clean up the flags now. + h.flags -= (int)attrBits; // strip attr bits + assert(h.flags == (char)h.flags); // 16 bits only now + assert((ctype != ATTR_CONTEXT_CODE) || h.flags == 0); + if (haveLongFlags) + attrBits += (long)xxx_flags_hi.getInt() << 32; + if (attrBits == 0) continue; // no attrs on this guy + + int noa = 0; // number of overflow attrs + long overflowBit = (attrBits & overflowMask); + assert(overflowBit >= 0); + attrBits -= overflowBit; + if (overflowBit != 0) { + noa = xxx_attr_count.getInt(); + } + + int nfa = 0; // number of flag attrs + long bits = attrBits; + for (int ai = 0; bits != 0; ai++) { + if ((bits & (1L< ha = new ArrayList<>(nfa + noa); + h.attributes = ha; + bits = attrBits; // iterate again + for (int ai = 0; bits != 0; ai++) { + if ((bits & (1L< 0; noa--) { + int ai = xxx_attr_indexes.getInt(); + totalCounts[ai] += 1; + // This definition index is live in this holder. + if (defs[ai] == null) badAttrIndex(ai, ctype); + Attribute canonical = defs[ai].canonicalInstance(); + ha.add(canonical); + } + } + + xxx_flags_hi.doneDisbursing(); + xxx_flags_lo.doneDisbursing(); + xxx_attr_count.doneDisbursing(); + xxx_attr_indexes.doneDisbursing(); + + // Now each holder has a list of canonical attribute instances. + // For layouts with no elements, we are done. However, for + // layouts with bands, we must replace each canonical (empty) + // instance with a value-bearing one, initialized from the + // appropriate bands. + + // Make a small pass to detect and read backward call counts. + int callCounts = 0; + for (boolean predef = true; ; predef = false) { + for (int ai = 0; ai < defs.length; ai++) { + Attribute.Layout def = defs[ai]; + if (def == null) continue; // unused index + if (predef != isPredefinedAttr(ctype, ai)) + continue; // wrong pass + int totalCount = totalCounts[ai]; + if (totalCount == 0) + continue; // irrelevant + Attribute.Layout.Element[] cbles = def.getCallables(); + for (int j = 0; j < cbles.length; j++) { + assert(cbles[j].kind == Attribute.EK_CBLE); + if (cbles[j].flagTest(Attribute.EF_BACK)) + callCounts += 1; + } + } + if (!predef) break; + } + xxx_attr_calls.expectLength(callCounts); + xxx_attr_calls.readFrom(in); + + // Finally, size all the attribute bands. + for (boolean predef = true; ; predef = false) { + for (int ai = 0; ai < defs.length; ai++) { + Attribute.Layout def = defs[ai]; + if (def == null) continue; // unused index + if (predef != isPredefinedAttr(ctype, ai)) + continue; // wrong pass + int totalCount = totalCounts[ai]; + Band[] ab = attrBandTable.get(def); + if (def == attrInnerClassesEmpty) { + // Special case. + // Size the bands as if using the following layout: + // [RCH TI[ (0)[] ()[RCNH RUNH] ]]. + class_InnerClasses_N.expectLength(totalCount); + class_InnerClasses_N.readFrom(in); + int tupleCount = class_InnerClasses_N.getIntTotal(); + class_InnerClasses_RC.expectLength(tupleCount); + class_InnerClasses_RC.readFrom(in); + class_InnerClasses_F.expectLength(tupleCount); + class_InnerClasses_F.readFrom(in); + // Drop remaining columns wherever flags are zero: + tupleCount -= class_InnerClasses_F.getIntCount(0); + class_InnerClasses_outer_RCN.expectLength(tupleCount); + class_InnerClasses_outer_RCN.readFrom(in); + class_InnerClasses_name_RUN.expectLength(tupleCount); + class_InnerClasses_name_RUN.readFrom(in); + } else if (!optDebugBands && totalCount == 0) { + // Expect no elements at all. Skip quickly. however if we + // are debugging bands, read all bands regardless + for (int j = 0; j < ab.length; j++) { + ab[j].doneWithUnusedBand(); + } + } else { + // Read these bands in sequence. + boolean hasCallables = def.hasCallables(); + if (!hasCallables) { + readAttrBands(def.elems, totalCount, new int[0], ab); + } else { + Attribute.Layout.Element[] cbles = def.getCallables(); + // At first, record initial calls. + // Later, forward calls may also accumulate here: + int[] forwardCounts = new int[cbles.length]; + forwardCounts[0] = totalCount; + for (int j = 0; j < cbles.length; j++) { + assert(cbles[j].kind == Attribute.EK_CBLE); + int entryCount = forwardCounts[j]; + forwardCounts[j] = -1; // No more, please! + if (totalCount > 0 && cbles[j].flagTest(Attribute.EF_BACK)) + entryCount += xxx_attr_calls.getInt(); + readAttrBands(cbles[j].body, entryCount, forwardCounts, ab); + } + } + // mark them read, to satisfy asserts + if (optDebugBands && totalCount == 0) { + for (int j = 0; j < ab.length; j++) { + ab[j].doneDisbursing(); + } + } + } + } + if (!predef) break; + } + xxx_attr_calls.doneDisbursing(); + } + + void badAttrIndex(int ai, int ctype) throws IOException { + throw new IOException("Unknown attribute index "+ai+" for "+ + ATTR_CONTEXT_NAME[ctype]+" attribute"); + } + + void readAttrs(int ctype, Collection holders) + throws IOException { + // Decode band values into attributes. + Set sawDefs = new HashSet<>(); + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + for (final Attribute.Holder h : holders) { + if (h.attributes == null) continue; + for (ListIterator j = h.attributes.listIterator(); j.hasNext(); ) { + Attribute a = j.next(); + Attribute.Layout def = a.layout(); + if (def.bandCount == 0) { + if (def == attrInnerClassesEmpty) { + // Special logic to read this attr. + readLocalInnerClasses((Class) h); + continue; + } + // Canonical empty attr works fine (e.g., Synthetic). + continue; + } + sawDefs.add(def); + boolean isCV = (ctype == ATTR_CONTEXT_FIELD && def == attrConstantValue); + if (isCV) setConstantValueIndex((Class.Field)h); + if (verbose > 2) + Utils.log.fine("read "+a+" in "+h); + final Band[] ab = attrBandTable.get(def); + // Read one attribute of type def from ab into a byte array. + buf.reset(); + Object fixups = a.unparse(new Attribute.ValueStream() { + public int getInt(int bandIndex) { + return ((IntBand) ab[bandIndex]).getInt(); + } + public Entry getRef(int bandIndex) { + return ((CPRefBand) ab[bandIndex]).getRef(); + } + public int decodeBCI(int bciCode) { + Code code = (Code) h; + return code.decodeBCI(bciCode); + } + }, buf); + // Replace the canonical attr with the one just read. + j.set(a.addContent(buf.toByteArray(), fixups)); + if (isCV) setConstantValueIndex(null); // clean up + } + } + + // Mark the bands we just used as done disbursing. + for (Attribute.Layout def : sawDefs) { + if (def == null) continue; // unused index + Band[] ab = attrBandTable.get(def); + for (int j = 0; j < ab.length; j++) { + ab[j].doneDisbursing(); + } + } + + if (ctype == ATTR_CONTEXT_CLASS) { + class_InnerClasses_N.doneDisbursing(); + class_InnerClasses_RC.doneDisbursing(); + class_InnerClasses_F.doneDisbursing(); + class_InnerClasses_outer_RCN.doneDisbursing(); + class_InnerClasses_name_RUN.doneDisbursing(); + } + + MultiBand xxx_attr_bands = attrBands[ctype]; + for (int i = 0; i < xxx_attr_bands.size(); i++) { + Band b = xxx_attr_bands.get(i); + if (b instanceof MultiBand) + b.doneDisbursing(); + } + xxx_attr_bands.doneDisbursing(); + } + + private + void readAttrBands(Attribute.Layout.Element[] elems, + int count, int[] forwardCounts, + Band[] ab) + throws IOException { + for (int i = 0; i < elems.length; i++) { + Attribute.Layout.Element e = elems[i]; + Band eBand = null; + if (e.hasBand()) { + eBand = ab[e.bandIndex]; + eBand.expectLength(count); + eBand.readFrom(in); + } + switch (e.kind) { + case Attribute.EK_REPL: + // Recursive call. + int repCount = ((IntBand)eBand).getIntTotal(); + // Note: getIntTotal makes an extra pass over this band. + readAttrBands(e.body, repCount, forwardCounts, ab); + break; + case Attribute.EK_UN: + int remainingCount = count; + for (int j = 0; j < e.body.length; j++) { + int caseCount; + if (j == e.body.length-1) { + caseCount = remainingCount; + } else { + caseCount = 0; + for (int j0 = j; + (j == j0) + || (j < e.body.length + && e.body[j].flagTest(Attribute.EF_BACK)); + j++) { + caseCount += ((IntBand)eBand).getIntCount(e.body[j].value); + } + --j; // back up to last occurrence of this body + } + remainingCount -= caseCount; + readAttrBands(e.body[j].body, caseCount, forwardCounts, ab); + } + assert(remainingCount == 0); + break; + case Attribute.EK_CALL: + assert(e.body.length == 1); + assert(e.body[0].kind == Attribute.EK_CBLE); + if (!e.flagTest(Attribute.EF_BACK)) { + // Backward calls are pre-counted, but forwards are not. + // Push the present count forward. + assert(forwardCounts[e.value] >= 0); + forwardCounts[e.value] += count; + } + break; + case Attribute.EK_CBLE: + assert(false); + break; + } + } + } + + void readByteCodes() throws IOException { + // bc_bands: + // *bc_codes :BYTE1 + // *bc_case_count :UNSIGNED5 + // *bc_case_value :DELTA5 + // *bc_byte :BYTE1 + // *bc_short :DELTA5 + // *bc_local :UNSIGNED5 + // *bc_label :BRANCH5 + // *bc_intref :DELTA5 (cp_Int) + // *bc_floatref :DELTA5 (cp_Float) + // *bc_longref :DELTA5 (cp_Long) + // *bc_doubleref :DELTA5 (cp_Double) + // *bc_stringref :DELTA5 (cp_String) + // *bc_classref :UNSIGNED5 (current class or cp_Class) + // *bc_fieldref :DELTA5 (cp_Field) + // *bc_methodref :UNSIGNED5 (cp_Method) + // *bc_imethodref :DELTA5 (cp_Imethod) + // *bc_thisfield :UNSIGNED5 (cp_Field, only for current class) + // *bc_superfield :UNSIGNED5 (cp_Field, only for current super) + // *bc_thismethod :UNSIGNED5 (cp_Method, only for current class) + // *bc_supermethod :UNSIGNED5 (cp_Method, only for current super) + // *bc_initref :UNSIGNED5 (cp_Field, only for most recent new) + // *bc_escref :UNSIGNED5 (cp_All) + // *bc_escrefsize :UNSIGNED5 + // *bc_escsize :UNSIGNED5 + // *bc_escbyte :BYTE1 + bc_codes.elementCountForDebug = allCodes.length; + bc_codes.setInputStreamFrom(in); + readByteCodeOps(); // reads from bc_codes and bc_case_count + bc_codes.doneDisbursing(); + + // All the operand bands have now been sized. Read them all in turn. + Band[] operand_bands = { + bc_case_value, + bc_byte, bc_short, + bc_local, bc_label, + bc_intref, bc_floatref, + bc_longref, bc_doubleref, bc_stringref, + bc_loadablevalueref, + bc_classref, bc_fieldref, + bc_methodref, bc_imethodref, + bc_indyref, + bc_thisfield, bc_superfield, + bc_thismethod, bc_supermethod, + bc_initref, + bc_escref, bc_escrefsize, bc_escsize + }; + for (int i = 0; i < operand_bands.length; i++) { + operand_bands[i].readFrom(in); + } + bc_escbyte.expectLength(bc_escsize.getIntTotal()); + bc_escbyte.readFrom(in); + + expandByteCodeOps(); + + // Done fetching values from operand bands: + bc_case_count.doneDisbursing(); + for (int i = 0; i < operand_bands.length; i++) { + operand_bands[i].doneDisbursing(); + } + bc_escbyte.doneDisbursing(); + bc_bands.doneDisbursing(); + + // We must delay the parsing of Code attributes until we + // have a complete model of bytecodes, for BCI encodings. + readAttrs(ATTR_CONTEXT_CODE, codesWithFlags); + // Ditto for exception handlers in codes. + fixupCodeHandlers(); + // Now we can finish with class_bands; cf. readClasses(). + code_bands.doneDisbursing(); + class_bands.doneDisbursing(); + } + + private void readByteCodeOps() throws IOException { + // scratch buffer for collecting code:: + byte[] buf = new byte[1<<12]; + // record of all switch opcodes (these are variable-length) + List allSwitchOps = new ArrayList<>(); + for (int k = 0; k < allCodes.length; k++) { + Code c = allCodes[k]; + scanOneMethod: + for (int i = 0; ; i++) { + int bc = bc_codes.getByte(); + if (i + 10 > buf.length) buf = realloc(buf); + buf[i] = (byte)bc; + boolean isWide = false; + if (bc == _wide) { + bc = bc_codes.getByte(); + buf[++i] = (byte)bc; + isWide = true; + } + assert(bc == (0xFF & bc)); + // Adjust expectations of various band sizes. + switch (bc) { + case _tableswitch: + case _lookupswitch: + bc_case_count.expectMoreLength(1); + allSwitchOps.add(bc); + break; + case _iinc: + bc_local.expectMoreLength(1); + if (isWide) + bc_short.expectMoreLength(1); + else + bc_byte.expectMoreLength(1); + break; + case _sipush: + bc_short.expectMoreLength(1); + break; + case _bipush: + bc_byte.expectMoreLength(1); + break; + case _newarray: + bc_byte.expectMoreLength(1); + break; + case _multianewarray: + assert(getCPRefOpBand(bc) == bc_classref); + bc_classref.expectMoreLength(1); + bc_byte.expectMoreLength(1); + break; + case _ref_escape: + bc_escrefsize.expectMoreLength(1); + bc_escref.expectMoreLength(1); + break; + case _byte_escape: + bc_escsize.expectMoreLength(1); + // bc_escbyte will have to be counted too + break; + default: + if (Instruction.isInvokeInitOp(bc)) { + bc_initref.expectMoreLength(1); + break; + } + if (Instruction.isSelfLinkerOp(bc)) { + CPRefBand bc_which = selfOpRefBand(bc); + bc_which.expectMoreLength(1); + break; + } + if (Instruction.isBranchOp(bc)) { + bc_label.expectMoreLength(1); + break; + } + if (Instruction.isCPRefOp(bc)) { + CPRefBand bc_which = getCPRefOpBand(bc); + bc_which.expectMoreLength(1); + assert(bc != _multianewarray); // handled elsewhere + break; + } + if (Instruction.isLocalSlotOp(bc)) { + bc_local.expectMoreLength(1); + break; + } + break; + case _end_marker: + { + // Transfer from buf to a more permanent place: + c.bytes = realloc(buf, i); + break scanOneMethod; + } + } + } + } + + // To size instruction bands correctly, we need info on switches: + bc_case_count.readFrom(in); + for (Integer i : allSwitchOps) { + int bc = i.intValue(); + int caseCount = bc_case_count.getInt(); + bc_label.expectMoreLength(1+caseCount); // default label + cases + bc_case_value.expectMoreLength(bc == _tableswitch ? 1 : caseCount); + } + bc_case_count.resetForSecondPass(); + } + + private void expandByteCodeOps() throws IOException { + // scratch buffer for collecting code: + byte[] buf = new byte[1<<12]; + // scratch buffer for collecting instruction boundaries: + int[] insnMap = new int[1<<12]; + // list of label carriers, for label decoding post-pass: + int[] labels = new int[1<<10]; + // scratch buffer for registering CP refs: + Fixups fixupBuf = new Fixups(); + + for (int k = 0; k < allCodes.length; k++) { + Code code = allCodes[k]; + byte[] codeOps = code.bytes; + code.bytes = null; // just for now, while we accumulate bits + + Class curClass = code.thisClass(); + + Set ldcRefSet = ldcRefMap.get(curClass); + if (ldcRefSet == null) + ldcRefMap.put(curClass, ldcRefSet = new HashSet<>()); + + ClassEntry thisClass = curClass.thisClass; + ClassEntry superClass = curClass.superClass; + ClassEntry newClass = null; // class of last _new opcode + + int pc = 0; // fill pointer in buf; actual bytecode PC + int numInsns = 0; + int numLabels = 0; + boolean hasEscs = false; + fixupBuf.clear(); + for (int i = 0; i < codeOps.length; i++) { + int bc = Instruction.getByte(codeOps, i); + int curPC = pc; + insnMap[numInsns++] = curPC; + if (pc + 10 > buf.length) buf = realloc(buf); + if (numInsns+10 > insnMap.length) insnMap = realloc(insnMap); + if (numLabels+10 > labels.length) labels = realloc(labels); + boolean isWide = false; + if (bc == _wide) { + buf[pc++] = (byte) bc; + bc = Instruction.getByte(codeOps, ++i); + isWide = true; + } + switch (bc) { + case _tableswitch: // apc: (df, lo, hi, (hi-lo+1)*(label)) + case _lookupswitch: // apc: (df, nc, nc*(case, label)) + { + int caseCount = bc_case_count.getInt(); + while ((pc + 30 + caseCount*8) > buf.length) + buf = realloc(buf); + buf[pc++] = (byte) bc; + //initialize apc, df, lo, hi bytes to reasonable bits: + Arrays.fill(buf, pc, pc+30, (byte)0); + Instruction.Switch isw = (Instruction.Switch) + Instruction.at(buf, curPC); + //isw.setDefaultLabel(getLabel(bc_label, code, curPC)); + isw.setCaseCount(caseCount); + if (bc == _tableswitch) { + isw.setCaseValue(0, bc_case_value.getInt()); + } else { + for (int j = 0; j < caseCount; j++) { + isw.setCaseValue(j, bc_case_value.getInt()); + } + } + // Make our getLabel calls later. + labels[numLabels++] = curPC; + pc = isw.getNextPC(); + continue; + } + case _iinc: + { + buf[pc++] = (byte) bc; + int local = bc_local.getInt(); + int delta; + if (isWide) { + delta = bc_short.getInt(); + Instruction.setShort(buf, pc, local); pc += 2; + Instruction.setShort(buf, pc, delta); pc += 2; + } else { + delta = (byte) bc_byte.getByte(); + buf[pc++] = (byte)local; + buf[pc++] = (byte)delta; + } + continue; + } + case _sipush: + { + int val = bc_short.getInt(); + buf[pc++] = (byte) bc; + Instruction.setShort(buf, pc, val); pc += 2; + continue; + } + case _bipush: + case _newarray: + { + int val = bc_byte.getByte(); + buf[pc++] = (byte) bc; + buf[pc++] = (byte) val; + continue; + } + case _ref_escape: + { + // Note that insnMap has one entry for this. + hasEscs = true; + int size = bc_escrefsize.getInt(); + Entry ref = bc_escref.getRef(); + if (size == 1) ldcRefSet.add(ref); + int fmt; + switch (size) { + case 1: fixupBuf.addU1(pc, ref); break; + case 2: fixupBuf.addU2(pc, ref); break; + default: assert(false); fmt = 0; + } + buf[pc+0] = buf[pc+1] = 0; + pc += size; + } + continue; + case _byte_escape: + { + // Note that insnMap has one entry for all these bytes. + hasEscs = true; + int size = bc_escsize.getInt(); + while ((pc + size) > buf.length) + buf = realloc(buf); + while (size-- > 0) { + buf[pc++] = (byte) bc_escbyte.getByte(); + } + } + continue; + default: + if (Instruction.isInvokeInitOp(bc)) { + int idx = (bc - _invokeinit_op); + int origBC = _invokespecial; + ClassEntry classRef; + switch (idx) { + case _invokeinit_self_option: + classRef = thisClass; break; + case _invokeinit_super_option: + classRef = superClass; break; + default: + assert(idx == _invokeinit_new_option); + classRef = newClass; break; + } + buf[pc++] = (byte) origBC; + int coding = bc_initref.getInt(); + // Find the nth overloading of in classRef. + MemberEntry ref = pkg.cp.getOverloadingForIndex(CONSTANT_Methodref, classRef, "", coding); + fixupBuf.addU2(pc, ref); + buf[pc+0] = buf[pc+1] = 0; + pc += 2; + assert(Instruction.opLength(origBC) == (pc - curPC)); + continue; + } + if (Instruction.isSelfLinkerOp(bc)) { + int idx = (bc - _self_linker_op); + boolean isSuper = (idx >= _self_linker_super_flag); + if (isSuper) idx -= _self_linker_super_flag; + boolean isAload = (idx >= _self_linker_aload_flag); + if (isAload) idx -= _self_linker_aload_flag; + int origBC = _first_linker_op + idx; + boolean isField = Instruction.isFieldOp(origBC); + CPRefBand bc_which; + ClassEntry which_cls = isSuper ? superClass : thisClass; + Index which_ix; + if (isField) { + bc_which = isSuper ? bc_superfield : bc_thisfield; + which_ix = pkg.cp.getMemberIndex(CONSTANT_Fieldref, which_cls); + } else { + bc_which = isSuper ? bc_supermethod : bc_thismethod; + which_ix = pkg.cp.getMemberIndex(CONSTANT_Methodref, which_cls); + } + assert(bc_which == selfOpRefBand(bc)); + MemberEntry ref = (MemberEntry) bc_which.getRef(which_ix); + if (isAload) { + buf[pc++] = (byte) _aload_0; + curPC = pc; + // Note: insnMap keeps the _aload_0 separate. + insnMap[numInsns++] = curPC; + } + buf[pc++] = (byte) origBC; + fixupBuf.addU2(pc, ref); + buf[pc+0] = buf[pc+1] = 0; + pc += 2; + assert(Instruction.opLength(origBC) == (pc - curPC)); + continue; + } + if (Instruction.isBranchOp(bc)) { + buf[pc++] = (byte) bc; + assert(!isWide); // no wide prefix for branches + int nextPC = curPC + Instruction.opLength(bc); + // Make our getLabel calls later. + labels[numLabels++] = curPC; + //Instruction.at(buf, curPC).setBranchLabel(getLabel(bc_label, code, curPC)); + while (pc < nextPC) buf[pc++] = 0; + continue; + } + if (Instruction.isCPRefOp(bc)) { + CPRefBand bc_which = getCPRefOpBand(bc); + Entry ref = bc_which.getRef(); + if (ref == null) { + if (bc_which == bc_classref) { + // Shorthand for class self-references. + ref = thisClass; + } else { + assert(false); + } + } + int origBC = bc; + int size = 2; + switch (bc) { + case _invokestatic_int: + origBC = _invokestatic; + break; + case _invokespecial_int: + origBC = _invokespecial; + break; + case _ildc: + case _cldc: + case _fldc: + case _sldc: + case _qldc: + origBC = _ldc; + size = 1; + ldcRefSet.add(ref); + break; + case _ildc_w: + case _cldc_w: + case _fldc_w: + case _sldc_w: + case _qldc_w: + origBC = _ldc_w; + break; + case _lldc2_w: + case _dldc2_w: + origBC = _ldc2_w; + break; + case _new: + newClass = (ClassEntry) ref; + break; + } + buf[pc++] = (byte) origBC; + int fmt; + switch (size) { + case 1: fixupBuf.addU1(pc, ref); break; + case 2: fixupBuf.addU2(pc, ref); break; + default: assert(false); fmt = 0; + } + buf[pc+0] = buf[pc+1] = 0; + pc += size; + if (origBC == _multianewarray) { + // Copy the trailing byte also. + int val = bc_byte.getByte(); + buf[pc++] = (byte) val; + } else if (origBC == _invokeinterface) { + int argSize = ((MemberEntry)ref).descRef.typeRef.computeSize(true); + buf[pc++] = (byte)( 1 + argSize ); + buf[pc++] = 0; + } else if (origBC == _invokedynamic) { + buf[pc++] = 0; + buf[pc++] = 0; + } + assert(Instruction.opLength(origBC) == (pc - curPC)); + continue; + } + if (Instruction.isLocalSlotOp(bc)) { + buf[pc++] = (byte) bc; + int local = bc_local.getInt(); + if (isWide) { + Instruction.setShort(buf, pc, local); + pc += 2; + if (bc == _iinc) { + int iVal = bc_short.getInt(); + Instruction.setShort(buf, pc, iVal); + pc += 2; + } + } else { + Instruction.setByte(buf, pc, local); + pc += 1; + if (bc == _iinc) { + int iVal = bc_byte.getByte(); + Instruction.setByte(buf, pc, iVal); + pc += 1; + } + } + assert(Instruction.opLength(bc) == (pc - curPC)); + continue; + } + // Random bytecode. Just copy it. + if (bc >= _bytecode_limit) + Utils.log.warning("unrecognized bytescode "+bc + +" "+Instruction.byteName(bc)); + assert(bc < _bytecode_limit); + buf[pc++] = (byte) bc; + assert(Instruction.opLength(bc) == (pc - curPC)); + continue; + } + } + // now make a permanent copy of the bytecodes + code.setBytes(realloc(buf, pc)); + code.setInstructionMap(insnMap, numInsns); + // fix up labels, now that code has its insnMap + Instruction ibr = null; // temporary branch instruction + for (int i = 0; i < numLabels; i++) { + int curPC = labels[i]; + // (Note: Passing ibr in allows reuse, a speed hack.) + ibr = Instruction.at(code.bytes, curPC, ibr); + if (ibr instanceof Instruction.Switch) { + Instruction.Switch isw = (Instruction.Switch) ibr; + isw.setDefaultLabel(getLabel(bc_label, code, curPC)); + int caseCount = isw.getCaseCount(); + for (int j = 0; j < caseCount; j++) { + isw.setCaseLabel(j, getLabel(bc_label, code, curPC)); + } + } else { + ibr.setBranchLabel(getLabel(bc_label, code, curPC)); + } + } + if (fixupBuf.size() > 0) { + if (verbose > 2) + Utils.log.fine("Fixups in code: "+fixupBuf); + code.addFixups(fixupBuf); + } + } + } +} diff --git a/openjdk/copyright.txt b/openjdk/copyright.txt new file mode 100644 index 0000000..fc1b7df --- /dev/null +++ b/openjdk/copyright.txt @@ -0,0 +1,24 @@ + "1988 AT&T\r\n" + + "2009-2014 Attila Szegedi\r\n" + + "1995 Colin Plumb\r\n" + + "1999-2014 Free Software Foundation\r\n" + + "2001-2005 freebxml.org\r\n" + + "1998 FundsXpress, INC.\r\n" + + "2009 Google Inc.\r\n" + + "2008-2013 i-net software\r\n" + + "2000-2013 INRIA, France Telecom\r\n" + + "1993-2013 International Business Machines, Inc.\r\n" + + "2002-2015 Jeroen Frijters\r\n" + + "1994-2015 Oracle and/or its affiliates\r\n" + + "2007 Red Hat, Inc.\r\n" + + "2007-2013 Stephen Colebourne & Michael Nascimento Santos\r\n" + + "1993-1997 Sun Microsystems, Inc.\r\n" + + "1996-1998 Taligent, Inc.\r\n" + + "2001-2002 Thai Open Source Software Center Ltd\r\n" + + "1999-2006 The Apache Software Foundation\r\n" + + "1995-2000 The Cryptix Foundation Limited\r\n" + + "1997 The Open Group Research Institute\r\n" + + "1991-2012 Unicode, Inc.\r\n" + + "1999 Visual Numerics Inc.\r\n" + + "2003 Wily Technology, Inc.\r\n" + + "2000-2004 World Wide Web Consortium" diff --git a/openjdk/dependencies.txt b/openjdk/dependencies.txt new file mode 100644 index 0000000..fe74d5f --- /dev/null +++ b/openjdk/dependencies.txt @@ -0,0 +1,151 @@ +# This file declares the dependencies of the OpenJDK assemblies. +# It exists to prevent accidentally introducing new dependencies. +# +# Note that mscorlib, System, IKVM.Runtime and IKVM.OpenJDK.Core are not very interesting, +# so these dependencies are ignored by the dependency checker. + +IKVM.OpenJDK.Core +->System.Core +->IKVM.OpenJDK.Util +->IKVM.OpenJDK.Security +->IKVM.OpenJDK.Text + +IKVM.OpenJDK.Corba +->IKVM.OpenJDK.Util +->IKVM.OpenJDK.SwingAWT +->IKVM.OpenJDK.Text +->IKVM.OpenJDK.Naming +->IKVM.OpenJDK.Remoting + +IKVM.OpenJDK.XML.API + +IKVM.OpenJDK.XML.XPath +->IKVM.OpenJDK.XML.API +->IKVM.OpenJDK.XML.Parse +->IKVM.OpenJDK.Text + +IKVM.OpenJDK.XML.Parse +->IKVM.OpenJDK.XML.API +->IKVM.OpenJDK.Text +->IKVM.OpenJDK.Beans +->IKVM.OpenJDK.Util + +IKVM.OpenJDK.XML.Transform +->IKVM.OpenJDK.Util +->IKVM.OpenJDK.XML.Parse +->IKVM.OpenJDK.XML.API +->IKVM.OpenJDK.Text +->IKVM.OpenJDK.XML.XPath + +IKVM.OpenJDK.XML.Bind +->IKVM.OpenJDK.XML.API +->IKVM.OpenJDK.Util +->IKVM.OpenJDK.Text +->IKVM.OpenJDK.SwingAWT +->IKVM.OpenJDK.Beans +->IKVM.OpenJDK.Media +->IKVM.OpenJDK.XML.Parse +->IKVM.OpenJDK.Misc + +IKVM.OpenJDK.XML.WebServices +->IKVM.OpenJDK.XML.API +->IKVM.OpenJDK.Text +->IKVM.OpenJDK.Util +->IKVM.OpenJDK.Misc +->IKVM.OpenJDK.SwingAWT +->IKVM.OpenJDK.XML.Parse +->IKVM.OpenJDK.XML.Bind +->IKVM.OpenJDK.Security +->IKVM.OpenJDK.Remoting +->IKVM.OpenJDK.Beans +->IKVM.OpenJDK.Media +->IKVM.OpenJDK.Management + +IKVM.OpenJDK.XML.Crypto +->IKVM.OpenJDK.Util +->IKVM.OpenJDK.XML.API +->IKVM.OpenJDK.Security +->IKVM.OpenJDK.Text +->IKVM.OpenJDK.XML.Parse +->IKVM.OpenJDK.XML.XPath + +IKVM.OpenJDK.SwingAWT +->System.Drawing +->IKVM.AWT.WinForms +->IKVM.OpenJDK.Util +->IKVM.OpenJDK.Text +->IKVM.OpenJDK.XML.API +->IKVM.OpenJDK.Charsets +->IKVM.OpenJDK.Beans +->IKVM.OpenJDK.Media +->IKVM.OpenJDK.Remoting + +IKVM.OpenJDK.Charsets + +IKVM.OpenJDK.Util +->IKVM.OpenJDK.Security +->IKVM.OpenJDK.Text +->IKVM.OpenJDK.XML.API + +IKVM.OpenJDK.Text +->IKVM.OpenJDK.Util + +IKVM.OpenJDK.Security +->IKVM.OpenJDK.Text +->IKVM.OpenJDK.SwingAWT +->IKVM.OpenJDK.Util +->IKVM.OpenJDK.Naming + +IKVM.OpenJDK.Management +->IKVM.OpenJDK.Security +->IKVM.OpenJDK.Corba +->IKVM.OpenJDK.Util +->IKVM.OpenJDK.Naming +->IKVM.OpenJDK.Remoting +->IKVM.OpenJDK.Beans +->IKVM.OpenJDK.Text + +IKVM.OpenJDK.Misc +->IKVM.OpenJDK.Util +->IKVM.OpenJDK.Text +->IKVM.OpenJDK.Security + +IKVM.OpenJDK.Jdbc +->System.Data +->IKVM.OpenJDK.Text +->IKVM.OpenJDK.XML.API +->IKVM.OpenJDK.Util +->IKVM.OpenJDK.Naming +->IKVM.OpenJDK.Corba + +IKVM.OpenJDK.Naming +->IKVM.OpenJDK.Security + +IKVM.OpenJDK.Remoting +->IKVM.OpenJDK.Naming +->IKVM.OpenJDK.Security +->IKVM.OpenJDK.Text +->IKVM.OpenJDK.Util + +IKVM.OpenJDK.Beans +->IKVM.OpenJDK.SwingAWT +->IKVM.OpenJDK.XML.API +->IKVM.OpenJDK.Util + +IKVM.OpenJDK.Media +->System.Drawing +->IKVM.OpenJDK.SwingAWT +->IKVM.OpenJDK.XML.API +->IKVM.OpenJDK.Util +->IKVM.OpenJDK.Text + +IKVM.OpenJDK.Nashorn +->IKVM.OpenJDK.Util +->IKVM.OpenJDK.Misc +->IKVM.OpenJDK.Text + +IKVM.OpenJDK.Localedata +->IKVM.OpenJDK.Util + +IKVM.OpenJDK.Cldrdata +->IKVM.OpenJDK.Util diff --git a/openjdk/exclude.lst b/openjdk/exclude.lst new file mode 100644 index 0000000..5388e59 --- /dev/null +++ b/openjdk/exclude.lst @@ -0,0 +1,6 @@ +^java\.lang\.AutoCloseable$ +^java\.lang\.Comparable$ +^java\.lang\.Object$ +^java\.lang\.String$ +^java\.lang\.Throwable$ +^sun\.reflect\.misc\.Trampoline$ diff --git a/openjdk/gnu/java/awt/Buffers.java b/openjdk/gnu/java/awt/Buffers.java new file mode 100644 index 0000000..2015634 --- /dev/null +++ b/openjdk/gnu/java/awt/Buffers.java @@ -0,0 +1,225 @@ +/* Buffers.java -- + Copyright (C) 2000, 2002, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.java.awt; + +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferDouble; +import java.awt.image.DataBufferFloat; +import java.awt.image.DataBufferInt; +import java.awt.image.DataBufferShort; +import java.awt.image.DataBufferUShort; + +/** + * Utility class for creating and accessing data buffers of arbitrary + * data types. + */ +public final class Buffers +{ + /** + * Create a data buffer of a particular type. + * + * @param dataType the desired data type of the buffer. + * @param data an array containing data, or null + * @param size the size of the data buffer bank + */ + public static DataBuffer createBuffer(int dataType, Object data, + int size) + { + if (data == null) return createBuffer(dataType, size, 1); + + return createBufferFromData(dataType, data, size); + } + + + /** + * Create a data buffer of a particular type. + * + * @param dataType the desired data type of the buffer. + * @param size the size of the data buffer bank + */ + public static DataBuffer createBuffer(int dataType, int size) { + return createBuffer(dataType, size, 1); + } + + /** + * Create a data buffer of a particular type. + * + * @param dataType the desired data type of the buffer. + * @param size the size of the data buffer bank + * @param numBanks the number of banks the buffer should have + */ + public static DataBuffer createBuffer(int dataType, int size, int numBanks) + { + switch (dataType) + { + case DataBuffer.TYPE_BYTE: + return new DataBufferByte(size, numBanks); + case DataBuffer.TYPE_SHORT: + return new DataBufferShort(size, numBanks); + case DataBuffer.TYPE_USHORT: + return new DataBufferUShort(size, numBanks); + case DataBuffer.TYPE_INT: + return new DataBufferInt(size, numBanks); + case DataBuffer.TYPE_FLOAT: + return new DataBufferFloat(size, numBanks); + case DataBuffer.TYPE_DOUBLE: + return new DataBufferDouble(size, numBanks); + default: + throw new UnsupportedOperationException(); + } + } + + /** + * Create a data buffer of a particular type. + * + * @param dataType the desired data type of the buffer + * @param data an array containing the data + * @param size the size of the data buffer bank + */ + public static DataBuffer createBufferFromData(int dataType, Object data, + int size) + { + switch (dataType) + { + case DataBuffer.TYPE_BYTE: + return new DataBufferByte((byte[]) data, size); + case DataBuffer.TYPE_SHORT: + return new DataBufferShort((short[]) data, size); + case DataBuffer.TYPE_USHORT: + return new DataBufferUShort((short[]) data, size); + case DataBuffer.TYPE_INT: + return new DataBufferInt((int[]) data, size); + case DataBuffer.TYPE_FLOAT: + return new DataBufferFloat((float[]) data, size); + case DataBuffer.TYPE_DOUBLE: + return new DataBufferDouble((double[]) data, size); + default: + throw new UnsupportedOperationException(); + } + } + + /** + * Return the data array of a data buffer, regardless of the data + * type. + * + * @return an array of primitive values. The actual array type + * depends on the data type of the buffer. + */ + public static Object getData(DataBuffer buffer) + { + return getData(buffer, 0, null, 0, buffer.getSize()); + } + + + /** + * Copy data from array contained in data buffer, much like + * System.arraycopy. Create a suitable destination array if the + * given destination array is null. + */ + public static Object getData(DataBuffer src, int srcOffset, + Object dest, int dstOffset, + int length) + { + Object from; + switch(src.getDataType()) + { + case DataBuffer.TYPE_BYTE: + if (dest == null) dest = new byte[length+dstOffset]; + for(int i = 0; i < length; i++) + ((byte[])dest)[i + dstOffset] = (byte)src.getElem(i + srcOffset); + break; + + case DataBuffer.TYPE_DOUBLE: + if (dest == null) dest = new double[length+dstOffset]; + for(int i = 0; i < length; i++) + ((double[])dest)[i + dstOffset] = src.getElemDouble(i + srcOffset); + break; + + case DataBuffer.TYPE_FLOAT: + if (dest == null) dest = new float[length+dstOffset]; + for(int i = 0; i < length; i++) + ((float[])dest)[i + dstOffset] = src.getElemFloat(i + srcOffset); + break; + + case DataBuffer.TYPE_INT: + if (dest == null) dest = new int[length+dstOffset]; + for(int i = 0; i < length; i++) + ((int[])dest)[i + dstOffset] = src.getElem(i + srcOffset); + break; + + case DataBuffer.TYPE_SHORT: + case DataBuffer.TYPE_USHORT: + if (dest == null) dest = new short[length+dstOffset]; + for(int i = 0; i < length; i++) + ((short[])dest)[i + dstOffset] = (short)src.getElem(i + srcOffset); + break; + + case DataBuffer.TYPE_UNDEFINED: + throw new ClassCastException("Unknown data buffer type"); + } + return dest; + } + + /** + * @param bits the width of a data element measured in bits + * + * @return the smallest data type that can store data elements of + * the given number of bits, without any truncation. + */ + public static int smallestAppropriateTransferType(int bits) + { + if (bits <= 8) + { + return DataBuffer.TYPE_BYTE; + } + else if (bits <= 16) + { + return DataBuffer.TYPE_USHORT; + } + else if (bits <= 32) + { + return DataBuffer.TYPE_INT; + } + else + { + return DataBuffer.TYPE_UNDEFINED; + } + } +} diff --git a/openjdk/gnu/java/awt/color/CieXyzConverter.java b/openjdk/gnu/java/awt/color/CieXyzConverter.java new file mode 100644 index 0000000..e1b548e --- /dev/null +++ b/openjdk/gnu/java/awt/color/CieXyzConverter.java @@ -0,0 +1,73 @@ +/* CieXyzConverter.java -- CieXyz conversion class + Copyright (C) 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.java.awt.color; + + +/** + * CieXyzConverter - converts to/from a D50-relative CIE XYZ color space. + * + * The sRGB<->CIE XYZ conversions in SrgbConverter are used. + * + * @author Sven de Marothy + */ +public class CieXyzConverter implements ColorSpaceConverter +{ + public float[] toCIEXYZ(float[] in) + { + float[] out = new float[3]; + System.arraycopy(in, 0, out, 0, 3); + return out; + } + + public float[] fromCIEXYZ(float[] in) + { + float[] out = new float[3]; + System.arraycopy(in, 0, out, 0, 3); + return out; + } + + public float[] toRGB(float[] in) + { + return SrgbConverter.XYZtoRGB(in); + } + + public float[] fromRGB(float[] in) + { + return SrgbConverter.RGBtoXYZ(in); + } +} diff --git a/openjdk/gnu/java/awt/color/ClutProfileConverter.java b/openjdk/gnu/java/awt/color/ClutProfileConverter.java new file mode 100644 index 0000000..5229ce8 --- /dev/null +++ b/openjdk/gnu/java/awt/color/ClutProfileConverter.java @@ -0,0 +1,152 @@ +/* ClutProfileConverter.java -- Conversion routines for CLUT-Based profiles + Copyright (C) 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.java.awt.color; + +import java.awt.color.ICC_Profile; + + +/** + * ClutProfileConverter - conversions through a CLUT-based profile + * + * @author Sven de Marothy + */ +public class ClutProfileConverter implements ColorSpaceConverter +{ + private ColorLookUpTable toPCS; + private ColorLookUpTable fromPCS; + private int nChannels; + + public ClutProfileConverter(ICC_Profile profile) + { + nChannels = profile.getNumComponents(); + + // Sun does not specifiy which rendering intent should be used, + // neither does the ICC v2 spec really. + // Try intent 0 + try + { + toPCS = new ColorLookUpTable(profile, ICC_Profile.icSigAToB0Tag); + } + catch (Exception e) + { + toPCS = null; + } + + try + { + fromPCS = new ColorLookUpTable(profile, ICC_Profile.icSigBToA0Tag); + } + catch (Exception e) + { + fromPCS = null; + } + + if (toPCS != null || fromPCS != null) + return; + + // If no intent 0 clut is available, look for a intent 1 clut. + try + { + toPCS = new ColorLookUpTable(profile, ICC_Profile.icSigAToB1Tag); + } + catch (Exception e) + { + toPCS = null; + } + + try + { + fromPCS = new ColorLookUpTable(profile, ICC_Profile.icSigBToA1Tag); + } + catch (Exception e) + { + fromPCS = null; + } + + if (toPCS != null || fromPCS != null) + return; + + // Last shot.. intent 2 CLUT. + try + { + toPCS = new ColorLookUpTable(profile, ICC_Profile.icSigAToB2Tag); + } + catch (Exception e) + { + toPCS = null; + } + + try + { + fromPCS = new ColorLookUpTable(profile, ICC_Profile.icSigBToA2Tag); + } + catch (Exception e) + { + fromPCS = null; + } + + if (toPCS == null && fromPCS == null) + throw new IllegalArgumentException("No CLUTs in profile!"); + } + + public float[] toCIEXYZ(float[] in) + { + if (toPCS != null) + return toPCS.lookup(in); + else + return new float[3]; + } + + public float[] toRGB(float[] in) + { + return SrgbConverter.XYZtoRGB(toCIEXYZ(in)); + } + + public float[] fromCIEXYZ(float[] in) + { + if (fromPCS != null) + return fromPCS.lookup(in); + else + return new float[nChannels]; + } + + public float[] fromRGB(float[] in) + { + return fromCIEXYZ(SrgbConverter.RGBtoXYZ(in)); + } +} diff --git a/openjdk/gnu/java/awt/color/ColorLookUpTable.java b/openjdk/gnu/java/awt/color/ColorLookUpTable.java new file mode 100644 index 0000000..581320c --- /dev/null +++ b/openjdk/gnu/java/awt/color/ColorLookUpTable.java @@ -0,0 +1,429 @@ +/* ColorLookUpTable.java -- ICC v2 CLUT + Copyright (C) 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.java.awt.color; + +import java.awt.color.ColorSpace; +import java.awt.color.ICC_Profile; +import java.nio.ByteBuffer; + + +/** + * ColorLookUpTable handles color lookups through a color lookup table, + * as defined in the ICC specification. + * Both 'mft2' and 'mft1' (8 and 16-bit) type CLUTs are handled. + * + * This will have to be updated later for ICC 4.0.0 + * + * @author Sven de Marothy + */ +public class ColorLookUpTable +{ + /** + * CIE 1931 D50 white point (in Lab coordinates) + */ + private static float[] D50 = { 0.96422f, 1.00f, 0.82521f }; + + /** + * Number of input/output channels + */ + int nIn; + + /** + * Number of input/output channels + */ + int nOut; + int nInTableEntries; // Number of input table entries + int nOutTableEntries; // Number of output table entries + int gridpoints; // Number of gridpoints + int nClut; // This is nOut*(gridpoints**nIn) + double[][] inTable; // 1D input table ([channel][table]) + short[][] outTable; // 1D input table ([channel][table]) + double[] clut; // The color lookup table + float[][] inMatrix; // input matrix (XYZ only) + boolean useMatrix; // Whether to use the matrix or not. + int[] multiplier; + int[] offsets; // Hypercube offsets + boolean inputLab; // Set if the CLUT input CS is Lab + boolean outputLab; // Set if the CLUT output CS is Lab + + /** + * Constructor + * Requires a profile file to get the CLUT from and the tag of the + * CLUT to create. (icSigXToYZTag where X,Y = [A | B], Z = [0,1,2]) + */ + public ColorLookUpTable(ICC_Profile profile, int tag) + { + useMatrix = false; + + switch (tag) + { + case ICC_Profile.icSigAToB0Tag: + case ICC_Profile.icSigAToB1Tag: + case ICC_Profile.icSigAToB2Tag: + if (profile.getColorSpaceType() == ColorSpace.TYPE_XYZ) + useMatrix = true; + inputLab = false; + outputLab = (profile.getPCSType() == ColorSpace.TYPE_Lab); + break; + case ICC_Profile.icSigBToA0Tag: + case ICC_Profile.icSigBToA1Tag: + case ICC_Profile.icSigBToA2Tag: + if (profile.getPCSType() == ColorSpace.TYPE_XYZ) + useMatrix = true; + inputLab = (profile.getPCSType() == ColorSpace.TYPE_Lab); + outputLab = false; + break; + default: + throw new IllegalArgumentException("Not a clut-type tag."); + } + + byte[] data = profile.getData(tag); + if (data == null) + throw new IllegalArgumentException("Unsuitable profile, does not contain a CLUT."); + + // check 'mft' + if (data[0] != 0x6d || data[1] != 0x66 || data[2] != 0x74) + throw new IllegalArgumentException("Unsuitable profile, invalid CLUT data."); + + if (data[3] == 0x32) + readClut16(data); + else if (data[3] == 0x31) + readClut8(data); + else + throw new IllegalArgumentException("Unknown/invalid CLUT type."); + } + + /** + * Loads a 16-bit CLUT into our data structures + */ + private void readClut16(byte[] data) + { + ByteBuffer buf = ByteBuffer.wrap(data); + + nIn = data[8] & (0xFF); + nOut = data[9] & (0xFF); + nInTableEntries = buf.getShort(48); + nOutTableEntries = buf.getShort(50); + gridpoints = data[10] & (0xFF); + + inMatrix = new float[3][3]; + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + inMatrix[i][j] = ((float) (buf.getInt(12 + (i * 3 + j) * 4))) / 65536.0f; + + inTable = new double[nIn][nInTableEntries]; + for (int channel = 0; channel < nIn; channel++) + for (int i = 0; i < nInTableEntries; i++) + inTable[channel][i] = (double) ((int) buf.getShort(52 + + (channel * nInTableEntries + + i) * 2) + & (0xFFFF)) / 65536.0; + + nClut = nOut; + multiplier = new int[nIn]; + multiplier[nIn - 1] = nOut; + for (int i = 0; i < nIn; i++) + { + nClut *= gridpoints; + if (i > 0) + multiplier[nIn - i - 1] = multiplier[nIn - i] * gridpoints; + } + + int clutOffset = 52 + nIn * nInTableEntries * 2; + clut = new double[nClut]; + for (int i = 0; i < nClut; i++) + clut[i] = (double) ((int) buf.getShort(clutOffset + i * 2) & (0xFFFF)) / 65536.0; + + outTable = new short[nOut][nOutTableEntries]; + for (int channel = 0; channel < nOut; channel++) + for (int i = 0; i < nOutTableEntries; i++) + outTable[channel][i] = buf.getShort(clutOffset + + (nClut + + channel * nOutTableEntries + i) * 2); + + // calculate the hypercube corner offsets + offsets = new int[(1 << nIn)]; + offsets[0] = 0; + for (int j = 0; j < nIn; j++) + { + int factor = 1 << j; + for (int i = 0; i < factor; i++) + offsets[factor + i] = offsets[i] + multiplier[j]; + } + } + + /** + * Loads a 8-bit CLUT into our data structures. + */ + private void readClut8(byte[] data) + { + ByteBuffer buf = ByteBuffer.wrap(data); + + nIn = (data[8] & (0xFF)); + nOut = (data[9] & (0xFF)); + nInTableEntries = 256; // always 256 + nOutTableEntries = 256; // always 256 + gridpoints = (data[10] & (0xFF)); + + inMatrix = new float[3][3]; + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + inMatrix[i][j] = ((float) (buf.getInt(12 + (i * 3 + j) * 4))) / 65536.0f; + + inTable = new double[nIn][nInTableEntries]; + for (int channel = 0; channel < nIn; channel++) + for (int i = 0; i < nInTableEntries; i++) + inTable[channel][i] = (double) ((int) buf.get(48 + + (channel * nInTableEntries + + i)) & (0xFF)) / 255.0; + + nClut = nOut; + multiplier = new int[nIn]; + multiplier[nIn - 1] = nOut; + for (int i = 0; i < nIn; i++) + { + nClut *= gridpoints; + if (i > 0) + multiplier[nIn - i - 1] = multiplier[nIn - i] * gridpoints; + } + + int clutOffset = 48 + nIn * nInTableEntries; + clut = new double[nClut]; + for (int i = 0; i < nClut; i++) + clut[i] = (double) ((int) buf.get(clutOffset + i) & (0xFF)) / 255.0; + + outTable = new short[nOut][nOutTableEntries]; + for (int channel = 0; channel < nOut; channel++) + for (int i = 0; i < nOutTableEntries; i++) + outTable[channel][i] = (short) (buf.get(clutOffset + nClut + + channel * nOutTableEntries + + i) * 257); + + // calculate the hypercube corner offsets + offsets = new int[(1 << nIn)]; + offsets[0] = 0; + for (int j = 0; j < nIn; j++) + { + int factor = 1 << j; + for (int i = 0; i < factor; i++) + offsets[factor + i] = offsets[i] + multiplier[j]; + } + } + + /** + * Performs a lookup through the Color LookUp Table. + * If the CLUT tag type is AtoB the conversion will be from the device + * color space to the PCS, BtoA type goes in the opposite direction. + * + * For convenience, the PCS values for input or output will always be + * CIE XYZ (D50), if the actual PCS is Lab, the values will be converted. + * + * N-dimensional linear interpolation is used. + */ + float[] lookup(float[] in) + { + float[] in2 = new float[in.length]; + if (useMatrix) + { + for (int i = 0; i < 3; i++) + in2[i] = in[0] * inMatrix[i][0] + in[1] * inMatrix[i][1] + + in[2] * inMatrix[i][2]; + } + else if (inputLab) + in2 = XYZtoLab(in); + else + System.arraycopy(in, 0, in2, 0, in.length); + + // input table + for (int i = 0; i < nIn; i++) + { + int index = (int) Math.floor(in2[i] * (double) (nInTableEntries - 1)); // floor in + + // clip values. + if (index >= nInTableEntries - 1) + in2[i] = (float) inTable[i][nInTableEntries - 1]; + else if (index < 0) + in2[i] = (float) inTable[i][0]; + else + { + // linear interpolation + double alpha = in2[i] * ((double) nInTableEntries - 1.0) - index; + in2[i] = (float) (inTable[i][index] * (1 - alpha) + + inTable[i][index + 1] * alpha); + } + } + + // CLUT lookup + double[] output2 = new double[nOut]; + double[] weights = new double[(1 << nIn)]; + double[] clutalpha = new double[nIn]; // interpolation values + int offset = 0; // = gp + for (int i = 0; i < nIn; i++) + { + int index = (int) Math.floor(in2[i] * ((double) gridpoints - 1.0)); + double alpha = in2[i] * ((double) gridpoints - 1.0) - (double) index; + + // clip values. + if (index >= gridpoints - 1) + { + index = gridpoints - 1; + alpha = 1.0; + } + else if (index < 0) + index = 0; + clutalpha[i] = alpha; + offset += index * multiplier[i]; + } + + // Calculate interpolation weights + weights[0] = 1.0; + for (int j = 0; j < nIn; j++) + { + int factor = 1 << j; + for (int i = 0; i < factor; i++) + { + weights[factor + i] = weights[i] * clutalpha[j]; + weights[i] *= (1.0 - clutalpha[j]); + } + } + + for (int i = 0; i < nOut; i++) + output2[i] = weights[0] * clut[offset + i]; + + for (int i = 1; i < (1 << nIn); i++) + { + int offset2 = offset + offsets[i]; + for (int f = 0; f < nOut; f++) + output2[f] += weights[i] * clut[offset2 + f]; + } + + // output table + float[] output = new float[nOut]; + for (int i = 0; i < nOut; i++) + { + int index = (int) Math.floor(output2[i] * ((double) nOutTableEntries + - 1.0)); + + // clip values. + if (index >= nOutTableEntries - 1) + output[i] = outTable[i][nOutTableEntries - 1]; + else if (index < 0) + output[i] = outTable[i][0]; + else + { + // linear interpolation + double a = output2[i] * ((double) nOutTableEntries - 1.0) + - (double) index; + output[i] = (float) ((double) ((int) outTable[i][index] & (0xFFFF)) * (1 + - a) + + (double) ((int) outTable[i][index + 1] & (0xFFFF)) * a) / 65536f; + } + } + + if (outputLab) + return LabtoXYZ(output); + return output; + } + + /** + * Converts CIE Lab coordinates to (D50) XYZ ones. + */ + private float[] LabtoXYZ(float[] in) + { + // Convert from byte-packed format to a + // more convenient one (actual Lab values) + // (See ICC spec for details) + // factor is 100 * 65536 / 65280 + in[0] = (float) (100.392156862745 * in[0]); + in[1] = (in[1] * 256.0f) - 128.0f; + in[2] = (in[2] * 256.0f) - 128.0f; + + float[] out = new float[3]; + + out[1] = (in[0] + 16.0f) / 116.0f; + out[0] = in[1] / 500.0f + out[1]; + out[2] = out[1] - in[2] / 200.0f; + + for (int i = 0; i < 3; i++) + { + double exp = out[i] * out[i] * out[i]; + if (exp <= 0.008856) + out[i] = (out[i] - 16.0f / 116.0f) / 7.787f; + else + out[i] = (float) exp; + out[i] = D50[i] * out[i]; + } + return out; + } + + /** + * Converts CIE XYZ coordinates to Lab ones. + */ + private float[] XYZtoLab(float[] in) + { + float[] temp = new float[3]; + + for (int i = 0; i < 3; i++) + { + temp[i] = in[i] / D50[i]; + + if (temp[i] <= 0.008856f) + temp[i] = (7.7870689f * temp[i]) + (16f / 116.0f); + else + temp[i] = (float) Math.exp((1.0 / 3.0) * Math.log(temp[i])); + } + + float[] out = new float[3]; + out[0] = (116.0f * temp[1]) - 16f; + out[1] = 500.0f * (temp[0] - temp[1]); + out[2] = 200.0f * (temp[1] - temp[2]); + + // Normalize to packed format + out[0] = (float) (out[0] / 100.392156862745); + out[1] = (out[1] + 128f) / 256f; + out[2] = (out[2] + 128f) / 256f; + for (int i = 0; i < 3; i++) + { + if (out[i] < 0f) + out[i] = 0f; + if (out[i] > 1f) + out[i] = 1f; + } + return out; + } +} diff --git a/openjdk/gnu/java/awt/color/ColorSpaceConverter.java b/openjdk/gnu/java/awt/color/ColorSpaceConverter.java new file mode 100644 index 0000000..63ba08a --- /dev/null +++ b/openjdk/gnu/java/awt/color/ColorSpaceConverter.java @@ -0,0 +1,69 @@ +/* ColorSpaceConverter.java -- an interface for colorspace conversion + Copyright (C) 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.java.awt.color; + + +/** + * ColorSpaceConverter - used by java.awt.color.ICC_ColorSpace + * + * Color space conversion can occur in several ways: + * + * -Directly (for the built in spaces sRGB, linear RGB, gray, CIE XYZ and PYCC + * -ICC_ProfileRGB works through TRC curves and a matrix + * -ICC_ProfileGray works through a single TRC + * -Everything else is done through Color lookup tables. + * + * The different conversion methods are implemented through + * an interface. The built-in colorspaces are implemented directly + * with the relevant conversion equations. + * + * In this way, we hopefully will always use the fastest and most + * accurate method available. + * + * @author Sven de Marothy + */ +public interface ColorSpaceConverter +{ + float[] toCIEXYZ(float[] in); + + float[] fromCIEXYZ(float[] in); + + float[] toRGB(float[] in); + + float[] fromRGB(float[] in); +} diff --git a/openjdk/gnu/java/awt/color/GrayProfileConverter.java b/openjdk/gnu/java/awt/color/GrayProfileConverter.java new file mode 100644 index 0000000..3f95b07 --- /dev/null +++ b/openjdk/gnu/java/awt/color/GrayProfileConverter.java @@ -0,0 +1,137 @@ +/* GrayProfileConverter.java -- Gray profile conversion class + Copyright (C) 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.java.awt.color; + +import java.awt.color.ICC_Profile; +import java.awt.color.ICC_ProfileGray; +import java.awt.color.ProfileDataException; + +/** + * GrayProfileConverter - converts Grayscale profiles (ICC_ProfileGray) + * + * This type of profile contains a single tone reproduction curve (TRC). + * Conversion consists of simple TRC lookup. + * + * This implementation is very lazy and does everything applying the TRC and + * utilizing the built-in linear grayscale color space. + * + * @author Sven de Marothy + */ +public class GrayProfileConverter implements ColorSpaceConverter +{ + private GrayScaleConverter gc; + private ToneReproductionCurve trc; + private ColorLookUpTable toPCS; + private ColorLookUpTable fromPCS; + + /** + * Constructs the converter described by an ICC_ProfileGray object + */ + public GrayProfileConverter(ICC_ProfileGray profile) + { + try + { + trc = new ToneReproductionCurve(profile.getGamma()); + } + catch (ProfileDataException e) + { + trc = new ToneReproductionCurve(profile.getTRC()); + } + + // linear grayscale converter + gc = new GrayScaleConverter(); + + // If a CLUT is available, it should be used, and the TRCs ignored. + // Note: A valid profile may only have CLUTs in one direction, and + // TRC:s without useful info, making reverse-transforms impossible. + // In this case the TRC will be used for the reverse-transform with + // unpredictable results. This is in line with the Java specification, + try + { + toPCS = new ColorLookUpTable(profile, ICC_Profile.icSigAToB0Tag); + } + catch (Exception e) + { + toPCS = null; + } + + try + { + fromPCS = new ColorLookUpTable(profile, ICC_Profile.icSigBToA0Tag); + } + catch (Exception e) + { + fromPCS = null; + } + } + + public float[] toCIEXYZ(float[] in) + { + if (toPCS != null) + return toPCS.lookup(in); + float[] gray = new float[1]; + gray[0] = trc.lookup(in[0]); + return gc.toCIEXYZ(gray); + } + + public float[] toRGB(float[] in) + { + float[] gray = new float[1]; + gray[0] = trc.lookup(in[0]); + return gc.toRGB(gray); + } + + public float[] fromRGB(float[] in) + { + // get linear grayscale value + float[] gray = gc.fromRGB(in); + gray[0] = trc.reverseLookup(gray[0]); + return gray; + } + + public float[] fromCIEXYZ(float[] in) + { + if (fromPCS != null) + return fromPCS.lookup(in); + + float[] gray = gc.fromCIEXYZ(in); + gray[0] = trc.reverseLookup(gray[0]); + return gray; + } +} diff --git a/openjdk/gnu/java/awt/color/GrayScaleConverter.java b/openjdk/gnu/java/awt/color/GrayScaleConverter.java new file mode 100644 index 0000000..1466d4e --- /dev/null +++ b/openjdk/gnu/java/awt/color/GrayScaleConverter.java @@ -0,0 +1,110 @@ +/* GrayScaleConverter.java -- Linear grayscale conversion class + Copyright (C) 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.java.awt.color; + + +/** + * Linear Grayscale converter + * + * @author Sven de Marothy + */ +public class GrayScaleConverter implements ColorSpaceConverter +{ + // intensity factors (ITU Rec. BT.709) + double[] coeff = { 0.2125f, 0.7154f, 0.0721f }; + + /** + * CIE 1931 D50 white point (in Lab coordinates) + */ + private static float[] D50 = { 0.96422f, 1.00f, 0.82521f }; + + public float[] toCIEXYZ(float[] in) + { + float g = in[0]; + if (g < 0) + g = 1 + g; + float[] out = { g * D50[0], g * D50[1], g * D50[2] }; // White spot + return out; + } + + public float[] toRGB(float[] in) + { + float[] out = new float[3]; + if (in[0] <= 0.00304f) + out[0] = in[0] * 12.92f; + else + out[0] = 1.055f * ((float) Math.exp((1 / 2.4) * Math.log(in[0]))) + - 0.055f; + out[1] = out[2] = out[0]; + return out; + } + + public float[] fromCIEXYZ(float[] in) + { + float[] temp = new float[3]; + temp[0] = 3.1338f * in[0] - 1.6171f * in[1] - 0.4907f * in[2]; + temp[1] = -0.9785f * in[0] + 1.9160f * in[1] + 0.0334f * in[2]; + temp[2] = 0.0720f * in[0] - 0.2290f * in[1] + 1.4056f * in[2]; + float[] out = new float[1]; + for (int i = 0; i < 3; i++) + out[0] += (float) (temp[i] * coeff[i]); + return out; + } + + public float[] fromRGB(float[] in) + { + float[] out = new float[1]; + + // Convert non-linear RGB coordinates to linear ones, + // numbers from the w3 spec. + out[0] = 0; + for (int i = 0; i < 3; i++) + { + float n = in[i]; + if (n < 0) + n = 0f; + if (n > 1) + n = 1f; + if (n <= 0.03928f) + out[0] += (float) (coeff[i] * n / 12.92); + else + out[0] += (float) (coeff[i] * Math.exp(2.4 * Math.log((n + 0.055) / 1.055))); + } + return out; + } +} diff --git a/openjdk/gnu/java/awt/color/ProfileHeader.java b/openjdk/gnu/java/awt/color/ProfileHeader.java new file mode 100644 index 0000000..2a6402d --- /dev/null +++ b/openjdk/gnu/java/awt/color/ProfileHeader.java @@ -0,0 +1,398 @@ +/* ProfileHeader.java -- Encapsules ICC Profile header data + Copyright (C) 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.java.awt.color; + +import java.awt.color.ColorSpace; +import java.awt.color.ICC_Profile; +import java.nio.ByteBuffer; + + +/** + * Header, abstracts and validates the header data. + * + * @author Sven de Marothy + */ +public class ProfileHeader +{ + /** + * Magic identifier (ASCII 'acsp') + */ + private static final int icMagicNumber = 0x61637370; + + /** + * Mapping from ICC Profile signatures to ColorSpace types + */ + private static final int[] csTypeMap = + { + ICC_Profile.icSigXYZData, + ColorSpace.TYPE_XYZ, + ICC_Profile.icSigLabData, + ColorSpace.TYPE_Lab, + ICC_Profile.icSigLuvData, + ColorSpace.TYPE_Luv, + ICC_Profile.icSigYCbCrData, + ColorSpace.TYPE_YCbCr, + ICC_Profile.icSigYxyData, + ColorSpace.TYPE_Yxy, + ICC_Profile.icSigRgbData, + ColorSpace.TYPE_RGB, + ICC_Profile.icSigGrayData, + ColorSpace.TYPE_GRAY, + ICC_Profile.icSigHsvData, + ColorSpace.TYPE_HSV, + ICC_Profile.icSigHlsData, + ColorSpace.TYPE_HLS, + ICC_Profile.icSigCmykData, + ColorSpace.TYPE_CMYK, + ICC_Profile.icSigCmyData, + ColorSpace.TYPE_CMY, + ICC_Profile.icSigSpace2CLR, + ColorSpace.TYPE_2CLR, + ICC_Profile.icSigSpace3CLR, + ColorSpace.TYPE_3CLR, + ICC_Profile.icSigSpace4CLR, + ColorSpace.TYPE_4CLR, + ICC_Profile.icSigSpace5CLR, + ColorSpace.TYPE_5CLR, + ICC_Profile.icSigSpace6CLR, + ColorSpace.TYPE_6CLR, + ICC_Profile.icSigSpace7CLR, + ColorSpace.TYPE_7CLR, + ICC_Profile.icSigSpace8CLR, + ColorSpace.TYPE_8CLR, + ICC_Profile.icSigSpace9CLR, + ColorSpace.TYPE_9CLR, + ICC_Profile.icSigSpaceACLR, + ColorSpace.TYPE_ACLR, + ICC_Profile.icSigSpaceBCLR, + ColorSpace.TYPE_BCLR, + ICC_Profile.icSigSpaceCCLR, + ColorSpace.TYPE_CCLR, + ICC_Profile.icSigSpaceDCLR, + ColorSpace.TYPE_DCLR, + ICC_Profile.icSigSpaceECLR, + ColorSpace.TYPE_ECLR, + ICC_Profile.icSigSpaceFCLR, + ColorSpace.TYPE_FCLR + }; + + /** + * Size of an ICC header (128 bytes) + */ + public static final int HEADERSIZE = 128; + + /** + * Mapping of ICC class signatures to profile class constants + */ + private static final int[] classMap = + { + ICC_Profile.icSigInputClass, + ICC_Profile.CLASS_INPUT, + ICC_Profile.icSigDisplayClass, + ICC_Profile.CLASS_DISPLAY, + ICC_Profile.icSigOutputClass, + ICC_Profile.CLASS_OUTPUT, + ICC_Profile.icSigLinkClass, + ICC_Profile.CLASS_DEVICELINK, + ICC_Profile.icSigColorSpaceClass, + ICC_Profile.CLASS_COLORSPACECONVERSION, + ICC_Profile.icSigAbstractClass, + ICC_Profile.CLASS_ABSTRACT, + ICC_Profile.icSigNamedColorClass, + ICC_Profile.CLASS_NAMEDCOLOR + }; + private int size; + private int cmmId; + + // Major/Minor version, The ICC-1998 spec is major v2 + private int majorVersion; + + // Major/Minor version, The ICC-1998 spec is major v2 + private int minorVersion; + private int profileClass; // profile device class + private int colorSpace; // data color space type + private int profileColorSpace; // profile connection space (PCS) type + private byte[] timestamp; // original creation timestamp + private int platform; // platform signature + private int flags; // flags + private int magic; // magic number. + private int manufacturerSig; // manufacturer sig + private int modelSig; // model sig + private byte[] attributes; // Attributes + private int intent; // rendering intent + private byte[] illuminant; // illuminant info (Coordinates of D50 in the PCS) + private int creatorSig; // Creator sig (same type as manufacturer) + + /** + * Creates a 'default' header for use with our predefined profiles. + * Note the device and profile color spaces are not set. + */ + public ProfileHeader() + { + creatorSig = 0; + intent = 0; + modelSig = manufacturerSig = (int) 0x6E6f6E65; // 'none' + magic = icMagicNumber; + cmmId = 0; + platform = 0; // no preferred platform + timestamp = new byte[8]; + majorVersion = 2; + minorVersion = 0x10; + flags = 0; + + // D50 in XYZ format (encoded) + illuminant = new byte[] + { + (byte) 0x00, (byte) 0x00, (byte) 0xf6, (byte) 0xd6, + (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0xd3, (byte) 0x2d + }; + attributes = new byte[8]; + profileClass = ICC_Profile.CLASS_DISPLAY; + } + + /** + * Creates a header from profile data. Only the header portion (128 bytes) + * is read, so the array passed need not be the full profile. + */ + public ProfileHeader(byte[] data) + { + ByteBuffer buf = ByteBuffer.wrap(data); + + // Get size (the sign bit shouldn't matter. + // A valid profile can never be +2Gb) + size = buf.getInt(ICC_Profile.icHdrSize); + + // CMM ID + cmmId = buf.getInt(ICC_Profile.icHdrCmmId); + + // Version number + majorVersion = (int) (data[ICC_Profile.icHdrVersion]); + minorVersion = (int) (data[ICC_Profile.icHdrVersion + 1]); + + // Profile/Device class + int classSig = buf.getInt(ICC_Profile.icHdrDeviceClass); + profileClass = -1; + for (int i = 0; i < classMap.length; i += 2) + if (classMap[i] == classSig) + { + profileClass = classMap[i + 1]; + break; + } + + // get the data color space + int csSig = buf.getInt(ICC_Profile.icHdrColorSpace); + colorSpace = -1; + for (int i = 0; i < csTypeMap.length; i += 2) + if (csTypeMap[i] == csSig) + { + colorSpace = csTypeMap[i + 1]; + break; + } + + // get the profile color space (PCS), must be xyz or lab except + // for device-link-class profiles + int pcsSig = buf.getInt(ICC_Profile.icHdrPcs); + profileColorSpace = -1; + if (profileClass != ICC_Profile.CLASS_DEVICELINK) + { + if (pcsSig == ICC_Profile.icSigXYZData) + profileColorSpace = ColorSpace.TYPE_XYZ; + if (pcsSig == ICC_Profile.icSigLabData) + profileColorSpace = ColorSpace.TYPE_Lab; + } + else + { + for (int i = 0; i < csTypeMap.length; i += 2) + if (csTypeMap[i] == pcsSig) + { + profileColorSpace = csTypeMap[i + 1]; + break; + } + } + + // creation timestamp + timestamp = new byte[8]; + System.arraycopy(data, ICC_Profile.icHdrDate, timestamp, 0, 8); + + // magic number + magic = buf.getInt(ICC_Profile.icHdrMagic); + + // platform info + platform = buf.getInt(ICC_Profile.icHdrPlatform); + // get flags + flags = buf.getInt(ICC_Profile.icHdrFlags); + // get manufacturer sign + manufacturerSig = buf.getInt(ICC_Profile.icHdrManufacturer); + // get header model + modelSig = buf.getInt(ICC_Profile.icHdrModel); + // attributes + attributes = new byte[8]; + System.arraycopy(data, ICC_Profile.icHdrAttributes, attributes, 0, 8); + // rendering intent + intent = buf.getInt(ICC_Profile.icHdrRenderingIntent); + // illuminant info + illuminant = new byte[12]; + System.arraycopy(data, ICC_Profile.icHdrIlluminant, illuminant, 0, 12); + // Creator signature + creatorSig = buf.getInt(ICC_Profile.icHdrCreator); + // The rest of the header (Total size: 128 bytes) is unused.. + } + + /** + * Verify that the header is valid + * @param size equals the file size if it is to be verified, -1 otherwise + * @throws IllegalArgumentException if the header is found to be invalid. + */ + public void verifyHeader(int size) throws IllegalArgumentException + { + // verify size + if (size != -1 && this.size != size) + throw new IllegalArgumentException("Invalid profile length:" + size); + + // Check version number + if (majorVersion != 2) + throw new IllegalArgumentException("Wrong major version number:" + + majorVersion); + + // Profile/Device class + if (profileClass == -1) + throw new IllegalArgumentException("Invalid profile/device class"); + + // get the data color space + if (colorSpace == -1) + throw new IllegalArgumentException("Invalid colorspace"); + + // profile color space + if (profileColorSpace == -1) + throw new IllegalArgumentException("Invalid PCS."); + + // check magic number + if (magic != icMagicNumber) + throw new IllegalArgumentException("Invalid magic number!"); + } + + /** + * Creates a header, setting the header file size at the same time. + * @param size the profile file size. + */ + public byte[] getData(int size) + { + byte[] data = new byte[HEADERSIZE]; + ByteBuffer buf = ByteBuffer.wrap(data); + buf.putInt(ICC_Profile.icHdrSize, size); + buf.putInt(ICC_Profile.icHdrCmmId, cmmId); + buf.putShort(ICC_Profile.icHdrVersion, + (short) (majorVersion << 8 | minorVersion)); + for (int i = 1; i < classMap.length; i += 2) + if (profileClass == classMap[i]) + buf.putInt(ICC_Profile.icHdrDeviceClass, classMap[i - 1]); + for (int i = 1; i < csTypeMap.length; i += 2) + if (csTypeMap[i] == colorSpace) + buf.putInt(ICC_Profile.icHdrColorSpace, csTypeMap[i - 1]); + for (int i = 1; i < csTypeMap.length; i += 2) + if (csTypeMap[i] == profileColorSpace) + buf.putInt(ICC_Profile.icHdrPcs, csTypeMap[i - 1]); + + System.arraycopy(timestamp, 0, data, ICC_Profile.icHdrDate, + timestamp.length); + buf.putInt(ICC_Profile.icHdrMagic, icMagicNumber); + buf.putInt(ICC_Profile.icHdrPlatform, platform); + buf.putInt(ICC_Profile.icHdrFlags, flags); + buf.putInt(ICC_Profile.icHdrManufacturer, manufacturerSig); + buf.putInt(ICC_Profile.icHdrModel, modelSig); + System.arraycopy(attributes, 0, data, ICC_Profile.icHdrAttributes, + attributes.length); + buf.putInt(ICC_Profile.icHdrRenderingIntent, intent); + System.arraycopy(illuminant, 0, data, ICC_Profile.icHdrIlluminant, + illuminant.length); + buf.putInt(ICC_Profile.icHdrCreator, creatorSig); + return buf.array(); + } + + public int getSize() + { + return size; + } + + public void setSize(int s) + { + size = s; + } + + public int getMajorVersion() + { + return majorVersion; + } + + public int getMinorVersion() + { + return minorVersion; + } + + public int getProfileClass() + { + return profileClass; + } + + public void setProfileClass(int pc) + { + profileClass = pc; + } + + public int getColorSpace() + { + return colorSpace; + } + + public int getProfileColorSpace() + { + return profileColorSpace; + } + + public void setColorSpace(int cs) + { + colorSpace = cs; + } + + public void setProfileColorSpace(int pcs) + { + profileColorSpace = pcs; + } + +} diff --git a/openjdk/gnu/java/awt/color/RgbProfileConverter.java b/openjdk/gnu/java/awt/color/RgbProfileConverter.java new file mode 100644 index 0000000..7623890 --- /dev/null +++ b/openjdk/gnu/java/awt/color/RgbProfileConverter.java @@ -0,0 +1,244 @@ +/* RgbProfileConverter.java -- RGB Profile conversion class + Copyright (C) 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.java.awt.color; + +import java.awt.color.ICC_Profile; +import java.awt.color.ICC_ProfileRGB; +import java.awt.color.ProfileDataException; + +/** + * RgbProfileConverter - converts RGB profiles (ICC_ProfileRGB) + * + * This type of profile contains a matrix and three + * tone reproduction curves (TRCs). + * + * Device RGB --> CIE XYZ is done through first multiplying with + * a matrix, then each component is looked-up against it's TRC. + * + * The opposite transform is done using the inverse of the matrix, + * and TRC:s. + * + * @author Sven de Marothy + */ +public class RgbProfileConverter implements ColorSpaceConverter +{ + private float[][] matrix; + private float[][] inv_matrix; + private ToneReproductionCurve rTRC; + private ToneReproductionCurve gTRC; + private ToneReproductionCurve bTRC; + private ColorLookUpTable toPCS; + private ColorLookUpTable fromPCS; + + /** + * CIE 1931 D50 white point (in Lab coordinates) + */ + private static float[] D50 = { 0.96422f, 1.00f, 0.82521f }; + + /** + * Constructs an RgbProfileConverter from a given ICC_ProfileRGB + */ + public RgbProfileConverter(ICC_ProfileRGB profile) + { + toPCS = fromPCS = null; + matrix = profile.getMatrix(); + + // get TRCs + try + { + rTRC = new ToneReproductionCurve(profile.getGamma(ICC_ProfileRGB.REDCOMPONENT)); + } + catch (ProfileDataException e) + { + rTRC = new ToneReproductionCurve(profile.getTRC(ICC_ProfileRGB.REDCOMPONENT)); + } + try + { + gTRC = new ToneReproductionCurve(profile.getGamma(ICC_ProfileRGB.GREENCOMPONENT)); + } + catch (ProfileDataException e) + { + gTRC = new ToneReproductionCurve(profile.getTRC(ICC_ProfileRGB.GREENCOMPONENT)); + } + try + { + bTRC = new ToneReproductionCurve(profile.getGamma(ICC_ProfileRGB.BLUECOMPONENT)); + } + catch (ProfileDataException e) + { + bTRC = new ToneReproductionCurve(profile.getTRC(ICC_ProfileRGB.BLUECOMPONENT)); + } + + // If a CLUT is available, it should be used, and the TRCs ignored. + // Note: A valid profile may only have CLUTs in one direction, and + // TRC:s without useful info, making reverse-transforms impossible. + // In this case the TRC will be used for the reverse-transform with + // unpredictable results. This is in line with the Java specification, + try + { + toPCS = new ColorLookUpTable(profile, ICC_Profile.icSigAToB0Tag); + } + catch (Exception e) + { + toPCS = null; + } + + try + { + fromPCS = new ColorLookUpTable(profile, ICC_Profile.icSigBToA0Tag); + } + catch (Exception e) + { + fromPCS = null; + } + + // Calculate the inverse matrix if no reverse CLUT is available + if(fromPCS == null) + inv_matrix = invertMatrix(matrix); + else + { + // otherwise just set it to an identity matrix + inv_matrix = new float[3][3]; + inv_matrix[0][0] = inv_matrix[1][1] = inv_matrix[2][2] = 1.0f; + } + } + + public float[] toCIEXYZ(float[] in) + { + // CLUT takes precedence + if (toPCS != null) + return toPCS.lookup(in); + + float[] temp = new float[3]; + float[] out = new float[3]; + + // device space --> linear gamma + temp[0] = rTRC.lookup(in[0]); + temp[1] = gTRC.lookup(in[1]); + temp[2] = bTRC.lookup(in[2]); + + // matrix multiplication + out[0] = matrix[0][0] * temp[0] + matrix[0][1] * temp[1] + + matrix[0][2] * temp[2]; + out[1] = matrix[1][0] * temp[0] + matrix[1][1] * temp[1] + + matrix[1][2] * temp[2]; + out[2] = matrix[2][0] * temp[0] + matrix[2][1] * temp[1] + + matrix[2][2] * temp[2]; + + return out; + } + + public float[] toRGB(float[] in) + { + return SrgbConverter.XYZtoRGB(toCIEXYZ(in)); + } + + public float[] fromCIEXYZ(float[] in) + { + if (fromPCS != null) + return fromPCS.lookup(in); + + float[] temp = new float[3]; + float[] out = new float[3]; + + // matrix multiplication + temp[0] = inv_matrix[0][0] * in[0] + inv_matrix[0][1] * in[1] + + inv_matrix[0][2] * in[2]; + temp[1] = inv_matrix[1][0] * in[0] + inv_matrix[1][1] * in[1] + + inv_matrix[1][2] * in[2]; + temp[2] = inv_matrix[2][0] * in[0] + inv_matrix[2][1] * in[1] + + inv_matrix[2][2] * in[2]; + + // device space --> linear gamma + out[0] = rTRC.reverseLookup(temp[0]); + out[1] = gTRC.reverseLookup(temp[1]); + out[2] = bTRC.reverseLookup(temp[2]); + + // FIXME: Sun appears to clip the return values to [0,1] + // I don't believe that is a Good Thing, + // (some colorspaces may allow values outside that range.) + // So we return the actual values here. + return out; + } + + public float[] fromRGB(float[] in) + { + return fromCIEXYZ(SrgbConverter.RGBtoXYZ(in)); + } + + /** + * Inverts a 3x3 matrix, returns the inverse, + * throws an IllegalArgumentException if the matrix is not + * invertible (this shouldn't happen for a valid profile) + */ + private float[][] invertMatrix(float[][] matrix) + { + float[][] out = new float[3][3]; + double determinant = matrix[0][0] * (matrix[1][1] * matrix[2][2] + - matrix[2][1] * matrix[1][2]) + - matrix[0][1] * (matrix[1][0] * matrix[2][2] + - matrix[2][0] * matrix[1][2]) + + matrix[0][2] * (matrix[1][0] * matrix[2][1] + - matrix[2][0] * matrix[1][1]); + + if (determinant == 0.0) + throw new IllegalArgumentException("Can't invert conversion matrix."); + float invdet = (float) (1.0 / determinant); + + out[0][0] = invdet * (matrix[1][1] * matrix[2][2] + - matrix[1][2] * matrix[2][1]); + out[0][1] = invdet * (matrix[0][2] * matrix[2][1] + - matrix[0][1] * matrix[2][2]); + out[0][2] = invdet * (matrix[0][1] * matrix[1][2] + - matrix[0][2] * matrix[1][1]); + out[1][0] = invdet * (matrix[1][2] * matrix[2][0] + - matrix[1][0] * matrix[2][2]); + out[1][1] = invdet * (matrix[0][0] * matrix[2][2] + - matrix[0][2] * matrix[2][0]); + out[1][2] = invdet * (matrix[0][2] * matrix[1][0] + - matrix[0][0] * matrix[1][2]); + out[2][0] = invdet * (matrix[1][0] * matrix[2][1] + - matrix[1][1] * matrix[2][0]); + out[2][1] = invdet * (matrix[0][1] * matrix[2][0] + - matrix[0][0] * matrix[2][1]); + out[2][2] = invdet * (matrix[0][0] * matrix[1][1] + - matrix[0][1] * matrix[1][0]); + return out; + } +} diff --git a/openjdk/gnu/java/awt/color/SrgbConverter.java b/openjdk/gnu/java/awt/color/SrgbConverter.java new file mode 100644 index 0000000..76831c0 --- /dev/null +++ b/openjdk/gnu/java/awt/color/SrgbConverter.java @@ -0,0 +1,152 @@ +/* SrgbConverter.java -- sRGB conversion class + Copyright (C) 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.java.awt.color; + + +/** + * SrgbConverter - conversion routines for the sRGB colorspace + * sRGB is a standard for RGB colorspaces, adopted by the w3c. + * + * The specification is available at: + * http://www.w3.org/Graphics/Color/sRGB.html + * + * @author Sven de Marothy + */ +/** + * + * Note the matrix numbers used here are NOT identical to those in the + * w3 spec, as those numbers are CIE XYZ relative a D65 white point. + * The CIE XYZ we use is relative a D50 white point, so therefore a + * linear Bradford transform matrix for D65->D50 mapping has been applied. + * (The ICC documents describe this transform) + * + * Linearized Bradford transform: + * 0.8951 0.2664 -0.1614 + * -0.7502 1.7135 0.0367 + * 0.0389 -0.0685 1.0296 + * + * Inverse: + * 0.9870 -0.1471 0.1600 + * 0.4323 0.5184 0.0493 + * -0.00853 0.0400 0.9685 + */ +public class SrgbConverter implements ColorSpaceConverter +{ + public float[] fromCIEXYZ(float[] in) + { + return XYZtoRGB(in); + } + + public float[] toCIEXYZ(float[] in) + { + return RGBtoXYZ(in); + } + + public float[] toRGB(float[] in) + { + float[] out = new float[3]; + System.arraycopy(in, 0, out, 0, 3); + return out; + } + + public float[] fromRGB(float[] in) + { + float[] out = new float[3]; + System.arraycopy(in, 0, out, 0, 3); + return out; + } + + /** + * CIE XYZ (D50 relative) --> sRGB + * + * Static as it's used by other ColorSpaceConverters to + * convert to sRGB if the color space is defined in XYZ. + */ + public static float[] XYZtoRGB(float[] in) + { + float[] temp = new float[3]; + temp[0] = 3.1338f * in[0] - 1.6171f * in[1] - 0.4907f * in[2]; + temp[1] = -0.9785f * in[0] + 1.9160f * in[1] + 0.0334f * in[2]; + temp[2] = 0.0720f * in[0] - 0.2290f * in[1] + 1.4056f * in[2]; + + float[] out = new float[3]; + for (int i = 0; i < 3; i++) + { + if (temp[i] < 0) + temp[i] = 0.0f; + if (temp[i] > 1) + temp[i] = 1.0f; + if (temp[i] <= 0.00304f) + out[i] = temp[i] * 12.92f; + else + out[i] = 1.055f * ((float) Math.exp((1 / 2.4) * Math.log(temp[i]))) + - 0.055f; + } + return out; + } + + /** + * sRGB --> CIE XYZ (D50 relative) + * + * Static as it's used by other ColorSpaceConverters to + * convert to XYZ if the color space is defined in RGB. + */ + public static float[] RGBtoXYZ(float[] in) + { + float[] temp = new float[3]; + float[] out = new float[3]; + for (int i = 0; i < 3; i++) + if (in[i] <= 0.03928f) + temp[i] = in[i] / 12.92f; + else + temp[i] = (float) Math.exp(2.4 * Math.log((in[i] + 0.055) / 1.055)); + + /* + * Note: The numbers which were used to calculate this only had four + * digits of accuracy. So don't be fooled by the number of digits here. + * If someone has more accurate source, feel free to update this. + */ + out[0] = (float) (0.436063750222 * temp[0] + 0.385149601465 * temp[1] + + 0.143086418888 * temp[2]); + out[1] = (float) (0.222450894035 * temp[0] + 0.71692584775 * temp[1] + + 0.060624511256 * temp[2]); + out[2] = (float) (0.0138985186 * temp[0] + 0.097079690112 * temp[1] + + 0.713996045725 * temp[2]); + return out; + } +} diff --git a/openjdk/gnu/java/awt/color/TagEntry.java b/openjdk/gnu/java/awt/color/TagEntry.java new file mode 100644 index 0000000..a978646 --- /dev/null +++ b/openjdk/gnu/java/awt/color/TagEntry.java @@ -0,0 +1,121 @@ +/* TagEntry.java -- A utility class used for storing the tags in ICC_Profile + Copyright (C) 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.java.awt.color; + + +/** + * TagEntry - stores a profile tag. + * These are conveniently stored in a hashtable with the tag signature + * as a key. A legal profile can only have one tag with a given sig, + * so we can conveniently ignore collisions. + * + * @author Sven de Marothy + */ +public class TagEntry +{ + // tag table entry size + public static final int entrySize = 12; + private int signature; + private int size; + private int offset; + private byte[] data; + + public TagEntry(int sig, int offset, int size, byte[] data) + { + this.signature = sig; + this.offset = offset; + this.size = size; + this.data = new byte[size]; + System.arraycopy(data, offset, this.data, 0, size); + } + + public TagEntry(int sig, byte[] data) + { + this.signature = sig; + this.size = data.length; + this.data = new byte[size]; + System.arraycopy(data, offset, this.data, 0, size); + } + + public byte[] getData() + { + byte[] d = new byte[size]; + System.arraycopy(this.data, 0, d, 0, size); + return d; + } + + public String hashKey() + { + return tagHashKey(signature); + } + + public String toString() + { + String s = ""; + s = s + (char) ((byte) ((signature >> 24) & 0xFF)); + s = s + (char) ((byte) ((signature >> 16) & 0xFF)); + s = s + (char) ((byte) ((signature >> 8) & 0xFF)); + s = s + (char) ((byte) (signature & 0xFF)); + return s; + } + + public int getSignature() + { + return signature; + } + + public int getSize() + { + return size; + } + + public int getOffset() + { + return offset; + } + + public void setOffset(int offset) + { + this.offset = offset; + } + + public static String tagHashKey(int sig) + { + return "" + sig; + } +} diff --git a/openjdk/gnu/java/awt/color/ToneReproductionCurve.java b/openjdk/gnu/java/awt/color/ToneReproductionCurve.java new file mode 100644 index 0000000..208e168 --- /dev/null +++ b/openjdk/gnu/java/awt/color/ToneReproductionCurve.java @@ -0,0 +1,177 @@ +/* ToneReproductionCurve.java -- Representation of an ICC 'curv' type TRC + Copyright (C) 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.java.awt.color; + + +/** + * ToneReproductionCurve - TRCs are used to describe RGB + * and Grayscale profiles. The TRC is essentially the gamma + * function of the color space. + * + * For example, Apple RGB has a gamma of 1.8, most monitors are ~2.2, + * sRGB is 2.4 with a small linear part near 0. + * Linear spaces are of course 1.0. + * (The exact function is implemented in SrgbConverter) + * + * The ICC specification allows the TRC to be described as a single + * Gamma value, where the function is thus out = in**gamma. + * Alternatively, the gamma function may be represented by a lookup table + * of values, in which case linear interpolation is used. + * + * @author Sven de Marothy + */ +public class ToneReproductionCurve +{ + private float[] trc; + private float gamma; + private float[] reverseTrc; + + /** + * Constructs a TRC from a gamma values + */ + public ToneReproductionCurve(float gamma) + { + trc = null; + reverseTrc = null; + this.gamma = gamma; + } + + /** + * Constructs a TRC from a set of float values + */ + public ToneReproductionCurve(float[] trcValues) + { + trc = new float[trcValues.length]; + System.arraycopy(trcValues, 0, trc, 0, trcValues.length); + setupReverseTrc(); + } + + /** + * Constructs a TRC from a set of short values normalized to + * the 0-65535 range (as in the ICC profile file). + * (Note the values are treated as unsigned) + */ + public ToneReproductionCurve(short[] trcValues) + { + trc = new float[trcValues.length]; + for (int i = 0; i < trcValues.length; i++) + trc[i] = (float) ((int) trcValues[i] & (0xFFFF)) / 65535.0f; + setupReverseTrc(); + } + + /** + * Performs a TRC lookup + */ + public float lookup(float in) + { + float out; + + if (trc == null) + { + if (in == 0f) + return 0.0f; + return (float) Math.exp(gamma * Math.log(in)); + } + else + { + double alpha = in * (trc.length - 1); + int index = (int) Math.floor(alpha); + alpha = alpha - (double) index; + if (index >= trc.length - 1) + return trc[trc.length - 1]; + if (index <= 0) + return trc[0]; + out = (float) (trc[index] * (1.0 - alpha) + trc[index + 1] * alpha); + } + return out; + } + + /** + * Performs an reverse lookup + */ + public float reverseLookup(float in) + { + float out; + + if (trc == null) + { + if (in == 0f) + return 0.0f; + return (float) Math.exp((1.0 / gamma) * Math.log(in)); + } + else + { + double alpha = in * (reverseTrc.length - 1); + int index = (int) Math.floor(alpha); + alpha = alpha - (double) index; + if (index >= reverseTrc.length - 1) + return reverseTrc[reverseTrc.length - 1]; + if (index <= 0) + return reverseTrc[0]; + out = (float) (reverseTrc[index] * (1.0 - alpha) + + reverseTrc[index + 1] * alpha); + } + return out; + } + + /** + * Calculates a reverse-lookup table. + * We use a whopping 10,000 entries.. This is should be more than any + * real-life TRC table (typically around 256-1024) so we won't be losing + * any precision. + * + * This will of course generate completely invalid results if the curve + * is not monotonic and invertable. But what's the alternative? + */ + public void setupReverseTrc() + { + reverseTrc = new float[10000]; + int j = 0; + for (int i = 0; i < 10000; i++) + { + float n = ((float) i) / 10000f; + while (trc[j + 1] < n && j < trc.length - 2) + j++; + + if (j == trc.length - 2) + reverseTrc[i] = trc[trc.length - 1]; + else + reverseTrc[i] = (j + (n - trc[j]) / (trc[j + 1] - trc[j])) / ((float) trc.length); + } + } +} diff --git a/openjdk/gnu/java/util/EmptyEnumeration.java b/openjdk/gnu/java/util/EmptyEnumeration.java new file mode 100644 index 0000000..46a82d6 --- /dev/null +++ b/openjdk/gnu/java/util/EmptyEnumeration.java @@ -0,0 +1,96 @@ +/* EmptyEnumeration.java -- a constant empty enumeration + Copyright (C) 2001, 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.java.util; + +import java.io.Serializable; +import java.util.Enumeration; +import java.util.NoSuchElementException; + +/** + * This is a helper class that produces an empty Enumerations. There is only + * one instance of this class that can be used whenever one needs a + * non-null but empty enumeration. Using this class prevents multiple + * small objects and inner classes. getInstance() returns + * the only instance of this class. It can be shared by multiple objects and + * threads. + * + * @author Mark Wielaard (mark@klomp.org) + */ +public final class EmptyEnumeration implements Enumeration, Serializable +{ + /** The only instance of this class */ + private static final EmptyEnumeration instance = new EmptyEnumeration(); + + /** + * Private constructor that creates a new empty Enumeration. + */ + private EmptyEnumeration() + { + } + + /** + * Returns the only instance of this class. + * It can be shared by multiple objects and threads. + * + * @return the common empty enumeration + */ + public static EmptyEnumeration getInstance() + { + return instance; + } + + /** + * Returns false, since there are no elements. + * + * @return false + */ + public boolean hasMoreElements() + { + return false; + } + + /** + * Always throws NoSuchElementException, since it is empty. + * + * @throws NoSuchElementException this is empty + */ + public Object nextElement() + { + throw new NoSuchElementException(); + } +} diff --git a/openjdk/icedtea/jce/gnu/java/security/action/GetPropertyAction.java b/openjdk/icedtea/jce/gnu/java/security/action/GetPropertyAction.java new file mode 100644 index 0000000..0c8141a --- /dev/null +++ b/openjdk/icedtea/jce/gnu/java/security/action/GetPropertyAction.java @@ -0,0 +1,89 @@ +/* GetPropertyAction.java + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.java.security.action; + +import java.security.PrivilegedAction; + +/** + * PrivilegedAction implementation that calls System.getProperty() with + * the property name passed to its constructor. + * + * Example of use: + * + * GetPropertyAction action = new GetPropertyAction("http.proxyPort"); + * String port = AccessController.doPrivileged(action); + * + */ +public class GetPropertyAction implements PrivilegedAction +{ + String name; + String value = null; + + public GetPropertyAction() + { + } + + public GetPropertyAction(String propName) + { + setParameters(propName); + } + + public GetPropertyAction(String propName, String defaultValue) + { + setParameters(propName, defaultValue); + } + + public String run() + { + return System.getProperty(name, value); + } + + public GetPropertyAction setParameters(String propName) + { + this.name = propName; + this.value = null; + return this; + } + + public GetPropertyAction setParameters(String propName, String defaultValue) + { + this.name = propName; + this.value = defaultValue; + return this; + } +} diff --git a/openjdk/icedtea/jce/gnu/java/security/action/GetSecurityPropertyAction.java b/openjdk/icedtea/jce/gnu/java/security/action/GetSecurityPropertyAction.java new file mode 100644 index 0000000..ac928ca --- /dev/null +++ b/openjdk/icedtea/jce/gnu/java/security/action/GetSecurityPropertyAction.java @@ -0,0 +1,93 @@ +/* GetSecurityPropertyAction.java + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.java.security.action; + +import java.security.PrivilegedAction; +import java.security.Security; + +/** + * PrivilegedAction implementation that calls Security.getProperty() + * with the property name passed to its constructor. + * + * Example of use: + * + * GetSecurityPropertyAction action = new GetSecurityPropertyAction("javax.net.ssl.trustStorePassword"); + * String passwd = AccessController.doPrivileged(action); + * + */ +public class GetSecurityPropertyAction implements PrivilegedAction +{ + private String name; + private String value; + + public GetSecurityPropertyAction() + { + } + + public GetSecurityPropertyAction(String propName) + { + setParameters(propName); + } + + public GetSecurityPropertyAction(String propName, String defaultValue) + { + setParameters(propName, defaultValue); + } + + public GetSecurityPropertyAction setParameters(String propName) + { + this.name = propName; + this.value = null; + return this; + } + + public GetSecurityPropertyAction setParameters(String propName, String defaultValue) + { + this.name = propName; + this.value = defaultValue; + return this; + } + + public String run() + { + String val = Security.getProperty(name); + if (val == null) + val = value; + return val; + } +} diff --git a/openjdk/icedtea/jce/gnu/java/security/action/SetAccessibleAction.java b/openjdk/icedtea/jce/gnu/java/security/action/SetAccessibleAction.java new file mode 100644 index 0000000..77e5fc9 --- /dev/null +++ b/openjdk/icedtea/jce/gnu/java/security/action/SetAccessibleAction.java @@ -0,0 +1,77 @@ +/* SetAccessibleAction.java + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.java.security.action; + +import java.lang.reflect.AccessibleObject; +import java.security.PrivilegedAction; + +/** + * PrivilegedAction implementation that calls setAccessible(true) on the + * AccessibleObject passed to its constructor. + * + * Example of use: + * + * Field dataField = cl.getDeclaredField("data"); + * AccessController.doPrivileged(new SetAccessibleAction(dataField)); + * + */ +public class SetAccessibleAction implements PrivilegedAction +{ + AccessibleObject member; + + public SetAccessibleAction() + { + } + + public SetAccessibleAction(AccessibleObject member) + { + this.member = member; + } + + public Object run() + { + member.setAccessible(true); + return null; + } + + public SetAccessibleAction setMember(AccessibleObject member) + { + this.member = member; + return this; + } +} diff --git a/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpDataTypeEnums.java b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpDataTypeEnums.java new file mode 100644 index 0000000..2f8f527 --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpDataTypeEnums.java @@ -0,0 +1,52 @@ +/* SnmpDataTypeEnums.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.jmx.snmp; + +public interface SnmpDataTypeEnums { + // Random values chosen to prevent conflicts in switch statements. + final static int IpAddressTag = 01; + final static int CounterTag = 11; + final static int GaugeTag = 21; + final static int TimeticksTag = 31; + final static int OpaqueTag = 41; + int NullTag = 0; + final static int errNoSuchObjectTag = 33; + final static int errNoSuchInstanceTag = 44; + final static int errEndOfMibViewTag = 55; + public static final int Counter64Tag = 0; +} diff --git a/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpDefinitions.java b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpDefinitions.java new file mode 100644 index 0000000..919105c --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpDefinitions.java @@ -0,0 +1,83 @@ +/* SnmpDefinitions.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.jmx.snmp; + +public interface SnmpDefinitions { + // Random values chosen to prevent conflicts in switch statements. + final int snmpRspNoError = 1230; + final int pduGetRequestPdu = 1; + final int pduGetNextRequestPdu = 2; + final int pduWalkRequest = 3; + final int pduSetRequestPdu = 4; + final int pduV1TrapPdu = 5; + final int pduGetResponsePdu = 6; + final int pduInformRequestPdu = 7; + final int pduGetBulkRequestPdu = 8; + final int pduV2TrapPdu = 9; + int snmpVersionOne = 330; + int snmpVersionTwo = 220; + final int pduReportPdu = 10; + int snmpRspWrongEncoding = 0; + final int snmpReqUnknownError = 110; + final byte noAuthNoPriv = 0; + final byte privMask = 0; + final int snmpVersionThree = 4430; + final int snmpRspGenErr = 0; + final int snmpRspNotWritable = 0; + final byte authPriv = 0; + final int authMask = 0; + final int snmpRspNoSuchName = 10; + final int snmpRspNoAccess = 20; + final int snmpRspReadOnly = 30; + final int snmpRspBadValue = 40; + final int snmpRspWrongValue = 50; + final int snmpRspInconsistentName = 60; + final int snmpRspAuthorizationError = 70; + final int snmpRspNoCreation = 80; + final int snmpRspWrongType = 90; + final int snmpRspWrongLength = 110; + final int snmpRspInconsistentValue = 220; + final int snmpRspResourceUnavailable = 330; + final int snmpRspCommitFailed = 440; + final int snmpRspUndoFailed = 550; + final int snmpRspTooBig = 660; + final int snmpV1SecurityModel = 650; + final int snmpV2SecurityModel = 560; + final int snmpWrongSnmpVersion = 221; + +} diff --git a/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpOid.java b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpOid.java new file mode 100644 index 0000000..a3b69a9 --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpOid.java @@ -0,0 +1,137 @@ +/* SnmpOid.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.jmx.snmp; + +public class SnmpOid extends SnmpValue { + + public int componentCount = 0; + public long[] components; + + public SnmpOid() { + } + + public SnmpOid(long[] ls) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated constructor stub + } + + public SnmpOid(String dotAddress) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated constructor stub + } + + public SnmpOid(long b1, long b2, long b3, long b4) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated constructor stub + } + + public SnmpOid(long value) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated constructor stub + } + + @Override + public SnmpValue duplicate() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + @Override + public String getTypeName() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + @Override + public SnmpOid toOid() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public long[] longValue() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public int getLength() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public void append(SnmpOid source) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public void append(int length) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public int compareTo(SnmpOid oid) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public long[] longValue(boolean b) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public long getOidArc(int depth) throws SnmpStatusException { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public Byte[] toByte() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + +} diff --git a/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpOidRecord.java b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpOidRecord.java new file mode 100644 index 0000000..c119c0f --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpOidRecord.java @@ -0,0 +1,53 @@ +/* SnmpOidRecord.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.jmx.snmp; + +public class SnmpOidRecord { + + public SnmpOidRecord(String string, String string2, String string3) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated constructor stub + } + + public String getOid() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + +} diff --git a/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpOidTable.java b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpOidTable.java new file mode 100644 index 0000000..c87cf7f --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpOidTable.java @@ -0,0 +1,53 @@ +/* SnmpOidTable.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.jmx.snmp; + +public class SnmpOidTable { + + public SnmpOidTable(String string) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated constructor stub + } + + public SnmpOidRecord resolveVarName(String string) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + +} diff --git a/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpOidTableSupport.java b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpOidTableSupport.java new file mode 100644 index 0000000..c29858c --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpOidTableSupport.java @@ -0,0 +1,54 @@ +/* SnmpOidTableSupport.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.jmx.snmp; + +public class SnmpOidTableSupport extends SnmpOidTable { + + public SnmpOidTableSupport(String string) { + super(string); + throw new RuntimeException("Not implemented."); + // TODO Auto-generated constructor stub + } + + public void loadMib(SnmpOidRecord[] varList2) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + +} diff --git a/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpParameters.java b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpParameters.java new file mode 100644 index 0000000..9880436 --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpParameters.java @@ -0,0 +1,60 @@ +/* SnmpParameters.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.jmx.snmp; + +public class SnmpParameters { + + public String getRdCommunity() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public String getInformCommunity() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public void setRdCommunity(String community) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + +} diff --git a/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpPduPacket.java b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpPduPacket.java new file mode 100644 index 0000000..36381f4 --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpPduPacket.java @@ -0,0 +1,53 @@ +/* SnmpPduPacket.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.jmx.snmp; + +import java.net.InetAddress; + +public class SnmpPduPacket extends SnmpPdu { + // Random values chosen to prevent conflicts in switch statements. + public int type; + public final static int pduGetBulkRequestPdu = 223; + public final static int trapAuthenticationFailure = 93764; + public int version; + public int snmpVersionTwo; + public InetAddress address; + public int port; + public byte[] community; + public int requestId; +} diff --git a/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpPeer.java b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpPeer.java new file mode 100644 index 0000000..a6e7f64 --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpPeer.java @@ -0,0 +1,73 @@ +/* SnmpPeer.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.jmx.snmp; + +import java.net.InetAddress; + +public class SnmpPeer { + + public SnmpPeer(InetAddress address, int port) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated constructor stub + } + + public SnmpParameters getParams() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public InetAddress getDestAddr() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public int getDestPort() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public void setParams(SnmpParameters p) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + +} diff --git a/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpSession.java b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpSession.java new file mode 100644 index 0000000..c638f2f --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpSession.java @@ -0,0 +1,65 @@ +/* SnmpSession.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.jmx.snmp; + +import java.net.InetAddress; + +import com.sun.jmx.snmp.daemon.SnmpAdaptorServer; +import com.sun.jmx.snmp.daemon.SnmpInformHandler; +import com.sun.jmx.snmp.daemon.SnmpInformRequest; + +public class SnmpSession { + + public SnmpSession(SnmpAdaptorServer server) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated constructor stub + } + + public SnmpInformRequest makeAsyncRequest(InetAddress addr, String cs, SnmpInformHandler cb, SnmpVarBindList fullVbl, int informPort) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public void destroySession() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + +} diff --git a/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpTimeticks.java b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpTimeticks.java new file mode 100644 index 0000000..d59f20b --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpTimeticks.java @@ -0,0 +1,74 @@ +/* SnmpTimeticks.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.jmx.snmp; + +public class SnmpTimeticks extends SnmpValue { + + public SnmpTimeticks(long l) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated constructor stub + } + + @Override + public SnmpValue duplicate() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + @Override + public String getTypeName() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + @Override + public SnmpOid toOid() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public int longValue() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + +} diff --git a/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpVarBind.java b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpVarBind.java new file mode 100644 index 0000000..1af0a9c --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpVarBind.java @@ -0,0 +1,74 @@ +/* SnmpVarBind.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.jmx.snmp; + +public class SnmpVarBind { + // Random values chosen to prevent conflicts in switch statements. + public final static int errNoSuchObjectTag = 3; + public final static int errNoSuchInstanceTag = 8; + public final static int errEndOfMibViewTag = 9; + public static SnmpValue noSuchObject; + public static SnmpValue noSuchInstance; + public static SnmpValue endOfMibView; + public SnmpValue value; + public SnmpOid oid; + public SnmpVarBind(SnmpOid oid2, SnmpValue value2) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated constructor stub + } + public SnmpVarBind() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated constructor stub + } + public void setSnmpValue(SnmpValue value2) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + public void setEndOfMibView() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + public void setNoSuchObject() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + +} diff --git a/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpVarBindList.java b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpVarBindList.java new file mode 100644 index 0000000..515cbdf --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/jmx/snmp/SnmpVarBindList.java @@ -0,0 +1,82 @@ +/* SnmpVarBindList.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.jmx.snmp; + +public class SnmpVarBindList { + + public SnmpVarBindList(int i) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated constructor stub + } + + public SnmpVarBindList() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated constructor stub + } + + public int size() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public void copyInto(SnmpVarBind[] varBindList) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public void insertElementAt(SnmpVarBind bind, int i) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public SnmpVarBindList clone() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public void add(SnmpVarBind varPoolName) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + +} diff --git a/openjdk/icedtea/rt/com/sun/jmx/snmp/daemon/SnmpInformRequest.java b/openjdk/icedtea/rt/com/sun/jmx/snmp/daemon/SnmpInformRequest.java new file mode 100644 index 0000000..0c7f8dd --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/jmx/snmp/daemon/SnmpInformRequest.java @@ -0,0 +1,42 @@ +/* SnmpInformRequest.java -- stub file + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.jmx.snmp.daemon; + +public class SnmpInformRequest { + +} diff --git a/openjdk/icedtea/rt/com/sun/jmx/snmp/daemon/SnmpSession.java b/openjdk/icedtea/rt/com/sun/jmx/snmp/daemon/SnmpSession.java new file mode 100644 index 0000000..8404275 --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/jmx/snmp/daemon/SnmpSession.java @@ -0,0 +1,66 @@ +/* SnmpSession.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.jmx.snmp.daemon; + +import java.net.InetAddress; + +import com.sun.jmx.snmp.SnmpVarBindList; +import com.sun.jmx.snmp.daemon.SnmpAdaptorServer; +import com.sun.jmx.snmp.daemon.SnmpInformHandler; +import com.sun.jmx.snmp.daemon.SnmpInformRequest; + +public class SnmpSession { + + public SnmpSession(SnmpAdaptorServer server) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated constructor stub + } + + public SnmpInformRequest makeAsyncRequest(InetAddress addr, String cs, SnmpInformHandler cb, SnmpVarBindList fullVbl, int informPort) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public void destroySession() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + +} diff --git a/openjdk/icedtea/rt/com/sun/media/sound/AbstractPlayer.java b/openjdk/icedtea/rt/com/sun/media/sound/AbstractPlayer.java new file mode 100644 index 0000000..f0c83dd --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/AbstractPlayer.java @@ -0,0 +1,45 @@ +/* AbstractPlayer.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +public class AbstractPlayer +{ + +} + + diff --git a/openjdk/icedtea/rt/com/sun/media/sound/AutoConnectSequencer.java b/openjdk/icedtea/rt/com/sun/media/sound/AutoConnectSequencer.java new file mode 100644 index 0000000..30ed3b1 --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/AutoConnectSequencer.java @@ -0,0 +1,50 @@ +/* AutoConnectSequencer.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +import javax.sound.midi.Receiver; + +public class AutoConnectSequencer { + + public void setAutoConnect(Receiver rec) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + +} diff --git a/openjdk/icedtea/rt/com/sun/media/sound/DataPusher.java b/openjdk/icedtea/rt/com/sun/media/sound/DataPusher.java new file mode 100644 index 0000000..d31cd80 --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/DataPusher.java @@ -0,0 +1,62 @@ +/* DataPusher.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.SourceDataLine; + +public class DataPusher { + + public DataPusher(SourceDataLine sourcedataline, AudioInputStream as) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated constructor stub + } + + public void stop() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public void start() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + +} diff --git a/openjdk/icedtea/rt/com/sun/media/sound/DirectAudioDevice.java b/openjdk/icedtea/rt/com/sun/media/sound/DirectAudioDevice.java new file mode 100644 index 0000000..2950652 --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/DirectAudioDevice.java @@ -0,0 +1,45 @@ +/* DirectAudioDevice.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +public class DirectAudioDevice +{ + +} + + diff --git a/openjdk/icedtea/rt/com/sun/media/sound/DirectAudioDeviceProvider.java b/openjdk/icedtea/rt/com/sun/media/sound/DirectAudioDeviceProvider.java new file mode 100644 index 0000000..9e5e2a1 --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/DirectAudioDeviceProvider.java @@ -0,0 +1,45 @@ +/* DirectAudioDeviceProvider.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +public class DirectAudioDeviceProvider +{ + +} + + diff --git a/openjdk/icedtea/rt/com/sun/media/sound/HeadspaceMixer.java b/openjdk/icedtea/rt/com/sun/media/sound/HeadspaceMixer.java new file mode 100644 index 0000000..ad5b386 --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/HeadspaceMixer.java @@ -0,0 +1,44 @@ +/* HeadspaceMixer.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +public class HeadspaceMixer +{ + +} + diff --git a/openjdk/icedtea/rt/com/sun/media/sound/HeadspaceSoundbank.java b/openjdk/icedtea/rt/com/sun/media/sound/HeadspaceSoundbank.java new file mode 100644 index 0000000..1510227 --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/HeadspaceSoundbank.java @@ -0,0 +1,45 @@ +/* HeadspaceSoundbank.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +public class HeadspaceSoundbank +{ + +} + + diff --git a/openjdk/icedtea/rt/com/sun/media/sound/JDK13Services.java b/openjdk/icedtea/rt/com/sun/media/sound/JDK13Services.java new file mode 100644 index 0000000..dec0171 --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/JDK13Services.java @@ -0,0 +1,50 @@ +/* JDK13Services.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +import java.util.List; + +public class JDK13Services { + + public static native String getDefaultProviderClassName(Class deviceClass); + + public static native String getDefaultInstanceName(Class deviceClass); + + public static native List getProviders(Class providerClass); + +} diff --git a/openjdk/icedtea/rt/com/sun/media/sound/JavaSoundAudioClip.java b/openjdk/icedtea/rt/com/sun/media/sound/JavaSoundAudioClip.java new file mode 100644 index 0000000..6b75fac --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/JavaSoundAudioClip.java @@ -0,0 +1,68 @@ +/* JavaSoundAudioClip.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +import java.applet.AudioClip; +import java.io.InputStream; + +public class JavaSoundAudioClip implements AudioClip { + + public JavaSoundAudioClip(InputStream in) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated constructor stub + } + + public void loop() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public void play() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public void stop() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + +} diff --git a/openjdk/icedtea/rt/com/sun/media/sound/MidiInDevice.java b/openjdk/icedtea/rt/com/sun/media/sound/MidiInDevice.java new file mode 100644 index 0000000..f51e937 --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/MidiInDevice.java @@ -0,0 +1,45 @@ +/* MidiInDevice.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +public class MidiInDevice +{ + +} + + diff --git a/openjdk/icedtea/rt/com/sun/media/sound/MidiInDeviceProvider.java b/openjdk/icedtea/rt/com/sun/media/sound/MidiInDeviceProvider.java new file mode 100644 index 0000000..fb08b3e --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/MidiInDeviceProvider.java @@ -0,0 +1,45 @@ +/* MidiInDeviceProvider.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +public class MidiInDeviceProvider +{ + +} + + diff --git a/openjdk/icedtea/rt/com/sun/media/sound/MidiOutDevice.java b/openjdk/icedtea/rt/com/sun/media/sound/MidiOutDevice.java new file mode 100644 index 0000000..4f70f65 --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/MidiOutDevice.java @@ -0,0 +1,44 @@ +/* MidiOutDevice.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +public class MidiOutDevice +{ + +} + diff --git a/openjdk/icedtea/rt/com/sun/media/sound/MidiOutDeviceProvider.java b/openjdk/icedtea/rt/com/sun/media/sound/MidiOutDeviceProvider.java new file mode 100644 index 0000000..7a55070 --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/MidiOutDeviceProvider.java @@ -0,0 +1,45 @@ +/* MidiOutDeviceProvider.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +public class MidiOutDeviceProvider +{ + +} + + diff --git a/openjdk/icedtea/rt/com/sun/media/sound/MidiUtils.java b/openjdk/icedtea/rt/com/sun/media/sound/MidiUtils.java new file mode 100644 index 0000000..ba10e3f --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/MidiUtils.java @@ -0,0 +1,59 @@ +/* MidiUtils.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +import javax.sound.midi.MidiMessage; +import javax.sound.midi.Sequence; + +public class MidiUtils { + + public static final byte META_END_OF_TRACK_TYPE = 0; + + public static long tick2microsecond(Sequence sequence, long tickLength, Object object) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public static boolean isMetaEndOfTrack(MidiMessage message) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + +} diff --git a/openjdk/icedtea/rt/com/sun/media/sound/MixerClip.java b/openjdk/icedtea/rt/com/sun/media/sound/MixerClip.java new file mode 100644 index 0000000..efec8fc --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/MixerClip.java @@ -0,0 +1,44 @@ +/* MixerClip.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +public class MixerClip +{ + +} + diff --git a/openjdk/icedtea/rt/com/sun/media/sound/MixerMidiChannel.java b/openjdk/icedtea/rt/com/sun/media/sound/MixerMidiChannel.java new file mode 100644 index 0000000..4bdad6d --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/MixerMidiChannel.java @@ -0,0 +1,45 @@ +/* MixerMidiChannel.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +public class MixerMidiChannel +{ + +} + + diff --git a/openjdk/icedtea/rt/com/sun/media/sound/MixerSequencer.java b/openjdk/icedtea/rt/com/sun/media/sound/MixerSequencer.java new file mode 100644 index 0000000..b8199ab --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/MixerSequencer.java @@ -0,0 +1,45 @@ +/* MixerSequencer.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +public class MixerSequencer +{ + +} + + diff --git a/openjdk/icedtea/rt/com/sun/media/sound/MixerSourceLine.java b/openjdk/icedtea/rt/com/sun/media/sound/MixerSourceLine.java new file mode 100644 index 0000000..dbc6920 --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/MixerSourceLine.java @@ -0,0 +1,44 @@ +/* MixerSourceLine.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +public class MixerSourceLine +{ + +} + diff --git a/openjdk/icedtea/rt/com/sun/media/sound/MixerSynth.java b/openjdk/icedtea/rt/com/sun/media/sound/MixerSynth.java new file mode 100644 index 0000000..362aa7a --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/MixerSynth.java @@ -0,0 +1,45 @@ +/* MixerSynth.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +public class MixerSynth +{ + +} + + diff --git a/openjdk/icedtea/rt/com/sun/media/sound/MixerThread.java b/openjdk/icedtea/rt/com/sun/media/sound/MixerThread.java new file mode 100644 index 0000000..9b2e67c --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/MixerThread.java @@ -0,0 +1,44 @@ +/* MixerThread.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +public class MixerThread +{ + +} + diff --git a/openjdk/icedtea/rt/com/sun/media/sound/Platform.java b/openjdk/icedtea/rt/com/sun/media/sound/Platform.java new file mode 100644 index 0000000..649ba3a --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/Platform.java @@ -0,0 +1,45 @@ +/* Platform.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +public class Platform +{ + +} + + diff --git a/openjdk/icedtea/rt/com/sun/media/sound/PortMixer.java b/openjdk/icedtea/rt/com/sun/media/sound/PortMixer.java new file mode 100644 index 0000000..08e1f6d --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/PortMixer.java @@ -0,0 +1,45 @@ +/* PortMixer.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +public class PortMixer +{ + +} + + diff --git a/openjdk/icedtea/rt/com/sun/media/sound/PortMixerProvider.java b/openjdk/icedtea/rt/com/sun/media/sound/PortMixerProvider.java new file mode 100644 index 0000000..ba099cd --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/PortMixerProvider.java @@ -0,0 +1,45 @@ +/* PortMixerProvider.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +public class PortMixerProvider +{ + +} + + diff --git a/openjdk/icedtea/rt/com/sun/media/sound/ReferenceCountingDevice.java b/openjdk/icedtea/rt/com/sun/media/sound/ReferenceCountingDevice.java new file mode 100644 index 0000000..a4ad974 --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/ReferenceCountingDevice.java @@ -0,0 +1,57 @@ +/* ReferenceCountingDevice.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +import javax.sound.midi.Receiver; +import javax.sound.midi.Transmitter; + +public class ReferenceCountingDevice { + + public Receiver getReceiverReferenceCounting() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + + public Transmitter getTransmitterReferenceCounting() { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + +} diff --git a/openjdk/icedtea/rt/com/sun/media/sound/SimpleInputDevice.java b/openjdk/icedtea/rt/com/sun/media/sound/SimpleInputDevice.java new file mode 100644 index 0000000..e25a132 --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/SimpleInputDevice.java @@ -0,0 +1,44 @@ +/* SimpleInputDevice.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +public class SimpleInputDevice +{ + +} + diff --git a/openjdk/icedtea/rt/com/sun/media/sound/SimpleInputDeviceProvider.java b/openjdk/icedtea/rt/com/sun/media/sound/SimpleInputDeviceProvider.java new file mode 100644 index 0000000..d89fc16 --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/SimpleInputDeviceProvider.java @@ -0,0 +1,45 @@ +/* SimpleInputDeviceProvider.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +public class SimpleInputDeviceProvider +{ + +} + + diff --git a/openjdk/icedtea/rt/com/sun/media/sound/Toolkit.java b/openjdk/icedtea/rt/com/sun/media/sound/Toolkit.java new file mode 100644 index 0000000..02ff5c3 --- /dev/null +++ b/openjdk/icedtea/rt/com/sun/media/sound/Toolkit.java @@ -0,0 +1,50 @@ +/* Toolkit.java -- stub file. + Copyright (C) 2007 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package com.sun.media.sound; + +import javax.sound.sampled.AudioInputStream; + +public class Toolkit { + + public static AudioInputStream getPCMConvertedAudioInputStream(AudioInputStream as) { + throw new RuntimeException("Not implemented."); + // TODO Auto-generated method stub + + } + +} diff --git a/openjdk/ikvm/awt/IkvmToolkit.java b/openjdk/ikvm/awt/IkvmToolkit.java new file mode 100644 index 0000000..9b575d0 --- /dev/null +++ b/openjdk/ikvm/awt/IkvmToolkit.java @@ -0,0 +1,48 @@ +/* + Copyright (C) 2008 Volker Berlin (i-net software) + Copyright (C) 2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package ikvm.awt; + +import java.awt.Toolkit; +import sun.awt.HeadlessToolkit; + +public interface IkvmToolkit{ + + public sun.print.PrintPeer getPrintPeer(); + + public java.awt.Shape outline(java.awt.Font javaFont, java.awt.font.FontRenderContext frc, String text, float x, float y); + + public static class DefaultToolkit + { + public static IkvmToolkit get() + { + Toolkit tk = Toolkit.getDefaultToolkit(); + if (tk instanceof HeadlessToolkit) + { + tk = ((HeadlessToolkit)tk).getUnderlyingToolkit(); + } + return (IkvmToolkit)tk; + } + } +} diff --git a/openjdk/ikvm/internal/AnnotationAttributeBase.java b/openjdk/ikvm/internal/AnnotationAttributeBase.java new file mode 100644 index 0000000..6b77d2f --- /dev/null +++ b/openjdk/ikvm/internal/AnnotationAttributeBase.java @@ -0,0 +1,726 @@ +/* + Copyright (C) 2005-2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package ikvm.internal; + +import ikvm.lang.CIL; +import java.io.Serializable; +import java.lang.annotation.Annotation; +import java.lang.reflect.Array; +import java.lang.reflect.GenericSignatureFormatError; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Arrays; +import java.util.Iterator; +import java.util.Map; +import java.util.HashMap; +import sun.reflect.annotation.TypeNotPresentExceptionProxy; + +public abstract class AnnotationAttributeBase + extends cli.System.Attribute + implements Annotation, Serializable +{ + private final Class annotationType; + private HashMap values; + private Object[] definition; + private boolean frozen; + + protected AnnotationAttributeBase(Class annotationType) + { + this.annotationType = annotationType; + } + + protected final Object getValue(String name) + { + freeze(); + return values.get(name); + } + + protected final byte getByteValue(String name) + { + freeze(); + return ((Byte)values.get(name)).byteValue(); + } + + protected final boolean getBooleanValue(String name) + { + freeze(); + return ((Boolean)values.get(name)).booleanValue(); + } + + protected final short getShortValue(String name) + { + freeze(); + return ((Short)values.get(name)).shortValue(); + } + + protected final char getCharValue(String name) + { + freeze(); + return ((Character)values.get(name)).charValue(); + } + + protected final int getIntValue(String name) + { + freeze(); + return ((Integer)values.get(name)).intValue(); + } + + protected final float getFloatValue(String name) + { + freeze(); + return ((Float)values.get(name)).floatValue(); + } + + protected final long getLongValue(String name) + { + freeze(); + return ((Long)values.get(name)).longValue(); + } + + protected final double getDoubleValue(String name) + { + freeze(); + return ((Double)values.get(name)).doubleValue(); + } + + protected final synchronized void setValue(String name, Object value) + { + if(frozen || definition != null) + { + throw new IllegalStateException("Annotation properties have already been defined"); + } + try + { + Class type = annotationType.getMethod(name).getReturnType(); + if(type.isEnum()) + { + value = Enum.valueOf(type, value.toString()); + } + else if(type == Class.class) + { + value = ikvm.runtime.Util.getFriendlyClassFromType((cli.System.Type)value); + } + else if(type == boolean.class) + { + value = ikvm.lang.CIL.unbox_boolean(value); + } + else if(type == byte.class) + { + value = ikvm.lang.CIL.unbox_byte(value); + } + else if(type == short.class) + { + value = ikvm.lang.CIL.unbox_short(value); + } + else if(type == char.class) + { + value = ikvm.lang.CIL.unbox_char(value); + } + else if(type == int.class) + { + value = ikvm.lang.CIL.unbox_int(value); + } + else if(type == long.class) + { + value = ikvm.lang.CIL.unbox_long(value); + } + else if(type == float.class) + { + value = ikvm.lang.CIL.unbox_float(value); + } + else if(type == double.class) + { + value = ikvm.lang.CIL.unbox_double(value); + } + else if(type == String.class) + { + // no conversion needed + } + else if(type.isArray()) + { + type = type.getComponentType(); + if(type.isEnum()) + { + cli.System.Array orgarray = (cli.System.Array)value; + Object[] array = (Object[])Array.newInstance(type, orgarray.get_Length()); + for(int i = 0; i < array.length; i++) + { + array[i] = Enum.valueOf(type, orgarray.GetValue(i).toString()); + } + value = array; + } + else if(type == Class.class) + { + cli.System.Type[] orgarray = (cli.System.Type[])value; + Class[] array = new Class[orgarray.length]; + for(int i = 0; i < array.length; i++) + { + array[i] = ikvm.runtime.Util.getFriendlyClassFromType(orgarray[i]); + } + value = array; + } + else + { + // no conversion needed + } + } + else + { + throw new InternalError("Invalid annotation type: " + type); + } + if(values == null) + { + values = new HashMap(); + } + values.put(name, value); + } + catch (NoSuchMethodException x) + { + throw (NoSuchMethodError)new NoSuchMethodError().initCause(x); + } + } + + protected final synchronized void setDefinition(Object[] array) + { + if(frozen || definition != null) + { + throw new IllegalStateException("Annotation properties have already been defined"); + } + definition = array; + } + + @ikvm.lang.Internal + public final Map getValues() + { + return values; + } + + @ikvm.lang.Internal + public final synchronized void freeze() + { + if(!frozen) + { + frozen = true; + if(values == null) + { + values = new HashMap(); + } + if(definition == null) + { + setDefaults(values, annotationType); + } + else + { + // TODO consider checking that the type matches + // (or better yet (?), remove the first two redundant elements from the array) + decodeValues(values, annotationType, annotationType.getClassLoader(), unescapeInvalidSurrogates(definition)); + definition = null; + } + } + } + + private static native Object[] unescapeInvalidSurrogates(Object[] definition); + + private static void decodeValues(HashMap map, Class annotationClass, ClassLoader loader, Object[] array) + { + for (int i = 2; i < array.length; i += 2) + { + String name = (String)array[i]; + try + { + Method method = annotationClass.getDeclaredMethod(name, new Class[0]); + map.put(name, decodeElementValue(array[i + 1], method.getReturnType(), loader)); + } + catch (IllegalAccessException x) + { + // TODO this probably isn't the right exception + throw new IncompatibleClassChangeError(); + } + catch (NoSuchMethodException x) + { + // ignore values for members that are no longer present + } + } + setDefaults(map, annotationClass); + } + + private static void setDefaults(HashMap map, Class annotationClass) + { + for (Method m : annotationClass.getDeclaredMethods()) + { + Object defaultValue = m.getDefaultValue(); + // TODO throw exception if default is missing for method that doesn't yet have a value + if (defaultValue != null && !map.containsKey(m.getName())) + { + map.put(m.getName(), defaultValue); + } + } + } + + private static Class classFromSig(ClassLoader loader, String name) + { + if (name.length() == 1) + { + switch (name.charAt(0)) + { + case 'Z': + return Boolean.TYPE; + case 'B': + return Byte.TYPE; + case 'C': + return Character.TYPE; + case 'S': + return Short.TYPE; + case 'I': + return Integer.TYPE; + case 'F': + return Float.TYPE; + case 'J': + return Long.TYPE; + case 'D': + return Double.TYPE; + case 'V': + return Void.TYPE; + default: + throw new GenericSignatureFormatError(); + } + } + + if (!isValidTypeSig(name, 0, name.length())) + { + throw new GenericSignatureFormatError(); + } + + if (name.charAt(0) == 'L') + { + name = name.substring(1, name.length() - 1).replace('/', '.'); + } + else // must be an array then + { + name = name.replace('/', '.'); + } + try + { + return Class.forName(name, false, loader); + } + catch (ClassNotFoundException x) + { + throw new TypeNotPresentException(name, x); + } + } + + private static boolean isValidTypeSig(String sig, int start, int end) + { + if (start >= end) + { + return false; + } + switch (sig.charAt(start)) + { + case 'L': + return sig.indexOf(';', start + 1) == end - 1; + case '[': + while (sig.charAt(start) == '[') + { + start++; + if (start == end) + { + return false; + } + } + return isValidTypeSig(sig, start, end); + case 'B': + case 'Z': + case 'C': + case 'S': + case 'I': + case 'J': + case 'F': + case 'D': + return start == end - 1; + default: + return false; + } + } + + @ikvm.lang.Internal + public static Object newAnnotation(ClassLoader loader, Object definition) + { + Object[] array = (Object[])definition; + byte tag = CIL.unbox_byte(array[0]); + if (tag != '@') + throw new ClassCastException(); + Object classNameOrClass = array[1]; + Class annotationClass; + if (classNameOrClass instanceof String) + { + annotationClass = classFromSig(loader, (String)classNameOrClass); + if (!annotationClass.isAnnotation()) + { + return null; + } + array[1] = annotationClass; + } + else + { + annotationClass = (Class)classNameOrClass; + } + HashMap map = new HashMap(); + decodeValues(map, annotationClass, loader, array); + return Proxy.newProxyInstance(annotationClass.getClassLoader(), new Class[] { annotationClass }, newAnnotationInvocationHandler(annotationClass, map)); + } + + @ikvm.lang.Internal + public static Object decodeElementValue(Object obj, Class type, ClassLoader loader) + throws IllegalAccessException + { + if (obj instanceof Object[] && CIL.unbox_byte(((Object[])obj)[0]) == '?') + { + Throwable t; + try + { + Object[] error = (Object[])obj; + Class exception = Class.forName((String)error[1]); + t = (Throwable)(error.length == 2 + ? exception.newInstance() + : exception.getConstructor(String.class).newInstance(error[2])); + } + catch (Exception x) + { + t = x; + } + sun.misc.Unsafe.getUnsafe().throwException(t); + } + if (type == Byte.TYPE) + { + return new Byte(CIL.unbox_byte(obj)); + } + else if (type == Boolean.TYPE) + { + return new Boolean(CIL.unbox_boolean(obj)); + } + else if (type == Short.TYPE) + { + return new Short(CIL.unbox_short(obj)); + } + else if (type == Character.TYPE) + { + return new Character(CIL.unbox_char(obj)); + } + else if (type == Integer.TYPE) + { + return new Integer(CIL.unbox_int(obj)); + } + else if (type == Float.TYPE) + { + return new Float(CIL.unbox_float(obj)); + } + else if (type == Long.TYPE) + { + return new Long(CIL.unbox_long(obj)); + } + else if (type == Double.TYPE) + { + return new Double(CIL.unbox_double(obj)); + } + else if (type == String.class) + { + return (String)obj; + } + else if (type == Class.class) + { + Object[] array = (Object[])obj; + byte tag = CIL.unbox_byte(array[0]); + if (tag != 'c') + throw new ClassCastException(); + try + { + return classFromSig(loader, (String)array[1]); + } + catch (TypeNotPresentException x) + { + return new TypeNotPresentExceptionProxy(x.typeName(), x); + } + } + else if (type.isArray()) + { + Object[] array = (Object[])obj; + byte tag = CIL.unbox_byte(array[0]); + if (tag != '[') + throw new ClassCastException(); + type = type.getComponentType(); + Object dst = Array.newInstance(type, array.length - 1); + for (int i = 0; i < array.length - 1; i++) + { + Object val = decodeElementValue(array[i + 1], type, loader); + try + { + Array.set(dst, i, val); + } + catch (IllegalArgumentException _) + { + // JDKBUG emulate JDK bug + throw new ArrayStoreException(val.getClass().getName()); + } + } + return dst; + } + else if (type.isEnum()) + { + Object[] array = (Object[])obj; + byte tag = CIL.unbox_byte(array[0]); + if (tag != 'e') + throw new ClassCastException(); + Class enumClass; + try + { + enumClass = classFromSig(loader, (String)array[1]); + } + catch (TypeNotPresentException x) + { + return new TypeNotPresentExceptionProxy(x.typeName(), x); + } + try + { + return Enum.valueOf(enumClass, (String)array[2]); + } + catch (IllegalArgumentException x) + { + throw new EnumConstantNotPresentException(enumClass, (String)array[2]); + } + } + else // must be an annotation then + { + Object ann = newAnnotation(loader, obj); + if (!type.isInstance(ann)) + { + // JDKBUG if newAnnotation() returns null (because the class is not an annotation), + // the next line will throw a NullPointerException (similar to the JDK) + return newAnnotationTypeMismatchExceptionProxy(ann.getClass() + "[" + ann + "]"); + } + return ann; + } + } + + private final Object writeReplace() + { + freeze(); + return Proxy.newProxyInstance(annotationType.getClassLoader(), + new Class[] { annotationType }, + newAnnotationInvocationHandler(annotationType, values)); + } + + private static native InvocationHandler newAnnotationInvocationHandler(Class type, Map memberValues); + private static native Object newAnnotationTypeMismatchExceptionProxy(String msg); + + public final Class annotationType() + { + return annotationType; + } + + public final boolean Equals(Object o) + { + freeze(); + return equals(annotationType, values, o); + } + + public final int GetHashCode() + { + freeze(); + return hashCode(annotationType, values); + } + + public final String ToString() + { + freeze(); + return toString(annotationType, values); + } + + private static boolean equals(Class type, Map memberValues, Object other) + { + if (type.isInstance(other)) + { + try + { + Method[] methods = type.getDeclaredMethods(); + if (methods.length == memberValues.size()) + { + for (int i = 0; i < methods.length; i++) + { + String key = methods[i].getName(); + Object val = methods[i].invoke(other, new Object[0]); + if (! deepEquals(memberValues.get(key), val)) + { + return false; + } + } + return true; + } + } + catch (IllegalAccessException _) + { + // Ignore exception, like the JDK + } + catch (InvocationTargetException _) + { + // Ignore exception, like the JDK + } + } + return false; + } + + private static boolean deepEquals(Object o1, Object o2) + { + if (o1 == o2) + return true; + + if (o1 == null || o2 == null) + return false; + + if (o1 instanceof boolean[] && o2 instanceof boolean[]) + return Arrays.equals((boolean[]) o1, (boolean[]) o2); + + if (o1 instanceof byte[] && o2 instanceof byte[]) + return Arrays.equals((byte[]) o1, (byte[]) o2); + + if (o1 instanceof char[] && o2 instanceof char[]) + return Arrays.equals((char[]) o1, (char[]) o2); + + if (o1 instanceof short[] && o2 instanceof short[]) + return Arrays.equals((short[]) o1, (short[]) o2); + + if (o1 instanceof int[] && o2 instanceof int[]) + return Arrays.equals((int[]) o1, (int[]) o2); + + if (o1 instanceof float[] && o2 instanceof float[]) + return Arrays.equals((float[]) o1, (float[]) o2); + + if (o1 instanceof long[] && o2 instanceof long[]) + return Arrays.equals((long[]) o1, (long[]) o2); + + if (o1 instanceof double[] && o2 instanceof double[]) + return Arrays.equals((double[]) o1, (double[]) o2); + + if (o1 instanceof Object[] && o2 instanceof Object[]) + return Arrays.equals((Object[]) o1, (Object[]) o2); + + return o1.equals(o2); + } + + private static int deepHashCode(Object obj) + { + if (obj instanceof boolean[]) + return Arrays.hashCode((boolean[]) obj); + + if (obj instanceof byte[]) + return Arrays.hashCode((byte[]) obj); + + if (obj instanceof char[]) + return Arrays.hashCode((char[]) obj); + + if (obj instanceof short[]) + return Arrays.hashCode((short[]) obj); + + if (obj instanceof int[]) + return Arrays.hashCode((int[]) obj); + + if (obj instanceof float[]) + return Arrays.hashCode((float[]) obj); + + if (obj instanceof long[]) + return Arrays.hashCode((long[]) obj); + + if (obj instanceof double[]) + return Arrays.hashCode((double[]) obj); + + if (obj instanceof Object[]) + return Arrays.hashCode((Object[]) obj); + + return obj.hashCode(); + } + + private static int hashCode(Class type, Map memberValues) + { + int h = 0; + Iterator iter = memberValues.keySet().iterator(); + while (iter.hasNext()) + { + Object key = iter.next(); + Object val = memberValues.get(key); + h += deepHashCode(val) ^ 127 * key.hashCode(); + } + return h; + } + + private static String deepToString(Object obj) + { + if (obj instanceof boolean[]) + return Arrays.toString((boolean[]) obj); + + if (obj instanceof byte[]) + return Arrays.toString((byte[]) obj); + + if (obj instanceof char[]) + return Arrays.toString((char[]) obj); + + if (obj instanceof short[]) + return Arrays.toString((short[]) obj); + + if (obj instanceof int[]) + return Arrays.toString((int[]) obj); + + if (obj instanceof float[]) + return Arrays.toString((float[]) obj); + + if (obj instanceof long[]) + return Arrays.toString((long[]) obj); + + if (obj instanceof double[]) + return Arrays.toString((double[]) obj); + + if (obj instanceof Object[]) + return Arrays.toString((Object[]) obj); + + return obj.toString(); + } + + private static String toString(Class type, Map memberValues) + { + StringBuffer sb = new StringBuffer(); + sb.append('@').append(type.getName()).append('('); + String sep = ""; + Iterator iter = memberValues.keySet().iterator(); + while (iter.hasNext()) + { + Object key = iter.next(); + Object val = memberValues.get(key); + sb.append(sep).append(key).append('=').append(deepToString(val)); + sep = ", "; + } + sb.append(')'); + return sb.toString(); + } +} diff --git a/openjdk/ikvm/internal/FieldReflectorBase.java b/openjdk/ikvm/internal/FieldReflectorBase.java new file mode 100644 index 0000000..f98931f --- /dev/null +++ b/openjdk/ikvm/internal/FieldReflectorBase.java @@ -0,0 +1,35 @@ +/* + Copyright (C) 2007 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package ikvm.internal; + +import java.io.ObjectStreamField; + +public abstract class FieldReflectorBase +{ + public abstract ObjectStreamField[] getFields(); + public abstract void getPrimFieldValues(Object obj, byte[] buf); + public abstract void setPrimFieldValues(Object obj, byte[] buf); + public abstract void getObjFieldValues(Object obj, Object[] vals); + public abstract void setObjFieldValues(Object obj, Object[] vals); +} diff --git a/openjdk/ikvm/internal/InterlockedCompareAndSet.java b/openjdk/ikvm/internal/InterlockedCompareAndSet.java new file mode 100644 index 0000000..7c4b473 --- /dev/null +++ b/openjdk/ikvm/internal/InterlockedCompareAndSet.java @@ -0,0 +1,37 @@ +/* + Copyright (C) 2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package ikvm.internal; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.CLASS) +@Target(ElementType.METHOD) +public @interface InterlockedCompareAndSet +{ + String value(); +} diff --git a/openjdk/ikvm/internal/IntrinsicAtomicReferenceFieldUpdater.java b/openjdk/ikvm/internal/IntrinsicAtomicReferenceFieldUpdater.java new file mode 100644 index 0000000..6a9ea19 --- /dev/null +++ b/openjdk/ikvm/internal/IntrinsicAtomicReferenceFieldUpdater.java @@ -0,0 +1,62 @@ +/* + Copyright (C) 2010 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package ikvm.internal; + +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; + +// This is the base class for intrinsified AtomicReferenceFieldUpdater. +// The real class of an intrinsic ARFU is a subclass of this, but since it +// is not visible to Java code, this class serves as the class. + +public class IntrinsicAtomicReferenceFieldUpdater extends AtomicReferenceFieldUpdater +{ + protected IntrinsicAtomicReferenceFieldUpdater() + { + } + + public boolean compareAndSet(T obj, V expect, V update) + { + throw new AbstractMethodError(); + } + + public final boolean weakCompareAndSet(T obj, V expect, V update) + { + return compareAndSet(obj, expect, update); + } + + public void set(T obj, V newValue) + { + throw new AbstractMethodError(); + } + + public final void lazySet(T obj, V newValue) + { + set(obj, newValue); + } + + public V get(T obj) + { + throw new AbstractMethodError(); + } +} diff --git a/openjdk/ikvm/internal/IntrinsicThreadLocal.java b/openjdk/ikvm/internal/IntrinsicThreadLocal.java new file mode 100644 index 0000000..abfb4e9 --- /dev/null +++ b/openjdk/ikvm/internal/IntrinsicThreadLocal.java @@ -0,0 +1,41 @@ +/* + Copyright (C) 2010 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package ikvm.internal; + +// This is the base class for intrinsified ThreadLocals, it's main purpose +// is to avoid having to add a remove() method to every generated class, +// but it also gives us some maneuvering room should a future JDK version +// change ThreadLocal. +// Note that because this class is abstract, getClass() on an intrinsified +// ThreadLocal instance will return java.lang.ThreadLocal instead of this class. +// We don't use HideFromJava for this, because that would make the life of +// the runtime/ikvmc more difficult (because it needs a TypeWrapper for this class). + +public abstract class IntrinsicThreadLocal extends ThreadLocal +{ + public final void remove() + { + set(null); + } +} diff --git a/openjdk/ikvm/internal/JNI.java b/openjdk/ikvm/internal/JNI.java new file mode 100644 index 0000000..2b7aa9d --- /dev/null +++ b/openjdk/ikvm/internal/JNI.java @@ -0,0 +1,114 @@ +/* + Copyright (C) 2010 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package ikvm.internal; + +@ikvm.lang.Internal +public final class JNI +{ + public static final Object NULL = null; + public static final boolean TRUE = true; + public static final boolean FALSE = false; + public static final boolean JNI_TRUE = true; + public static final boolean JNI_FALSE = false; + + public static final String JNU_JAVAIOPKG = "java.io."; + public static final String JNU_JAVANETPKG = "java.net."; + + public static long JVM_CurrentTimeMillis(JNIEnv env, int ignored) + { + return System.currentTimeMillis(); + } + + public static void JNU_ThrowNullPointerException(JNIEnv env, String message) + { + env.Throw(new NullPointerException(message)); + } + + public static void JNU_ThrowByName(JNIEnv env, String exceptionClass, String message) + { + if (exceptionClass.equals("java.net.SocketException")) + { + env.Throw(new java.net.SocketException(message)); + } + else if (exceptionClass.equals("java.net.SocketTimeoutException")) + { + env.Throw(new java.net.SocketTimeoutException(message)); + } + else if (exceptionClass.equals("java.net.PortUnreachableException")) + { + env.Throw(new java.net.PortUnreachableException(message)); + } + else if (exceptionClass.equals("java.io.InterruptedIOException")) + { + env.Throw(new java.io.InterruptedIOException(message)); + } + else + { + try + { + env.ThrowNew(Class.forName(exceptionClass), message); + } + catch (ClassNotFoundException x) + { + env.Throw(x); + } + } + } + + public static final class JNIEnv + { + private Throwable pendingException; + + public void Throw(Throwable t) + { + pendingException = t; + } + + public void ThrowNew(Class c, String msg) + { + try + { + pendingException = (Throwable)c.getConstructor(String.class).newInstance(msg); + } + catch (Exception x) + { + pendingException = x; + } + } + + public Throwable ExceptionOccurred() + { + return pendingException; + } + + public void ThrowPendingException() + { + if (pendingException != null) + { + sun.misc.Unsafe.getUnsafe().throwException(pendingException); + } + } + } +} diff --git a/openjdk/ikvm/internal/NotYetImplementedError.java b/openjdk/ikvm/internal/NotYetImplementedError.java new file mode 100644 index 0000000..e2978ba --- /dev/null +++ b/openjdk/ikvm/internal/NotYetImplementedError.java @@ -0,0 +1,37 @@ +/* + Copyright (C) 2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package ikvm.internal; + +public final class NotYetImplementedError extends Error +{ + public NotYetImplementedError() + { + this("This method has not yet been implemented in IKVM.NET."); + } + + public NotYetImplementedError(String message) + { + super(message); + } +} diff --git a/openjdk/ikvm/internal/Serialization.java b/openjdk/ikvm/internal/Serialization.java new file mode 100644 index 0000000..28fec14 --- /dev/null +++ b/openjdk/ikvm/internal/Serialization.java @@ -0,0 +1,47 @@ +/* + Copyright (C) 2009-2010 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package ikvm.internal; + +import cli.System.Runtime.Serialization.SerializationInfo; +import cli.System.Security.Permissions.SecurityAction; +import cli.System.Security.Permissions.SecurityPermissionAttribute; +import java.io.InteropObjectInputStream; +import java.io.InteropObjectOutputStream; + +public final class Serialization +{ + private Serialization() { } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.Demand, SerializationFormatter = true) + public static void writeObject(Object obj, SerializationInfo info) + { + InteropObjectOutputStream.writeObject(obj, info); + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.Demand, SerializationFormatter = true) + public static void readObject(Object obj, SerializationInfo info) + { + InteropObjectInputStream.readObject(obj, info); + } +} diff --git a/openjdk/ikvm/internal/Winsock.java b/openjdk/ikvm/internal/Winsock.java new file mode 100644 index 0000000..69a1eb2 --- /dev/null +++ b/openjdk/ikvm/internal/Winsock.java @@ -0,0 +1,982 @@ +/* + Copyright (C) 2010-2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package ikvm.internal; + +import cli.System.Net.EndPoint; +import cli.System.Net.IPAddress; +import cli.System.Net.IPEndPoint; +import cli.System.Net.Sockets.AddressFamily; +import cli.System.Net.Sockets.IOControlCode; +import cli.System.Net.Sockets.IPv6MulticastOption; +import cli.System.Net.Sockets.LingerOption; +import cli.System.Net.Sockets.MulticastOption; +import cli.System.Net.Sockets.ProtocolType; +import cli.System.Net.Sockets.SocketFlags; +import cli.System.Net.Sockets.SocketOptionName; +import cli.System.Net.Sockets.SocketOptionLevel; +import cli.System.Net.Sockets.SocketShutdown; +import cli.System.Net.Sockets.SocketType; +import ikvm.lang.CIL; + +@ikvm.lang.Internal +public final class Winsock +{ + private Winsock() { } + + // remember the last error code + @cli.System.ThreadStaticAttribute.Annotation + private static int lastError; + + // Error Codes + public static final int WSA_NOT_ENOUGH_MEMORY = 8; + public static final int WSA_OPERATION_ABORTED = 995; + public static final int WSAEINTR = 10004; + public static final int WSAEACCES = 10013; + public static final int WSAEFAULT = 10014; + public static final int WSAEINVAL = 10022; + public static final int WSAEMFILE = 10024; + public static final int WSAEWOULDBLOCK = 10035; + public static final int WSAEINPROGRESS = 10036; + public static final int WSAEALREADY = 10037; + public static final int WSAENOTSOCK = 10038; + public static final int WSAEDESTADDRREQ = 10039; + public static final int WSAEMSGSIZE = 10040; + public static final int WSAEPROTOTYPE = 10041; + public static final int WSAENOPROTOOPT = 10042; + public static final int WSAEPROTONOSUPPORT = 10043; + public static final int WSAESOCKTNOSUPPORT = 10044; + public static final int WSAEOPNOTSUPP = 10045; + public static final int WSAEPFNOSUPPORT = 10046; + public static final int WSAEAFNOSUPPORT = 10047; + public static final int WSAEADDRINUSE = 10048; + public static final int WSAEADDRNOTAVAIL = 10049; + public static final int WSAENETDOWN = 10050; + public static final int WSAENETUNREACH = 10051; + public static final int WSAENETRESET = 10052; + public static final int WSAECONNABORTED = 10053; + public static final int WSAECONNRESET = 10054; + public static final int WSAENOBUFS = 10055; + public static final int WSAEISCONN = 10056; + public static final int WSAENOTCONN = 10057; + public static final int WSAESHUTDOWN = 10058; + public static final int WSAETIMEDOUT = 10060; + public static final int WSAECONNREFUSED = 10061; + public static final int WSAEHOSTDOWN = 10064; + public static final int WSAEHOSTUNREACH = 10065; + public static final int WSAEPROCLIM = 10067; + public static final int WSASYSNOTREADY = 10091; + public static final int WSAVERNOTSUPPORTED = 10092; + public static final int WSANOTINITIALISED = 10093; + public static final int WSAEDISCON = 10101; + public static final int WSATYPE_NOT_FOUND = 10109; + public static final int WSAHOST_NOT_FOUND = 11001; + public static final int WSATRY_AGAIN = 11002; + public static final int WSANO_RECOVERY = 11003; + public static final int WSANO_DATA = 11004; + + // Other constants + public static final int SOCKET_ERROR = -1; + public static final cli.System.Net.Sockets.Socket INVALID_SOCKET = null; + + public static final int AF_INET = AddressFamily.InterNetwork; + public static final int AF_INET6 = AddressFamily.InterNetworkV6; + + public static final int SOCK_STREAM = SocketType.Stream; + public static final int SOCK_DGRAM = SocketType.Dgram; + + public static final int SD_RECEIVE = SocketShutdown.Receive; + public static final int SD_SEND = SocketShutdown.Send; + public static final int SD_BOTH = SocketShutdown.Both; + + public static final int SOL_SOCKET = SocketOptionLevel.Socket; + public static final int IPPROTO_TCP = SocketOptionLevel.Tcp; + public static final int IPPROTO_IP = SocketOptionLevel.IP; + public static final int IPPROTO_IPV6 = SocketOptionLevel.IPv6; + + public static final int TCP_NODELAY = SocketOptionName.NoDelay; + public static final int SO_OOBINLINE = SocketOptionName.OutOfBandInline; + public static final int SO_LINGER = SocketOptionName.Linger; + public static final int SO_SNDBUF = SocketOptionName.SendBuffer; + public static final int SO_RCVBUF = SocketOptionName.ReceiveBuffer; + public static final int SO_KEEPALIVE = SocketOptionName.KeepAlive; + public static final int SO_REUSEADDR = SocketOptionName.ReuseAddress; + public static final int SO_EXCLUSIVEADDRUSE = SocketOptionName.ExclusiveAddressUse; + public static final int SO_BROADCAST = SocketOptionName.Broadcast; + public static final int SO_RCVTIMEO = SocketOptionName.ReceiveTimeout; + public static final int SO_ERROR = SocketOptionName.Error; + public static final int IP_MULTICAST_IF = SocketOptionName.MulticastInterface; + public static final int IP_MULTICAST_LOOP = SocketOptionName.MulticastLoopback; + public static final int IP_TOS = SocketOptionName.TypeOfService; + public static final int IP_MULTICAST_TTL = SocketOptionName.MulticastTimeToLive; + public static final int IP_ADD_MEMBERSHIP = SocketOptionName.AddMembership; + public static final int IP_DROP_MEMBERSHIP = SocketOptionName.DropMembership; + public static final int IPV6_MULTICAST_IF = SocketOptionName.MulticastInterface; + public static final int IPV6_MULTICAST_LOOP = SocketOptionName.MulticastLoopback; + public static final int IPV6_MULTICAST_HOPS = SocketOptionName.MulticastTimeToLive; + public static final int IPV6_ADD_MEMBERSHIP = SocketOptionName.AddMembership; + public static final int IPV6_DROP_MEMBERSHIP = SocketOptionName.DropMembership; + public static final int IPV6_V6ONLY = 27; + public static final int IPV6_TCLASS = 39; + + public static final int SIO_UDP_CONNRESET = 0x9800000C; + + public static final int MSG_PEEK = SocketFlags.Peek; + public static final int MSG_OOB = SocketFlags.OutOfBand; + + public static final int FIONREAD = (int)IOControlCode.DataToRead; + public static final int FIONBIO = (int)IOControlCode.NonBlockingIO; + + public static final int MAX_PACKET_LEN = 0xFFFF; + + public static int WSAGetLastError() + { + return lastError; + } + + public static void WSASetLastError(int err) + { + lastError = err; + } + + public static int WSASendDisconnect(cli.System.Net.Sockets.Socket socket) + { + if (socket == null) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + socket.Shutdown(SocketShutdown.wrap(SocketShutdown.Send)); + return 0; + } + catch (cli.System.Net.Sockets.SocketException x) + { + lastError = x.get_ErrorCode(); + return SOCKET_ERROR; + } + catch (cli.System.ObjectDisposedException _) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + } + + public static int WSAIoctl(cli.System.Net.Sockets.Socket socket, int ioControlCode, boolean optionInValue) + { + byte[] in = new byte[4]; + in[0] = optionInValue ? (byte)1 : (byte)0; + byte[] out = new byte[4]; + return WSAIoctl(socket, ioControlCode, in, out); + } + + public static int WSAIoctl(cli.System.Net.Sockets.Socket socket, int ioControlCode, byte[] optionInValue, byte[] optionOutValue) + { + if (socket == null) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + if (false) throw new cli.System.InvalidOperationException(); + if (ioControlCode == FIONBIO) + { + // it's illegal to meddle with the blocking mode via IOControl + socket.set_Blocking(optionInValue[0] == 0); + } + else if (ioControlCode == FIONREAD) + { + int avail = socket.get_Available(); + optionOutValue[0] = (byte)(avail >> 0); + optionOutValue[1] = (byte)(avail >> 8); + optionOutValue[2] = (byte)(avail >> 16); + optionOutValue[3] = (byte)(avail >> 24); + } + else + { + socket.IOControl(ioControlCode, optionInValue, optionOutValue); + } + return 0; + } + catch (cli.System.Net.Sockets.SocketException x) + { + lastError = x.get_ErrorCode(); + return SOCKET_ERROR; + } + catch (cli.System.ObjectDisposedException _) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + catch (cli.System.InvalidOperationException _) + { + lastError = WSAEINVAL; + return SOCKET_ERROR; + } + } + + public static int ioctlsocket(cli.System.Net.Sockets.Socket s, int cmd, int[] argp) + { + byte[] in = cli.System.BitConverter.GetBytes(argp[0]); + byte[] out = new byte[4]; + int ret = WSAIoctl(s, cmd, in, out); + argp[0] = cli.System.BitConverter.ToInt32(out, 0); + return ret; + } + + public static int ioctlsocket(cli.System.Net.Sockets.Socket s, int cmd, int arg) + { + byte[] in = cli.System.BitConverter.GetBytes(arg); + return WSAIoctl(s, cmd, in, in); + } + + public static cli.System.Net.Sockets.Socket socket(int af, int type, int protocol) + { + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + return new cli.System.Net.Sockets.Socket(AddressFamily.wrap(af), SocketType.wrap(type), ProtocolType.wrap(protocol)); + } + catch (cli.System.Net.Sockets.SocketException x) + { + lastError = x.get_ErrorCode(); + return INVALID_SOCKET; + } + catch (cli.System.ObjectDisposedException _) + { + lastError = WSAENOTSOCK; + return INVALID_SOCKET; + } + } + + public static int closesocket(cli.System.Net.Sockets.Socket socket) + { + if (socket == null) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + socket.Close(); + return 0; + } + + public static final class linger + { + public int l_onoff; + public int l_linger; + + LingerOption ToLingerOption() + { + return new LingerOption(l_onoff != 0, l_linger); + } + } + + public static final class ip_mreq + { + public final in_addr imr_multiaddr = new in_addr(); + public final in_addr imr_interface = new in_addr(); + + MulticastOption ToMulticastOption() + { + return new MulticastOption(imr_multiaddr.ToIPAddress(), imr_interface.ToIPAddress()); + } + } + + public static final class in_addr + { + public int s_addr; + + IPAddress ToIPAddress() + { + return new IPAddress(s_addr & 0xFFFFFFFFL); + } + } + + public static final class ipv6_mreq + { + public in6_addr ipv6mr_multiaddr; + public int ipv6mr_interface; + + IPv6MulticastOption ToIPv6MulticastOption() + { + return new IPv6MulticastOption(ipv6mr_multiaddr.addr, ipv6mr_interface & 0xFFFFFFFFL); + } + } + + public static final class in6_addr + { + IPAddress addr; + + public byte[] s6_bytes() + { + return addr == null ? new byte[16] : addr.GetAddressBytes(); + } + + public static in6_addr FromSockAddr(IIPEndPointWrapper ep) + { + in6_addr addr = new in6_addr(); + addr.addr = ep.get().get_Address(); + return addr; + } + } + + public static int getsockopt(cli.System.Net.Sockets.Socket socket, int level, int optname, Object optval) + { + if (socket == null) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + Object val = socket.GetSocketOption(SocketOptionLevel.wrap(level), SocketOptionName.wrap(optname)); + if (val instanceof cli.System.Int32) + { + if (optval instanceof in_addr) + { + ((in_addr)optval).s_addr = CIL.unbox_int(val); + } + else + { + ((cli.System.Array)optval).SetValue(val, 0); + } + } + else if (val instanceof LingerOption) + { + LingerOption lo = (LingerOption)val; + linger ling = (linger)optval; + ling.l_onoff = lo.get_Enabled() ? 1 : 0; + // FXBUG the linger time is treated as a signed short instead of an unsiged short + ling.l_linger = lo.get_LingerTime() & 0xFFFF; + } + else + { + lastError = WSAEINVAL; + return SOCKET_ERROR; + } + return 0; + } + catch (cli.System.Net.Sockets.SocketException x) + { + lastError = x.get_ErrorCode(); + return SOCKET_ERROR; + } + catch (cli.System.ObjectDisposedException _) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + } + + public static int connect(cli.System.Net.Sockets.Socket socket, IIPEndPointWrapper epw) + { + if (socket == null) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + IPEndPoint ep = epw.get(); + if (ep == null) + { + // it is a disconnect request, we must connect to the Any address + if (socket.get_AddressFamily().Value == AddressFamily.InterNetwork) + { + ep = new IPEndPoint(cli.System.Net.IPAddress.Any, 0); + } + else + { + ep = new IPEndPoint(cli.System.Net.IPAddress.IPv6Any, 0); + } + } + else + { + ep = v4mapped(socket, ep); + } + if (socket.get_SocketType().Value == SocketType.Dgram) + { + // NOTE we use async connect to work around the issue that the .NET Socket class disallows sync Connect after the socket has received WSAECONNRESET + socket.EndConnect(socket.BeginConnect(ep, null, null)); + } + else + { + socket.Connect(ep); + } + return 0; + } + catch (cli.System.Net.Sockets.SocketException x) + { + lastError = x.get_ErrorCode(); + return SOCKET_ERROR; + } + catch (cli.System.ObjectDisposedException _) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + } + + private static IPEndPoint v4mapped(cli.System.Net.Sockets.Socket socket, IPEndPoint ep) + { + // when binding an IPv6 socket to an IPv4 address, we need to use a mapped v4 address + if (socket.get_AddressFamily().Value == AF_INET6 && ep.get_AddressFamily().Value == AF_INET) + { + byte[] v4 = ep.get_Address().GetAddressBytes(); + if (v4[0] == 0 && v4[1] == 0 && v4[2] == 0 && v4[3] == 0) + { + return new IPEndPoint(IPAddress.IPv6Any, ep.get_Port()); + } + else + { + byte[] v6 = new byte[16]; + v6[10] = -1; + v6[11] = -1; + v6[12] = v4[0]; + v6[13] = v4[1]; + v6[14] = v4[2]; + v6[15] = v4[3]; + return new IPEndPoint(new IPAddress(v6), ep.get_Port()); + } + } + return ep; + } + + public static int bind(cli.System.Net.Sockets.Socket socket, IIPEndPointWrapper ep) + { + if (socket == null) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + socket.Bind(v4mapped(socket, ep.get())); + return 0; + } + catch (cli.System.Net.Sockets.SocketException x) + { + lastError = x.get_ErrorCode(); + return SOCKET_ERROR; + } + catch (cli.System.ObjectDisposedException _) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + } + + public static int listen(cli.System.Net.Sockets.Socket socket, int count) + { + if (socket == null) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + socket.Listen(count); + return 0; + } + catch (cli.System.Net.Sockets.SocketException x) + { + lastError = x.get_ErrorCode(); + return SOCKET_ERROR; + } + catch (cli.System.ObjectDisposedException _) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + } + + public static int shutdown(cli.System.Net.Sockets.Socket socket, int how) + { + if (socket == null) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + socket.Shutdown(SocketShutdown.wrap(how)); + return 0; + } + catch (cli.System.Net.Sockets.SocketException x) + { + lastError = x.get_ErrorCode(); + return SOCKET_ERROR; + } + catch (cli.System.ObjectDisposedException _) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + } + + public static final class fd_set + { + cli.System.Collections.ArrayList list = new cli.System.Collections.ArrayList(); + } + + public static final class timeval + { + public long tv_sec; + public long tv_usec; + } + + public static void FD_ZERO(fd_set set) + { + set.list.Clear(); + } + + public static void FD_SET(cli.System.Net.Sockets.Socket socket, fd_set set) + { + set.list.Add(socket); + } + + public static boolean FD_ISSET(cli.System.Net.Sockets.Socket socket, fd_set set) + { + return set.list.Contains(socket); + } + + private static cli.System.Collections.ArrayList copy(fd_set set) + { + return set == null ? null : (cli.System.Collections.ArrayList)set.list.Clone(); + } + + public static int select(fd_set readfds, fd_set writefds, fd_set exceptfds, timeval timeout) + { + long expiration; + long current = cli.System.DateTime.get_UtcNow().get_Ticks(); + if (timeout == null) + { + // FXBUG documentation says that -1 will block forever, but in fact it returns immediately, + // so we simulate timeout with a large expiration + expiration = Long.MAX_VALUE; + } + else + { + long timeout100nanos = Math.min(Long.MAX_VALUE / 10, timeout.tv_usec) * 10 + Math.min(Long.MAX_VALUE / 10000000, timeout.tv_sec) * 10000000; + expiration = current + Math.min(Long.MAX_VALUE - current, timeout100nanos); + } + try + { + if (false) throw new cli.System.ArgumentNullException(); + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + for (; ; ) + { + cli.System.Collections.ArrayList checkRead = copy(readfds); + cli.System.Collections.ArrayList checkWrite = copy(writefds); + cli.System.Collections.ArrayList checkError = copy(exceptfds); + int microSeconds = (int)Math.min(Integer.MAX_VALUE, (expiration - current) / 10); + cli.System.Net.Sockets.Socket.Select(checkRead, checkWrite, checkError, microSeconds); + int count = 0; + if (checkRead != null) + { + count += checkRead.get_Count(); + } + if (checkWrite != null) + { + count += checkWrite.get_Count(); + } + if (checkError != null) + { + count += checkError.get_Count(); + } + current = cli.System.DateTime.get_UtcNow().get_Ticks(); + if (count != 0 || current >= expiration) + { + if (readfds != null) + { + readfds.list = checkRead; + } + if (writefds != null) + { + writefds.list = checkWrite; + } + if (exceptfds != null) + { + exceptfds.list = checkError; + } + return count; + } + } + } + catch (cli.System.ArgumentNullException _) + { + lastError = WSAEINVAL; + return SOCKET_ERROR; + } + catch (cli.System.Net.Sockets.SocketException x) + { + lastError = x.get_ErrorCode(); + return SOCKET_ERROR; + } + catch (cli.System.ObjectDisposedException _) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + } + + public static int send(cli.System.Net.Sockets.Socket socket, byte[] buf, int len, int flags) + { + return send(socket, buf, 0, len, flags); + } + + public static int send(cli.System.Net.Sockets.Socket socket, byte[] buf, int off, int len, int flags) + { + if (socket == null) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + try + { + if (false) throw new cli.System.ArgumentException(); + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + return socket.Send(buf, off, len, SocketFlags.wrap(flags)); + } + catch (cli.System.ArgumentException _) + { + lastError = WSAEINVAL; + return SOCKET_ERROR; + } + catch (cli.System.Net.Sockets.SocketException x) + { + lastError = x.get_ErrorCode(); + return SOCKET_ERROR; + } + catch (cli.System.ObjectDisposedException _) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + } + + public static int recv(cli.System.Net.Sockets.Socket socket, byte[] buf, int len, int flags) + { + return recv(socket, buf, 0, len, flags); + } + + public static int recv(cli.System.Net.Sockets.Socket socket, byte[] buf, int off, int len, int flags) + { + if (socket == null) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + try + { + if (false) throw new cli.System.ArgumentException(); + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + return socket.Receive(buf, off, len, SocketFlags.wrap(flags)); + } + catch (cli.System.ArgumentException _) + { + lastError = WSAEINVAL; + return SOCKET_ERROR; + } + catch (cli.System.Net.Sockets.SocketException x) + { + lastError = x.get_ErrorCode(); + return SOCKET_ERROR; + } + catch (cli.System.ObjectDisposedException _) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + } + + public static int sendto(cli.System.Net.Sockets.Socket socket, byte[] buf, int off, int len, int flags, IIPEndPointWrapper to) + { + if (socket == null) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + try + { + if (false) throw new cli.System.ArgumentException(); + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + if (to == null) + { + return socket.Send(buf, off, len, SocketFlags.wrap(flags)); + } + else + { + return socket.SendTo(buf, off, len, SocketFlags.wrap(flags), v4mapped(socket, to.get())); + } + } + catch (cli.System.ArgumentException _) + { + lastError = WSAEINVAL; + return SOCKET_ERROR; + } + catch (cli.System.Net.Sockets.SocketException x) + { + // on Linux we get a WSAECONNREFUSED when sending to an unreachable port/destination, so ignore that + if (x.get_ErrorCode() == WSAECONNREFUSED) + { + return 0; + } + lastError = x.get_ErrorCode(); + return SOCKET_ERROR; + } + catch (cli.System.ObjectDisposedException _) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + } + + public static int recvfrom(cli.System.Net.Sockets.Socket socket, byte[] buf, int len, int flags, IIPEndPointWrapper from) + { + return recvfrom(socket, buf, 0, len, flags, from); + } + + public static int recvfrom(cli.System.Net.Sockets.Socket socket, byte[] buf, int off, int len, int flags, IIPEndPointWrapper from) + { + if (socket == null) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + try + { + if (false) throw new cli.System.ArgumentException(); + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + EndPoint[] ep = new EndPoint[] { socket.get_AddressFamily().Value == AF_INET6 ? new IPEndPoint(IPAddress.IPv6Any, 0) : new IPEndPoint(0, 0) }; + try + { + return socket.ReceiveFrom(buf, off, len, SocketFlags.wrap(flags), ep); + } + finally + { + if (from != null) + { + from.set((IPEndPoint)ep[0]); + } + } + } + catch (cli.System.ArgumentException _) + { + lastError = WSAEINVAL; + return SOCKET_ERROR; + } + catch (cli.System.Net.Sockets.SocketException x) + { + lastError = x.get_ErrorCode(); + return SOCKET_ERROR; + } + catch (cli.System.ObjectDisposedException _) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + } + + public static int setsockopt(cli.System.Net.Sockets.Socket s, int level, int optname, Object optval) + { + if (s == null) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + try + { + if (false) throw new cli.System.ArgumentException(); + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + if (optval instanceof Boolean) + { + s.SetSocketOption(SocketOptionLevel.wrap(level), SocketOptionName.wrap(optname), ((Boolean)optval).booleanValue()); + } + else if (optval instanceof Integer) + { + s.SetSocketOption(SocketOptionLevel.wrap(level), SocketOptionName.wrap(optname), ((Integer)optval).intValue()); + } + else if (optval instanceof linger) + { + s.set_LingerState(((linger)optval).ToLingerOption()); + } + else if (optval instanceof ip_mreq) + { + s.SetSocketOption(SocketOptionLevel.wrap(level), SocketOptionName.wrap(optname), ((ip_mreq)optval).ToMulticastOption()); + } + else if (optval instanceof ipv6_mreq) + { + s.SetSocketOption(SocketOptionLevel.wrap(level), SocketOptionName.wrap(optname), ((ipv6_mreq)optval).ToIPv6MulticastOption()); + } + else if (optval instanceof in_addr) + { + s.SetSocketOption(SocketOptionLevel.wrap(level), SocketOptionName.wrap(optname), ((in_addr)optval).s_addr); + } + else + { + lastError = WSAEINVAL; + return SOCKET_ERROR; + } + return 0; + } + catch (cli.System.ArgumentException _) + { + lastError = WSAEINVAL; + return SOCKET_ERROR; + } + catch (cli.System.Net.Sockets.SocketException x) + { + lastError = x.get_ErrorCode(); + return SOCKET_ERROR; + } + catch (cli.System.ObjectDisposedException _) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + } + + public static cli.System.Net.Sockets.Socket accept(cli.System.Net.Sockets.Socket s, IIPEndPointWrapper ep) + { + if (s == null) + { + lastError = WSAENOTSOCK; + return INVALID_SOCKET; + } + try + { + if (false) throw new cli.System.InvalidOperationException(); + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + cli.System.Net.Sockets.Socket remote = s.Accept(); + if (ep != null) + { + ep.set((IPEndPoint)remote.get_RemoteEndPoint()); + } + return remote; + } + catch (cli.System.ObjectDisposedException _) + { + lastError = WSAENOTSOCK; + return INVALID_SOCKET; + } + catch (cli.System.InvalidOperationException _) + { + lastError = WSAEINVAL; + return INVALID_SOCKET; + } + catch (cli.System.Net.Sockets.SocketException x) + { + lastError = x.get_ErrorCode(); + return INVALID_SOCKET; + } + } + + public interface IIPEndPointWrapper + { + void set(IPEndPoint value); + IPEndPoint get(); + } + + public static int getsockname(cli.System.Net.Sockets.Socket s, IIPEndPointWrapper name) + { + if (s == null) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + IPEndPoint ep = (IPEndPoint)s.get_LocalEndPoint(); + if (ep == null) + { + lastError = WSAEINVAL; + return SOCKET_ERROR; + } + name.set(ep); + return 0; + } + catch (ClassCastException _) + { + lastError = WSAEOPNOTSUPP; + return SOCKET_ERROR; + } + catch (cli.System.ObjectDisposedException _) + { + lastError = WSAENOTSOCK; + return SOCKET_ERROR; + } + catch (cli.System.Net.Sockets.SocketException x) + { + lastError = x.get_ErrorCode(); + return SOCKET_ERROR; + } + } + + public static int ntohl(int address) + { + return Integer.reverseBytes(address); + } + + public static int htonl(int address) + { + return Integer.reverseBytes(address); + } + + public static int ntohs(int port) + { + return Short.reverseBytes((short)port) & 0xFFFF; + } + + public static int htons(int port) + { + return Short.reverseBytes((short)port) & 0xFFFF; + } +} diff --git a/openjdk/java/awt/Font.java b/openjdk/java/awt/Font.java new file mode 100644 index 0000000..d99c675 --- /dev/null +++ b/openjdk/java/awt/Font.java @@ -0,0 +1,2640 @@ +/* + * Copyright (c) 1995, 2013, 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 java.awt; + +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.font.LineMetrics; +import java.awt.font.TextAttribute; +import java.awt.font.TextLayout; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.peer.FontPeer; +import java.io.*; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.SoftReference; +import java.lang.ref.WeakReference; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.text.AttributedCharacterIterator.Attribute; +import java.text.CharacterIterator; +import java.text.StringCharacterIterator; +import java.util.Collections; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import sun.font.StandardGlyphVector; + +import cli.System.IntPtr; +import cli.System.Drawing.FontFamily; +import cli.System.Drawing.GraphicsUnit; +import cli.System.Drawing.Text.PrivateFontCollection; +import cli.System.Runtime.InteropServices.DllImportAttribute; + +import sun.font.AttributeMap; +import sun.font.AttributeValues; +import sun.font.CompositeFont; +import sun.font.CreatedFontTracker; +import sun.font.Font2D; +import sun.font.Font2DHandle; +import sun.font.FontAccess; +import sun.font.FontManager; +import sun.font.FontManagerFactory; +import sun.font.FontUtilities; +import sun.font.GlyphLayout; +import sun.font.FontLineMetrics; +import sun.font.CoreMetrics; +import sun.font.SunFontManager; + +import static sun.font.EAttribute.*; + +/** + * The Font class represents fonts, which are used to + * render text in a visible way. + * A font provides the information needed to map sequences of + * characters to sequences of glyphs + * and to render sequences of glyphs on Graphics and + * Component objects. + * + *

Characters and Glyphs

+ * + * A character is a symbol that represents an item such as a letter, + * a digit, or punctuation in an abstract way. For example, 'g', + * LATIN SMALL LETTER G, is a character. + *

+ * A glyph is a shape used to render a character or a sequence of + * characters. In simple writing systems, such as Latin, typically one glyph + * represents one character. In general, however, characters and glyphs do not + * have one-to-one correspondence. For example, the character 'á' + * LATIN SMALL LETTER A WITH ACUTE, can be represented by + * two glyphs: one for 'a' and one for '´'. On the other hand, the + * two-character string "fi" can be represented by a single glyph, an + * "fi" ligature. In complex writing systems, such as Arabic or the South + * and South-East Asian writing systems, the relationship between characters + * and glyphs can be more complicated and involve context-dependent selection + * of glyphs as well as glyph reordering. + * + * A font encapsulates the collection of glyphs needed to render a selected set + * of characters as well as the tables needed to map sequences of characters to + * corresponding sequences of glyphs. + * + *

Physical and Logical Fonts

+ * + * The Java Platform distinguishes between two kinds of fonts: + * physical fonts and logical fonts. + *

+ * Physical fonts are the actual font libraries containing glyph data + * and tables to map from character sequences to glyph sequences, using a font + * technology such as TrueType or PostScript Type 1. + * All implementations of the Java Platform must support TrueType fonts; + * support for other font technologies is implementation dependent. + * Physical fonts may use names such as Helvetica, Palatino, HonMincho, or + * any number of other font names. + * Typically, each physical font supports only a limited set of writing + * systems, for example, only Latin characters or only Japanese and Basic + * Latin. + * The set of available physical fonts varies between configurations. + * Applications that require specific fonts can bundle them and instantiate + * them using the {@link #createFont createFont} method. + *

+ * Logical fonts are the five font families defined by the Java + * platform which must be supported by any Java runtime environment: + * Serif, SansSerif, Monospaced, Dialog, and DialogInput. + * These logical fonts are not actual font libraries. Instead, the logical + * font names are mapped to physical fonts by the Java runtime environment. + * The mapping is implementation and usually locale dependent, so the look + * and the metrics provided by them vary. + * Typically, each logical font name maps to several physical fonts in order to + * cover a large range of characters. + *

+ * Peered AWT components, such as {@link Label Label} and + * {@link TextField TextField}, can only use logical fonts. + *

+ * For a discussion of the relative advantages and disadvantages of using + * physical or logical fonts, see the + * Internationalization FAQ + * document. + * + *

Font Faces and Names

+ * + * A Font + * can have many faces, such as heavy, medium, oblique, gothic and + * regular. All of these faces have similar typographic design. + *

+ * There are three different names that you can get from a + * Font object. The logical font name is simply the + * name that was used to construct the font. + * The font face name, or just font name for + * short, is the name of a particular font face, like Helvetica Bold. The + * family name is the name of the font family that determines the + * typographic design across several faces, like Helvetica. + *

+ * The Font class represents an instance of a font face from + * a collection of font faces that are present in the system resources + * of the host system. As examples, Arial Bold and Courier Bold Italic + * are font faces. There can be several Font objects + * associated with a font face, each differing in size, style, transform + * and font features. + *

+ * The {@link GraphicsEnvironment#getAllFonts() getAllFonts} method + * of the GraphicsEnvironment class returns an + * array of all font faces available in the system. These font faces are + * returned as Font objects with a size of 1, identity + * transform and default font features. These + * base fonts can then be used to derive new Font objects + * with varying sizes, styles, transforms and font features via the + * deriveFont methods in this class. + * + *

Font and TextAttribute

+ * + *

Font supports most + * TextAttributes. This makes some operations, such as + * rendering underlined text, convenient since it is not + * necessary to explicitly construct a TextLayout object. + * Attributes can be set on a Font by constructing or deriving it + * using a Map of TextAttribute values. + * + *

The values of some TextAttributes are not + * serializable, and therefore attempting to serialize an instance of + * Font that has such values will not serialize them. + * This means a Font deserialized from such a stream will not compare + * equal to the original Font that contained the non-serializable + * attributes. This should very rarely pose a problem + * since these attributes are typically used only in special + * circumstances and are unlikely to be serialized. + * + *

    + *
  • FOREGROUND and BACKGROUND use + * Paint values. The subclass Color is + * serializable, while GradientPaint and + * TexturePaint are not.
  • + *
  • CHAR_REPLACEMENT uses + * GraphicAttribute values. The subclasses + * ShapeGraphicAttribute and + * ImageGraphicAttribute are not serializable.
  • + *
  • INPUT_METHOD_HIGHLIGHT uses + * InputMethodHighlight values, which are + * not serializable. See {@link java.awt.im.InputMethodHighlight}.
  • + *
+ * + *

Clients who create custom subclasses of Paint and + * GraphicAttribute can make them serializable and + * avoid this problem. Clients who use input method highlights can + * convert these to the platform-specific attributes for that + * highlight on the current platform and set them on the Font as + * a workaround. + * + *

The Map-based constructor and + * deriveFont APIs ignore the FONT attribute, and it is + * not retained by the Font; the static {@link #getFont} method should + * be used if the FONT attribute might be present. See {@link + * java.awt.font.TextAttribute#FONT} for more information.

+ * + *

Several attributes will cause additional rendering overhead + * and potentially invoke layout. If a Font has such + * attributes, the {@link #hasLayoutAttributes()} method + * will return true.

+ * + *

Note: Font rotations can cause text baselines to be rotated. In + * order to account for this (rare) possibility, font APIs are + * specified to return metrics and take parameters 'in + * baseline-relative coordinates'. This maps the 'x' coordinate to + * the advance along the baseline, (positive x is forward along the + * baseline), and the 'y' coordinate to a distance along the + * perpendicular to the baseline at 'x' (positive y is 90 degrees + * clockwise from the baseline vector). APIs for which this is + * especially important are called out as having 'baseline-relative + * coordinates.' + */ +public class Font implements java.io.Serializable +{ + private static class FontAccessImpl extends FontAccess { + public Font2D getFont2D(Font font) { + return font.getFont2D(); + } + + public void setFont2D(Font font, Font2DHandle handle) { + font.font2DHandle = handle; + } + + public void setCreatedFont(Font font) { + font.createdFont = true; + } + + public boolean isCreatedFont(Font font) { + return font.createdFont; + } + } + + static { + FontAccess.setFontAccess(new FontAccessImpl()); + } + + /** + * This is now only used during serialization. Typically + * it is null. + * + * @serial + * @see #getAttributes() + */ + private Hashtable fRequestedAttributes; + + /* + * Constants to be used for logical font family names. + */ + + /** + * A String constant for the canonical family name of the + * logical font "Dialog". It is useful in Font construction + * to provide compile-time verification of the name. + * @since 1.6 + */ + public static final String DIALOG = "Dialog"; + + /** + * A String constant for the canonical family name of the + * logical font "DialogInput". It is useful in Font construction + * to provide compile-time verification of the name. + * @since 1.6 + */ + public static final String DIALOG_INPUT = "DialogInput"; + + /** + * A String constant for the canonical family name of the + * logical font "SansSerif". It is useful in Font construction + * to provide compile-time verification of the name. + * @since 1.6 + */ + public static final String SANS_SERIF = "SansSerif"; + + /** + * A String constant for the canonical family name of the + * logical font "Serif". It is useful in Font construction + * to provide compile-time verification of the name. + * @since 1.6 + */ + public static final String SERIF = "Serif"; + + /** + * A String constant for the canonical family name of the + * logical font "Monospaced". It is useful in Font construction + * to provide compile-time verification of the name. + * @since 1.6 + */ + public static final String MONOSPACED = "Monospaced"; + + /* + * Constants to be used for styles. Can be combined to mix + * styles. + */ + + /** + * The plain style constant. + */ + public static final int PLAIN = 0; + + /** + * The bold style constant. This can be combined with the other style + * constants (except PLAIN) for mixed styles. + */ + public static final int BOLD = 1; + + /** + * The italicized style constant. This can be combined with the other + * style constants (except PLAIN) for mixed styles. + */ + public static final int ITALIC = 2; + + /** + * The baseline used in most Roman scripts when laying out text. + */ + public static final int ROMAN_BASELINE = 0; + + /** + * The baseline used in ideographic scripts like Chinese, Japanese, + * and Korean when laying out text. + */ + public static final int CENTER_BASELINE = 1; + + /** + * The baseline used in Devanigiri and similar scripts when laying + * out text. + */ + public static final int HANGING_BASELINE = 2; + + /** + * Identify a font resource of type TRUETYPE. + * Used to specify a TrueType font resource to the + * {@link #createFont} method. + * The TrueType format was extended to become the OpenType + * format, which adds support for fonts with Postscript outlines, + * this tag therefore references these fonts, as well as those + * with TrueType outlines. + * @since 1.3 + */ + + public static final int TRUETYPE_FONT = 0; + + /** + * Identify a font resource of type TYPE1. + * Used to specify a Type1 font resource to the + * {@link #createFont} method. + * @since 1.5 + */ + public static final int TYPE1_FONT = 1; + + /** + * The logical name of this Font, as passed to the + * constructor. + * @since JDK1.0 + * + * @serial + * @see #getName + */ + protected String name; + + /** + * The style of this Font, as passed to the constructor. + * This style can be PLAIN, BOLD, ITALIC, or BOLD+ITALIC. + * @since JDK1.0 + * + * @serial + * @see #getStyle() + */ + protected int style; + + /** + * The point size of this Font, rounded to integer. + * @since JDK1.0 + * + * @serial + * @see #getSize() + */ + protected int size; + + /** + * The point size of this Font in float. + * + * @serial + * @see #getSize() + * @see #getSize2D() + */ + protected float pointSize; + + /** + * The platform specific font information. + */ + private transient FontPeer peer; + private transient cli.System.Drawing.Font netFont; + private transient Font2DHandle font2DHandle; + + private transient AttributeValues values; + private transient boolean hasLayoutAttributes; + + /* + * If the origin of a Font is a created font then this attribute + * must be set on all derived fonts too. + */ + private transient boolean createdFont = false; + + /* + * This is true if the font transform is not identity. It + * is used to avoid unnecessary instantiation of an AffineTransform. + */ + private transient boolean nonIdentityTx; + + /* + * A cached value used when a transform is required for internal + * use. This must not be exposed to callers since AffineTransform + * is mutable. + */ + private static final AffineTransform identityTx = new AffineTransform(); + + /* + * JDK 1.1 serialVersionUID + */ + private static final long serialVersionUID = -4206021311591459213L; + + /** + * Gets the peer of this Font. + * @return the peer of the Font. + * @since JDK1.1 + * @deprecated Font rendering is now platform independent. + */ + @Deprecated + public FontPeer getPeer(){ + return getPeer_NoClientCode(); + } + // NOTE: This method is called by privileged threads. + // We implement this functionality in a package-private method + // to insure that it cannot be overridden by client subclasses. + // DO NOT INVOKE CLIENT CODE ON THIS THREAD! + @SuppressWarnings("deprecation") + final FontPeer getPeer_NoClientCode() { + if(peer == null) { + Toolkit tk = Toolkit.getDefaultToolkit(); + this.peer = tk.getFontPeer(name, style); + } + return peer; + } + + /** + * Return the AttributeValues object associated with this + * font. Most of the time, the internal object is null. + * If required, it will be created from the 'standard' + * state on the font. Only non-default values will be + * set in the AttributeValues object. + * + *

Since the AttributeValues object is mutable, and it + * is cached in the font, care must be taken to ensure that + * it is not mutated. + */ + private AttributeValues getAttributeValues() { + if (values == null) { + AttributeValues valuesTmp = new AttributeValues(); + valuesTmp.setFamily(name); + valuesTmp.setSize(pointSize); // expects the float value. + + if ((style & BOLD) != 0) { + valuesTmp.setWeight(2); // WEIGHT_BOLD + } + + if ((style & ITALIC) != 0) { + valuesTmp.setPosture(.2f); // POSTURE_OBLIQUE + } + valuesTmp.defineAll(PRIMARY_MASK); // for streaming compatibility + values = valuesTmp; + } + + return values; + } + + private Font2D getFont2D() { + FontManager fm = FontManagerFactory.getInstance(); + if (fm.usingPerAppContextComposites() && + font2DHandle != null && + font2DHandle.font2D instanceof CompositeFont && + ((CompositeFont)(font2DHandle.font2D)).isStdComposite()) { + return fm.findFont2D(name, style, + FontManager.LOGICAL_FALLBACK); + } else if (font2DHandle == null) { + font2DHandle = + fm.findFont2D(name, style, + FontManager.LOGICAL_FALLBACK).handle; + } + /* Do not cache the de-referenced font2D. It must be explicitly + * de-referenced to pick up a valid font in the event that the + * original one is marked invalid + */ + return font2DHandle.font2D; + } + + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + public cli.System.Drawing.Font getNetFont(){ + if(netFont == null){ + netFont = getFont2D().createNetFont(this); + } + return netFont; + } + /** + * Creates a new Font from the specified name, style and + * point size. + *

+ * The font name can be a font face name or a font family name. + * It is used together with the style to find an appropriate font face. + * When a font family name is specified, the style argument is used to + * select the most appropriate face from the family. When a font face + * name is specified, the face's style and the style argument are + * merged to locate the best matching font from the same family. + * For example if face name "Arial Bold" is specified with style + * Font.ITALIC, the font system looks for a face in the + * "Arial" family that is bold and italic, and may associate the font + * instance with the physical font face "Arial Bold Italic". + * The style argument is merged with the specified face's style, not + * added or subtracted. + * This means, specifying a bold face and a bold style does not + * double-embolden the font, and specifying a bold face and a plain + * style does not lighten the font. + *

+ * If no face for the requested style can be found, the font system + * may apply algorithmic styling to achieve the desired style. + * For example, if ITALIC is requested, but no italic + * face is available, glyphs from the plain face may be algorithmically + * obliqued (slanted). + *

+ * Font name lookup is case insensitive, using the case folding + * rules of the US locale. + *

+ * If the name parameter represents something other than a + * logical font, i.e. is interpreted as a physical font face or family, and + * this cannot be mapped by the implementation to a physical font or a + * compatible alternative, then the font system will map the Font + * instance to "Dialog", such that for example, the family as reported + * by {@link #getFamily() getFamily} will be "Dialog". + *

+ * + * @param name the font name. This can be a font face name or a font + * family name, and may represent either a logical font or a physical + * font found in this {@code GraphicsEnvironment}. + * The family names for logical fonts are: Dialog, DialogInput, + * Monospaced, Serif, or SansSerif. Pre-defined String constants exist + * for all of these names, for example, {@code DIALOG}. If {@code name} is + * {@code null}, the logical font name of the new + * {@code Font} as returned by {@code getName()} is set to + * the name "Default". + * @param style the style constant for the {@code Font} + * The style argument is an integer bitmask that may + * be {@code PLAIN}, or a bitwise union of {@code BOLD} and/or + * {@code ITALIC} (for example, {@code ITALIC} or {@code BOLD|ITALIC}). + * If the style argument does not conform to one of the expected + * integer bitmasks then the style is set to {@code PLAIN}. + * @param size the point size of the {@code Font} + * @see GraphicsEnvironment#getAllFonts + * @see GraphicsEnvironment#getAvailableFontFamilyNames + * @since JDK1.0 + */ + public Font(String name, int style, int size) { + this.name = (name != null) ? name : "Default"; + this.style = (style & ~0x03) == 0 ? style : 0; + this.size = size; + this.pointSize = size; + } + + private Font(String name, int style, float sizePts) { + this.name = (name != null) ? name : "Default"; + this.style = (style & ~0x03) == 0 ? style : 0; + this.size = (int)(sizePts + 0.5); + this.pointSize = sizePts; + } + + /* This constructor is used by deriveFont when attributes is null */ + private Font(String name, int style, float sizePts, + boolean created, Font2DHandle handle) { + this(name, style, sizePts); + this.createdFont = created; + /* Fonts created from a stream will use the same font2D instance + * as the parent. + * One exception is that if the derived font is requested to be + * in a different style, then also check if its a CompositeFont + * and if so build a new CompositeFont from components of that style. + * CompositeFonts can only be marked as "created" if they are used + * to add fall backs to a physical font. And non-composites are + * always from "Font.createFont()" and shouldn't get this treatment. + */ + if (created) { + if (handle.font2D instanceof CompositeFont && + handle.font2D.getStyle() != style) { + FontManager fm = FontManagerFactory.getInstance(); + this.font2DHandle = fm.getNewComposite(null, style, handle); + } else { + this.font2DHandle = handle; + } + } + } + + /* This constructor is used when one font is derived from another. + * Fonts created from a stream will use the same font2D instance as the + * parent. They can be distinguished because the "created" argument + * will be "true". Since there is no way to recreate these fonts they + * need to have the handle to the underlying font2D passed in. + * "created" is also true when a special composite is referenced by the + * handle for essentially the same reasons. + * But when deriving a font in these cases two particular attributes + * need special attention: family/face and style. + * The "composites" in these cases need to be recreated with optimal + * fonts for the new values of family and style. + * For fonts created with createFont() these are treated differently. + * JDK can often synthesise a different style (bold from plain + * for example). For fonts created with "createFont" this is a reasonable + * solution but its also possible (although rare) to derive a font with a + * different family attribute. In this case JDK needs + * to break the tie with the original Font2D and find a new Font. + * The oldName and oldStyle are supplied so they can be compared with + * what the Font2D and the values. To speed things along : + * oldName == null will be interpreted as the name is unchanged. + * oldStyle = -1 will be interpreted as the style is unchanged. + * In these cases there is no need to interrogate "values". + */ + private Font(AttributeValues values, String oldName, int oldStyle, + boolean created, Font2DHandle handle) { + + this.createdFont = created; + if (created) { + this.font2DHandle = handle; + + String newName = null; + if (oldName != null) { + newName = values.getFamily(); + if (oldName.equals(newName)) newName = null; + } + int newStyle = 0; + if (oldStyle == -1) { + newStyle = -1; + } else { + if (values.getWeight() >= 2f) newStyle = BOLD; + if (values.getPosture() >= .2f) newStyle |= ITALIC; + if (oldStyle == newStyle) newStyle = -1; + } + if (handle.font2D instanceof CompositeFont) { + if (newStyle != -1 || newName != null) { + FontManager fm = FontManagerFactory.getInstance(); + this.font2DHandle = + fm.getNewComposite(newName, newStyle, handle); + } + } else if (newName != null) { + this.createdFont = false; + this.font2DHandle = null; + } + } + initFromValues(values); + } + + /** + * Creates a new Font with the specified attributes. + * Only keys defined in {@link java.awt.font.TextAttribute TextAttribute} + * are recognized. In addition the FONT attribute is + * not recognized by this constructor + * (see {@link #getAvailableAttributes}). Only attributes that have + * values of valid types will affect the new Font. + *

+ * If attributes is null, a new + * Font is initialized with default values. + * @see java.awt.font.TextAttribute + * @param attributes the attributes to assign to the new + * Font, or null + */ + public Font(Map attributes) { + initFromValues(AttributeValues.fromMap(attributes, RECOGNIZED_MASK)); + } + + /** + * Creates a new Font from the specified font. + * This constructor is intended for use by subclasses. + * @param font from which to create this Font. + * @throws NullPointerException if font is null + * @since 1.6 + */ + protected Font(Font font) { + if (font.values != null) { + initFromValues(font.getAttributeValues().clone()); + } else { + this.name = font.name; + this.style = font.style; + this.size = font.size; + this.pointSize = font.pointSize; + } + this.font2DHandle = font.font2DHandle; + this.createdFont = font.createdFont; + } + + /** + * Font recognizes all attributes except FONT. + */ + private static final int RECOGNIZED_MASK = AttributeValues.MASK_ALL + & ~AttributeValues.getMask(EFONT); + + /** + * These attributes are considered primary by the FONT attribute. + */ + private static final int PRIMARY_MASK = + AttributeValues.getMask(EFAMILY, EWEIGHT, EWIDTH, EPOSTURE, ESIZE, + ETRANSFORM, ESUPERSCRIPT, ETRACKING); + + /** + * These attributes are considered secondary by the FONT attribute. + */ + private static final int SECONDARY_MASK = + RECOGNIZED_MASK & ~PRIMARY_MASK; + + /** + * These attributes are handled by layout. + */ + private static final int LAYOUT_MASK = + AttributeValues.getMask(ECHAR_REPLACEMENT, EFOREGROUND, EBACKGROUND, + EUNDERLINE, ESTRIKETHROUGH, ERUN_DIRECTION, + EBIDI_EMBEDDING, EJUSTIFICATION, + EINPUT_METHOD_HIGHLIGHT, EINPUT_METHOD_UNDERLINE, + ESWAP_COLORS, ENUMERIC_SHAPING, EKERNING, + ELIGATURES, ETRACKING, ESUPERSCRIPT); + + private static final int EXTRA_MASK = + AttributeValues.getMask(ETRANSFORM, ESUPERSCRIPT, EWIDTH); + + /** + * Initialize the standard Font fields from the values object. + */ + private void initFromValues(AttributeValues values) { + this.values = values; + values.defineAll(PRIMARY_MASK); // for 1.5 streaming compatibility + + this.name = values.getFamily(); + this.pointSize = values.getSize(); + this.size = (int)(values.getSize() + 0.5); + if (values.getWeight() >= 2f) this.style |= BOLD; // not == 2f + if (values.getPosture() >= .2f) this.style |= ITALIC; // not == .2f + + this.nonIdentityTx = values.anyNonDefault(EXTRA_MASK); + this.hasLayoutAttributes = values.anyNonDefault(LAYOUT_MASK); + } + + /** + * Returns a Font appropriate to the attributes. + * If attributescontains a FONT attribute + * with a valid Font as its value, it will be + * merged with any remaining attributes. See + * {@link java.awt.font.TextAttribute#FONT} for more + * information. + * + * @param attributes the attributes to assign to the new + * Font + * @return a new Font created with the specified + * attributes + * @throws NullPointerException if attributes is null. + * @since 1.2 + * @see java.awt.font.TextAttribute + */ + public static Font getFont(Map attributes) { + // optimize for two cases: + // 1) FONT attribute, and nothing else + // 2) attributes, but no FONT + + // avoid turning the attributemap into a regular map for no reason + if (attributes instanceof AttributeMap && + ((AttributeMap)attributes).getValues() != null) { + AttributeValues values = ((AttributeMap)attributes).getValues(); + if (values.isNonDefault(EFONT)) { + Font font = values.getFont(); + if (!values.anyDefined(SECONDARY_MASK)) { + return font; + } + // merge + values = font.getAttributeValues().clone(); + values.merge(attributes, SECONDARY_MASK); + return new Font(values, font.name, font.style, + font.createdFont, font.font2DHandle); + } + return new Font(attributes); + } + + Font font = (Font)attributes.get(TextAttribute.FONT); + if (font != null) { + if (attributes.size() > 1) { // oh well, check for anything else + AttributeValues values = font.getAttributeValues().clone(); + values.merge(attributes, SECONDARY_MASK); + return new Font(values, font.name, font.style, + font.createdFont, font.font2DHandle); + } + + return font; + } + + return new Font(attributes); + } + + private static class FontFamilyReference extends WeakReference { + + private static final ReferenceQueue fontFamilyQueue = new ReferenceQueue<>(); + private static final Set refs = Collections.synchronizedSet( new HashSet() ); + static { + sun.misc.SharedSecrets.getJavaLangAccess().registerShutdownHook( 5, // Shutdown hook invocation order + true, // register even if shutdown in progress + new Runnable() { + public void run() { + for( FontFamilyReference ref : refs ) { + ref.delete( false ); + } + } + } ); + } + private File fontFile; + + private FontFamilyReference( FontFamily family, File fontFile ) { + super( family, fontFamilyQueue ); + this.fontFile = fontFile; + refs.add( this ); + + do { + FontFamilyReference ref = (FontFamilyReference)fontFamilyQueue.poll(); + if( ref == null ) { + break; + } + ref.delete( true ); + } while(true); + } + + private void delete( boolean isQueue ) { + FontFamily family = get(); + if( family != null ) { + family.Dispose(); + } + + if( fontFile.delete() && isQueue) { + refs.remove( this ); + } + } + } + + /** + * Returns a new Font using the specified font type + * and input data. The new Font is + * created with a point size of 1 and style {@link #PLAIN PLAIN}. + * This base font can then be used with the deriveFont + * methods in this class to derive new Font objects with + * varying sizes, styles, transforms and font features. This + * method does not close the {@link InputStream}. + *

+ * To make the Font available to Font constructors the + * returned Font must be registered in the + * GraphicsEnviroment by calling + * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}. + * @param fontFormat the type of the Font, which is + * {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is specified. + * or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is specified. + * @param fontStream an InputStream object representing the + * input data for the font. + * @return a new Font created with the specified font type. + * @throws IllegalArgumentException if fontFormat is not + * TRUETYPE_FONTorTYPE1_FONT. + * @throws FontFormatException if the fontStream data does + * not contain the required font tables for the specified format. + * @throws IOException if the fontStream + * cannot be completely read. + * @see GraphicsEnvironment#registerFont(Font) + * @since 1.3 + */ + public static Font createFont(int fontFormat, InputStream fontStream) + throws java.awt.FontFormatException, java.io.IOException { + + if (fontFormat != Font.TRUETYPE_FONT && + fontFormat != Font.TYPE1_FONT) { + throw new IllegalArgumentException ("font format not recognized"); + } + + File fontFile; + try { + fontFile = AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public File run() throws IOException { + return Files.createTempFile("+~JF", ".tmp").toFile(); + } + } + ); + } catch( PrivilegedActionException ex ) { + throw (IOException)ex.getException(); + } + Files.copy( fontStream, fontFile.toPath(), StandardCopyOption.REPLACE_EXISTING ); + + // create a private Font Collection and add the font data + PrivateFontCollection pfc = new PrivateFontCollection(); + try { + String fileName = fontFile.getPath(); + pfc.AddFontFile( fileName ); + RemoveFontResourceEx( fileName ); // hack for bug http://stackoverflow.com/questions/26671026/how-to-delete-the-file-of-a-privatefontcollection-addfontfile + if (false) throw new cli.System.IO.FileNotFoundException(); + } catch( cli.System.IO.FileNotFoundException x ) { + FontFormatException ffe = new FontFormatException(x.getMessage()); + ffe.initCause(x); + fontFile.delete(); + throw ffe; + } + + FontFamily family = pfc.get_Families()[0]; + new FontFamilyReference( family, fontFile ); + + // create the font object + Font2D font2D = SunFontManager.createFont2D( family, 0 ); + Font2DHandle font2DHandle = font2D.handle; + Font font = new Font( font2D.getFontName( Locale.getDefault() ), PLAIN, 1, true, font2DHandle ); + return font; + } + + @DllImportAttribute.Annotation(value="gdi32") + private static native int RemoveFontResourceEx(String filename, int fl, IntPtr pdv); + + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + private static void RemoveFontResourceEx(String filename) { + if( ikvm.internal.Util.WINDOWS ) { + RemoveFontResourceEx( filename, 16, IntPtr.Zero ); + } + } + + /** + * Returns a new Font using the specified font type + * and the specified font file. The new Font is + * created with a point size of 1 and style {@link #PLAIN PLAIN}. + * This base font can then be used with the deriveFont + * methods in this class to derive new Font objects with + * varying sizes, styles, transforms and font features. + * @param fontFormat the type of the Font, which is + * {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is + * specified or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is + * specified. + * So long as the returned font, or its derived fonts are referenced + * the implementation may continue to access fontFile + * to retrieve font data. Thus the results are undefined if the file + * is changed, or becomes inaccessible. + *

+ * To make the Font available to Font constructors the + * returned Font must be registered in the + * GraphicsEnviroment by calling + * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}. + * @param fontFile a File object representing the + * input data for the font. + * @return a new Font created with the specified font type. + * @throws IllegalArgumentException if fontFormat is not + * TRUETYPE_FONTorTYPE1_FONT. + * @throws NullPointerException if fontFile is null. + * @throws IOException if the fontFile cannot be read. + * @throws FontFormatException if fontFile does + * not contain the required font tables for the specified format. + * @throws SecurityException if the executing code does not have + * permission to read from the file. + * @see GraphicsEnvironment#registerFont(Font) + * @since 1.5 + */ + public static Font createFont(int fontFormat, File fontFile) + throws java.awt.FontFormatException, java.io.IOException { + + fontFile = new File(fontFile.getPath()); + + if (fontFormat != Font.TRUETYPE_FONT && + fontFormat != Font.TYPE1_FONT) { + throw new IllegalArgumentException ("font format not recognized"); + } + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + FilePermission filePermission = + new FilePermission(fontFile.getPath(), "read"); + sm.checkPermission(filePermission); + } + if (!fontFile.canRead()) { + throw new IOException("Can't read " + fontFile); + } + // create a private Font Collection and add the font data + PrivateFontCollection pfc = new PrivateFontCollection(); + try { + String fileName = fontFile.getPath(); + pfc.AddFontFile( fileName ); + RemoveFontResourceEx( fileName );// hack for bug http://stackoverflow.com/questions/26671026/how-to-delete-the-file-of-a-privatefontcollection-addfontfile + if (false) throw new cli.System.IO.FileNotFoundException(); + } catch( cli.System.IO.FileNotFoundException fnfe ) { + FileNotFoundException ex = new FileNotFoundException(fnfe.getMessage()); + ex.initCause( fnfe ); + throw ex; + } + // create the font object + Font2D font2D = SunFontManager.createFont2D( pfc.get_Families()[0], 0 ); + Font2DHandle font2DHandle = font2D.handle; + Font font = new Font( font2D.getFontName( Locale.getDefault() ), PLAIN, 1, true, font2DHandle ); + return font; + } + + /** + * Returns a copy of the transform associated with this + * Font. This transform is not necessarily the one + * used to construct the font. If the font has algorithmic + * superscripting or width adjustment, this will be incorporated + * into the returned AffineTransform. + *

+ * Typically, fonts will not be transformed. Clients generally + * should call {@link #isTransformed} first, and only call this + * method if isTransformed returns true. + * + * @return an {@link AffineTransform} object representing the + * transform attribute of this Font object. + */ + public AffineTransform getTransform() { + /* The most common case is the identity transform. Most callers + * should call isTransformed() first, to decide if they need to + * get the transform, but some may not. Here we check to see + * if we have a nonidentity transform, and only do the work to + * fetch and/or compute it if so, otherwise we return a new + * identity transform. + * + * Note that the transform is _not_ necessarily the same as + * the transform passed in as an Attribute in a Map, as the + * transform returned will also reflect the effects of WIDTH and + * SUPERSCRIPT attributes. Clients who want the actual transform + * need to call getRequestedAttributes. + */ + if (nonIdentityTx) { + AttributeValues values = getAttributeValues(); + + AffineTransform at = values.isNonDefault(ETRANSFORM) + ? new AffineTransform(values.getTransform()) + : new AffineTransform(); + + if (values.getSuperscript() != 0) { + // can't get ascent and descent here, recursive call to this fn, + // so use pointsize + // let users combine super- and sub-scripting + + int superscript = values.getSuperscript(); + + double trans = 0; + int n = 0; + boolean up = superscript > 0; + int sign = up ? -1 : 1; + int ss = up ? superscript : -superscript; + + while ((ss & 7) > n) { + int newn = ss & 7; + trans += sign * (ssinfo[newn] - ssinfo[n]); + ss >>= 3; + sign = -sign; + n = newn; + } + trans *= pointSize; + double scale = Math.pow(2./3., n); + + at.preConcatenate(AffineTransform.getTranslateInstance(0, trans)); + at.scale(scale, scale); + + // note on placement and italics + // We preconcatenate the transform because we don't want to translate along + // the italic angle, but purely perpendicular to the baseline. While this + // looks ok for superscripts, it can lead subscripts to stack on each other + // and bring the following text too close. The way we deal with potential + // collisions that can occur in the case of italics is by adjusting the + // horizontal spacing of the adjacent glyphvectors. Examine the italic + // angle of both vectors, if one is non-zero, compute the minimum ascent + // and descent, and then the x position at each for each vector along its + // italic angle starting from its (offset) baseline. Compute the difference + // between the x positions and use the maximum difference to adjust the + // position of the right gv. + } + + if (values.isNonDefault(EWIDTH)) { + at.scale(values.getWidth(), 1f); + } + + return at; + } + + return new AffineTransform(); + } + + // x = r^0 + r^1 + r^2... r^n + // rx = r^1 + r^2 + r^3... r^(n+1) + // x - rx = r^0 - r^(n+1) + // x (1 - r) = r^0 - r^(n+1) + // x = (r^0 - r^(n+1)) / (1 - r) + // x = (1 - r^(n+1)) / (1 - r) + + // scale ratio is 2/3 + // trans = 1/2 of ascent * x + // assume ascent is 3/4 of point size + + private static final float[] ssinfo = { + 0.0f, + 0.375f, + 0.625f, + 0.7916667f, + 0.9027778f, + 0.9768519f, + 1.0262346f, + 1.0591564f, + }; + + /** + * Returns the family name of this Font. + * + *

The family name of a font is font specific. Two fonts such as + * Helvetica Italic and Helvetica Bold have the same family name, + * Helvetica, whereas their font face names are + * Helvetica Bold and Helvetica Italic. The list of + * available family names may be obtained by using the + * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method. + * + *

Use getName to get the logical name of the font. + * Use getFontName to get the font face name of the font. + * @return a String that is the family name of this + * Font. + * + * @see #getName + * @see #getFontName + * @since JDK1.1 + */ + public String getFamily() { + return getFamily_NoClientCode(); + } + // NOTE: This method is called by privileged threads. + // We implement this functionality in a package-private + // method to insure that it cannot be overridden by client + // subclasses. + // DO NOT INVOKE CLIENT CODE ON THIS THREAD! + final String getFamily_NoClientCode() { + return getFamily(Locale.getDefault()); + } + + /** + * Returns the family name of this Font, localized for + * the specified locale. + * + *

The family name of a font is font specific. Two fonts such as + * Helvetica Italic and Helvetica Bold have the same family name, + * Helvetica, whereas their font face names are + * Helvetica Bold and Helvetica Italic. The list of + * available family names may be obtained by using the + * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method. + * + *

Use getFontName to get the font face name of the font. + * @param l locale for which to get the family name + * @return a String representing the family name of the + * font, localized for the specified locale. + * @see #getFontName + * @see java.util.Locale + * @since 1.2 + */ + public String getFamily(Locale l) { + if (l == null) { + throw new NullPointerException("null locale doesn't mean default"); + } + return getFont2D().getFamilyName(l); + } + + /** + * Returns the postscript name of this Font. + * Use getFamily to get the family name of the font. + * Use getFontName to get the font face name of the font. + * @return a String representing the postscript name of + * this Font. + * @since 1.2 + */ + public String getPSName() { + return getFont2D().getPostscriptName(); + } + + /** + * Returns the logical name of this Font. + * Use getFamily to get the family name of the font. + * Use getFontName to get the font face name of the font. + * @return a String representing the logical name of + * this Font. + * @see #getFamily + * @see #getFontName + * @since JDK1.0 + */ + public String getName() { + return name; + } + + /** + * Returns the font face name of this Font. For example, + * Helvetica Bold could be returned as a font face name. + * Use getFamily to get the family name of the font. + * Use getName to get the logical name of the font. + * @return a String representing the font face name of + * this Font. + * @see #getFamily + * @see #getName + * @since 1.2 + */ + public String getFontName() { + return getFontName(Locale.getDefault()); + } + + /** + * Returns the font face name of the Font, localized + * for the specified locale. For example, Helvetica Fett could be + * returned as the font face name. + * Use getFamily to get the family name of the font. + * @param l a locale for which to get the font face name + * @return a String representing the font face name, + * localized for the specified locale. + * @see #getFamily + * @see java.util.Locale + */ + public String getFontName(Locale l) { + if (l == null) { + throw new NullPointerException("null locale doesn't mean default"); + } + return getFont2D().getFontName(l); + } + + /** + * Returns the style of this Font. The style can be + * PLAIN, BOLD, ITALIC, or BOLD+ITALIC. + * @return the style of this Font + * @see #isPlain + * @see #isBold + * @see #isItalic + * @since JDK1.0 + */ + public int getStyle() { + return style; + } + + /** + * Returns the point size of this Font, rounded to + * an integer. + * Most users are familiar with the idea of using point size to + * specify the size of glyphs in a font. This point size defines a + * measurement between the baseline of one line to the baseline of the + * following line in a single spaced text document. The point size is + * based on typographic points, approximately 1/72 of an inch. + *

+ * The Java(tm)2D API adopts the convention that one point is + * equivalent to one unit in user coordinates. When using a + * normalized transform for converting user space coordinates to + * device space coordinates 72 user + * space units equal 1 inch in device space. In this case one point + * is 1/72 of an inch. + * @return the point size of this Font in 1/72 of an + * inch units. + * @see #getSize2D + * @see GraphicsConfiguration#getDefaultTransform + * @see GraphicsConfiguration#getNormalizingTransform + * @since JDK1.0 + */ + public int getSize() { + return size; + } + + /** + * Returns the point size of this Font in + * float value. + * @return the point size of this Font as a + * float value. + * @see #getSize + * @since 1.2 + */ + public float getSize2D() { + return pointSize; + } + + /** + * Indicates whether or not this Font object's style is + * PLAIN. + * @return true if this Font has a + * PLAIN style; + * false otherwise. + * @see java.awt.Font#getStyle + * @since JDK1.0 + */ + public boolean isPlain() { + return style == 0; + } + + /** + * Indicates whether or not this Font object's style is + * BOLD. + * @return true if this Font object's + * style is BOLD; + * false otherwise. + * @see java.awt.Font#getStyle + * @since JDK1.0 + */ + public boolean isBold() { + return (style & BOLD) != 0; + } + + /** + * Indicates whether or not this Font object's style is + * ITALIC. + * @return true if this Font object's + * style is ITALIC; + * false otherwise. + * @see java.awt.Font#getStyle + * @since JDK1.0 + */ + public boolean isItalic() { + return (style & ITALIC) != 0; + } + + /** + * Indicates whether or not this Font object has a + * transform that affects its size in addition to the Size + * attribute. + * @return true if this Font object + * has a non-identity AffineTransform attribute. + * false otherwise. + * @see java.awt.Font#getTransform + * @since 1.4 + */ + public boolean isTransformed() { + return nonIdentityTx; + } + + /** + * Return true if this Font contains attributes that require extra + * layout processing. + * @return true if the font has layout attributes + * @since 1.6 + */ + public boolean hasLayoutAttributes() { + return hasLayoutAttributes; + } + + /** + * Returns a Font object from the system properties list. + * nm is treated as the name of a system property to be + * obtained. The String value of this property is then + * interpreted as a Font object according to the + * specification of Font.decode(String) + * If the specified property is not found, or the executing code does + * not have permission to read the property, null is returned instead. + * + * @param nm the property name + * @return a Font object that the property name + * describes, or null if no such property exists. + * @throws NullPointerException if nm is null. + * @since 1.2 + * @see #decode(String) + */ + public static Font getFont(String nm) { + return getFont(nm, null); + } + + /** + * Returns the Font that the str + * argument describes. + * To ensure that this method returns the desired Font, + * format the str parameter in + * one of these ways + * + *

    + *
  • fontname-style-pointsize + *
  • fontname-pointsize + *
  • fontname-style + *
  • fontname + *
  • fontname style pointsize + *
  • fontname pointsize + *
  • fontname style + *
  • fontname + *
+ * in which style is one of the four + * case-insensitive strings: + * "PLAIN", "BOLD", "BOLDITALIC", or + * "ITALIC", and pointsize is a positive decimal integer + * representation of the point size. + * For example, if you want a font that is Arial, bold, with + * a point size of 18, you would call this method with: + * "Arial-BOLD-18". + * This is equivalent to calling the Font constructor : + * new Font("Arial", Font.BOLD, 18); + * and the values are interpreted as specified by that constructor. + *

+ * A valid trailing decimal field is always interpreted as the pointsize. + * Therefore a fontname containing a trailing decimal value should not + * be used in the fontname only form. + *

+ * If a style name field is not one of the valid style strings, it is + * interpreted as part of the font name, and the default style is used. + *

+ * Only one of ' ' or '-' may be used to separate fields in the input. + * The identified separator is the one closest to the end of the string + * which separates a valid pointsize, or a valid style name from + * the rest of the string. + * Null (empty) pointsize and style fields are treated + * as valid fields with the default value for that field. + *

+ * Some font names may include the separator characters ' ' or '-'. + * If str is not formed with 3 components, e.g. such that + * style or pointsize fields are not present in + * str, and fontname also contains a + * character determined to be the separator character + * then these characters where they appear as intended to be part of + * fontname may instead be interpreted as separators + * so the font name may not be properly recognised. + * + *

+ * The default size is 12 and the default style is PLAIN. + * If str does not specify a valid size, the returned + * Font has a size of 12. If str does not + * specify a valid style, the returned Font has a style of PLAIN. + * If you do not specify a valid font name in + * the str argument, this method will return + * a font with the family name "Dialog". + * To determine what font family names are available on + * your system, use the + * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method. + * If str is null, a new Font + * is returned with the family name "Dialog", a size of 12 and a + * PLAIN style. + * @param str the name of the font, or null + * @return the Font object that str + * describes, or a new default Font if + * str is null. + * @see #getFamily + * @since JDK1.1 + */ + public static Font decode(String str) { + String fontName = str; + String styleName = ""; + int fontSize = 12; + int fontStyle = Font.PLAIN; + + if (str == null) { + return new Font(DIALOG, fontStyle, fontSize); + } + + int lastHyphen = str.lastIndexOf('-'); + int lastSpace = str.lastIndexOf(' '); + char sepChar = (lastHyphen > lastSpace) ? '-' : ' '; + int sizeIndex = str.lastIndexOf(sepChar); + int styleIndex = str.lastIndexOf(sepChar, sizeIndex-1); + int strlen = str.length(); + + if (sizeIndex > 0 && sizeIndex+1 < strlen) { + try { + fontSize = + Integer.valueOf(str.substring(sizeIndex+1)).intValue(); + if (fontSize <= 0) { + fontSize = 12; + } + } catch (NumberFormatException e) { + /* It wasn't a valid size, if we didn't also find the + * start of the style string perhaps this is the style */ + styleIndex = sizeIndex; + sizeIndex = strlen; + if (str.charAt(sizeIndex-1) == sepChar) { + sizeIndex--; + } + } + } + + if (styleIndex >= 0 && styleIndex+1 < strlen) { + styleName = str.substring(styleIndex+1, sizeIndex); + styleName = styleName.toLowerCase(Locale.ENGLISH); + if (styleName.equals("bolditalic")) { + fontStyle = Font.BOLD | Font.ITALIC; + } else if (styleName.equals("italic")) { + fontStyle = Font.ITALIC; + } else if (styleName.equals("bold")) { + fontStyle = Font.BOLD; + } else if (styleName.equals("plain")) { + fontStyle = Font.PLAIN; + } else { + /* this string isn't any of the expected styles, so + * assume its part of the font name + */ + styleIndex = sizeIndex; + if (str.charAt(styleIndex-1) == sepChar) { + styleIndex--; + } + } + fontName = str.substring(0, styleIndex); + + } else { + int fontEnd = strlen; + if (styleIndex > 0) { + fontEnd = styleIndex; + } else if (sizeIndex > 0) { + fontEnd = sizeIndex; + } + if (fontEnd > 0 && str.charAt(fontEnd-1) == sepChar) { + fontEnd--; + } + fontName = str.substring(0, fontEnd); + } + + return new Font(fontName, fontStyle, fontSize); + } + + /** + * Gets the specified Font from the system properties + * list. As in the getProperty method of + * System, the first + * argument is treated as the name of a system property to be + * obtained. The String value of this property is then + * interpreted as a Font object. + *

+ * The property value should be one of the forms accepted by + * Font.decode(String) + * If the specified property is not found, or the executing code does not + * have permission to read the property, the font + * argument is returned instead. + * @param nm the case-insensitive property name + * @param font a default Font to return if property + * nm is not defined + * @return the Font value of the property. + * @throws NullPointerException if nm is null. + * @see #decode(String) + */ + public static Font getFont(String nm, Font font) { + String str = null; + try { + str =System.getProperty(nm); + } catch(SecurityException e) { + } + if (str == null) { + return font; + } + return decode ( str ); + } + + transient int hash; + /** + * Returns a hashcode for this Font. + * @return a hashcode value for this Font. + * @since JDK1.0 + */ + public int hashCode() { + if (hash == 0) { + hash = name.hashCode() ^ style ^ size; + /* It is possible many fonts differ only in transform. + * So include the transform in the hash calculation. + * nonIdentityTx is set whenever there is a transform in + * 'values'. The tests for null are required because it can + * also be set for other reasons. + */ + if (nonIdentityTx && + values != null && values.getTransform() != null) { + hash ^= values.getTransform().hashCode(); + } + } + return hash; + } + + /** + * Compares this Font object to the specified + * Object. + * @param obj the Object to compare + * @return true if the objects are the same + * or if the argument is a Font object + * describing the same font as this object; + * false otherwise. + * @since JDK1.0 + */ + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (obj != null) { + try { + Font font = (Font)obj; + if (size == font.size && + style == font.style && + nonIdentityTx == font.nonIdentityTx && + hasLayoutAttributes == font.hasLayoutAttributes && + pointSize == font.pointSize && + name.equals(font.name)) { + + /* 'values' is usually initialized lazily, except when + * the font is constructed from a Map, or derived using + * a Map or other values. So if only one font has + * the field initialized we need to initialize it in + * the other instance and compare. + */ + if (values == null) { + if (font.values == null) { + return true; + } else { + return getAttributeValues().equals(font.values); + } + } else { + return values.equals(font.getAttributeValues()); + } + } + } + catch (ClassCastException e) { + } + } + return false; + } + + /** + * Converts this Font object to a String + * representation. + * @return a String representation of this + * Font object. + * @since JDK1.0 + */ + // NOTE: This method may be called by privileged threads. + // DO NOT INVOKE CLIENT CODE ON THIS THREAD! + public String toString() { + String strStyle; + + if (isBold()) { + strStyle = isItalic() ? "bolditalic" : "bold"; + } else { + strStyle = isItalic() ? "italic" : "plain"; + } + + return getClass().getName() + "[family=" + getFamily() + ",name=" + name + ",style=" + + strStyle + ",size=" + size + "]"; + } // toString() + + + /** Serialization support. A readObject + * method is neccessary because the constructor creates + * the font's peer, and we can't serialize the peer. + * Similarly the computed font "family" may be different + * at readObject time than at + * writeObject time. An integer version is + * written so that future versions of this class will be + * able to recognize serialized output from this one. + */ + /** + * The Font Serializable Data Form. + * + * @serial + */ + private int fontSerializedDataVersion = 1; + + /** + * Writes default serializable fields to a stream. + * + * @param s the ObjectOutputStream to write + * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener) + * @see #readObject(java.io.ObjectInputStream) + */ + private void writeObject(java.io.ObjectOutputStream s) + throws java.lang.ClassNotFoundException, + java.io.IOException + { + if (values != null) { + synchronized(values) { + // transient + fRequestedAttributes = values.toSerializableHashtable(); + s.defaultWriteObject(); + fRequestedAttributes = null; + } + } else { + s.defaultWriteObject(); + } + } + + /** + * Reads the ObjectInputStream. + * Unrecognized keys or values will be ignored. + * + * @param s the ObjectInputStream to read + * @serial + * @see #writeObject(java.io.ObjectOutputStream) + */ + private void readObject(java.io.ObjectInputStream s) + throws java.lang.ClassNotFoundException, + java.io.IOException + { + s.defaultReadObject(); + if (pointSize == 0) { + pointSize = (float)size; + } + + // Handle fRequestedAttributes. + // in 1.5, we always streamed out the font values plus + // TRANSFORM, SUPERSCRIPT, and WIDTH, regardless of whether the + // values were default or not. In 1.6 we only stream out + // defined values. So, 1.6 streams in from a 1.5 stream, + // it check each of these values and 'undefines' it if the + // value is the default. + + if (fRequestedAttributes != null) { + values = getAttributeValues(); // init + AttributeValues extras = + AttributeValues.fromSerializableHashtable(fRequestedAttributes); + if (!AttributeValues.is16Hashtable(fRequestedAttributes)) { + extras.unsetDefault(); // if legacy stream, undefine these + } + values = getAttributeValues().merge(extras); + this.nonIdentityTx = values.anyNonDefault(EXTRA_MASK); + this.hasLayoutAttributes = values.anyNonDefault(LAYOUT_MASK); + + fRequestedAttributes = null; // don't need it any more + } + } + + /** + * Returns the number of glyphs in this Font. Glyph codes + * for this Font range from 0 to + * getNumGlyphs() - 1. + * @return the number of glyphs in this Font. + * @since 1.2 + */ + public int getNumGlyphs() { + return getFont2D().getNumGlyphs(); + } + + /** + * Returns the glyphCode which is used when this Font + * does not have a glyph for a specified unicode code point. + * @return the glyphCode of this Font. + * @since 1.2 + */ + public int getMissingGlyphCode() { + return getFont2D().getMissingGlyphCode(); + } + + /** + * Returns the baseline appropriate for displaying this character. + *

+ * Large fonts can support different writing systems, and each system can + * use a different baseline. + * The character argument determines the writing system to use. Clients + * should not assume all characters use the same baseline. + * + * @param c a character used to identify the writing system + * @return the baseline appropriate for the specified character. + * @see LineMetrics#getBaselineOffsets + * @see #ROMAN_BASELINE + * @see #CENTER_BASELINE + * @see #HANGING_BASELINE + * @since 1.2 + */ + public byte getBaselineFor(char c) { + return getFont2D().getBaselineFor(c); + } + + /** + * Returns a map of font attributes available in this + * Font. Attributes include things like ligatures and + * glyph substitution. + * @return the attributes map of this Font. + */ + public Map getAttributes(){ + return new AttributeMap(getAttributeValues()); + } + + /** + * Returns the keys of all the attributes supported by this + * Font. These attributes can be used to derive other + * fonts. + * @return an array containing the keys of all the attributes + * supported by this Font. + * @since 1.2 + */ + public Attribute[] getAvailableAttributes() { + // FONT is not supported by Font + + Attribute attributes[] = { + TextAttribute.FAMILY, + TextAttribute.WEIGHT, + TextAttribute.WIDTH, + TextAttribute.POSTURE, + TextAttribute.SIZE, + TextAttribute.TRANSFORM, + TextAttribute.SUPERSCRIPT, + TextAttribute.CHAR_REPLACEMENT, + TextAttribute.FOREGROUND, + TextAttribute.BACKGROUND, + TextAttribute.UNDERLINE, + TextAttribute.STRIKETHROUGH, + TextAttribute.RUN_DIRECTION, + TextAttribute.BIDI_EMBEDDING, + TextAttribute.JUSTIFICATION, + TextAttribute.INPUT_METHOD_HIGHLIGHT, + TextAttribute.INPUT_METHOD_UNDERLINE, + TextAttribute.SWAP_COLORS, + TextAttribute.NUMERIC_SHAPING, + TextAttribute.KERNING, + TextAttribute.LIGATURES, + TextAttribute.TRACKING, + }; + + return attributes; + } + + /** + * Creates a new Font object by replicating this + * Font object and applying a new style and size. + * @param style the style for the new Font + * @param size the size for the new Font + * @return a new Font object. + * @since 1.2 + */ + public Font deriveFont(int style, float size){ + if (values == null) { + return new Font(name, style, size, createdFont, font2DHandle); + } + AttributeValues newValues = getAttributeValues().clone(); + int oldStyle = (this.style != style) ? this.style : -1; + applyStyle(style, newValues); + newValues.setSize(size); + return new Font(newValues, null, oldStyle, createdFont, font2DHandle); + } + + /** + * Creates a new Font object by replicating this + * Font object and applying a new style and transform. + * @param style the style for the new Font + * @param trans the AffineTransform associated with the + * new Font + * @return a new Font object. + * @throws IllegalArgumentException if trans is + * null + * @since 1.2 + */ + public Font deriveFont(int style, AffineTransform trans){ + AttributeValues newValues = getAttributeValues().clone(); + int oldStyle = (this.style != style) ? this.style : -1; + applyStyle(style, newValues); + applyTransform(trans, newValues); + return new Font(newValues, null, oldStyle, createdFont, font2DHandle); + } + + /** + * Creates a new Font object by replicating the current + * Font object and applying a new size to it. + * @param size the size for the new Font. + * @return a new Font object. + * @since 1.2 + */ + public Font deriveFont(float size){ + if (values == null) { + return new Font(name, style, size, createdFont, font2DHandle); + } + AttributeValues newValues = getAttributeValues().clone(); + newValues.setSize(size); + return new Font(newValues, null, -1, createdFont, font2DHandle); + } + + /** + * Creates a new Font object by replicating the current + * Font object and applying a new transform to it. + * @param trans the AffineTransform associated with the + * new Font + * @return a new Font object. + * @throws IllegalArgumentException if trans is + * null + * @since 1.2 + */ + public Font deriveFont(AffineTransform trans){ + AttributeValues newValues = getAttributeValues().clone(); + applyTransform(trans, newValues); + return new Font(newValues, null, -1, createdFont, font2DHandle); + } + + /** + * Creates a new Font object by replicating the current + * Font object and applying a new style to it. + * @param style the style for the new Font + * @return a new Font object. + * @since 1.2 + */ + public Font deriveFont(int style){ + if (values == null) { + return new Font(name, style, size, createdFont, font2DHandle); + } + AttributeValues newValues = getAttributeValues().clone(); + int oldStyle = (this.style != style) ? this.style : -1; + applyStyle(style, newValues); + return new Font(newValues, null, oldStyle, createdFont, font2DHandle); + } + + /** + * Creates a new Font object by replicating the current + * Font object and applying a new set of font attributes + * to it. + * + * @param attributes a map of attributes enabled for the new + * Font + * @return a new Font object. + * @since 1.2 + */ + public Font deriveFont(Map attributes) { + if (attributes == null) { + return this; + } + AttributeValues newValues = getAttributeValues().clone(); + newValues.merge(attributes, RECOGNIZED_MASK); + + return new Font(newValues, name, style, createdFont, font2DHandle); + } + + /** + * Checks if this Font has a glyph for the specified + * character. + * + *

Note: This method cannot handle supplementary + * characters. To support all Unicode characters, including + * supplementary characters, use the {@link #canDisplay(int)} + * method or canDisplayUpTo methods. + * + * @param c the character for which a glyph is needed + * @return true if this Font has a glyph for this + * character; false otherwise. + * @since 1.2 + */ + public boolean canDisplay(char c){ + return getFont2D().canDisplay(c); + } + + /** + * Checks if this Font has a glyph for the specified + * character. + * + * @param codePoint the character (Unicode code point) for which a glyph + * is needed. + * @return true if this Font has a glyph for the + * character; false otherwise. + * @throws IllegalArgumentException if the code point is not a valid Unicode + * code point. + * @see Character#isValidCodePoint(int) + * @since 1.5 + */ + public boolean canDisplay(int codePoint) { + if (!Character.isValidCodePoint(codePoint)) { + throw new IllegalArgumentException("invalid code point: " + + Integer.toHexString(codePoint)); + } + return getFont2D().canDisplay(codePoint); + } + + /** + * Indicates whether or not this Font can display a + * specified String. For strings with Unicode encoding, + * it is important to know if a particular font can display the + * string. This method returns an offset into the String + * str which is the first character this + * Font cannot display without using the missing glyph + * code. If the Font can display all characters, -1 is + * returned. + * @param str a String object + * @return an offset into str that points + * to the first character in str that this + * Font cannot display; or -1 if + * this Font can display all characters in + * str. + * @since 1.2 + */ + public int canDisplayUpTo(String str) { + Font2D font2d = getFont2D(); + int len = str.length(); + for (int i = 0; i < len; i++) { + char c = str.charAt(i); + if (font2d.canDisplay(c)) { + continue; + } + if (!Character.isHighSurrogate(c)) { + return i; + } + if (!font2d.canDisplay(str.codePointAt(i))) { + return i; + } + i++; + } + return -1; + } + + /** + * Indicates whether or not this Font can display + * the characters in the specified text + * starting at start and ending at + * limit. This method is a convenience overload. + * @param text the specified array of char values + * @param start the specified starting offset (in + * chars) into the specified array of + * char values + * @param limit the specified ending offset (in + * chars) into the specified array of + * char values + * @return an offset into text that points + * to the first character in text that this + * Font cannot display; or -1 if + * this Font can display all characters in + * text. + * @since 1.2 + */ + public int canDisplayUpTo(char[] text, int start, int limit) { + Font2D font2d = getFont2D(); + for (int i = start; i < limit; i++) { + char c = text[i]; + if (font2d.canDisplay(c)) { + continue; + } + if (!Character.isHighSurrogate(c)) { + return i; + } + if (!font2d.canDisplay(Character.codePointAt(text, i, limit))) { + return i; + } + i++; + } + return -1; + } + + /** + * Indicates whether or not this Font can display the + * text specified by the iter starting at + * start and ending at limit. + * + * @param iter a {@link CharacterIterator} object + * @param start the specified starting offset into the specified + * CharacterIterator. + * @param limit the specified ending offset into the specified + * CharacterIterator. + * @return an offset into iter that points + * to the first character in iter that this + * Font cannot display; or -1 if + * this Font can display all characters in + * iter. + * @since 1.2 + */ + public int canDisplayUpTo(CharacterIterator iter, int start, int limit) { + Font2D font2d = getFont2D(); + char c = iter.setIndex(start); + for (int i = start; i < limit; i++, c = iter.next()) { + if (font2d.canDisplay(c)) { + continue; + } + if (!Character.isHighSurrogate(c)) { + return i; + } + char c2 = iter.next(); + // c2 could be CharacterIterator.DONE which is not a low surrogate. + if (!Character.isLowSurrogate(c2)) { + return i; + } + if (!font2d.canDisplay(Character.toCodePoint(c, c2))) { + return i; + } + i++; + } + return -1; + } + + /** + * Returns the italic angle of this Font. The italic angle + * is the inverse slope of the caret which best matches the posture of this + * Font. + * @see TextAttribute#POSTURE + * @return the angle of the ITALIC style of this Font. + */ + public float getItalicAngle() { + return getItalicAngle(null); + } + + /* The FRC hints don't affect the value of the italic angle but + * we need to pass them in to look up a strike. + * If we can pass in ones already being used it can prevent an extra + * strike from being allocated. Note that since italic angle is + * a property of the font, the font transform is needed not the + * device transform. Finally, this is private but the only caller of this + * in the JDK - and the only likely caller - is in this same class. + */ + private float getItalicAngle(FontRenderContext frc) { + Object aa, fm; + if (frc == null) { + aa = RenderingHints.VALUE_TEXT_ANTIALIAS_OFF; + fm = RenderingHints.VALUE_FRACTIONALMETRICS_OFF; + } else { + aa = frc.getAntiAliasingHint(); + fm = frc.getFractionalMetricsHint(); + } + return getFont2D().getItalicAngle(this, identityTx, aa, fm); + } + + /** + * Checks whether or not this Font has uniform + * line metrics. A logical Font might be a + * composite font, which means that it is composed of different + * physical fonts to cover different code ranges. Each of these + * fonts might have different LineMetrics. If the + * logical Font is a single + * font then the metrics would be uniform. + * @return true if this Font has + * uniform line metrics; false otherwise. + */ + public boolean hasUniformLineMetrics() { + return false; // REMIND always safe, but prevents caller optimize + } + + private transient SoftReference flmref; + private FontLineMetrics defaultLineMetrics(FontRenderContext frc) { + FontLineMetrics flm = null; + if (flmref == null + || (flm = flmref.get()) == null + || !flm.frc.equals(frc)) { + + /* The device transform in the frc is not used in obtaining line + * metrics, although it probably should be: REMIND find why not? + * The font transform is used but its applied in getFontMetrics, so + * just pass identity here + */ + float [] metrics = new float[8]; + getFont2D().getFontMetrics(this, identityTx, + frc.getAntiAliasingHint(), + frc.getFractionalMetricsHint(), + metrics); + float ascent = metrics[0]; + float descent = metrics[1]; + float leading = metrics[2]; + float ssOffset = 0; + if (values != null && values.getSuperscript() != 0) { + ssOffset = (float)getTransform().getTranslateY(); + ascent -= ssOffset; + descent += ssOffset; + } + float height = ascent + descent + leading; + + int baselineIndex = 0; // need real index, assumes roman for everything + // need real baselines eventually + float[] baselineOffsets = { 0, (descent/2f - ascent) / 2f, -ascent }; + + float strikethroughOffset = metrics[4]; + float strikethroughThickness = metrics[5]; + + float underlineOffset = metrics[6]; + float underlineThickness = metrics[7]; + + float italicAngle = getItalicAngle(frc); + + if (isTransformed()) { + AffineTransform ctx = values.getCharTransform(); // extract rotation + if (ctx != null) { + Point2D.Float pt = new Point2D.Float(); + pt.setLocation(0, strikethroughOffset); + ctx.deltaTransform(pt, pt); + strikethroughOffset = pt.y; + pt.setLocation(0, strikethroughThickness); + ctx.deltaTransform(pt, pt); + strikethroughThickness = pt.y; + pt.setLocation(0, underlineOffset); + ctx.deltaTransform(pt, pt); + underlineOffset = pt.y; + pt.setLocation(0, underlineThickness); + ctx.deltaTransform(pt, pt); + underlineThickness = pt.y; + } + } + strikethroughOffset += ssOffset; + underlineOffset += ssOffset; + + CoreMetrics cm = new CoreMetrics(ascent, descent, leading, height, + baselineIndex, baselineOffsets, + strikethroughOffset, strikethroughThickness, + underlineOffset, underlineThickness, + ssOffset, italicAngle); + + flm = new FontLineMetrics(0, cm, frc); + flmref = new SoftReference(flm); + } + + return (FontLineMetrics)flm.clone(); + } + + /** + * Returns a {@link LineMetrics} object created with the specified + * String and {@link FontRenderContext}. + * @param str the specified String + * @param frc the specified FontRenderContext + * @return a LineMetrics object created with the + * specified String and {@link FontRenderContext}. + */ + public LineMetrics getLineMetrics( String str, FontRenderContext frc) { + FontLineMetrics flm = defaultLineMetrics(frc); + flm.numchars = str.length(); + return flm; + } + + /** + * Returns a LineMetrics object created with the + * specified arguments. + * @param str the specified String + * @param beginIndex the initial offset of str + * @param limit the end offset of str + * @param frc the specified FontRenderContext + * @return a LineMetrics object created with the + * specified arguments. + */ + public LineMetrics getLineMetrics( String str, + int beginIndex, int limit, + FontRenderContext frc) { + FontLineMetrics flm = defaultLineMetrics(frc); + int numChars = limit - beginIndex; + flm.numchars = (numChars < 0)? 0: numChars; + return flm; + } + + /** + * Returns a LineMetrics object created with the + * specified arguments. + * @param chars an array of characters + * @param beginIndex the initial offset of chars + * @param limit the end offset of chars + * @param frc the specified FontRenderContext + * @return a LineMetrics object created with the + * specified arguments. + */ + public LineMetrics getLineMetrics(char [] chars, + int beginIndex, int limit, + FontRenderContext frc) { + FontLineMetrics flm = defaultLineMetrics(frc); + int numChars = limit - beginIndex; + flm.numchars = (numChars < 0)? 0: numChars; + return flm; + } + + /** + * Returns a LineMetrics object created with the + * specified arguments. + * @param ci the specified CharacterIterator + * @param beginIndex the initial offset in ci + * @param limit the end offset of ci + * @param frc the specified FontRenderContext + * @return a LineMetrics object created with the + * specified arguments. + */ + public LineMetrics getLineMetrics(CharacterIterator ci, + int beginIndex, int limit, + FontRenderContext frc) { + FontLineMetrics flm = defaultLineMetrics(frc); + int numChars = limit - beginIndex; + flm.numchars = (numChars < 0)? 0: numChars; + return flm; + } + + /** + * Returns the logical bounds of the specified String in + * the specified FontRenderContext. The logical bounds + * contains the origin, ascent, advance, and height, which includes + * the leading. The logical bounds does not always enclose all the + * text. For example, in some languages and in some fonts, accent + * marks can be positioned above the ascent or below the descent. + * To obtain a visual bounding box, which encloses all the text, + * use the {@link TextLayout#getBounds() getBounds} method of + * TextLayout. + *

Note: The returned bounds is in baseline-relative coordinates + * (see {@link java.awt.Font class notes}). + * @param str the specified String + * @param frc the specified FontRenderContext + * @return a {@link Rectangle2D} that is the bounding box of the + * specified String in the specified + * FontRenderContext. + * @see FontRenderContext + * @see Font#createGlyphVector + * @since 1.2 + */ + public Rectangle2D getStringBounds( String str, FontRenderContext frc) { + char[] array = str.toCharArray(); + return getStringBounds(array, 0, array.length, frc); + } + + /** + * Returns the logical bounds of the specified String in + * the specified FontRenderContext. The logical bounds + * contains the origin, ascent, advance, and height, which includes + * the leading. The logical bounds does not always enclose all the + * text. For example, in some languages and in some fonts, accent + * marks can be positioned above the ascent or below the descent. + * To obtain a visual bounding box, which encloses all the text, + * use the {@link TextLayout#getBounds() getBounds} method of + * TextLayout. + *

Note: The returned bounds is in baseline-relative coordinates + * (see {@link java.awt.Font class notes}). + * @param str the specified String + * @param beginIndex the initial offset of str + * @param limit the end offset of str + * @param frc the specified FontRenderContext + * @return a Rectangle2D that is the bounding box of the + * specified String in the specified + * FontRenderContext. + * @throws IndexOutOfBoundsException if beginIndex is + * less than zero, or limit is greater than the + * length of str, or beginIndex + * is greater than limit. + * @see FontRenderContext + * @see Font#createGlyphVector + * @since 1.2 + */ + public Rectangle2D getStringBounds( String str, + int beginIndex, int limit, + FontRenderContext frc) { + String substr = str.substring(beginIndex, limit); + return getStringBounds(substr, frc); + } + + /** + * Returns the logical bounds of the specified array of characters + * in the specified FontRenderContext. The logical + * bounds contains the origin, ascent, advance, and height, which + * includes the leading. The logical bounds does not always enclose + * all the text. For example, in some languages and in some fonts, + * accent marks can be positioned above the ascent or below the + * descent. To obtain a visual bounding box, which encloses all the + * text, use the {@link TextLayout#getBounds() getBounds} method of + * TextLayout. + *

Note: The returned bounds is in baseline-relative coordinates + * (see {@link java.awt.Font class notes}). + * @param chars an array of characters + * @param beginIndex the initial offset in the array of + * characters + * @param limit the end offset in the array of characters + * @param frc the specified FontRenderContext + * @return a Rectangle2D that is the bounding box of the + * specified array of characters in the specified + * FontRenderContext. + * @throws IndexOutOfBoundsException if beginIndex is + * less than zero, or limit is greater than the + * length of chars, or beginIndex + * is greater than limit. + * @see FontRenderContext + * @see Font#createGlyphVector + * @since 1.2 + */ + public Rectangle2D getStringBounds(char [] chars, + int beginIndex, int limit, + FontRenderContext frc) { + if (beginIndex < 0) { + throw new IndexOutOfBoundsException("beginIndex: " + beginIndex); + } + if (limit > chars.length) { + throw new IndexOutOfBoundsException("limit: " + limit); + } + if (beginIndex > limit) { + throw new IndexOutOfBoundsException("range length: " + + (limit - beginIndex)); + } + + // this code should be in textlayout + // quick check for simple text, assume GV ok to use if simple + + boolean simple = values == null || + (values.getKerning() == 0 && values.getLigatures() == 0 && + values.getBaselineTransform() == null); + if (simple) { + simple = ! FontUtilities.isComplexText(chars, beginIndex, limit); + } + + if (simple) { + GlyphVector gv = new StandardGlyphVector(this, chars, beginIndex, + limit - beginIndex, frc); + return gv.getLogicalBounds(); + } else { + // need char array constructor on textlayout + String str = new String(chars, beginIndex, limit - beginIndex); + TextLayout tl = new TextLayout(str, this, frc); + return new Rectangle2D.Float(0, -tl.getAscent(), tl.getAdvance(), + tl.getAscent() + tl.getDescent() + + tl.getLeading()); + } + } + + /** + * Returns the logical bounds of the characters indexed in the + * specified {@link CharacterIterator} in the + * specified FontRenderContext. The logical bounds + * contains the origin, ascent, advance, and height, which includes + * the leading. The logical bounds does not always enclose all the + * text. For example, in some languages and in some fonts, accent + * marks can be positioned above the ascent or below the descent. + * To obtain a visual bounding box, which encloses all the text, + * use the {@link TextLayout#getBounds() getBounds} method of + * TextLayout. + *

Note: The returned bounds is in baseline-relative coordinates + * (see {@link java.awt.Font class notes}). + * @param ci the specified CharacterIterator + * @param beginIndex the initial offset in ci + * @param limit the end offset in ci + * @param frc the specified FontRenderContext + * @return a Rectangle2D that is the bounding box of the + * characters indexed in the specified CharacterIterator + * in the specified FontRenderContext. + * @see FontRenderContext + * @see Font#createGlyphVector + * @since 1.2 + * @throws IndexOutOfBoundsException if beginIndex is + * less than the start index of ci, or + * limit is greater than the end index of + * ci, or beginIndex is greater + * than limit + */ + public Rectangle2D getStringBounds(CharacterIterator ci, + int beginIndex, int limit, + FontRenderContext frc) { + int start = ci.getBeginIndex(); + int end = ci.getEndIndex(); + + if (beginIndex < start) { + throw new IndexOutOfBoundsException("beginIndex: " + beginIndex); + } + if (limit > end) { + throw new IndexOutOfBoundsException("limit: " + limit); + } + if (beginIndex > limit) { + throw new IndexOutOfBoundsException("range length: " + + (limit - beginIndex)); + } + + char[] arr = new char[limit - beginIndex]; + + ci.setIndex(beginIndex); + for(int idx = 0; idx < arr.length; idx++) { + arr[idx] = ci.current(); + ci.next(); + } + + return getStringBounds(arr,0,arr.length,frc); + } + + /** + * Returns the bounds for the character with the maximum + * bounds as defined in the specified FontRenderContext. + *

Note: The returned bounds is in baseline-relative coordinates + * (see {@link java.awt.Font class notes}). + * @param frc the specified FontRenderContext + * @return a Rectangle2D that is the bounding box + * for the character with the maximum bounds. + */ + public Rectangle2D getMaxCharBounds(FontRenderContext frc) { + float [] metrics = new float[4]; + + getFont2D().getFontMetrics(this, frc, metrics); + + return new Rectangle2D.Float(0, -metrics[0], + metrics[3], + metrics[0] + metrics[1] + metrics[2]); + } + + /** + * Creates a {@link java.awt.font.GlyphVector GlyphVector} by + * mapping characters to glyphs one-to-one based on the + * Unicode cmap in this Font. This method does no other + * processing besides the mapping of glyphs to characters. This + * means that this method is not useful for some scripts, such + * as Arabic, Hebrew, Thai, and Indic, that require reordering, + * shaping, or ligature substitution. + * @param frc the specified FontRenderContext + * @param str the specified String + * @return a new GlyphVector created with the + * specified String and the specified + * FontRenderContext. + */ + public GlyphVector createGlyphVector(FontRenderContext frc, String str) + { + return (GlyphVector)new StandardGlyphVector(this, str, frc); + } + + /** + * Creates a {@link java.awt.font.GlyphVector GlyphVector} by + * mapping characters to glyphs one-to-one based on the + * Unicode cmap in this Font. This method does no other + * processing besides the mapping of glyphs to characters. This + * means that this method is not useful for some scripts, such + * as Arabic, Hebrew, Thai, and Indic, that require reordering, + * shaping, or ligature substitution. + * @param frc the specified FontRenderContext + * @param chars the specified array of characters + * @return a new GlyphVector created with the + * specified array of characters and the specified + * FontRenderContext. + */ + public GlyphVector createGlyphVector(FontRenderContext frc, char[] chars) + { + return (GlyphVector)new StandardGlyphVector(this, chars, frc); + } + + /** + * Creates a {@link java.awt.font.GlyphVector GlyphVector} by + * mapping the specified characters to glyphs one-to-one based on the + * Unicode cmap in this Font. This method does no other + * processing besides the mapping of glyphs to characters. This + * means that this method is not useful for some scripts, such + * as Arabic, Hebrew, Thai, and Indic, that require reordering, + * shaping, or ligature substitution. + * @param frc the specified FontRenderContext + * @param ci the specified CharacterIterator + * @return a new GlyphVector created with the + * specified CharacterIterator and the specified + * FontRenderContext. + */ + public GlyphVector createGlyphVector( FontRenderContext frc, + CharacterIterator ci) + { + return (GlyphVector)new StandardGlyphVector(this, ci, frc); + } + + /** + * Creates a {@link java.awt.font.GlyphVector GlyphVector} by + * mapping characters to glyphs one-to-one based on the + * Unicode cmap in this Font. This method does no other + * processing besides the mapping of glyphs to characters. This + * means that this method is not useful for some scripts, such + * as Arabic, Hebrew, Thai, and Indic, that require reordering, + * shaping, or ligature substitution. + * @param frc the specified FontRenderContext + * @param glyphCodes the specified integer array + * @return a new GlyphVector created with the + * specified integer array and the specified + * FontRenderContext. + */ + public GlyphVector createGlyphVector( FontRenderContext frc, + int [] glyphCodes) + { + return (GlyphVector)new StandardGlyphVector(this, glyphCodes, frc); + } + + /** + * Returns a new GlyphVector object, performing full + * layout of the text if possible. Full layout is required for + * complex text, such as Arabic or Hindi. Support for different + * scripts depends on the font and implementation. + *

+ * Layout requires bidi analysis, as performed by + * Bidi, and should only be performed on text that + * has a uniform direction. The direction is indicated in the + * flags parameter,by using LAYOUT_RIGHT_TO_LEFT to indicate a + * right-to-left (Arabic and Hebrew) run direction, or + * LAYOUT_LEFT_TO_RIGHT to indicate a left-to-right (English) + * run direction. + *

+ * In addition, some operations, such as Arabic shaping, require + * context, so that the characters at the start and limit can have + * the proper shapes. Sometimes the data in the buffer outside + * the provided range does not have valid data. The values + * LAYOUT_NO_START_CONTEXT and LAYOUT_NO_LIMIT_CONTEXT can be + * added to the flags parameter to indicate that the text before + * start, or after limit, respectively, should not be examined + * for context. + *

+ * All other values for the flags parameter are reserved. + * + * @param frc the specified FontRenderContext + * @param text the text to layout + * @param start the start of the text to use for the GlyphVector + * @param limit the limit of the text to use for the GlyphVector + * @param flags control flags as described above + * @return a new GlyphVector representing the text between + * start and limit, with glyphs chosen and positioned so as to best represent + * the text + * @throws ArrayIndexOutOfBoundsException if start or limit is + * out of bounds + * @see java.text.Bidi + * @see #LAYOUT_LEFT_TO_RIGHT + * @see #LAYOUT_RIGHT_TO_LEFT + * @see #LAYOUT_NO_START_CONTEXT + * @see #LAYOUT_NO_LIMIT_CONTEXT + * @since 1.4 + */ + public GlyphVector layoutGlyphVector(FontRenderContext frc, + char[] text, + int start, + int limit, + int flags) { + + return new StandardGlyphVector(this,text,start, limit-start, frc); + } + + /** + * A flag to layoutGlyphVector indicating that text is left-to-right as + * determined by Bidi analysis. + */ + public static final int LAYOUT_LEFT_TO_RIGHT = 0; + + /** + * A flag to layoutGlyphVector indicating that text is right-to-left as + * determined by Bidi analysis. + */ + public static final int LAYOUT_RIGHT_TO_LEFT = 1; + + /** + * A flag to layoutGlyphVector indicating that text in the char array + * before the indicated start should not be examined. + */ + public static final int LAYOUT_NO_START_CONTEXT = 2; + + /** + * A flag to layoutGlyphVector indicating that text in the char array + * after the indicated limit should not be examined. + */ + public static final int LAYOUT_NO_LIMIT_CONTEXT = 4; + + + private static void applyTransform(AffineTransform trans, AttributeValues values) { + if (trans == null) { + throw new IllegalArgumentException("transform must not be null"); + } + values.setTransform(trans); + } + + private static void applyStyle(int style, AttributeValues values) { + // WEIGHT_BOLD, WEIGHT_REGULAR + values.setWeight((style & BOLD) != 0 ? 2f : 1f); + // POSTURE_OBLIQUE, POSTURE_REGULAR + values.setPosture((style & ITALIC) != 0 ? .2f : 0f); + } + +} diff --git a/openjdk/java/awt/GraphicsConfiguration.java b/openjdk/java/awt/GraphicsConfiguration.java new file mode 100644 index 0000000..a93d014 --- /dev/null +++ b/openjdk/java/awt/GraphicsConfiguration.java @@ -0,0 +1,452 @@ +/* + * Copyright (c) 1997, 2013, 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 java.awt; + +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.VolatileImage; +import java.awt.image.WritableRaster; + +/** + * The GraphicsConfiguration class describes the + * characteristics of a graphics destination such as a printer or monitor. + * There can be many GraphicsConfiguration objects associated + * with a single graphics device, representing different drawing modes or + * capabilities. The corresponding native structure will vary from platform + * to platform. For example, on X11 windowing systems, + * each visual is a different GraphicsConfiguration. + * On Microsoft Windows, GraphicsConfigurations represent + * PixelFormats available in the current resolution and color depth. + *

+ * In a virtual device multi-screen environment in which the desktop + * area could span multiple physical screen devices, the bounds of the + * GraphicsConfiguration objects are relative to the + * virtual coordinate system. When setting the location of a + * component, use {@link #getBounds() getBounds} to get the bounds of + * the desired GraphicsConfiguration and offset the location + * with the coordinates of the GraphicsConfiguration, + * as the following code sample illustrates: + *

+ * + *
+ *      Frame f = new Frame(gc);  // where gc is a GraphicsConfiguration
+ *      Rectangle bounds = gc.getBounds();
+ *      f.setLocation(10 + bounds.x, 10 + bounds.y); 
+ * + *

+ * To determine if your environment is a virtual device + * environment, call getBounds on all of the + * GraphicsConfiguration objects in your system. If + * any of the origins of the returned bounds is not (0, 0), + * your environment is a virtual device environment. + * + *

+ * You can also use getBounds to determine the bounds + * of the virtual device. To do this, first call getBounds on all + * of the GraphicsConfiguration objects in your + * system. Then calculate the union of all of the bounds returned + * from the calls to getBounds. The union is the + * bounds of the virtual device. The following code sample + * calculates the bounds of the virtual device. + * + *

{@code
+ *      Rectangle virtualBounds = new Rectangle();
+ *      GraphicsEnvironment ge = GraphicsEnvironment.
+ *              getLocalGraphicsEnvironment();
+ *      GraphicsDevice[] gs =
+ *              ge.getScreenDevices();
+ *      for (int j = 0; j < gs.length; j++) {
+ *          GraphicsDevice gd = gs[j];
+ *          GraphicsConfiguration[] gc =
+ *              gd.getConfigurations();
+ *          for (int i=0; i < gc.length; i++) {
+ *              virtualBounds =
+ *                  virtualBounds.union(gc[i].getBounds());
+ *          }
+ *      } }
+ * + * @see Window + * @see Frame + * @see GraphicsEnvironment + * @see GraphicsDevice + */ +/* + * REMIND: What to do about capabilities? + * The + * capabilities of the device can be determined by enumerating the possible + * capabilities and checking if the GraphicsConfiguration + * implements the interface for that capability. + * + */ + + +public abstract class GraphicsConfiguration { + + private static BufferCapabilities defaultBufferCaps; + private static ImageCapabilities defaultImageCaps; + + /** + * This is an abstract class that cannot be instantiated directly. + * Instances must be obtained from a suitable factory or query method. + * + * @see GraphicsDevice#getConfigurations + * @see GraphicsDevice#getDefaultConfiguration + * @see GraphicsDevice#getBestConfiguration + * @see Graphics2D#getDeviceConfiguration + */ + protected GraphicsConfiguration() { + } + + /** + * Returns the {@link GraphicsDevice} associated with this + * GraphicsConfiguration. + * @return a GraphicsDevice object that is + * associated with this GraphicsConfiguration. + */ + public abstract GraphicsDevice getDevice(); + + /** + * Returns a {@link BufferedImage} with a data layout and color model + * compatible with this GraphicsConfiguration. This + * method has nothing to do with memory-mapping + * a device. The returned BufferedImage has + * a layout and color model that is closest to this native device + * configuration and can therefore be optimally blitted to this + * device. + * @param width the width of the returned BufferedImage + * @param height the height of the returned BufferedImage + * @return a BufferedImage whose data layout and color + * model is compatible with this GraphicsConfiguration. + */ + public BufferedImage createCompatibleImage(int width, int height) { + ColorModel model = getColorModel(); + WritableRaster raster = + model.createCompatibleWritableRaster(width, height); + return new BufferedImage(model, raster, + model.isAlphaPremultiplied(), null); + } + + /** + * Returns a BufferedImage that supports the specified + * transparency and has a data layout and color model + * compatible with this GraphicsConfiguration. This + * method has nothing to do with memory-mapping + * a device. The returned BufferedImage has a layout and + * color model that can be optimally blitted to a device + * with this GraphicsConfiguration. + * @param width the width of the returned BufferedImage + * @param height the height of the returned BufferedImage + * @param transparency the specified transparency mode + * @return a BufferedImage whose data layout and color + * model is compatible with this GraphicsConfiguration + * and also supports the specified transparency. + * @throws IllegalArgumentException if the transparency is not a valid value + * @see Transparency#OPAQUE + * @see Transparency#BITMASK + * @see Transparency#TRANSLUCENT + */ + public BufferedImage createCompatibleImage(int width, int height, + int transparency) + { + if (getColorModel().getTransparency() == transparency) { + return createCompatibleImage(width, height); + } + + ColorModel cm = getColorModel(transparency); + if (cm == null) { + throw new IllegalArgumentException("Unknown transparency: " + + transparency); + } + WritableRaster wr = cm.createCompatibleWritableRaster(width, height); + return new BufferedImage(cm, wr, cm.isAlphaPremultiplied(), null); + } + + + /** + * Returns a {@link VolatileImage} with a data layout and color model + * compatible with this GraphicsConfiguration. + * The returned VolatileImage + * may have data that is stored optimally for the underlying graphics + * device and may therefore benefit from platform-specific rendering + * acceleration. + * @param width the width of the returned VolatileImage + * @param height the height of the returned VolatileImage + * @return a VolatileImage whose data layout and color + * model is compatible with this GraphicsConfiguration. + * @see Component#createVolatileImage(int, int) + * @since 1.4 + */ + public VolatileImage createCompatibleVolatileImage(int width, int height) { + VolatileImage vi = null; + try { + vi = createCompatibleVolatileImage(width, height, + null, Transparency.OPAQUE); + } catch (AWTException e) { + // shouldn't happen: we're passing in null caps + assert false; + } + return vi; + } + + /** + * Returns a {@link VolatileImage} with a data layout and color model + * compatible with this GraphicsConfiguration. + * The returned VolatileImage + * may have data that is stored optimally for the underlying graphics + * device and may therefore benefit from platform-specific rendering + * acceleration. + * @param width the width of the returned VolatileImage + * @param height the height of the returned VolatileImage + * @param transparency the specified transparency mode + * @return a VolatileImage whose data layout and color + * model is compatible with this GraphicsConfiguration. + * @throws IllegalArgumentException if the transparency is not a valid value + * @see Transparency#OPAQUE + * @see Transparency#BITMASK + * @see Transparency#TRANSLUCENT + * @see Component#createVolatileImage(int, int) + * @since 1.5 + */ + public VolatileImage createCompatibleVolatileImage(int width, int height, + int transparency) + { + VolatileImage vi = null; + try { + vi = createCompatibleVolatileImage(width, height, null, transparency); + } catch (AWTException e) { + // shouldn't happen: we're passing in null caps + assert false; + } + return vi; + } + + /** + * Returns a {@link VolatileImage} with a data layout and color model + * compatible with this GraphicsConfiguration, using + * the specified image capabilities. + * If the caps parameter is null, it is effectively ignored + * and this method will create a VolatileImage without regard to + * ImageCapabilities constraints. + * + * The returned VolatileImage has + * a layout and color model that is closest to this native device + * configuration and can therefore be optimally blitted to this + * device. + * @return a VolatileImage whose data layout and color + * model is compatible with this GraphicsConfiguration. + * @param width the width of the returned VolatileImage + * @param height the height of the returned VolatileImage + * @param caps the image capabilities + * @exception AWTException if the supplied image capabilities could not + * be met by this graphics configuration + * @since 1.4 + */ + public VolatileImage createCompatibleVolatileImage(int width, int height, + ImageCapabilities caps) throws AWTException + { + return createCompatibleVolatileImage(width, height, caps, + Transparency.OPAQUE); + } + + /** + * Returns a {@link VolatileImage} with a data layout and color model + * compatible with this GraphicsConfiguration, using + * the specified image capabilities and transparency value. + * If the caps parameter is null, it is effectively ignored + * and this method will create a VolatileImage without regard to + * ImageCapabilities constraints. + * + * The returned VolatileImage has + * a layout and color model that is closest to this native device + * configuration and can therefore be optimally blitted to this + * device. + * @param width the width of the returned VolatileImage + * @param height the height of the returned VolatileImage + * @param caps the image capabilities + * @param transparency the specified transparency mode + * @return a VolatileImage whose data layout and color + * model is compatible with this GraphicsConfiguration. + * @see Transparency#OPAQUE + * @see Transparency#BITMASK + * @see Transparency#TRANSLUCENT + * @throws IllegalArgumentException if the transparency is not a valid value + * @exception AWTException if the supplied image capabilities could not + * be met by this graphics configuration + * @see Component#createVolatileImage(int, int) + * @since 1.5 + */ + public VolatileImage createCompatibleVolatileImage(int width, int height, + ImageCapabilities caps, int transparency) throws AWTException + { + VolatileImage vi = + new Container().createVolatileImage(width, height, caps); + if (caps != null && caps.isAccelerated() && + !vi.getCapabilities().isAccelerated()) + { + throw new AWTException("Supplied image capabilities could not " + + "be met by this graphics configuration."); + } + return vi; + } + + /** + * Returns the {@link ColorModel} associated with this + * GraphicsConfiguration. + * @return a ColorModel object that is associated with + * this GraphicsConfiguration. + */ + public abstract ColorModel getColorModel(); + + /** + * Returns the ColorModel associated with this + * GraphicsConfiguration that supports the specified + * transparency. + * @param transparency the specified transparency mode + * @return a ColorModel object that is associated with + * this GraphicsConfiguration and supports the + * specified transparency or null if the transparency is not a valid + * value. + * @see Transparency#OPAQUE + * @see Transparency#BITMASK + * @see Transparency#TRANSLUCENT + */ + public abstract ColorModel getColorModel(int transparency); + + /** + * Returns the default {@link AffineTransform} for this + * GraphicsConfiguration. This + * AffineTransform is typically the Identity transform + * for most normal screens. The default AffineTransform + * maps coordinates onto the device such that 72 user space + * coordinate units measure approximately 1 inch in device + * space. The normalizing transform can be used to make + * this mapping more exact. Coordinates in the coordinate space + * defined by the default AffineTransform for screen and + * printer devices have the origin in the upper left-hand corner of + * the target region of the device, with X coordinates + * increasing to the right and Y coordinates increasing downwards. + * For image buffers not associated with a device, such as those not + * created by createCompatibleImage, + * this AffineTransform is the Identity transform. + * @return the default AffineTransform for this + * GraphicsConfiguration. + */ + public abstract AffineTransform getDefaultTransform(); + + /** + * + * Returns a AffineTransform that can be concatenated + * with the default AffineTransform + * of a GraphicsConfiguration so that 72 units in user + * space equals 1 inch in device space. + *

+ * For a particular {@link Graphics2D}, g, one + * can reset the transformation to create + * such a mapping by using the following pseudocode: + *

+     *      GraphicsConfiguration gc = g.getDeviceConfiguration();
+     *
+     *      g.setTransform(gc.getDefaultTransform());
+     *      g.transform(gc.getNormalizingTransform());
+     * 
+ * Note that sometimes this AffineTransform is identity, + * such as for printers or metafile output, and that this + * AffineTransform is only as accurate as the information + * supplied by the underlying system. For image buffers not + * associated with a device, such as those not created by + * createCompatibleImage, this + * AffineTransform is the Identity transform + * since there is no valid distance measurement. + * @return an AffineTransform to concatenate to the + * default AffineTransform so that 72 units in user + * space is mapped to 1 inch in device space. + */ + public abstract AffineTransform getNormalizingTransform(); + + /** + * Returns the bounds of the GraphicsConfiguration + * in the device coordinates. In a multi-screen environment + * with a virtual device, the bounds can have negative X + * or Y origins. + * @return the bounds of the area covered by this + * GraphicsConfiguration. + * @since 1.3 + */ + public abstract Rectangle getBounds(); + + private static class DefaultBufferCapabilities extends BufferCapabilities { + public DefaultBufferCapabilities(ImageCapabilities imageCaps) { + super(imageCaps, imageCaps, null); + } + } + + /** + * Returns the buffering capabilities of this + * GraphicsConfiguration. + * @return the buffering capabilities of this graphics + * configuration object + * @since 1.4 + */ + public BufferCapabilities getBufferCapabilities() { + if (defaultBufferCaps == null) { + defaultBufferCaps = new DefaultBufferCapabilities( + getImageCapabilities()); + } + return defaultBufferCaps; + } + + /** + * Returns the image capabilities of this + * GraphicsConfiguration. + * @return the image capabilities of this graphics + * configuration object + * @since 1.4 + */ + public ImageCapabilities getImageCapabilities() { + if (defaultImageCaps == null) { + defaultImageCaps = new ImageCapabilities(false); + } + return defaultImageCaps; + } + + /** + * Returns whether this {@code GraphicsConfiguration} supports + * the {@link GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT + * PERPIXEL_TRANSLUCENT} kind of translucency. + * + * @return whether the given GraphicsConfiguration supports + * the translucency effects. + * + * @see Window#setBackground(Color) + * + * @since 1.7 + */ + public boolean isTranslucencyCapable() { + // Overridden in subclasses + return false; + } +} diff --git a/openjdk/java/awt/Image.java b/openjdk/java/awt/Image.java new file mode 100644 index 0000000..a2485d5 --- /dev/null +++ b/openjdk/java/awt/Image.java @@ -0,0 +1,354 @@ +/* + * Copyright (c) 1995, 2013, 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 java.awt; + +import java.awt.image.ImageProducer; +import java.awt.image.ImageObserver; +import java.awt.image.ImageFilter; +import java.awt.image.FilteredImageSource; +import java.awt.image.AreaAveragingScaleFilter; +import java.awt.image.ReplicateScaleFilter; + +//import sun.awt.image.SurfaceManager; + + +/** + * The abstract class Image is the superclass of all + * classes that represent graphical images. The image must be + * obtained in a platform-specific manner. + * + * @author Sami Shaio + * @author Arthur van Hoff + * @since JDK1.0 + */ +public abstract class Image { + + /** + * convenience object; we can use this single static object for + * all images that do not create their own image caps; it holds the + * default (unaccelerated) properties. + */ + private static ImageCapabilities defaultImageCaps = + new ImageCapabilities(false); + + /** + * Priority for accelerating this image. Subclasses are free to + * set different default priorities and applications are free to + * set the priority for specific images via the + * setAccelerationPriority(float) method. + * @since 1.5 + */ + protected float accelerationPriority = .5f; + + /** + * Determines the width of the image. If the width is not yet known, + * this method returns -1 and the specified + * ImageObserver object is notified later. + * @param observer an object waiting for the image to be loaded. + * @return the width of this image, or -1 + * if the width is not yet known. + * @see java.awt.Image#getHeight + * @see java.awt.image.ImageObserver + */ + public abstract int getWidth(ImageObserver observer); + + /** + * Determines the height of the image. If the height is not yet known, + * this method returns -1 and the specified + * ImageObserver object is notified later. + * @param observer an object waiting for the image to be loaded. + * @return the height of this image, or -1 + * if the height is not yet known. + * @see java.awt.Image#getWidth + * @see java.awt.image.ImageObserver + */ + public abstract int getHeight(ImageObserver observer); + + /** + * Gets the object that produces the pixels for the image. + * This method is called by the image filtering classes and by + * methods that perform image conversion and scaling. + * @return the image producer that produces the pixels + * for this image. + * @see java.awt.image.ImageProducer + */ + public abstract ImageProducer getSource(); + + /** + * Creates a graphics context for drawing to an off-screen image. + * This method can only be called for off-screen images. + * @return a graphics context to draw to the off-screen image. + * @exception UnsupportedOperationException if called for a + * non-off-screen image. + * @see java.awt.Graphics + * @see java.awt.Component#createImage(int, int) + */ + public abstract Graphics getGraphics(); + + /** + * Gets a property of this image by name. + *

+ * Individual property names are defined by the various image + * formats. If a property is not defined for a particular image, this + * method returns the UndefinedProperty object. + *

+ * If the properties for this image are not yet known, this method + * returns null, and the ImageObserver + * object is notified later. + *

+ * The property name "comment" should be used to store + * an optional comment which can be presented to the application as a + * description of the image, its source, or its author. + * @param name a property name. + * @param observer an object waiting for this image to be loaded. + * @return the value of the named property. + * @throws NullPointerException if the property name is null. + * @see java.awt.image.ImageObserver + * @see java.awt.Image#UndefinedProperty + */ + public abstract Object getProperty(String name, ImageObserver observer); + + /** + * The UndefinedProperty object should be returned whenever a + * property which was not defined for a particular image is fetched. + */ + public static final Object UndefinedProperty = new Object(); + + /** + * Creates a scaled version of this image. + * A new Image object is returned which will render + * the image at the specified width and + * height by default. The new Image object + * may be loaded asynchronously even if the original source image + * has already been loaded completely. + * + *

+ * + * If either width + * or height is a negative number then a value is + * substituted to maintain the aspect ratio of the original image + * dimensions. If both width and height + * are negative, then the original image dimensions are used. + * + * @param width the width to which to scale the image. + * @param height the height to which to scale the image. + * @param hints flags to indicate the type of algorithm to use + * for image resampling. + * @return a scaled version of the image. + * @exception IllegalArgumentException if width + * or height is zero. + * @see java.awt.Image#SCALE_DEFAULT + * @see java.awt.Image#SCALE_FAST + * @see java.awt.Image#SCALE_SMOOTH + * @see java.awt.Image#SCALE_REPLICATE + * @see java.awt.Image#SCALE_AREA_AVERAGING + * @since JDK1.1 + */ + public Image getScaledInstance(int width, int height, int hints) { + ImageFilter filter; + if ((hints & (SCALE_SMOOTH | SCALE_AREA_AVERAGING)) != 0) { + filter = new AreaAveragingScaleFilter(width, height); + } else { + filter = new ReplicateScaleFilter(width, height); + } + ImageProducer prod; + prod = new FilteredImageSource(getSource(), filter); + return Toolkit.getDefaultToolkit().createImage(prod); + } + + /** + * Use the default image-scaling algorithm. + * @since JDK1.1 + */ + public static final int SCALE_DEFAULT = 1; + + /** + * Choose an image-scaling algorithm that gives higher priority + * to scaling speed than smoothness of the scaled image. + * @since JDK1.1 + */ + public static final int SCALE_FAST = 2; + + /** + * Choose an image-scaling algorithm that gives higher priority + * to image smoothness than scaling speed. + * @since JDK1.1 + */ + public static final int SCALE_SMOOTH = 4; + + /** + * Use the image scaling algorithm embodied in the + * ReplicateScaleFilter class. + * The Image object is free to substitute a different filter + * that performs the same algorithm yet integrates more efficiently + * into the imaging infrastructure supplied by the toolkit. + * @see java.awt.image.ReplicateScaleFilter + * @since JDK1.1 + */ + public static final int SCALE_REPLICATE = 8; + + /** + * Use the Area Averaging image scaling algorithm. The + * image object is free to substitute a different filter that + * performs the same algorithm yet integrates more efficiently + * into the image infrastructure supplied by the toolkit. + * @see java.awt.image.AreaAveragingScaleFilter + * @since JDK1.1 + */ + public static final int SCALE_AREA_AVERAGING = 16; + + /** + * Flushes all reconstructable resources being used by this Image object. + * This includes any pixel data that is being cached for rendering to + * the screen as well as any system resources that are being used + * to store data or pixels for the image if they can be recreated. + * The image is reset to a state similar to when it was first created + * so that if it is again rendered, the image data will have to be + * recreated or fetched again from its source. + *

+ * Examples of how this method affects specific types of Image object: + *

    + *
  • + * BufferedImage objects leave the primary Raster which stores their + * pixels untouched, but flush any information cached about those + * pixels such as copies uploaded to the display hardware for + * accelerated blits. + *
  • + * Image objects created by the Component methods which take a + * width and height leave their primary buffer of pixels untouched, + * but have all cached information released much like is done for + * BufferedImage objects. + *
  • + * VolatileImage objects release all of their pixel resources + * including their primary copy which is typically stored on + * the display hardware where resources are scarce. + * These objects can later be restored using their + * {@link java.awt.image.VolatileImage#validate validate} + * method. + *
  • + * Image objects created by the Toolkit and Component classes which are + * loaded from files, URLs or produced by an {@link ImageProducer} + * are unloaded and all local resources are released. + * These objects can later be reloaded from their original source + * as needed when they are rendered, just as when they were first + * created. + *
+ */ + public void flush() { +// if (surfaceManager != null) { +// surfaceManager.flush(); +// } + } + + /** + * Returns an ImageCapabilities object which can be + * inquired as to the capabilities of this + * Image on the specified GraphicsConfiguration. + * This allows programmers to find + * out more runtime information on the specific Image + * object that they have created. For example, the user + * might create a BufferedImage but the system may have + * no video memory left for creating an image of that + * size on the given GraphicsConfiguration, so although the object + * may be acceleratable in general, it + * does not have that capability on this GraphicsConfiguration. + * @param gc a GraphicsConfiguration object. A value of null + * for this parameter will result in getting the image capabilities + * for the default GraphicsConfiguration. + * @return an ImageCapabilities object that contains + * the capabilities of this Image on the specified + * GraphicsConfiguration. + * @see java.awt.image.VolatileImage#getCapabilities() + * VolatileImage.getCapabilities() + * @since 1.5 + */ + public ImageCapabilities getCapabilities(GraphicsConfiguration gc) { +// if (surfaceManager != null) { +// return surfaceManager.getCapabilities(gc); +// } + // Note: this is just a default object that gets returned in the + // absence of any more specific information from a surfaceManager. + // Subclasses of Image should either override this method or + // make sure that they always have a non-null SurfaceManager + // to return an ImageCapabilities object that is appropriate + // for their given subclass type. + return defaultImageCaps; + } + + /** + * Sets a hint for this image about how important acceleration is. + * This priority hint is used to compare to the priorities of other + * Image objects when determining how to use scarce acceleration + * resources such as video memory. When and if it is possible to + * accelerate this Image, if there are not enough resources available + * to provide that acceleration but enough can be freed up by + * de-accelerating some other image of lower priority, then that other + * Image may be de-accelerated in deference to this one. Images + * that have the same priority take up resources on a first-come, + * first-served basis. + * @param priority a value between 0 and 1, inclusive, where higher + * values indicate more importance for acceleration. A value of 0 + * means that this Image should never be accelerated. Other values + * are used simply to determine acceleration priority relative to other + * Images. + * @throws IllegalArgumentException if priority is less + * than zero or greater than 1. + * @since 1.5 + */ + public void setAccelerationPriority(float priority) { + if (priority < 0 || priority > 1) { + throw new IllegalArgumentException("Priority must be a value " + + "between 0 and 1, inclusive"); + } + accelerationPriority = priority; +// if (surfaceManager != null) { +// surfaceManager.setAccelerationPriority(accelerationPriority); +// } + } + + /** + * Returns the current value of the acceleration priority hint. + * @see #setAccelerationPriority(float priority) setAccelerationPriority + * @return value between 0 and 1, inclusive, which represents the current + * priority value + * @since 1.5 + */ + public float getAccelerationPriority() { + return accelerationPriority; + } + +// SurfaceManager surfaceManager; +// +// static { +// SurfaceManager.setImageAccessor(new SurfaceManager.ImageAccessor() { +// public SurfaceManager getSurfaceManager(Image img) { +// return img.surfaceManager; +// } +// public void setSurfaceManager(Image img, SurfaceManager mgr) { +// img.surfaceManager = mgr; +// } +// }); +// } +} diff --git a/openjdk/java/awt/color/ICC_ColorSpace.java b/openjdk/java/awt/color/ICC_ColorSpace.java new file mode 100644 index 0000000..465d7dc --- /dev/null +++ b/openjdk/java/awt/color/ICC_ColorSpace.java @@ -0,0 +1,295 @@ +/* ICC_ColorSpace.java -- the canonical color space implementation + Copyright (C) 2000, 2002, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.color; + +import gnu.java.awt.color.CieXyzConverter; +import gnu.java.awt.color.ClutProfileConverter; +import gnu.java.awt.color.ColorSpaceConverter; +import gnu.java.awt.color.GrayProfileConverter; +import gnu.java.awt.color.GrayScaleConverter; +import gnu.java.awt.color.RgbProfileConverter; +import gnu.java.awt.color.SrgbConverter; + +import java.io.IOException; +import java.io.ObjectInputStream; + +/** + * ICC_ColorSpace - an implementation of ColorSpace + * + * While an ICC_Profile class abstracts the data in an ICC profile file + * an ICC_ColorSpace performs the color space conversions defined by + * an ICC_Profile instance. + * + * Typically, an ICC_Profile will either be created using getInstance, + * either from the built-in colorspaces, or from an ICC profile file. + * Then a ICC_Colorspace will be used to perform transforms from the + * device colorspace to and from the profile color space. + * + * The PCS used by ColorSpace is CIE XYZ relative a D50 white point. + * (Profiles using a CIE Lab PCS will have their input and output converted + * to D50 CIE XYZ accordingly. + * + * Note that a valid profile may not contain transforms in both directions, + * in which case the output may be undefined. + * All built-in colorspaces have bidirectional transforms, but developers + * using an ICC profile file may want to check the profile class using + * the ICC_Profile.getProfileClass() method. Input class profiles are + * guaranteed to have transforms to the PCS, output class profiles are + * guaranteed to have transforms from the PCS to device space. + * + * @author Sven de Marothy + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + * @since 1.2 + */ +public class ICC_ColorSpace extends ColorSpace +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = 3455889114070431483L; + + /** + * @serial + */ + private ICC_Profile thisProfile; + + /** + * @serial + */ + private float[] minVal; + + /** + * @serial + */ + private float[] maxVal; + + /** + * @serial + */ + private float[] diffMinMax; + + /** + * @serial + */ + private float[] invDiffMinMax; + + /** + * @serial + */ + private boolean needScaleInit; + + /** + * Tells us if the PCS is CIE LAB (must be CIEXYZ otherwise) + */ + private transient int type; + private transient int nComponents; + private transient ColorSpaceConverter converter; + + /** + * Constructs a new ICC_ColorSpace from an ICC_Profile object. + * + * @exception IllegalArgumentException If profile is inappropriate for + * representing a ColorSpace. + */ + public ICC_ColorSpace(ICC_Profile profile) + { + super(profile.getColorSpaceType(), profile.getNumComponents()); + + converter = getConverter(profile); + thisProfile = profile; + nComponents = profile.getNumComponents(); + type = profile.getColorSpaceType(); + makeArrays(); + } + + /** + * Return the profile + */ + public ICC_Profile getProfile() + { + return thisProfile; + } + + /** + * Transforms a color value assumed to be in this ColorSpace into a value in + * the default CS_sRGB color space. + * + * @exception ArrayIndexOutOfBoundsException If array length is not at least + * the number of components in this ColorSpace. + */ + public float[] toRGB(float[] colorvalue) + { + return converter.toRGB(colorvalue); + } + + /** + * Transforms a color value assumed to be in the default CS_sRGB color space + * into this ColorSpace. + * + * @exception ArrayIndexOutOfBoundsException If array length is not at + * least 3. + */ + public float[] fromRGB(float[] rgbvalue) + { + return converter.fromRGB(rgbvalue); + } + + /** + * Transforms a color value assumed to be in this ColorSpace into the + * CS_CIEXYZ conversion color space. + * + * @exception ArrayIndexOutOfBoundsException If array length is not at + * least the number of components in this ColorSpace. + */ + public float[] toCIEXYZ(float[] colorvalue) + { + return converter.toCIEXYZ(colorvalue); + } + + /** + * Transforms a color value assumed to be in the CS_CIEXYZ conversion color + * space into this ColorSpace. + * + * @exception ArrayIndexOutOfBoundsException If array length is not at + * least 3. + */ + public float[] fromCIEXYZ(float[] colorvalue) + { + return converter.fromCIEXYZ(colorvalue); + } + + /** + * Returns the minimum normalized color component value for the specified + * component. + * + * @exception IllegalArgumentException If component is less than 0 or greater + * than numComponents - 1. + * + * @since 1.4 + */ + public float getMinValue(int idx) + { + // FIXME: Not 100% certain of this. + if (type == ColorSpace.TYPE_Lab && (idx == 1 || idx == 2)) + return -128f; + + if (idx < 0 || idx >= nComponents) + throw new IllegalArgumentException(); + return 0; + } + + /** + * Returns the maximum normalized color component value for the specified + * component. + * + * @exception IllegalArgumentException If component is less than 0 or greater + * than numComponents - 1. + * + * @since 1.4 + */ + public float getMaxValue(int idx) + { + if (type == ColorSpace.TYPE_XYZ && idx >= 0 && idx <= 2) + return 1 + 32767 / 32768f; + else if (type == ColorSpace.TYPE_Lab) + { + if (idx == 0) + return 100; + if (idx == 1 || idx == 2) + return 127; + } + if (idx < 0 || idx >= nComponents) + throw new IllegalArgumentException(); + return 1; + } + + /** + * Returns a colorspace converter suitable for a given profile + */ + private ColorSpaceConverter getConverter(ICC_Profile profile) + { + ColorSpaceConverter converter; + switch (profile.getColorSpaceType()) + { + case TYPE_XYZ: + converter = new CieXyzConverter(); + break; + default: + if (profile instanceof ICC_ProfileRGB) + converter = new RgbProfileConverter((ICC_ProfileRGB) profile); + else if (profile instanceof ICC_ProfileGray) + converter = new GrayProfileConverter((ICC_ProfileGray) profile); + else + converter = new ClutProfileConverter(profile); + break; + } + return converter; + } + + /** + * Serialization compatibility requires these variable to be set, + * although we don't use them. Perhaps we should? + */ + private void makeArrays() + { + minVal = new float[nComponents]; + maxVal = new float[nComponents]; + + invDiffMinMax = diffMinMax = null; + for (int i = 0; i < nComponents; i++) + { + minVal[i] = getMinValue(i); + maxVal[i] = getMaxValue(i); + } + needScaleInit = true; + } + + /** + * Deserializes the object + */ + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException + { + s.defaultReadObject(); + // set up objects + converter = getConverter(thisProfile); + nComponents = thisProfile.getNumComponents(); + type = thisProfile.getColorSpaceType(); + } +} // class ICC_ColorSpace diff --git a/openjdk/java/awt/image/AffineTransformOp.java b/openjdk/java/awt/image/AffineTransformOp.java new file mode 100644 index 0000000..df9db7d --- /dev/null +++ b/openjdk/java/awt/image/AffineTransformOp.java @@ -0,0 +1,608 @@ +/* AffineTransformOp.java -- This class performs affine + transformation between two images or rasters in 2 dimensions. + Copyright (C) 2004, 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.image; + +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.geom.NoninvertibleTransformException; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.Arrays; + +/** + * AffineTransformOp performs matrix-based transformations (translations, + * scales, flips, rotations, and shears). + * + * If interpolation is required, nearest neighbour, bilinear, and bicubic + * methods are available. + * + * @author Olga Rodimina (rodimina@redhat.com) + * @author Francis Kung (fkung@redhat.com) + */ +public class AffineTransformOp implements BufferedImageOp, RasterOp +{ + public static final int TYPE_NEAREST_NEIGHBOR = 1; + + public static final int TYPE_BILINEAR = 2; + + /** + * @since 1.5.0 + */ + public static final int TYPE_BICUBIC = 3; + + private AffineTransform transform; + private RenderingHints hints; + + /** + * Construct AffineTransformOp with the given xform and interpolationType. + * Interpolation type can be TYPE_BILINEAR, TYPE_BICUBIC or + * TYPE_NEAREST_NEIGHBOR. + * + * @param xform AffineTransform that will applied to the source image + * @param interpolationType type of interpolation used + * @throws ImagingOpException if the transform matrix is noninvertible + */ + public AffineTransformOp (AffineTransform xform, int interpolationType) + { + this.transform = xform; + if (xform.getDeterminant() == 0) + throw new ImagingOpException(null); + + switch (interpolationType) + { + case TYPE_BILINEAR: + hints = new RenderingHints (RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_BILINEAR); + break; + case TYPE_BICUBIC: + hints = new RenderingHints (RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_BICUBIC); + break; + default: + hints = new RenderingHints (RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); + } + } + + /** + * Construct AffineTransformOp with the given xform and rendering hints. + * + * @param xform AffineTransform that will applied to the source image + * @param hints rendering hints that will be used during transformation + * @throws ImagingOpException if the transform matrix is noninvertible + */ + public AffineTransformOp (AffineTransform xform, RenderingHints hints) + { + this.transform = xform; + this.hints = hints; + if (xform.getDeterminant() == 0) + throw new ImagingOpException(null); + } + + /** + * Creates a new BufferedImage with the size equal to that of the + * transformed image and the correct number of bands. The newly created + * image is created with the specified ColorModel. + * If a ColorModel is not specified, an appropriate ColorModel is used. + * + * @param src the source image. + * @param destCM color model for the destination image (can be null). + * @return a new compatible destination image. + */ + public BufferedImage createCompatibleDestImage (BufferedImage src, + ColorModel destCM) + { + if (destCM != null) + return new BufferedImage(destCM, + createCompatibleDestRaster(src.getRaster()), + src.isAlphaPremultiplied(), null); + + // This behaviour was determined by Mauve testcases, and is compatible + // with the reference implementation + if (src.getType() == BufferedImage.TYPE_INT_ARGB_PRE + || src.getType() == BufferedImage.TYPE_4BYTE_ABGR + || src.getType() == BufferedImage.TYPE_4BYTE_ABGR_PRE) + return new BufferedImage(src.getWidth(), src.getHeight(), src.getType()); + + else + return new BufferedImage(src.getWidth(), src.getHeight(), + BufferedImage.TYPE_INT_ARGB); + } + + /** + * Creates a new WritableRaster with the size equal to the transformed + * source raster and correct number of bands . + * + * @param src the source raster. + * @throws RasterFormatException if resulting width or height of raster is 0. + * @return a new compatible raster. + */ + public WritableRaster createCompatibleDestRaster (Raster src) + { + Rectangle2D rect = getBounds2D(src); + + if (rect.getWidth() == 0 || rect.getHeight() == 0) + throw new RasterFormatException("width or height is 0"); + + return src.createCompatibleWritableRaster((int) rect.getWidth(), + (int) rect.getHeight()); + } + + /** + * Transforms source image using transform specified at the constructor. + * The resulting transformed image is stored in the destination image if one + * is provided; otherwise a new BufferedImage is created and returned. + * + * @param src source image + * @param dst destination image + * @throws IllegalArgumentException if the source and destination image are + * the same + * @return transformed source image. + */ + public final BufferedImage filter (BufferedImage src, BufferedImage dst) + { + if (dst == src) + throw new IllegalArgumentException("src image cannot be the same as " + + "the dst image"); + + // If the destination image is null, then use a compatible BufferedImage + if (dst == null) + dst = createCompatibleDestImage(src, null); + + Graphics2D gr = dst.createGraphics(); + gr.setRenderingHints(hints); + gr.drawImage(src, transform, null); + return dst; + } + + /** + * Transforms source raster using transform specified at the constructor. + * The resulting raster is stored in the destination raster if it is not + * null, otherwise a new raster is created and returned. + * + * @param src source raster + * @param dst destination raster + * @throws IllegalArgumentException if the source and destination are not + * compatible + * @return transformed raster. + */ + public final WritableRaster filter(Raster src, WritableRaster dst) + { + // Initial checks + if (dst == src) + throw new IllegalArgumentException("src image cannot be the same as" + + " the dst image"); + + if (dst == null) + dst = createCompatibleDestRaster(src); + + if (src.getNumBands() != dst.getNumBands()) + throw new IllegalArgumentException("src and dst must have same number" + + " of bands"); + + // Optimization for rasters that can be represented in the RGB colormodel: + // wrap the rasters in images, and let Cairo do the transformation + if (ColorModel.getRGBdefault().isCompatibleSampleModel(src.getSampleModel()) + && ColorModel.getRGBdefault().isCompatibleSampleModel(dst.getSampleModel())) + { + WritableRaster src2 = Raster.createWritableRaster(src.getSampleModel(), + src.getDataBuffer(), + new Point(src.getMinX(), + src.getMinY())); + BufferedImage iSrc = new BufferedImage(ColorModel.getRGBdefault(), + src2, false, null); + BufferedImage iDst = new BufferedImage(ColorModel.getRGBdefault(), dst, + false, null); + + return filter(iSrc, iDst).getRaster(); + } + + // Otherwise, we need to do the transformation in java code... + // Create arrays to hold all the points + double[] dstPts = new double[dst.getHeight() * dst.getWidth() * 2]; + double[] srcPts = new double[dst.getHeight() * dst.getWidth() * 2]; + + // Populate array with all points in the *destination* raster + int i = 0; + for (int x = 0; x < dst.getWidth(); x++) + { + for (int y = 0; y < dst.getHeight(); y++) + { + dstPts[i++] = x; + dstPts[i++] = y; + } + } + Rectangle srcbounds = src.getBounds(); + + // Use an inverse transform to map each point in the destination to + // a point in the source. Note that, while all points in the destination + // matrix are integers, this is not necessarily true for points in the + // source (hence why interpolation is required) + try + { + AffineTransform inverseTx = transform.createInverse(); + inverseTx.transform(dstPts, 0, srcPts, 0, dstPts.length / 2); + } + catch (NoninvertibleTransformException e) + { + // Shouldn't happen since the constructor traps this + throw new ImagingOpException(e.getMessage()); + } + + // Different interpolation methods... + if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR)) + filterNearest(src, dst, dstPts, srcPts); + + else if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BILINEAR)) + filterBilinear(src, dst, dstPts, srcPts); + + else // bicubic + filterBicubic(src, dst, dstPts, srcPts); + + return dst; + } + + /** + * Transforms source image using transform specified at the constructor and + * returns bounds of the transformed image. + * + * @param src image to be transformed + * @return bounds of the transformed image. + */ + public final Rectangle2D getBounds2D (BufferedImage src) + { + return getBounds2D (src.getRaster()); + } + + /** + * Returns bounds of the transformed raster. + * + * @param src raster to be transformed + * @return bounds of the transformed raster. + */ + public final Rectangle2D getBounds2D (Raster src) + { + return transform.createTransformedShape(src.getBounds()).getBounds2D(); + } + + /** + * Returns interpolation type used during transformations. + * + * @return interpolation type + */ + public final int getInterpolationType () + { + if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BILINEAR)) + return TYPE_BILINEAR; + + else if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BICUBIC)) + return TYPE_BICUBIC; + + else + return TYPE_NEAREST_NEIGHBOR; + } + + /** + * Returns location of the transformed source point. The resulting point + * is stored in the dstPt if one is specified. + * + * @param srcPt point to be transformed + * @param dstPt destination point + * @return the location of the transformed source point. + */ + public final Point2D getPoint2D (Point2D srcPt, Point2D dstPt) + { + return transform.transform (srcPt, dstPt); + } + + /** + * Returns rendering hints that are used during transformation. + * + * @return the rendering hints used in this Op. + */ + public final RenderingHints getRenderingHints () + { + return hints; + } + + /** + * Returns transform used in transformation between source and destination + * image. + * + * @return the transform used in this Op. + */ + public final AffineTransform getTransform () + { + return transform; + } + + /** + * Perform nearest-neighbour filtering + * + * @param src the source raster + * @param dst the destination raster + * @param dpts array of points on the destination raster + * @param pts array of corresponding points on the source raster + */ + private void filterNearest(Raster src, WritableRaster dst, double[] dpts, + double[] pts) + { + Rectangle srcbounds = src.getBounds(); + + // For all points on the destination raster, copy the value from the + // corrosponding (rounded) source point + for (int i = 0; i < dpts.length; i += 2) + { + int srcX = (int) Math.round(pts[i]) + src.getMinX(); + int srcY = (int) Math.round(pts[i + 1]) + src.getMinY(); + + if (srcbounds.contains(srcX, srcY)) + dst.setDataElements((int) dpts[i] + dst.getMinX(), + (int) dpts[i + 1] + dst.getMinY(), + src.getDataElements(srcX, srcY, null)); + } + } + + /** + * Perform bilinear filtering + * + * @param src the source raster + * @param dst the destination raster + * @param dpts array of points on the destination raster + * @param pts array of corresponding points on the source raster + */ + private void filterBilinear(Raster src, WritableRaster dst, double[] dpts, + double[] pts) + { + Rectangle srcbounds = src.getBounds(); + + Object xyarr = null; + Object xp1arr = null; + Object yp1arr = null; + Object xyp1arr = null; + + double xy; + double xp1; + double yp1; + double xyp1; + + double[] result = new double[src.getNumBands()]; + + // For all points in the destination raster, use bilinear interpolation + // to find the value from the corrosponding source points + for (int i = 0; i < dpts.length; i += 2) + { + int srcX = (int) Math.round(pts[i]) + src.getMinX(); + int srcY = (int) Math.round(pts[i + 1]) + src.getMinY(); + + if (srcbounds.contains(srcX, srcY)) + { + // Corner case at the bottom or right edge; use nearest neighbour + if (pts[i] >= src.getWidth() - 1 + || pts[i + 1] >= src.getHeight() - 1) + dst.setDataElements((int) dpts[i] + dst.getMinX(), + (int) dpts[i + 1] + dst.getMinY(), + src.getDataElements(srcX, srcY, null)); + + // Standard case, apply the bilinear formula + else + { + int x = (int) Math.floor(pts[i] + src.getMinX()); + int y = (int) Math.floor(pts[i + 1] + src.getMinY()); + double xdiff = pts[i] + src.getMinX() - x; + double ydiff = pts[i + 1] + src.getMinY() - y; + + // Get surrounding pixels used in interpolation... optimized + // to use the smallest datatype possible. + if (src.getTransferType() == DataBuffer.TYPE_DOUBLE + || src.getTransferType() == DataBuffer.TYPE_FLOAT) + { + xyarr = src.getPixel(x, y, (double[])xyarr); + xp1arr = src.getPixel(x+1, y, (double[])xp1arr); + yp1arr = src.getPixel(x, y+1, (double[])yp1arr); + xyp1arr = src.getPixel(x+1, y+1, (double[])xyp1arr); + } + else + { + xyarr = src.getPixel(x, y, (int[])xyarr); + xp1arr = src.getPixel(x+1, y, (int[])xp1arr); + yp1arr = src.getPixel(x, y+1, (int[])yp1arr); + xyp1arr = src.getPixel(x+1, y+1, (int[])xyp1arr); + } + // using + // array[] pixels = src.getPixels(x, y, 2, 2, pixels); + // instead of doing four individual src.getPixel() calls + // should be faster, but benchmarking shows that it's not... + + // Run interpolation for each band + for (int j = 0; j < src.getNumBands(); j++) + { + // Pull individual sample values out of array + if (src.getTransferType() == DataBuffer.TYPE_DOUBLE + || src.getTransferType() == DataBuffer.TYPE_FLOAT) + { + xy = ((double[])xyarr)[j]; + xp1 = ((double[])xp1arr)[j]; + yp1 = ((double[])yp1arr)[j]; + xyp1 = ((double[])xyp1arr)[j]; + } + else + { + xy = ((int[])xyarr)[j]; + xp1 = ((int[])xp1arr)[j]; + yp1 = ((int[])yp1arr)[j]; + xyp1 = ((int[])xyp1arr)[j]; + } + + // If all four samples are identical, there's no need to + // calculate anything + if (xy == xp1 && xy == yp1 && xy == xyp1) + result[j] = xy; + + // Run bilinear interpolation formula + else + result[j] = (xy * (1-xdiff) + xp1 * xdiff) + * (1-ydiff) + + (yp1 * (1-xdiff) + xyp1 * xdiff) + * ydiff; + } + + dst.setPixel((int)dpts[i] + dst.getMinX(), + (int)dpts[i+1] + dst.getMinY(), + result); + } + } + } + } + + /** + * Perform bicubic filtering + * based on http://local.wasp.uwa.edu.au/~pbourke/colour/bicubic/ + * + * @param src the source raster + * @param dst the destination raster + * @param dpts array of points on the destination raster + * @param pts array of corresponding points on the source raster + */ + private void filterBicubic(Raster src, WritableRaster dst, double[] dpts, + double[] pts) + { + Rectangle srcbounds = src.getBounds(); + double[] result = new double[src.getNumBands()]; + Object pixels = null; + + // For all points on the destination raster, perform bicubic interpolation + // from corrosponding source points + for (int i = 0; i < dpts.length; i += 2) + { + if (srcbounds.contains((int) Math.round(pts[i]) + src.getMinX(), + (int) Math.round(pts[i + 1]) + src.getMinY())) + { + int x = (int) Math.floor(pts[i] + src.getMinX()); + int y = (int) Math.floor(pts[i + 1] + src.getMinY()); + double dx = pts[i] + src.getMinX() - x; + double dy = pts[i + 1] + src.getMinY() - y; + Arrays.fill(result, 0); + + for (int m = - 1; m < 3; m++) + for (int n = - 1; n < 3; n++) + { + // R(x) = ( P(x+2)^3 - 4 P(x+1)^3 + 6 P(x)^3 - 4 P(x-1)^3 ) / 6 + double r1 = 0; + double r2 = 0; + + // Calculate R(m - dx) + double rx = m - dx + 2; + r1 += rx * rx * rx; + + rx = m - dx + 1; + if (rx > 0) + r1 -= 4 * rx * rx * rx; + + rx = m - dx; + if (rx > 0) + r1 += 6 * rx * rx * rx; + + rx = m - dx - 1; + if (rx > 0) + r1 -= 4 * rx * rx * rx; + + r1 /= 6; + + // Calculate R(dy - n); + rx = dy - n + 2; + if (rx > 0) + r2 += rx * rx * rx; + + rx = dy - n + 1; + if (rx > 0) + r2 -= 4 * rx * rx * rx; + + rx = dy - n; + if (rx > 0) + r2 += 6 * rx * rx * rx; + + rx = dy - n - 1; + if (rx > 0) + r2 -= 4 * rx * rx * rx; + + r2 /= 6; + + // Calculate F(i+m, j+n) R(m - dx) R(dy - n) + // Check corner cases + int srcX = x + m; + if (srcX >= src.getMinX() + src.getWidth()) + srcX = src.getMinX() + src.getWidth() - 1; + else if (srcX < src.getMinX()) + srcX = src.getMinX(); + + int srcY = y + n; + if (srcY >= src.getMinY() + src.getHeight()) + srcY = src.getMinY() + src.getHeight() - 1; + else if (srcY < src.getMinY()) + srcY = src.getMinY(); + + // Calculate once for each band, using the smallest + // datatype possible + if (src.getTransferType() == DataBuffer.TYPE_DOUBLE + || src.getTransferType() == DataBuffer.TYPE_FLOAT) + { + pixels = src.getPixel(srcX, srcY, (double[])pixels); + for (int j = 0; j < result.length; j++) + result[j] += ((double[])pixels)[j] * r1 * r2; + } + else + { + pixels = src.getPixel(srcX, srcY, (int[])pixels); + for (int j = 0; j < result.length; j++) + result[j] += ((int[])pixels)[j] * r1 * r2; + } + } + + // Put it all together + dst.setPixel((int)dpts[i] + dst.getMinX(), + (int)dpts[i+1] + dst.getMinY(), + result); + } + } + } +} diff --git a/openjdk/java/awt/image/BandCombineOp.java b/openjdk/java/awt/image/BandCombineOp.java new file mode 100644 index 0000000..d9ce16f --- /dev/null +++ b/openjdk/java/awt/image/BandCombineOp.java @@ -0,0 +1,218 @@ +/* BandCombineOp.java - perform a combination on the bands of a raster + Copyright (C) 2004, 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.image; + +import java.awt.RenderingHints; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.Arrays; + +/** + * Filter Raster pixels by applying a matrix. + * + * BandCombineOp applies a matrix to each pixel to produce new pixel values. + * The width of the matrix must be the same or one more than the number of + * bands in the source Raster. If one more, the pixels in the source are + * assumed to contain an implicit 1.0 at the end. + * + * The rows of the matrix are multiplied by the pixel to produce the values + * for the destination. Therefore the destination Raster must contain the + * same number of bands as the number of rows in the filter matrix. + * + * This Op assumes that samples are integers; floating point sample types will + * be rounded to their nearest integer value during filtering. + * + * @author Jerry Quinn (jlquinn@optonline.net) + */ +public class BandCombineOp implements RasterOp +{ + private RenderingHints hints; + private float[][] matrix; + + /** + * Construct a BandCombineOp. + * + * @param matrix The matrix to filter pixels with. + * @param hints Rendering hints to apply. Ignored. + * @throws ArrayIndexOutOfBoundsException if the matrix is invalid + */ + public BandCombineOp(float[][] matrix, RenderingHints hints) + { + this.matrix = new float[matrix.length][]; + int width = matrix[0].length; + for (int i = 0; i < matrix.length; i++) + { + this.matrix[i] = new float[width + 1]; + for (int j = 0; j < width; j++) + this.matrix[i][j] = matrix[i][j]; + + // The reference implementation pads the array with a trailing zero... + this.matrix[i][width] = 0; + } + + this.hints = hints; + } + + /** + * Filter Raster pixels through a matrix. Applies the Op matrix to source + * pixes to produce dest pixels. Each row of the matrix is multiplied by the + * src pixel components to produce the dest pixel. If matrix is one more than + * the number of bands in the src, the last element is implicitly multiplied + * by 1, i.e. added to the sum for that dest component. If dest is null, a + * suitable Raster is created. This implementation uses + * createCompatibleDestRaster. + * + * @param src The source Raster. + * @param dest The destination Raster, or null. + * @throws IllegalArgumentException if the destination raster is incompatible + * with the source raster. + * @return The filtered Raster. + * @see java.awt.image.RasterOp#filter(java.awt.image.Raster, + * java.awt.image.WritableRaster) + */ + public WritableRaster filter(Raster src, WritableRaster dest) { + if (dest == null) + dest = createCompatibleDestRaster(src); + else if (dest.getNumBands() != src.getNumBands() + || dest.getTransferType() != src.getTransferType()) + throw new IllegalArgumentException("Destination raster is incompatible with source raster"); + + // Filter the pixels + int[] spix = new int[matrix[0].length - 1]; + int[] spix2 = new int[matrix[0].length - 1]; + int[] dpix = new int[matrix.length]; + for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++) + for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++) + { + // In case matrix rows have implicit translation + spix[spix.length - 1] = 1; + src.getPixel(x, y, spix); + + // Do not re-calculate if pixel is identical to the last one + // (ie, blocks of the same colour) + if (!Arrays.equals(spix, spix2)) + { + System.arraycopy(spix, 0, spix2, 0, spix.length); + for (int i = 0; i < matrix.length; i++) + { + dpix[i] = 0; + for (int j = 0; j < matrix[0].length - 1; j++) + dpix[i] += spix[j] * (int)matrix[i][j]; + } + } + dest.setPixel(x, y, dpix); + } + + return dest; + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster) + */ + public final Rectangle2D getBounds2D(Raster src) + { + return src.getBounds(); + } + + /** + * Creates a new WritableRaster that can be used as the destination for this + * Op. The number of bands in the source raster must equal the number of rows + * in the op matrix, which must also be equal to either the number of columns + * or (columns - 1) in the matrix. + * + * @param src The source raster. + * @return A compatible raster. + * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster) + * @throws IllegalArgumentException if the raster is incompatible with the + * matrix. + */ + public WritableRaster createCompatibleDestRaster(Raster src) + { + // Destination raster must have same number of bands as source + if (src.getNumBands() != matrix.length) + throw new IllegalArgumentException("Number of rows in matrix specifies an " + + "incompatible number of bands"); + + // We use -1 and -2 because we previously padded the rows with a trailing 0 + if (src.getNumBands() != matrix[0].length - 1 + && src.getNumBands() != matrix[0].length - 2) + throw new IllegalArgumentException("Incompatible number of bands: " + + "the number of bands in the raster must equal the number of " + + "columns in the matrix, optionally minus one"); + + return src.createCompatibleWritableRaster(); + } + + /** + * Return corresponding destination point for source point. Because this is + * not a geometric operation, it simply returns a copy of the source. + * + * @param src The source point. + * @param dst The destination point. + * @return dst The destination point. + * @see java.awt.image.RasterOp#getPoint2D(java.awt.geom.Point2D, + *java.awt.geom.Point2D) + */ + public final Point2D getPoint2D(Point2D src, Point2D dst) + { + if (dst == null) + return (Point2D)src.clone(); + + dst.setLocation(src); + return dst; + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#getRenderingHints() + */ + public final RenderingHints getRenderingHints() + { + return hints; + } + + /** + * Return the matrix used in this operation. + * + * @return The matrix used in this operation. + */ + public final float[][] getMatrix() + { + return matrix; + } + +} diff --git a/openjdk/java/awt/image/BufferedImage.java b/openjdk/java/awt/image/BufferedImage.java new file mode 100644 index 0000000..91be2dc --- /dev/null +++ b/openjdk/java/awt/image/BufferedImage.java @@ -0,0 +1,1811 @@ +/* + * Copyright (c) 1997, 2013, 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 java.awt.image; + +import cli.System.Drawing.Color; +import cli.System.Drawing.Imaging.*; + +import java.awt.Transparency; +import java.awt.color.ColorSpace; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsEnvironment; +import java.awt.ImageCapabilities; +import java.awt.geom.Rectangle2D; +import java.awt.geom.Point2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Hashtable; +import java.util.Vector; + +import sun.awt.image.BytePackedRaster; +import sun.awt.image.ShortComponentRaster; +import sun.awt.image.ByteComponentRaster; +import sun.awt.image.IntegerComponentRaster; +import sun.awt.image.OffScreenImageSource; + +/** + * + * The BufferedImage subclass describes an {@link + * java.awt.Image Image} with an accessible buffer of image data. + * A BufferedImage is comprised of a {@link ColorModel} and a + * {@link Raster} of image data. + * The number and types of bands in the {@link SampleModel} of the + * Raster must match the number and types required by the + * ColorModel to represent its color and alpha components. + * All BufferedImage objects have an upper left corner + * coordinate of (0, 0). Any Raster used to construct a + * BufferedImage must therefore have minX=0 and minY=0. + * + *

+ * This class relies on the data fetching and setting methods + * of Raster, + * and on the color characterization methods of ColorModel. + * + * @see ColorModel + * @see Raster + * @see WritableRaster + */ + +public class BufferedImage extends java.awt.Image + implements WritableRenderedImage, Transparency +{ + int imageType = TYPE_CUSTOM; + ColorModel colorModel; + WritableRaster raster; + OffScreenImageSource osis; + Hashtable properties; + + boolean isAlphaPremultiplied;// If true, alpha has been premultiplied in + // color channels + + /** + * Image Type Constants + */ + + /** + * Image type is not recognized so it must be a customized + * image. This type is only used as a return value for the getType() + * method. + */ + public static final int TYPE_CUSTOM = 0; + + /** + * Represents an image with 8-bit RGB color components packed into + * integer pixels. The image has a {@link DirectColorModel} without + * alpha. + * When data with non-opaque alpha is stored + * in an image of this type, + * the color data must be adjusted to a non-premultiplied form + * and the alpha discarded, + * as described in the + * {@link java.awt.AlphaComposite} documentation. + */ + public static final int TYPE_INT_RGB = 1; + + /** + * Represents an image with 8-bit RGBA color components packed into + * integer pixels. The image has a DirectColorModel + * with alpha. The color data in this image is considered not to be + * premultiplied with alpha. When this type is used as the + * imageType argument to a BufferedImage + * constructor, the created image is consistent with images + * created in the JDK1.1 and earlier releases. + */ + public static final int TYPE_INT_ARGB = 2; + + /** + * Represents an image with 8-bit RGBA color components packed into + * integer pixels. The image has a DirectColorModel + * with alpha. The color data in this image is considered to be + * premultiplied with alpha. + */ + public static final int TYPE_INT_ARGB_PRE = 3; + + /** + * Represents an image with 8-bit RGB color components, corresponding + * to a Windows- or Solaris- style BGR color model, with the colors + * Blue, Green, and Red packed into integer pixels. There is no alpha. + * The image has a {@link DirectColorModel}. + * When data with non-opaque alpha is stored + * in an image of this type, + * the color data must be adjusted to a non-premultiplied form + * and the alpha discarded, + * as described in the + * {@link java.awt.AlphaComposite} documentation. + */ + public static final int TYPE_INT_BGR = 4; + + /** + * Represents an image with 8-bit RGB color components, corresponding + * to a Windows-style BGR color model) with the colors Blue, Green, + * and Red stored in 3 bytes. There is no alpha. The image has a + * ComponentColorModel. + * When data with non-opaque alpha is stored + * in an image of this type, + * the color data must be adjusted to a non-premultiplied form + * and the alpha discarded, + * as described in the + * {@link java.awt.AlphaComposite} documentation. + */ + public static final int TYPE_3BYTE_BGR = 5; + + /** + * Represents an image with 8-bit RGBA color components with the colors + * Blue, Green, and Red stored in 3 bytes and 1 byte of alpha. The + * image has a ComponentColorModel with alpha. The + * color data in this image is considered not to be premultiplied with + * alpha. The byte data is interleaved in a single + * byte array in the order A, B, G, R + * from lower to higher byte addresses within each pixel. + */ + public static final int TYPE_4BYTE_ABGR = 6; + + /** + * Represents an image with 8-bit RGBA color components with the colors + * Blue, Green, and Red stored in 3 bytes and 1 byte of alpha. The + * image has a ComponentColorModel with alpha. The color + * data in this image is considered to be premultiplied with alpha. + * The byte data is interleaved in a single byte array in the order + * A, B, G, R from lower to higher byte addresses within each pixel. + */ + public static final int TYPE_4BYTE_ABGR_PRE = 7; + + /** + * Represents an image with 5-6-5 RGB color components (5-bits red, + * 6-bits green, 5-bits blue) with no alpha. This image has + * a DirectColorModel. + * When data with non-opaque alpha is stored + * in an image of this type, + * the color data must be adjusted to a non-premultiplied form + * and the alpha discarded, + * as described in the + * {@link java.awt.AlphaComposite} documentation. + */ + public static final int TYPE_USHORT_565_RGB = 8; + + /** + * Represents an image with 5-5-5 RGB color components (5-bits red, + * 5-bits green, 5-bits blue) with no alpha. This image has + * a DirectColorModel. + * When data with non-opaque alpha is stored + * in an image of this type, + * the color data must be adjusted to a non-premultiplied form + * and the alpha discarded, + * as described in the + * {@link java.awt.AlphaComposite} documentation. + */ + public static final int TYPE_USHORT_555_RGB = 9; + + /** + * Represents a unsigned byte grayscale image, non-indexed. This + * image has a ComponentColorModel with a CS_GRAY + * {@link ColorSpace}. + * When data with non-opaque alpha is stored + * in an image of this type, + * the color data must be adjusted to a non-premultiplied form + * and the alpha discarded, + * as described in the + * {@link java.awt.AlphaComposite} documentation. + */ + public static final int TYPE_BYTE_GRAY = 10; + + /** + * Represents an unsigned short grayscale image, non-indexed). This + * image has a ComponentColorModel with a CS_GRAY + * ColorSpace. + * When data with non-opaque alpha is stored + * in an image of this type, + * the color data must be adjusted to a non-premultiplied form + * and the alpha discarded, + * as described in the + * {@link java.awt.AlphaComposite} documentation. + */ + public static final int TYPE_USHORT_GRAY = 11; + + /** + * Represents an opaque byte-packed 1, 2, or 4 bit image. The + * image has an {@link IndexColorModel} without alpha. When this + * type is used as the imageType argument to the + * BufferedImage constructor that takes an + * imageType argument but no ColorModel + * argument, a 1-bit image is created with an + * IndexColorModel with two colors in the default + * sRGB ColorSpace: {0, 0, 0} and + * {255, 255, 255}. + * + *

Images with 2 or 4 bits per pixel may be constructed via + * the BufferedImage constructor that takes a + * ColorModel argument by supplying a + * ColorModel with an appropriate map size. + * + *

Images with 8 bits per pixel should use the image types + * TYPE_BYTE_INDEXED or TYPE_BYTE_GRAY + * depending on their ColorModel. + + *

When color data is stored in an image of this type, + * the closest color in the colormap is determined + * by the IndexColorModel and the resulting index is stored. + * Approximation and loss of alpha or color components + * can result, depending on the colors in the + * IndexColorModel colormap. + */ + public static final int TYPE_BYTE_BINARY = 12; + + /** + * Represents an indexed byte image. When this type is used as the + * imageType argument to the BufferedImage + * constructor that takes an imageType argument + * but no ColorModel argument, an + * IndexColorModel is created with + * a 256-color 6/6/6 color cube palette with the rest of the colors + * from 216-255 populated by grayscale values in the + * default sRGB ColorSpace. + * + *

When color data is stored in an image of this type, + * the closest color in the colormap is determined + * by the IndexColorModel and the resulting index is stored. + * Approximation and loss of alpha or color components + * can result, depending on the colors in the + * IndexColorModel colormap. + */ + public static final int TYPE_BYTE_INDEXED = 13; + + private static final int DCM_RED_MASK = 0x00ff0000; + private static final int DCM_GREEN_MASK = 0x0000ff00; + private static final int DCM_BLUE_MASK = 0x000000ff; + private static final int DCM_ALPHA_MASK = 0xff000000; + private static final int DCM_565_RED_MASK = 0xf800; + private static final int DCM_565_GRN_MASK = 0x07E0; + private static final int DCM_565_BLU_MASK = 0x001F; + private static final int DCM_555_RED_MASK = 0x7C00; + private static final int DCM_555_GRN_MASK = 0x03E0; + private static final int DCM_555_BLU_MASK = 0x001F; + private static final int DCM_BGR_RED_MASK = 0x0000ff; + private static final int DCM_BGR_GRN_MASK = 0x00ff00; + private static final int DCM_BGR_BLU_MASK = 0xff0000; + + /** reference to the :NET equivalent */ + private cli.System.Drawing.Bitmap bitmap; + + /** Which buffer include the current data, raster or bitmap */ + private int currentBuffer; + + private static final int BUFFER_BITMAP = 1; + private static final int BUFFER_RASTER = 2; + private static final int BUFFER_BOTH = 3; + + /** + * Create a BufferedImage directly from the .NET Bitmap class + */ + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + public BufferedImage(cli.System.Drawing.Bitmap bitmap){ + this.imageType = TYPE_INT_ARGB; + this.colorModel = createColorModel(); + this.bitmap = bitmap; + this.currentBuffer = BUFFER_BITMAP; + } + + /** + * Constructs a BufferedImage of one of the predefined + * image types. The ColorSpace for the image is the + * default sRGB space. + * @param width width of the created image + * @param height height of the created image + * @param imageType type of the created image + * @see ColorSpace + * @see #TYPE_INT_RGB + * @see #TYPE_INT_ARGB + * @see #TYPE_INT_ARGB_PRE + * @see #TYPE_INT_BGR + * @see #TYPE_3BYTE_BGR + * @see #TYPE_4BYTE_ABGR + * @see #TYPE_4BYTE_ABGR_PRE + * @see #TYPE_BYTE_GRAY + * @see #TYPE_USHORT_GRAY + * @see #TYPE_BYTE_BINARY + * @see #TYPE_BYTE_INDEXED + * @see #TYPE_USHORT_565_RGB + * @see #TYPE_USHORT_555_RGB + */ + public BufferedImage(int width, + int height, + int imageType) { + this.imageType = imageType; + this.colorModel = createColorModel(); + this.bitmap = createBitmap(width, height); + this.currentBuffer = BUFFER_BITMAP; + } + + /** + * Create a Bitmap if not already one exists + * @param width width of the created image + * @param height height of the created image + * @return a Bitmap object, never null + */ + private cli.System.Drawing.Bitmap createBitmap(int width, int height){ + if(bitmap != null){ + return bitmap; + } + if(width <= 0 || height <= 0){ + throw new IllegalArgumentException("Width (" + width + ") and height (" + height + ") cannot be <= 0"); + } + return new cli.System.Drawing.Bitmap(width, height, PixelFormat.wrap(PixelFormat.Format32bppArgb)); + } + + /** + * Constructs a BufferedImage of one of the predefined + * image types: + * TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED. + * + *

If the image type is TYPE_BYTE_BINARY, the number of + * entries in the color model is used to determine whether the + * image should have 1, 2, or 4 bits per pixel. If the color model + * has 1 or 2 entries, the image will have 1 bit per pixel. If it + * has 3 or 4 entries, the image with have 2 bits per pixel. If + * it has between 5 and 16 entries, the image will have 4 bits per + * pixel. Otherwise, an IllegalArgumentException will be thrown. + * + * @param width width of the created image + * @param height height of the created image + * @param imageType type of the created image + * @param cm IndexColorModel of the created image + * @throws IllegalArgumentException if the imageType is not + * TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED or if the imageType is + * TYPE_BYTE_BINARY and the color map has more than 16 entries. + * @see #TYPE_BYTE_BINARY + * @see #TYPE_BYTE_INDEXED + */ + public BufferedImage (int width, + int height, + int imageType, + IndexColorModel cm) { + if (cm.hasAlpha() && cm.isAlphaPremultiplied()) { + throw new IllegalArgumentException("This image types do not have "+ + "premultiplied alpha."); + } + + switch(imageType) { + case TYPE_BYTE_BINARY: + int bits; // Will be set below + int mapSize = cm.getMapSize(); + if (mapSize <= 2) { + bits = 1; + } else if (mapSize <= 4) { + bits = 2; + } else if (mapSize <= 16) { + bits = 4; + } else { + throw new IllegalArgumentException + ("Color map for TYPE_BYTE_BINARY " + + "must have no more than 16 entries"); + } + raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE, + width, height, 1, bits, null); + break; + + case TYPE_BYTE_INDEXED: + raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, + width, height, 1, null); + break; + default: + throw new IllegalArgumentException("Invalid image type (" + + imageType+"). Image type must"+ + " be either TYPE_BYTE_BINARY or "+ + " TYPE_BYTE_INDEXED"); + } + + if (!cm.isCompatibleRaster(raster)) { + throw new IllegalArgumentException("Incompatible image type and IndexColorModel"); + } + + colorModel = cm; + this.imageType = imageType; + this.currentBuffer = BUFFER_RASTER; + raster.getDataBuffer().setImage( this ); + } + + /** + * Constructs a new BufferedImage with a specified + * ColorModel and Raster. If the number and + * types of bands in the SampleModel of the + * Raster do not match the number and types required by + * the ColorModel to represent its color and alpha + * components, a {@link RasterFormatException} is thrown. This + * method can multiply or divide the color Raster data by + * alpha to match the alphaPremultiplied state + * in the ColorModel. Properties for this + * BufferedImage can be established by passing + * in a {@link Hashtable} of String/Object + * pairs. + * @param cm ColorModel for the new image + * @param raster Raster for the image data + * @param isRasterPremultiplied if true, the data in + * the raster has been premultiplied with alpha. + * @param properties Hashtable of + * String/Object pairs. + * @exception RasterFormatException if the number and + * types of bands in the SampleModel of the + * Raster do not match the number and types required by + * the ColorModel to represent its color and alpha + * components. + * @exception IllegalArgumentException if + * raster is incompatible with cm + * @see ColorModel + * @see Raster + * @see WritableRaster + */ + + +/* + * + * FOR NOW THE CODE WHICH DEFINES THE RASTER TYPE IS DUPLICATED BY DVF + * SEE THE METHOD DEFINERASTERTYPE @ RASTEROUTPUTMANAGER + * + */ + public BufferedImage (ColorModel cm, + WritableRaster raster, + boolean isRasterPremultiplied, + Hashtable properties) { + + if (!cm.isCompatibleRaster(raster)) { + throw new + IllegalArgumentException("Raster "+raster+ + " is incompatible with ColorModel "+ + cm); + } + + if ((raster.minX != 0) || (raster.minY != 0)) { + throw new + IllegalArgumentException("Raster "+raster+ + " has minX or minY not equal to zero: " + + raster.minX + " " + raster.minY); + } + + colorModel = cm; + this.raster = raster; + raster.getDataBuffer().setImage( this ); + this.currentBuffer = BUFFER_RASTER; + this.properties = properties; + int numBands = raster.getNumBands(); + boolean isAlphaPre = cm.isAlphaPremultiplied(); + final boolean isStandard = isStandard(cm, raster); + ColorSpace cs; + + // Force the raster data alpha state to match the premultiplied + // state in the color model + coerceData(isRasterPremultiplied); + + SampleModel sm = raster.getSampleModel(); + cs = cm.getColorSpace(); + int csType = cs.getType(); + if (csType != ColorSpace.TYPE_RGB) { + if (csType == ColorSpace.TYPE_GRAY && + isStandard && + cm instanceof ComponentColorModel) { + // Check if this might be a child raster (fix for bug 4240596) + if (sm instanceof ComponentSampleModel && + ((ComponentSampleModel)sm).getPixelStride() != numBands) { + imageType = TYPE_CUSTOM; + } else if (raster instanceof ByteComponentRaster && + raster.getNumBands() == 1 && + cm.getComponentSize(0) == 8 && + ((ByteComponentRaster)raster).getPixelStride() == 1) { + imageType = TYPE_BYTE_GRAY; + } else if (raster instanceof ShortComponentRaster && + raster.getNumBands() == 1 && + cm.getComponentSize(0) == 16 && + ((ShortComponentRaster)raster).getPixelStride() == 1) { + imageType = TYPE_USHORT_GRAY; + } + } else { + imageType = TYPE_CUSTOM; + } + return; + } + + if ((raster instanceof IntegerComponentRaster) && + (numBands == 3 || numBands == 4)) { + IntegerComponentRaster iraster = + (IntegerComponentRaster) raster; + // Check if the raster params and the color model + // are correct + int pixSize = cm.getPixelSize(); + if (iraster.getPixelStride() == 1 && + isStandard && + cm instanceof DirectColorModel && + (pixSize == 32 || pixSize == 24)) + { + // Now check on the DirectColorModel params + DirectColorModel dcm = (DirectColorModel) cm; + int rmask = dcm.getRedMask(); + int gmask = dcm.getGreenMask(); + int bmask = dcm.getBlueMask(); + if (rmask == DCM_RED_MASK && gmask == DCM_GREEN_MASK && + bmask == DCM_BLUE_MASK) + { + if (dcm.getAlphaMask() == DCM_ALPHA_MASK) { + imageType = (isAlphaPre + ? TYPE_INT_ARGB_PRE + : TYPE_INT_ARGB); + } + else { + // No Alpha + if (!dcm.hasAlpha()) { + imageType = TYPE_INT_RGB; + } + } + } // if (dcm.getRedMask() == DCM_RED_MASK && + else if (rmask == DCM_BGR_RED_MASK && gmask == DCM_BGR_GRN_MASK + && bmask == DCM_BGR_BLU_MASK) { + if (!dcm.hasAlpha()) { + imageType = TYPE_INT_BGR; + } + } // if (rmask == DCM_BGR_RED_MASK && + } // if (iraster.getPixelStride() == 1 + } // ((raster instanceof IntegerComponentRaster) && + else if ((cm instanceof IndexColorModel) && (numBands == 1) && + isStandard && + (!cm.hasAlpha() || !isAlphaPre)) + { + IndexColorModel icm = (IndexColorModel) cm; + int pixSize = icm.getPixelSize(); + + if (raster instanceof BytePackedRaster) { + imageType = TYPE_BYTE_BINARY; + } // if (raster instanceof BytePackedRaster) + else if (raster instanceof ByteComponentRaster) { + ByteComponentRaster braster = (ByteComponentRaster) raster; + if (braster.getPixelStride() == 1 && pixSize <= 8) { + imageType = TYPE_BYTE_INDEXED; + } + } + } // else if (cm instanceof IndexColorModel) && (numBands == 1)) + else if ((raster instanceof ShortComponentRaster) + && (cm instanceof DirectColorModel) + && isStandard + && (numBands == 3) + && !cm.hasAlpha()) + { + DirectColorModel dcm = (DirectColorModel) cm; + if (dcm.getRedMask() == DCM_565_RED_MASK) { + if (dcm.getGreenMask() == DCM_565_GRN_MASK && + dcm.getBlueMask() == DCM_565_BLU_MASK) { + imageType = TYPE_USHORT_565_RGB; + } + } + else if (dcm.getRedMask() == DCM_555_RED_MASK) { + if (dcm.getGreenMask() == DCM_555_GRN_MASK && + dcm.getBlueMask() == DCM_555_BLU_MASK) { + imageType = TYPE_USHORT_555_RGB; + } + } + } // else if ((cm instanceof IndexColorModel) && (numBands == 1)) + else if ((raster instanceof ByteComponentRaster) + && (cm instanceof ComponentColorModel) + && isStandard + && (raster.getSampleModel() instanceof PixelInterleavedSampleModel) + && (numBands == 3 || numBands == 4)) + { + ComponentColorModel ccm = (ComponentColorModel) cm; + PixelInterleavedSampleModel csm = + (PixelInterleavedSampleModel)raster.getSampleModel(); + ByteComponentRaster braster = (ByteComponentRaster) raster; + int[] offs = csm.getBandOffsets(); + if (ccm.getNumComponents() != numBands) { + throw new RasterFormatException("Number of components in "+ + "ColorModel ("+ + ccm.getNumComponents()+ + ") does not match # in "+ + " Raster ("+numBands+")"); + } + int[] nBits = ccm.getComponentSize(); + boolean is8bit = true; + for (int i=0; i < numBands; i++) { + if (nBits[i] != 8) { + is8bit = false; + break; + } + } + if (is8bit && + braster.getPixelStride() == numBands && + offs[0] == numBands-1 && + offs[1] == numBands-2 && + offs[2] == numBands-3) + { + if (numBands == 3 && !ccm.hasAlpha()) { + imageType = TYPE_3BYTE_BGR; + } + else if (offs[3] == 0 && ccm.hasAlpha()) { + imageType = (isAlphaPre + ? TYPE_4BYTE_ABGR_PRE + : TYPE_4BYTE_ABGR); + } + } + } // else if ((raster instanceof ByteComponentRaster) && + } + + private static boolean isStandard(ColorModel cm, WritableRaster wr) { + final Class cmClass = cm.getClass(); + final Class wrClass = wr.getClass(); + final Class smClass = wr.getSampleModel().getClass(); + + final PrivilegedAction checkClassLoadersAction = + new PrivilegedAction() + { + + @Override + public Boolean run() { + final ClassLoader std = System.class.getClassLoader(); + + return (cmClass.getClassLoader() == std) && + (smClass.getClassLoader() == std) && + (wrClass.getClassLoader() == std); + } + }; + return AccessController.doPrivileged(checkClassLoadersAction); + } + + /** + * Get the .NET Bitmap object. + */ + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + public cli.System.Drawing.Bitmap getBitmap(){ + raster2Bitmap(); + return bitmap; + } + + /** + * Switch to the BITMAP buffer and invalidate the RASTER buffer before a graphics operation. + */ + final void toBitmap(){ + raster2Bitmap(); + currentBuffer = BUFFER_BITMAP; + } + + /** + * Switch to the RASTER buffer and invalidate the BITMAP buffer before a graphics operation. + */ + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + final void toRaster() { + bitmap2Raster(); + currentBuffer = BUFFER_RASTER; + } + + /** + * This Implementation of BufferedImage has 2 different Buffer, + * a Java WritableRaster and a .NET Bitmap. + * This method convert a Java WritableRaster to a .NET Bitmap if needed. + */ + private void raster2Bitmap(){ + if(currentBuffer != BUFFER_RASTER){ + return; // BUFFER_BOTH and BUFFER_BITMAP + } + int width = getWidth(); + int height = getHeight(); + + bitmap = createBitmap(width, height); + synchronized( bitmap ) { + // First map the pixel from Java type to .NET type + switch (getType()){ + case TYPE_INT_ARGB: + copyToBitmap(width, height, ((DataBufferInt)raster.getDataBuffer()).getData()); + break; + default:{ + for( int y = 0; y pixelData.length) + { + throw new IllegalArgumentException(); + } + cli.System.Drawing.Rectangle rect = new cli.System.Drawing.Rectangle(0, 0, width, height); + cli.System.Drawing.Imaging.BitmapData data = bitmap.LockBits(rect, ImageLockMode.wrap(ImageLockMode.WriteOnly), PixelFormat.wrap(PixelFormat.Format32bppArgb)); + cli.System.IntPtr pixelPtr = data.get_Scan0(); + cli.System.Runtime.InteropServices.Marshal.Copy(pixelData, 0, pixelPtr, (int)size); + bitmap.UnlockBits(data); + } + + /** + * This Implementation of BufferedImage has 2 different Buffer, + * a Java WritableRaster and a .NET Bitmap. + * This method convert the .NET Bitmap object to Java WritableRaster. + */ + private void bitmap2Raster(){ + if(currentBuffer != BUFFER_BITMAP){ + return; // BUFFER_BOTH and BUFFER_RASTER + } + synchronized( bitmap ) { + int width = bitmap.get_Width(); + int height = bitmap.get_Height(); + if(colorModel == null){ + colorModel = createColorModel(); + } + if(raster == null){ + raster = createRaster(width, height); + raster.getDataBuffer().setImage( this ); + } + + this.currentBuffer = BUFFER_BOTH; + switch (getType()){ + case TYPE_INT_ARGB: + copyFromBitmap(bitmap, ((DataBufferInt)raster.getDataBuffer()).getData()); + break; + default: + Object pixel = colorModel.getDataElements( 0, null ); //allocate a buffer for the follow loop + for( int y = 0; yBufferedImage. + * @see #TYPE_INT_RGB + * @see #TYPE_INT_ARGB + * @see #TYPE_INT_ARGB_PRE + * @see #TYPE_INT_BGR + * @see #TYPE_3BYTE_BGR + * @see #TYPE_4BYTE_ABGR + * @see #TYPE_4BYTE_ABGR_PRE + * @see #TYPE_BYTE_GRAY + * @see #TYPE_BYTE_BINARY + * @see #TYPE_BYTE_INDEXED + * @see #TYPE_USHORT_GRAY + * @see #TYPE_USHORT_565_RGB + * @see #TYPE_USHORT_555_RGB + * @see #TYPE_CUSTOM + */ + public int getType() { + return imageType; + } + + /** + * Returns the ColorModel. + * @return the ColorModel of this + * BufferedImage. + */ + public ColorModel getColorModel() { + return colorModel; + } + + /** + * Returns the {@link WritableRaster}. + * @return the WriteableRaster of this + * BufferedImage. + */ + public WritableRaster getRaster() { + bitmap2Raster(); + this.currentBuffer = BUFFER_RASTER; + return raster; + } + + + /** + * Returns a WritableRaster representing the alpha + * channel for BufferedImage objects + * with ColorModel objects that support a separate + * spatial alpha channel, such as ComponentColorModel and + * DirectColorModel. Returns null if there + * is no alpha channel associated with the ColorModel in + * this image. This method assumes that for all + * ColorModel objects other than + * IndexColorModel, if the ColorModel + * supports alpha, there is a separate alpha channel + * which is stored as the last band of image data. + * If the image uses an IndexColorModel that + * has alpha in the lookup table, this method returns + * null since there is no spatially discrete alpha + * channel. This method creates a new + * WritableRaster, but shares the data array. + * @return a WritableRaster or null if this + * BufferedImage has no alpha channel associated + * with its ColorModel. + */ + public WritableRaster getAlphaRaster() { + bitmap2Raster(); + return colorModel.getAlphaRaster(raster); + } + + /** + * Returns an integer pixel in the default RGB color model + * (TYPE_INT_ARGB) and default sRGB colorspace. Color + * conversion takes place if this default model does not match + * the image ColorModel. There are only 8-bits of + * precision for each color component in the returned data when using + * this method. + * + *

+ * + * An ArrayOutOfBoundsException may be thrown + * if the coordinates are not in bounds. + * However, explicit bounds checking is not guaranteed. + * + * @param x the X coordinate of the pixel from which to get + * the pixel in the default RGB color model and sRGB + * color space + * @param y the Y coordinate of the pixel from which to get + * the pixel in the default RGB color model and sRGB + * color space + * @return an integer pixel in the default RGB color model and + * default sRGB colorspace. + * @see #setRGB(int, int, int) + * @see #setRGB(int, int, int, int, int[], int, int) + */ + public int getRGB(int x, int y) { + bitmap2Raster(); + return colorModel.getRGB(raster.getDataElements(x, y, null)); + } + + /** + * Returns an array of integer pixels in the default RGB color model + * (TYPE_INT_ARGB) and default sRGB color space, + * from a portion of the image data. Color conversion takes + * place if the default model does not match the image + * ColorModel. There are only 8-bits of precision for + * each color component in the returned data when + * using this method. With a specified coordinate (x, y) in the + * image, the ARGB pixel can be accessed in this way: + * + *

+     *    pixel   = rgbArray[offset + (y-startY)*scansize + (x-startX)]; 
+ * + *

+ * + * An ArrayOutOfBoundsException may be thrown + * if the region is not in bounds. + * However, explicit bounds checking is not guaranteed. + * + * @param startX the starting X coordinate + * @param startY the starting Y coordinate + * @param w width of region + * @param h height of region + * @param rgbArray if not null, the rgb pixels are + * written here + * @param offset offset into the rgbArray + * @param scansize scanline stride for the rgbArray + * @return array of RGB pixels. + * @see #setRGB(int, int, int) + * @see #setRGB(int, int, int, int, int[], int, int) + */ + public int[] getRGB(int startX, int startY, int w, int h, + int[] rgbArray, int offset, int scansize) { + int yoff = offset; + int off; + Object data; + bitmap2Raster(); + int nbands = raster.getNumBands(); + int dataType = raster.getDataBuffer().getDataType(); + switch (dataType) { + case DataBuffer.TYPE_BYTE: + data = new byte[nbands]; + break; + case DataBuffer.TYPE_USHORT: + data = new short[nbands]; + break; + case DataBuffer.TYPE_INT: + data = new int[nbands]; + break; + case DataBuffer.TYPE_FLOAT: + data = new float[nbands]; + break; + case DataBuffer.TYPE_DOUBLE: + data = new double[nbands]; + break; + default: + throw new IllegalArgumentException("Unknown data buffer type: "+ + dataType); + } + + if (rgbArray == null) { + rgbArray = new int[offset+h*scansize]; + } + + for (int y = startY; y < startY+h; y++, yoff+=scansize) { + off = yoff; + for (int x = startX; x < startX+w; x++) { + rgbArray[off++] = colorModel.getRGB(raster.getDataElements(x, + y, + data)); + } + } + + return rgbArray; + } + + + /** + * Sets a pixel in this BufferedImage to the specified + * RGB value. The pixel is assumed to be in the default RGB color + * model, TYPE_INT_ARGB, and default sRGB color space. For images + * with an IndexColorModel, the index with the nearest + * color is chosen. + * + *

+ * + * An ArrayOutOfBoundsException may be thrown + * if the coordinates are not in bounds. + * However, explicit bounds checking is not guaranteed. + * + * @param x the X coordinate of the pixel to set + * @param y the Y coordinate of the pixel to set + * @param rgb the RGB value + * @see #getRGB(int, int) + * @see #getRGB(int, int, int, int, int[], int, int) + */ + public synchronized void setRGB(int x, int y, int rgb) { + switch( currentBuffer ) { + case BUFFER_BITMAP: + synchronized (bitmap) { + bitmap.SetPixel(x, y, Color.FromArgb(rgb)); + } + break; + case BUFFER_RASTER: + raster.setDataElements(x, y, colorModel.getDataElements(rgb, null)); + break; + case BUFFER_BOTH: + raster.setDataElements(x, y, colorModel.getDataElements(rgb, null)); + synchronized (bitmap) { + bitmap.SetPixel(x, y, Color.FromArgb(rgb)); + } + break; + } + } + + /** + * Sets an array of integer pixels in the default RGB color model + * (TYPE_INT_ARGB) and default sRGB color space, + * into a portion of the image data. Color conversion takes place + * if the default model does not match the image + * ColorModel. There are only 8-bits of precision for + * each color component in the returned data when + * using this method. With a specified coordinate (x, y) in the + * this image, the ARGB pixel can be accessed in this way: + *

+     *    pixel   = rgbArray[offset + (y-startY)*scansize + (x-startX)];
+     * 
+ * WARNING: No dithering takes place. + * + *

+ * + * An ArrayOutOfBoundsException may be thrown + * if the region is not in bounds. + * However, explicit bounds checking is not guaranteed. + * + * @param startX the starting X coordinate + * @param startY the starting Y coordinate + * @param w width of the region + * @param h height of the region + * @param rgbArray the rgb pixels + * @param offset offset into the rgbArray + * @param scansize scanline stride for the rgbArray + * @see #getRGB(int, int) + * @see #getRGB(int, int, int, int, int[], int, int) + */ + public void setRGB(int startX, int startY, int w, int h, + int[] rgbArray, int offset, int scansize) { + int yoff = offset; + int off; + + for (int y = startY; y < startY+h; y++, yoff+=scansize) { + off = yoff; + for (int x = startX; x < startX+w; x++) { + setRGB(x, y, rgbArray[off++]); + } + } + } + + + /** + * Returns the width of the BufferedImage. + * @return the width of this BufferedImage + */ + public int getWidth() { + if(currentBuffer == BUFFER_BITMAP){ + synchronized( bitmap ) { + return bitmap.get_Width(); + } + }else{ + return raster.getWidth(); + } + } + + /** + * Returns the height of the BufferedImage. + * @return the height of this BufferedImage + */ + public int getHeight() { + if(currentBuffer == BUFFER_BITMAP){ + synchronized( bitmap ) { + return bitmap.get_Height(); + } + }else{ + return raster.getHeight(); + } + } + + /** + * Returns the width of the BufferedImage. + * @param observer ignored + * @return the width of this BufferedImage + */ + public int getWidth(ImageObserver observer) { + return getWidth(); + } + + /** + * Returns the height of the BufferedImage. + * @param observer ignored + * @return the height of this BufferedImage + */ + public int getHeight(ImageObserver observer) { + return getHeight(); + } + + /** + * Returns the object that produces the pixels for the image. + * @return the {@link ImageProducer} that is used to produce the + * pixels for this image. + * @see ImageProducer + */ + public ImageProducer getSource() { + if(currentBuffer != BUFFER_RASTER){ + synchronized( bitmap ) { + int width = bitmap.get_Width(); + int height = bitmap.get_Height(); + int[] pix = new int[width * height]; + for(int y = 0; y < height; y++){ + for(int x = 0; x < width; x++){ + pix[x + y * width] = bitmap.GetPixel(x, y).ToArgb(); + } + } + return new java.awt.image.MemoryImageSource(width, height, pix, 0, width); + } + }else{ + if(osis == null){ + if(properties == null){ + properties = new Hashtable(); + } + osis = new OffScreenImageSource(this, properties); + } + return osis; + } + } + + + /** + * Returns a property of the image by name. Individual property names + * are defined by the various image formats. If a property is not + * defined for a particular image, this method returns the + * UndefinedProperty field. If the properties + * for this image are not yet known, then this method returns + * null and the ImageObserver object is + * notified later. The property name "comment" should be used to + * store an optional comment that can be presented to the user as a + * description of the image, its source, or its author. + * @param name the property name + * @param observer the ImageObserver that receives + * notification regarding image information + * @return an {@link Object} that is the property referred to by the + * specified name or null if the + * properties of this image are not yet known. + * @throws NullPointerException if the property name is null. + * @see ImageObserver + * @see java.awt.Image#UndefinedProperty + */ + public Object getProperty(String name, ImageObserver observer) { + return getProperty(name); + } + + /** + * Returns a property of the image by name. + * @param name the property name + * @return an Object that is the property referred to by + * the specified name. + * @throws NullPointerException if the property name is null. + */ + public Object getProperty(String name) { + if (name == null) { + throw new NullPointerException("null property name is not allowed"); + } + if (properties == null) { + return java.awt.Image.UndefinedProperty; + } + Object o = properties.get(name); + if (o == null) { + o = java.awt.Image.UndefinedProperty; + } + return o; + } + + /** + * This method returns a {@link Graphics2D}, but is here + * for backwards compatibility. {@link #createGraphics() createGraphics} is more + * convenient, since it is declared to return a + * Graphics2D. + * @return a Graphics2D, which can be used to draw into + * this image. + */ + public java.awt.Graphics getGraphics() { + return createGraphics(); + } + + /** + * Creates a Graphics2D, which can be used to draw into + * this BufferedImage. + * @return a Graphics2D, used for drawing into this + * image. + */ + public Graphics2D createGraphics() { + GraphicsEnvironment env = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + return env.createGraphics(this); + } + + /** + * Returns a subimage defined by a specified rectangular region. + * The returned BufferedImage shares the same + * data array as the original image. + * @param x the X coordinate of the upper-left corner of the + * specified rectangular region + * @param y the Y coordinate of the upper-left corner of the + * specified rectangular region + * @param w the width of the specified rectangular region + * @param h the height of the specified rectangular region + * @return a BufferedImage that is the subimage of this + * BufferedImage. + * @exception RasterFormatException if the specified + * area is not contained within this BufferedImage. + */ + public BufferedImage getSubimage (int x, int y, int w, int h) { + bitmap2Raster(); + return new BufferedImage (colorModel, + raster.createWritableChild(x, y, w, h, + 0, 0, null), + colorModel.isAlphaPremultiplied(), + properties); + } + + /** + * Returns whether or not the alpha has been premultiplied. It + * returns false if there is no alpha. + * @return true if the alpha has been premultiplied; + * false otherwise. + */ + public boolean isAlphaPremultiplied() { + return colorModel.isAlphaPremultiplied(); + } + + /** + * Forces the data to match the state specified in the + * isAlphaPremultiplied variable. It may multiply or + * divide the color raster data by alpha, or do nothing if the data is + * in the correct state. + * @param isAlphaPremultiplied true if the alpha has been + * premultiplied; false otherwise. + */ + public void coerceData (boolean isAlphaPremultiplied) { + if (colorModel.hasAlpha() && + colorModel.isAlphaPremultiplied() != isAlphaPremultiplied) { + bitmap2Raster(); + this.currentBuffer = BUFFER_RASTER; + // Make the color model do the conversion + colorModel = colorModel.coerceData (raster, isAlphaPremultiplied); + } + } + + /** + * Returns a String representation of this + * BufferedImage object and its values. + * @return a String representing this + * BufferedImage. + */ + public String toString() { + return "BufferedImage@"+Integer.toHexString(hashCode()) + +": type = "+imageType + +" "+colorModel+" "+raster; + } + + /** + * Returns a {@link Vector} of {@link RenderedImage} objects that are + * the immediate sources, not the sources of these immediate sources, + * of image data for this BufferedImage. This + * method returns null if the BufferedImage + * has no information about its immediate sources. It returns an + * empty Vector if the BufferedImage has no + * immediate sources. + * @return a Vector containing immediate sources of + * this BufferedImage object's image date, or + * null if this BufferedImage has + * no information about its immediate sources, or an empty + * Vector if this BufferedImage + * has no immediate sources. + */ + public Vector getSources() { + return null; + } + + /** + * Returns an array of names recognized by + * {@link #getProperty(String) getProperty(String)} + * or null, if no property names are recognized. + * @return a String array containing all of the property + * names that getProperty(String) recognizes; + * or null if no property names are recognized. + */ + public String[] getPropertyNames() { + return null; + } + + /** + * Returns the minimum x coordinate of this + * BufferedImage. This is always zero. + * @return the minimum x coordinate of this + * BufferedImage. + */ + public int getMinX() { + return 0; + } + + /** + * Returns the minimum y coordinate of this + * BufferedImage. This is always zero. + * @return the minimum y coordinate of this + * BufferedImage. + */ + public int getMinY() { + return 0; + } + + /** + * Returns the SampleModel associated with this + * BufferedImage. + * @return the SampleModel of this + * BufferedImage. + */ + public SampleModel getSampleModel() { + bitmap2Raster(); + return raster.getSampleModel(); + } + + /** + * Returns the number of tiles in the x direction. + * This is always one. + * @return the number of tiles in the x direction. + */ + public int getNumXTiles() { + return 1; + } + + /** + * Returns the number of tiles in the y direction. + * This is always one. + * @return the number of tiles in the y direction. + */ + public int getNumYTiles() { + return 1; + } + + /** + * Returns the minimum tile index in the x direction. + * This is always zero. + * @return the minimum tile index in the x direction. + */ + public int getMinTileX() { + return 0; + } + + /** + * Returns the minimum tile index in the y direction. + * This is always zero. + * @return the minimum tile index in the y direction. + */ + public int getMinTileY() { + return 0; + } + + /** + * Returns the tile width in pixels. + * @return the tile width in pixels. + */ + public int getTileWidth() { + return getWidth(); + } + + /** + * Returns the tile height in pixels. + * @return the tile height in pixels. + */ + public int getTileHeight() { + return getHeight(); + } + + /** + * Returns the x offset of the tile grid relative to the origin, + * For example, the x coordinate of the location of tile + * (0, 0). This is always zero. + * @return the x offset of the tile grid. + */ + public int getTileGridXOffset() { + bitmap2Raster(); + return raster.getSampleModelTranslateX(); + } + + /** + * Returns the y offset of the tile grid relative to the origin, + * For example, the y coordinate of the location of tile + * (0, 0). This is always zero. + * @return the y offset of the tile grid. + */ + public int getTileGridYOffset() { + bitmap2Raster(); + return raster.getSampleModelTranslateY(); + } + + /** + * Returns tile (tileXtileY). Note + * that tileX and tileY are indices + * into the tile array, not pixel locations. The Raster + * that is returned is live, which means that it is updated if the + * image is changed. + * @param tileX the x index of the requested tile in the tile array + * @param tileY the y index of the requested tile in the tile array + * @return a Raster that is the tile defined by the + * arguments tileX and tileY. + * @exception ArrayIndexOutOfBoundsException if both + * tileX and tileY are not + * equal to 0 + */ + public Raster getTile(int tileX, int tileY) { + if (tileX == 0 && tileY == 0) { + bitmap2Raster(); + return raster; + } + throw new ArrayIndexOutOfBoundsException("BufferedImages only have"+ + " one tile with index 0,0"); + } + + /** + * Returns the image as one large tile. The Raster + * returned is a copy of the image data is not updated if the + * image is changed. + * @return a Raster that is a copy of the image data. + * @see #setData(Raster) + */ + public Raster getData() { + bitmap2Raster(); + + // REMIND : this allocates a whole new tile if raster is a + // subtile. (It only copies in the requested area) + // We should do something smarter. + int width = raster.getWidth(); + int height = raster.getHeight(); + int startX = raster.getMinX(); + int startY = raster.getMinY(); + WritableRaster wr = + Raster.createWritableRaster(raster.getSampleModel(), + new Point(raster.getSampleModelTranslateX(), + raster.getSampleModelTranslateY())); + + Object tdata = null; + + for (int i = startY; i < startY+height; i++) { + tdata = raster.getDataElements(startX,i,width,1,tdata); + wr.setDataElements(startX,i,width,1, tdata); + } + return wr; + } + + /** + * Computes and returns an arbitrary region of the + * BufferedImage. The Raster returned is a + * copy of the image data and is not updated if the image is + * changed. + * @param rect the region of the BufferedImage to be + * returned. + * @return a Raster that is a copy of the image data of + * the specified region of the BufferedImage + * @see #setData(Raster) + */ + public Raster getData(Rectangle rect) { + bitmap2Raster(); + SampleModel sm = raster.getSampleModel(); + SampleModel nsm = sm.createCompatibleSampleModel(rect.width, + rect.height); + WritableRaster wr = Raster.createWritableRaster(nsm, + rect.getLocation()); + int width = rect.width; + int height = rect.height; + int startX = rect.x; + int startY = rect.y; + + Object tdata = null; + + for (int i = startY; i < startY+height; i++) { + tdata = raster.getDataElements(startX,i,width,1,tdata); + wr.setDataElements(startX,i,width,1, tdata); + } + return wr; + } + + /** + * Computes an arbitrary rectangular region of the + * BufferedImage and copies it into a specified + * WritableRaster. The region to be computed is + * determined from the bounds of the specified + * WritableRaster. The specified + * WritableRaster must have a + * SampleModel that is compatible with this image. If + * outRaster is null, + * an appropriate WritableRaster is created. + * @param outRaster a WritableRaster to hold the returned + * part of the image, or null + * @return a reference to the supplied or created + * WritableRaster. + */ + public WritableRaster copyData(WritableRaster outRaster) { + bitmap2Raster(); + if (outRaster == null) { + return (WritableRaster) getData(); + } + int width = outRaster.getWidth(); + int height = outRaster.getHeight(); + int startX = outRaster.getMinX(); + int startY = outRaster.getMinY(); + + Object tdata = null; + + for (int i = startY; i < startY+height; i++) { + tdata = raster.getDataElements(startX,i,width,1,tdata); + outRaster.setDataElements(startX,i,width,1, tdata); + } + + return outRaster; + } + + /** + * Sets a rectangular region of the image to the contents of the + * specified Raster r, which is + * assumed to be in the same coordinate space as the + * BufferedImage. The operation is clipped to the bounds + * of the BufferedImage. + * @param r the specified Raster + * @see #getData + * @see #getData(Rectangle) + */ + public void setData(Raster r) { + bitmap2Raster(); + this.currentBuffer = BUFFER_RASTER; + + int width = r.getWidth(); + int height = r.getHeight(); + int startX = r.getMinX(); + int startY = r.getMinY(); + + int[] tdata = null; + + // Clip to the current Raster + Rectangle rclip = new Rectangle(startX, startY, width, height); + Rectangle bclip = new Rectangle(0, 0, raster.width, raster.height); + Rectangle intersect = rclip.intersection(bclip); + if (intersect.isEmpty()) { + return; + } + width = intersect.width; + height = intersect.height; + startX = intersect.x; + startY = intersect.y; + + // remind use get/setDataElements for speed if Rasters are + // compatible + for (int i = startY; i < startY+height; i++) { + tdata = r.getPixels(startX,i,width,1,tdata); + raster.setPixels(startX,i,width,1, tdata); + } + } + + + /** + * Adds a tile observer. If the observer is already present, + * it receives multiple notifications. + * @param to the specified {@link TileObserver} + */ + public void addTileObserver (TileObserver to) { + } + + /** + * Removes a tile observer. If the observer was not registered, + * nothing happens. If the observer was registered for multiple + * notifications, it is now registered for one fewer notification. + * @param to the specified TileObserver. + */ + public void removeTileObserver (TileObserver to) { + } + + /** + * Returns whether or not a tile is currently checked out for writing. + * @param tileX the x index of the tile. + * @param tileY the y index of the tile. + * @return true if the tile specified by the specified + * indices is checked out for writing; false + * otherwise. + * @exception ArrayIndexOutOfBoundsException if both + * tileX and tileY are not equal + * to 0 + */ + public boolean isTileWritable (int tileX, int tileY) { + if (tileX == 0 && tileY == 0) { + return true; + } + throw new IllegalArgumentException("Only 1 tile in image"); + } + + /** + * Returns an array of {@link Point} objects indicating which tiles + * are checked out for writing. Returns null if none are + * checked out. + * @return a Point array that indicates the tiles that + * are checked out for writing, or null if no + * tiles are checked out for writing. + */ + public Point[] getWritableTileIndices() { + Point[] p = new Point[1]; + p[0] = new Point(0, 0); + + return p; + } + + /** + * Returns whether or not any tile is checked out for writing. + * Semantically equivalent to + *

+     * (getWritableTileIndices() != null).
+     * 
+ * @return true if any tile is checked out for writing; + * false otherwise. + */ + public boolean hasTileWriters () { + return true; + } + + /** + * Checks out a tile for writing. All registered + * TileObservers are notified when a tile goes from having + * no writers to having one writer. + * @param tileX the x index of the tile + * @param tileY the y index of the tile + * @return a WritableRaster that is the tile, indicated by + * the specified indices, to be checked out for writing. + */ + public WritableRaster getWritableTile (int tileX, int tileY) { + bitmap2Raster(); + this.currentBuffer = BUFFER_RASTER; + return raster; + } + + /** + * Relinquishes permission to write to a tile. If the caller + * continues to write to the tile, the results are undefined. + * Calls to this method should only appear in matching pairs + * with calls to {@link #getWritableTile(int, int) getWritableTile(int, int)}. Any other leads + * to undefined results. All registered TileObservers + * are notified when a tile goes from having one writer to having no + * writers. + * @param tileX the x index of the tile + * @param tileY the y index of the tile + */ + public void releaseWritableTile (int tileX, int tileY) { + } + + /** + * Returns the transparency. Returns either OPAQUE, BITMASK, + * or TRANSLUCENT. + * @return the transparency of this BufferedImage. + * @see Transparency#OPAQUE + * @see Transparency#BITMASK + * @see Transparency#TRANSLUCENT + * @since 1.5 + */ + public int getTransparency() { + return colorModel.getTransparency(); + } + + public void flush(){ + } +} diff --git a/openjdk/java/awt/image/ColorConvertOp.java b/openjdk/java/awt/image/ColorConvertOp.java new file mode 100644 index 0000000..0fb7497 --- /dev/null +++ b/openjdk/java/awt/image/ColorConvertOp.java @@ -0,0 +1,537 @@ +/* ColorConvertOp.java -- + Copyright (C) 2004, 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import gnu.java.awt.Buffers; + +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.RenderingHints; +import java.awt.color.ColorSpace; +import java.awt.color.ICC_ColorSpace; +import java.awt.color.ICC_Profile; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +/** + * ColorConvertOp is a filter for converting images or rasters between + * colorspaces, either through a sequence of colorspaces or just from source to + * destination. + * + * Color conversion is done on the color components without alpha. Thus + * if a BufferedImage has alpha premultiplied, this is divided out before + * color conversion, and premultiplication applied if the destination + * requires it. + * + * Color rendering and dithering hints may be applied if specified. This is + * likely platform-dependent. + * + * @author jlquinn@optonline.net + */ +public class ColorConvertOp implements BufferedImageOp, RasterOp +{ + private RenderingHints hints; + private ICC_Profile[] profiles = null; + private ColorSpace[] spaces; + + + /** + * Convert a BufferedImage through a ColorSpace. + * + * Objects created with this constructor can be used to convert + * BufferedImage's to a destination ColorSpace. Attempts to convert Rasters + * with this constructor will result in an IllegalArgumentException when the + * filter(Raster, WritableRaster) method is called. + * + * @param cspace The target color space. + * @param hints Rendering hints to use in conversion, if any (may be null) + * @throws NullPointerException if the ColorSpace is null. + */ + public ColorConvertOp(ColorSpace cspace, RenderingHints hints) + { + if (cspace == null) + throw new NullPointerException(); + spaces = new ColorSpace[]{cspace}; + this.hints = hints; + } + + /** + * Convert from a source colorspace to a destination colorspace. + * + * This constructor takes two ColorSpace arguments as the source and + * destination color spaces. It is usually used with the + * filter(Raster, WritableRaster) method, in which case the source colorspace + * is assumed to correspond to the source Raster, and the destination + * colorspace with the destination Raster. + * + * If used with BufferedImages that do not match the source or destination + * colorspaces specified here, there is an implicit conversion from the + * source image to the source ColorSpace, or the destination ColorSpace to + * the destination image. + * + * @param srcCspace The source ColorSpace. + * @param dstCspace The destination ColorSpace. + * @param hints Rendering hints to use in conversion, if any (may be null). + * @throws NullPointerException if any ColorSpace is null. + */ + public ColorConvertOp(ColorSpace srcCspace, ColorSpace dstCspace, + RenderingHints hints) + { + if (srcCspace == null || dstCspace == null) + throw new NullPointerException(); + spaces = new ColorSpace[]{srcCspace, dstCspace}; + this.hints = hints; + } + + /** + * Convert from a source colorspace to a destinatino colorspace. + * + * This constructor builds a ColorConvertOp from an array of ICC_Profiles. + * The source will be converted through the sequence of color spaces + * defined by the profiles. If the sequence of profiles doesn't give a + * well-defined conversion, an IllegalArgumentException is thrown. + * + * If used with BufferedImages that do not match the source or destination + * colorspaces specified here, there is an implicit conversion from the + * source image to the source ColorSpace, or the destination ColorSpace to + * the destination image. + * + * For Rasters, the first and last profiles must have the same number of + * bands as the source and destination Rasters, respectively. If this is + * not the case, or there fewer than 2 profiles, an IllegalArgumentException + * will be thrown. + * + * @param profiles An array of ICC_Profile's to convert through. + * @param hints Rendering hints to use in conversion, if any (may be null). + * @throws NullPointerException if the profile array is null. + * @throws IllegalArgumentException if the array is not a well-defined + * conversion. + */ + public ColorConvertOp(ICC_Profile[] profiles, RenderingHints hints) + { + if (profiles == null) + throw new NullPointerException(); + + this.hints = hints; + this.profiles = profiles; + + // Create colorspace array with space for src and dest colorspace + // Note that the ICC_ColorSpace constructor will throw an + // IllegalArgumentException if the profile is invalid; thus we check + // for a "well defined conversion" + spaces = new ColorSpace[profiles.length]; + for (int i = 0; i < profiles.length; i++) + spaces[i] = new ICC_ColorSpace(profiles[i]); + } + + /** + * Convert from source color space to destination color space. + * + * Only valid for BufferedImage objects, this Op converts from the source + * image's color space to the destination image's color space. + * + * The destination in the filter(BufferedImage, BufferedImage) method cannot + * be null for this operation, and it also cannot be used with the + * filter(Raster, WritableRaster) method. + * + * @param hints Rendering hints to use in conversion, if any (may be null). + */ + public ColorConvertOp(RenderingHints hints) + { + this.hints = hints; + spaces = new ColorSpace[0]; + } + + /** + * Converts the source image using the conversion path specified in the + * constructor. The resulting image is stored in the destination image if one + * is provided; otherwise a new BufferedImage is created and returned. + * + * The source and destination BufferedImage (if one is supplied) must have + * the same dimensions. + * + * @param src The source image. + * @param dst The destination image. + * @throws IllegalArgumentException if the rasters and/or color spaces are + * incompatible. + * @return The transformed image. + */ + public final BufferedImage filter(BufferedImage src, BufferedImage dst) + { + // TODO: The plan is to create a scanline buffer for intermediate buffers. + // For now we just suck it up and create intermediate buffers. + + if (dst == null && spaces.length == 0) + throw new IllegalArgumentException("Not enough color space information " + + "to complete conversion."); + + if (dst != null + && (src.getHeight() != dst.getHeight() || src.getWidth() != dst.getWidth())) + throw new IllegalArgumentException("Source and destination images have " + + "different dimensions"); + + // Make sure input isn't premultiplied by alpha + if (src.isAlphaPremultiplied()) + { + BufferedImage tmp = createCompatibleDestImage(src, src.getColorModel()); + copyimage(src, tmp); + tmp.coerceData(false); + src = tmp; + } + + // Convert through defined intermediate conversions + BufferedImage tmp; + for (int i = 0; i < spaces.length; i++) + { + if (src.getColorModel().getColorSpace().getType() != spaces[i].getType()) + { + tmp = createCompatibleDestImage(src, + createCompatibleColorModel(src, + spaces[i])); + copyimage(src, tmp); + src = tmp; + } + } + + // No implicit conversion to destination type needed; return result from the + // last intermediate conversions (which was left in src) + if (dst == null) + dst = src; + + // Implicit conversion to destination image's color space + else + copyimage(src, dst); + + return dst; + } + + /** + * Converts the source raster using the conversion path specified in the + * constructor. The resulting raster is stored in the destination raster if + * one is provided; otherwise a new WritableRaster is created and returned. + * + * This operation is not valid with every constructor of this class; see + * the constructors for details. Further, the source raster must have the + * same number of bands as the source ColorSpace, and the destination raster + * must have the same number of bands as the destination ColorSpace. + * + * The source and destination raster (if one is supplied) must also have the + * same dimensions. + * + * @param src The source raster. + * @param dest The destination raster. + * @throws IllegalArgumentException if the rasters and/or color spaces are + * incompatible. + * @return The transformed raster. + */ + public final WritableRaster filter(Raster src, WritableRaster dest) + { + // Various checks to ensure that the rasters and color spaces are compatible + if (spaces.length < 2) + throw new IllegalArgumentException("Not enough information about " + + "source and destination colorspaces."); + + if (spaces[0].getNumComponents() != src.getNumBands() + || (dest != null && spaces[spaces.length - 1].getNumComponents() != dest.getNumBands())) + throw new IllegalArgumentException("Source or destination raster " + + "contains the wrong number of bands."); + + if (dest != null + && (src.getHeight() != dest.getHeight() || src.getWidth() != dest.getWidth())) + throw new IllegalArgumentException("Source and destination rasters " + + "have different dimensions"); + + // Need to iterate through each color space. + // spaces[0] corresponds to the ColorSpace of the source raster, and + // spaces[spaces.length - 1] corresponds to the ColorSpace of the + // destination, with any number (or zero) of intermediate conversions. + + for (int i = 0; i < spaces.length - 2; i++) + { + WritableRaster tmp = createCompatibleDestRaster(src, spaces[i + 1], + false, + src.getTransferType()); + copyraster(src, spaces[i], tmp, spaces[i + 1]); + src = tmp; + } + + // The last conversion is done outside of the loop so that we can + // use the dest raster supplied, instead of creating our own temp raster + if (dest == null) + dest = createCompatibleDestRaster(src, spaces[spaces.length - 1], false, + DataBuffer.TYPE_BYTE); + copyraster(src, spaces[spaces.length - 2], dest, spaces[spaces.length - 1]); + + return dest; + } + + /** + * Creates an empty BufferedImage with the size equal to the source and the + * correct number of bands for the conversion defined in this Op. The newly + * created image is created with the specified ColorModel, or if no ColorModel + * is supplied, an appropriate one is chosen. + * + * @param src The source image. + * @param dstCM A color model for the destination image (may be null). + * @throws IllegalArgumentException if an appropriate colormodel cannot be + * chosen with the information given. + * @return The new compatible destination image. + */ + public BufferedImage createCompatibleDestImage(BufferedImage src, + ColorModel dstCM) + { + if (dstCM == null && spaces.length == 0) + throw new IllegalArgumentException("Don't know the destination " + + "colormodel"); + + if (dstCM == null) + { + dstCM = createCompatibleColorModel(src, spaces[spaces.length - 1]); + } + + return new BufferedImage(dstCM, + createCompatibleDestRaster(src.getRaster(), + dstCM.getColorSpace(), + src.getColorModel().hasAlpha(), + dstCM.getTransferType()), + src.isAlphaPremultiplied, null); + } + + /** + * Creates a new WritableRaster with the size equal to the source and the + * correct number of bands. + * + * Note, the new Raster will always use a BYTE storage size, regardless of + * the color model or defined destination; this is for compatibility with + * the reference implementation. + * + * @param src The source Raster. + * @throws IllegalArgumentException if there isn't enough colorspace + * information to create a compatible Raster. + * @return The new compatible destination raster. + */ + public WritableRaster createCompatibleDestRaster(Raster src) + { + if (spaces.length < 2) + throw new IllegalArgumentException("Not enough destination colorspace " + + "information"); + + // Create a new raster with the last ColorSpace in the conversion + // chain, and with no alpha (implied) + return createCompatibleDestRaster(src, spaces[spaces.length-1], false, + DataBuffer.TYPE_BYTE); + } + + /** + * Returns the array of ICC_Profiles used to create this Op, or null if the + * Op was created using ColorSpace arguments. + * + * @return The array of ICC_Profiles, or null. + */ + public final ICC_Profile[] getICC_Profiles() + { + return profiles; + } + + /** + * Returns the rendering hints for this op. + * + * @return The rendering hints for this Op, or null. + */ + public final RenderingHints getRenderingHints() + { + return hints; + } + + /** + * Returns the corresponding destination point for a source point. + * Because this is not a geometric operation, the destination and source + * points will be identical. + * + * @param src The source point. + * @param dst The transformed destination point. + * @return The transformed destination point. + */ + public final Point2D getPoint2D(Point2D src, Point2D dst) + { + if (dst == null) + return (Point2D)src.clone(); + + dst.setLocation(src); + return dst; + } + + /** + * Returns the corresponding destination boundary of a source boundary. + * Because this is not a geometric operation, the destination and source + * boundaries will be identical. + * + * @param src The source boundary. + * @return The boundaries of the destination. + */ + public final Rectangle2D getBounds2D(BufferedImage src) + { + return src.getRaster().getBounds(); + } + + /** + * Returns the corresponding destination boundary of a source boundary. + * Because this is not a geometric operation, the destination and source + * boundaries will be identical. + * + * @param src The source boundary. + * @return The boundaries of the destination. + */ + public final Rectangle2D getBounds2D(Raster src) + { + return src.getBounds(); + } + + /** + * Copy a source image to a destination image, respecting their colorspaces + * and performing colorspace conversions if necessary. + * + * @param src The source image. + * @param dst The destination image. + */ + private void copyimage(BufferedImage src, BufferedImage dst) + { + // This is done using Graphics2D in order to respect the rendering hints. + Graphics2D gg = dst.createGraphics(); + + // If no hints are set there is no need to call + // setRenderingHints on the Graphics2D object. + if (hints != null) + gg.setRenderingHints(hints); + + gg.drawImage(src, 0, 0, null); + gg.dispose(); + } + + /** + * Copy a source raster to a destination raster, performing a colorspace + * conversion between the two. The conversion will respect the + * KEY_COLOR_RENDERING rendering hint if one is present. + * + * @param src The source raster. + * @param scs The colorspace of the source raster. + * @dst The destination raster. + * @dcs The colorspace of the destination raster. + */ + private void copyraster(Raster src, ColorSpace scs, WritableRaster dst, ColorSpace dcs) + { + float[] sbuf = new float[src.getNumBands()]; + + if (hints != null + && hints.get(RenderingHints.KEY_COLOR_RENDERING) == + RenderingHints.VALUE_COLOR_RENDER_QUALITY) + { + // use cie for accuracy + for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++) + for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++) + dst.setPixel(x, y, + dcs.fromCIEXYZ(scs.toCIEXYZ(src.getPixel(x, y, sbuf)))); + } + else + { + // use rgb - it's probably faster + for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++) + for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++) + dst.setPixel(x, y, + dcs.fromRGB(scs.toRGB(src.getPixel(x, y, sbuf)))); + } + } + + /** + * This method creates a color model with the same colorspace and alpha + * settings as the source image. The created color model will always be a + * ComponentColorModel and have a BYTE transfer type. + * + * @param img The source image. + * @param cs The ColorSpace to use. + * @return A color model compatible with the source image. + */ + private ColorModel createCompatibleColorModel(BufferedImage img, ColorSpace cs) + { + // The choice of ComponentColorModel and DataBuffer.TYPE_BYTE is based on + // Mauve testing of the reference implementation. + return new ComponentColorModel(cs, + img.getColorModel().hasAlpha(), + img.isAlphaPremultiplied(), + img.getColorModel().getTransparency(), + DataBuffer.TYPE_BYTE); + } + + /** + * This method creates a compatible Raster, given a source raster, colorspace, + * alpha value, and transfer type. + * + * @param src The source raster. + * @param cs The ColorSpace to use. + * @param hasAlpha Whether the raster should include a component for an alpha. + * @param transferType The size of a single data element. + * @return A compatible WritableRaster. + */ + private WritableRaster createCompatibleDestRaster(Raster src, ColorSpace cs, + boolean hasAlpha, + int transferType) + { + // The use of a PixelInterleavedSampleModel weas determined using mauve + // tests, based on the reference implementation + + int numComponents = cs.getNumComponents(); + if (hasAlpha) + numComponents++; + + int[] offsets = new int[numComponents]; + for (int i = 0; i < offsets.length; i++) + offsets[i] = i; + + DataBuffer db = Buffers.createBuffer(transferType, + src.getWidth() * src.getHeight() * numComponents, + 1); + return new WritableRaster(new PixelInterleavedSampleModel(transferType, + src.getWidth(), + src.getHeight(), + numComponents, + numComponents * src.getWidth(), + offsets), + db, new Point(src.getMinX(), src.getMinY())); + } +} diff --git a/openjdk/java/awt/image/ConvolveOp.java b/openjdk/java/awt/image/ConvolveOp.java new file mode 100644 index 0000000..cf30e76 --- /dev/null +++ b/openjdk/java/awt/image/ConvolveOp.java @@ -0,0 +1,380 @@ +/* ConvolveOp.java -- + Copyright (C) 2004, 2005, 2006, Free Software Foundation -- ConvolveOp + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.awt.RenderingHints; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +/** + * Convolution filter. + * + * ConvolveOp convolves the source image with a Kernel to generate a + * destination image. This involves multiplying each pixel and its neighbors + * with elements in the kernel to compute a new pixel. + * + * Each band in a Raster is convolved and copied to the destination Raster. + * For BufferedImages, convolution is applied to all components. Color + * conversion will be applied if needed. + * + * Note that this filter ignores whether the source or destination is alpha + * premultiplied. The reference spec states that data will be premultiplied + * prior to convolving and divided back out afterwards (if needed), but testing + * has shown that this is not the case with their implementation. + * + * @author jlquinn@optonline.net + */ +public class ConvolveOp implements BufferedImageOp, RasterOp +{ + /** Edge pixels are set to 0. */ + public static final int EDGE_ZERO_FILL = 0; + + /** Edge pixels are copied from the source. */ + public static final int EDGE_NO_OP = 1; + + private Kernel kernel; + private int edge; + private RenderingHints hints; + + /** + * Construct a ConvolveOp. + * + * The edge condition specifies that pixels outside the area that can be + * filtered are either set to 0 or copied from the source image. + * + * @param kernel The kernel to convolve with. + * @param edgeCondition Either EDGE_ZERO_FILL or EDGE_NO_OP. + * @param hints Rendering hints for color conversion, or null. + */ + public ConvolveOp(Kernel kernel, + int edgeCondition, + RenderingHints hints) + { + this.kernel = kernel; + edge = edgeCondition; + this.hints = hints; + } + + /** + * Construct a ConvolveOp. + * + * The edge condition defaults to EDGE_ZERO_FILL. + * + * @param kernel The kernel to convolve with. + */ + public ConvolveOp(Kernel kernel) + { + this.kernel = kernel; + edge = EDGE_ZERO_FILL; + hints = null; + } + + /** + * Converts the source image using the kernel specified in the + * constructor. The resulting image is stored in the destination image if one + * is provided; otherwise a new BufferedImage is created and returned. + * + * The source and destination BufferedImage (if one is supplied) must have + * the same dimensions. + * + * @param src The source image. + * @param dst The destination image. + * @throws IllegalArgumentException if the rasters and/or color spaces are + * incompatible. + * @return The convolved image. + */ + public final BufferedImage filter(BufferedImage src, BufferedImage dst) + { + if (src == dst) + throw new IllegalArgumentException("Source and destination images " + + "cannot be the same."); + + if (dst == null) + dst = createCompatibleDestImage(src, src.getColorModel()); + + // Make sure source image is premultiplied + BufferedImage src1 = src; + // The spec says we should do this, but mauve testing shows that Sun's + // implementation does not check this. + /* + if (!src.isAlphaPremultiplied()) + { + src1 = createCompatibleDestImage(src, src.getColorModel()); + src.copyData(src1.getRaster()); + src1.coerceData(true); + } + */ + + BufferedImage dst1 = dst; + if (src1.getColorModel().getColorSpace().getType() != dst.getColorModel().getColorSpace().getType()) + dst1 = createCompatibleDestImage(src, src.getColorModel()); + + filter(src1.getRaster(), dst1.getRaster()); + + // Since we don't coerceData above, we don't need to divide it back out. + // This is wrong (one mauve test specifically tests converting a non- + // premultiplied image to a premultiplied image, and it shows that Sun + // simply ignores the premultipled flag, contrary to the spec), but we + // mimic it for compatibility. + /* + if (! dst.isAlphaPremultiplied()) + dst1.coerceData(false); + */ + + // Convert between color models if needed + if (dst1 != dst) + new ColorConvertOp(hints).filter(dst1, dst); + + return dst; + } + + /** + * Creates an empty BufferedImage with the size equal to the source and the + * correct number of bands. The new image is created with the specified + * ColorModel, or if no ColorModel is supplied, an appropriate one is chosen. + * + * @param src The source image. + * @param dstCM A color model for the destination image (may be null). + * @return The new compatible destination image. + */ + public BufferedImage createCompatibleDestImage(BufferedImage src, + ColorModel dstCM) + { + if (dstCM != null) + return new BufferedImage(dstCM, + src.getRaster().createCompatibleWritableRaster(), + src.isAlphaPremultiplied(), null); + + return new BufferedImage(src.getWidth(), src.getHeight(), src.getType()); + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#getRenderingHints() + */ + public final RenderingHints getRenderingHints() + { + return hints; + } + + /** + * Get the edge condition for this Op. + * + * @return The edge condition. + */ + public int getEdgeCondition() + { + return edge; + } + + /** + * Returns (a clone of) the convolution kernel. + * + * @return The convolution kernel. + */ + public final Kernel getKernel() + { + return (Kernel) kernel.clone(); + } + + /** + * Converts the source raster using the kernel specified in the constructor. + * The resulting raster is stored in the destination raster if one is + * provided; otherwise a new WritableRaster is created and returned. + * + * If the convolved value for a sample is outside the range of [0-255], it + * will be clipped. + * + * The source and destination raster (if one is supplied) cannot be the same, + * and must also have the same dimensions. + * + * @param src The source raster. + * @param dest The destination raster. + * @throws IllegalArgumentException if the rasters identical. + * @throws ImagingOpException if the convolution is not possible. + * @return The transformed raster. + */ + public final WritableRaster filter(Raster src, WritableRaster dest) + { + if (src == dest) + throw new IllegalArgumentException("src == dest is not allowed."); + if (kernel.getWidth() > src.getWidth() + || kernel.getHeight() > src.getHeight()) + throw new ImagingOpException("The kernel is too large."); + if (dest == null) + dest = createCompatibleDestRaster(src); + else if (src.getNumBands() != dest.getNumBands()) + throw new ImagingOpException("src and dest have different band counts."); + + // calculate the borders that the op can't reach... + int kWidth = kernel.getWidth(); + int kHeight = kernel.getHeight(); + int left = kernel.getXOrigin(); + int right = Math.max(kWidth - left - 1, 0); + int top = kernel.getYOrigin(); + int bottom = Math.max(kHeight - top - 1, 0); + + // Calculate max sample values for clipping + int[] maxValue = src.getSampleModel().getSampleSize(); + for (int i = 0; i < maxValue.length; i++) + maxValue[i] = (int)Math.pow(2, maxValue[i]) - 1; + + // process the region that is reachable... + int regionW = src.width - left - right; + int regionH = src.height - top - bottom; + float[] kvals = kernel.getKernelData(null); + float[] tmp = new float[kWidth * kHeight]; + + for (int x = 0; x < regionW; x++) + { + for (int y = 0; y < regionH; y++) + { + // FIXME: This needs a much more efficient implementation + for (int b = 0; b < src.getNumBands(); b++) + { + float v = 0; + src.getSamples(x, y, kWidth, kHeight, b, tmp); + for (int i = 0; i < tmp.length; i++) + v += tmp[tmp.length - i - 1] * kvals[i]; + // FIXME: in the above line, I've had to reverse the order of + // the samples array to make the tests pass. I haven't worked + // out why this is necessary. + + // This clipping is is undocumented, but determined by testing. + if (v > maxValue[b]) + v = maxValue[b]; + else if (v < 0) + v = 0; + + dest.setSample(x + kernel.getXOrigin(), y + kernel.getYOrigin(), + b, v); + } + } + } + + // fill in the top border + fillEdge(src, dest, 0, 0, src.width, top, edge); + + // fill in the bottom border + fillEdge(src, dest, 0, src.height - bottom, src.width, bottom, edge); + + // fill in the left border + fillEdge(src, dest, 0, top, left, regionH, edge); + + // fill in the right border + fillEdge(src, dest, src.width - right, top, right, regionH, edge); + + return dest; + } + + /** + * Fills a range of pixels (typically at the edge of a raster) with either + * zero values (if edgeOp is EDGE_ZERO_FILL) or the + * corresponding pixel values from the source raster (if edgeOp + * is EDGE_NO_OP). This utility method is called by the + * {@link #fillEdge(Raster, WritableRaster, int, int, int, int, int)} method. + * + * @param src the source raster. + * @param dest the destination raster. + * @param x the x-coordinate of the top left pixel in the range. + * @param y the y-coordinate of the top left pixel in the range. + * @param w the width of the pixel range. + * @param h the height of the pixel range. + * @param edgeOp indicates how to determine the values for the range + * (either {@link #EDGE_ZERO_FILL} or {@link #EDGE_NO_OP}). + */ + private void fillEdge(Raster src, WritableRaster dest, int x, int y, int w, + int h, int edgeOp) + { + if (w <= 0) + return; + if (h <= 0) + return; + if (edgeOp == EDGE_ZERO_FILL) // fill region with zeroes + { + float[] zeros = new float[src.getNumBands() * w * h]; + dest.setPixels(x, y, w, h, zeros); + } + else // copy pixels from source + { + float[] pixels = new float[src.getNumBands() * w * h]; + src.getPixels(x, y, w, h, pixels); + dest.setPixels(x, y, w, h, pixels); + } + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster) + */ + public WritableRaster createCompatibleDestRaster(Raster src) + { + return src.createCompatibleWritableRaster(); + } + + /* (non-Javadoc) + * @see java.awt.image.BufferedImageOp#getBounds2D(java.awt.image.BufferedImage) + */ + public final Rectangle2D getBounds2D(BufferedImage src) + { + return src.getRaster().getBounds(); + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster) + */ + public final Rectangle2D getBounds2D(Raster src) + { + return src.getBounds(); + } + + /** + * Returns the corresponding destination point for a source point. Because + * this is not a geometric operation, the destination and source points will + * be identical. + * + * @param src The source point. + * @param dst The transformed destination point. + * @return The transformed destination point. + */ + public final Point2D getPoint2D(Point2D src, Point2D dst) + { + if (dst == null) return (Point2D)src.clone(); + dst.setLocation(src); + return dst; + } +} diff --git a/openjdk/java/awt/image/DataBuffer.java b/openjdk/java/awt/image/DataBuffer.java new file mode 100644 index 0000000..51dc6db --- /dev/null +++ b/openjdk/java/awt/image/DataBuffer.java @@ -0,0 +1,562 @@ +/* + * Copyright (c) 1997, 2013, 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. + */ + +/* **************************************************************** + ****************************************************************** + ****************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 + *** As an unpublished work pursuant to Title 17 of the United + *** States Code. All rights reserved. + ****************************************************************** + ****************************************************************** + ******************************************************************/ + +package java.awt.image; + +import sun.java2d.StateTrackable.State; +import static sun.java2d.StateTrackable.State.*; +import sun.java2d.StateTrackableDelegate; + +import sun.awt.image.SunWritableRaster; + +import java.lang.annotation.Native; + +/** + * This class exists to wrap one or more data arrays. Each data array in + * the DataBuffer is referred to as a bank. Accessor methods for getting + * and setting elements of the DataBuffer's banks exist with and without + * a bank specifier. The methods without a bank specifier use the default 0th + * bank. The DataBuffer can optionally take an offset per bank, so that + * data in an existing array can be used even if the interesting data + * doesn't start at array location zero. Getting or setting the 0th + * element of a bank, uses the (0+offset)th element of the array. The + * size field specifies how much of the data array is available for + * use. Size + offset for a given bank should never be greater + * than the length of the associated data array. The data type of + * a data buffer indicates the type of the data array(s) and may also + * indicate additional semantics, e.g. storing unsigned 8-bit data + * in elements of a byte array. The data type may be TYPE_UNDEFINED + * or one of the types defined below. Other types may be added in + * the future. Generally, an object of class DataBuffer will be cast down + * to one of its data type specific subclasses to access data type specific + * methods for improved performance. Currently, the Java 2D(tm) API + * image classes use TYPE_BYTE, TYPE_USHORT, TYPE_INT, TYPE_SHORT, + * TYPE_FLOAT, and TYPE_DOUBLE DataBuffers to store image data. + * @see java.awt.image.Raster + * @see java.awt.image.SampleModel + */ +public abstract class DataBuffer { + + /** Tag for unsigned byte data. */ + @Native public static final int TYPE_BYTE = 0; + + /** Tag for unsigned short data. */ + @Native public static final int TYPE_USHORT = 1; + + /** Tag for signed short data. Placeholder for future use. */ + @Native public static final int TYPE_SHORT = 2; + + /** Tag for int data. */ + @Native public static final int TYPE_INT = 3; + + /** Tag for float data. Placeholder for future use. */ + @Native public static final int TYPE_FLOAT = 4; + + /** Tag for double data. Placeholder for future use. */ + @Native public static final int TYPE_DOUBLE = 5; + + /** Tag for undefined data. */ + @Native public static final int TYPE_UNDEFINED = 32; + + /** The data type of this DataBuffer. */ + protected int dataType; + + /** The number of banks in this DataBuffer. */ + protected int banks; + + /** Offset into default (first) bank from which to get the first element. */ + protected int offset; + + /** Usable size of all banks. */ + protected int size; + + /** Offsets into all banks. */ + protected int offsets[]; + + /* The current StateTrackable state. */ + StateTrackableDelegate theTrackable; + + private BufferedImage image; + + /** + * Set a reference to BufferedImage + */ + void setImage( BufferedImage image ) { + this.image = image; + } + + /** + * Invalidate the .NET BITMAP buffer + */ + @ikvm.lang.Internal + public final void markBitmapDirty() { + if( image != null ) { + image.toRaster(); + } + } + + /** Size of the data types indexed by DataType tags defined above. */ + private static final int dataTypeSize[] = {8,16,16,32,32,64}; + + /** Returns the size (in bits) of the data type, given a datatype tag. + * @param type the value of one of the defined datatype tags + * @return the size of the data type + * @throws IllegalArgumentException if type is less than + * zero or greater than {@link #TYPE_DOUBLE} + */ + public static int getDataTypeSize(int type) { + if (type < TYPE_BYTE || type > TYPE_DOUBLE) { + throw new IllegalArgumentException("Unknown data type "+type); + } + return dataTypeSize[type]; + } + + /** + * Constructs a DataBuffer containing one bank of the specified + * data type and size. + * + * @param dataType the data type of this DataBuffer + * @param size the size of the banks + */ + protected DataBuffer(int dataType, int size) { + this(UNTRACKABLE, dataType, size); + } + + /** + * Constructs a DataBuffer containing one bank of the specified + * data type and size with the indicated initial {@link State State}. + * + * @param initialState the initial {@link State State} state of the data + * @param dataType the data type of this DataBuffer + * @param size the size of the banks + * @since 1.7 + */ + DataBuffer(State initialState, + int dataType, int size) + { + this.theTrackable = StateTrackableDelegate.createInstance(initialState); + this.dataType = dataType; + this.banks = 1; + this.size = size; + this.offset = 0; + this.offsets = new int[1]; // init to 0 by new + } + + /** + * Constructs a DataBuffer containing the specified number of + * banks. Each bank has the specified size and an offset of 0. + * + * @param dataType the data type of this DataBuffer + * @param size the size of the banks + * @param numBanks the number of banks in this + * DataBuffer + */ + protected DataBuffer(int dataType, int size, int numBanks) { + this(UNTRACKABLE, dataType, size, numBanks); + } + + /** + * Constructs a DataBuffer containing the specified number of + * banks with the indicated initial {@link State State}. + * Each bank has the specified size and an offset of 0. + * + * @param initialState the initial {@link State State} state of the data + * @param dataType the data type of this DataBuffer + * @param size the size of the banks + * @param numBanks the number of banks in this + * DataBuffer + * @since 1.7 + */ + DataBuffer(State initialState, + int dataType, int size, int numBanks) + { + this.theTrackable = StateTrackableDelegate.createInstance(initialState); + this.dataType = dataType; + this.banks = numBanks; + this.size = size; + this.offset = 0; + this.offsets = new int[banks]; // init to 0 by new + } + + /** + * Constructs a DataBuffer that contains the specified number + * of banks. Each bank has the specified datatype, size and offset. + * + * @param dataType the data type of this DataBuffer + * @param size the size of the banks + * @param numBanks the number of banks in this + * DataBuffer + * @param offset the offset for each bank + */ + protected DataBuffer(int dataType, int size, int numBanks, int offset) { + this(UNTRACKABLE, dataType, size, numBanks, offset); + } + + /** + * Constructs a DataBuffer that contains the specified number + * of banks with the indicated initial {@link State State}. + * Each bank has the specified datatype, size and offset. + * + * @param initialState the initial {@link State State} state of the data + * @param dataType the data type of this DataBuffer + * @param size the size of the banks + * @param numBanks the number of banks in this + * DataBuffer + * @param offset the offset for each bank + * @since 1.7 + */ + DataBuffer(State initialState, + int dataType, int size, int numBanks, int offset) + { + this.theTrackable = StateTrackableDelegate.createInstance(initialState); + this.dataType = dataType; + this.banks = numBanks; + this.size = size; + this.offset = offset; + this.offsets = new int[numBanks]; + for (int i = 0; i < numBanks; i++) { + this.offsets[i] = offset; + } + } + + /** + * Constructs a DataBuffer which contains the specified number + * of banks. Each bank has the specified datatype and size. The + * offset for each bank is specified by its respective entry in + * the offsets array. + * + * @param dataType the data type of this DataBuffer + * @param size the size of the banks + * @param numBanks the number of banks in this + * DataBuffer + * @param offsets an array containing an offset for each bank. + * @throws ArrayIndexOutOfBoundsException if numBanks + * does not equal the length of offsets + */ + protected DataBuffer(int dataType, int size, int numBanks, int offsets[]) { + this(UNTRACKABLE, dataType, size, numBanks, offsets); + } + + /** + * Constructs a DataBuffer which contains the specified number + * of banks with the indicated initial {@link State State}. + * Each bank has the specified datatype and size. The + * offset for each bank is specified by its respective entry in + * the offsets array. + * + * @param initialState the initial {@link State State} state of the data + * @param dataType the data type of this DataBuffer + * @param size the size of the banks + * @param numBanks the number of banks in this + * DataBuffer + * @param offsets an array containing an offset for each bank. + * @throws ArrayIndexOutOfBoundsException if numBanks + * does not equal the length of offsets + * @since 1.7 + */ + DataBuffer(State initialState, + int dataType, int size, int numBanks, int offsets[]) + { + if (numBanks != offsets.length) { + throw new ArrayIndexOutOfBoundsException("Number of banks" + + " does not match number of bank offsets"); + } + this.theTrackable = StateTrackableDelegate.createInstance(initialState); + this.dataType = dataType; + this.banks = numBanks; + this.size = size; + this.offset = offsets[0]; + this.offsets = (int[])offsets.clone(); + } + + /** Returns the data type of this DataBuffer. + * @return the data type of this DataBuffer. + */ + public int getDataType() { + return dataType; + } + + /** Returns the size (in array elements) of all banks. + * @return the size of all banks. + */ + public int getSize() { + return size; + } + + /** Returns the offset of the default bank in array elements. + * @return the offset of the default bank. + */ + public int getOffset() { + return offset; + } + + /** Returns the offsets (in array elements) of all the banks. + * @return the offsets of all banks. + */ + public int[] getOffsets() { + return (int[])offsets.clone(); + } + + /** Returns the number of banks in this DataBuffer. + * @return the number of banks. + */ + public int getNumBanks() { + return banks; + } + + /** + * Returns the requested data array element from the first (default) bank + * as an integer. + * @param i the index of the requested data array element + * @return the data array element at the specified index. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int i) { + return getElem(0,i); + } + + /** + * Returns the requested data array element from the specified bank + * as an integer. + * @param bank the specified bank + * @param i the index of the requested data array element + * @return the data array element at the specified index from the + * specified bank at the specified index. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public abstract int getElem(int bank, int i); + + /** + * Sets the requested data array element in the first (default) bank + * from the given integer. + * @param i the specified index into the data array + * @param val the data to set the element at the specified index in + * the data array + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int i, int val) { + setElem(0,i,val); + } + + /** + * Sets the requested data array element in the specified bank + * from the given integer. + * @param bank the specified bank + * @param i the specified index into the data array + * @param val the data to set the element in the specified bank + * at the specified index in the data array + * @see #getElem(int) + * @see #getElem(int, int) + */ + public abstract void setElem(int bank, int i, int val); + + /** + * Returns the requested data array element from the first (default) bank + * as a float. The implementation in this class is to cast getElem(i) + * to a float. Subclasses may override this method if another + * implementation is needed. + * @param i the index of the requested data array element + * @return a float value representing the data array element at the + * specified index. + * @see #setElemFloat(int, float) + * @see #setElemFloat(int, int, float) + */ + public float getElemFloat(int i) { + return (float)getElem(i); + } + + /** + * Returns the requested data array element from the specified bank + * as a float. The implementation in this class is to cast + * {@link #getElem(int, int)} + * to a float. Subclasses can override this method if another + * implementation is needed. + * @param bank the specified bank + * @param i the index of the requested data array element + * @return a float value representing the data array element from the + * specified bank at the specified index. + * @see #setElemFloat(int, float) + * @see #setElemFloat(int, int, float) + */ + public float getElemFloat(int bank, int i) { + return (float)getElem(bank,i); + } + + /** + * Sets the requested data array element in the first (default) bank + * from the given float. The implementation in this class is to cast + * val to an int and call {@link #setElem(int, int)}. Subclasses + * can override this method if another implementation is needed. + * @param i the specified index + * @param val the value to set the element at the specified index in + * the data array + * @see #getElemFloat(int) + * @see #getElemFloat(int, int) + */ + public void setElemFloat(int i, float val) { + setElem(i,(int)val); + } + + /** + * Sets the requested data array element in the specified bank + * from the given float. The implementation in this class is to cast + * val to an int and call {@link #setElem(int, int)}. Subclasses can + * override this method if another implementation is needed. + * @param bank the specified bank + * @param i the specified index + * @param val the value to set the element in the specified bank at + * the specified index in the data array + * @see #getElemFloat(int) + * @see #getElemFloat(int, int) + */ + public void setElemFloat(int bank, int i, float val) { + setElem(bank,i,(int)val); + } + + /** + * Returns the requested data array element from the first (default) bank + * as a double. The implementation in this class is to cast + * {@link #getElem(int)} + * to a double. Subclasses can override this method if another + * implementation is needed. + * @param i the specified index + * @return a double value representing the element at the specified + * index in the data array. + * @see #setElemDouble(int, double) + * @see #setElemDouble(int, int, double) + */ + public double getElemDouble(int i) { + return (double)getElem(i); + } + + /** + * Returns the requested data array element from the specified bank as + * a double. The implementation in this class is to cast getElem(bank, i) + * to a double. Subclasses may override this method if another + * implementation is needed. + * @param bank the specified bank + * @param i the specified index + * @return a double value representing the element from the specified + * bank at the specified index in the data array. + * @see #setElemDouble(int, double) + * @see #setElemDouble(int, int, double) + */ + public double getElemDouble(int bank, int i) { + return (double)getElem(bank,i); + } + + /** + * Sets the requested data array element in the first (default) bank + * from the given double. The implementation in this class is to cast + * val to an int and call {@link #setElem(int, int)}. Subclasses can + * override this method if another implementation is needed. + * @param i the specified index + * @param val the value to set the element at the specified index + * in the data array + * @see #getElemDouble(int) + * @see #getElemDouble(int, int) + */ + public void setElemDouble(int i, double val) { + setElem(i,(int)val); + } + + /** + * Sets the requested data array element in the specified bank + * from the given double. The implementation in this class is to cast + * val to an int and call {@link #setElem(int, int)}. Subclasses can + * override this method if another implementation is needed. + * @param bank the specified bank + * @param i the specified index + * @param val the value to set the element in the specified bank + * at the specified index of the data array + * @see #getElemDouble(int) + * @see #getElemDouble(int, int) + */ + public void setElemDouble(int bank, int i, double val) { + setElem(bank,i,(int)val); + } + + static int[] toIntArray(Object obj) { + if (obj instanceof int[]) { + return (int[])obj; + } else if (obj == null) { + return null; + } else if (obj instanceof short[]) { + short sdata[] = (short[])obj; + int idata[] = new int[sdata.length]; + for (int i = 0; i < sdata.length; i++) { + idata[i] = (int)sdata[i] & 0xffff; + } + return idata; + } else if (obj instanceof byte[]) { + byte bdata[] = (byte[])obj; + int idata[] = new int[bdata.length]; + for (int i = 0; i < bdata.length; i++) { + idata[i] = 0xff & (int)bdata[i]; + } + return idata; + } + return null; + } + + static { + SunWritableRaster.setDataStealer(new SunWritableRaster.DataStealer() { + public byte[] getData(DataBufferByte dbb, int bank) { + return dbb.bankdata[bank]; + } + + public short[] getData(DataBufferUShort dbus, int bank) { + return dbus.bankdata[bank]; + } + + public int[] getData(DataBufferInt dbi, int bank) { + return dbi.bankdata[bank]; + } + + public StateTrackableDelegate getTrackable(DataBuffer db) { + return db.theTrackable; + } + + public void setTrackable(DataBuffer db, + StateTrackableDelegate trackable) + { + db.theTrackable = trackable; + } + }); + } +} diff --git a/openjdk/java/awt/image/DataBufferByte.java b/openjdk/java/awt/image/DataBufferByte.java new file mode 100644 index 0000000..3dd57c2 --- /dev/null +++ b/openjdk/java/awt/image/DataBufferByte.java @@ -0,0 +1,288 @@ +/* + * Copyright (c) 1997, 2008, 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. + */ + +/* **************************************************************** + ****************************************************************** + ****************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 + *** As an unpublished work pursuant to Title 17 of the United + *** States Code. All rights reserved. + ****************************************************************** + ****************************************************************** + ******************************************************************/ + +package java.awt.image; + +import static sun.java2d.StateTrackable.State.*; + +/** + * This class extends DataBuffer and stores data internally as bytes. + * Values stored in the byte array(s) of this DataBuffer are treated as + * unsigned values. + *

+ * + * Note that some implementations may function more efficiently + * if they can maintain control over how the data for an image is + * stored. + * For example, optimizations such as caching an image in video + * memory require that the implementation track all modifications + * to that data. + * Other implementations may operate better if they can store the + * data in locations other than a Java array. + * To maintain optimum compatibility with various optimizations + * it is best to avoid constructors and methods which expose the + * underlying storage as a Java array, as noted below in the + * documentation for those methods. + * + */ +public final class DataBufferByte extends DataBuffer +{ + /** The default data bank. */ + byte data[]; + + /** All data banks */ + byte bankdata[][]; + + /** + * Constructs a byte-based DataBuffer with a single bank and the + * specified size. + * + * @param size The size of the DataBuffer. + */ + public DataBufferByte(int size) { + super(STABLE, TYPE_BYTE, size); + data = new byte[size]; + bankdata = new byte[1][]; + bankdata[0] = data; + } + + /** + * Constructs a byte based DataBuffer with the specified number of + * banks all of which are the specified size. + * + * @param size The size of the banks in the DataBuffer. + * @param numBanks The number of banks in the aDataBuffer. + */ + public DataBufferByte(int size, int numBanks) { + super(STABLE, TYPE_BYTE, size, numBanks); + bankdata = new byte[numBanks][]; + for (int i= 0; i < numBanks; i++) { + bankdata[i] = new byte[size]; + } + data = bankdata[0]; + } + + /** + * Constructs a byte-based DataBuffer with a single bank using the + * specified array. + * Only the first size elements should be used by accessors of + * this DataBuffer. dataArray must be large enough to + * hold size elements. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The byte array for the DataBuffer. + * @param size The size of the DataBuffer bank. + */ + public DataBufferByte(byte dataArray[], int size) { + super(UNTRACKABLE, TYPE_BYTE, size); + data = dataArray; + bankdata = new byte[1][]; + bankdata[0] = data; + } + + /** + * Constructs a byte-based DataBuffer with a single bank using the + * specified array, size, and offset. dataArray must have at least + * offset + size elements. Only elements offset + * through offset + size - 1 + * should be used by accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The byte array for the DataBuffer. + * @param size The size of the DataBuffer bank. + * @param offset The offset into the dataArray. dataArray + * must have at least offset + size elements. + */ + public DataBufferByte(byte dataArray[], int size, int offset){ + super(UNTRACKABLE, TYPE_BYTE, size, 1, offset); + data = dataArray; + bankdata = new byte[1][]; + bankdata[0] = data; + } + + /** + * Constructs a byte-based DataBuffer with the specified arrays. + * The number of banks is equal to dataArray.length. + * Only the first size elements of each array should be used by + * accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The byte arrays for the DataBuffer. + * @param size The size of the banks in the DataBuffer. + */ + public DataBufferByte(byte dataArray[][], int size) { + super(UNTRACKABLE, TYPE_BYTE, size, dataArray.length); + bankdata = (byte[][]) dataArray.clone(); + data = bankdata[0]; + } + + /** + * Constructs a byte-based DataBuffer with the specified arrays, size, + * and offsets. + * The number of banks is equal to dataArray.length. Each array must + * be at least as large as size + the corresponding offset. + * There must be an entry in the offset array for each dataArray + * entry. For each bank, only elements offset through + * offset + size - 1 should be used by accessors of this + * DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The byte arrays for the DataBuffer. + * @param size The size of the banks in the DataBuffer. + * @param offsets The offsets into each array. + */ + public DataBufferByte(byte dataArray[][], int size, int offsets[]) { + super(UNTRACKABLE, TYPE_BYTE, size, dataArray.length, offsets); + bankdata = (byte[][]) dataArray.clone(); + data = bankdata[0]; + } + + /** + * Returns the default (first) byte data array. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @return The first byte data array. + */ + public byte[] getData() { + theTrackable.setUntrackable(); + return data; + } + + /** + * Returns the data array for the specified bank. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param bank The bank whose data array you want to get. + * @return The data array for the specified bank. + */ + public byte[] getData(int bank) { + theTrackable.setUntrackable(); + return bankdata[bank]; + } + + /** + * Returns the data arrays for all banks. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @return All of the data arrays. + */ + public byte[][] getBankData() { + theTrackable.setUntrackable(); + return (byte[][]) bankdata.clone(); + } + + /** + * Returns the requested data array element from the first (default) bank. + * + * @param i The data array element you want to get. + * @return The requested data array element as an integer. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int i) { + return (int)(data[i+offset]) & 0xff; + } + + /** + * Returns the requested data array element from the specified bank. + * + * @param bank The bank from which you want to get a data array element. + * @param i The data array element you want to get. + * @return The requested data array element as an integer. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int bank, int i) { + return (int)(bankdata[bank][i+offsets[bank]]) & 0xff; + } + + /** + * Sets the requested data array element in the first (default) bank + * to the specified value. + * + * @param i The data array element you want to set. + * @param val The integer value to which you want to set the data array element. + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int i, int val) { + markBitmapDirty(); + data[i+offset] = (byte)val; + theTrackable.markDirty(); + } + + /** + * Sets the requested data array element in the specified bank + * from the given integer. + * @param bank The bank in which you want to set the data array element. + * @param i The data array element you want to set. + * @param val The integer value to which you want to set the specified data array element. + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int bank, int i, int val) { + markBitmapDirty(); + bankdata[bank][i+offsets[bank]] = (byte)val; + theTrackable.markDirty(); + } +} diff --git a/openjdk/java/awt/image/DataBufferDouble.java b/openjdk/java/awt/image/DataBufferDouble.java new file mode 100644 index 0000000..713c975 --- /dev/null +++ b/openjdk/java/awt/image/DataBufferDouble.java @@ -0,0 +1,409 @@ +/* + * Copyright (c) 2000, 2007, 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 java.awt.image; + +import static sun.java2d.StateTrackable.State.*; + +/** + * This class extends DataBuffer and stores data internally + * in double form. + *

+ * + * Note that some implementations may function more efficiently + * if they can maintain control over how the data for an image is + * stored. + * For example, optimizations such as caching an image in video + * memory require that the implementation track all modifications + * to that data. + * Other implementations may operate better if they can store the + * data in locations other than a Java array. + * To maintain optimum compatibility with various optimizations + * it is best to avoid constructors and methods which expose the + * underlying storage as a Java array as noted below in the + * documentation for those methods. + * + * + * @since 1.4 + */ + +public final class DataBufferDouble extends DataBuffer { + + /** The array of data banks. */ + double bankdata[][]; + + /** A reference to the default data bank. */ + double data[]; + + /** + * Constructs a double-based DataBuffer + * with a specified size. + * + * @param size The number of elements in the DataBuffer. + */ + public DataBufferDouble(int size) { + super(STABLE, TYPE_DOUBLE, size); + data = new double[size]; + bankdata = new double[1][]; + bankdata[0] = data; + } + + /** + * Constructs a double-based DataBuffer + * with a specified number of banks, all of which are of a + * specified size. + * + * @param size The number of elements in each bank of the + * DataBuffer. + * @param numBanks The number of banks in the DataBuffer. + */ + public DataBufferDouble(int size, int numBanks) { + super(STABLE, TYPE_DOUBLE, size, numBanks); + bankdata = new double[numBanks][]; + for (int i= 0; i < numBanks; i++) { + bankdata[i] = new double[size]; + } + data = bankdata[0]; + } + + /** + * Constructs a double-based DataBuffer + * with the specified data array. Only the first + * size elements are available for use by this + * DataBuffer. The array must be large enough to + * hold size elements. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray An array of doubles to be used as the + * first and only bank of this DataBuffer. + * @param size The number of elements of the array to be used. + */ + public DataBufferDouble(double dataArray[], int size) { + super(UNTRACKABLE, TYPE_DOUBLE, size); + data = dataArray; + bankdata = new double[1][]; + bankdata[0] = data; + } + + /** + * Constructs a double-based DataBuffer + * with the specified data array. Only the elements between + * offset and offset + size - 1 are + * available for use by this DataBuffer. The array + * must be large enough to hold offset + size elements. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray An array of doubles to be used as the + * first and only bank of this DataBuffer. + * @param size The number of elements of the array to be used. + * @param offset The offset of the first element of the array + * that will be used. + */ + public DataBufferDouble(double dataArray[], int size, int offset) { + super(UNTRACKABLE, TYPE_DOUBLE, size, 1, offset); + data = dataArray; + bankdata = new double[1][]; + bankdata[0] = data; + } + + /** + * Constructs a double-based DataBuffer + * with the specified data arrays. Only the first + * size elements of each array are available for use + * by this DataBuffer. The number of banks will be + * equal to dataArray.length. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray An array of arrays of doubles to be + * used as the banks of this DataBuffer. + * @param size The number of elements of each array to be used. + */ + public DataBufferDouble(double dataArray[][], int size) { + super(UNTRACKABLE, TYPE_DOUBLE, size, dataArray.length); + bankdata = (double[][]) dataArray.clone(); + data = bankdata[0]; + } + + /** + * Constructs a double-based DataBuffer + * with the specified data arrays, size, and per-bank offsets. + * The number of banks is equal to dataArray.length. Each array + * must be at least as large as size plus the + * corresponding offset. There must be an entry in the + * offsets array for each data array. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray An array of arrays of doubles to be + * used as the banks of this DataBuffer. + * @param size The number of elements of each array to be used. + * @param offsets An array of integer offsets, one for each bank. + */ + public DataBufferDouble(double dataArray[][], int size, int offsets[]) { + super(UNTRACKABLE, TYPE_DOUBLE, size, dataArray.length, offsets); + bankdata = (double[][]) dataArray.clone(); + data = bankdata[0]; + } + + /** + * Returns the default (first) double data array. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @return the first double data array. + */ + public double[] getData() { + theTrackable.setUntrackable(); + return data; + } + + /** + * Returns the data array for the specified bank. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param bank the data array + * @return the data array specified by bank. + */ + public double[] getData(int bank) { + theTrackable.setUntrackable(); + return bankdata[bank]; + } + + /** + * Returns the data array for all banks. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @return all data arrays from this data buffer. + */ + public double[][] getBankData() { + theTrackable.setUntrackable(); + return (double[][]) bankdata.clone(); + } + + /** + * Returns the requested data array element from the first + * (default) bank as an int. + * + * @param i The desired data array element. + * @return The data entry as an int. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int i) { + return (int)(data[i+offset]); + } + + /** + * Returns the requested data array element from the specified + * bank as an int. + * + * @param bank The bank number. + * @param i The desired data array element. + * + * @return The data entry as an int. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int bank, int i) { + return (int)(bankdata[bank][i+offsets[bank]]); + } + + /** + * Sets the requested data array element in the first (default) + * bank to the given int. + * + * @param i The desired data array element. + * @param val The value to be set. + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int i, int val) { + markBitmapDirty(); + data[i+offset] = (double)val; + theTrackable.markDirty(); + } + + /** + * Sets the requested data array element in the specified bank + * to the given int. + * + * @param bank The bank number. + * @param i The desired data array element. + * @param val The value to be set. + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int bank, int i, int val) { + markBitmapDirty(); + bankdata[bank][i+offsets[bank]] = (double)val; + theTrackable.markDirty(); + } + + /** + * Returns the requested data array element from the first + * (default) bank as a float. + * + * @param i The desired data array element. + * + * @return The data entry as a float. + * @see #setElemFloat(int, float) + * @see #setElemFloat(int, int, float) + */ + public float getElemFloat(int i) { + return (float)data[i+offset]; + } + + /** + * Returns the requested data array element from the specified + * bank as a float. + * + * @param bank The bank number. + * @param i The desired data array element. + * + * @return The data entry as a float. + * @see #setElemFloat(int, float) + * @see #setElemFloat(int, int, float) + */ + public float getElemFloat(int bank, int i) { + return (float)bankdata[bank][i+offsets[bank]]; + } + + /** + * Sets the requested data array element in the first (default) + * bank to the given float. + * + * @param i The desired data array element. + * @param val The value to be set. + * @see #getElemFloat(int) + * @see #getElemFloat(int, int) + */ + public void setElemFloat(int i, float val) { + markBitmapDirty(); + data[i+offset] = (double)val; + theTrackable.markDirty(); + } + + /** + * Sets the requested data array element in the specified bank to + * the given float. + * + * @param bank The bank number. + * @param i The desired data array element. + * @param val The value to be set. + * @see #getElemFloat(int) + * @see #getElemFloat(int, int) + */ + public void setElemFloat(int bank, int i, float val) { + markBitmapDirty(); + bankdata[bank][i+offsets[bank]] = (double)val; + theTrackable.markDirty(); + } + + /** + * Returns the requested data array element from the first + * (default) bank as a double. + * + * @param i The desired data array element. + * + * @return The data entry as a double. + * @see #setElemDouble(int, double) + * @see #setElemDouble(int, int, double) + */ + public double getElemDouble(int i) { + return data[i+offset]; + } + + /** + * Returns the requested data array element from the specified + * bank as a double. + * + * @param bank The bank number. + * @param i The desired data array element. + * + * @return The data entry as a double. + * @see #setElemDouble(int, double) + * @see #setElemDouble(int, int, double) + */ + public double getElemDouble(int bank, int i) { + return bankdata[bank][i+offsets[bank]]; + } + + /** + * Sets the requested data array element in the first (default) + * bank to the given double. + * + * @param i The desired data array element. + * @param val The value to be set. + * @see #getElemDouble(int) + * @see #getElemDouble(int, int) + */ + public void setElemDouble(int i, double val) { + markBitmapDirty(); + data[i+offset] = val; + theTrackable.markDirty(); + } + + /** + * Sets the requested data array element in the specified bank to + * the given double. + * + * @param bank The bank number. + * @param i The desired data array element. + * @param val The value to be set. + * @see #getElemDouble(int) + * @see #getElemDouble(int, int) + */ + public void setElemDouble(int bank, int i, double val) { + markBitmapDirty(); + bankdata[bank][i+offsets[bank]] = val; + theTrackable.markDirty(); + } +} diff --git a/openjdk/java/awt/image/DataBufferFloat.java b/openjdk/java/awt/image/DataBufferFloat.java new file mode 100644 index 0000000..3a87e86 --- /dev/null +++ b/openjdk/java/awt/image/DataBufferFloat.java @@ -0,0 +1,412 @@ +/* + * Copyright (c) 2000, 2007, 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 java.awt.image; + +import static sun.java2d.StateTrackable.State.*; + +/** + * This class extends DataBuffer and stores data internally + * in float form. + *

+ * + * Note that some implementations may function more efficiently + * if they can maintain control over how the data for an image is + * stored. + * For example, optimizations such as caching an image in video + * memory require that the implementation track all modifications + * to that data. + * Other implementations may operate better if they can store the + * data in locations other than a Java array. + * To maintain optimum compatibility with various optimizations + * it is best to avoid constructors and methods which expose the + * underlying storage as a Java array as noted below in the + * documentation for those methods. + * + * + * @since 1.4 + */ + +public final class DataBufferFloat extends DataBuffer { + + /** The array of data banks. */ + float bankdata[][]; + + /** A reference to the default data bank. */ + float data[]; + + /** + * Constructs a float-based DataBuffer + * with a specified size. + * + * @param size The number of elements in the DataBuffer. + */ + public DataBufferFloat(int size) { + super(STABLE, TYPE_FLOAT, size); + data = new float[size]; + bankdata = new float[1][]; + bankdata[0] = data; + } + + /** + * Constructs a float-based DataBuffer + * with a specified number of banks, all of which are of a + * specified size. + * + * @param size The number of elements in each bank of the + * DataBuffer. + * @param numBanks The number of banks in the + * DataBuffer. + */ + public DataBufferFloat(int size, int numBanks) { + super(STABLE, TYPE_FLOAT, size, numBanks); + bankdata = new float[numBanks][]; + for (int i= 0; i < numBanks; i++) { + bankdata[i] = new float[size]; + } + data = bankdata[0]; + } + + /** + * Constructs a float-based DataBuffer + * with the specified data array. Only the first + * size elements are available for use by this + * DataBuffer. The array must be large enough to + * hold size elements. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray An array of floats to be used as the + * first and only bank of this DataBuffer. + * @param size The number of elements of the array to be used. + */ + public DataBufferFloat(float dataArray[], int size) { + super(UNTRACKABLE, TYPE_FLOAT, size); + data = dataArray; + bankdata = new float[1][]; + bankdata[0] = data; + } + + /** + * Constructs a float-based DataBuffer + * with the specified data array. Only the elements between + * offset and offset + size - 1 are + * available for use by this DataBuffer. The array + * must be large enough to hold offset + size + * elements. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray An array of floats to be used as the + * first and only bank of this DataBuffer. + * @param size The number of elements of the array to be used. + * @param offset The offset of the first element of the array + * that will be used. + */ + public DataBufferFloat(float dataArray[], int size, int offset) { + super(UNTRACKABLE, TYPE_FLOAT, size, 1, offset); + data = dataArray; + bankdata = new float[1][]; + bankdata[0] = data; + } + + /** + * Constructs a float-based DataBuffer + * with the specified data arrays. Only the first + * size elements of each array are available for use + * by this DataBuffer. The number of banks will be + * equal to dataArray.length. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray An array of arrays of floats to be + * used as the banks of this DataBuffer. + * @param size The number of elements of each array to be used. + */ + public DataBufferFloat(float dataArray[][], int size) { + super(UNTRACKABLE, TYPE_FLOAT, size, dataArray.length); + bankdata = (float[][]) dataArray.clone(); + data = bankdata[0]; + } + + /** + * Constructs a float-based DataBuffer + * with the specified data arrays, size, and per-bank offsets. + * The number of banks is equal to dataArray.length. + * Each array must be at least as large as size plus the + * corresponding offset. There must be an entry in the offsets + * array for each data array. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray An array of arrays of floats to be + * used as the banks of this DataBuffer. + * @param size The number of elements of each array to be used. + * @param offsets An array of integer offsets, one for each bank. + */ + public DataBufferFloat(float dataArray[][], int size, int offsets[]) { + super(UNTRACKABLE, TYPE_FLOAT, size,dataArray.length, offsets); + bankdata = (float[][]) dataArray.clone(); + data = bankdata[0]; + } + + /** + * Returns the default (first) float data array. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @return the first float data array. + */ + public float[] getData() { + theTrackable.setUntrackable(); + return data; + } + + /** + * Returns the data array for the specified bank. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param bank the data array + * @return the data array specified by bank. + */ + public float[] getData(int bank) { + theTrackable.setUntrackable(); + return bankdata[bank]; + } + + /** + * Returns the data array for all banks. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @return all data arrays for this data buffer. + */ + public float[][] getBankData() { + theTrackable.setUntrackable(); + return (float[][]) bankdata.clone(); + } + + /** + * Returns the requested data array element from the first + * (default) bank as an int. + * + * @param i The desired data array element. + * + * @return The data entry as an int. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int i) { + return (int)(data[i+offset]); + } + + /** + * Returns the requested data array element from the specified + * bank as an int. + * + * @param bank The bank number. + * @param i The desired data array element. + * + * @return The data entry as an int. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int bank, int i) { + return (int)(bankdata[bank][i+offsets[bank]]); + } + + /** + * Sets the requested data array element in the first (default) + * bank to the given int. + * + * @param i The desired data array element. + * @param val The value to be set. + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int i, int val) { + markBitmapDirty(); + data[i+offset] = (float)val; + theTrackable.markDirty(); + } + + /** + * Sets the requested data array element in the specified bank to + * the given int. + * + * @param bank The bank number. + * @param i The desired data array element. + * @param val The value to be set. + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int bank, int i, int val) { + markBitmapDirty(); + bankdata[bank][i+offsets[bank]] = (float)val; + theTrackable.markDirty(); + } + + /** + * Returns the requested data array element from the first + * (default) bank as a float. + * + * @param i The desired data array element. + * + * @return The data entry as a float. + * @see #setElemFloat(int, float) + * @see #setElemFloat(int, int, float) + */ + public float getElemFloat(int i) { + return data[i+offset]; + } + + /** + * Returns the requested data array element from the specified + * bank as a float. + * + * @param bank The bank number. + * @param i The desired data array element. + * + * @return The data entry as a float. + * @see #setElemFloat(int, float) + * @see #setElemFloat(int, int, float) + */ + public float getElemFloat(int bank, int i) { + return bankdata[bank][i+offsets[bank]]; + } + + /** + * Sets the requested data array element in the first (default) + * bank to the given float. + * + * @param i The desired data array element. + * @param val The value to be set. + * @see #getElemFloat(int) + * @see #getElemFloat(int, int) + */ + public void setElemFloat(int i, float val) { + markBitmapDirty(); + data[i+offset] = val; + theTrackable.markDirty(); + } + + /** + * Sets the requested data array element in the specified bank to + * the given float. + * + * @param bank The bank number. + * @param i The desired data array element. + * @param val The value to be set. + * @see #getElemFloat(int) + * @see #getElemFloat(int, int) + */ + public void setElemFloat(int bank, int i, float val) { + markBitmapDirty(); + bankdata[bank][i+offsets[bank]] = val; + theTrackable.markDirty(); + } + + /** + * Returns the requested data array element from the first + * (default) bank as a double. + * + * @param i The desired data array element. + * + * @return The data entry as a double. + * @see #setElemDouble(int, double) + * @see #setElemDouble(int, int, double) + */ + public double getElemDouble(int i) { + return (double)data[i+offset]; + } + + /** + * Returns the requested data array element from the specified + * bank as a double. + * + * @param bank The bank number. + * @param i The desired data array element. + * + * @return The data entry as a double. + * @see #setElemDouble(int, double) + * @see #setElemDouble(int, int, double) + */ + public double getElemDouble(int bank, int i) { + return (double)bankdata[bank][i+offsets[bank]]; + } + + /** + * Sets the requested data array element in the first (default) + * bank to the given double. + * + * @param i The desired data array element. + * @param val The value to be set. + * @see #getElemDouble(int) + * @see #getElemDouble(int, int) + */ + public void setElemDouble(int i, double val) { + markBitmapDirty(); + data[i+offset] = (float)val; + theTrackable.markDirty(); + } + + /** + * Sets the requested data array element in the specified bank to + * the given double. + * + * @param bank The bank number. + * @param i The desired data array element. + * @param val The value to be set. + * @see #getElemDouble(int) + * @see #getElemDouble(int, int) + */ + public void setElemDouble(int bank, int i, double val) { + markBitmapDirty(); + bankdata[bank][i+offsets[bank]] = (float)val; + theTrackable.markDirty(); + } +} diff --git a/openjdk/java/awt/image/DataBufferInt.java b/openjdk/java/awt/image/DataBufferInt.java new file mode 100644 index 0000000..32d6ce2 --- /dev/null +++ b/openjdk/java/awt/image/DataBufferInt.java @@ -0,0 +1,286 @@ +/* + * Copyright (c) 1997, 2008, 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. + */ + +/* **************************************************************** + ****************************************************************** + ****************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 + *** As an unpublished work pursuant to Title 17 of the United + *** States Code. All rights reserved. + ****************************************************************** + ****************************************************************** + ******************************************************************/ + +package java.awt.image; + +import static sun.java2d.StateTrackable.State.*; + +/** + * This class extends DataBuffer and stores data internally + * as integers. + *

+ * + * Note that some implementations may function more efficiently + * if they can maintain control over how the data for an image is + * stored. + * For example, optimizations such as caching an image in video + * memory require that the implementation track all modifications + * to that data. + * Other implementations may operate better if they can store the + * data in locations other than a Java array. + * To maintain optimum compatibility with various optimizations + * it is best to avoid constructors and methods which expose the + * underlying storage as a Java array as noted below in the + * documentation for those methods. + * + */ +public final class DataBufferInt extends DataBuffer +{ + /** The default data bank. */ + int data[]; + + /** All data banks */ + int bankdata[][]; + + /** + * Constructs an integer-based DataBuffer with a single bank + * and the specified size. + * + * @param size The size of the DataBuffer. + */ + public DataBufferInt(int size) { + super(STABLE, TYPE_INT, size); + data = new int[size]; + bankdata = new int[1][]; + bankdata[0] = data; + } + + /** + * Constructs an integer-based DataBuffer with the specified number of + * banks, all of which are the specified size. + * + * @param size The size of the banks in the DataBuffer. + * @param numBanks The number of banks in the aDataBuffer. + */ + public DataBufferInt(int size, int numBanks) { + super(STABLE, TYPE_INT, size, numBanks); + bankdata = new int[numBanks][]; + for (int i= 0; i < numBanks; i++) { + bankdata[i] = new int[size]; + } + data = bankdata[0]; + } + + /** + * Constructs an integer-based DataBuffer with a single bank using the + * specified array. + * Only the first size elements should be used by accessors of + * this DataBuffer. dataArray must be large enough to + * hold size elements. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The integer array for the DataBuffer. + * @param size The size of the DataBuffer bank. + */ + public DataBufferInt(int dataArray[], int size) { + super(UNTRACKABLE, TYPE_INT, size); + data = dataArray; + bankdata = new int[1][]; + bankdata[0] = data; + } + + /** + * Constructs an integer-based DataBuffer with a single bank using the + * specified array, size, and offset. dataArray must have at least + * offset + size elements. Only elements offset + * through offset + size - 1 + * should be used by accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The integer array for the DataBuffer. + * @param size The size of the DataBuffer bank. + * @param offset The offset into the dataArray. + */ + public DataBufferInt(int dataArray[], int size, int offset) { + super(UNTRACKABLE, TYPE_INT, size, 1, offset); + data = dataArray; + bankdata = new int[1][]; + bankdata[0] = data; + } + + /** + * Constructs an integer-based DataBuffer with the specified arrays. + * The number of banks will be equal to dataArray.length. + * Only the first size elements of each array should be used by + * accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The integer arrays for the DataBuffer. + * @param size The size of the banks in the DataBuffer. + */ + public DataBufferInt(int dataArray[][], int size) { + super(UNTRACKABLE, TYPE_INT, size, dataArray.length); + bankdata = (int [][]) dataArray.clone(); + data = bankdata[0]; + } + + /** + * Constructs an integer-based DataBuffer with the specified arrays, size, + * and offsets. + * The number of banks is equal to dataArray.length. Each array must + * be at least as large as size + the corresponding offset. There must + * be an entry in the offset array for each dataArray entry. For each + * bank, only elements offset through + * offset + size - 1 should be + * used by accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The integer arrays for the DataBuffer. + * @param size The size of the banks in the DataBuffer. + * @param offsets The offsets into each array. + */ + public DataBufferInt(int dataArray[][], int size, int offsets[]) { + super(UNTRACKABLE, TYPE_INT, size, dataArray.length, offsets); + bankdata = (int [][]) dataArray.clone(); + data = bankdata[0]; + } + + /** + * Returns the default (first) int data array in DataBuffer. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @return The first integer data array. + */ + public int[] getData() { + theTrackable.setUntrackable(); + return data; + } + + /** + * Returns the data array for the specified bank. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param bank The bank whose data array you want to get. + * @return The data array for the specified bank. + */ + public int[] getData(int bank) { + theTrackable.setUntrackable(); + return bankdata[bank]; + } + + /** + * Returns the data arrays for all banks. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @return All of the data arrays. + */ + public int[][] getBankData() { + theTrackable.setUntrackable(); + return (int [][]) bankdata.clone(); + } + + /** + * Returns the requested data array element from the first (default) bank. + * + * @param i The data array element you want to get. + * @return The requested data array element as an integer. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int i) { + return data[i+offset]; + } + + /** + * Returns the requested data array element from the specified bank. + * + * @param bank The bank from which you want to get a data array element. + * @param i The data array element you want to get. + * @return The requested data array element as an integer. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int bank, int i) { + return bankdata[bank][i+offsets[bank]]; + } + + /** + * Sets the requested data array element in the first (default) bank + * to the specified value. + * + * @param i The data array element you want to set. + * @param val The integer value to which you want to set the data array element. + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int i, int val) { + markBitmapDirty(); + data[i+offset] = val; + theTrackable.markDirty(); + } + + /** + * Sets the requested data array element in the specified bank + * to the integer value i. + * @param bank The bank in which you want to set the data array element. + * @param i The data array element you want to set. + * @param val The integer value to which you want to set the specified data array element. + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int bank, int i, int val) { + markBitmapDirty(); + bankdata[bank][i+offsets[bank]] = (int)val; + theTrackable.markDirty(); + } +} diff --git a/openjdk/java/awt/image/DataBufferShort.java b/openjdk/java/awt/image/DataBufferShort.java new file mode 100644 index 0000000..4cdaaf3 --- /dev/null +++ b/openjdk/java/awt/image/DataBufferShort.java @@ -0,0 +1,285 @@ +/* + * Copyright (c) 1997, 2008, 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. + */ + +/* **************************************************************** + ****************************************************************** + ****************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 + *** As an unpublished work pursuant to Title 17 of the United + *** States Code. All rights reserved. + ****************************************************************** + ****************************************************************** + ******************************************************************/ + +package java.awt.image; + +import static sun.java2d.StateTrackable.State.*; + +/** + * This class extends DataBuffer and stores data internally as shorts. + *

+ * + * Note that some implementations may function more efficiently + * if they can maintain control over how the data for an image is + * stored. + * For example, optimizations such as caching an image in video + * memory require that the implementation track all modifications + * to that data. + * Other implementations may operate better if they can store the + * data in locations other than a Java array. + * To maintain optimum compatibility with various optimizations + * it is best to avoid constructors and methods which expose the + * underlying storage as a Java array as noted below in the + * documentation for those methods. + * + */ +public final class DataBufferShort extends DataBuffer +{ + /** The default data bank. */ + short data[]; + + /** All data banks */ + short bankdata[][]; + + /** + * Constructs a short-based DataBuffer with a single bank and the + * specified size. + * + * @param size The size of the DataBuffer. + */ + public DataBufferShort(int size) { + super(STABLE, TYPE_SHORT,size); + data = new short[size]; + bankdata = new short[1][]; + bankdata[0] = data; + } + + /** + * Constructs a short-based DataBuffer with the specified number of + * banks all of which are the specified size. + * + * @param size The size of the banks in the DataBuffer. + * @param numBanks The number of banks in the aDataBuffer. + */ + public DataBufferShort(int size, int numBanks) { + super(STABLE, TYPE_SHORT,size,numBanks); + bankdata = new short[numBanks][]; + for (int i= 0; i < numBanks; i++) { + bankdata[i] = new short[size]; + } + data = bankdata[0]; + } + + /** + * Constructs a short-based DataBuffer with a single bank using the + * specified array. + * Only the first size elements should be used by accessors of + * this DataBuffer. dataArray must be large enough to + * hold size elements. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The short array for the DataBuffer. + * @param size The size of the DataBuffer bank. + */ + public DataBufferShort(short dataArray[], int size) { + super(UNTRACKABLE, TYPE_SHORT, size); + data = dataArray; + bankdata = new short[1][]; + bankdata[0] = data; + } + + /** + * Constructs a short-based DataBuffer with a single bank using the + * specified array, size, and offset. dataArray must have at least + * offset + size elements. Only elements offset + * through offset + size - 1 + * should be used by accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The short array for the DataBuffer. + * @param size The size of the DataBuffer bank. + * @param offset The offset into the dataArray. + */ + public DataBufferShort(short dataArray[], int size, int offset) { + super(UNTRACKABLE, TYPE_SHORT, size, 1, offset); + data = dataArray; + bankdata = new short[1][]; + bankdata[0] = data; + } + + /** + * Constructs a short-based DataBuffer with the specified arrays. + * The number of banks will be equal to dataArray.length. + * Only the first size elements of each array should be used by + * accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The short arrays for the DataBuffer. + * @param size The size of the banks in the DataBuffer. + */ + public DataBufferShort(short dataArray[][], int size) { + super(UNTRACKABLE, TYPE_SHORT, size, dataArray.length); + bankdata = (short[][]) dataArray.clone(); + data = bankdata[0]; + } + + /** + * Constructs a short-based DataBuffer with the specified arrays, size, + * and offsets. + * The number of banks is equal to dataArray.length. Each array must + * be at least as large as size + the corresponding offset. There must + * be an entry in the offset array for each dataArray entry. For each + * bank, only elements offset through + * offset + size - 1 should be + * used by accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The short arrays for the DataBuffer. + * @param size The size of the banks in the DataBuffer. + * @param offsets The offsets into each array. + */ + public DataBufferShort(short dataArray[][], int size, int offsets[]) { + super(UNTRACKABLE, TYPE_SHORT, size, dataArray.length, offsets); + bankdata = (short[][]) dataArray.clone(); + data = bankdata[0]; + } + + /** + * Returns the default (first) byte data array. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @return The first short data array. + */ + public short[] getData() { + theTrackable.setUntrackable(); + return data; + } + + /** + * Returns the data array for the specified bank. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param bank The bank whose data array you want to get. + * @return The data array for the specified bank. + */ + public short[] getData(int bank) { + theTrackable.setUntrackable(); + return bankdata[bank]; + } + + /** + * Returns the data arrays for all banks. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @return All of the data arrays. + */ + public short[][] getBankData() { + theTrackable.setUntrackable(); + return (short[][]) bankdata.clone(); + } + + /** + * Returns the requested data array element from the first (default) bank. + * + * @param i The data array element you want to get. + * @return The requested data array element as an integer. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int i) { + return (int)(data[i+offset]); + } + + /** + * Returns the requested data array element from the specified bank. + * + * @param bank The bank from which you want to get a data array element. + * @param i The data array element you want to get. + * @return The requested data array element as an integer. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int bank, int i) { + return (int)(bankdata[bank][i+offsets[bank]]); + } + + /** + * Sets the requested data array element in the first (default) bank + * to the specified value. + * + * @param i The data array element you want to set. + * @param val The integer value to which you want to set the data array element. + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int i, int val) { + markBitmapDirty(); + data[i+offset] = (short)val; + theTrackable.markDirty(); + } + + /** + * Sets the requested data array element in the specified bank + * from the given integer. + * @param bank The bank in which you want to set the data array element. + * @param i The data array element you want to set. + * @param val The integer value to which you want to set the specified data array element. + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int bank, int i, int val) { + markBitmapDirty(); + bankdata[bank][i+offsets[bank]] = (short)val; + theTrackable.markDirty(); + } +} diff --git a/openjdk/java/awt/image/DataBufferUShort.java b/openjdk/java/awt/image/DataBufferUShort.java new file mode 100644 index 0000000..e1cb1ba --- /dev/null +++ b/openjdk/java/awt/image/DataBufferUShort.java @@ -0,0 +1,320 @@ +/* + * Copyright (c) 1997, 2008, 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. + */ + +/* **************************************************************** + ****************************************************************** + ****************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 + *** As an unpublished work pursuant to Title 17 of the United + *** States Code. All rights reserved. + ****************************************************************** + ****************************************************************** + ******************************************************************/ + +package java.awt.image; + +import static sun.java2d.StateTrackable.State.*; + +/** + * This class extends DataBuffer and stores data internally as + * shorts. Values stored in the short array(s) of this DataBuffer + * are treated as unsigned values. + *

+ * + * Note that some implementations may function more efficiently + * if they can maintain control over how the data for an image is + * stored. + * For example, optimizations such as caching an image in video + * memory require that the implementation track all modifications + * to that data. + * Other implementations may operate better if they can store the + * data in locations other than a Java array. + * To maintain optimum compatibility with various optimizations + * it is best to avoid constructors and methods which expose the + * underlying storage as a Java array as noted below in the + * documentation for those methods. + * + */ +public final class DataBufferUShort extends DataBuffer +{ + /** The default data bank. */ + short data[]; + + /** All data banks */ + short bankdata[][]; + + /** + * Constructs an unsigned-short based DataBuffer with a single bank and the + * specified size. + * + * @param size The size of the DataBuffer. + */ + public DataBufferUShort(int size) { + super(STABLE, TYPE_USHORT, size); + data = new short[size]; + bankdata = new short[1][]; + bankdata[0] = data; + } + + /** + * Constructs an unsigned-short based DataBuffer with the specified number of + * banks, all of which are the specified size. + * + * @param size The size of the banks in the DataBuffer. + * @param numBanks The number of banks in the aDataBuffer. + */ + public DataBufferUShort(int size, int numBanks) { + super(STABLE, TYPE_USHORT, size, numBanks); + bankdata = new short[numBanks][]; + for (int i= 0; i < numBanks; i++) { + bankdata[i] = new short[size]; + } + data = bankdata[0]; + } + + /** + * Constructs an unsigned-short based DataBuffer with a single bank + * using the specified array. + * Only the first size elements should be used by accessors of + * this DataBuffer. dataArray must be large enough to + * hold size elements. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The unsigned-short array for the DataBuffer. + * @param size The size of the DataBuffer bank. + */ + public DataBufferUShort(short dataArray[], int size) { + super(UNTRACKABLE, TYPE_USHORT, size); + if (dataArray == null) { + throw new NullPointerException("dataArray is null"); + } + data = dataArray; + bankdata = new short[1][]; + bankdata[0] = data; + } + + /** + * Constructs an unsigned-short based DataBuffer with a single bank + * using the specified array, size, and offset. dataArray must have at + * least offset + size elements. Only elements + * offset through offset + size - 1 should + * be used by accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The unsigned-short array for the DataBuffer. + * @param size The size of the DataBuffer bank. + * @param offset The offset into the dataArray. + */ + public DataBufferUShort(short dataArray[], int size, int offset) { + super(UNTRACKABLE, TYPE_USHORT, size, 1, offset); + if (dataArray == null) { + throw new NullPointerException("dataArray is null"); + } + if ((size+offset) > dataArray.length) { + throw new IllegalArgumentException("Length of dataArray is less "+ + " than size+offset."); + } + data = dataArray; + bankdata = new short[1][]; + bankdata[0] = data; + } + + /** + * Constructs an unsigned-short based DataBuffer with the specified arrays. + * The number of banks will be equal to dataArray.length. + * Only the first size elements of each array should be used by + * accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The unsigned-short arrays for the DataBuffer. + * @param size The size of the banks in the DataBuffer. + */ + public DataBufferUShort(short dataArray[][], int size) { + super(UNTRACKABLE, TYPE_USHORT, size, dataArray.length); + if (dataArray == null) { + throw new NullPointerException("dataArray is null"); + } + for (int i=0; i < dataArray.length; i++) { + if (dataArray[i] == null) { + throw new NullPointerException("dataArray["+i+"] is null"); + } + } + + bankdata = (short[][]) dataArray.clone(); + data = bankdata[0]; + } + + /** + * Constructs an unsigned-short based DataBuffer with specified arrays, + * size, and offsets. + * The number of banks is equal to dataArray.length. Each array must + * be at least as large as size + the corresponding offset. There must + * be an entry in the offset array for each dataArray entry. For each + * bank, only elements offset through + * offset + size - 1 should be + * used by accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The unsigned-short arrays for the DataBuffer. + * @param size The size of the banks in the DataBuffer. + * @param offsets The offsets into each array. + */ + public DataBufferUShort(short dataArray[][], int size, int offsets[]) { + super(UNTRACKABLE, TYPE_USHORT, size, dataArray.length, offsets); + if (dataArray == null) { + throw new NullPointerException("dataArray is null"); + } + for (int i=0; i < dataArray.length; i++) { + if (dataArray[i] == null) { + throw new NullPointerException("dataArray["+i+"] is null"); + } + if ((size+offsets[i]) > dataArray[i].length) { + throw new IllegalArgumentException("Length of dataArray["+i+ + "] is less than size+"+ + "offsets["+i+"]."); + } + + } + bankdata = (short[][]) dataArray.clone(); + data = bankdata[0]; + } + + /** + * Returns the default (first) unsigned-short data array. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @return The first unsigned-short data array. + */ + public short[] getData() { + theTrackable.setUntrackable(); + return data; + } + + /** + * Returns the data array for the specified bank. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param bank The bank whose data array you want to get. + * @return The data array for the specified bank. + */ + public short[] getData(int bank) { + theTrackable.setUntrackable(); + return bankdata[bank]; + } + + /** + * Returns the data arrays for all banks. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @return All of the data arrays. + */ + public short[][] getBankData() { + theTrackable.setUntrackable(); + return (short[][]) bankdata.clone(); + } + + /** + * Returns the requested data array element from the first (default) bank. + * + * @param i The data array element you want to get. + * @return The requested data array element as an integer. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int i) { + return (int)(data[i+offset]&0xffff); + } + + /** + * Returns the requested data array element from the specified bank. + * + * @param bank The bank from which you want to get a data array element. + * @param i The data array element you want to get. + * @return The requested data array element as an integer. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int bank, int i) { + return (int)(bankdata[bank][i+offsets[bank]]&0xffff); + } + + /** + * Sets the requested data array element in the first (default) bank + * to the specified value. + * + * @param i The data array element you want to set. + * @param val The integer value to which you want to set the data array element. + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int i, int val) { + markBitmapDirty(); + data[i+offset] = (short)(val&0xffff); + theTrackable.markDirty(); + } + + /** + * Sets the requested data array element in the specified bank + * from the given integer. + * @param bank The bank in which you want to set the data array element. + * @param i The data array element you want to set. + * @param val The integer value to which you want to set the specified data array element. + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int bank, int i, int val) { + markBitmapDirty(); + bankdata[bank][i+offsets[bank]] = (short)(val&0xffff); + theTrackable.markDirty(); + } +} diff --git a/openjdk/java/awt/image/IndexColorModel.java b/openjdk/java/awt/image/IndexColorModel.java new file mode 100644 index 0000000..ff0fe6a --- /dev/null +++ b/openjdk/java/awt/image/IndexColorModel.java @@ -0,0 +1,1528 @@ +/* + * Copyright (c) 1995, 2013, 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 java.awt.image; + +import java.awt.Transparency; +import java.awt.color.ColorSpace; +import java.math.BigInteger; + +/** + * The IndexColorModel class is a ColorModel + * class that works with pixel values consisting of a + * single sample that is an index into a fixed colormap in the default + * sRGB color space. The colormap specifies red, green, blue, and + * optional alpha components corresponding to each index. All components + * are represented in the colormap as 8-bit unsigned integral values. + * Some constructors allow the caller to specify "holes" in the colormap + * by indicating which colormap entries are valid and which represent + * unusable colors via the bits set in a BigInteger object. + * This color model is similar to an X11 PseudoColor visual. + *

+ * Some constructors provide a means to specify an alpha component + * for each pixel in the colormap, while others either provide no + * such means or, in some cases, a flag to indicate whether the + * colormap data contains alpha values. If no alpha is supplied to + * the constructor, an opaque alpha component (alpha = 1.0) is + * assumed for each entry. + * An optional transparent pixel value can be supplied that indicates a + * pixel to be made completely transparent, regardless of any alpha + * component supplied or assumed for that pixel value. + * Note that the color components in the colormap of an + * IndexColorModel objects are never pre-multiplied with + * the alpha components. + *

+ * + * The transparency of an IndexColorModel object is + * determined by examining the alpha components of the colors in the + * colormap and choosing the most specific value after considering + * the optional alpha values and any transparent index specified. + * The transparency value is Transparency.OPAQUE + * only if all valid colors in + * the colormap are opaque and there is no valid transparent pixel. + * If all valid colors + * in the colormap are either completely opaque (alpha = 1.0) or + * completely transparent (alpha = 0.0), which typically occurs when + * a valid transparent pixel is specified, + * the value is Transparency.BITMASK. + * Otherwise, the value is Transparency.TRANSLUCENT, indicating + * that some valid color has an alpha component that is + * neither completely transparent nor completely opaque + * (0.0 < alpha < 1.0). + * + * + *

+ * If an IndexColorModel object has + * a transparency value of Transparency.OPAQUE, + * then the hasAlpha + * and getNumComponents methods + * (both inherited from ColorModel) + * return false and 3, respectively. + * For any other transparency value, + * hasAlpha returns true + * and getNumComponents returns 4. + * + *

+ * + * The values used to index into the colormap are taken from the least + * significant n bits of pixel representations where + * n is based on the pixel size specified in the constructor. + * For pixel sizes smaller than 8 bits, n is rounded up to a + * power of two (3 becomes 4 and 5,6,7 become 8). + * For pixel sizes between 8 and 16 bits, n is equal to the + * pixel size. + * Pixel sizes larger than 16 bits are not supported by this class. + * Higher order bits beyond n are ignored in pixel representations. + * Index values greater than or equal to the map size, but less than + * 2n, are undefined and return 0 for all color and + * alpha components. + * + *

+ * For those methods that use a primitive array pixel representation of + * type transferType, the array length is always one. + * The transfer types supported are DataBuffer.TYPE_BYTE and + * DataBuffer.TYPE_USHORT. A single int pixel + * representation is valid for all objects of this class, since it is + * always possible to represent pixel values used with this class in a + * single int. Therefore, methods that use this representation do + * not throw an IllegalArgumentException due to an invalid + * pixel value. + *

+ * Many of the methods in this class are final. The reason for + * this is that the underlying native graphics code makes assumptions + * about the layout and operation of this class and those assumptions + * are reflected in the implementations of the methods here that are + * marked final. You can subclass this class for other reasons, but + * you cannot override or modify the behaviour of those methods. + * + * @see ColorModel + * @see ColorSpace + * @see DataBuffer + * + */ +public class IndexColorModel extends ColorModel { + private int rgb[]; + private int map_size; + private int pixel_mask; + private int transparent_index = -1; + private boolean allgrayopaque; + private BigInteger validBits; + + private static int[] opaqueBits = {8, 8, 8}; + private static int[] alphaBits = {8, 8, 8, 8}; + + /** + * Constructs an IndexColorModel from the specified + * arrays of red, green, and blue components. Pixels described + * by this color model all have alpha components of 255 + * unnormalized (1.0 normalized), which means they + * are fully opaque. All of the arrays specifying the color + * components must have at least the specified number of entries. + * The ColorSpace is the default sRGB space. + * Since there is no alpha information in any of the arguments + * to this constructor, the transparency value is always + * Transparency.OPAQUE. + * The transfer type is the smallest of DataBuffer.TYPE_BYTE + * or DataBuffer.TYPE_USHORT that can hold a single pixel. + * @param bits the number of bits each pixel occupies + * @param size the size of the color component arrays + * @param r the array of red color components + * @param g the array of green color components + * @param b the array of blue color components + * @throws IllegalArgumentException if bits is less + * than 1 or greater than 16 + * @throws IllegalArgumentException if size is less + * than 1 + */ + public IndexColorModel(int bits, int size, + byte r[], byte g[], byte b[]) { + super(bits, opaqueBits, + ColorSpace.getInstance(ColorSpace.CS_sRGB), + false, false, OPAQUE, + ColorModel.getDefaultTransferType(bits)); + if (bits < 1 || bits > 16) { + throw new IllegalArgumentException("Number of bits must be between" + +" 1 and 16."); + } + setRGBs(size, r, g, b, null); + calculatePixelMask(); + } + + /** + * Constructs an IndexColorModel from the given arrays + * of red, green, and blue components. Pixels described by this color + * model all have alpha components of 255 unnormalized + * (1.0 normalized), which means they are fully opaque, except + * for the indicated pixel to be made transparent. All of the arrays + * specifying the color components must have at least the specified + * number of entries. + * The ColorSpace is the default sRGB space. + * The transparency value may be Transparency.OPAQUE or + * Transparency.BITMASK depending on the arguments, as + * specified in the class description above. + * The transfer type is the smallest of DataBuffer.TYPE_BYTE + * or DataBuffer.TYPE_USHORT that can hold a + * single pixel. + * @param bits the number of bits each pixel occupies + * @param size the size of the color component arrays + * @param r the array of red color components + * @param g the array of green color components + * @param b the array of blue color components + * @param trans the index of the transparent pixel + * @throws IllegalArgumentException if bits is less than + * 1 or greater than 16 + * @throws IllegalArgumentException if size is less than + * 1 + */ + public IndexColorModel(int bits, int size, + byte r[], byte g[], byte b[], int trans) { + super(bits, opaqueBits, + ColorSpace.getInstance(ColorSpace.CS_sRGB), + false, false, OPAQUE, + ColorModel.getDefaultTransferType(bits)); + if (bits < 1 || bits > 16) { + throw new IllegalArgumentException("Number of bits must be between" + +" 1 and 16."); + } + setRGBs(size, r, g, b, null); + setTransparentPixel(trans); + calculatePixelMask(); + } + + /** + * Constructs an IndexColorModel from the given + * arrays of red, green, blue and alpha components. All of the + * arrays specifying the components must have at least the specified + * number of entries. + * The ColorSpace is the default sRGB space. + * The transparency value may be any of Transparency.OPAQUE, + * Transparency.BITMASK, + * or Transparency.TRANSLUCENT + * depending on the arguments, as specified + * in the class description above. + * The transfer type is the smallest of DataBuffer.TYPE_BYTE + * or DataBuffer.TYPE_USHORT that can hold a single pixel. + * @param bits the number of bits each pixel occupies + * @param size the size of the color component arrays + * @param r the array of red color components + * @param g the array of green color components + * @param b the array of blue color components + * @param a the array of alpha value components + * @throws IllegalArgumentException if bits is less + * than 1 or greater than 16 + * @throws IllegalArgumentException if size is less + * than 1 + */ + public IndexColorModel(int bits, int size, + byte r[], byte g[], byte b[], byte a[]) { + super (bits, alphaBits, + ColorSpace.getInstance(ColorSpace.CS_sRGB), + true, false, TRANSLUCENT, + ColorModel.getDefaultTransferType(bits)); + if (bits < 1 || bits > 16) { + throw new IllegalArgumentException("Number of bits must be between" + +" 1 and 16."); + } + setRGBs (size, r, g, b, a); + calculatePixelMask(); + } + + /** + * Constructs an IndexColorModel from a single + * array of interleaved red, green, blue and optional alpha + * components. The array must have enough values in it to + * fill all of the needed component arrays of the specified + * size. The ColorSpace is the default sRGB space. + * The transparency value may be any of Transparency.OPAQUE, + * Transparency.BITMASK, + * or Transparency.TRANSLUCENT + * depending on the arguments, as specified + * in the class description above. + * The transfer type is the smallest of + * DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT + * that can hold a single pixel. + * + * @param bits the number of bits each pixel occupies + * @param size the size of the color component arrays + * @param cmap the array of color components + * @param start the starting offset of the first color component + * @param hasalpha indicates whether alpha values are contained in + * the cmap array + * @throws IllegalArgumentException if bits is less + * than 1 or greater than 16 + * @throws IllegalArgumentException if size is less + * than 1 + */ + public IndexColorModel(int bits, int size, byte cmap[], int start, + boolean hasalpha) { + this(bits, size, cmap, start, hasalpha, -1); + if (bits < 1 || bits > 16) { + throw new IllegalArgumentException("Number of bits must be between" + +" 1 and 16."); + } + } + + /** + * Constructs an IndexColorModel from a single array of + * interleaved red, green, blue and optional alpha components. The + * specified transparent index represents a pixel that is made + * entirely transparent regardless of any alpha value specified + * for it. The array must have enough values in it to fill all + * of the needed component arrays of the specified size. + * The ColorSpace is the default sRGB space. + * The transparency value may be any of Transparency.OPAQUE, + * Transparency.BITMASK, + * or Transparency.TRANSLUCENT + * depending on the arguments, as specified + * in the class description above. + * The transfer type is the smallest of + * DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT + * that can hold a single pixel. + * @param bits the number of bits each pixel occupies + * @param size the size of the color component arrays + * @param cmap the array of color components + * @param start the starting offset of the first color component + * @param hasalpha indicates whether alpha values are contained in + * the cmap array + * @param trans the index of the fully transparent pixel + * @throws IllegalArgumentException if bits is less than + * 1 or greater than 16 + * @throws IllegalArgumentException if size is less than + * 1 + */ + public IndexColorModel(int bits, int size, byte cmap[], int start, + boolean hasalpha, int trans) { + // REMIND: This assumes the ordering: RGB[A] + super(bits, opaqueBits, + ColorSpace.getInstance(ColorSpace.CS_sRGB), + false, false, OPAQUE, + ColorModel.getDefaultTransferType(bits)); + + if (bits < 1 || bits > 16) { + throw new IllegalArgumentException("Number of bits must be between" + +" 1 and 16."); + } + if (size < 1) { + throw new IllegalArgumentException("Map size ("+size+ + ") must be >= 1"); + } + map_size = size; + rgb = new int[calcRealMapSize(bits, size)]; + int j = start; + int alpha = 0xff; + boolean allgray = true; + int transparency = OPAQUE; + for (int i = 0; i < size; i++) { + int r = cmap[j++] & 0xff; + int g = cmap[j++] & 0xff; + int b = cmap[j++] & 0xff; + allgray = allgray && (r == g) && (g == b); + if (hasalpha) { + alpha = cmap[j++] & 0xff; + if (alpha != 0xff) { + if (alpha == 0x00) { + if (transparency == OPAQUE) { + transparency = BITMASK; + } + if (transparent_index < 0) { + transparent_index = i; + } + } else { + transparency = TRANSLUCENT; + } + allgray = false; + } + } + rgb[i] = (alpha << 24) | (r << 16) | (g << 8) | b; + } + this.allgrayopaque = allgray; + setTransparency(transparency); + setTransparentPixel(trans); + calculatePixelMask(); + } + + /** + * Constructs an IndexColorModel from an array of + * ints where each int is comprised of red, green, blue, and + * optional alpha components in the default RGB color model format. + * The specified transparent index represents a pixel that is made + * entirely transparent regardless of any alpha value specified + * for it. The array must have enough values in it to fill all + * of the needed component arrays of the specified size. + * The ColorSpace is the default sRGB space. + * The transparency value may be any of Transparency.OPAQUE, + * Transparency.BITMASK, + * or Transparency.TRANSLUCENT + * depending on the arguments, as specified + * in the class description above. + * @param bits the number of bits each pixel occupies + * @param size the size of the color component arrays + * @param cmap the array of color components + * @param start the starting offset of the first color component + * @param hasalpha indicates whether alpha values are contained in + * the cmap array + * @param trans the index of the fully transparent pixel + * @param transferType the data type of the array used to represent + * pixel values. The data type must be either + * DataBuffer.TYPE_BYTE or + * DataBuffer.TYPE_USHORT. + * @throws IllegalArgumentException if bits is less + * than 1 or greater than 16 + * @throws IllegalArgumentException if size is less + * than 1 + * @throws IllegalArgumentException if transferType is not + * one of DataBuffer.TYPE_BYTE or + * DataBuffer.TYPE_USHORT + */ + public IndexColorModel(int bits, int size, + int cmap[], int start, + boolean hasalpha, int trans, int transferType) { + // REMIND: This assumes the ordering: RGB[A] + super(bits, opaqueBits, + ColorSpace.getInstance(ColorSpace.CS_sRGB), + false, false, OPAQUE, + transferType); + + if (bits < 1 || bits > 16) { + throw new IllegalArgumentException("Number of bits must be between" + +" 1 and 16."); + } + if (size < 1) { + throw new IllegalArgumentException("Map size ("+size+ + ") must be >= 1"); + } + if ((transferType != DataBuffer.TYPE_BYTE) && + (transferType != DataBuffer.TYPE_USHORT)) { + throw new IllegalArgumentException("transferType must be either" + + "DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT"); + } + + setRGBs(size, cmap, start, hasalpha); + setTransparentPixel(trans); + calculatePixelMask(); + } + + /** + * Constructs an IndexColorModel from an + * int array where each int is + * comprised of red, green, blue, and alpha + * components in the default RGB color model format. + * The array must have enough values in it to fill all + * of the needed component arrays of the specified size. + * The ColorSpace is the default sRGB space. + * The transparency value may be any of Transparency.OPAQUE, + * Transparency.BITMASK, + * or Transparency.TRANSLUCENT + * depending on the arguments, as specified + * in the class description above. + * The transfer type must be one of DataBuffer.TYPE_BYTE + * DataBuffer.TYPE_USHORT. + * The BigInteger object specifies the valid/invalid pixels + * in the cmap array. A pixel is valid if the + * BigInteger value at that index is set, and is invalid + * if the BigInteger bit at that index is not set. + * @param bits the number of bits each pixel occupies + * @param size the size of the color component array + * @param cmap the array of color components + * @param start the starting offset of the first color component + * @param transferType the specified data type + * @param validBits a BigInteger object. If a bit is + * set in the BigInteger, the pixel at that index is valid. + * If a bit is not set, the pixel at that index + * is considered invalid. If null, all pixels are valid. + * Only bits from 0 to the map size are considered. + * @throws IllegalArgumentException if bits is less + * than 1 or greater than 16 + * @throws IllegalArgumentException if size is less + * than 1 + * @throws IllegalArgumentException if transferType is not + * one of DataBuffer.TYPE_BYTE or + * DataBuffer.TYPE_USHORT + * + * @since 1.3 + */ + public IndexColorModel(int bits, int size, int cmap[], int start, + int transferType, BigInteger validBits) { + super (bits, alphaBits, + ColorSpace.getInstance(ColorSpace.CS_sRGB), + true, false, TRANSLUCENT, + transferType); + + if (bits < 1 || bits > 16) { + throw new IllegalArgumentException("Number of bits must be between" + +" 1 and 16."); + } + if (size < 1) { + throw new IllegalArgumentException("Map size ("+size+ + ") must be >= 1"); + } + if ((transferType != DataBuffer.TYPE_BYTE) && + (transferType != DataBuffer.TYPE_USHORT)) { + throw new IllegalArgumentException("transferType must be either" + + "DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT"); + } + + if (validBits != null) { + // Check to see if it is all valid + for (int i=0; i < size; i++) { + if (!validBits.testBit(i)) { + this.validBits = validBits; + break; + } + } + } + + setRGBs(size, cmap, start, true); + calculatePixelMask(); + } + + private void setRGBs(int size, byte r[], byte g[], byte b[], byte a[]) { + if (size < 1) { + throw new IllegalArgumentException("Map size ("+size+ + ") must be >= 1"); + } + map_size = size; + rgb = new int[calcRealMapSize(pixel_bits, size)]; + int alpha = 0xff; + int transparency = OPAQUE; + boolean allgray = true; + for (int i = 0; i < size; i++) { + int rc = r[i] & 0xff; + int gc = g[i] & 0xff; + int bc = b[i] & 0xff; + allgray = allgray && (rc == gc) && (gc == bc); + if (a != null) { + alpha = a[i] & 0xff; + if (alpha != 0xff) { + if (alpha == 0x00) { + if (transparency == OPAQUE) { + transparency = BITMASK; + } + if (transparent_index < 0) { + transparent_index = i; + } + } else { + transparency = TRANSLUCENT; + } + allgray = false; + } + } + rgb[i] = (alpha << 24) | (rc << 16) | (gc << 8) | bc; + } + this.allgrayopaque = allgray; + setTransparency(transparency); + } + + private void setRGBs(int size, int cmap[], int start, boolean hasalpha) { + map_size = size; + rgb = new int[calcRealMapSize(pixel_bits, size)]; + int j = start; + int transparency = OPAQUE; + boolean allgray = true; + BigInteger validBits = this.validBits; + for (int i = 0; i < size; i++, j++) { + if (validBits != null && !validBits.testBit(i)) { + continue; + } + int cmaprgb = cmap[j]; + int r = (cmaprgb >> 16) & 0xff; + int g = (cmaprgb >> 8) & 0xff; + int b = (cmaprgb ) & 0xff; + allgray = allgray && (r == g) && (g == b); + if (hasalpha) { + int alpha = cmaprgb >>> 24; + if (alpha != 0xff) { + if (alpha == 0x00) { + if (transparency == OPAQUE) { + transparency = BITMASK; + } + if (transparent_index < 0) { + transparent_index = i; + } + } else { + transparency = TRANSLUCENT; + } + allgray = false; + } + } else { + cmaprgb |= 0xff000000; + } + rgb[i] = cmaprgb; + } + this.allgrayopaque = allgray; + setTransparency(transparency); + } + + private int calcRealMapSize(int bits, int size) { + int newSize = Math.max(1 << bits, size); + return Math.max(newSize, 256); + } + + private BigInteger getAllValid() { + int numbytes = (map_size+7)/8; + byte[] valid = new byte[numbytes]; + java.util.Arrays.fill(valid, (byte)0xff); + valid[0] = (byte)(0xff >>> (numbytes*8 - map_size)); + + return new BigInteger(1, valid); + } + + /** + * Returns the transparency. Returns either OPAQUE, BITMASK, + * or TRANSLUCENT + * @return the transparency of this IndexColorModel + * @see Transparency#OPAQUE + * @see Transparency#BITMASK + * @see Transparency#TRANSLUCENT + */ + public int getTransparency() { + return transparency; + } + + /** + * Returns an array of the number of bits for each color/alpha component. + * The array contains the color components in the order red, green, + * blue, followed by the alpha component, if present. + * @return an array containing the number of bits of each color + * and alpha component of this IndexColorModel + */ + public int[] getComponentSize() { + if (nBits == null) { + if (supportsAlpha) { + nBits = new int[4]; + nBits[3] = 8; + } + else { + nBits = new int[3]; + } + nBits[0] = nBits[1] = nBits[2] = 8; + } + return nBits.clone(); + } + + /** + * Returns the size of the color/alpha component arrays in this + * IndexColorModel. + * @return the size of the color and alpha component arrays. + */ + final public int getMapSize() { + return map_size; + } + + /** + * Returns the index of a transparent pixel in this + * IndexColorModel or -1 if there is no pixel + * with an alpha value of 0. If a transparent pixel was + * explicitly specified in one of the constructors by its + * index, then that index will be preferred, otherwise, + * the index of any pixel which happens to be fully transparent + * may be returned. + * @return the index of a transparent pixel in this + * IndexColorModel object, or -1 if there + * is no such pixel + */ + final public int getTransparentPixel() { + return transparent_index; + } + + /** + * Copies the array of red color components into the specified array. + * Only the initial entries of the array as specified by + * {@link #getMapSize() getMapSize} are written. + * @param r the specified array into which the elements of the + * array of red color components are copied + */ + final public void getReds(byte r[]) { + for (int i = 0; i < map_size; i++) { + r[i] = (byte) (rgb[i] >> 16); + } + } + + /** + * Copies the array of green color components into the specified array. + * Only the initial entries of the array as specified by + * getMapSize are written. + * @param g the specified array into which the elements of the + * array of green color components are copied + */ + final public void getGreens(byte g[]) { + for (int i = 0; i < map_size; i++) { + g[i] = (byte) (rgb[i] >> 8); + } + } + + /** + * Copies the array of blue color components into the specified array. + * Only the initial entries of the array as specified by + * getMapSize are written. + * @param b the specified array into which the elements of the + * array of blue color components are copied + */ + final public void getBlues(byte b[]) { + for (int i = 0; i < map_size; i++) { + b[i] = (byte) rgb[i]; + } + } + + /** + * Copies the array of alpha transparency components into the + * specified array. Only the initial entries of the array as specified + * by getMapSize are written. + * @param a the specified array into which the elements of the + * array of alpha components are copied + */ + final public void getAlphas(byte a[]) { + for (int i = 0; i < map_size; i++) { + a[i] = (byte) (rgb[i] >> 24); + } + } + + /** + * Converts data for each index from the color and alpha component + * arrays to an int in the default RGB ColorModel format and copies + * the resulting 32-bit ARGB values into the specified array. Only + * the initial entries of the array as specified by + * getMapSize are + * written. + * @param rgb the specified array into which the converted ARGB + * values from this array of color and alpha components + * are copied. + */ + final public void getRGBs(int rgb[]) { + System.arraycopy(this.rgb, 0, rgb, 0, map_size); + } + + private void setTransparentPixel(int trans) { + if (trans >= 0 && trans < map_size) { + rgb[trans] &= 0x00ffffff; + transparent_index = trans; + allgrayopaque = false; + if (this.transparency == OPAQUE) { + setTransparency(BITMASK); + } + } + } + + private void setTransparency(int transparency) { + if (this.transparency != transparency) { + this.transparency = transparency; + if (transparency == OPAQUE) { + supportsAlpha = false; + numComponents = 3; + nBits = opaqueBits; + } else { + supportsAlpha = true; + numComponents = 4; + nBits = alphaBits; + } + } + } + + /** + * This method is called from the constructors to set the pixel_mask + * value, which is based on the value of pixel_bits. The pixel_mask + * value is used to mask off the pixel parameters for methods such + * as getRed(), getGreen(), getBlue(), getAlpha(), and getRGB(). + */ + private final void calculatePixelMask() { + // Note that we adjust the mask so that our masking behavior here + // is consistent with that of our native rendering loops. + int maskbits = pixel_bits; + if (maskbits == 3) { + maskbits = 4; + } else if (maskbits > 4 && maskbits < 8) { + maskbits = 8; + } + pixel_mask = (1 << maskbits) - 1; + } + + /** + * Returns the red color component for the specified pixel, scaled + * from 0 to 255 in the default RGB ColorSpace, sRGB. The pixel value + * is specified as an int. + * Only the lower n bits of the pixel value, as specified in the + * class description above, are used to + * calculate the returned value. + * The returned value is a non pre-multiplied value. + * @param pixel the specified pixel + * @return the value of the red color component for the specified pixel + */ + final public int getRed(int pixel) { + return (rgb[pixel & pixel_mask] >> 16) & 0xff; + } + + /** + * Returns the green color component for the specified pixel, scaled + * from 0 to 255 in the default RGB ColorSpace, sRGB. The pixel value + * is specified as an int. + * Only the lower n bits of the pixel value, as specified in the + * class description above, are used to + * calculate the returned value. + * The returned value is a non pre-multiplied value. + * @param pixel the specified pixel + * @return the value of the green color component for the specified pixel + */ + final public int getGreen(int pixel) { + return (rgb[pixel & pixel_mask] >> 8) & 0xff; + } + + /** + * Returns the blue color component for the specified pixel, scaled + * from 0 to 255 in the default RGB ColorSpace, sRGB. The pixel value + * is specified as an int. + * Only the lower n bits of the pixel value, as specified in the + * class description above, are used to + * calculate the returned value. + * The returned value is a non pre-multiplied value. + * @param pixel the specified pixel + * @return the value of the blue color component for the specified pixel + */ + final public int getBlue(int pixel) { + return rgb[pixel & pixel_mask] & 0xff; + } + + /** + * Returns the alpha component for the specified pixel, scaled + * from 0 to 255. The pixel value is specified as an int. + * Only the lower n bits of the pixel value, as specified in the + * class description above, are used to + * calculate the returned value. + * @param pixel the specified pixel + * @return the value of the alpha component for the specified pixel + */ + final public int getAlpha(int pixel) { + return (rgb[pixel & pixel_mask] >> 24) & 0xff; + } + + /** + * Returns the color/alpha components of the pixel in the default + * RGB color model format. The pixel value is specified as an int. + * Only the lower n bits of the pixel value, as specified in the + * class description above, are used to + * calculate the returned value. + * The returned value is in a non pre-multiplied format. + * @param pixel the specified pixel + * @return the color and alpha components of the specified pixel + * @see ColorModel#getRGBdefault + */ + final public int getRGB(int pixel) { + return rgb[pixel & pixel_mask]; + } + + private static final int CACHESIZE = 40; + private int lookupcache[] = new int[CACHESIZE]; + + /** + * Returns a data element array representation of a pixel in this + * ColorModel, given an integer pixel representation in the + * default RGB color model. This array can then be passed to the + * {@link WritableRaster#setDataElements(int, int, java.lang.Object) setDataElements} + * method of a {@link WritableRaster} object. If the pixel variable is + * null, a new array is allocated. If pixel + * is not null, it must be + * a primitive array of type transferType; otherwise, a + * ClassCastException is thrown. An + * ArrayIndexOutOfBoundsException is + * thrown if pixel is not large enough to hold a pixel + * value for this ColorModel. The pixel array is returned. + *

+ * Since IndexColorModel can be subclassed, subclasses + * inherit the implementation of this method and if they don't + * override it then they throw an exception if they use an + * unsupported transferType. + * + * @param rgb the integer pixel representation in the default RGB + * color model + * @param pixel the specified pixel + * @return an array representation of the specified pixel in this + * IndexColorModel. + * @throws ClassCastException if pixel + * is not a primitive array of type transferType + * @throws ArrayIndexOutOfBoundsException if + * pixel is not large enough to hold a pixel value + * for this ColorModel + * @throws UnsupportedOperationException if transferType + * is invalid + * @see WritableRaster#setDataElements + * @see SampleModel#setDataElements + */ + public synchronized Object getDataElements(int rgb, Object pixel) { + int red = (rgb>>16) & 0xff; + int green = (rgb>>8) & 0xff; + int blue = rgb & 0xff; + int alpha = (rgb>>>24); + int pix = 0; + + // Note that pixels are stored at lookupcache[2*i] + // and the rgb that was searched is stored at + // lookupcache[2*i+1]. Also, the pixel is first + // inverted using the unary complement operator + // before storing in the cache so it can never be 0. + for (int i = CACHESIZE - 2; i >= 0; i -= 2) { + if ((pix = lookupcache[i]) == 0) { + break; + } + if (rgb == lookupcache[i+1]) { + return installpixel(pixel, ~pix); + } + } + + if (allgrayopaque) { + // IndexColorModel objects are all tagged as + // non-premultiplied so ignore the alpha value + // of the incoming color, convert the + // non-premultiplied color components to a + // grayscale value and search for the closest + // gray value in the palette. Since all colors + // in the palette are gray, we only need compare + // to one of the color components for a match + // using a simple linear distance formula. + + int minDist = 256; + int d; + int gray = (int) (red*77 + green*150 + blue*29 + 128)/256; + + for (int i = 0; i < map_size; i++) { + if (this.rgb[i] == 0x0) { + // For allgrayopaque colormaps, entries are 0 + // iff they are an invalid color and should be + // ignored during color searches. + continue; + } + d = (this.rgb[i] & 0xff) - gray; + if (d < 0) d = -d; + if (d < minDist) { + pix = i; + if (d == 0) { + break; + } + minDist = d; + } + } + } else if (transparency == OPAQUE) { + // IndexColorModel objects are all tagged as + // non-premultiplied so ignore the alpha value + // of the incoming color and search for closest + // color match independently using a 3 component + // Euclidean distance formula. + // For opaque colormaps, palette entries are 0 + // iff they are an invalid color and should be + // ignored during color searches. + // As an optimization, exact color searches are + // likely to be fairly common in opaque colormaps + // so first we will do a quick search for an + // exact match. + + int smallestError = Integer.MAX_VALUE; + int lut[] = this.rgb; + int lutrgb; + for (int i=0; i < map_size; i++) { + lutrgb = lut[i]; + if (lutrgb == rgb && lutrgb != 0) { + pix = i; + smallestError = 0; + break; + } + } + + if (smallestError != 0) { + for (int i=0; i < map_size; i++) { + lutrgb = lut[i]; + if (lutrgb == 0) { + continue; + } + + int tmp = ((lutrgb >> 16) & 0xff) - red; + int currentError = tmp*tmp; + if (currentError < smallestError) { + tmp = ((lutrgb >> 8) & 0xff) - green; + currentError += tmp * tmp; + if (currentError < smallestError) { + tmp = (lutrgb & 0xff) - blue; + currentError += tmp * tmp; + if (currentError < smallestError) { + pix = i; + smallestError = currentError; + } + } + } + } + } + } else if (alpha == 0 && transparent_index >= 0) { + // Special case - transparent color maps to the + // specified transparent pixel, if there is one + + pix = transparent_index; + } else { + // IndexColorModel objects are all tagged as + // non-premultiplied so use non-premultiplied + // color components in the distance calculations. + // Look for closest match using a 4 component + // Euclidean distance formula. + + int smallestError = Integer.MAX_VALUE; + int lut[] = this.rgb; + for (int i=0; i < map_size; i++) { + int lutrgb = lut[i]; + if (lutrgb == rgb) { + if (validBits != null && !validBits.testBit(i)) { + continue; + } + pix = i; + break; + } + + int tmp = ((lutrgb >> 16) & 0xff) - red; + int currentError = tmp*tmp; + if (currentError < smallestError) { + tmp = ((lutrgb >> 8) & 0xff) - green; + currentError += tmp * tmp; + if (currentError < smallestError) { + tmp = (lutrgb & 0xff) - blue; + currentError += tmp * tmp; + if (currentError < smallestError) { + tmp = (lutrgb >>> 24) - alpha; + currentError += tmp * tmp; + if (currentError < smallestError && + (validBits == null || validBits.testBit(i))) + { + pix = i; + smallestError = currentError; + } + } + } + } + } + } + System.arraycopy(lookupcache, 2, lookupcache, 0, CACHESIZE - 2); + lookupcache[CACHESIZE - 1] = rgb; + lookupcache[CACHESIZE - 2] = ~pix; + return installpixel(pixel, pix); + } + + private Object installpixel(Object pixel, int pix) { + switch (transferType) { + case DataBuffer.TYPE_INT: + int[] intObj; + if (pixel == null) { + pixel = intObj = new int[1]; + } else { + intObj = (int[]) pixel; + } + intObj[0] = pix; + break; + case DataBuffer.TYPE_BYTE: + byte[] byteObj; + if (pixel == null) { + pixel = byteObj = new byte[1]; + } else { + byteObj = (byte[]) pixel; + } + byteObj[0] = (byte) pix; + break; + case DataBuffer.TYPE_USHORT: + short[] shortObj; + if (pixel == null) { + pixel = shortObj = new short[1]; + } else { + shortObj = (short[]) pixel; + } + shortObj[0] = (short) pix; + break; + default: + throw new UnsupportedOperationException("This method has not been "+ + "implemented for transferType " + transferType); + } + return pixel; + } + + /** + * Returns an array of unnormalized color/alpha components for a + * specified pixel in this ColorModel. The pixel value + * is specified as an int. If the components array is null, + * a new array is allocated that contains + * offset + getNumComponents() elements. + * The components array is returned, + * with the alpha component included + * only if hasAlpha returns true. + * Color/alpha components are stored in the components array starting + * at offset even if the array is allocated by this method. + * An ArrayIndexOutOfBoundsException + * is thrown if the components array is not null and is + * not large enough to hold all the color and alpha components + * starting at offset. + * @param pixel the specified pixel + * @param components the array to receive the color and alpha + * components of the specified pixel + * @param offset the offset into the components array at + * which to start storing the color and alpha components + * @return an array containing the color and alpha components of the + * specified pixel starting at the specified offset. + * @see ColorModel#hasAlpha + * @see ColorModel#getNumComponents + */ + public int[] getComponents(int pixel, int[] components, int offset) { + if (components == null) { + components = new int[offset+numComponents]; + } + + // REMIND: Needs to change if different color space + components[offset+0] = getRed(pixel); + components[offset+1] = getGreen(pixel); + components[offset+2] = getBlue(pixel); + if (supportsAlpha && (components.length-offset) > 3) { + components[offset+3] = getAlpha(pixel); + } + + return components; + } + + /** + * Returns an array of unnormalized color/alpha components for + * a specified pixel in this ColorModel. The pixel + * value is specified by an array of data elements of type + * transferType passed in as an object reference. + * If pixel is not a primitive array of type + * transferType, a ClassCastException + * is thrown. An ArrayIndexOutOfBoundsException + * is thrown if pixel is not large enough to hold + * a pixel value for this ColorModel. If the + * components array is null, a new array + * is allocated that contains + * offset + getNumComponents() elements. + * The components array is returned, + * with the alpha component included + * only if hasAlpha returns true. + * Color/alpha components are stored in the components + * array starting at offset even if the array is + * allocated by this method. An + * ArrayIndexOutOfBoundsException is also + * thrown if the components array is not + * null and is not large enough to hold all the color + * and alpha components starting at offset. + *

+ * Since IndexColorModel can be subclassed, subclasses + * inherit the implementation of this method and if they don't + * override it then they throw an exception if they use an + * unsupported transferType. + * + * @param pixel the specified pixel + * @param components an array that receives the color and alpha + * components of the specified pixel + * @param offset the index into the components array at + * which to begin storing the color and alpha components of the + * specified pixel + * @return an array containing the color and alpha components of the + * specified pixel starting at the specified offset. + * @throws ArrayIndexOutOfBoundsException if pixel + * is not large enough to hold a pixel value for this + * ColorModel or if the + * components array is not null + * and is not large enough to hold all the color + * and alpha components starting at offset + * @throws ClassCastException if pixel is not a + * primitive array of type transferType + * @throws UnsupportedOperationException if transferType + * is not one of the supported transfer types + * @see ColorModel#hasAlpha + * @see ColorModel#getNumComponents + */ + public int[] getComponents(Object pixel, int[] components, int offset) { + int intpixel; + switch (transferType) { + case DataBuffer.TYPE_BYTE: + byte bdata[] = (byte[])pixel; + intpixel = bdata[0] & 0xff; + break; + case DataBuffer.TYPE_USHORT: + short sdata[] = (short[])pixel; + intpixel = sdata[0] & 0xffff; + break; + case DataBuffer.TYPE_INT: + int idata[] = (int[])pixel; + intpixel = idata[0]; + break; + default: + throw new UnsupportedOperationException("This method has not been "+ + "implemented for transferType " + transferType); + } + return getComponents(intpixel, components, offset); + } + + /** + * Returns a pixel value represented as an int in this + * ColorModel given an array of unnormalized + * color/alpha components. An + * ArrayIndexOutOfBoundsException + * is thrown if the components array is not large + * enough to hold all of the color and alpha components starting + * at offset. Since + * ColorModel can be subclassed, subclasses inherit the + * implementation of this method and if they don't override it then + * they throw an exception if they use an unsupported transferType. + * @param components an array of unnormalized color and alpha + * components + * @param offset the index into components at which to + * begin retrieving the color and alpha components + * @return an int pixel value in this + * ColorModel corresponding to the specified components. + * @throws ArrayIndexOutOfBoundsException if + * the components array is not large enough to + * hold all of the color and alpha components starting at + * offset + * @throws UnsupportedOperationException if transferType + * is invalid + */ + public int getDataElement(int[] components, int offset) { + int rgb = (components[offset+0]<<16) + | (components[offset+1]<<8) | (components[offset+2]); + if (supportsAlpha) { + rgb |= (components[offset+3]<<24); + } + else { + rgb |= 0xff000000; + } + Object inData = getDataElements(rgb, null); + int pixel; + switch (transferType) { + case DataBuffer.TYPE_BYTE: + byte bdata[] = (byte[])inData; + pixel = bdata[0] & 0xff; + break; + case DataBuffer.TYPE_USHORT: + short sdata[] = (short[])inData; + pixel = sdata[0]; + break; + case DataBuffer.TYPE_INT: + int idata[] = (int[])inData; + pixel = idata[0]; + break; + default: + throw new UnsupportedOperationException("This method has not been "+ + "implemented for transferType " + transferType); + } + return pixel; + } + + /** + * Returns a data element array representation of a pixel in this + * ColorModel given an array of unnormalized color/alpha + * components. This array can then be passed to the + * setDataElements method of a WritableRaster + * object. An ArrayIndexOutOfBoundsException is + * thrown if the + * components array is not large enough to hold all of the + * color and alpha components starting at offset. + * If the pixel variable is null, a new array + * is allocated. If pixel is not null, + * it must be a primitive array of type transferType; + * otherwise, a ClassCastException is thrown. + * An ArrayIndexOutOfBoundsException is thrown if pixel + * is not large enough to hold a pixel value for this + * ColorModel. + *

+ * Since IndexColorModel can be subclassed, subclasses + * inherit the implementation of this method and if they don't + * override it then they throw an exception if they use an + * unsupported transferType + * + * @param components an array of unnormalized color and alpha + * components + * @param offset the index into components at which to + * begin retrieving color and alpha components + * @param pixel the Object representing an array of color + * and alpha components + * @return an Object representing an array of color and + * alpha components. + * @throws ClassCastException if pixel + * is not a primitive array of type transferType + * @throws ArrayIndexOutOfBoundsException if + * pixel is not large enough to hold a pixel value + * for this ColorModel or the components + * array is not large enough to hold all of the color and alpha + * components starting at offset + * @throws UnsupportedOperationException if transferType + * is not one of the supported transfer types + * @see WritableRaster#setDataElements + * @see SampleModel#setDataElements + */ + public Object getDataElements(int[] components, int offset, Object pixel) { + int rgb = (components[offset+0]<<16) | (components[offset+1]<<8) + | (components[offset+2]); + if (supportsAlpha) { + rgb |= (components[offset+3]<<24); + } + else { + rgb &= 0xff000000; + } + return getDataElements(rgb, pixel); + } + + /** + * Creates a WritableRaster with the specified width + * and height that has a data layout (SampleModel) + * compatible with this ColorModel. This method + * only works for color models with 16 or fewer bits per pixel. + *

+ * Since IndexColorModel can be subclassed, any + * subclass that supports greater than 16 bits per pixel must + * override this method. + * + * @param w the width to apply to the new WritableRaster + * @param h the height to apply to the new WritableRaster + * @return a WritableRaster object with the specified + * width and height. + * @throws UnsupportedOperationException if the number of bits in a + * pixel is greater than 16 + * @see WritableRaster + * @see SampleModel + */ + public WritableRaster createCompatibleWritableRaster(int w, int h) { + WritableRaster raster; + + if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) { + // TYPE_BINARY + raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE, + w, h, 1, pixel_bits, null); + } + else if (pixel_bits <= 8) { + raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, + w,h,1,null); + } + else if (pixel_bits <= 16) { + raster = Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT, + w,h,1,null); + } + else { + throw new + UnsupportedOperationException("This method is not supported "+ + " for pixel bits > 16."); + } + return raster; + } + + /** + * Returns true if raster is compatible + * with this ColorModel or false if it + * is not compatible with this ColorModel. + * @param raster the {@link Raster} object to test for compatibility + * @return true if raster is compatible + * with this ColorModel; false otherwise. + * + */ + public boolean isCompatibleRaster(Raster raster) { + + int size = raster.getSampleModel().getSampleSize(0); + return ((raster.getTransferType() == transferType) && + (raster.getNumBands() == 1) && ((1 << size) >= map_size)); + } + + /** + * Creates a SampleModel with the specified + * width and height that has a data layout compatible with + * this ColorModel. + * @param w the width to apply to the new SampleModel + * @param h the height to apply to the new SampleModel + * @return a SampleModel object with the specified + * width and height. + * @throws IllegalArgumentException if w or + * h is not greater than 0 + * @see SampleModel + */ + public SampleModel createCompatibleSampleModel(int w, int h) { + int[] off = new int[1]; + off[0] = 0; + if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) { + return new MultiPixelPackedSampleModel(transferType, w, h, + pixel_bits); + } + else { + return new ComponentSampleModel(transferType, w, h, 1, w, + off); + } + } + + /** + * Checks if the specified SampleModel is compatible + * with this ColorModel. If sm is + * null, this method returns false. + * @param sm the specified SampleModel, + * or null + * @return true if the specified SampleModel + * is compatible with this ColorModel; false + * otherwise. + * @see SampleModel + */ + public boolean isCompatibleSampleModel(SampleModel sm) { + // fix 4238629 + if (! (sm instanceof ComponentSampleModel) && + ! (sm instanceof MultiPixelPackedSampleModel) ) { + return false; + } + + // Transfer type must be the same + if (sm.getTransferType() != transferType) { + return false; + } + + if (sm.getNumBands() != 1) { + return false; + } + + return true; + } + + /** + * Returns a new BufferedImage of TYPE_INT_ARGB or + * TYPE_INT_RGB that has a Raster with pixel data + * computed by expanding the indices in the source Raster + * using the color/alpha component arrays of this ColorModel. + * Only the lower n bits of each index value in the source + * Raster, as specified in the + * class description above, are used to + * compute the color/alpha values in the returned image. + * If forceARGB is true, a TYPE_INT_ARGB image is + * returned regardless of whether or not this ColorModel + * has an alpha component array or a transparent pixel. + * @param raster the specified Raster + * @param forceARGB if true, the returned + * BufferedImage is TYPE_INT_ARGB; otherwise it is + * TYPE_INT_RGB + * @return a BufferedImage created with the specified + * Raster + * @throws IllegalArgumentException if the raster argument is not + * compatible with this IndexColorModel + */ + public BufferedImage convertToIntDiscrete(Raster raster, + boolean forceARGB) { + ColorModel cm; + + if (!isCompatibleRaster(raster)) { + throw new IllegalArgumentException("This raster is not compatible" + + "with this IndexColorModel."); + } + if (forceARGB || transparency == TRANSLUCENT) { + cm = ColorModel.getRGBdefault(); + } + else if (transparency == BITMASK) { + cm = new DirectColorModel(25, 0xff0000, 0x00ff00, 0x0000ff, + 0x1000000); + } + else { + cm = new DirectColorModel(24, 0xff0000, 0x00ff00, 0x0000ff); + } + + int w = raster.getWidth(); + int h = raster.getHeight(); + WritableRaster discreteRaster = + cm.createCompatibleWritableRaster(w, h); + Object obj = null; + int[] data = null; + + int rX = raster.getMinX(); + int rY = raster.getMinY(); + + for (int y=0; y < h; y++, rY++) { + obj = raster.getDataElements(rX, rY, w, 1, obj); + if (obj instanceof int[]) { + data = (int[])obj; + } else { + data = DataBuffer.toIntArray(obj); + } + for (int x=0; x < w; x++) { + data[x] = rgb[data[x] & pixel_mask]; + } + discreteRaster.setDataElements(0, y, w, 1, data); + } + + return new BufferedImage(cm, discreteRaster, false, null); + } + + /** + * Returns whether or not the pixel is valid. + * @param pixel the specified pixel value + * @return true if pixel + * is valid; false otherwise. + * @since 1.3 + */ + public boolean isValid(int pixel) { + return ((pixel >= 0 && pixel < map_size) && + (validBits == null || validBits.testBit(pixel))); + } + + /** + * Returns whether or not all of the pixels are valid. + * @return true if all pixels are valid; + * false otherwise. + * @since 1.3 + */ + public boolean isValid() { + return (validBits == null); + } + + /** + * Returns a BigInteger that indicates the valid/invalid + * pixels in the colormap. A bit is valid if the + * BigInteger value at that index is set, and is invalid + * if the BigInteger value at that index is not set. + * The only valid ranges to query in the BigInteger are + * between 0 and the map size. + * @return a BigInteger indicating the valid/invalid pixels. + * @since 1.3 + */ + public BigInteger getValidPixels() { + if (validBits == null) { + return getAllValid(); + } + else { + return validBits; + } + } + + /** + * Disposes of system resources associated with this + * ColorModel once this ColorModel is no + * longer referenced. + */ + public void finalize() { + } + + /** + * Returns the String representation of the contents of + * this ColorModelobject. + * @return a String representing the contents of this + * ColorModel object. + */ + public String toString() { + return new String("IndexColorModel: #pixelBits = "+pixel_bits + + " numComponents = "+numComponents + + " color space = "+colorSpace + + " transparency = "+transparency + + " transIndex = "+transparent_index + + " has alpha = "+supportsAlpha + + " isAlphaPre = "+isAlphaPremultiplied + ); + } +} diff --git a/openjdk/java/awt/image/LookupOp.java b/openjdk/java/awt/image/LookupOp.java new file mode 100644 index 0000000..5b0cf78 --- /dev/null +++ b/openjdk/java/awt/image/LookupOp.java @@ -0,0 +1,307 @@ +/* LookupOp.java -- Filter that converts each pixel using a lookup table. + Copyright (C) 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.awt.RenderingHints; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +/** + * LookupOp is a filter that converts each pixel using a lookup table. + * + * For filtering Rasters, the lookup table must have either one component + * that is applied to all bands, or one component for every band in the + * Rasters. + * + * For BufferedImages, the lookup table may apply to both color and alpha + * components. If the lookup table contains one component, or if there are + * the same number of components as color components in the source, the table + * applies to all color components. Otherwise the table applies to all + * components including alpha. Alpha premultiplication is ignored during the + * lookup filtering. + * + * After filtering, if color conversion is necessary, the conversion happens, + * taking alpha premultiplication into account. + * + * @author jlquinn + */ +public class LookupOp implements BufferedImageOp, RasterOp +{ + private LookupTable lut; + private RenderingHints hints; + + /** + * Construct a new LookupOp using the given LookupTable. + * + * @param lookup LookupTable to use. + * @param hints Rendering hints (can be null). + */ + public LookupOp(LookupTable lookup, RenderingHints hints) + { + lut = lookup; + this.hints = hints; + } + + /** + * Converts the source image using the lookup table specified in the + * constructor. The resulting image is stored in the destination image if one + * is provided; otherwise a new BufferedImage is created and returned. + * + * The source image cannot use an IndexColorModel, and the destination image + * (if one is provided) must have the same size. + * + * @param src The source image. + * @param dst The destination image. + * @throws IllegalArgumentException if the rasters and/or color spaces are + * incompatible. + * @throws ArrayIndexOutOfBoundsException if a pixel in the source is not + * contained in the LookupTable. + * @return The convolved image. + */ + public final BufferedImage filter(BufferedImage src, BufferedImage dst) + { + if (src.getColorModel() instanceof IndexColorModel) + throw new IllegalArgumentException("LookupOp.filter: IndexColorModel " + + "not allowed"); + + if (lut.getNumComponents() != 1 + && lut.getNumComponents() != src.getColorModel().getNumComponents() + && lut.getNumComponents() != src.getColorModel().getNumColorComponents()) + throw new IllegalArgumentException("LookupOp.filter: Incompatible " + + "lookup table and source image"); + + if (dst == null) + dst = createCompatibleDestImage(src, null); + + else if (src.getHeight() != dst.getHeight() || src.getWidth() != dst.getWidth()) + throw new IllegalArgumentException("Source and destination images are " + + "different sizes."); + + // Set up for potential colormodel mismatch + BufferedImage tgt; + if (dst.getColorModel().equals(src.getColorModel())) + tgt = dst; + else + tgt = createCompatibleDestImage(src, src.getColorModel()); + + Raster sr = src.getRaster(); + WritableRaster dr = tgt.getRaster(); + + if (src.getColorModel().hasAlpha() && + (lut.getNumComponents() == 1 || + lut.getNumComponents() == src.getColorModel().getNumColorComponents())) + { + // Need to ignore alpha for lookup + int[] dbuf = new int[src.getColorModel().getNumComponents()]; + int tmpBands = src.getColorModel().getNumColorComponents(); + int[] tmp = new int[tmpBands]; + + // Filter the pixels + for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++) + for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++) + { + // Filter only color components, but also copy alpha + sr.getPixel(x, y, dbuf); + System.arraycopy(dbuf, 0, tmp, 0, tmpBands); + dr.setPixel(x, y, lut.lookupPixel(tmp, dbuf)); + + /* The reference implementation does not use LookupTable.lookupPixel, + * but rather it seems to copy the table into a native array. The + * effect of this (a probable bug in their implementation) is that + * an out-of-bounds lookup on a ByteLookupTable will *not* throw an + * out of bounds exception, but will instead return random garbage. + * A bad lookup on a ShortLookupTable, however, will throw an + * exception. + * + * Instead of mimicing this behaviour, we always throw an + * ArrayOutofBoundsException by virtue of using + * LookupTable.lookupPixle. + */ + } + } + else + { + // No alpha to ignore + int[] dbuf = new int[src.getColorModel().getNumComponents()]; + + // Filter the pixels + for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++) + for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++) + dr.setPixel(x, y, lut.lookupPixel(sr.getPixel(x, y, dbuf), dbuf)); + } + + if (tgt != dst) + new ColorConvertOp(hints).filter(tgt, dst); + + return dst; + } + + /* (non-Javadoc) + * @see java.awt.image.BufferedImageOp#getBounds2D(java.awt.image.BufferedImage) + */ + public final Rectangle2D getBounds2D(BufferedImage src) + { + return src.getRaster().getBounds(); + } + + /* (non-Javadoc) + * @see java.awt.image.BufferedImageOp#createCompatibleDestImage(java.awt.image.BufferedImage, java.awt.image.ColorModel) + */ + public BufferedImage createCompatibleDestImage(BufferedImage src, + ColorModel dstCM) + { + if (dstCM != null) + return new BufferedImage(dstCM, + src.getRaster().createCompatibleWritableRaster(), + src.isAlphaPremultiplied(), null); + + // This is a strange exception, done for compatibility with the reference + // (as demonstrated by a mauve testcase) + int imgType = src.getType(); + if (imgType == BufferedImage.TYPE_USHORT_GRAY) + imgType = BufferedImage.TYPE_BYTE_GRAY; + + return new BufferedImage(src.getWidth(), src.getHeight(), imgType); + } + + /** + * Returns the corresponding destination point for a given source point. + * + * This Op will return the source point unchanged. + * + * @param src The source point. + * @param dst The destination point. + */ + public final Point2D getPoint2D(Point2D src, Point2D dst) + { + if (dst == null) + return (Point2D) src.clone(); + + dst.setLocation(src); + return dst; + } + + /** + * Return the LookupTable for this op. + * + * @return The lookup table. + */ + public final LookupTable getTable() + { + return lut; + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#getRenderingHints() + */ + public final RenderingHints getRenderingHints() + { + return hints; + } + + /** + * Filter a raster through a lookup table. + * + * Applies the lookup table for this Rasterop to each pixel of src and + * puts the results in dest. If dest is null, a new Raster is created and + * returned. + * + * @param src The source raster. + * @param dest The destination raster. + * @return The WritableRaster with the filtered pixels. + * @throws IllegalArgumentException if lookup table has more than one + * component but not the same as src and dest. + * @throws ArrayIndexOutOfBoundsException if a pixel in the source is not + * contained in the LookupTable. + */ + public final WritableRaster filter(Raster src, WritableRaster dest) + { + if (dest == null) + // Allocate a raster if needed + dest = createCompatibleDestRaster(src); + else + if (src.getNumBands() != dest.getNumBands()) + throw new IllegalArgumentException("Source and destination rasters " + + "are incompatible."); + + if (lut.getNumComponents() != 1 + && lut.getNumComponents() != src.getNumBands()) + throw new IllegalArgumentException("Lookup table is incompatible with " + + "this raster."); + + // Allocate pixel storage. + int[] tmp = new int[src.getNumBands()]; + + // Filter the pixels + for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++) + for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++) + dest.setPixel(x, y, lut.lookupPixel(src.getPixel(x, y, tmp), tmp)); + + /* The reference implementation does not use LookupTable.lookupPixel, + * but rather it seems to copy the table into a native array. The + * effect of this (a probable bug in their implementation) is that + * an out-of-bounds lookup on a ByteLookupTable will *not* throw an + * out of bounds exception, but will instead return random garbage. + * A bad lookup on a ShortLookupTable, however, will throw an + * exception. + * + * Instead of mimicing this behaviour, we always throw an + * ArrayOutofBoundsException by virtue of using + * LookupTable.lookupPixle. + */ + return dest; + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster) + */ + public final Rectangle2D getBounds2D(Raster src) + { + return src.getBounds(); + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster) + */ + public WritableRaster createCompatibleDestRaster(Raster src) + { + return src.createCompatibleWritableRaster(); + } + +} diff --git a/openjdk/java/awt/image/RescaleOp.java b/openjdk/java/awt/image/RescaleOp.java new file mode 100644 index 0000000..d56b12c --- /dev/null +++ b/openjdk/java/awt/image/RescaleOp.java @@ -0,0 +1,385 @@ +/* Copyright (C) 2004, 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.awt.RenderingHints; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.Arrays; + +/** + * RescaleOp is a filter that changes each pixel by a scaling factor and offset. + * + * For filtering Rasters, either one scaling factor and offset can be specified, + * which will be applied to all bands; or a scaling factor and offset can be + * specified for each band. + * + * For BufferedImages, the scaling may apply to both color and alpha components. + * If only one scaling factor is provided, or if the number of factors provided + * equals the number of color components, the scaling is performed on all color + * components. Otherwise, the scaling is performed on all components including + * alpha. Alpha premultiplication is ignored. + * + * After filtering, if color conversion is necessary, the conversion happens, + * taking alpha premultiplication into account. + * + * @author Jerry Quinn (jlquinn@optonline.net) + * @author Francis Kung (fkung@redhat.com) + */ +public class RescaleOp implements BufferedImageOp, RasterOp +{ + private float[] scale; + private float[] offsets; + private RenderingHints hints = null; + + /** + * Create a new RescaleOp object using the given scale factors and offsets. + * + * The length of the arrays must be equal to the number of bands (or number of + * data or color components) of the raster/image that this Op will be used on, + * otherwise an IllegalArgumentException will be thrown when calling the + * filter method. + * + * @param scaleFactors an array of scale factors. + * @param offsets an array of offsets. + * @param hints any rendering hints to use (can be null). + * @throws NullPointerException if the scaleFactors or offsets array is null. + */ + public RescaleOp(float[] scaleFactors, + float[] offsets, + RenderingHints hints) + { + int length = Math.min(scaleFactors.length, offsets.length); + + scale = new float[length]; + System.arraycopy(scaleFactors, 0, this.scale, 0, length); + + this.offsets = new float[length]; + System.arraycopy(offsets, 0, this.offsets, 0, length); + + this.hints = hints; + } + + /** + * Create a new RescaleOp object using the given scale factor and offset. + * + * The same scale factor and offset will be used on all bands/components. + * + * @param scaleFactor the scale factor to use. + * @param offset the offset to use. + * @param hints any rendering hints to use (can be null). + */ + public RescaleOp(float scaleFactor, + float offset, + RenderingHints hints) + { + scale = new float[]{ scaleFactor }; + offsets = new float[]{offset}; + this.hints = hints; + } + + /** + * Returns the scaling factors. This method accepts an optional array, which + * will be used to store the factors if not null (this avoids allocating a + * new array). If this array is too small to hold all the scaling factors, + * the array will be filled and the remaining factors discarded. + * + * @param scaleFactors array to store the scaling factors in (can be null). + * @return an array of scaling factors. + */ + public final float[] getScaleFactors(float[] scaleFactors) + { + if (scaleFactors == null) + scaleFactors = new float[scale.length]; + System.arraycopy(scale, 0, scaleFactors, 0, Math.min(scale.length, + scaleFactors.length)); + return scaleFactors; + } + + /** + * Returns the offsets. This method accepts an optional array, which + * will be used to store the offsets if not null (this avoids allocating a + * new array). If this array is too small to hold all the offsets, the array + * will be filled and the remaining factors discarded. + * + * @param offsets array to store the offsets in (can be null). + * @return an array of offsets. + */ + public final float[] getOffsets(float[] offsets) + { + if (offsets == null) + offsets = new float[this.offsets.length]; + System.arraycopy(this.offsets, 0, offsets, 0, Math.min(this.offsets.length, + offsets.length)); + return offsets; + } + + /** + * Returns the number of scaling factors / offsets. + * + * @return the number of scaling factors / offsets. + */ + public final int getNumFactors() + { + return scale.length; + } + + /* (non-Javadoc) + * @see java.awt.image.BufferedImageOp#getRenderingHints() + */ + public final RenderingHints getRenderingHints() + { + return hints; + } + + /** + * Converts the source image using the scale factors and offsets specified in + * the constructor. The resulting image is stored in the destination image if + * one is provided; otherwise a new BufferedImage is created and returned. + * + * The source image cannot use an IndexColorModel, and the destination image + * (if one is provided) must have the same size. + * + * If the final value of a sample is beyond the range of the color model, it + * will be clipped to the appropriate maximum / minimum. + * + * @param src The source image. + * @param dst The destination image. + * @throws IllegalArgumentException if the rasters and/or color spaces are + * incompatible. + * @return The rescaled image. + */ + public final BufferedImage filter(BufferedImage src, BufferedImage dst) + { + // Initial checks + if (scale.length != 1 + && scale.length != src.getColorModel().getNumComponents() + && (scale.length != src.getColorModel().getNumColorComponents())) + throw new IllegalArgumentException("Source image has wrong number of " + + "bands for these scaling factors."); + + if (dst == null) + dst = createCompatibleDestImage(src, null); + else if (src.getHeight() != dst.getHeight() + || src.getWidth() != dst.getWidth()) + throw new IllegalArgumentException("Source and destination images are " + + "different sizes."); + + // Prepare for possible colorspace conversion + BufferedImage dst2 = dst; + if (dst.getColorModel().getColorSpace().getType() != src.getColorModel().getColorSpace().getType()) + dst2 = createCompatibleDestImage(src, src.getColorModel()); + + // Figure out how many bands to scale + int numBands = scale.length; + if (scale.length == 1) + numBands = src.getColorModel().getNumColorComponents(); + boolean[] bands = new boolean[numBands]; + // this assumes the alpha, if present, is the last band + Arrays.fill(bands, true); + + // Perform rescaling + filter(src.getRaster(), dst2.getRaster(), bands); + + // Copy alpha band if needed (ie if it exists and wasn't scaled) + // NOTE: This assumes the alpha component is the last band! + if (src.getColorModel().hasAlpha() + && numBands == src.getColorModel().getNumColorComponents()) + { + + dst2.getRaster().setSamples(0, 0, src.getWidth(), src.getHeight(), + numBands, + src.getRaster().getSamples(0, 0, + src.getWidth(), + src.getHeight(), + numBands, + (int[]) null)); + } + + // Perform colorspace conversion if needed + if (dst != dst2) + new ColorConvertOp(hints).filter(dst2, dst); + + return dst; + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#filter(java.awt.image.Raster, java.awt.image.WritableRaster) + */ + public final WritableRaster filter(Raster src, WritableRaster dest) + { + // Required sanity checks + if (scale.length != 1 && scale.length != src.numBands) + throw new IllegalArgumentException("Number of rasters is incompatible " + + "with the number of scaling " + + "factors provided."); + + if (dest == null) + dest = src.createCompatibleWritableRaster(); + else if (src.getHeight() != dest.getHeight() + || src.getWidth() != dest.getWidth()) + throw new IllegalArgumentException("Source and destination rasters are " + + "different sizes."); + else if (src.numBands != dest.numBands) + throw new IllegalArgumentException("Source and destination rasters " + + "are incompatible."); + + // Filter all bands + boolean[] bands = new boolean[src.getNumBands()]; + Arrays.fill(bands, true); + return filter(src, dest, bands); + } + + /** + * Perform raster-based filtering on a selected number of bands. + * + * The length of the bands array should equal the number of bands; a true + * element indicates filtering should happen on the corresponding band, while + * a false element will skip the band. + * + * The rasters are assumed to be compatible and non-null. + * + * @param src the source raster. + * @param dest the destination raster. + * @param bands an array indicating which bands to filter. + * @throws NullPointerException if any parameter is null. + * @throws ArrayIndexOutOfBoundsException if the bands array is too small. + * @return the destination raster. + */ + private WritableRaster filter(Raster src, WritableRaster dest, boolean[] bands) + { + int[] values = new int[src.getHeight() * src.getWidth()]; + float scaleFactor, offset; + + // Find max sample value, to be used for clipping later + int[] maxValue = src.getSampleModel().getSampleSize(); + for (int i = 0; i < maxValue.length; i++) + maxValue[i] = (int)Math.pow(2, maxValue[i]) - 1; + + // TODO: can this be optimized further? + // Filter all samples of all requested bands + for (int band = 0; band < bands.length; band++) + if (bands[band]) + { + values = src.getSamples(src.getMinX(), src.getMinY(), src.getWidth(), + src.getHeight(), band, values); + + if (scale.length == 1) + { + scaleFactor = scale[0]; + offset = offsets[0]; + } + else + { + scaleFactor = scale[band]; + offset = offsets[band]; + } + + for (int i = 0; i < values.length; i++) + { + values[i] = (int) (values[i] * scaleFactor + offset); + + // Clip if needed + if (values[i] < 0) + values[i] = 0; + if (values[i] > maxValue[band]) + values[i] = maxValue[band]; + } + + dest.setSamples(dest.getMinX(), dest.getMinY(), dest.getWidth(), + dest.getHeight(), band, values); + } + + return dest; + } + + /* + * (non-Javadoc) + * + * @see java.awt.image.BufferedImageOp#createCompatibleDestImage(java.awt.image.BufferedImage, + * java.awt.image.ColorModel) + */ + public BufferedImage createCompatibleDestImage(BufferedImage src, + ColorModel dstCM) + { + if (dstCM == null) + return new BufferedImage(src.getWidth(), src.getHeight(), src.getType()); + + return new BufferedImage(dstCM, + src.getRaster().createCompatibleWritableRaster(), + src.isAlphaPremultiplied(), null); + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster) + */ + public WritableRaster createCompatibleDestRaster(Raster src) + { + return src.createCompatibleWritableRaster(); + } + + /* (non-Javadoc) + * @see java.awt.image.BufferedImageOp#getBounds2D(java.awt.image.BufferedImage) + */ + public final Rectangle2D getBounds2D(BufferedImage src) + { + return src.getRaster().getBounds(); + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster) + */ + public final Rectangle2D getBounds2D(Raster src) + { + return src.getBounds(); + } + + /* (non-Javadoc) + * @see java.awt.image.BufferedImageOp#getPoint2D(java.awt.geom.Point2D, java.awt.geom.Point2D) + */ + public final Point2D getPoint2D(Point2D src, Point2D dst) + { + if (dst == null) + dst = (Point2D) src.clone(); + else + dst.setLocation(src); + + return dst; + } + +} diff --git a/openjdk/java/io/DefaultFileSystem.java b/openjdk/java/io/DefaultFileSystem.java new file mode 100644 index 0000000..7fcb523 --- /dev/null +++ b/openjdk/java/io/DefaultFileSystem.java @@ -0,0 +1,35 @@ +/* + Copyright (C) 2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package java.io; + +class DefaultFileSystem +{ + static FileSystem getFileSystem() + { + return ikvm.internal.Util.WINDOWS + ? new WinNTFileSystem() + : new UnixFileSystem(); + } +} diff --git a/openjdk/java/io/FileDescriptor.java b/openjdk/java/io/FileDescriptor.java new file mode 100644 index 0000000..128112a --- /dev/null +++ b/openjdk/java/io/FileDescriptor.java @@ -0,0 +1,781 @@ +/* + * Copyright (c) 2003, 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 java.io; + +import cli.System.IO.FileAccess; +import cli.System.IO.FileMode; +import cli.System.IO.FileShare; +import cli.System.IO.FileStream; +import cli.System.IO.SeekOrigin; +import cli.System.Runtime.InteropServices.DllImportAttribute; +import java.util.ArrayList; +import java.util.List; + +/** + * Instances of the file descriptor class serve as an opaque handle + * to the underlying machine-specific structure representing an + * open file, an open socket, or another source or sink of bytes. + * The main practical use for a file descriptor is to create a + * {@link FileInputStream} or {@link FileOutputStream} to contain it. + * + *

Applications should not create their own file descriptors. + * + * @author Pavani Diwanji + * @since JDK1.0 + */ +public final class FileDescriptor { + + private volatile cli.System.IO.Stream stream; + private volatile cli.System.Net.Sockets.Socket socket; + private volatile boolean nonBlockingSocket; + private volatile cli.System.IAsyncResult asyncResult; + + /** + * HACK + * JRuby uses reflection to get at the handle (on Windows) and fd (on non-Windows) + * fields to convert it into a native handle and query if it is a tty. + */ + @ikvm.lang.Property(get = "get_fd") + private int fd; + + @ikvm.lang.Property(get = "get_handle") + private long handle; + + private Closeable parent; + private List otherParents; + private boolean closed; + + @cli.System.Security.SecurityCriticalAttribute.Annotation + private long get_handle() + { + if (ikvm.internal.Util.WINDOWS) + { + if (stream instanceof cli.System.IO.FileStream) + { + cli.System.IO.FileStream fs = (cli.System.IO.FileStream)stream; + return fs.get_Handle().ToInt64(); + } + else if (this == in) + { + return GetStdHandle(-10).ToInt64(); + } + else if (this == out) + { + return GetStdHandle(-11).ToInt64(); + } + else if (this == err) + { + return GetStdHandle(-12).ToInt64(); + } + } + return -1; + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + private int get_fd() + { + if (!ikvm.internal.Util.WINDOWS) + { + if (stream instanceof cli.System.IO.FileStream) + { + cli.System.IO.FileStream fs = (cli.System.IO.FileStream)stream; + return fs.get_Handle().ToInt32(); + } + else if (this == in) + { + return 0; + } + else if (this == out) + { + return 1; + } + else if (this == err) + { + return 2; + } + } + return -1; + } + + @DllImportAttribute.Annotation("kernel32") + private static native cli.System.IntPtr GetStdHandle(int nStdHandle); + + /** + * Constructs an (invalid) FileDescriptor + * object. + */ + public /**/ FileDescriptor() { + } + + /** + * A handle to the standard input stream. Usually, this file + * descriptor is not used directly, but rather via the input stream + * known as {@code System.in}. + * + * @see java.lang.System#in + */ + public static final FileDescriptor in = standardStream(0); + + /** + * A handle to the standard output stream. Usually, this file + * descriptor is not used directly, but rather via the output stream + * known as {@code System.out}. + * @see java.lang.System#out + */ + public static final FileDescriptor out = standardStream(1); + + /** + * A handle to the standard error stream. Usually, this file + * descriptor is not used directly, but rather via the output stream + * known as {@code System.err}. + * + * @see java.lang.System#err + */ + public static final FileDescriptor err = standardStream(2); + + /** + * Tests if this file descriptor object is valid. + * + * @return {@code true} if the file descriptor object represents a + * valid, open file, socket, or other active I/O connection; + * {@code false} otherwise. + */ + public boolean valid() { + return stream != null || socket != null; + } + + /** + * Force all system buffers to synchronize with the underlying + * device. This method returns after all modified data and + * attributes of this FileDescriptor have been written to the + * relevant device(s). In particular, if this FileDescriptor + * refers to a physical storage medium, such as a file in a file + * system, sync will not return until all in-memory modified copies + * of buffers associated with this FileDesecriptor have been + * written to the physical medium. + * + * sync is meant to be used by code that requires physical + * storage (such as a file) to be in a known state For + * example, a class that provided a simple transaction facility + * might use sync to ensure that all changes to a file caused + * by a given transaction were recorded on a storage medium. + * + * sync only affects buffers downstream of this FileDescriptor. If + * any in-memory buffering is being done by the application (for + * example, by a BufferedOutputStream object), those buffers must + * be flushed into the FileDescriptor (for example, by invoking + * OutputStream.flush) before that data will be affected by sync. + * + * @exception SyncFailedException + * Thrown when the buffers cannot be flushed, + * or because the system cannot guarantee that all the + * buffers have been synchronized with physical media. + * @since JDK1.1 + */ + public void sync() throws SyncFailedException + { + if (stream == null) + { + throw new SyncFailedException("sync failed"); + } + + if (!stream.get_CanWrite()) + { + return; + } + + try + { + if (false) throw new cli.System.IO.IOException(); + stream.Flush(); + } + catch (cli.System.IO.IOException x) + { + throw new SyncFailedException(x.getMessage()); + } + + if (stream instanceof FileStream) + { + FileStream fs = (FileStream)stream; + boolean ok = ikvm.internal.Util.WINDOWS ? flushWin32(fs) : flushPosix(fs); + if (!ok) + { + throw new SyncFailedException("sync failed"); + } + } + } + + private static native boolean flushPosix(FileStream fs); + + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + private static boolean flushWin32(FileStream fs) + { + return FlushFileBuffers(fs.get_SafeFileHandle()) != 0; + } + + @DllImportAttribute.Annotation("kernel32") + private static native int FlushFileBuffers(cli.Microsoft.Win32.SafeHandles.SafeFileHandle handle); + + private static FileDescriptor standardStream(int fd) { + FileDescriptor desc = new FileDescriptor(); + try + { + desc.stream = getStandardStream(fd); + } + catch (cli.System.MissingMethodException _) + { + desc.stream = cli.System.IO.Stream.Null; + } + return desc; + } + + private static cli.System.IO.Stream getStandardStream(int fd) throws cli.System.MissingMethodException + { + switch (fd) + { + case 0: + return cli.System.Console.OpenStandardInput(); + case 1: + return cli.System.Console.OpenStandardOutput(); + case 2: + return cli.System.Console.OpenStandardError(); + default: + throw new Error(); + } + } + + /* + * Package private methods to track referents. + * If multiple streams point to the same FileDescriptor, we cycle + * through the list of all referents and call close() + */ + + /** + * Attach a Closeable to this FD for tracking. + * parent reference is added to otherParents when + * needed to make closeAll simpler. + */ + synchronized void attach(Closeable c) { + if (parent == null) { + // first caller gets to do this + parent = c; + } else if (otherParents == null) { + otherParents = new ArrayList<>(); + otherParents.add(parent); + otherParents.add(c); + } else { + otherParents.add(c); + } + } + + /** + * Cycle through all Closeables sharing this FD and call + * close() on each one. + * + * The caller closeable gets to call close0(). + */ + @SuppressWarnings("try") + synchronized void closeAll(Closeable releaser) throws IOException { + if (!closed) { + closed = true; + IOException ioe = null; + try (Closeable c = releaser) { + if (otherParents != null) { + for (Closeable referent : otherParents) { + try { + referent.close(); + } catch(IOException x) { + if (ioe == null) { + ioe = x; + } else { + ioe.addSuppressed(x); + } + } + } + } + } catch(IOException ex) { + /* + * If releaser close() throws IOException + * add other exceptions as suppressed. + */ + if (ioe != null) + ex.addSuppressed(ioe); + ioe = ex; + } finally { + if (ioe != null) + throw ioe; + } + } + } + + void openReadOnly(String name) throws FileNotFoundException + { + open(name, FileMode.Open, FileAccess.Read); + } + + void openWriteOnly(String name) throws FileNotFoundException + { + open(name, FileMode.Create, FileAccess.Write); + } + + void openReadWrite(String name) throws FileNotFoundException + { + open(name, FileMode.OpenOrCreate, FileAccess.ReadWrite); + } + + void openAppend(String name) throws FileNotFoundException + { + open(name, FileMode.Append, FileAccess.Write); + } + + private static native cli.System.IO.Stream open(String name, FileMode fileMode, FileAccess fileAccess) + throws cli.System.IO.IOException, + cli.System.Security.SecurityException, + cli.System.UnauthorizedAccessException, + cli.System.ArgumentException, + cli.System.NotSupportedException; + + private void open(String name, int fileMode, int fileAccess) throws FileNotFoundException + { + try + { + stream = open(name, FileMode.wrap(fileMode), FileAccess.wrap(fileAccess)); + } + catch (cli.System.Security.SecurityException x1) + { + throw new SecurityException(x1.getMessage()); + } + catch (cli.System.IO.IOException x2) + { + throw new FileNotFoundException(x2.getMessage()); + } + catch (cli.System.UnauthorizedAccessException x3) + { + // this is caused by "name" being a directory instead of a file + // or by name being a read-only file + throw new FileNotFoundException(name + " (Access is denied)"); + } + catch (cli.System.ArgumentException x4) + { + throw new FileNotFoundException(x4.getMessage()); + } + catch (cli.System.NotSupportedException x5) + { + throw new FileNotFoundException(x5.getMessage()); + } + } + + private void checkOpen() throws IOException + { + if (stream == null) + { + throw new IOException("Stream Closed"); + } + } + + int read() throws IOException + { + checkOpen(); + try + { + if (false) throw new cli.System.NotSupportedException(); + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.ObjectDisposedException(null); + return stream.ReadByte(); + } + catch (cli.System.NotSupportedException x) + { + throw new IOException(x.getMessage()); + } + catch (cli.System.IO.IOException x) + { + throw new IOException(x.getMessage()); + } + catch (cli.System.ObjectDisposedException x) + { + throw new java.nio.channels.ClosedChannelException(); + } + } + + @ikvm.lang.Internal + public int readBytes(byte buf[], int offset, int len) throws IOException + { + // NOTE we start by dereferencing buf, to make sure you get a NullPointerException first if you pass a null reference. + int bufLen = buf.length; + if ((offset < 0) || (offset > bufLen) || (len < 0) || (len > (bufLen - offset))) + { + throw new IndexOutOfBoundsException(); + } + + if (len == 0) + { + return 0; + } + + checkOpen(); + + try + { + if (false) throw new cli.System.NotSupportedException(); + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.ObjectDisposedException(null); + int count = stream.Read(buf, offset, len); + if (count == 0) + { + count = -1; + } + return count; + } + catch (cli.System.NotSupportedException x) + { + throw new IOException(x.getMessage()); + } + catch (cli.System.IO.IOException x) + { + throw new IOException(x.getMessage()); + } + catch (cli.System.ObjectDisposedException x) + { + throw new java.nio.channels.ClosedChannelException(); + } + } + + long skip(long n) throws IOException + { + checkOpen(); + if (!stream.get_CanSeek()) + { + // in a somewhat bizar twist, for non-seekable streams the JDK throws an exception + throw new IOException("The handle is invalid"); + } + try + { + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.NotSupportedException(); + if (false) throw new cli.System.ObjectDisposedException(null); + long cur = stream.get_Position(); + long end = stream.Seek(n, SeekOrigin.wrap(SeekOrigin.Current)); + return end - cur; + } + catch (cli.System.IO.IOException x) + { + throw new IOException(x.getMessage()); + } + catch (cli.System.NotSupportedException x1) + { + // this means we have a broken Stream, because if CanSeek returns true, it must + // support Length and Position + throw new IOException(x1); + } + catch (cli.System.ObjectDisposedException x) + { + throw new java.nio.channels.ClosedChannelException(); + } + } + + @ikvm.lang.Internal + public int available() throws IOException + { + checkOpen(); + try + { + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.NotSupportedException(); + if (false) throw new cli.System.ObjectDisposedException(null); + if (stream.get_CanSeek()) + { + return (int)Math.min(Integer.MAX_VALUE, Math.max(0, stream.get_Length() - stream.get_Position())); + } + return 0; + } + catch (cli.System.IO.IOException x) + { + throw new IOException(x.getMessage()); + } + catch (cli.System.NotSupportedException x1) + { + // this means we have a broken Stream, because if CanSeek returns true, it must + // support Length and Position + throw new IOException(x1); + } + catch (cli.System.ObjectDisposedException x) + { + throw new java.nio.channels.ClosedChannelException(); + } + } + + void write(int b) throws IOException + { + checkOpen(); + try + { + if (false) throw new cli.System.NotSupportedException(); + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.ObjectDisposedException(null); + stream.WriteByte((byte)b); + // NOTE FileStream buffers the output, so we have to flush explicitly + stream.Flush(); + } + catch (cli.System.NotSupportedException x) + { + throw new IOException(x.getMessage()); + } + catch (cli.System.IO.IOException x) + { + throw new IOException(x.getMessage()); + } + catch (cli.System.ObjectDisposedException x) + { + throw new java.nio.channels.ClosedChannelException(); + } + } + + @ikvm.lang.Internal + public void writeBytes(byte buf[], int offset, int len) throws IOException + { + // NOTE we start by dereferencing buf, to make sure you get a NullPointerException first if you pass a null reference. + int bufLen = buf.length; + if ((offset < 0) || (offset > bufLen) || (len < 0) || (len > (bufLen - offset))) + { + throw new IndexOutOfBoundsException(); + } + + if (len == 0) + { + return; + } + + checkOpen(); + + try + { + if (false) throw new cli.System.NotSupportedException(); + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.ObjectDisposedException(null); + stream.Write(buf, offset, len); + // NOTE FileStream buffers the output, so we have to flush explicitly + stream.Flush(); + } + catch (cli.System.NotSupportedException x) + { + throw new IOException(x.getMessage()); + } + catch (cli.System.IO.IOException x) + { + throw new IOException(x.getMessage()); + } + catch (cli.System.ObjectDisposedException x) + { + throw new java.nio.channels.ClosedChannelException(); + } + } + + @ikvm.lang.Internal + public long getFilePointer() throws IOException + { + checkOpen(); + try + { + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.NotSupportedException(); + if (false) throw new cli.System.ObjectDisposedException(null); + return stream.get_Position(); + } + catch (cli.System.IO.IOException x) + { + throw new IOException(x.getMessage()); + } + catch (cli.System.NotSupportedException x1) + { + throw new IOException(x1); + } + catch (cli.System.ObjectDisposedException x) + { + throw new java.nio.channels.ClosedChannelException(); + } + } + + @ikvm.lang.Internal + public void seek(long newPosition) throws IOException + { + checkOpen(); + try + { + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.NotSupportedException(); + if (false) throw new cli.System.ObjectDisposedException(null); + if (false) throw new cli.System.ArgumentOutOfRangeException(); + stream.set_Position(newPosition); + } + catch (cli.System.IO.IOException x) + { + throw new IOException(x.getMessage()); + } + catch (cli.System.NotSupportedException x1) + { + throw new IOException(x1); + } + catch (cli.System.ObjectDisposedException x) + { + throw new java.nio.channels.ClosedChannelException(); + } + catch (cli.System.ArgumentOutOfRangeException _) + { + throw new IOException("Negative seek offset"); + } + } + + @ikvm.lang.Internal + public long length() throws IOException + { + checkOpen(); + try + { + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.NotSupportedException(); + if (false) throw new cli.System.ObjectDisposedException(null); + return stream.get_Length(); + } + catch (cli.System.IO.IOException x) + { + throw new IOException(x.getMessage()); + } + catch (cli.System.NotSupportedException x1) + { + throw new IOException(x1); + } + catch (cli.System.ObjectDisposedException x) + { + throw new java.nio.channels.ClosedChannelException(); + } + } + + @ikvm.lang.Internal + public void setLength(long newLength) throws IOException + { + checkOpen(); + try + { + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.NotSupportedException(); + if (false) throw new cli.System.ObjectDisposedException(null); + stream.SetLength(newLength); + } + catch (cli.System.IO.IOException x) + { + throw new IOException(x.getMessage()); + } + catch (cli.System.NotSupportedException x1) + { + throw new IOException(x1); + } + catch (cli.System.ObjectDisposedException x) + { + throw new java.nio.channels.ClosedChannelException(); + } + } + + @ikvm.lang.Internal + public void close() throws IOException + { + cli.System.IO.Stream s = stream; + stream = null; + if (s != null) + { + s.Close(); + } + } + + @ikvm.lang.Internal + public cli.System.IO.Stream getStream() + { + return stream; + } + + @ikvm.lang.Internal + public static FileDescriptor fromStream(cli.System.IO.Stream stream) + { + FileDescriptor desc = new FileDescriptor(); + desc.stream = stream; + return desc; + } + + @ikvm.lang.Internal + public cli.System.Net.Sockets.Socket getSocket() + { + return socket; + } + + @ikvm.lang.Internal + public void setSocket(cli.System.Net.Sockets.Socket socket) + { + this.socket = socket; + } + + @ikvm.lang.Internal + public void setSocketBlocking(boolean blocking) throws IOException + { + this.nonBlockingSocket = !blocking; + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + socket.set_Blocking(blocking); + } + catch (cli.System.Net.Sockets.SocketException x) + { + if (x.get_ErrorCode() == java.net.SocketUtil.WSAEINVAL) + { + // Work around for winsock issue. You can't set a socket to blocking if a connection request is pending, + // so we'll have to set the blocking again in SocketChannelImpl.checkConnect(). + return; + } + throw java.net.SocketUtil.convertSocketExceptionToIOException(x); + } + catch (cli.System.ObjectDisposedException _) + { + throw new java.net.SocketException("Socket is closed"); + } + } + + @ikvm.lang.Internal + public boolean isSocketBlocking() + { + return !nonBlockingSocket; + } + + @ikvm.lang.Internal + public cli.System.IAsyncResult getAsyncResult() + { + return asyncResult; + } + + @ikvm.lang.Internal + public void setAsyncResult(cli.System.IAsyncResult asyncResult) + { + this.asyncResult = asyncResult; + } +} diff --git a/openjdk/java/io/InteropObjectInputStream.java b/openjdk/java/io/InteropObjectInputStream.java new file mode 100644 index 0000000..de08fe3 --- /dev/null +++ b/openjdk/java/io/InteropObjectInputStream.java @@ -0,0 +1,740 @@ +/* + * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright 2009 Jeroen Frijters + * 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 java.io; + +import cli.System.Runtime.Serialization.SerializationException; +import cli.System.Runtime.Serialization.SerializationInfo; +import java.util.concurrent.atomic.AtomicBoolean; + +@ikvm.lang.Internal +public final class InteropObjectInputStream extends ObjectInputStream +{ + private ObjectDataInputStream dis; + private CallbackContext curContext; + + public static void readObject(Object obj, SerializationInfo info) + { + try + { + new InteropObjectInputStream(obj, info); + } + catch (Exception x) + { + ikvm.runtime.Util.throwException(new SerializationException(x.getMessage(), x)); + } + } + + private InteropObjectInputStream(Object obj, SerializationInfo info) throws IOException, ClassNotFoundException + { + dis = new ObjectDataInputStream(info); + if (obj instanceof ObjectStreamClass) + { + switch (readByte()) + { + case TC_PROXYCLASSDESC: + readProxyDesc((ObjectStreamClass)obj); + break; + case TC_CLASSDESC: + readNonProxyDesc((ObjectStreamClass)obj); + break; + default: + throw new StreamCorruptedException(); + } + } + else + { + readOrdinaryObject(obj); + } + } + + private ObjectStreamClass readClassDesc() throws IOException, ClassNotFoundException + { + return (ObjectStreamClass)readObject(); + } + + private void readProxyDesc(ObjectStreamClass desc) throws IOException, ClassNotFoundException + { + int numIfaces = readInt(); + Class[] ifaces = new Class[numIfaces]; + for (int i = 0; i < numIfaces; i++) + { + ifaces[i] = (Class)readObject(); + } + Class cl = java.lang.reflect.Proxy.getProxyClass(Thread.currentThread().getContextClassLoader(), ifaces); + desc.initProxy(cl, null, readClassDesc()); + } + + private void readNonProxyDesc(ObjectStreamClass desc) throws IOException, ClassNotFoundException + { + Class cl = (Class)readObject(); + ObjectStreamClass readDesc = new ObjectStreamClass(); + readDesc.readNonProxy(this); + desc.initNonProxy(readDesc, cl, null, readClassDesc()); + } + + private void readOrdinaryObject(Object obj) throws IOException, ClassNotFoundException + { + ObjectStreamClass desc = readClassDesc(); + desc.checkDeserialize(); + + if (obj instanceof InteropObjectOutputStream.DynamicProxy) + { + InteropObjectOutputStream.DynamicProxy pp = (InteropObjectOutputStream.DynamicProxy)obj; + try + { + obj = desc.newInstance(); + pp.obj = obj; + } + catch (Exception ex) + { + throw (IOException) new InvalidClassException( + desc.forClass().getName(), + "unable to create instance").initCause(ex); + } + } + + if (desc.isExternalizable()) + { + readExternalData((Externalizable)obj, desc); + } + else + { + readSerialData(obj, desc); + } + } + + private void readExternalData(Externalizable obj, ObjectStreamClass desc) throws IOException, ClassNotFoundException + { + CallbackContext oldContext = curContext; + curContext = null; + try { + obj.readExternal(this); + skipCustomData(); + } finally { + curContext = oldContext; + } + } + + private void readSerialData(Object obj, ObjectStreamClass desc) throws IOException, ClassNotFoundException + { + ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout(); + for (int i = 0; i < slots.length; i++) + { + ObjectStreamClass slotDesc = slots[i].desc; + + if (slots[i].hasData) + { + if (slotDesc.hasReadObjectMethod()) + { + CallbackContext oldContext = curContext; + try + { + curContext = new CallbackContext(obj, slotDesc); + slotDesc.invokeReadObject(obj, this); + } + finally + { + curContext.setUsed(); + curContext = oldContext; + } + } + else + { + defaultReadFields(obj, slotDesc); + } + if (slotDesc.hasWriteObjectData()) + { + skipCustomData(); + } + } + else if (slotDesc.hasReadObjectNoDataMethod()) + { + slotDesc.invokeReadObjectNoData(obj); + } + } + } + + private void skipCustomData() throws IOException + { + dis.skipMarker(); + } + + private void defaultReadFields(Object obj, ObjectStreamClass desc) throws IOException, ClassNotFoundException + { + byte[] primVals = new byte[desc.getPrimDataSize()]; + readFully(primVals); + desc.setPrimFieldValues(obj, primVals); + + Object[] objVals = new Object[desc.getNumObjFields()]; + for (int i = 0; i < objVals.length; i++) + { + objVals[i] = readObject(); + } + desc.setObjFieldValues(obj, objVals); + } + + @Override + public void defaultReadObject() throws IOException, ClassNotFoundException + { + if (curContext == null) { + throw new NotActiveException("not in call to readObject"); + } + Object curObj = curContext.getObj(); + ObjectStreamClass curDesc = curContext.getDesc(); + defaultReadFields(curObj, curDesc); + } + + @Override + protected Object readObjectOverride() throws IOException + { + return dis.readObject(); + } + + @Override + public Object readUnshared() + { + throw new UnsupportedOperationException(); + } + + @Override + public ObjectInputStream.GetField readFields() throws IOException, ClassNotFoundException + { + if (curContext == null) { + throw new NotActiveException("not in call to readObject"); + } + Object curObj = curContext.getObj(); + ObjectStreamClass curDesc = curContext.getDesc(); + GetFieldImpl getField = new GetFieldImpl(curDesc); + getField.readFields(); + return getField; + } + + @Override + public void registerValidation(ObjectInputValidation obj, int prio) + { + throw new UnsupportedOperationException(); + } + + @Override + public int read() throws IOException + { + return dis.read(); + } + + @Override + public int read(byte[] buf, int off, int len) throws IOException + { + return dis.read(buf, off, len); + } + + @Override + public int available() throws IOException + { + return dis.available(); + } + + @Override + public void close() throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public boolean readBoolean() throws IOException + { + return dis.readBoolean(); + } + + @Override + public byte readByte() throws IOException + { + return dis.readByte(); + } + + @Override + public int readUnsignedByte() throws IOException + { + return dis.readUnsignedByte(); + } + + @Override + public char readChar() throws IOException + { + return dis.readChar(); + } + + @Override + public short readShort() throws IOException + { + return dis.readShort(); + } + + @Override + public int readUnsignedShort() throws IOException + { + return dis.readUnsignedShort(); + } + + @Override + public int readInt() throws IOException + { + return dis.readInt(); + } + + @Override + public long readLong() throws IOException + { + return dis.readLong(); + } + + @Override + public float readFloat() throws IOException + { + return dis.readFloat(); + } + + @Override + public double readDouble() throws IOException + { + return dis.readDouble(); + } + + @Override + public void readFully(byte[] buf) throws IOException + { + readFully(buf, 0, buf.length); + } + + @Override + public void readFully(byte[] buf, int off, int len) throws IOException + { + dis.readFully(buf, off, len); + } + + @Override + public int skipBytes(int len) throws IOException + { + return dis.skipBytes(len); + } + + @Deprecated + @Override + public String readLine() throws IOException + { + return dis.readLine(); + } + + @Override + public String readUTF() throws IOException + { + return dis.readUTF(); + } + + // private API used by ObjectStreamClass + @Override + String readTypeString() throws IOException + { + return (String)readObjectOverride(); + } + + private final class GetFieldImpl extends GetField { + + /** class descriptor describing serializable fields */ + private final ObjectStreamClass desc; + /** primitive field values */ + private final byte[] primVals; + /** object field values */ + private final Object[] objVals; + /** object field value handles */ + private final int[] objHandles; + + /** + * Creates GetFieldImpl object for reading fields defined in given + * class descriptor. + */ + GetFieldImpl(ObjectStreamClass desc) { + this.desc = desc; + primVals = new byte[desc.getPrimDataSize()]; + objVals = new Object[desc.getNumObjFields()]; + objHandles = new int[objVals.length]; + } + + public ObjectStreamClass getObjectStreamClass() { + return desc; + } + + public boolean defaulted(String name) throws IOException { + return (getFieldOffset(name, null) < 0); + } + + public boolean get(String name, boolean val) throws IOException { + int off = getFieldOffset(name, Boolean.TYPE); + return (off >= 0) ? Bits.getBoolean(primVals, off) : val; + } + + public byte get(String name, byte val) throws IOException { + int off = getFieldOffset(name, Byte.TYPE); + return (off >= 0) ? primVals[off] : val; + } + + public char get(String name, char val) throws IOException { + int off = getFieldOffset(name, Character.TYPE); + return (off >= 0) ? Bits.getChar(primVals, off) : val; + } + + public short get(String name, short val) throws IOException { + int off = getFieldOffset(name, Short.TYPE); + return (off >= 0) ? Bits.getShort(primVals, off) : val; + } + + public int get(String name, int val) throws IOException { + int off = getFieldOffset(name, Integer.TYPE); + return (off >= 0) ? Bits.getInt(primVals, off) : val; + } + + public float get(String name, float val) throws IOException { + int off = getFieldOffset(name, Float.TYPE); + return (off >= 0) ? Bits.getFloat(primVals, off) : val; + } + + public long get(String name, long val) throws IOException { + int off = getFieldOffset(name, Long.TYPE); + return (off >= 0) ? Bits.getLong(primVals, off) : val; + } + + public double get(String name, double val) throws IOException { + int off = getFieldOffset(name, Double.TYPE); + return (off >= 0) ? Bits.getDouble(primVals, off) : val; + } + + public Object get(String name, Object val) throws IOException { + int off = getFieldOffset(name, Object.class); + if (off >= 0) { + return objVals[off]; + } else { + return val; + } + } + + /** + * Reads primitive and object field values from stream. + */ + void readFields() throws IOException { + readFully(primVals, 0, primVals.length); + + for (int i = 0; i < objVals.length; i++) { + objVals[i] = readObjectOverride(); + } + } + + /** + * Returns offset of field with given name and type. A specified type + * of null matches all types, Object.class matches all non-primitive + * types, and any other non-null type matches assignable types only. + * If no matching field is found in the (incoming) class + * descriptor but a matching field is present in the associated local + * class descriptor, returns -1. Throws IllegalArgumentException if + * neither incoming nor local class descriptor contains a match. + */ + private int getFieldOffset(String name, Class type) { + ObjectStreamField field = desc.getField(name, type); + if (field != null) { + return field.getOffset(); + } else if (desc.getLocalDesc().getField(name, type) != null) { + return -1; + } else { + throw new IllegalArgumentException("no such field " + name + + " with type " + type); + } + } + } + + private final static class CallbackContext { + private final Object obj; + private final ObjectStreamClass desc; + private final AtomicBoolean used = new AtomicBoolean(); + + public CallbackContext(Object obj, ObjectStreamClass desc) { + this.obj = obj; + this.desc = desc; + } + + public Object getObj() throws NotActiveException { + checkAndSetUsed(); + return obj; + } + + public ObjectStreamClass getDesc() { + return desc; + } + + private void checkAndSetUsed() throws NotActiveException { + if (!used.compareAndSet(false, true)) { + throw new NotActiveException( + "not in readObject invocation or fields already read"); + } + } + + public void setUsed() { + used.set(true); + } + } + + private static final class ObjectDataInputStream extends DataInputStream + { + private final static class Inp extends FilterInputStream + { + private static final byte MARKER = 0; + private static final byte OBJECTS = 10; + private static final byte BYTES = 20; + private final SerializationInfo info; + private byte[] buf; + private int pos; + private int blockEnd = -1; + private int objCount; + private int objId; + + Inp(SerializationInfo info) throws IOException + { + super(null); + this.info = info; + buf = (byte[])info.GetValue("$data", ikvm.runtime.Util.getInstanceTypeFromClass(cli.System.Object.class)); + modeSwitch(); + } + + private void modeSwitch() throws IOException + { + if (pos == buf.length) + { + // next read will report error + blockEnd = -1; + objCount = -1; + } + else if (buf[pos] == OBJECTS) + { + pos++; + objCount = readPacked(); + blockEnd = -1; + } + else if (buf[pos] == BYTES) + { + pos++; + switchToData(); + } + else if (buf[pos] == MARKER) + { + } + else + { + throw new StreamCorruptedException(); + } + } + + private int packedLength(int val) + { + if (val < 0) + { + // we only use packed integers for lengths or counts, so they can never be negative + throw new Error(); + } + else if (val < 128) + { + return 1; + } + else if (val < 16129) + { + return 2; + } + else + { + return 5; + } + } + + private int readPacked() + { + int b1 = buf[pos++] & 0xFF; + if (b1 < 128) + { + return b1; + } + else if (b1 != 128) + { + return ((b1 & 127) << 7) + (buf[pos++] & 0xFF); + } + else + { + int v = 0; + v |= (buf[pos++] & 0xFF) << 24; + v |= (buf[pos++] & 0xFF) << 16; + v |= (buf[pos++] & 0xFF) << 8; + v |= (buf[pos++] & 0xFF) << 0; + return v; + } + } + + private void switchToData() throws IOException + { + if (blockEnd != -1 || objCount != 0 || buf[pos] == MARKER) + { + throw new StreamCorruptedException(); + } + int len = readPacked(); + blockEnd = pos + len; + if (blockEnd > buf.length) + { + throw new StreamCorruptedException(); + } + } + + public int read() throws IOException + { + if (blockEnd - pos < 1) + { + switchToData(); + } + return buf[pos++] & 0xFF; + } + + public int read(byte b[], int off, int len) throws IOException + { + if (len == 0) + { + return 0; + } + if (blockEnd - pos < len) + { + switchToData(); + } + System.arraycopy(buf, pos, b, off, len); + pos += len; + return len; + } + + public long skip(long n) throws IOException + { + if (n == 0) + { + return 0; + } + if (blockEnd - pos < n) + { + switchToData(); + } + pos += (int)n; + return n; + } + + public int available() throws IOException + { + return 0; + } + + public void close() throws IOException + { + } + + public void mark(int readlimit) + { + } + + public void reset() throws IOException + { + } + + public boolean markSupported() + { + return false; + } + + Object readObject() throws IOException + { + if (objCount <= 0) + { + if (pos != blockEnd || buf[pos] == MARKER) + { + throw new StreamCorruptedException(); + } + blockEnd = -1; + objCount = readPacked(); + } + objCount--; + return info.GetValue("$" + (objId++), ikvm.runtime.Util.getInstanceTypeFromClass(cli.System.Object.class)); + } + + void skipMarker() throws IOException + { + for (;;) + { + if (objCount > 0) + { + objId += objCount; + objCount = 0; + if (buf[pos] == MARKER) + { + pos++; + modeSwitch(); + break; + } + switchToData(); + } + if (blockEnd != -1) + { + pos = blockEnd; + blockEnd = -1; + } + if (pos == buf.length) + { + throw new StreamCorruptedException(); + } + if (buf[pos] == MARKER) + { + pos++; + modeSwitch(); + break; + } + blockEnd = -1; + objCount = readPacked(); + } + } + } + + ObjectDataInputStream(SerializationInfo info) throws IOException + { + super(new Inp(info)); + } + + public Object readObject() throws IOException + { + return ((Inp)in).readObject(); + } + + public void skipMarker() throws IOException + { + ((Inp)in).skipMarker(); + } + } +} diff --git a/openjdk/java/io/InteropObjectOutputStream.java b/openjdk/java/io/InteropObjectOutputStream.java new file mode 100644 index 0000000..f32c98b --- /dev/null +++ b/openjdk/java/io/InteropObjectOutputStream.java @@ -0,0 +1,738 @@ +/* + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright 2009 Jeroen Frijters + * 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 java.io; + +import cli.System.Runtime.Serialization.IObjectReference; +import cli.System.Runtime.Serialization.SerializationException; +import cli.System.Runtime.Serialization.SerializationInfo; +import cli.System.Runtime.Serialization.StreamingContext; +import cli.System.SerializableAttribute; +import java.util.ArrayList; + +@ikvm.lang.Internal +public final class InteropObjectOutputStream extends ObjectOutputStream +{ + private final ObjectDataOutputStream dos; + private Object curObj; + private ObjectStreamClass curDesc; + private PutFieldImpl curPut; + + @SerializableAttribute.Annotation + private static final class ReplaceProxy implements IObjectReference + { + private Object obj; + + @cli.System.Security.SecurityCriticalAttribute.Annotation + public Object GetRealObject(StreamingContext context) + { + return obj; + } + } + + static final class DynamicProxy implements Serializable + { + Object obj; + + private Object readResolve() + { + return obj; + } + } + + public static void writeObject(Object obj, SerializationInfo info) + { + try + { + boolean replaced = false; + Class cl = obj.getClass(); + ObjectStreamClass desc; + for (;;) + { + Class repCl; + desc = ObjectStreamClass.lookup(cl, true); + if (!desc.hasWriteReplaceMethod() || + (obj = desc.invokeWriteReplace(obj)) == null || + (repCl = obj.getClass()) == cl) + { + break; + } + cl = repCl; + replaced = true; + } + if (replaced) + { + info.AddValue("obj", obj); + info.SetType(ikvm.runtime.Util.getInstanceTypeFromClass(ReplaceProxy.class)); + } + else + { + new InteropObjectOutputStream(info, obj, cl, desc); + } + } + catch (IOException x) + { + ikvm.runtime.Util.throwException(new SerializationException(x.getMessage(), x)); + } + } + + private InteropObjectOutputStream(SerializationInfo info, Object obj, Class cl, ObjectStreamClass desc) throws IOException + { + dos = new ObjectDataOutputStream(info); + if (obj instanceof ObjectStreamClass) + { + ObjectStreamClass osc = (ObjectStreamClass)obj; + if (osc.isProxy()) + { + writeProxyDesc(osc); + } + else + { + writeNonProxyDesc(osc); + } + } + else if (obj instanceof Serializable) + { + if (desc.isDynamicClass()) + { + info.SetType(ikvm.runtime.Util.getInstanceTypeFromClass(DynamicProxy.class)); + } + writeOrdinaryObject(obj, desc); + } + else + { + throw new NotSerializableException(cl.getName()); + } + dos.close(); + } + + private void writeProxyDesc(ObjectStreamClass desc) throws IOException + { + writeByte(TC_PROXYCLASSDESC); + Class cl = desc.forClass(); + Class[] ifaces = cl.getInterfaces(); + writeInt(ifaces.length); + for (int i = 0; i < ifaces.length; i++) + { + writeObject(ifaces[i]); + } + writeObject(desc.getSuperDesc()); + } + + private void writeNonProxyDesc(ObjectStreamClass desc) throws IOException + { + writeByte(TC_CLASSDESC); + writeObject(desc.forClass()); + desc.writeNonProxy(this); + writeObject(desc.getSuperDesc()); + } + + private void writeOrdinaryObject(Object obj, ObjectStreamClass desc) throws IOException + { + desc.checkSerialize(); + writeObject(desc); + if (desc.isExternalizable() && !desc.isProxy()) + { + writeExternalData((Externalizable)obj); + } + else + { + writeSerialData(obj, desc); + } + } + + private void writeExternalData(Externalizable obj) throws IOException + { + Object oldObj = curObj; + ObjectStreamClass oldDesc = curDesc; + PutFieldImpl oldPut = curPut; + curObj = obj; + curDesc = null; + curPut = null; + + obj.writeExternal(this); + dos.writeMarker(); + + curObj = oldObj; + curDesc = oldDesc; + curPut = oldPut; + } + + private void writeSerialData(Object obj, ObjectStreamClass desc) throws IOException + { + ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout(); + for (int i = 0; i < slots.length; i++) + { + ObjectStreamClass slotDesc = slots[i].desc; + if (slotDesc.hasWriteObjectMethod()) + { + Object oldObj = curObj; + ObjectStreamClass oldDesc = curDesc; + PutFieldImpl oldPut = curPut; + curObj = obj; + curDesc = slotDesc; + curPut = null; + slotDesc.invokeWriteObject(obj, this); + dos.writeMarker(); + curObj = oldObj; + curDesc = oldDesc; + curPut = oldPut; + } + else + { + defaultWriteFields(obj, slotDesc); + } + } + } + + private void defaultWriteFields(Object obj, ObjectStreamClass desc) throws IOException + { + desc.checkDefaultSerialize(); + + byte[] primVals = new byte[desc.getPrimDataSize()]; + desc.getPrimFieldValues(obj, primVals); + write(primVals); + + Object[] objVals = new Object[desc.getNumObjFields()]; + desc.getObjFieldValues(obj, objVals); + for (int i = 0; i < objVals.length; i++) + { + writeObject(objVals[i]); + } + } + + @Override + public void defaultWriteObject() throws IOException + { + defaultWriteFields(curObj, curDesc); + } + + @Override + public void close() + { + throw new UnsupportedOperationException(); + } + + @Override + public void flush() + { + } + + @Override + public ObjectOutputStream.PutField putFields() throws IOException + { + if (curPut == null) + { + if (curObj == null || curDesc == null) + { + throw new NotActiveException("not in call to writeObject"); + } + curPut = new PutFieldImpl(curDesc); + } + return curPut; + } + + @Override + public void reset() throws IOException + { + throw new IOException("stream active"); + } + + @Override + protected void writeObjectOverride(Object obj) + { + // TODO consider tagging ghost arrays + dos.writeObject(obj); + } + + @Override + public void writeFields() throws IOException + { + if (curPut == null) + { + throw new NotActiveException("no current PutField object"); + } + curPut.writeFields(); + } + + @Override + public void writeUnshared(Object obj) + { + throw new UnsupportedOperationException(); + } + + @Override + public void useProtocolVersion(int version) + { + throw new IllegalStateException("stream non-empty"); + } + + @Override + public void write(byte[] buf) throws IOException + { + write(buf, 0, buf.length); + } + + @Override + public void write(int val) throws IOException + { + dos.write(val); + } + + @Override + public void write(byte[] buf, int off, int len) throws IOException + { + dos.write(buf, off, len); + } + + @Override + public void writeBoolean(boolean val) throws IOException + { + dos.writeBoolean(val); + } + + @Override + public void writeByte(int val) throws IOException + { + dos.writeByte(val); + } + + @Override + public void writeBytes(String str) throws IOException + { + dos.writeBytes(str); + } + + @Override + public void writeChar(int val) throws IOException + { + dos.writeChar(val); + } + + @Override + public void writeChars(String str) throws IOException + { + dos.writeChars(str); + } + + @Override + public void writeDouble(double val) throws IOException + { + dos.writeDouble(val); + } + + @Override + public void writeFloat(float val) throws IOException + { + dos.writeFloat(val); + } + + @Override + public void writeInt(int val) throws IOException + { + dos.writeInt(val); + } + + @Override + public void writeLong(long val) throws IOException + { + dos.writeLong(val); + } + + @Override + public void writeShort(int val) throws IOException + { + dos.writeShort(val); + } + + @Override + public void writeUTF(String str) throws IOException + { + dos.writeUTF(str); + } + + // private API used by ObjectStreamClass + @Override + void writeTypeString(String str) throws IOException + { + writeObject(str); + } + + private final class PutFieldImpl extends PutField { + + /** class descriptor describing serializable fields */ + private final ObjectStreamClass desc; + /** primitive field values */ + private final byte[] primVals; + /** object field values */ + private final Object[] objVals; + + /** + * Creates PutFieldImpl object for writing fields defined in given + * class descriptor. + */ + PutFieldImpl(ObjectStreamClass desc) { + this.desc = desc; + primVals = new byte[desc.getPrimDataSize()]; + objVals = new Object[desc.getNumObjFields()]; + } + + public void put(String name, boolean val) { + Bits.putBoolean(primVals, getFieldOffset(name, Boolean.TYPE), val); + } + + public void put(String name, byte val) { + primVals[getFieldOffset(name, Byte.TYPE)] = val; + } + + public void put(String name, char val) { + Bits.putChar(primVals, getFieldOffset(name, Character.TYPE), val); + } + + public void put(String name, short val) { + Bits.putShort(primVals, getFieldOffset(name, Short.TYPE), val); + } + + public void put(String name, int val) { + Bits.putInt(primVals, getFieldOffset(name, Integer.TYPE), val); + } + + public void put(String name, float val) { + Bits.putFloat(primVals, getFieldOffset(name, Float.TYPE), val); + } + + public void put(String name, long val) { + Bits.putLong(primVals, getFieldOffset(name, Long.TYPE), val); + } + + public void put(String name, double val) { + Bits.putDouble(primVals, getFieldOffset(name, Double.TYPE), val); + } + + public void put(String name, Object val) { + objVals[getFieldOffset(name, Object.class)] = val; + } + + // deprecated in ObjectOutputStream.PutField + public void write(ObjectOutput out) throws IOException { + /* + * Applications should *not* use this method to write PutField + * data, as it will lead to stream corruption if the PutField + * object writes any primitive data (since block data mode is not + * unset/set properly, as is done in OOS.writeFields()). This + * broken implementation is being retained solely for behavioral + * compatibility, in order to support applications which use + * OOS.PutField.write() for writing only non-primitive data. + * + * Serialization of unshared objects is not implemented here since + * it is not necessary for backwards compatibility; also, unshared + * semantics may not be supported by the given ObjectOutput + * instance. Applications which write unshared objects using the + * PutField API must use OOS.writeFields(). + */ + if (InteropObjectOutputStream.this != out) { + throw new IllegalArgumentException("wrong stream"); + } + out.write(primVals, 0, primVals.length); + + ObjectStreamField[] fields = desc.getFields(false); + int numPrimFields = fields.length - objVals.length; + // REMIND: warn if numPrimFields > 0? + for (int i = 0; i < objVals.length; i++) { + if (fields[numPrimFields + i].isUnshared()) { + throw new IOException("cannot write unshared object"); + } + out.writeObject(objVals[i]); + } + } + + /** + * Writes buffered primitive data and object fields to stream. + */ + void writeFields() throws IOException { + InteropObjectOutputStream.this.write(primVals, 0, primVals.length); + + ObjectStreamField[] fields = desc.getFields(false); + int numPrimFields = fields.length - objVals.length; + for (int i = 0; i < objVals.length; i++) { + writeObject(objVals[i]); + } + } + + /** + * Returns offset of field with given name and type. A specified type + * of null matches all types, Object.class matches all non-primitive + * types, and any other non-null type matches assignable types only. + * Throws IllegalArgumentException if no matching field found. + */ + private int getFieldOffset(String name, Class type) { + ObjectStreamField field = desc.getField(name, type); + if (field == null) { + throw new IllegalArgumentException("no such field " + name + + " with type " + type); + } + return field.getOffset(); + } + } + + private static final class ObjectDataOutputStream extends DataOutputStream + { + /* + * States: + * blockStart objCount + * -1 0 Previous byte was a marker (or we're at the start of the stream), next byte will be MARKER, OBJECTS or BYTES + * >=0 0 We're currently writing a byte stream (that starts at blockStart + 1) + * -1 >0 We're currently writing objects (just a count of objects really) + * + */ + private static final byte MARKER = 0; + private static final byte OBJECTS = 10; + private static final byte BYTES = 20; + private final SerializationInfo info; + private byte[] buf = new byte[16]; + private int pos; + private int blockStart = -1; + private int objCount; + private int objId; + + ObjectDataOutputStream(SerializationInfo info) + { + super(null); + out = this; + this.info = info; + } + + private void grow(int minGrow) + { + int newSize = buf.length + Math.max(buf.length, minGrow); + byte[] newBuf = new byte[newSize]; + System.arraycopy(buf, 0, newBuf, 0, pos); + buf = newBuf; + } + + private void switchToData() + { + if (objCount == 0) + { + if (pos == buf.length) + { + grow(1); + } + buf[pos++] = BYTES; + } + else + { + int len = packedLength(objCount); + if (pos + len >= buf.length) + { + grow(len); + } + writePacked(pos, objCount); + objCount = 0; + pos += len; + } + blockStart = pos; + // reserve space for the number of bytes + // (we assume that one byte will suffice, but if it won't the endData code will copy the data to make room) + if (pos == buf.length) + { + grow(1); + } + pos++; + } + + private void endData() + { + if (blockStart == -1) + { + if (pos == buf.length) + { + grow(1); + } + buf[pos++] = OBJECTS; + } + else + { + int len = (pos - blockStart) - 1; + int lenlen = packedLength(len); + if (lenlen > 1) + { + lenlen--; + if (buf.length - pos <= lenlen) + { + grow(lenlen); + } + System.arraycopy(buf, blockStart + 1, buf, blockStart + 1 + lenlen, pos - (blockStart + 1)); + pos += lenlen; + } + writePacked(blockStart, len); + blockStart = -1; + } + } + + private int packedLength(int val) + { + if (val < 0) + { + // we only use packed integers for lengths or counts, so they can never be negative + throw new Error(); + } + else if (val < 128) + { + return 1; + } + else if (val < 16129) + { + return 2; + } + else + { + return 5; + } + } + + private void writePacked(int pos, int v) + { + if (v < 128) + { + buf[pos] = (byte)v; + } + else if (v < 16129) + { + buf[pos + 0] = (byte)(128 | (v >> 7)); + buf[pos + 1] = (byte)(v & 127); + } + else + { + buf[pos + 0] = (byte)128; + buf[pos + 1] = (byte)(v >>> 24); + buf[pos + 2] = (byte)(v >>> 16); + buf[pos + 3] = (byte)(v >>> 8); + buf[pos + 4] = (byte)(v >>> 0); + } + } + + @Override + public void write(int b) + { + if (blockStart == -1) + { + switchToData(); + } + if (pos == buf.length) + { + grow(1); + } + buf[pos++] = (byte)b; + } + + @Override + public void write(byte[] b, int off, int len) + { + if (len == 0) + { + return; + } + if (blockStart == -1) + { + switchToData(); + } + if (pos + len >= buf.length) + { + grow(len); + } + System.arraycopy(b, off, buf, pos, len); + pos += len; + } + + public void writeObject(Object obj) + { + if (objCount == 0) + { + endData(); + } + objCount++; + info.AddValue("$" + (objId++), obj); + } + + @Override + public void close() + { + if (objCount == 0) + { + if (blockStart == -1) + { + // we've just written a marker, so we don't need to do anything else + } + else + { + endData(); + } + } + else + { + switchToData(); + } + trim(); + info.AddValue("$data", buf); + } + + private void trim() + { + if (buf.length != pos) + { + byte[] newBuf = new byte[pos]; + System.arraycopy(buf, 0, newBuf, 0, pos); + buf = newBuf; + } + } + + @Override + public void flush() + { + } + + public void writeMarker() + { + if (objCount == 0) + { + if (blockStart != -1) + { + endData(); + } + if (pos == buf.length) + { + grow(1); + } + buf[pos++] = MARKER; + } + else + { + switchToData(); + } + blockStart = -1; + } + } +} diff --git a/openjdk/java/io/ObjectStreamClass.java b/openjdk/java/io/ObjectStreamClass.java new file mode 100644 index 0000000..b38d190 --- /dev/null +++ b/openjdk/java/io/ObjectStreamClass.java @@ -0,0 +1,2361 @@ +/* + * Copyright (c) 1996, 2013, 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 java.io; + +import ikvm.internal.FieldReflectorBase; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.SoftReference; +import java.lang.ref.WeakReference; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Proxy; +import java.security.AccessController; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import sun.misc.Unsafe; +import sun.reflect.CallerSensitive; +import sun.reflect.Reflection; +import sun.reflect.ReflectionFactory; +import sun.reflect.misc.ReflectUtil; + +/** + * Serialization's descriptor for classes. It contains the name and + * serialVersionUID of the class. The ObjectStreamClass for a specific class + * loaded in this Java VM can be found/created using the lookup method. + * + *

The algorithm to compute the SerialVersionUID is described in + * Object + * Serialization Specification, Section 4.6, Stream Unique Identifiers. + * + * @author Mike Warres + * @author Roger Riggs + * @see ObjectStreamField + * @see Object Serialization Specification, Section 4, Class Descriptors + * @since JDK1.1 + */ +public class ObjectStreamClass implements Serializable { + + /** serialPersistentFields value indicating no serializable fields */ + public static final ObjectStreamField[] NO_FIELDS = + new ObjectStreamField[0]; + + private static final long serialVersionUID = -6120832682080437368L; + private static final ObjectStreamField[] serialPersistentFields = + NO_FIELDS; + + /** reflection factory for obtaining serialization constructors */ + private static final ReflectionFactory reflFactory = + AccessController.doPrivileged( + new ReflectionFactory.GetReflectionFactoryAction()); + + private static class Caches { + /** cache mapping local classes -> descriptors */ + static final ConcurrentMap> localDescs = + new ConcurrentHashMap<>(); + + /** cache mapping field group/local desc pairs -> field reflectors */ + static final ConcurrentMap> reflectors = + new ConcurrentHashMap<>(); + + /** queue for WeakReferences to local classes */ + private static final ReferenceQueue> localDescsQueue = + new ReferenceQueue<>(); + /** queue for WeakReferences to field reflectors keys */ + private static final ReferenceQueue> reflectorsQueue = + new ReferenceQueue<>(); + } + + /** class associated with this descriptor (if any) */ + private Class cl; + /** name of class represented by this descriptor */ + private String name; + /** serialVersionUID of represented class (null if not computed yet) */ + private volatile Long suid; + + /** true if represents dynamic proxy class */ + private boolean isProxy; + /** true if represents enum type */ + private boolean isEnum; + /** true if represented class implements Serializable */ + private boolean serializable; + /** true if represented class implements Externalizable */ + private boolean externalizable; + /** true if desc has data written by class-defined writeObject method */ + private boolean hasWriteObjectData; + /** + * true if desc has externalizable data written in block data format; this + * must be true by default to accommodate ObjectInputStream subclasses which + * override readClassDescriptor() to return class descriptors obtained from + * ObjectStreamClass.lookup() (see 4461737) + */ + private boolean hasBlockExternalData = true; + + /** + * Contains information about InvalidClassException instances to be thrown + * when attempting operations on an invalid class. Note that instances of + * this class are immutable and are potentially shared among + * ObjectStreamClass instances. + */ + private static class ExceptionInfo { + private final String className; + private final String message; + + ExceptionInfo(String cn, String msg) { + className = cn; + message = msg; + } + + /** + * Returns (does not throw) an InvalidClassException instance created + * from the information in this object, suitable for being thrown by + * the caller. + */ + InvalidClassException newInvalidClassException() { + return new InvalidClassException(className, message); + } + } + + /** exception (if any) thrown while attempting to resolve class */ + private ClassNotFoundException resolveEx; + /** exception (if any) to throw if non-enum deserialization attempted */ + private ExceptionInfo deserializeEx; + /** exception (if any) to throw if non-enum serialization attempted */ + private ExceptionInfo serializeEx; + /** exception (if any) to throw if default serialization attempted */ + private ExceptionInfo defaultSerializeEx; + + /** serializable fields */ + private ObjectStreamField[] fields; + /** aggregate marshalled size of primitive fields */ + private int primDataSize; + /** number of non-primitive fields */ + private int numObjFields; + /** reflector for setting/getting serializable field values */ + private FieldReflectorBase fieldRefl; + /** data layout of serialized objects described by this class desc */ + private volatile ClassDataSlot[] dataLayout; + + /** serialization-appropriate constructor, or null if none */ + private Constructor cons; + /** class-defined writeObject method, or null if none */ + private Method writeObjectMethod; + /** class-defined readObject method, or null if none */ + private Method readObjectMethod; + /** class-defined readObjectNoData method, or null if none */ + private Method readObjectNoDataMethod; + /** class-defined writeReplace method, or null if none */ + private Method writeReplaceMethod; + /** class-defined readResolve method, or null if none */ + private Method readResolveMethod; + + /** local class descriptor for represented class (may point to self) */ + private ObjectStreamClass localDesc; + /** superclass descriptor appearing in stream */ + private ObjectStreamClass superDesc; + + /** [IKVM] true if the the class was dynamically loaded from Java bytecode */ + private boolean dynamicClass; + + /** + * Initializes native code. + */ + private static native void initNative(); + static { + initNative(); + } + + /** + * Find the descriptor for a class that can be serialized. Creates an + * ObjectStreamClass instance if one does not exist yet for class. Null is + * returned if the specified class does not implement java.io.Serializable + * or java.io.Externalizable. + * + * @param cl class for which to get the descriptor + * @return the class descriptor for the specified class + */ + public static ObjectStreamClass lookup(Class cl) { + return lookup(cl, false); + } + + /** + * Returns the descriptor for any class, regardless of whether it + * implements {@link Serializable}. + * + * @param cl class for which to get the descriptor + * @return the class descriptor for the specified class + * @since 1.6 + */ + public static ObjectStreamClass lookupAny(Class cl) { + return lookup(cl, true); + } + + /** + * Returns the name of the class described by this descriptor. + * This method returns the name of the class in the format that + * is used by the {@link Class#getName} method. + * + * @return a string representing the name of the class + */ + public String getName() { + return name; + } + + /** + * Return the serialVersionUID for this class. The serialVersionUID + * defines a set of classes all with the same name that have evolved from a + * common root class and agree to be serialized and deserialized using a + * common format. NonSerializable classes have a serialVersionUID of 0L. + * + * @return the SUID of the class described by this descriptor + */ + public long getSerialVersionUID() { + // REMIND: synchronize instead of relying on volatile? + if (suid == null) { + suid = AccessController.doPrivileged( + new PrivilegedAction() { + public Long run() { + return computeDefaultSUID(cl); + } + } + ); + } + return suid.longValue(); + } + + /** + * Return the class in the local VM that this version is mapped to. Null + * is returned if there is no corresponding local class. + * + * @return the Class instance that this descriptor represents + */ + @CallerSensitive + public Class forClass() { + if (cl == null) { + return null; + } + if (System.getSecurityManager() != null) { + Class caller = Reflection.getCallerClass(); + if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(), cl.getClassLoader())) { + ReflectUtil.checkPackageAccess(cl); + } + } + return cl; + } + + /** + * Return an array of the fields of this serializable class. + * + * @return an array containing an element for each persistent field of + * this class. Returns an array of length zero if there are no + * fields. + * @since 1.2 + */ + public ObjectStreamField[] getFields() { + return getFields(true); + } + + /** + * Get the field of this class by name. + * + * @param name the name of the data field to look for + * @return The ObjectStreamField object of the named field or null if + * there is no such named field. + */ + public ObjectStreamField getField(String name) { + return getField(name, null); + } + + /** + * Return a string describing this ObjectStreamClass. + */ + public String toString() { + return name + ": static final long serialVersionUID = " + + getSerialVersionUID() + "L;"; + } + + /** + * Looks up and returns class descriptor for given class, or null if class + * is non-serializable and "all" is set to false. + * + * @param cl class to look up + * @param all if true, return descriptors for all classes; if false, only + * return descriptors for serializable classes + */ + static ObjectStreamClass lookup(Class cl, boolean all) { + if (!(all || Serializable.class.isAssignableFrom(cl))) { + return null; + } + processQueue(Caches.localDescsQueue, Caches.localDescs); + WeakClassKey key = new WeakClassKey(cl, Caches.localDescsQueue); + Reference ref = Caches.localDescs.get(key); + Object entry = null; + if (ref != null) { + entry = ref.get(); + } + EntryFuture future = null; + if (entry == null) { + EntryFuture newEntry = new EntryFuture(); + Reference newRef = new SoftReference<>(newEntry); + do { + if (ref != null) { + Caches.localDescs.remove(key, ref); + } + ref = Caches.localDescs.putIfAbsent(key, newRef); + if (ref != null) { + entry = ref.get(); + } + } while (ref != null && entry == null); + if (entry == null) { + future = newEntry; + } + } + + if (entry instanceof ObjectStreamClass) { // check common case first + return (ObjectStreamClass) entry; + } + if (entry instanceof EntryFuture) { + future = (EntryFuture) entry; + if (future.getOwner() == Thread.currentThread()) { + /* + * Handle nested call situation described by 4803747: waiting + * for future value to be set by a lookup() call further up the + * stack will result in deadlock, so calculate and set the + * future value here instead. + */ + entry = null; + } else { + entry = future.get(); + } + } + if (entry == null) { + try { + entry = new ObjectStreamClass(cl); + } catch (Throwable th) { + entry = th; + } + if (future.set(entry)) { + Caches.localDescs.put(key, new SoftReference(entry)); + } else { + // nested lookup call already set future + entry = future.get(); + } + } + + if (entry instanceof ObjectStreamClass) { + return (ObjectStreamClass) entry; + } else if (entry instanceof RuntimeException) { + throw (RuntimeException) entry; + } else if (entry instanceof Error) { + throw (Error) entry; + } else { + throw new InternalError("unexpected entry: " + entry); + } + } + + /** + * Placeholder used in class descriptor and field reflector lookup tables + * for an entry in the process of being initialized. (Internal) callers + * which receive an EntryFuture belonging to another thread as the result + * of a lookup should call the get() method of the EntryFuture; this will + * return the actual entry once it is ready for use and has been set(). To + * conserve objects, EntryFutures synchronize on themselves. + */ + private static class EntryFuture { + + private static final Object unset = new Object(); + private final Thread owner = Thread.currentThread(); + private Object entry = unset; + + /** + * Attempts to set the value contained by this EntryFuture. If the + * EntryFuture's value has not been set already, then the value is + * saved, any callers blocked in the get() method are notified, and + * true is returned. If the value has already been set, then no saving + * or notification occurs, and false is returned. + */ + synchronized boolean set(Object entry) { + if (this.entry != unset) { + return false; + } + this.entry = entry; + notifyAll(); + return true; + } + + /** + * Returns the value contained by this EntryFuture, blocking if + * necessary until a value is set. + */ + synchronized Object get() { + boolean interrupted = false; + while (entry == unset) { + try { + wait(); + } catch (InterruptedException ex) { + interrupted = true; + } + } + if (interrupted) { + AccessController.doPrivileged( + new PrivilegedAction() { + public Void run() { + Thread.currentThread().interrupt(); + return null; + } + } + ); + } + return entry; + } + + /** + * Returns the thread that created this EntryFuture. + */ + Thread getOwner() { + return owner; + } + } + + /** + * Creates local class descriptor representing given class. + */ + private ObjectStreamClass(final Class cl) { + this.cl = cl; + name = cl.getName(); + isProxy = Proxy.isProxyClass(cl); + isEnum = Enum.class.isAssignableFrom(cl); + serializable = Serializable.class.isAssignableFrom(cl); + externalizable = Externalizable.class.isAssignableFrom(cl); + dynamicClass = isDynamicTypeWrapper(cl); + + Class superCl = cl.getSuperclass(); + superDesc = (superCl != null) ? lookup(superCl, false) : null; + localDesc = this; + + if (serializable) { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + if (isEnum) { + suid = Long.valueOf(0); + fields = NO_FIELDS; + return null; + } + if (cl.isArray()) { + fields = NO_FIELDS; + return null; + } + + suid = getDeclaredSUID(cl); + try { + fields = getSerialFields(cl); + computeFieldOffsets(); + } catch (InvalidClassException e) { + serializeEx = deserializeEx = + new ExceptionInfo(e.classname, e.getMessage()); + fields = NO_FIELDS; + } + + if (externalizable) { + cons = getExternalizableConstructor(cl); + } else { + cons = getSerializableConstructor(cl); + writeObjectMethod = getPrivateMethod(cl, "writeObject", + new Class[] { ObjectOutputStream.class }, + Void.TYPE); + readObjectMethod = getPrivateMethod(cl, "readObject", + new Class[] { ObjectInputStream.class }, + Void.TYPE); + readObjectNoDataMethod = getPrivateMethod( + cl, "readObjectNoData", null, Void.TYPE); + hasWriteObjectData = (writeObjectMethod != null); + } + writeReplaceMethod = getInheritableMethod( + cl, "writeReplace", null, Object.class); + readResolveMethod = getInheritableMethod( + cl, "readResolve", null, Object.class); + return null; + } + }); + } else { + suid = Long.valueOf(0); + fields = NO_FIELDS; + } + + try { + fieldRefl = getReflector(fields, this); + } catch (InvalidClassException ex) { + // field mismatches impossible when matching local fields vs. self + throw new InternalError(ex); + } + + if (deserializeEx == null) { + if (isEnum) { + deserializeEx = new ExceptionInfo(name, "enum type"); + } else if (cons == null) { + deserializeEx = new ExceptionInfo(name, "no valid constructor"); + } + } + for (int i = 0; i < fields.length; i++) { + if (fields[i].getField() == null) { + defaultSerializeEx = new ExceptionInfo( + name, "unmatched serializable field(s) declared"); + } + } + } + + /** + * Creates blank class descriptor which should be initialized via a + * subsequent call to initProxy(), initNonProxy() or readNonProxy(). + */ + ObjectStreamClass() { + } + + /** + * Initializes class descriptor representing a proxy class. + */ + void initProxy(Class cl, + ClassNotFoundException resolveEx, + ObjectStreamClass superDesc) + throws InvalidClassException + { + this.cl = cl; + this.resolveEx = resolveEx; + this.superDesc = superDesc; + isProxy = true; + serializable = true; + suid = Long.valueOf(0); + fields = NO_FIELDS; + + if (cl != null) { + localDesc = lookup(cl, true); + if (!localDesc.isProxy) { + throw new InvalidClassException( + "cannot bind proxy descriptor to a non-proxy class"); + } + name = localDesc.name; + externalizable = localDesc.externalizable; + cons = localDesc.cons; + writeReplaceMethod = localDesc.writeReplaceMethod; + readResolveMethod = localDesc.readResolveMethod; + deserializeEx = localDesc.deserializeEx; + } + fieldRefl = getReflector(fields, localDesc); + } + + /** + * Initializes class descriptor representing a non-proxy class. + */ + void initNonProxy(ObjectStreamClass model, + Class cl, + ClassNotFoundException resolveEx, + ObjectStreamClass superDesc) + throws InvalidClassException + { + this.cl = cl; + this.resolveEx = resolveEx; + this.superDesc = superDesc; + name = model.name; + suid = Long.valueOf(model.getSerialVersionUID()); + isProxy = false; + isEnum = model.isEnum; + serializable = model.serializable; + externalizable = model.externalizable; + hasBlockExternalData = model.hasBlockExternalData; + hasWriteObjectData = model.hasWriteObjectData; + fields = model.fields; + primDataSize = model.primDataSize; + numObjFields = model.numObjFields; + + if (cl != null) { + localDesc = lookup(cl, true); + if (localDesc.isProxy) { + throw new InvalidClassException( + "cannot bind non-proxy descriptor to a proxy class"); + } + if (isEnum != localDesc.isEnum) { + throw new InvalidClassException(isEnum ? + "cannot bind enum descriptor to a non-enum class" : + "cannot bind non-enum descriptor to an enum class"); + } + + if (serializable == localDesc.serializable && + !cl.isArray() && + suid.longValue() != localDesc.getSerialVersionUID()) + { + throw new InvalidClassException(localDesc.name, + "local class incompatible: " + + "stream classdesc serialVersionUID = " + suid + + ", local class serialVersionUID = " + + localDesc.getSerialVersionUID()); + } + + if (!classNamesEqual(name, localDesc.name)) { + throw new InvalidClassException(localDesc.name, + "local class name incompatible with stream class " + + "name \"" + name + "\""); + } + + if (!isEnum) { + if ((serializable == localDesc.serializable) && + (externalizable != localDesc.externalizable)) + { + throw new InvalidClassException(localDesc.name, + "Serializable incompatible with Externalizable"); + } + + if ((serializable != localDesc.serializable) || + (externalizable != localDesc.externalizable) || + !(serializable || externalizable)) + { + deserializeEx = new ExceptionInfo( + localDesc.name, "class invalid for deserialization"); + } + } + + cons = localDesc.cons; + writeObjectMethod = localDesc.writeObjectMethod; + readObjectMethod = localDesc.readObjectMethod; + readObjectNoDataMethod = localDesc.readObjectNoDataMethod; + writeReplaceMethod = localDesc.writeReplaceMethod; + readResolveMethod = localDesc.readResolveMethod; + if (deserializeEx == null) { + deserializeEx = localDesc.deserializeEx; + } + } + fieldRefl = getReflector(fields, localDesc); + // reassign to matched fields so as to reflect local unshared settings + fields = fieldRefl.getFields(); + } + + /** + * Reads non-proxy class descriptor information from given input stream. + * The resulting class descriptor is not fully functional; it can only be + * used as input to the ObjectInputStream.resolveClass() and + * ObjectStreamClass.initNonProxy() methods. + */ + void readNonProxy(ObjectInputStream in) + throws IOException, ClassNotFoundException + { + name = in.readUTF(); + suid = Long.valueOf(in.readLong()); + isProxy = false; + + byte flags = in.readByte(); + hasWriteObjectData = + ((flags & ObjectStreamConstants.SC_WRITE_METHOD) != 0); + hasBlockExternalData = + ((flags & ObjectStreamConstants.SC_BLOCK_DATA) != 0); + externalizable = + ((flags & ObjectStreamConstants.SC_EXTERNALIZABLE) != 0); + boolean sflag = + ((flags & ObjectStreamConstants.SC_SERIALIZABLE) != 0); + if (externalizable && sflag) { + throw new InvalidClassException( + name, "serializable and externalizable flags conflict"); + } + serializable = externalizable || sflag; + isEnum = ((flags & ObjectStreamConstants.SC_ENUM) != 0); + if (isEnum && suid.longValue() != 0L) { + throw new InvalidClassException(name, + "enum descriptor has non-zero serialVersionUID: " + suid); + } + + int numFields = in.readShort(); + if (isEnum && numFields != 0) { + throw new InvalidClassException(name, + "enum descriptor has non-zero field count: " + numFields); + } + fields = (numFields > 0) ? + new ObjectStreamField[numFields] : NO_FIELDS; + for (int i = 0; i < numFields; i++) { + char tcode = (char) in.readByte(); + String fname = in.readUTF(); + String signature = ((tcode == 'L') || (tcode == '[')) ? + in.readTypeString() : new String(new char[] { tcode }); + try { + fields[i] = new ObjectStreamField(fname, signature, false); + } catch (RuntimeException e) { + throw (IOException) new InvalidClassException(name, + "invalid descriptor for field " + fname).initCause(e); + } + } + computeFieldOffsets(); + } + + /** + * Writes non-proxy class descriptor information to given output stream. + */ + void writeNonProxy(ObjectOutputStream out) throws IOException { + out.writeUTF(name); + out.writeLong(getSerialVersionUID()); + + byte flags = 0; + if (externalizable) { + flags |= ObjectStreamConstants.SC_EXTERNALIZABLE; + int protocol = out.getProtocolVersion(); + if (protocol != ObjectStreamConstants.PROTOCOL_VERSION_1) { + flags |= ObjectStreamConstants.SC_BLOCK_DATA; + } + } else if (serializable) { + flags |= ObjectStreamConstants.SC_SERIALIZABLE; + } + if (hasWriteObjectData) { + flags |= ObjectStreamConstants.SC_WRITE_METHOD; + } + if (isEnum) { + flags |= ObjectStreamConstants.SC_ENUM; + } + out.writeByte(flags); + + out.writeShort(fields.length); + for (int i = 0; i < fields.length; i++) { + ObjectStreamField f = fields[i]; + out.writeByte(f.getTypeCode()); + out.writeUTF(f.getName()); + if (!f.isPrimitive()) { + out.writeTypeString(f.getTypeString()); + } + } + } + + /** + * Returns ClassNotFoundException (if any) thrown while attempting to + * resolve local class corresponding to this class descriptor. + */ + ClassNotFoundException getResolveException() { + return resolveEx; + } + + /** + * Throws an InvalidClassException if object instances referencing this + * class descriptor should not be allowed to deserialize. This method does + * not apply to deserialization of enum constants. + */ + void checkDeserialize() throws InvalidClassException { + if (deserializeEx != null) { + throw deserializeEx.newInvalidClassException(); + } + } + + /** + * Throws an InvalidClassException if objects whose class is represented by + * this descriptor should not be allowed to serialize. This method does + * not apply to serialization of enum constants. + */ + void checkSerialize() throws InvalidClassException { + if (serializeEx != null) { + throw serializeEx.newInvalidClassException(); + } + } + + /** + * Throws an InvalidClassException if objects whose class is represented by + * this descriptor should not be permitted to use default serialization + * (e.g., if the class declares serializable fields that do not correspond + * to actual fields, and hence must use the GetField API). This method + * does not apply to deserialization of enum constants. + */ + void checkDefaultSerialize() throws InvalidClassException { + if (defaultSerializeEx != null) { + throw defaultSerializeEx.newInvalidClassException(); + } + } + + /** + * Returns superclass descriptor. Note that on the receiving side, the + * superclass descriptor may be bound to a class that is not a superclass + * of the subclass descriptor's bound class. + */ + ObjectStreamClass getSuperDesc() { + return superDesc; + } + + /** + * Returns the "local" class descriptor for the class associated with this + * class descriptor (i.e., the result of + * ObjectStreamClass.lookup(this.forClass())) or null if there is no class + * associated with this descriptor. + */ + ObjectStreamClass getLocalDesc() { + return localDesc; + } + + /** + * Returns arrays of ObjectStreamFields representing the serializable + * fields of the represented class. If copy is true, a clone of this class + * descriptor's field array is returned, otherwise the array itself is + * returned. + */ + ObjectStreamField[] getFields(boolean copy) { + return copy ? fields.clone() : fields; + } + + /** + * Looks up a serializable field of the represented class by name and type. + * A specified type of null matches all types, Object.class matches all + * non-primitive types, and any other non-null type matches assignable + * types only. Returns matching field, or null if no match found. + */ + ObjectStreamField getField(String name, Class type) { + for (int i = 0; i < fields.length; i++) { + ObjectStreamField f = fields[i]; + if (f.getName().equals(name)) { + if (type == null || + (type == Object.class && !f.isPrimitive())) + { + return f; + } + Class ftype = f.getType(); + if (ftype != null && type.isAssignableFrom(ftype)) { + return f; + } + } + } + return null; + } + + /** + * Returns true if class descriptor represents a dynamic proxy class, false + * otherwise. + */ + boolean isProxy() { + return isProxy; + } + + /** + * Returns true if class descriptor represents an enum type, false + * otherwise. + */ + boolean isEnum() { + return isEnum; + } + + /** + * Returns true if represented class implements Externalizable, false + * otherwise. + */ + boolean isExternalizable() { + return externalizable; + } + + /** + * Returns true if represented class implements Serializable, false + * otherwise. + */ + boolean isSerializable() { + return serializable; + } + + /** + * Returns true if class descriptor represents externalizable class that + * has written its data in 1.2 (block data) format, false otherwise. + */ + boolean hasBlockExternalData() { + return hasBlockExternalData; + } + + /** + * Returns true if class descriptor represents serializable (but not + * externalizable) class which has written its data via a custom + * writeObject() method, false otherwise. + */ + boolean hasWriteObjectData() { + return hasWriteObjectData; + } + + /** + * Returns true if represented class is serializable/externalizable and can + * be instantiated by the serialization runtime--i.e., if it is + * externalizable and defines a public no-arg constructor, or if it is + * non-externalizable and its first non-serializable superclass defines an + * accessible no-arg constructor. Otherwise, returns false. + */ + boolean isInstantiable() { + return (cons != null); + } + + /** + * Returns true if represented class is serializable (but not + * externalizable) and defines a conformant writeObject method. Otherwise, + * returns false. + */ + boolean hasWriteObjectMethod() { + return (writeObjectMethod != null); + } + + /** + * Returns true if represented class is serializable (but not + * externalizable) and defines a conformant readObject method. Otherwise, + * returns false. + */ + boolean hasReadObjectMethod() { + return (readObjectMethod != null); + } + + /** + * Returns true if represented class is serializable (but not + * externalizable) and defines a conformant readObjectNoData method. + * Otherwise, returns false. + */ + boolean hasReadObjectNoDataMethod() { + return (readObjectNoDataMethod != null); + } + + /** + * Returns true if represented class is serializable or externalizable and + * defines a conformant writeReplace method. Otherwise, returns false. + */ + boolean hasWriteReplaceMethod() { + return (writeReplaceMethod != null); + } + + /** + * Returns true if represented class is serializable or externalizable and + * defines a conformant readResolve method. Otherwise, returns false. + */ + boolean hasReadResolveMethod() { + return (readResolveMethod != null); + } + + /** + * Creates a new instance of the represented class. If the class is + * externalizable, invokes its public no-arg constructor; otherwise, if the + * class is serializable, invokes the no-arg constructor of the first + * non-serializable superclass. Throws UnsupportedOperationException if + * this class descriptor is not associated with a class, if the associated + * class is non-serializable or if the appropriate no-arg constructor is + * inaccessible/unavailable. + */ + Object newInstance() + throws InstantiationException, InvocationTargetException, + UnsupportedOperationException + { + if (cons != null) { + try { + return cons.newInstance(); + } catch (IllegalAccessException ex) { + // should not occur, as access checks have been suppressed + throw new InternalError(ex); + } + } else { + throw new UnsupportedOperationException(); + } + } + + /** + * Invokes the writeObject method of the represented serializable class. + * Throws UnsupportedOperationException if this class descriptor is not + * associated with a class, or if the class is externalizable, + * non-serializable or does not define writeObject. + */ + void invokeWriteObject(Object obj, ObjectOutputStream out) + throws IOException, UnsupportedOperationException + { + if (writeObjectMethod != null) { + try { + writeObjectMethod.invoke(obj, new Object[]{ out }); + } catch (InvocationTargetException ex) { + Throwable th = ex.getTargetException(); + if (th instanceof IOException) { + throw (IOException) th; + } else { + throwMiscException(th); + } + } catch (IllegalAccessException ex) { + // should not occur, as access checks have been suppressed + throw new InternalError(ex); + } + } else { + throw new UnsupportedOperationException(); + } + } + + /** + * Invokes the readObject method of the represented serializable class. + * Throws UnsupportedOperationException if this class descriptor is not + * associated with a class, or if the class is externalizable, + * non-serializable or does not define readObject. + */ + void invokeReadObject(Object obj, ObjectInputStream in) + throws ClassNotFoundException, IOException, + UnsupportedOperationException + { + if (readObjectMethod != null) { + try { + readObjectMethod.invoke(obj, new Object[]{ in }); + } catch (InvocationTargetException ex) { + Throwable th = ex.getTargetException(); + if (th instanceof ClassNotFoundException) { + throw (ClassNotFoundException) th; + } else if (th instanceof IOException) { + throw (IOException) th; + } else { + throwMiscException(th); + } + } catch (IllegalAccessException ex) { + // should not occur, as access checks have been suppressed + throw new InternalError(ex); + } + } else { + throw new UnsupportedOperationException(); + } + } + + /** + * Invokes the readObjectNoData method of the represented serializable + * class. Throws UnsupportedOperationException if this class descriptor is + * not associated with a class, or if the class is externalizable, + * non-serializable or does not define readObjectNoData. + */ + void invokeReadObjectNoData(Object obj) + throws IOException, UnsupportedOperationException + { + if (readObjectNoDataMethod != null) { + try { + readObjectNoDataMethod.invoke(obj, (Object[]) null); + } catch (InvocationTargetException ex) { + Throwable th = ex.getTargetException(); + if (th instanceof ObjectStreamException) { + throw (ObjectStreamException) th; + } else { + throwMiscException(th); + } + } catch (IllegalAccessException ex) { + // should not occur, as access checks have been suppressed + throw new InternalError(ex); + } + } else { + throw new UnsupportedOperationException(); + } + } + + /** + * Invokes the writeReplace method of the represented serializable class and + * returns the result. Throws UnsupportedOperationException if this class + * descriptor is not associated with a class, or if the class is + * non-serializable or does not define writeReplace. + */ + Object invokeWriteReplace(Object obj) + throws IOException, UnsupportedOperationException + { + if (writeReplaceMethod != null) { + try { + return writeReplaceMethod.invoke(obj, (Object[]) null); + } catch (InvocationTargetException ex) { + Throwable th = ex.getTargetException(); + if (th instanceof ObjectStreamException) { + throw (ObjectStreamException) th; + } else { + throwMiscException(th); + throw new InternalError(th); // never reached + } + } catch (IllegalAccessException ex) { + // should not occur, as access checks have been suppressed + throw new InternalError(ex); + } + } else { + throw new UnsupportedOperationException(); + } + } + + /** + * Invokes the readResolve method of the represented serializable class and + * returns the result. Throws UnsupportedOperationException if this class + * descriptor is not associated with a class, or if the class is + * non-serializable or does not define readResolve. + */ + Object invokeReadResolve(Object obj) + throws IOException, UnsupportedOperationException + { + if (readResolveMethod != null) { + try { + return readResolveMethod.invoke(obj, (Object[]) null); + } catch (InvocationTargetException ex) { + Throwable th = ex.getTargetException(); + if (th instanceof ObjectStreamException) { + throw (ObjectStreamException) th; + } else { + throwMiscException(th); + throw new InternalError(th); // never reached + } + } catch (IllegalAccessException ex) { + // should not occur, as access checks have been suppressed + throw new InternalError(ex); + } + } else { + throw new UnsupportedOperationException(); + } + } + + /** + * Class representing the portion of an object's serialized form allotted + * to data described by a given class descriptor. If "hasData" is false, + * the object's serialized form does not contain data associated with the + * class descriptor. + */ + static class ClassDataSlot { + + /** class descriptor "occupying" this slot */ + final ObjectStreamClass desc; + /** true if serialized form includes data for this slot's descriptor */ + final boolean hasData; + + ClassDataSlot(ObjectStreamClass desc, boolean hasData) { + this.desc = desc; + this.hasData = hasData; + } + } + + /** + * Returns array of ClassDataSlot instances representing the data layout + * (including superclass data) for serialized objects described by this + * class descriptor. ClassDataSlots are ordered by inheritance with those + * containing "higher" superclasses appearing first. The final + * ClassDataSlot contains a reference to this descriptor. + */ + ClassDataSlot[] getClassDataLayout() throws InvalidClassException { + // REMIND: synchronize instead of relying on volatile? + if (dataLayout == null) { + dataLayout = getClassDataLayout0(); + } + return dataLayout; + } + + private ClassDataSlot[] getClassDataLayout0() + throws InvalidClassException + { + ArrayList slots = new ArrayList<>(); + Class start = cl, end = cl; + + // locate closest non-serializable superclass + while (end != null && Serializable.class.isAssignableFrom(end)) { + end = end.getSuperclass(); + } + + HashSet oscNames = new HashSet<>(3); + + for (ObjectStreamClass d = this; d != null; d = d.superDesc) { + if (oscNames.contains(d.name)) { + throw new InvalidClassException("Circular reference."); + } else { + oscNames.add(d.name); + } + + // search up inheritance hierarchy for class with matching name + String searchName = (d.cl != null) ? d.cl.getName() : d.name; + Class match = null; + for (Class c = start; c != end; c = c.getSuperclass()) { + if (searchName.equals(c.getName())) { + match = c; + break; + } + } + + // add "no data" slot for each unmatched class below match + if (match != null) { + for (Class c = start; c != match; c = c.getSuperclass()) { + slots.add(new ClassDataSlot( + ObjectStreamClass.lookup(c, true), false)); + } + start = match.getSuperclass(); + } + + // record descriptor/class pairing + slots.add(new ClassDataSlot(d.getVariantFor(match), true)); + } + + // add "no data" slot for any leftover unmatched classes + for (Class c = start; c != end; c = c.getSuperclass()) { + slots.add(new ClassDataSlot( + ObjectStreamClass.lookup(c, true), false)); + } + + // order slots from superclass -> subclass + Collections.reverse(slots); + return slots.toArray(new ClassDataSlot[slots.size()]); + } + + /** + * Returns aggregate size (in bytes) of marshalled primitive field values + * for represented class. + */ + int getPrimDataSize() { + return primDataSize; + } + + /** + * Returns number of non-primitive serializable fields of represented + * class. + */ + int getNumObjFields() { + return numObjFields; + } + + /** + * Fetches the serializable primitive field values of object obj and + * marshals them into byte array buf starting at offset 0. It is the + * responsibility of the caller to ensure that obj is of the proper type if + * non-null. + */ + void getPrimFieldValues(Object obj, byte[] buf) { + fieldRefl.getPrimFieldValues(obj, buf); + } + + /** + * Sets the serializable primitive fields of object obj using values + * unmarshalled from byte array buf starting at offset 0. It is the + * responsibility of the caller to ensure that obj is of the proper type if + * non-null. + */ + void setPrimFieldValues(Object obj, byte[] buf) { + fieldRefl.setPrimFieldValues(obj, buf); + } + + /** + * Fetches the serializable object field values of object obj and stores + * them in array vals starting at offset 0. It is the responsibility of + * the caller to ensure that obj is of the proper type if non-null. + */ + void getObjFieldValues(Object obj, Object[] vals) { + fieldRefl.getObjFieldValues(obj, vals); + } + + /** + * Sets the serializable object fields of object obj using values from + * array vals starting at offset 0. It is the responsibility of the caller + * to ensure that obj is of the proper type if non-null. + */ + void setObjFieldValues(Object obj, Object[] vals) { + fieldRefl.setObjFieldValues(obj, vals); + } + + /** + * Calculates and sets serializable field offsets, as well as primitive + * data size and object field count totals. Throws InvalidClassException + * if fields are illegally ordered. + */ + private void computeFieldOffsets() throws InvalidClassException { + primDataSize = 0; + numObjFields = 0; + int firstObjIndex = -1; + + for (int i = 0; i < fields.length; i++) { + ObjectStreamField f = fields[i]; + switch (f.getTypeCode()) { + case 'Z': + case 'B': + f.setOffset(primDataSize++); + break; + + case 'C': + case 'S': + f.setOffset(primDataSize); + primDataSize += 2; + break; + + case 'I': + case 'F': + f.setOffset(primDataSize); + primDataSize += 4; + break; + + case 'J': + case 'D': + f.setOffset(primDataSize); + primDataSize += 8; + break; + + case '[': + case 'L': + f.setOffset(numObjFields++); + if (firstObjIndex == -1) { + firstObjIndex = i; + } + break; + + default: + throw new InternalError(); + } + } + if (firstObjIndex != -1 && + firstObjIndex + numObjFields != fields.length) + { + throw new InvalidClassException(name, "illegal field order"); + } + } + + /** + * If given class is the same as the class associated with this class + * descriptor, returns reference to this class descriptor. Otherwise, + * returns variant of this class descriptor bound to given class. + */ + private ObjectStreamClass getVariantFor(Class cl) + throws InvalidClassException + { + if (this.cl == cl) { + return this; + } + ObjectStreamClass desc = new ObjectStreamClass(); + if (isProxy) { + desc.initProxy(cl, null, superDesc); + } else { + desc.initNonProxy(this, cl, null, superDesc); + } + return desc; + } + + /** + * Returns public no-arg constructor of given class, or null if none found. + * Access checks are disabled on the returned constructor (if any), since + * the defining class may still be non-public. + */ + private static Constructor getExternalizableConstructor(Class cl) { + try { + Constructor cons = cl.getDeclaredConstructor((Class[]) null); + cons.setAccessible(true); + return ((cons.getModifiers() & Modifier.PUBLIC) != 0) ? + cons : null; + } catch (NoSuchMethodException ex) { + return null; + } + } + + /** + * Returns subclass-accessible no-arg constructor of first non-serializable + * superclass, or null if none found. Access checks are disabled on the + * returned constructor (if any). + */ + private static Constructor getSerializableConstructor(Class cl) { + Class initCl = cl; + while (Serializable.class.isAssignableFrom(initCl)) { + if ((initCl = initCl.getSuperclass()) == null) { + return null; + } + } + try { + Constructor cons = initCl.getDeclaredConstructor((Class[]) null); + int mods = cons.getModifiers(); + if ((mods & Modifier.PRIVATE) != 0 || + ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 && + !packageEquals(cl, initCl))) + { + return null; + } + cons = reflFactory.newConstructorForSerialization(cl, cons); + cons.setAccessible(true); + return cons; + } catch (NoSuchMethodException ex) { + return null; + } + } + + /** + * Returns non-static, non-abstract method with given signature provided it + * is defined by or accessible (via inheritance) by the given class, or + * null if no match found. Access checks are disabled on the returned + * method (if any). + */ + private static Method getInheritableMethod(Class cl, String name, + Class[] argTypes, + Class returnType) + { + Method meth = null; + Class defCl = cl; + while (defCl != null) { + try { + meth = defCl.getDeclaredMethod(name, argTypes); + break; + } catch (NoSuchMethodException ex) { + defCl = defCl.getSuperclass(); + } + } + + if ((meth == null) || (meth.getReturnType() != returnType)) { + return null; + } + meth.setAccessible(true); + int mods = meth.getModifiers(); + if ((mods & (Modifier.STATIC | Modifier.ABSTRACT)) != 0) { + return null; + } else if ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0) { + return meth; + } else if ((mods & Modifier.PRIVATE) != 0) { + return (cl == defCl) ? meth : null; + } else { + return packageEquals(cl, defCl) ? meth : null; + } + } + + /** + * Returns non-static private method with given signature defined by given + * class, or null if none found. Access checks are disabled on the + * returned method (if any). + */ + private static Method getPrivateMethod(Class cl, String name, + Class[] argTypes, + Class returnType) + { + try { + Method meth = cl.getDeclaredMethod(name, argTypes); + meth.setAccessible(true); + int mods = meth.getModifiers(); + return ((meth.getReturnType() == returnType) && + ((mods & Modifier.STATIC) == 0) && + ((mods & Modifier.PRIVATE) != 0)) ? meth : null; + } catch (NoSuchMethodException ex) { + return null; + } + } + + /** + * Returns true if classes are defined in the same runtime package, false + * otherwise. + */ + private static boolean packageEquals(Class cl1, Class cl2) { + return (cl1.getClassLoader() == cl2.getClassLoader() && + getPackageName(cl1).equals(getPackageName(cl2))); + } + + /** + * Returns package name of given class. + */ + private static String getPackageName(Class cl) { + String s = cl.getName(); + int i = s.lastIndexOf('['); + if (i >= 0) { + s = s.substring(i + 2); + } + i = s.lastIndexOf('.'); + return (i >= 0) ? s.substring(0, i) : ""; + } + + /** + * Compares class names for equality, ignoring package names. Returns true + * if class names equal, false otherwise. + */ + private static boolean classNamesEqual(String name1, String name2) { + name1 = name1.substring(name1.lastIndexOf('.') + 1); + name2 = name2.substring(name2.lastIndexOf('.') + 1); + return name1.equals(name2); + } + + /** + * Returns JVM type signature for given class. + */ + private static String getClassSignature(Class cl) { + StringBuilder sbuf = new StringBuilder(); + while (cl.isArray()) { + sbuf.append('['); + cl = cl.getComponentType(); + } + if (cl.isPrimitive()) { + if (cl == Integer.TYPE) { + sbuf.append('I'); + } else if (cl == Byte.TYPE) { + sbuf.append('B'); + } else if (cl == Long.TYPE) { + sbuf.append('J'); + } else if (cl == Float.TYPE) { + sbuf.append('F'); + } else if (cl == Double.TYPE) { + sbuf.append('D'); + } else if (cl == Short.TYPE) { + sbuf.append('S'); + } else if (cl == Character.TYPE) { + sbuf.append('C'); + } else if (cl == Boolean.TYPE) { + sbuf.append('Z'); + } else if (cl == Void.TYPE) { + sbuf.append('V'); + } else { + throw new InternalError(); + } + } else { + sbuf.append('L' + cl.getName().replace('.', '/') + ';'); + } + return sbuf.toString(); + } + + /** + * Returns JVM type signature for given list of parameters and return type. + */ + private static String getMethodSignature(Class[] paramTypes, + Class retType) + { + StringBuilder sbuf = new StringBuilder(); + sbuf.append('('); + for (int i = 0; i < paramTypes.length; i++) { + sbuf.append(getClassSignature(paramTypes[i])); + } + sbuf.append(')'); + sbuf.append(getClassSignature(retType)); + return sbuf.toString(); + } + + /** + * Convenience method for throwing an exception that is either a + * RuntimeException, Error, or of some unexpected type (in which case it is + * wrapped inside an IOException). + */ + private static void throwMiscException(Throwable th) throws IOException { + if (th instanceof RuntimeException) { + throw (RuntimeException) th; + } else if (th instanceof Error) { + throw (Error) th; + } else { + IOException ex = new IOException("unexpected exception type"); + ex.initCause(th); + throw ex; + } + } + + /** + * Returns ObjectStreamField array describing the serializable fields of + * the given class. Serializable fields backed by an actual field of the + * class are represented by ObjectStreamFields with corresponding non-null + * Field objects. Throws InvalidClassException if the (explicitly + * declared) serializable fields are invalid. + */ + private static ObjectStreamField[] getSerialFields(Class cl) + throws InvalidClassException + { + ObjectStreamField[] fields; + if (Serializable.class.isAssignableFrom(cl) && + !Externalizable.class.isAssignableFrom(cl) && + !Proxy.isProxyClass(cl) && + !cl.isInterface()) + { + if ((fields = getDeclaredSerialFields(cl)) == null) { + fields = getDefaultSerialFields(cl); + } + Arrays.sort(fields); + } else { + fields = NO_FIELDS; + } + return fields; + } + + /** + * Returns serializable fields of given class as defined explicitly by a + * "serialPersistentFields" field, or null if no appropriate + * "serialPersistentFields" field is defined. Serializable fields backed + * by an actual field of the class are represented by ObjectStreamFields + * with corresponding non-null Field objects. For compatibility with past + * releases, a "serialPersistentFields" field with a null value is + * considered equivalent to not declaring "serialPersistentFields". Throws + * InvalidClassException if the declared serializable fields are + * invalid--e.g., if multiple fields share the same name. + */ + private static ObjectStreamField[] getDeclaredSerialFields(Class cl) + throws InvalidClassException + { + ObjectStreamField[] serialPersistentFields = null; + try { + Field f = cl.getDeclaredField("serialPersistentFields"); + int mask = Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL; + if ((f.getModifiers() & mask) == mask) { + f.setAccessible(true); + serialPersistentFields = (ObjectStreamField[]) f.get(null); + } + } catch (Exception ex) { + } + if (serialPersistentFields == null) { + return null; + } else if (serialPersistentFields.length == 0) { + return NO_FIELDS; + } + + ObjectStreamField[] boundFields = + new ObjectStreamField[serialPersistentFields.length]; + Set fieldNames = new HashSet<>(serialPersistentFields.length); + + for (int i = 0; i < serialPersistentFields.length; i++) { + ObjectStreamField spf = serialPersistentFields[i]; + + String fname = spf.getName(); + if (fieldNames.contains(fname)) { + throw new InvalidClassException( + "multiple serializable fields named " + fname); + } + fieldNames.add(fname); + + try { + Field f = cl.getDeclaredField(fname); + if ((f.getType() == spf.getType()) && + ((f.getModifiers() & Modifier.STATIC) == 0)) + { + boundFields[i] = + new ObjectStreamField(f, spf.isUnshared(), true); + } + } catch (NoSuchFieldException ex) { + } + if (boundFields[i] == null) { + boundFields[i] = new ObjectStreamField( + fname, spf.getType(), spf.isUnshared()); + } + } + return boundFields; + } + + /** + * Returns array of ObjectStreamFields corresponding to all non-static + * non-transient fields declared by given class. Each ObjectStreamField + * contains a Field object for the field it represents. If no default + * serializable fields exist, NO_FIELDS is returned. + */ + private static ObjectStreamField[] getDefaultSerialFields(Class cl) { + Field[] clFields = cl.getDeclaredFields(); + ArrayList list = new ArrayList<>(); + int mask = Modifier.STATIC | Modifier.TRANSIENT; + + for (int i = 0; i < clFields.length; i++) { + if ((clFields[i].getModifiers() & mask) == 0) { + list.add(new ObjectStreamField(clFields[i], false, true)); + } + } + int size = list.size(); + return (size == 0) ? NO_FIELDS : + list.toArray(new ObjectStreamField[size]); + } + + /** + * Returns explicit serial version UID value declared by given class, or + * null if none. + */ + private static Long getDeclaredSUID(Class cl) { + try { + Field f = cl.getDeclaredField("serialVersionUID"); + int mask = Modifier.STATIC | Modifier.FINAL; + if ((f.getModifiers() & mask) == mask) { + f.setAccessible(true); + return Long.valueOf(f.getLong(null)); + } + } catch (Exception ex) { + } + return null; + } + + /** + * Computes the default serial version UID value for the given class. + */ + private static long computeDefaultSUID(Class cl) { + if (!Serializable.class.isAssignableFrom(cl) || Proxy.isProxyClass(cl)) + { + return 0L; + } + + try { + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + DataOutputStream dout = new DataOutputStream(bout); + + dout.writeUTF(cl.getName()); + + int classMods = cl.getModifiers() & + (Modifier.PUBLIC | Modifier.FINAL | + Modifier.INTERFACE | Modifier.ABSTRACT); + + /* + * compensate for javac bug in which ABSTRACT bit was set for an + * interface only if the interface declared methods + */ + Method[] methods = cl.getDeclaredMethods(); + if ((classMods & Modifier.INTERFACE) != 0) { + classMods = (methods.length > 0) ? + (classMods | Modifier.ABSTRACT) : + (classMods & ~Modifier.ABSTRACT); + } + dout.writeInt(classMods); + + if (!cl.isArray()) { + /* + * compensate for change in 1.2FCS in which + * Class.getInterfaces() was modified to return Cloneable and + * Serializable for array classes. + */ + Class[] interfaces = cl.getInterfaces(); + String[] ifaceNames = new String[interfaces.length]; + for (int i = 0; i < interfaces.length; i++) { + ifaceNames[i] = interfaces[i].getName(); + } + Arrays.sort(ifaceNames); + for (int i = 0; i < ifaceNames.length; i++) { + dout.writeUTF(ifaceNames[i]); + } + } + + Field[] fields = cl.getDeclaredFields(); + MemberSignature[] fieldSigs = new MemberSignature[fields.length]; + for (int i = 0; i < fields.length; i++) { + fieldSigs[i] = new MemberSignature(fields[i]); + } + Arrays.sort(fieldSigs, new Comparator() { + public int compare(MemberSignature ms1, MemberSignature ms2) { + return ms1.name.compareTo(ms2.name); + } + }); + for (int i = 0; i < fieldSigs.length; i++) { + MemberSignature sig = fieldSigs[i]; + int mods = sig.member.getModifiers() & + (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED | + Modifier.STATIC | Modifier.FINAL | Modifier.VOLATILE | + Modifier.TRANSIENT); + if (((mods & Modifier.PRIVATE) == 0) || + ((mods & (Modifier.STATIC | Modifier.TRANSIENT)) == 0)) + { + dout.writeUTF(sig.name); + dout.writeInt(mods); + dout.writeUTF(sig.signature); + } + } + + if (hasStaticInitializer(cl)) { + dout.writeUTF(""); + dout.writeInt(Modifier.STATIC); + dout.writeUTF("()V"); + } + + Constructor[] cons = cl.getDeclaredConstructors(); + MemberSignature[] consSigs = new MemberSignature[cons.length]; + for (int i = 0; i < cons.length; i++) { + consSigs[i] = new MemberSignature(cons[i]); + } + Arrays.sort(consSigs, new Comparator() { + public int compare(MemberSignature ms1, MemberSignature ms2) { + return ms1.signature.compareTo(ms2.signature); + } + }); + for (int i = 0; i < consSigs.length; i++) { + MemberSignature sig = consSigs[i]; + int mods = sig.member.getModifiers() & + (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED | + Modifier.STATIC | Modifier.FINAL | + Modifier.SYNCHRONIZED | Modifier.NATIVE | + Modifier.ABSTRACT | Modifier.STRICT); + if ((mods & Modifier.PRIVATE) == 0) { + dout.writeUTF(""); + dout.writeInt(mods); + dout.writeUTF(sig.signature.replace('/', '.')); + } + } + + MemberSignature[] methSigs = new MemberSignature[methods.length]; + for (int i = 0; i < methods.length; i++) { + methSigs[i] = new MemberSignature(methods[i]); + } + Arrays.sort(methSigs, new Comparator() { + public int compare(MemberSignature ms1, MemberSignature ms2) { + int comp = ms1.name.compareTo(ms2.name); + if (comp == 0) { + comp = ms1.signature.compareTo(ms2.signature); + } + return comp; + } + }); + for (int i = 0; i < methSigs.length; i++) { + MemberSignature sig = methSigs[i]; + int mods = sig.member.getModifiers() & + (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED | + Modifier.STATIC | Modifier.FINAL | + Modifier.SYNCHRONIZED | Modifier.NATIVE | + Modifier.ABSTRACT | Modifier.STRICT); + if ((mods & Modifier.PRIVATE) == 0) { + dout.writeUTF(sig.name); + dout.writeInt(mods); + dout.writeUTF(sig.signature.replace('/', '.')); + } + } + + dout.flush(); + + MessageDigest md = MessageDigest.getInstance("SHA"); + byte[] hashBytes = md.digest(bout.toByteArray()); + long hash = 0; + for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) { + hash = (hash << 8) | (hashBytes[i] & 0xFF); + } + return hash; + } catch (IOException ex) { + throw new InternalError(ex); + } catch (NoSuchAlgorithmException ex) { + throw new SecurityException(ex.getMessage()); + } + } + + /** + * Returns true if the given class defines a static initializer method, + * false otherwise. + */ + private native static boolean hasStaticInitializer(Class cl); + + /** + * Class for computing and caching field/constructor/method signatures + * during serialVersionUID calculation. + */ + private static class MemberSignature { + + public final Member member; + public final String name; + public final String signature; + + public MemberSignature(Field field) { + member = field; + name = field.getName(); + signature = getClassSignature(field.getType()); + } + + public MemberSignature(Constructor cons) { + member = cons; + name = cons.getName(); + signature = getMethodSignature( + cons.getParameterTypes(), Void.TYPE); + } + + public MemberSignature(Method meth) { + member = meth; + name = meth.getName(); + signature = getMethodSignature( + meth.getParameterTypes(), meth.getReturnType()); + } + } + + /** + * Class for setting and retrieving serializable field values in batch. + */ + // REMIND: dynamically generate these? + private static class FieldReflector extends FieldReflectorBase { + + /** handle for performing unsafe operations */ + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + /** fields to operate on */ + private final ObjectStreamField[] fields; + /** number of primitive fields */ + private final int numPrimFields; + /** unsafe field keys for reading fields - may contain dupes */ + private final long[] readKeys; + /** unsafe fields keys for writing fields - no dupes */ + private final long[] writeKeys; + /** field data offsets */ + private final int[] offsets; + /** field type codes */ + private final char[] typeCodes; + /** field types */ + private final Class[] types; + + /** + * Constructs FieldReflector capable of setting/getting values from the + * subset of fields whose ObjectStreamFields contain non-null + * reflective Field objects. ObjectStreamFields with null Fields are + * treated as filler, for which get operations return default values + * and set operations discard given values. + */ + FieldReflector(ObjectStreamField[] fields) { + this.fields = fields; + int nfields = fields.length; + readKeys = new long[nfields]; + writeKeys = new long[nfields]; + offsets = new int[nfields]; + typeCodes = new char[nfields]; + ArrayList> typeList = new ArrayList<>(); + Set usedKeys = new HashSet<>(); + + + for (int i = 0; i < nfields; i++) { + ObjectStreamField f = fields[i]; + Field rf = f.getField(); + long key = (rf != null) ? + unsafe.objectFieldOffset(rf) : Unsafe.INVALID_FIELD_OFFSET; + readKeys[i] = key; + writeKeys[i] = usedKeys.add(key) ? + key : Unsafe.INVALID_FIELD_OFFSET; + offsets[i] = f.getOffset(); + typeCodes[i] = f.getTypeCode(); + if (!f.isPrimitive()) { + typeList.add((rf != null) ? rf.getType() : null); + } + } + + types = typeList.toArray(new Class[typeList.size()]); + numPrimFields = nfields - types.length; + } + + /** + * Returns list of ObjectStreamFields representing fields operated on + * by this reflector. The shared/unshared values and Field objects + * contained by ObjectStreamFields in the list reflect their bindings + * to locally defined serializable fields. + */ + public ObjectStreamField[] getFields() { + return fields; + } + + /** + * Fetches the serializable primitive field values of object obj and + * marshals them into byte array buf starting at offset 0. The caller + * is responsible for ensuring that obj is of the proper type. + */ + public void getPrimFieldValues(Object obj, byte[] buf) { + if (obj == null) { + throw new NullPointerException(); + } + /* assuming checkDefaultSerialize() has been called on the class + * descriptor this FieldReflector was obtained from, no field keys + * in array should be equal to Unsafe.INVALID_FIELD_OFFSET. + */ + for (int i = 0; i < numPrimFields; i++) { + long key = readKeys[i]; + int off = offsets[i]; + switch (typeCodes[i]) { + case 'Z': + Bits.putBoolean(buf, off, unsafe.getBoolean(obj, key)); + break; + + case 'B': + buf[off] = unsafe.getByte(obj, key); + break; + + case 'C': + Bits.putChar(buf, off, unsafe.getChar(obj, key)); + break; + + case 'S': + Bits.putShort(buf, off, unsafe.getShort(obj, key)); + break; + + case 'I': + Bits.putInt(buf, off, unsafe.getInt(obj, key)); + break; + + case 'F': + Bits.putFloat(buf, off, unsafe.getFloat(obj, key)); + break; + + case 'J': + Bits.putLong(buf, off, unsafe.getLong(obj, key)); + break; + + case 'D': + Bits.putDouble(buf, off, unsafe.getDouble(obj, key)); + break; + + default: + throw new InternalError(); + } + } + } + + /** + * Sets the serializable primitive fields of object obj using values + * unmarshalled from byte array buf starting at offset 0. The caller + * is responsible for ensuring that obj is of the proper type. + */ + public void setPrimFieldValues(Object obj, byte[] buf) { + if (obj == null) { + throw new NullPointerException(); + } + for (int i = 0; i < numPrimFields; i++) { + long key = writeKeys[i]; + if (key == Unsafe.INVALID_FIELD_OFFSET) { + continue; // discard value + } + int off = offsets[i]; + switch (typeCodes[i]) { + case 'Z': + unsafe.putBoolean(obj, key, Bits.getBoolean(buf, off)); + break; + + case 'B': + unsafe.putByte(obj, key, buf[off]); + break; + + case 'C': + unsafe.putChar(obj, key, Bits.getChar(buf, off)); + break; + + case 'S': + unsafe.putShort(obj, key, Bits.getShort(buf, off)); + break; + + case 'I': + unsafe.putInt(obj, key, Bits.getInt(buf, off)); + break; + + case 'F': + unsafe.putFloat(obj, key, Bits.getFloat(buf, off)); + break; + + case 'J': + unsafe.putLong(obj, key, Bits.getLong(buf, off)); + break; + + case 'D': + unsafe.putDouble(obj, key, Bits.getDouble(buf, off)); + break; + + default: + throw new InternalError(); + } + } + } + + /** + * Fetches the serializable object field values of object obj and + * stores them in array vals starting at offset 0. The caller is + * responsible for ensuring that obj is of the proper type. + */ + public void getObjFieldValues(Object obj, Object[] vals) { + if (obj == null) { + throw new NullPointerException(); + } + /* assuming checkDefaultSerialize() has been called on the class + * descriptor this FieldReflector was obtained from, no field keys + * in array should be equal to Unsafe.INVALID_FIELD_OFFSET. + */ + for (int i = numPrimFields; i < fields.length; i++) { + switch (typeCodes[i]) { + case 'L': + case '[': + vals[offsets[i]] = unsafe.getObject(obj, readKeys[i]); + break; + + default: + throw new InternalError(); + } + } + } + + /** + * Sets the serializable object fields of object obj using values from + * array vals starting at offset 0. The caller is responsible for + * ensuring that obj is of the proper type; however, attempts to set a + * field with a value of the wrong type will trigger an appropriate + * ClassCastException. + */ + public void setObjFieldValues(Object obj, Object[] vals) { + if (obj == null) { + throw new NullPointerException(); + } + for (int i = numPrimFields; i < fields.length; i++) { + long key = writeKeys[i]; + if (key == Unsafe.INVALID_FIELD_OFFSET) { + continue; // discard value + } + switch (typeCodes[i]) { + case 'L': + case '[': + Object val = vals[offsets[i]]; + if (val != null && + !types[i - numPrimFields].isInstance(val)) + { + Field f = fields[i].getField(); + throw new ClassCastException( + "cannot assign instance of " + + val.getClass().getName() + " to field " + + f.getDeclaringClass().getName() + "." + + f.getName() + " of type " + + f.getType().getName() + " in instance of " + + obj.getClass().getName()); + } + unsafe.putObject(obj, key, val); + break; + + default: + throw new InternalError(); + } + } + } + } + + /** + * Matches given set of serializable fields with serializable fields + * described by the given local class descriptor, and returns a + * FieldReflector instance capable of setting/getting values from the + * subset of fields that match (non-matching fields are treated as filler, + * for which get operations return default values and set operations + * discard given values). Throws InvalidClassException if unresolvable + * type conflicts exist between the two sets of fields. + */ + private static FieldReflectorBase getReflector(ObjectStreamField[] fields, + ObjectStreamClass localDesc) + throws InvalidClassException + { + // class irrelevant if no fields + Class cl = (localDesc != null && fields.length > 0) ? + localDesc.cl : null; + processQueue(Caches.reflectorsQueue, Caches.reflectors); + FieldReflectorKey key = new FieldReflectorKey(cl, fields, + Caches.reflectorsQueue); + Reference ref = Caches.reflectors.get(key); + Object entry = null; + if (ref != null) { + entry = ref.get(); + } + EntryFuture future = null; + if (entry == null) { + EntryFuture newEntry = new EntryFuture(); + Reference newRef = new SoftReference<>(newEntry); + do { + if (ref != null) { + Caches.reflectors.remove(key, ref); + } + ref = Caches.reflectors.putIfAbsent(key, newRef); + if (ref != null) { + entry = ref.get(); + } + } while (ref != null && entry == null); + if (entry == null) { + future = newEntry; + } + } + + if (entry instanceof FieldReflectorBase) { // check common case first + return (FieldReflectorBase) entry; + } else if (entry instanceof EntryFuture) { + entry = ((EntryFuture) entry).get(); + } else if (entry == null) { + try { + ObjectStreamField[] matchedFields = matchFields(fields, localDesc); + entry = getFastFieldReflector(matchedFields); + if (entry == null) { + entry = new FieldReflector(matchedFields); + } + } catch (Throwable th) { + entry = th; + } + future.set(entry); + Caches.reflectors.put(key, new SoftReference(entry)); + } + + if (entry instanceof FieldReflectorBase) { + return (FieldReflectorBase) entry; + } else if (entry instanceof InvalidClassException) { + throw (InvalidClassException) entry; + } else if (entry instanceof RuntimeException) { + throw (RuntimeException) entry; + } else if (entry instanceof Error) { + throw (Error) entry; + } else { + throw new InternalError("unexpected entry: " + entry); + } + } + + private static native Object getFastFieldReflector(ObjectStreamField[] fields); + + /** + * FieldReflector cache lookup key. Keys are considered equal if they + * refer to the same class and equivalent field formats. + */ + private static class FieldReflectorKey extends WeakReference> { + + private final String sigs; + private final int hash; + private final boolean nullClass; + + FieldReflectorKey(Class cl, ObjectStreamField[] fields, + ReferenceQueue> queue) + { + super(cl, queue); + nullClass = (cl == null); + StringBuilder sbuf = new StringBuilder(); + for (int i = 0; i < fields.length; i++) { + ObjectStreamField f = fields[i]; + sbuf.append(f.getName()).append(f.getSignature()); + } + sigs = sbuf.toString(); + hash = System.identityHashCode(cl) + sigs.hashCode(); + } + + public int hashCode() { + return hash; + } + + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (obj instanceof FieldReflectorKey) { + FieldReflectorKey other = (FieldReflectorKey) obj; + Class referent; + return (nullClass ? other.nullClass + : ((referent = get()) != null) && + (referent == other.get())) && + sigs.equals(other.sigs); + } else { + return false; + } + } + } + + /** + * Matches given set of serializable fields with serializable fields + * obtained from the given local class descriptor (which contain bindings + * to reflective Field objects). Returns list of ObjectStreamFields in + * which each ObjectStreamField whose signature matches that of a local + * field contains a Field object for that field; unmatched + * ObjectStreamFields contain null Field objects. Shared/unshared settings + * of the returned ObjectStreamFields also reflect those of matched local + * ObjectStreamFields. Throws InvalidClassException if unresolvable type + * conflicts exist between the two sets of fields. + */ + private static ObjectStreamField[] matchFields(ObjectStreamField[] fields, + ObjectStreamClass localDesc) + throws InvalidClassException + { + ObjectStreamField[] localFields = (localDesc != null) ? + localDesc.fields : NO_FIELDS; + + /* + * Even if fields == localFields, we cannot simply return localFields + * here. In previous implementations of serialization, + * ObjectStreamField.getType() returned Object.class if the + * ObjectStreamField represented a non-primitive field and belonged to + * a non-local class descriptor. To preserve this (questionable) + * behavior, the ObjectStreamField instances returned by matchFields + * cannot report non-primitive types other than Object.class; hence + * localFields cannot be returned directly. + */ + + ObjectStreamField[] matches = new ObjectStreamField[fields.length]; + for (int i = 0; i < fields.length; i++) { + ObjectStreamField f = fields[i], m = null; + for (int j = 0; j < localFields.length; j++) { + ObjectStreamField lf = localFields[j]; + if (f.getName().equals(lf.getName())) { + if ((f.isPrimitive() || lf.isPrimitive()) && + f.getTypeCode() != lf.getTypeCode()) + { + throw new InvalidClassException(localDesc.name, + "incompatible types for field " + f.getName()); + } + if (lf.getField() != null) { + m = new ObjectStreamField( + lf.getField(), lf.isUnshared(), false); + } else { + m = new ObjectStreamField( + lf.getName(), lf.getSignature(), lf.isUnshared()); + } + } + } + if (m == null) { + m = new ObjectStreamField( + f.getName(), f.getSignature(), false); + } + m.setOffset(f.getOffset()); + matches[i] = m; + } + return matches; + } + + /** + * Removes from the specified map any keys that have been enqueued + * on the specified reference queue. + */ + static void processQueue(ReferenceQueue> queue, + ConcurrentMap>, ?> map) + { + Reference> ref; + while((ref = queue.poll()) != null) { + map.remove(ref); + } + } + + /** + * Weak key for Class objects. + * + **/ + static class WeakClassKey extends WeakReference> { + /** + * saved value of the referent's identity hash code, to maintain + * a consistent hash code after the referent has been cleared + */ + private final int hash; + + /** + * Create a new WeakClassKey to the given object, registered + * with a queue. + */ + WeakClassKey(Class cl, ReferenceQueue> refQueue) { + super(cl, refQueue); + hash = System.identityHashCode(cl); + } + + /** + * Returns the identity hash code of the original referent. + */ + public int hashCode() { + return hash; + } + + /** + * Returns true if the given object is this identical + * WeakClassKey instance, or, if this object's referent has not + * been cleared, if the given object is another WeakClassKey + * instance with the identical non-null referent as this one. + */ + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (obj instanceof WeakClassKey) { + Object referent = get(); + return (referent != null) && + (referent == ((WeakClassKey) obj).get()); + } else { + return false; + } + } + } + + // [IKVM] interop serialization support + boolean isDynamicClass() { + return dynamicClass; + } + + private static native boolean isDynamicTypeWrapper(Class cl); + + // to force us to be resolved early (by the .NET deserialization engine) + // we implement readResolve() (which results in us implementing IObjectReference) + private Object readResolve() { + return this; + } +} diff --git a/openjdk/java/io/ObjectStreamField.java b/openjdk/java/io/ObjectStreamField.java new file mode 100644 index 0000000..f28aa2d --- /dev/null +++ b/openjdk/java/io/ObjectStreamField.java @@ -0,0 +1,337 @@ +/* + * Copyright (c) 1996, 2013, 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 java.io; + +import java.lang.reflect.Field; +import sun.reflect.CallerSensitive; +import sun.reflect.Reflection; +import sun.reflect.misc.ReflectUtil; + +/** + * A description of a Serializable field from a Serializable class. An array + * of ObjectStreamFields is used to declare the Serializable fields of a class. + * + * @author Mike Warres + * @author Roger Riggs + * @see ObjectStreamClass + * @since 1.2 + */ +public class ObjectStreamField + implements Comparable +{ + + /** field name */ + private final String name; + /** canonical JVM signature of field type */ + private String signature; + /** field type (Object.class if unknown non-primitive type) */ + private final Class type; + /** whether or not to (de)serialize field values as unshared */ + private final boolean unshared; + /** corresponding reflective field object, if any */ + private final Field field; + /** offset of field value in enclosing field group */ + private int offset = 0; + + /** + * Create a Serializable field with the specified type. This field should + * be documented with a serialField tag. + * + * @param name the name of the serializable field + * @param type the Class object of the serializable field + */ + public ObjectStreamField(String name, Class type) { + this(name, type, false); + } + + /** + * Creates an ObjectStreamField representing a serializable field with the + * given name and type. If unshared is false, values of the represented + * field are serialized and deserialized in the default manner--if the + * field is non-primitive, object values are serialized and deserialized as + * if they had been written and read by calls to writeObject and + * readObject. If unshared is true, values of the represented field are + * serialized and deserialized as if they had been written and read by + * calls to writeUnshared and readUnshared. + * + * @param name field name + * @param type field type + * @param unshared if false, write/read field values in the same manner + * as writeObject/readObject; if true, write/read in the same + * manner as writeUnshared/readUnshared + * @since 1.4 + */ + public ObjectStreamField(String name, Class type, boolean unshared) { + if (name == null || type == null) { + throw new NullPointerException(); + } + this.name = name; + this.type = type; + this.unshared = unshared; + field = null; + } + + // [IKVM] added lazy signature computation, to avoid the reflection hit, unless we really need it + private void lazyInitSignature() { + if (signature == null) { + signature = getClassSignature(type).intern(); + } + } + + /** + * Creates an ObjectStreamField representing a field with the given name, + * signature and unshared setting. + */ + ObjectStreamField(String name, String signature, boolean unshared) { + if (name == null) { + throw new NullPointerException(); + } + this.name = name; + this.signature = signature.intern(); + this.unshared = unshared; + field = null; + + switch (signature.charAt(0)) { + case 'Z': type = Boolean.TYPE; break; + case 'B': type = Byte.TYPE; break; + case 'C': type = Character.TYPE; break; + case 'S': type = Short.TYPE; break; + case 'I': type = Integer.TYPE; break; + case 'J': type = Long.TYPE; break; + case 'F': type = Float.TYPE; break; + case 'D': type = Double.TYPE; break; + case 'L': + case '[': type = Object.class; break; + default: throw new IllegalArgumentException("illegal signature"); + } + } + + /** + * Creates an ObjectStreamField representing the given field with the + * specified unshared setting. For compatibility with the behavior of + * earlier serialization implementations, a "showType" parameter is + * necessary to govern whether or not a getType() call on this + * ObjectStreamField (if non-primitive) will return Object.class (as + * opposed to a more specific reference type). + */ + ObjectStreamField(Field field, boolean unshared, boolean showType) { + this.field = field; + this.unshared = unshared; + name = field.getName(); + Class ftype = field.getType(); + type = (showType || ftype.isPrimitive()) ? ftype : Object.class; + signature = getClassSignature(ftype).intern(); + } + + /** + * Get the name of this field. + * + * @return a String representing the name of the serializable + * field + */ + public String getName() { + return name; + } + + /** + * Get the type of the field. If the type is non-primitive and this + * ObjectStreamField was obtained from a deserialized {@link + * ObjectStreamClass} instance, then Object.class is returned. + * Otherwise, the Class object for the type of the field is + * returned. + * + * @return a Class object representing the type of the + * serializable field + */ + @CallerSensitive + public Class getType() { + if (System.getSecurityManager() != null) { + Class caller = Reflection.getCallerClass(); + if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(), type.getClassLoader())) { + ReflectUtil.checkPackageAccess(type); + } + } + return type; + } + + /** + * Returns character encoding of field type. The encoding is as follows: + *
+     * B            byte
+     * C            char
+     * D            double
+     * F            float
+     * I            int
+     * J            long
+     * L            class or interface
+     * S            short
+     * Z            boolean
+     * [            array
+     * 
+ * + * @return the typecode of the serializable field + */ + // REMIND: deprecate? + public char getTypeCode() { + lazyInitSignature(); + return signature.charAt(0); + } + + /** + * Return the JVM type signature. + * + * @return null if this field has a primitive type. + */ + // REMIND: deprecate? + public String getTypeString() { + lazyInitSignature(); + return isPrimitive() ? null : signature; + } + + /** + * Offset of field within instance data. + * + * @return the offset of this field + * @see #setOffset + */ + // REMIND: deprecate? + public int getOffset() { + return offset; + } + + /** + * Offset within instance data. + * + * @param offset the offset of the field + * @see #getOffset + */ + // REMIND: deprecate? + protected void setOffset(int offset) { + this.offset = offset; + } + + /** + * Return true if this field has a primitive type. + * + * @return true if and only if this field corresponds to a primitive type + */ + // REMIND: deprecate? + public boolean isPrimitive() { + lazyInitSignature(); + char tcode = signature.charAt(0); + return ((tcode != 'L') && (tcode != '[')); + } + + /** + * Returns boolean value indicating whether or not the serializable field + * represented by this ObjectStreamField instance is unshared. + * + * @return {@code true} if this field is unshared + * + * @since 1.4 + */ + public boolean isUnshared() { + return unshared; + } + + /** + * Compare this field with another ObjectStreamField. Return + * -1 if this is smaller, 0 if equal, 1 if greater. Types that are + * primitives are "smaller" than object types. If equal, the field names + * are compared. + */ + // REMIND: deprecate? + public int compareTo(Object obj) { + ObjectStreamField other = (ObjectStreamField) obj; + boolean isPrim = isPrimitive(); + if (isPrim != other.isPrimitive()) { + return isPrim ? -1 : 1; + } + return name.compareTo(other.name); + } + + /** + * Return a string that describes this field. + */ + public String toString() { + lazyInitSignature(); + return signature + ' ' + name; + } + + /** + * Returns field represented by this ObjectStreamField, or null if + * ObjectStreamField is not associated with an actual field. + */ + Field getField() { + return field; + } + + /** + * Returns JVM type signature of field (similar to getTypeString, except + * that signature strings are returned for primitive fields as well). + */ + String getSignature() { + lazyInitSignature(); + return signature; + } + + /** + * Returns JVM type signature for given class. + */ + private static String getClassSignature(Class cl) { + StringBuilder sbuf = new StringBuilder(); + while (cl.isArray()) { + sbuf.append('['); + cl = cl.getComponentType(); + } + if (cl.isPrimitive()) { + if (cl == Integer.TYPE) { + sbuf.append('I'); + } else if (cl == Byte.TYPE) { + sbuf.append('B'); + } else if (cl == Long.TYPE) { + sbuf.append('J'); + } else if (cl == Float.TYPE) { + sbuf.append('F'); + } else if (cl == Double.TYPE) { + sbuf.append('D'); + } else if (cl == Short.TYPE) { + sbuf.append('S'); + } else if (cl == Character.TYPE) { + sbuf.append('C'); + } else if (cl == Boolean.TYPE) { + sbuf.append('Z'); + } else if (cl == Void.TYPE) { + sbuf.append('V'); + } else { + throw new InternalError(); + } + } else { + sbuf.append('L' + cl.getName().replace('.', '/') + ';'); + } + return sbuf.toString(); + } +} diff --git a/openjdk/java/lang/Class.java b/openjdk/java/lang/Class.java new file mode 100644 index 0000000..b11e668 --- /dev/null +++ b/openjdk/java/lang/Class.java @@ -0,0 +1,3646 @@ +/* + * Copyright (c) 1994, 2014, 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 java.lang; + +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Array; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.GenericDeclaration; +import java.lang.reflect.Member; +import java.lang.reflect.Field; +import java.lang.reflect.Executable; +import java.lang.reflect.Method; +import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.AnnotatedType; +import java.lang.ref.SoftReference; +import java.io.InputStream; +import java.io.ObjectStreamField; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Set; +import java.util.Map; +import java.util.HashMap; +import java.util.Objects; +import sun.misc.Unsafe; +import sun.reflect.CallerSensitive; +import sun.reflect.ConstantPool; +import sun.reflect.Reflection; +import sun.reflect.ReflectionFactory; +import sun.reflect.generics.factory.CoreReflectionFactory; +import sun.reflect.generics.factory.GenericsFactory; +import sun.reflect.generics.repository.ClassRepository; +import sun.reflect.generics.repository.MethodRepository; +import sun.reflect.generics.repository.ConstructorRepository; +import sun.reflect.generics.scope.ClassScope; +import sun.security.util.SecurityConstants; +import java.lang.annotation.Annotation; +import java.lang.reflect.Proxy; +import sun.reflect.annotation.*; +import sun.reflect.misc.ReflectUtil; +import cli.System.Runtime.Serialization.SerializationInfo; +import cli.System.Runtime.Serialization.StreamingContext; + +/** + * Instances of the class {@code Class} represent classes and + * interfaces in a running Java application. An enum is a kind of + * class and an annotation is a kind of interface. Every array also + * belongs to a class that is reflected as a {@code Class} object + * that is shared by all arrays with the same element type and number + * of dimensions. The primitive Java types ({@code boolean}, + * {@code byte}, {@code char}, {@code short}, + * {@code int}, {@code long}, {@code float}, and + * {@code double}), and the keyword {@code void} are also + * represented as {@code Class} objects. + * + *

{@code Class} has no public constructor. Instead {@code Class} + * objects are constructed automatically by the Java Virtual Machine as classes + * are loaded and by calls to the {@code defineClass} method in the class + * loader. + * + *

The following example uses a {@code Class} object to print the + * class name of an object: + * + *

+ *     void printClassName(Object obj) {
+ *         System.out.println("The class of " + obj +
+ *                            " is " + obj.getClass().getName());
+ *     }
+ * 
+ * + *

It is also possible to get the {@code Class} object for a named + * type (or for void) using a class literal. See Section 15.8.2 of + * The Java™ Language Specification. + * For example: + * + *

+ * {@code System.out.println("The name of class Foo is: "+Foo.class.getName());} + *
+ * + * @param the type of the class modeled by this {@code Class} + * object. For example, the type of {@code String.class} is {@code + * Class}. Use {@code Class} if the class being modeled is + * unknown. + * + * @author unascribed + * @see java.lang.ClassLoader#defineClass(byte[], int, int) + * @since JDK1.0 + */ +@cli.System.SerializableAttribute.Annotation +public final class Class implements java.io.Serializable, + GenericDeclaration, + Type, + AnnotatedElement { + private static final int ANNOTATION= 0x00002000; + private static final int ENUM = 0x00004000; + private static final int SYNTHETIC = 0x00001000; + + // [IKVM] additional fields + java.security.ProtectionDomain pd; + Object[] signers; + + // For types that live in a static .NET assembly (i.e. ikvmc compiled or .NET types) + // this field contains the type (used for .NET serialization of Class objects). + // This field is also used by fast class literals to remember the type that can then + // lazily be resolved to the corresponding TypeWrapper. + // For dynamically loaded classes and primitives it is null. + final cli.System.Type type; + + /* + * Private constructor. Only the Java Virtual Machine creates Class objects. + * This constructor is not used and prevents the default constructor being + * generated. + */ + private Class(ClassLoader loader) { + // Initialize final field for classLoader. The initialization value of non-null + // prevents future JIT optimizations from assuming this final field is null. + //classLoader = loader; + throw new InternalError(); + } + + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + Class(cli.System.Type type) + { + this.type = type; + } + + // We use custom serialization, because we want to deserialize a via proxy that properly resolves the Class singletons. + // Note that we don't implement ISerializable in this source, but in map.xml to avoid it being visible to Java code. + // We don't have a security demand, because the information exposed is harmless. + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + @cli.System.Security.SecurityCriticalAttribute.Annotation + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddValue("type", type); + info.AddValue("sig", type == null ? getSigName() : null); + info.SetType(ikvm.runtime.Util.getInstanceTypeFromClass(ClassSerializationProxy.class)); + } + + private native String getSigName(); + + // [IKVM] this provides an implicit conversion operator from System.Type to java.lang.Class + @cli.System.Runtime.CompilerServices.SpecialNameAttribute.Annotation + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + public static Class op_Implicit(cli.System.Type type) + { + return ikvm.runtime.Util.getFriendlyClassFromType(type); + } + + /** + * Converts the object to a string. The string representation is the + * string "class" or "interface", followed by a space, and then by the + * fully qualified name of the class in the format returned by + * {@code getName}. If this {@code Class} object represents a + * primitive type, this method returns the name of the primitive type. If + * this {@code Class} object represents void this method returns + * "void". + * + * @return a string representation of this class object. + */ + public String toString() { + return (isInterface() ? "interface " : (isPrimitive() ? "" : "class ")) + + getName(); + } + + /** + * Returns a string describing this {@code Class}, including + * information about modifiers and type parameters. + * + * The string is formatted as a list of type modifiers, if any, + * followed by the kind of type (empty string for primitive types + * and {@code class}, {@code enum}, {@code interface}, or + * @{@code interface}, as appropriate), followed + * by the type's name, followed by an angle-bracketed + * comma-separated list of the type's type parameters, if any. + * + * A space is used to separate modifiers from one another and to + * separate any modifiers from the kind of type. The modifiers + * occur in canonical order. If there are no type parameters, the + * type parameter list is elided. + * + *

Note that since information about the runtime representation + * of a type is being generated, modifiers not present on the + * originating source code or illegal on the originating source + * code may be present. + * + * @return a string describing this {@code Class}, including + * information about modifiers and type parameters + * + * @since 1.8 + */ + public String toGenericString() { + if (isPrimitive()) { + return toString(); + } else { + StringBuilder sb = new StringBuilder(); + + // Class modifiers are a superset of interface modifiers + int modifiers = getModifiers() & Modifier.classModifiers(); + if (modifiers != 0) { + sb.append(Modifier.toString(modifiers)); + sb.append(' '); + } + + if (isAnnotation()) { + sb.append('@'); + } + if (isInterface()) { // Note: all annotation types are interfaces + sb.append("interface"); + } else { + if (isEnum()) + sb.append("enum"); + else + sb.append("class"); + } + sb.append(' '); + sb.append(getName()); + + TypeVariable[] typeparms = getTypeParameters(); + if (typeparms.length > 0) { + boolean first = true; + sb.append('<'); + for(TypeVariable typeparm: typeparms) { + if (!first) + sb.append(','); + sb.append(typeparm.getTypeName()); + first = false; + } + sb.append('>'); + } + + return sb.toString(); + } + } + + /** + * Returns the {@code Class} object associated with the class or + * interface with the given string name. Invoking this method is + * equivalent to: + * + *

+ * {@code Class.forName(className, true, currentLoader)} + *
+ * + * where {@code currentLoader} denotes the defining class loader of + * the current class. + * + *

For example, the following code fragment returns the + * runtime {@code Class} descriptor for the class named + * {@code java.lang.Thread}: + * + *

+ * {@code Class t = Class.forName("java.lang.Thread")} + *
+ *

+ * A call to {@code forName("X")} causes the class named + * {@code X} to be initialized. + * + * @param className the fully qualified name of the desired class. + * @return the {@code Class} object for the class with the + * specified name. + * @exception LinkageError if the linkage fails + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails + * @exception ClassNotFoundException if the class cannot be located + */ + @CallerSensitive + public static Class forName(String className) + throws ClassNotFoundException { + Class caller = Reflection.getCallerClass(); + return forName0(className, true, ClassLoader.getClassLoader(caller), caller); + } + + + /** + * Returns the {@code Class} object associated with the class or + * interface with the given string name, using the given class loader. + * Given the fully qualified name for a class or interface (in the same + * format returned by {@code getName}) this method attempts to + * locate, load, and link the class or interface. The specified class + * loader is used to load the class or interface. If the parameter + * {@code loader} is null, the class is loaded through the bootstrap + * class loader. The class is initialized only if the + * {@code initialize} parameter is {@code true} and if it has + * not been initialized earlier. + * + *

If {@code name} denotes a primitive type or void, an attempt + * will be made to locate a user-defined class in the unnamed package whose + * name is {@code name}. Therefore, this method cannot be used to + * obtain any of the {@code Class} objects representing primitive + * types or void. + * + *

If {@code name} denotes an array class, the component type of + * the array class is loaded but not initialized. + * + *

For example, in an instance method the expression: + * + *

+ * {@code Class.forName("Foo")} + *
+ * + * is equivalent to: + * + *
+ * {@code Class.forName("Foo", true, this.getClass().getClassLoader())} + *
+ * + * Note that this method throws errors related to loading, linking or + * initializing as specified in Sections 12.2, 12.3 and 12.4 of The + * Java Language Specification. + * Note that this method does not check whether the requested class + * is accessible to its caller. + * + *

If the {@code loader} is {@code null}, and a security + * manager is present, and the caller's class loader is not null, then this + * method calls the security manager's {@code checkPermission} method + * with a {@code RuntimePermission("getClassLoader")} permission to + * ensure it's ok to access the bootstrap class loader. + * + * @param name fully qualified name of the desired class + * @param initialize if {@code true} the class will be initialized. + * See Section 12.4 of The Java Language Specification. + * @param loader class loader from which the class must be loaded + * @return class object representing the desired class + * + * @exception LinkageError if the linkage fails + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails + * @exception ClassNotFoundException if the class cannot be located by + * the specified class loader + * + * @see java.lang.Class#forName(String) + * @see java.lang.ClassLoader + * @since 1.2 + */ + @CallerSensitive + public static Class forName(String name, boolean initialize, + ClassLoader loader) + throws ClassNotFoundException + { + Class caller = null; + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + // Reflective call to get caller class is only needed if a security manager + // is present. Avoid the overhead of making this call otherwise. + caller = Reflection.getCallerClass(); + if (sun.misc.VM.isSystemDomainLoader(loader)) { + ClassLoader ccl = ClassLoader.getClassLoader(caller); + if (!sun.misc.VM.isSystemDomainLoader(ccl)) { + sm.checkPermission( + SecurityConstants.GET_CLASSLOADER_PERMISSION); + } + } + } + return forName0(name, initialize, loader, caller); + } + + /** Called after security check for system loader access checks have been made. */ + private static native Class forName0(String name, boolean initialize, + ClassLoader loader, + Class caller) + throws ClassNotFoundException; + + /** + * Creates a new instance of the class represented by this {@code Class} + * object. The class is instantiated as if by a {@code new} + * expression with an empty argument list. The class is initialized if it + * has not already been initialized. + * + *

Note that this method propagates any exception thrown by the + * nullary constructor, including a checked exception. Use of + * this method effectively bypasses the compile-time exception + * checking that would otherwise be performed by the compiler. + * The {@link + * java.lang.reflect.Constructor#newInstance(java.lang.Object...) + * Constructor.newInstance} method avoids this problem by wrapping + * any exception thrown by the constructor in a (checked) {@link + * java.lang.reflect.InvocationTargetException}. + * + * @return a newly allocated instance of the class represented by this + * object. + * @throws IllegalAccessException if the class or its nullary + * constructor is not accessible. + * @throws InstantiationException + * if this {@code Class} represents an abstract class, + * an interface, an array class, a primitive type, or void; + * or if the class has no nullary constructor; + * or if the instantiation fails for some other reason. + * @throws ExceptionInInitializerError if the initialization + * provoked by this method fails. + * @throws SecurityException + * If a security manager, s, is present and + * the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class. + */ + @CallerSensitive + public T newInstance() + throws InstantiationException, IllegalAccessException + { + if (System.getSecurityManager() != null) { + checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false); + } + + // NOTE: the following code may not be strictly correct under + // the current Java memory model. + + // Constructor lookup + if (cachedConstructor == null) { + if (this == Class.class) { + throw new IllegalAccessException( + "Can not call newInstance() on the Class for java.lang.Class" + ); + } + try { + Class[] empty = {}; + final Constructor c = getConstructor0(empty, Member.DECLARED); + // Disable accessibility checks on the constructor + // since we have to do the security check here anyway + // (the stack depth is wrong for the Constructor's + // security check to work) + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + c.setAccessible(true); + return null; + } + }); + cachedConstructor = c; + } catch (NoSuchMethodException e) { + throw (InstantiationException) + new InstantiationException(getName()).initCause(e); + } + } + Constructor tmpConstructor = cachedConstructor; + // Security check (same as in java.lang.reflect.Constructor) + int modifiers = tmpConstructor.getModifiers(); + if (!Reflection.quickCheckMemberAccess(this, modifiers)) { + Class caller = Reflection.getCallerClass(); + if (newInstanceCallerCache != caller) { + Reflection.ensureMemberAccess(caller, this, null, modifiers); + newInstanceCallerCache = caller; + } + } + // Run constructor + try { + return tmpConstructor.newInstance((Object[])null); + } catch (InvocationTargetException e) { + Unsafe.getUnsafe().throwException(e.getTargetException()); + // Not reached + return null; + } + } + private volatile transient Constructor cachedConstructor; + private volatile transient Class newInstanceCallerCache; + + + /** + * Determines if the specified {@code Object} is assignment-compatible + * with the object represented by this {@code Class}. This method is + * the dynamic equivalent of the Java language {@code instanceof} + * operator. The method returns {@code true} if the specified + * {@code Object} argument is non-null and can be cast to the + * reference type represented by this {@code Class} object without + * raising a {@code ClassCastException.} It returns {@code false} + * otherwise. + * + *

Specifically, if this {@code Class} object represents a + * declared class, this method returns {@code true} if the specified + * {@code Object} argument is an instance of the represented class (or + * of any of its subclasses); it returns {@code false} otherwise. If + * this {@code Class} object represents an array class, this method + * returns {@code true} if the specified {@code Object} argument + * can be converted to an object of the array class by an identity + * conversion or by a widening reference conversion; it returns + * {@code false} otherwise. If this {@code Class} object + * represents an interface, this method returns {@code true} if the + * class or any superclass of the specified {@code Object} argument + * implements this interface; it returns {@code false} otherwise. If + * this {@code Class} object represents a primitive type, this method + * returns {@code false}. + * + * @param obj the object to check + * @return true if {@code obj} is an instance of this class + * + * @since JDK1.1 + */ + public native boolean isInstance(Object obj); + + + /** + * Determines if the class or interface represented by this + * {@code Class} object is either the same as, or is a superclass or + * superinterface of, the class or interface represented by the specified + * {@code Class} parameter. It returns {@code true} if so; + * otherwise it returns {@code false}. If this {@code Class} + * object represents a primitive type, this method returns + * {@code true} if the specified {@code Class} parameter is + * exactly this {@code Class} object; otherwise it returns + * {@code false}. + * + *

Specifically, this method tests whether the type represented by the + * specified {@code Class} parameter can be converted to the type + * represented by this {@code Class} object via an identity conversion + * or via a widening reference conversion. See The Java Language + * Specification, sections 5.1.1 and 5.1.4 , for details. + * + * @param cls the {@code Class} object to be checked + * @return the {@code boolean} value indicating whether objects of the + * type {@code cls} can be assigned to objects of this class + * @exception NullPointerException if the specified Class parameter is + * null. + * @since JDK1.1 + */ + public native boolean isAssignableFrom(Class cls); + + + /** + * Determines if the specified {@code Class} object represents an + * interface type. + * + * @return {@code true} if this object represents an interface; + * {@code false} otherwise. + */ + public native boolean isInterface(); + + + /** + * Determines if this {@code Class} object represents an array class. + * + * @return {@code true} if this object represents an array class; + * {@code false} otherwise. + * @since JDK1.1 + */ + public native boolean isArray(); + + + /** + * Determines if the specified {@code Class} object represents a + * primitive type. + * + *

There are nine predefined {@code Class} objects to represent + * the eight primitive types and void. These are created by the Java + * Virtual Machine, and have the same names as the primitive types that + * they represent, namely {@code boolean}, {@code byte}, + * {@code char}, {@code short}, {@code int}, + * {@code long}, {@code float}, and {@code double}. + * + *

These objects may only be accessed via the following public static + * final variables, and are the only {@code Class} objects for which + * this method returns {@code true}. + * + * @return true if and only if this class represents a primitive type + * + * @see java.lang.Boolean#TYPE + * @see java.lang.Character#TYPE + * @see java.lang.Byte#TYPE + * @see java.lang.Short#TYPE + * @see java.lang.Integer#TYPE + * @see java.lang.Long#TYPE + * @see java.lang.Float#TYPE + * @see java.lang.Double#TYPE + * @see java.lang.Void#TYPE + * @since JDK1.1 + */ + public native boolean isPrimitive(); + + /** + * Returns true if this {@code Class} object represents an annotation + * type. Note that if this method returns true, {@link #isInterface()} + * would also return true, as all annotation types are also interfaces. + * + * @return {@code true} if this class object represents an annotation + * type; {@code false} otherwise + * @since 1.5 + */ + public boolean isAnnotation() { + return (getModifiers() & ANNOTATION) != 0; + } + + /** + * Returns {@code true} if this class is a synthetic class; + * returns {@code false} otherwise. + * @return {@code true} if and only if this class is a synthetic class as + * defined by the Java Language Specification. + * @jls 13.1 The Form of a Binary + * @since 1.5 + */ + public boolean isSynthetic() { + return (getModifiers() & SYNTHETIC) != 0; + } + + /** + * Returns the name of the entity (class, interface, array class, + * primitive type, or void) represented by this {@code Class} object, + * as a {@code String}. + * + *

If this class object represents a reference type that is not an + * array type then the binary name of the class is returned, as specified + * by + * The Java™ Language Specification. + * + *

If this class object represents a primitive type or void, then the + * name returned is a {@code String} equal to the Java language + * keyword corresponding to the primitive type or void. + * + *

If this class object represents a class of arrays, then the internal + * form of the name consists of the name of the element type preceded by + * one or more '{@code [}' characters representing the depth of the array + * nesting. The encoding of element type names is as follows: + * + *

+ *
Element Type     Encoding + *
boolean     Z + *
byte     B + *
char     C + *
class or interface + *     Lclassname; + *
double     D + *
float     F + *
int     I + *
long     J + *
short     S + *
+ * + *

The class or interface name classname is the binary name of + * the class specified above. + * + *

Examples: + *

+     * String.class.getName()
+     *     returns "java.lang.String"
+     * byte.class.getName()
+     *     returns "byte"
+     * (new Object[3]).getClass().getName()
+     *     returns "[Ljava.lang.Object;"
+     * (new int[3][4][5][6][7][8][9]).getClass().getName()
+     *     returns "[[[[[[[I"
+     * 
+ * + * @return the name of the class or interface + * represented by this object. + */ + public String getName() { + String name = this.name; + if (name == null) + this.name = name = getName0(); + return name; + } + + // cache the name to reduce the number of calls into the VM + private transient String name; + private native String getName0(); + + /** + * Returns the class loader for the class. Some implementations may use + * null to represent the bootstrap class loader. This method will return + * null in such implementations if this class was loaded by the bootstrap + * class loader. + * + *

If a security manager is present, and the caller's class loader is + * not null and the caller's class loader is not the same as or an ancestor of + * the class loader for the class whose class loader is requested, then + * this method calls the security manager's {@code checkPermission} + * method with a {@code RuntimePermission("getClassLoader")} + * permission to ensure it's ok to access the class loader for the class. + * + *

If this object + * represents a primitive type or void, null is returned. + * + * @return the class loader that loaded the class or interface + * represented by this object. + * @throws SecurityException + * if a security manager exists and its + * {@code checkPermission} method denies + * access to the class loader for the class. + * @see java.lang.ClassLoader + * @see SecurityManager#checkPermission + * @see java.lang.RuntimePermission + */ + @CallerSensitive + public ClassLoader getClassLoader() { + ClassLoader cl = getClassLoader0(); + if (cl == null) + return null; + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass()); + } + return cl; + } + + // Package-private to allow ClassLoader access + native ClassLoader getClassLoader0(); + + + /** + * Returns an array of {@code TypeVariable} objects that represent the + * type variables declared by the generic declaration represented by this + * {@code GenericDeclaration} object, in declaration order. Returns an + * array of length 0 if the underlying generic declaration declares no type + * variables. + * + * @return an array of {@code TypeVariable} objects that represent + * the type variables declared by this generic declaration + * @throws java.lang.reflect.GenericSignatureFormatError if the generic + * signature of this generic declaration does not conform to + * the format specified in + * The Java™ Virtual Machine Specification + * @since 1.5 + */ + @SuppressWarnings("unchecked") + public TypeVariable>[] getTypeParameters() { + ClassRepository info = getGenericInfo(); + if (info != null) + return (TypeVariable>[])info.getTypeParameters(); + else + return (TypeVariable>[])new TypeVariable[0]; + } + + + /** + * Returns the {@code Class} representing the superclass of the entity + * (class, interface, primitive type or void) represented by this + * {@code Class}. If this {@code Class} represents either the + * {@code Object} class, an interface, a primitive type, or void, then + * null is returned. If this object represents an array class then the + * {@code Class} object representing the {@code Object} class is + * returned. + * + * @return the superclass of the class represented by this object. + */ + public native Class getSuperclass(); + + + /** + * Returns the {@code Type} representing the direct superclass of + * the entity (class, interface, primitive type or void) represented by + * this {@code Class}. + * + *

If the superclass is a parameterized type, the {@code Type} + * object returned must accurately reflect the actual type + * parameters used in the source code. The parameterized type + * representing the superclass is created if it had not been + * created before. See the declaration of {@link + * java.lang.reflect.ParameterizedType ParameterizedType} for the + * semantics of the creation process for parameterized types. If + * this {@code Class} represents either the {@code Object} + * class, an interface, a primitive type, or void, then null is + * returned. If this object represents an array class then the + * {@code Class} object representing the {@code Object} class is + * returned. + * + * @throws java.lang.reflect.GenericSignatureFormatError if the generic + * class signature does not conform to the format specified in + * The Java™ Virtual Machine Specification + * @throws TypeNotPresentException if the generic superclass + * refers to a non-existent type declaration + * @throws java.lang.reflect.MalformedParameterizedTypeException if the + * generic superclass refers to a parameterized type that cannot be + * instantiated for any reason + * @return the superclass of the class represented by this object + * @since 1.5 + */ + public Type getGenericSuperclass() { + ClassRepository info = getGenericInfo(); + if (info == null) { + return getSuperclass(); + } + + // Historical irregularity: + // Generic signature marks interfaces with superclass = Object + // but this API returns null for interfaces + if (isInterface()) { + return null; + } + + return info.getSuperclass(); + } + + /** + * Gets the package for this class. The class loader of this class is used + * to find the package. If the class was loaded by the bootstrap class + * loader the set of packages loaded from CLASSPATH is searched to find the + * package of the class. Null is returned if no package object was created + * by the class loader of this class. + * + *

Packages have attributes for versions and specifications only if the + * information was defined in the manifests that accompany the classes, and + * if the class loader created the package instance with the attributes + * from the manifest. + * + * @return the package of the class, or null if no package + * information is available from the archive or codebase. + */ + public Package getPackage() { + return Package.getPackage(this); + } + + + /** + * Determines the interfaces implemented by the class or interface + * represented by this object. + * + *

If this object represents a class, the return value is an array + * containing objects representing all interfaces implemented by the + * class. The order of the interface objects in the array corresponds to + * the order of the interface names in the {@code implements} clause + * of the declaration of the class represented by this object. For + * example, given the declaration: + *

+ * {@code class Shimmer implements FloorWax, DessertTopping { ... }} + *
+ * suppose the value of {@code s} is an instance of + * {@code Shimmer}; the value of the expression: + *
+ * {@code s.getClass().getInterfaces()[0]} + *
+ * is the {@code Class} object that represents interface + * {@code FloorWax}; and the value of: + *
+ * {@code s.getClass().getInterfaces()[1]} + *
+ * is the {@code Class} object that represents interface + * {@code DessertTopping}. + * + *

If this object represents an interface, the array contains objects + * representing all interfaces extended by the interface. The order of the + * interface objects in the array corresponds to the order of the interface + * names in the {@code extends} clause of the declaration of the + * interface represented by this object. + * + *

If this object represents a class or interface that implements no + * interfaces, the method returns an array of length 0. + * + *

If this object represents a primitive type or void, the method + * returns an array of length 0. + * + *

If this {@code Class} object represents an array type, the + * interfaces {@code Cloneable} and {@code java.io.Serializable} are + * returned in that order. + * + * @return an array of interfaces implemented by this class. + */ + public Class[] getInterfaces() { + ReflectionData rd = reflectionData(); + if (rd == null) { + // no cloning required + return getInterfaces0(); + } else { + Class[] interfaces = rd.interfaces; + if (interfaces == null) { + interfaces = getInterfaces0(); + rd.interfaces = interfaces; + } + // defensively copy before handing over to user code + return interfaces.clone(); + } + } + + private native Class[] getInterfaces0(); + + /** + * Returns the {@code Type}s representing the interfaces + * directly implemented by the class or interface represented by + * this object. + * + *

If a superinterface is a parameterized type, the + * {@code Type} object returned for it must accurately reflect + * the actual type parameters used in the source code. The + * parameterized type representing each superinterface is created + * if it had not been created before. See the declaration of + * {@link java.lang.reflect.ParameterizedType ParameterizedType} + * for the semantics of the creation process for parameterized + * types. + * + *

If this object represents a class, the return value is an + * array containing objects representing all interfaces + * implemented by the class. The order of the interface objects in + * the array corresponds to the order of the interface names in + * the {@code implements} clause of the declaration of the class + * represented by this object. In the case of an array class, the + * interfaces {@code Cloneable} and {@code Serializable} are + * returned in that order. + * + *

If this object represents an interface, the array contains + * objects representing all interfaces directly extended by the + * interface. The order of the interface objects in the array + * corresponds to the order of the interface names in the + * {@code extends} clause of the declaration of the interface + * represented by this object. + * + *

If this object represents a class or interface that + * implements no interfaces, the method returns an array of length + * 0. + * + *

If this object represents a primitive type or void, the + * method returns an array of length 0. + * + * @throws java.lang.reflect.GenericSignatureFormatError + * if the generic class signature does not conform to the format + * specified in + * The Java™ Virtual Machine Specification + * @throws TypeNotPresentException if any of the generic + * superinterfaces refers to a non-existent type declaration + * @throws java.lang.reflect.MalformedParameterizedTypeException + * if any of the generic superinterfaces refer to a parameterized + * type that cannot be instantiated for any reason + * @return an array of interfaces implemented by this class + * @since 1.5 + */ + public Type[] getGenericInterfaces() { + ClassRepository info = getGenericInfo(); + return (info == null) ? getInterfaces() : info.getSuperInterfaces(); + } + + + /** + * Returns the {@code Class} representing the component type of an + * array. If this class does not represent an array class this method + * returns null. + * + * @return the {@code Class} representing the component type of this + * class if this class is an array + * @see java.lang.reflect.Array + * @since JDK1.1 + */ + public native Class getComponentType(); + + + /** + * Returns the Java language modifiers for this class or interface, encoded + * in an integer. The modifiers consist of the Java Virtual Machine's + * constants for {@code public}, {@code protected}, + * {@code private}, {@code final}, {@code static}, + * {@code abstract} and {@code interface}; they should be decoded + * using the methods of class {@code Modifier}. + * + *

If the underlying class is an array class, then its + * {@code public}, {@code private} and {@code protected} + * modifiers are the same as those of its component type. If this + * {@code Class} represents a primitive type or void, its + * {@code public} modifier is always {@code true}, and its + * {@code protected} and {@code private} modifiers are always + * {@code false}. If this object represents an array class, a + * primitive type or void, then its {@code final} modifier is always + * {@code true} and its interface modifier is always + * {@code false}. The values of its other modifiers are not determined + * by this specification. + * + *

The modifier encodings are defined in The Java Virtual Machine + * Specification, table 4.1. + * + * @return the {@code int} representing the modifiers for this class + * @see java.lang.reflect.Modifier + * @since JDK1.1 + */ + public native int getModifiers(); + + + /** + * Gets the signers of this class. + * + * @return the signers of this class, or null if there are no signers. In + * particular, this method returns null if this object represents + * a primitive type or void. + * @since JDK1.1 + */ + public native Object[] getSigners(); + + + /** + * Set the signers of this class. + */ + native void setSigners(Object[] signers); + + + /** + * If this {@code Class} object represents a local or anonymous + * class within a method, returns a {@link + * java.lang.reflect.Method Method} object representing the + * immediately enclosing method of the underlying class. Returns + * {@code null} otherwise. + * + * In particular, this method returns {@code null} if the underlying + * class is a local or anonymous class immediately enclosed by a type + * declaration, instance initializer or static initializer. + * + * @return the immediately enclosing method of the underlying class, if + * that class is a local or anonymous class; otherwise {@code null}. + * + * @throws SecurityException + * If a security manager, s, is present and any of the + * following conditions is met: + * + *

    + * + *
  • the caller's class loader is not the same as the + * class loader of the enclosing class and invocation of + * {@link SecurityManager#checkPermission + * s.checkPermission} method with + * {@code RuntimePermission("accessDeclaredMembers")} + * denies access to the methods within the enclosing class + * + *
  • the caller's class loader is not the same as or an + * ancestor of the class loader for the enclosing class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of the enclosing class + * + *
+ * @since 1.5 + */ + @CallerSensitive + public Method getEnclosingMethod() throws SecurityException { + EnclosingMethodInfo enclosingInfo = getEnclosingMethodInfo(); + + if (enclosingInfo == null) + return null; + else { + if (!enclosingInfo.isMethod()) + return null; + + MethodRepository typeInfo = MethodRepository.make(enclosingInfo.getDescriptor(), + getFactory()); + Class returnType = toClass(typeInfo.getReturnType()); + Type [] parameterTypes = typeInfo.getParameterTypes(); + Class[] parameterClasses = new Class[parameterTypes.length]; + + // Convert Types to Classes; returned types *should* + // be class objects since the methodDescriptor's used + // don't have generics information + for(int i = 0; i < parameterClasses.length; i++) + parameterClasses[i] = toClass(parameterTypes[i]); + + // Perform access check + Class enclosingCandidate = enclosingInfo.getEnclosingClass(); + enclosingCandidate.checkMemberAccess(Member.DECLARED, + Reflection.getCallerClass(), true); + /* + * Loop over all declared methods; match method name, + * number of and type of parameters, *and* return + * type. Matching return type is also necessary + * because of covariant returns, etc. + */ + for(Method m: enclosingCandidate.getDeclaredMethods()) { + if (m.getName().equals(enclosingInfo.getName()) ) { + Class[] candidateParamClasses = m.getParameterTypes(); + if (candidateParamClasses.length == parameterClasses.length) { + boolean matches = true; + for(int i = 0; i < candidateParamClasses.length; i++) { + if (!candidateParamClasses[i].equals(parameterClasses[i])) { + matches = false; + break; + } + } + + if (matches) { // finally, check return type + if (m.getReturnType().equals(returnType) ) + return m; + } + } + } + } + + throw new InternalError("Enclosing method not found"); + } + } + + private native Object[] getEnclosingMethod0(); + + private EnclosingMethodInfo getEnclosingMethodInfo() { + Object[] enclosingInfo = getEnclosingMethod0(); + if (enclosingInfo == null) + return null; + else { + return new EnclosingMethodInfo(enclosingInfo); + } + } + + private final static class EnclosingMethodInfo { + private Class enclosingClass; + private String name; + private String descriptor; + + private EnclosingMethodInfo(Object[] enclosingInfo) { + if (enclosingInfo.length != 3) + throw new InternalError("Malformed enclosing method information"); + try { + // The array is expected to have three elements: + + // the immediately enclosing class + enclosingClass = (Class) enclosingInfo[0]; + assert(enclosingClass != null); + + // the immediately enclosing method or constructor's + // name (can be null). + name = (String) enclosingInfo[1]; + + // the immediately enclosing method or constructor's + // descriptor (null iff name is). + descriptor = (String) enclosingInfo[2]; + assert((name != null && descriptor != null) || name == descriptor); + } catch (ClassCastException cce) { + throw new InternalError("Invalid type in enclosing method information", cce); + } + } + + boolean isPartial() { + return enclosingClass == null || name == null || descriptor == null; + } + + boolean isConstructor() { return !isPartial() && "".equals(name); } + + boolean isMethod() { return !isPartial() && !isConstructor() && !"".equals(name); } + + Class getEnclosingClass() { return enclosingClass; } + + String getName() { return name; } + + String getDescriptor() { return descriptor; } + + } + + private static Class toClass(Type o) { + if (o instanceof GenericArrayType) + return Array.newInstance(toClass(((GenericArrayType)o).getGenericComponentType()), + 0) + .getClass(); + return (Class)o; + } + + /** + * If this {@code Class} object represents a local or anonymous + * class within a constructor, returns a {@link + * java.lang.reflect.Constructor Constructor} object representing + * the immediately enclosing constructor of the underlying + * class. Returns {@code null} otherwise. In particular, this + * method returns {@code null} if the underlying class is a local + * or anonymous class immediately enclosed by a type declaration, + * instance initializer or static initializer. + * + * @return the immediately enclosing constructor of the underlying class, if + * that class is a local or anonymous class; otherwise {@code null}. + * @throws SecurityException + * If a security manager, s, is present and any of the + * following conditions is met: + * + *
    + * + *
  • the caller's class loader is not the same as the + * class loader of the enclosing class and invocation of + * {@link SecurityManager#checkPermission + * s.checkPermission} method with + * {@code RuntimePermission("accessDeclaredMembers")} + * denies access to the constructors within the enclosing class + * + *
  • the caller's class loader is not the same as or an + * ancestor of the class loader for the enclosing class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of the enclosing class + * + *
+ * @since 1.5 + */ + @CallerSensitive + public Constructor getEnclosingConstructor() throws SecurityException { + EnclosingMethodInfo enclosingInfo = getEnclosingMethodInfo(); + + if (enclosingInfo == null) + return null; + else { + if (!enclosingInfo.isConstructor()) + return null; + + ConstructorRepository typeInfo = ConstructorRepository.make(enclosingInfo.getDescriptor(), + getFactory()); + Type [] parameterTypes = typeInfo.getParameterTypes(); + Class[] parameterClasses = new Class[parameterTypes.length]; + + // Convert Types to Classes; returned types *should* + // be class objects since the methodDescriptor's used + // don't have generics information + for(int i = 0; i < parameterClasses.length; i++) + parameterClasses[i] = toClass(parameterTypes[i]); + + // Perform access check + Class enclosingCandidate = enclosingInfo.getEnclosingClass(); + enclosingCandidate.checkMemberAccess(Member.DECLARED, + Reflection.getCallerClass(), true); + /* + * Loop over all declared constructors; match number + * of and type of parameters. + */ + for(Constructor c: enclosingCandidate.getDeclaredConstructors()) { + Class[] candidateParamClasses = c.getParameterTypes(); + if (candidateParamClasses.length == parameterClasses.length) { + boolean matches = true; + for(int i = 0; i < candidateParamClasses.length; i++) { + if (!candidateParamClasses[i].equals(parameterClasses[i])) { + matches = false; + break; + } + } + + if (matches) + return c; + } + } + + throw new InternalError("Enclosing constructor not found"); + } + } + + + /** + * If the class or interface represented by this {@code Class} object + * is a member of another class, returns the {@code Class} object + * representing the class in which it was declared. This method returns + * null if this class or interface is not a member of any other class. If + * this {@code Class} object represents an array class, a primitive + * type, or void,then this method returns null. + * + * @return the declaring class for this class + * @throws SecurityException + * If a security manager, s, is present and the caller's + * class loader is not the same as or an ancestor of the class + * loader for the declaring class and invocation of {@link + * SecurityManager#checkPackageAccess s.checkPackageAccess()} + * denies access to the package of the declaring class + * @since JDK1.1 + */ + @CallerSensitive + public Class getDeclaringClass() throws SecurityException { + final Class candidate = getDeclaringClass0(); + + if (candidate != null) + candidate.checkPackageAccess( + ClassLoader.getClassLoader(Reflection.getCallerClass()), true); + return candidate; + } + + private native Class getDeclaringClass0(); + + + /** + * Returns the immediately enclosing class of the underlying + * class. If the underlying class is a top level class this + * method returns {@code null}. + * @return the immediately enclosing class of the underlying class + * @exception SecurityException + * If a security manager, s, is present and the caller's + * class loader is not the same as or an ancestor of the class + * loader for the enclosing class and invocation of {@link + * SecurityManager#checkPackageAccess s.checkPackageAccess()} + * denies access to the package of the enclosing class + * @since 1.5 + */ + @CallerSensitive + public Class getEnclosingClass() throws SecurityException { + // There are five kinds of classes (or interfaces): + // a) Top level classes + // b) Nested classes (static member classes) + // c) Inner classes (non-static member classes) + // d) Local classes (named classes declared within a method) + // e) Anonymous classes + + + // JVM Spec 4.8.6: A class must have an EnclosingMethod + // attribute if and only if it is a local class or an + // anonymous class. + EnclosingMethodInfo enclosingInfo = getEnclosingMethodInfo(); + Class enclosingCandidate; + + if (enclosingInfo == null) { + // This is a top level or a nested class or an inner class (a, b, or c) + enclosingCandidate = getDeclaringClass(); + } else { + Class enclosingClass = enclosingInfo.getEnclosingClass(); + // This is a local class or an anonymous class (d or e) + if (enclosingClass == this || enclosingClass == null) + throw new InternalError("Malformed enclosing method information"); + else + enclosingCandidate = enclosingClass; + } + + if (enclosingCandidate != null) + enclosingCandidate.checkPackageAccess( + ClassLoader.getClassLoader(Reflection.getCallerClass()), true); + return enclosingCandidate; + } + + /** + * Returns the simple name of the underlying class as given in the + * source code. Returns an empty string if the underlying class is + * anonymous. + * + *

The simple name of an array is the simple name of the + * component type with "[]" appended. In particular the simple + * name of an array whose component type is anonymous is "[]". + * + * @return the simple name of the underlying class + * @since 1.5 + */ + public String getSimpleName() { + if (isArray()) + return getComponentType().getSimpleName()+"[]"; + + String simpleName = getSimpleBinaryName(); + if (simpleName == null) { // top level class + simpleName = getName(); + return simpleName.substring(simpleName.lastIndexOf(".")+1); // strip the package name + } + // According to JLS3 "Binary Compatibility" (13.1) the binary + // name of non-package classes (not top level) is the binary + // name of the immediately enclosing class followed by a '$' followed by: + // (for nested and inner classes): the simple name. + // (for local classes): 1 or more digits followed by the simple name. + // (for anonymous classes): 1 or more digits. + + // Since getSimpleBinaryName() will strip the binary name of + // the immediatly enclosing class, we are now looking at a + // string that matches the regular expression "\$[0-9]*" + // followed by a simple name (considering the simple of an + // anonymous class to be the empty string). + + // Remove leading "\$[0-9]*" from the name + int length = simpleName.length(); + if (length < 1 || simpleName.charAt(0) != '$') + throw new InternalError("Malformed class name"); + int index = 1; + while (index < length && isAsciiDigit(simpleName.charAt(index))) + index++; + // Eventually, this is the empty string iff this is an anonymous class + return simpleName.substring(index); + } + + /** + * Return an informative string for the name of this type. + * + * @return an informative string for the name of this type + * @since 1.8 + */ + public String getTypeName() { + if (isArray()) { + try { + Class cl = this; + int dimensions = 0; + while (cl.isArray()) { + dimensions++; + cl = cl.getComponentType(); + } + StringBuilder sb = new StringBuilder(); + sb.append(cl.getName()); + for (int i = 0; i < dimensions; i++) { + sb.append("[]"); + } + return sb.toString(); + } catch (Throwable e) { /*FALLTHRU*/ } + } + return getName(); + } + + /** + * Character.isDigit answers {@code true} to some non-ascii + * digits. This one does not. + */ + private static boolean isAsciiDigit(char c) { + return '0' <= c && c <= '9'; + } + + /** + * Returns the canonical name of the underlying class as + * defined by the Java Language Specification. Returns null if + * the underlying class does not have a canonical name (i.e., if + * it is a local or anonymous class or an array whose component + * type does not have a canonical name). + * @return the canonical name of the underlying class if it exists, and + * {@code null} otherwise. + * @since 1.5 + */ + public String getCanonicalName() { + if (isArray()) { + String canonicalName = getComponentType().getCanonicalName(); + if (canonicalName != null) + return canonicalName + "[]"; + else + return null; + } + if (isLocalOrAnonymousClass()) + return null; + Class enclosingClass = getEnclosingClass(); + if (enclosingClass == null) { // top level class + return getName(); + } else { + String enclosingName = enclosingClass.getCanonicalName(); + if (enclosingName == null) + return null; + return enclosingName + "." + getSimpleName(); + } + } + + /** + * Returns {@code true} if and only if the underlying class + * is an anonymous class. + * + * @return {@code true} if and only if this class is an anonymous class. + * @since 1.5 + */ + public boolean isAnonymousClass() { + return "".equals(getSimpleName()); + } + + /** + * Returns {@code true} if and only if the underlying class + * is a local class. + * + * @return {@code true} if and only if this class is a local class. + * @since 1.5 + */ + public boolean isLocalClass() { + return isLocalOrAnonymousClass() && !isAnonymousClass(); + } + + /** + * Returns {@code true} if and only if the underlying class + * is a member class. + * + * @return {@code true} if and only if this class is a member class. + * @since 1.5 + */ + public boolean isMemberClass() { + return getSimpleBinaryName() != null && !isLocalOrAnonymousClass(); + } + + /** + * Returns the "simple binary name" of the underlying class, i.e., + * the binary name without the leading enclosing class name. + * Returns {@code null} if the underlying class is a top level + * class. + */ + private String getSimpleBinaryName() { + Class enclosingClass = getEnclosingClass(); + if (enclosingClass == null) // top level class + return null; + // Otherwise, strip the enclosing class' name + try { + return getName().substring(enclosingClass.getName().length()); + } catch (IndexOutOfBoundsException ex) { + throw new InternalError("Malformed class name", ex); + } + } + + /** + * Returns {@code true} if this is a local class or an anonymous + * class. Returns {@code false} otherwise. + */ + private boolean isLocalOrAnonymousClass() { + // JVM Spec 4.8.6: A class must have an EnclosingMethod + // attribute if and only if it is a local class or an + // anonymous class. + return getEnclosingMethodInfo() != null; + } + + /** + * Returns an array containing {@code Class} objects representing all + * the public classes and interfaces that are members of the class + * represented by this {@code Class} object. This includes public + * class and interface members inherited from superclasses and public class + * and interface members declared by the class. This method returns an + * array of length 0 if this {@code Class} object has no public member + * classes or interfaces. This method also returns an array of length 0 if + * this {@code Class} object represents a primitive type, an array + * class, or void. + * + * @return the array of {@code Class} objects representing the public + * members of this class + * @throws SecurityException + * If a security manager, s, is present and + * the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class. + * + * @since JDK1.1 + */ + @CallerSensitive + public Class[] getClasses() { + checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false); + + // Privileged so this implementation can look at DECLARED classes, + // something the caller might not have privilege to do. The code here + // is allowed to look at DECLARED classes because (1) it does not hand + // out anything other than public members and (2) public member access + // has already been ok'd by the SecurityManager. + + return java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction[]>() { + public Class[] run() { + List> list = new ArrayList<>(); + Class currentClass = Class.this; + while (currentClass != null) { + Class[] members = currentClass.getDeclaredClasses(); + for (int i = 0; i < members.length; i++) { + if (Modifier.isPublic(members[i].getModifiers())) { + list.add(members[i]); + } + } + currentClass = currentClass.getSuperclass(); + } + return list.toArray(new Class[0]); + } + }); + } + + + /** + * Returns an array containing {@code Field} objects reflecting all + * the accessible public fields of the class or interface represented by + * this {@code Class} object. + * + *

If this {@code Class} object represents a class or interface with no + * no accessible public fields, then this method returns an array of length + * 0. + * + *

If this {@code Class} object represents a class, then this method + * returns the public fields of the class and of all its superclasses. + * + *

If this {@code Class} object represents an interface, then this + * method returns the fields of the interface and of all its + * superinterfaces. + * + *

If this {@code Class} object represents an array type, a primitive + * type, or void, then this method returns an array of length 0. + * + *

The elements in the returned array are not sorted and are not in any + * particular order. + * + * @return the array of {@code Field} objects representing the + * public fields + * @throws SecurityException + * If a security manager, s, is present and + * the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class. + * + * @since JDK1.1 + * @jls 8.2 Class Members + * @jls 8.3 Field Declarations + */ + @CallerSensitive + public Field[] getFields() throws SecurityException { + checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); + return copyFields(privateGetPublicFields(null)); + } + + + /** + * Returns an array containing {@code Method} objects reflecting all the + * public methods of the class or interface represented by this {@code + * Class} object, including those declared by the class or interface and + * those inherited from superclasses and superinterfaces. + * + *

If this {@code Class} object represents a type that has multiple + * public methods with the same name and parameter types, but different + * return types, then the returned array has a {@code Method} object for + * each such method. + * + *

If this {@code Class} object represents a type with a class + * initialization method {@code }, then the returned array does + * not have a corresponding {@code Method} object. + * + *

If this {@code Class} object represents an array type, then the + * returned array has a {@code Method} object for each of the public + * methods inherited by the array type from {@code Object}. It does not + * contain a {@code Method} object for {@code clone()}. + * + *

If this {@code Class} object represents an interface then the + * returned array does not contain any implicitly declared methods from + * {@code Object}. Therefore, if no methods are explicitly declared in + * this interface or any of its superinterfaces then the returned array + * has length 0. (Note that a {@code Class} object which represents a class + * always has public methods, inherited from {@code Object}.) + * + *

If this {@code Class} object represents a primitive type or void, + * then the returned array has length 0. + * + *

Static methods declared in superinterfaces of the class or interface + * represented by this {@code Class} object are not considered members of + * the class or interface. + * + *

The elements in the returned array are not sorted and are not in any + * particular order. + * + * @return the array of {@code Method} objects representing the + * public methods of this class + * @throws SecurityException + * If a security manager, s, is present and + * the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class. + * + * @jls 8.2 Class Members + * @jls 8.4 Method Declarations + * @since JDK1.1 + */ + @CallerSensitive + public Method[] getMethods() throws SecurityException { + checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); + return copyMethods(privateGetPublicMethods()); + } + + + /** + * Returns an array containing {@code Constructor} objects reflecting + * all the public constructors of the class represented by this + * {@code Class} object. An array of length 0 is returned if the + * class has no public constructors, or if the class is an array class, or + * if the class reflects a primitive type or void. + * + * Note that while this method returns an array of {@code + * Constructor} objects (that is an array of constructors from + * this class), the return type of this method is {@code + * Constructor[]} and not {@code Constructor[]} as + * might be expected. This less informative return type is + * necessary since after being returned from this method, the + * array could be modified to hold {@code Constructor} objects for + * different classes, which would violate the type guarantees of + * {@code Constructor[]}. + * + * @return the array of {@code Constructor} objects representing the + * public constructors of this class + * @throws SecurityException + * If a security manager, s, is present and + * the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class. + * + * @since JDK1.1 + */ + @CallerSensitive + public Constructor[] getConstructors() throws SecurityException { + checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); + return copyConstructors(privateGetDeclaredConstructors(true)); + } + + + /** + * Returns a {@code Field} object that reflects the specified public member + * field of the class or interface represented by this {@code Class} + * object. The {@code name} parameter is a {@code String} specifying the + * simple name of the desired field. + * + *

The field to be reflected is determined by the algorithm that + * follows. Let C be the class or interface represented by this object: + * + *

    + *
  1. If C declares a public field with the name specified, that is the + * field to be reflected.
  2. + *
  3. If no field was found in step 1 above, this algorithm is applied + * recursively to each direct superinterface of C. The direct + * superinterfaces are searched in the order they were declared.
  4. + *
  5. If no field was found in steps 1 and 2 above, and C has a + * superclass S, then this algorithm is invoked recursively upon S. + * If C has no superclass, then a {@code NoSuchFieldException} + * is thrown.
  6. + *
+ * + *

If this {@code Class} object represents an array type, then this + * method does not find the {@code length} field of the array type. + * + * @param name the field name + * @return the {@code Field} object of this class specified by + * {@code name} + * @throws NoSuchFieldException if a field with the specified name is + * not found. + * @throws NullPointerException if {@code name} is {@code null} + * @throws SecurityException + * If a security manager, s, is present and + * the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class. + * + * @since JDK1.1 + * @jls 8.2 Class Members + * @jls 8.3 Field Declarations + */ + @CallerSensitive + public Field getField(String name) + throws NoSuchFieldException, SecurityException { + checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); + Field field = getField0(name); + if (field == null) { + throw new NoSuchFieldException(name); + } + return field; + } + + + /** + * Returns a {@code Method} object that reflects the specified public + * member method of the class or interface represented by this + * {@code Class} object. The {@code name} parameter is a + * {@code String} specifying the simple name of the desired method. The + * {@code parameterTypes} parameter is an array of {@code Class} + * objects that identify the method's formal parameter types, in declared + * order. If {@code parameterTypes} is {@code null}, it is + * treated as if it were an empty array. + * + *

If the {@code name} is "{@code }" or "{@code }" a + * {@code NoSuchMethodException} is raised. Otherwise, the method to + * be reflected is determined by the algorithm that follows. Let C be the + * class or interface represented by this object: + *

    + *
  1. C is searched for a matching method, as defined below. If a + * matching method is found, it is reflected.
  2. + *
  3. If no matching method is found by step 1 then: + *
      + *
    1. If C is a class other than {@code Object}, then this algorithm is + * invoked recursively on the superclass of C.
    2. + *
    3. If C is the class {@code Object}, or if C is an interface, then + * the superinterfaces of C (if any) are searched for a matching + * method. If any such method is found, it is reflected.
    4. + *
  4. + *
+ * + *

To find a matching method in a class or interface C:  If C + * declares exactly one public method with the specified name and exactly + * the same formal parameter types, that is the method reflected. If more + * than one such method is found in C, and one of these methods has a + * return type that is more specific than any of the others, that method is + * reflected; otherwise one of the methods is chosen arbitrarily. + * + *

Note that there may be more than one matching method in a + * class because while the Java language forbids a class to + * declare multiple methods with the same signature but different + * return types, the Java virtual machine does not. This + * increased flexibility in the virtual machine can be used to + * implement various language features. For example, covariant + * returns can be implemented with {@linkplain + * java.lang.reflect.Method#isBridge bridge methods}; the bridge + * method and the method being overridden would have the same + * signature but different return types. + * + *

If this {@code Class} object represents an array type, then this + * method does not find the {@code clone()} method. + * + *

Static methods declared in superinterfaces of the class or interface + * represented by this {@code Class} object are not considered members of + * the class or interface. + * + * @param name the name of the method + * @param parameterTypes the list of parameters + * @return the {@code Method} object that matches the specified + * {@code name} and {@code parameterTypes} + * @throws NoSuchMethodException if a matching method is not found + * or if the name is "<init>"or "<clinit>". + * @throws NullPointerException if {@code name} is {@code null} + * @throws SecurityException + * If a security manager, s, is present and + * the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class. + * + * @jls 8.2 Class Members + * @jls 8.4 Method Declarations + * @since JDK1.1 + */ + @CallerSensitive + public Method getMethod(String name, Class... parameterTypes) + throws NoSuchMethodException, SecurityException { + checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); + Method method = getMethod0(name, parameterTypes, true); + if (method == null) { + throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); + } + return method; + } + + + /** + * Returns a {@code Constructor} object that reflects the specified + * public constructor of the class represented by this {@code Class} + * object. The {@code parameterTypes} parameter is an array of + * {@code Class} objects that identify the constructor's formal + * parameter types, in declared order. + * + * If this {@code Class} object represents an inner class + * declared in a non-static context, the formal parameter types + * include the explicit enclosing instance as the first parameter. + * + *

The constructor to reflect is the public constructor of the class + * represented by this {@code Class} object whose formal parameter + * types match those specified by {@code parameterTypes}. + * + * @param parameterTypes the parameter array + * @return the {@code Constructor} object of the public constructor that + * matches the specified {@code parameterTypes} + * @throws NoSuchMethodException if a matching method is not found. + * @throws SecurityException + * If a security manager, s, is present and + * the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class. + * + * @since JDK1.1 + */ + @CallerSensitive + public Constructor getConstructor(Class... parameterTypes) + throws NoSuchMethodException, SecurityException { + checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); + return getConstructor0(parameterTypes, Member.PUBLIC); + } + + + /** + * Returns an array of {@code Class} objects reflecting all the + * classes and interfaces declared as members of the class represented by + * this {@code Class} object. This includes public, protected, default + * (package) access, and private classes and interfaces declared by the + * class, but excludes inherited classes and interfaces. This method + * returns an array of length 0 if the class declares no classes or + * interfaces as members, or if this {@code Class} object represents a + * primitive type, an array class, or void. + * + * @return the array of {@code Class} objects representing all the + * declared members of this class + * @throws SecurityException + * If a security manager, s, is present and any of the + * following conditions is met: + * + *

    + * + *
  • the caller's class loader is not the same as the + * class loader of this class and invocation of + * {@link SecurityManager#checkPermission + * s.checkPermission} method with + * {@code RuntimePermission("accessDeclaredMembers")} + * denies access to the declared classes within this class + * + *
  • the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class + * + *
+ * + * @since JDK1.1 + */ + @CallerSensitive + public Class[] getDeclaredClasses() throws SecurityException { + checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), false); + return getDeclaredClasses0(); + } + + + /** + * Returns an array of {@code Field} objects reflecting all the fields + * declared by the class or interface represented by this + * {@code Class} object. This includes public, protected, default + * (package) access, and private fields, but excludes inherited fields. + * + *

If this {@code Class} object represents a class or interface with no + * declared fields, then this method returns an array of length 0. + * + *

If this {@code Class} object represents an array type, a primitive + * type, or void, then this method returns an array of length 0. + * + *

The elements in the returned array are not sorted and are not in any + * particular order. + * + * @return the array of {@code Field} objects representing all the + * declared fields of this class + * @throws SecurityException + * If a security manager, s, is present and any of the + * following conditions is met: + * + *

    + * + *
  • the caller's class loader is not the same as the + * class loader of this class and invocation of + * {@link SecurityManager#checkPermission + * s.checkPermission} method with + * {@code RuntimePermission("accessDeclaredMembers")} + * denies access to the declared fields within this class + * + *
  • the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class + * + *
+ * + * @since JDK1.1 + * @jls 8.2 Class Members + * @jls 8.3 Field Declarations + */ + @CallerSensitive + public Field[] getDeclaredFields() throws SecurityException { + checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); + return copyFields(privateGetDeclaredFields(false)); + } + + + /** + * + * Returns an array containing {@code Method} objects reflecting all the + * declared methods of the class or interface represented by this {@code + * Class} object, including public, protected, default (package) + * access, and private methods, but excluding inherited methods. + * + *

If this {@code Class} object represents a type that has multiple + * declared methods with the same name and parameter types, but different + * return types, then the returned array has a {@code Method} object for + * each such method. + * + *

If this {@code Class} object represents a type that has a class + * initialization method {@code }, then the returned array does + * not have a corresponding {@code Method} object. + * + *

If this {@code Class} object represents a class or interface with no + * declared methods, then the returned array has length 0. + * + *

If this {@code Class} object represents an array type, a primitive + * type, or void, then the returned array has length 0. + * + *

The elements in the returned array are not sorted and are not in any + * particular order. + * + * @return the array of {@code Method} objects representing all the + * declared methods of this class + * @throws SecurityException + * If a security manager, s, is present and any of the + * following conditions is met: + * + *

    + * + *
  • the caller's class loader is not the same as the + * class loader of this class and invocation of + * {@link SecurityManager#checkPermission + * s.checkPermission} method with + * {@code RuntimePermission("accessDeclaredMembers")} + * denies access to the declared methods within this class + * + *
  • the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class + * + *
+ * + * @jls 8.2 Class Members + * @jls 8.4 Method Declarations + * @since JDK1.1 + */ + @CallerSensitive + public Method[] getDeclaredMethods() throws SecurityException { + checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); + return copyMethods(privateGetDeclaredMethods(false)); + } + + + /** + * Returns an array of {@code Constructor} objects reflecting all the + * constructors declared by the class represented by this + * {@code Class} object. These are public, protected, default + * (package) access, and private constructors. The elements in the array + * returned are not sorted and are not in any particular order. If the + * class has a default constructor, it is included in the returned array. + * This method returns an array of length 0 if this {@code Class} + * object represents an interface, a primitive type, an array class, or + * void. + * + *

See The Java Language Specification, section 8.2. + * + * @return the array of {@code Constructor} objects representing all the + * declared constructors of this class + * @throws SecurityException + * If a security manager, s, is present and any of the + * following conditions is met: + * + *

    + * + *
  • the caller's class loader is not the same as the + * class loader of this class and invocation of + * {@link SecurityManager#checkPermission + * s.checkPermission} method with + * {@code RuntimePermission("accessDeclaredMembers")} + * denies access to the declared constructors within this class + * + *
  • the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class + * + *
+ * + * @since JDK1.1 + */ + @CallerSensitive + public Constructor[] getDeclaredConstructors() throws SecurityException { + checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); + return copyConstructors(privateGetDeclaredConstructors(false)); + } + + + /** + * Returns a {@code Field} object that reflects the specified declared + * field of the class or interface represented by this {@code Class} + * object. The {@code name} parameter is a {@code String} that specifies + * the simple name of the desired field. + * + *

If this {@code Class} object represents an array type, then this + * method does not find the {@code length} field of the array type. + * + * @param name the name of the field + * @return the {@code Field} object for the specified field in this + * class + * @throws NoSuchFieldException if a field with the specified name is + * not found. + * @throws NullPointerException if {@code name} is {@code null} + * @throws SecurityException + * If a security manager, s, is present and any of the + * following conditions is met: + * + *

    + * + *
  • the caller's class loader is not the same as the + * class loader of this class and invocation of + * {@link SecurityManager#checkPermission + * s.checkPermission} method with + * {@code RuntimePermission("accessDeclaredMembers")} + * denies access to the declared field + * + *
  • the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class + * + *
+ * + * @since JDK1.1 + * @jls 8.2 Class Members + * @jls 8.3 Field Declarations + */ + @CallerSensitive + public Field getDeclaredField(String name) + throws NoSuchFieldException, SecurityException { + checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); + Field field = searchFields(privateGetDeclaredFields(false), name); + if (field == null) { + throw new NoSuchFieldException(name); + } + return field; + } + + + /** + * Returns a {@code Method} object that reflects the specified + * declared method of the class or interface represented by this + * {@code Class} object. The {@code name} parameter is a + * {@code String} that specifies the simple name of the desired + * method, and the {@code parameterTypes} parameter is an array of + * {@code Class} objects that identify the method's formal parameter + * types, in declared order. If more than one method with the same + * parameter types is declared in a class, and one of these methods has a + * return type that is more specific than any of the others, that method is + * returned; otherwise one of the methods is chosen arbitrarily. If the + * name is "<init>"or "<clinit>" a {@code NoSuchMethodException} + * is raised. + * + *

If this {@code Class} object represents an array type, then this + * method does not find the {@code clone()} method. + * + * @param name the name of the method + * @param parameterTypes the parameter array + * @return the {@code Method} object for the method of this class + * matching the specified name and parameters + * @throws NoSuchMethodException if a matching method is not found. + * @throws NullPointerException if {@code name} is {@code null} + * @throws SecurityException + * If a security manager, s, is present and any of the + * following conditions is met: + * + *

    + * + *
  • the caller's class loader is not the same as the + * class loader of this class and invocation of + * {@link SecurityManager#checkPermission + * s.checkPermission} method with + * {@code RuntimePermission("accessDeclaredMembers")} + * denies access to the declared method + * + *
  • the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class + * + *
+ * + * @jls 8.2 Class Members + * @jls 8.4 Method Declarations + * @since JDK1.1 + */ + @CallerSensitive + public Method getDeclaredMethod(String name, Class... parameterTypes) + throws NoSuchMethodException, SecurityException { + checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); + Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes); + if (method == null) { + throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); + } + return method; + } + + + /** + * Returns a {@code Constructor} object that reflects the specified + * constructor of the class or interface represented by this + * {@code Class} object. The {@code parameterTypes} parameter is + * an array of {@code Class} objects that identify the constructor's + * formal parameter types, in declared order. + * + * If this {@code Class} object represents an inner class + * declared in a non-static context, the formal parameter types + * include the explicit enclosing instance as the first parameter. + * + * @param parameterTypes the parameter array + * @return The {@code Constructor} object for the constructor with the + * specified parameter list + * @throws NoSuchMethodException if a matching method is not found. + * @throws SecurityException + * If a security manager, s, is present and any of the + * following conditions is met: + * + *
    + * + *
  • the caller's class loader is not the same as the + * class loader of this class and invocation of + * {@link SecurityManager#checkPermission + * s.checkPermission} method with + * {@code RuntimePermission("accessDeclaredMembers")} + * denies access to the declared constructor + * + *
  • the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class + * + *
+ * + * @since JDK1.1 + */ + @CallerSensitive + public Constructor getDeclaredConstructor(Class... parameterTypes) + throws NoSuchMethodException, SecurityException { + checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); + return getConstructor0(parameterTypes, Member.DECLARED); + } + + /** + * Finds a resource with a given name. The rules for searching resources + * associated with a given class are implemented by the defining + * {@linkplain ClassLoader class loader} of the class. This method + * delegates to this object's class loader. If this object was loaded by + * the bootstrap class loader, the method delegates to {@link + * ClassLoader#getSystemResourceAsStream}. + * + *

Before delegation, an absolute resource name is constructed from the + * given resource name using this algorithm: + * + *

    + * + *
  • If the {@code name} begins with a {@code '/'} + * ('\u002f'), then the absolute name of the resource is the + * portion of the {@code name} following the {@code '/'}. + * + *
  • Otherwise, the absolute name is of the following form: + * + *
    + * {@code modified_package_name/name} + *
    + * + *

    Where the {@code modified_package_name} is the package name of this + * object with {@code '/'} substituted for {@code '.'} + * ('\u002e'). + * + *

+ * + * @param name name of the desired resource + * @return A {@link java.io.InputStream} object or {@code null} if + * no resource with this name is found + * @throws NullPointerException If {@code name} is {@code null} + * @since JDK1.1 + */ + public InputStream getResourceAsStream(String name) { + name = resolveName(name); + ClassLoader cl = getClassLoader0(); + if (cl==null) { + // A system class. + return ClassLoader.getSystemResourceAsStream(name); + } + return cl.getResourceAsStream(name); + } + + /** + * Finds a resource with a given name. The rules for searching resources + * associated with a given class are implemented by the defining + * {@linkplain ClassLoader class loader} of the class. This method + * delegates to this object's class loader. If this object was loaded by + * the bootstrap class loader, the method delegates to {@link + * ClassLoader#getSystemResource}. + * + *

Before delegation, an absolute resource name is constructed from the + * given resource name using this algorithm: + * + *

    + * + *
  • If the {@code name} begins with a {@code '/'} + * ('\u002f'), then the absolute name of the resource is the + * portion of the {@code name} following the {@code '/'}. + * + *
  • Otherwise, the absolute name is of the following form: + * + *
    + * {@code modified_package_name/name} + *
    + * + *

    Where the {@code modified_package_name} is the package name of this + * object with {@code '/'} substituted for {@code '.'} + * ('\u002e'). + * + *

+ * + * @param name name of the desired resource + * @return A {@link java.net.URL} object or {@code null} if no + * resource with this name is found + * @since JDK1.1 + */ + public java.net.URL getResource(String name) { + name = resolveName(name); + ClassLoader cl = getClassLoader0(); + if (cl==null) { + // A system class. + return ClassLoader.getSystemResource(name); + } + return cl.getResource(name); + } + + + + /** protection domain returned when the internal domain is null */ + private static java.security.ProtectionDomain allPermDomain; + + + /** + * Returns the {@code ProtectionDomain} of this class. If there is a + * security manager installed, this method first calls the security + * manager's {@code checkPermission} method with a + * {@code RuntimePermission("getProtectionDomain")} permission to + * ensure it's ok to get the + * {@code ProtectionDomain}. + * + * @return the ProtectionDomain of this class + * + * @throws SecurityException + * if a security manager exists and its + * {@code checkPermission} method doesn't allow + * getting the ProtectionDomain. + * + * @see java.security.ProtectionDomain + * @see SecurityManager#checkPermission + * @see java.lang.RuntimePermission + * @since 1.2 + */ + public java.security.ProtectionDomain getProtectionDomain() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(SecurityConstants.GET_PD_PERMISSION); + } + java.security.ProtectionDomain pd = getProtectionDomain0(); + if (pd == null) { + if (allPermDomain == null) { + java.security.Permissions perms = + new java.security.Permissions(); + perms.add(SecurityConstants.ALL_PERMISSION); + allPermDomain = + new java.security.ProtectionDomain(null, perms); + } + pd = allPermDomain; + } + return pd; + } + + + /** + * Returns the ProtectionDomain of this class. + */ + private native java.security.ProtectionDomain getProtectionDomain0(); + + /* + * Return the Virtual Machine's Class object for the named + * primitive type. + */ + static native Class getPrimitiveClass(String name); + + /* + * Check if client is allowed to access members. If access is denied, + * throw a SecurityException. + * + * This method also enforces package access. + * + *

Default policy: allow all clients access with normal Java access + * control. + */ + private void checkMemberAccess(int which, Class caller, boolean checkProxyInterfaces) { + final SecurityManager s = System.getSecurityManager(); + if (s != null) { + /* Default policy allows access to all {@link Member#PUBLIC} members, + * as well as access to classes that have the same class loader as the caller. + * In all other cases, it requires RuntimePermission("accessDeclaredMembers") + * permission. + */ + final ClassLoader ccl = ClassLoader.getClassLoader(caller); + final ClassLoader cl = getClassLoader0(); + if (which != Member.PUBLIC) { + if (ccl != cl) { + s.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); + } + } + this.checkPackageAccess(ccl, checkProxyInterfaces); + } + } + + /* + * Checks if a client loaded in ClassLoader ccl is allowed to access this + * class under the current package access policy. If access is denied, + * throw a SecurityException. + */ + private void checkPackageAccess(final ClassLoader ccl, boolean checkProxyInterfaces) { + final SecurityManager s = System.getSecurityManager(); + if (s != null) { + final ClassLoader cl = getClassLoader0(); + + if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) { + String name = this.getName(); + int i = name.lastIndexOf('.'); + if (i != -1) { + // skip the package access check on a proxy class in default proxy package + String pkg = name.substring(0, i); + if (!Proxy.isProxyClass(this) || ReflectUtil.isNonPublicProxyClass(this)) { + s.checkPackageAccess(pkg); + } + } + } + // check package access on the proxy interfaces + if (checkProxyInterfaces && Proxy.isProxyClass(this)) { + ReflectUtil.checkProxyPackageAccess(ccl, this.getInterfaces()); + } + } + } + + /** + * Add a package name prefix if the name is not absolute Remove leading "/" + * if name is absolute + */ + private String resolveName(String name) { + if (name == null) { + return name; + } + if (!name.startsWith("/")) { + Class c = this; + while (c.isArray()) { + c = c.getComponentType(); + } + String baseName = c.getName(); + int index = baseName.lastIndexOf('.'); + if (index != -1) { + name = baseName.substring(0, index).replace('.', '/') + +"/"+name; + } + } else { + name = name.substring(1); + } + return name; + } + + /** + * Atomic operations support. + */ + private static class Atomic { + @ikvm.internal.InterlockedCompareAndSet("reflectionData") + static native boolean casReflectionData(Class clazz, + SoftReference> oldData, + SoftReference> newData); + + @ikvm.internal.InterlockedCompareAndSet("annotationType") + static native boolean casAnnotationType(Class clazz, + AnnotationType oldType, + AnnotationType newType); + + @ikvm.internal.InterlockedCompareAndSet("annotationData") + static native boolean casAnnotationData(Class clazz, + AnnotationData oldData, + AnnotationData newData); + } + + /** + * Reflection support. + */ + + // Caches for certain reflective results + private static boolean useCaches; + + // reflection data that might get invalidated when JVM TI RedefineClasses() is called + private static class ReflectionData { + volatile Field[] declaredFields; + volatile Field[] publicFields; + volatile Method[] declaredMethods; + volatile Method[] publicMethods; + volatile Constructor[] declaredConstructors; + volatile Constructor[] publicConstructors; + // Intermediate results for getFields and getMethods + volatile Field[] declaredPublicFields; + volatile Method[] declaredPublicMethods; + volatile Class[] interfaces; + + // Value of classRedefinedCount when we created this ReflectionData instance + final int redefinedCount; + + ReflectionData(int redefinedCount) { + this.redefinedCount = redefinedCount; + } + } + + private volatile transient SoftReference> reflectionData; + + // Incremented by the VM on each call to JVM TI RedefineClasses() + // that redefines this class or a superclass. + private volatile transient int classRedefinedCount; + + // Lazily create and cache ReflectionData + private ReflectionData reflectionData() { + SoftReference> reflectionData = this.reflectionData; + int classRedefinedCount = this.classRedefinedCount; + ReflectionData rd; + if (useCaches && + reflectionData != null && + (rd = reflectionData.get()) != null && + rd.redefinedCount == classRedefinedCount) { + return rd; + } + // else no SoftReference or cleared SoftReference or stale ReflectionData + // -> create and replace new instance + return newReflectionData(reflectionData, classRedefinedCount); + } + + private ReflectionData newReflectionData(SoftReference> oldReflectionData, + int classRedefinedCount) { + if (!useCaches) return null; + + while (true) { + ReflectionData rd = new ReflectionData<>(classRedefinedCount); + // try to CAS it... + if (Atomic.casReflectionData(this, oldReflectionData, new SoftReference<>(rd))) { + return rd; + } + // else retry + oldReflectionData = this.reflectionData; + classRedefinedCount = this.classRedefinedCount; + if (oldReflectionData != null && + (rd = oldReflectionData.get()) != null && + rd.redefinedCount == classRedefinedCount) { + return rd; + } + } + } + + // Generic signature handling + private native String getGenericSignature0(); + + // Generic info repository; lazily initialized + private volatile transient ClassRepository genericInfo; + + // accessor for factory + private GenericsFactory getFactory() { + // create scope and factory + return CoreReflectionFactory.make(this, ClassScope.make(this)); + } + + // accessor for generic info repository; + // generic info is lazily initialized + private ClassRepository getGenericInfo() { + ClassRepository genericInfo = this.genericInfo; + if (genericInfo == null) { + String signature = getGenericSignature0(); + if (signature == null) { + genericInfo = ClassRepository.NONE; + } else { + genericInfo = ClassRepository.make(signature, getFactory()); + } + this.genericInfo = genericInfo; + } + return (genericInfo != ClassRepository.NONE) ? genericInfo : null; + } + + // Annotations handling + private native Map, Annotation> getDeclaredAnnotationsImpl(); + // Since 1.8 + native byte[] getRawTypeAnnotations(); + static byte[] getExecutableTypeAnnotationBytes(Executable ex) { + return getReflectionFactory().getExecutableTypeAnnotationBytes(ex); + } + + native ConstantPool getConstantPool(); + + // + // + // java.lang.reflect.Field handling + // + // + + // Returns an array of "root" fields. These Field objects must NOT + // be propagated to the outside world, but must instead be copied + // via ReflectionFactory.copyField. + private Field[] privateGetDeclaredFields(boolean publicOnly) { + checkInitted(); + Field[] res; + ReflectionData rd = reflectionData(); + if (rd != null) { + res = publicOnly ? rd.declaredPublicFields : rd.declaredFields; + if (res != null) return res; + } + // No cached value available; request value from VM + res = Reflection.filterFields(this, getDeclaredFields0(publicOnly)); + if (rd != null) { + if (publicOnly) { + rd.declaredPublicFields = res; + } else { + rd.declaredFields = res; + } + } + return res; + } + + // Returns an array of "root" fields. These Field objects must NOT + // be propagated to the outside world, but must instead be copied + // via ReflectionFactory.copyField. + private Field[] privateGetPublicFields(Set> traversedInterfaces) { + checkInitted(); + Field[] res; + ReflectionData rd = reflectionData(); + if (rd != null) { + res = rd.publicFields; + if (res != null) return res; + } + + // No cached value available; compute value recursively. + // Traverse in correct order for getField(). + List fields = new ArrayList<>(); + if (traversedInterfaces == null) { + traversedInterfaces = new HashSet<>(); + } + + // Local fields + Field[] tmp = privateGetDeclaredFields(true); + addAll(fields, tmp); + + // Direct superinterfaces, recursively + for (Class c : getInterfaces()) { + if (!traversedInterfaces.contains(c)) { + traversedInterfaces.add(c); + addAll(fields, c.privateGetPublicFields(traversedInterfaces)); + } + } + + // Direct superclass, recursively + if (!isInterface()) { + Class c = getSuperclass(); + if (c != null) { + addAll(fields, c.privateGetPublicFields(traversedInterfaces)); + } + } + + res = new Field[fields.size()]; + fields.toArray(res); + if (rd != null) { + rd.publicFields = res; + } + return res; + } + + private static void addAll(Collection c, Field[] o) { + for (int i = 0; i < o.length; i++) { + c.add(o[i]); + } + } + + + // + // + // java.lang.reflect.Constructor handling + // + // + + // Returns an array of "root" constructors. These Constructor + // objects must NOT be propagated to the outside world, but must + // instead be copied via ReflectionFactory.copyConstructor. + private Constructor[] privateGetDeclaredConstructors(boolean publicOnly) { + checkInitted(); + Constructor[] res; + ReflectionData rd = reflectionData(); + if (rd != null) { + res = publicOnly ? rd.publicConstructors : rd.declaredConstructors; + if (res != null) return res; + } + // No cached value available; request value from VM + if (isInterface()) { + @SuppressWarnings("unchecked") + Constructor[] temporaryRes = (Constructor[]) new Constructor[0]; + res = temporaryRes; + } else { + res = getDeclaredConstructors0(publicOnly); + } + if (rd != null) { + if (publicOnly) { + rd.publicConstructors = res; + } else { + rd.declaredConstructors = res; + } + } + return res; + } + + // + // + // java.lang.reflect.Method handling + // + // + + // Returns an array of "root" methods. These Method objects must NOT + // be propagated to the outside world, but must instead be copied + // via ReflectionFactory.copyMethod. + private Method[] privateGetDeclaredMethods(boolean publicOnly) { + checkInitted(); + Method[] res; + ReflectionData rd = reflectionData(); + if (rd != null) { + res = publicOnly ? rd.declaredPublicMethods : rd.declaredMethods; + if (res != null) return res; + } + // No cached value available; request value from VM + res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly)); + if (rd != null) { + if (publicOnly) { + rd.declaredPublicMethods = res; + } else { + rd.declaredMethods = res; + } + } + return res; + } + + static class MethodArray { + // Don't add or remove methods except by add() or remove() calls. + private Method[] methods; + private int length; + private int defaults; + + MethodArray() { + this(20); + } + + MethodArray(int initialSize) { + if (initialSize < 2) + throw new IllegalArgumentException("Size should be 2 or more"); + + methods = new Method[initialSize]; + length = 0; + defaults = 0; + } + + boolean hasDefaults() { + return defaults != 0; + } + + void add(Method m) { + if (length == methods.length) { + methods = Arrays.copyOf(methods, 2 * methods.length); + } + methods[length++] = m; + + if (m != null && m.isDefault()) + defaults++; + } + + void addAll(Method[] ma) { + for (int i = 0; i < ma.length; i++) { + add(ma[i]); + } + } + + void addAll(MethodArray ma) { + for (int i = 0; i < ma.length(); i++) { + add(ma.get(i)); + } + } + + void addIfNotPresent(Method newMethod) { + for (int i = 0; i < length; i++) { + Method m = methods[i]; + if (m == newMethod || (m != null && m.equals(newMethod))) { + return; + } + } + add(newMethod); + } + + void addAllIfNotPresent(MethodArray newMethods) { + for (int i = 0; i < newMethods.length(); i++) { + Method m = newMethods.get(i); + if (m != null) { + addIfNotPresent(m); + } + } + } + + /* Add Methods declared in an interface to this MethodArray. + * Static methods declared in interfaces are not inherited. + */ + void addInterfaceMethods(Method[] methods) { + for (Method candidate : methods) { + if (!Modifier.isStatic(candidate.getModifiers())) { + add(candidate); + } + } + } + + int length() { + return length; + } + + Method get(int i) { + return methods[i]; + } + + Method getFirst() { + for (Method m : methods) + if (m != null) + return m; + return null; + } + + void removeByNameAndDescriptor(Method toRemove) { + for (int i = 0; i < length; i++) { + Method m = methods[i]; + if (m != null && matchesNameAndDescriptor(m, toRemove)) { + remove(i); + } + } + } + + private void remove(int i) { + if (methods[i] != null && methods[i].isDefault()) + defaults--; + methods[i] = null; + } + + private boolean matchesNameAndDescriptor(Method m1, Method m2) { + return m1.getReturnType() == m2.getReturnType() && + m1.getName() == m2.getName() && // name is guaranteed to be interned + arrayContentsEq(m1.getParameterTypes(), + m2.getParameterTypes()); + } + + void compactAndTrim() { + int newPos = 0; + // Get rid of null slots + for (int pos = 0; pos < length; pos++) { + Method m = methods[pos]; + if (m != null) { + if (pos != newPos) { + methods[newPos] = m; + } + newPos++; + } + } + if (newPos != methods.length) { + methods = Arrays.copyOf(methods, newPos); + } + } + + /* Removes all Methods from this MethodArray that have a more specific + * default Method in this MethodArray. + * + * Users of MethodArray are responsible for pruning Methods that have + * a more specific concrete Method. + */ + void removeLessSpecifics() { + if (!hasDefaults()) + return; + + for (int i = 0; i < length; i++) { + Method m = get(i); + if (m == null || !m.isDefault()) + continue; + + for (int j = 0; j < length; j++) { + if (i == j) + continue; + + Method candidate = get(j); + if (candidate == null) + continue; + + if (!matchesNameAndDescriptor(m, candidate)) + continue; + + if (hasMoreSpecificClass(m, candidate)) + remove(j); + } + } + } + + Method[] getArray() { + return methods; + } + + // Returns true if m1 is more specific than m2 + static boolean hasMoreSpecificClass(Method m1, Method m2) { + Class m1Class = m1.getDeclaringClass(); + Class m2Class = m2.getDeclaringClass(); + return m1Class != m2Class && m2Class.isAssignableFrom(m1Class); + } + } + + + // Returns an array of "root" methods. These Method objects must NOT + // be propagated to the outside world, but must instead be copied + // via ReflectionFactory.copyMethod. + private Method[] privateGetPublicMethods() { + checkInitted(); + Method[] res; + ReflectionData rd = reflectionData(); + if (rd != null) { + res = rd.publicMethods; + if (res != null) return res; + } + + // No cached value available; compute value recursively. + // Start by fetching public declared methods + MethodArray methods = new MethodArray(); + { + Method[] tmp = privateGetDeclaredMethods(true); + methods.addAll(tmp); + } + // Now recur over superclass and direct superinterfaces. + // Go over superinterfaces first so we can more easily filter + // out concrete implementations inherited from superclasses at + // the end. + MethodArray inheritedMethods = new MethodArray(); + for (Class i : getInterfaces()) { + inheritedMethods.addInterfaceMethods(i.privateGetPublicMethods()); + } + if (!isInterface()) { + Class c = getSuperclass(); + if (c != null) { + MethodArray supers = new MethodArray(); + supers.addAll(c.privateGetPublicMethods()); + // Filter out concrete implementations of any + // interface methods + for (int i = 0; i < supers.length(); i++) { + Method m = supers.get(i); + if (m != null && + !Modifier.isAbstract(m.getModifiers()) && + !m.isDefault()) { + inheritedMethods.removeByNameAndDescriptor(m); + } + } + // Insert superclass's inherited methods before + // superinterfaces' to satisfy getMethod's search + // order + supers.addAll(inheritedMethods); + inheritedMethods = supers; + } + } + // Filter out all local methods from inherited ones + for (int i = 0; i < methods.length(); i++) { + Method m = methods.get(i); + inheritedMethods.removeByNameAndDescriptor(m); + } + methods.addAllIfNotPresent(inheritedMethods); + methods.removeLessSpecifics(); + methods.compactAndTrim(); + res = methods.getArray(); + if (rd != null) { + rd.publicMethods = res; + } + return res; + } + + + // + // Helpers for fetchers of one field, method, or constructor + // + + private static Field searchFields(Field[] fields, String name) { + String internedName = name.intern(); + for (int i = 0; i < fields.length; i++) { + if (fields[i].getName() == internedName) { + return getReflectionFactory().copyField(fields[i]); + } + } + return null; + } + + private Field getField0(String name) throws NoSuchFieldException { + // Note: the intent is that the search algorithm this routine + // uses be equivalent to the ordering imposed by + // privateGetPublicFields(). It fetches only the declared + // public fields for each class, however, to reduce the number + // of Field objects which have to be created for the common + // case where the field being requested is declared in the + // class which is being queried. + Field res; + // Search declared public fields + if ((res = searchFields(privateGetDeclaredFields(true), name)) != null) { + return res; + } + // Direct superinterfaces, recursively + Class[] interfaces = getInterfaces(); + for (int i = 0; i < interfaces.length; i++) { + Class c = interfaces[i]; + if ((res = c.getField0(name)) != null) { + return res; + } + } + // Direct superclass, recursively + if (!isInterface()) { + Class c = getSuperclass(); + if (c != null) { + if ((res = c.getField0(name)) != null) { + return res; + } + } + } + return null; + } + + private static Method searchMethods(Method[] methods, + String name, + Class[] parameterTypes) + { + Method res = null; + String internedName = name.intern(); + for (int i = 0; i < methods.length; i++) { + Method m = methods[i]; + if (m.getName() == internedName + && arrayContentsEq(parameterTypes, m.getParameterTypes()) + && (res == null + || res.getReturnType().isAssignableFrom(m.getReturnType()))) + res = m; + } + + return (res == null ? res : getReflectionFactory().copyMethod(res)); + } + + private Method getMethod0(String name, Class[] parameterTypes, boolean includeStaticMethods) { + MethodArray interfaceCandidates = new MethodArray(2); + Method res = privateGetMethodRecursive(name, parameterTypes, includeStaticMethods, interfaceCandidates); + if (res != null) + return res; + + // Not found on class or superclass directly + interfaceCandidates.removeLessSpecifics(); + return interfaceCandidates.getFirst(); // may be null + } + + private Method privateGetMethodRecursive(String name, + Class[] parameterTypes, + boolean includeStaticMethods, + MethodArray allInterfaceCandidates) { + // Note: the intent is that the search algorithm this routine + // uses be equivalent to the ordering imposed by + // privateGetPublicMethods(). It fetches only the declared + // public methods for each class, however, to reduce the + // number of Method objects which have to be created for the + // common case where the method being requested is declared in + // the class which is being queried. + // + // Due to default methods, unless a method is found on a superclass, + // methods declared in any superinterface needs to be considered. + // Collect all candidates declared in superinterfaces in {@code + // allInterfaceCandidates} and select the most specific if no match on + // a superclass is found. + + // Must _not_ return root methods + Method res; + // Search declared public methods + if ((res = searchMethods(privateGetDeclaredMethods(true), + name, + parameterTypes)) != null) { + if (includeStaticMethods || !Modifier.isStatic(res.getModifiers())) + return res; + } + // Search superclass's methods + if (!isInterface()) { + Class c = getSuperclass(); + if (c != null) { + if ((res = c.getMethod0(name, parameterTypes, true)) != null) { + return res; + } + } + } + // Search superinterfaces' methods + Class[] interfaces = getInterfaces(); + for (Class c : interfaces) + if ((res = c.getMethod0(name, parameterTypes, false)) != null) + allInterfaceCandidates.add(res); + // Not found + return null; + } + + private Constructor getConstructor0(Class[] parameterTypes, + int which) throws NoSuchMethodException + { + Constructor[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC)); + for (Constructor constructor : constructors) { + if (arrayContentsEq(parameterTypes, + constructor.getParameterTypes())) { + return getReflectionFactory().copyConstructor(constructor); + } + } + throw new NoSuchMethodException(getName() + "." + argumentTypesToString(parameterTypes)); + } + + // + // Other helpers and base implementation + // + + private static boolean arrayContentsEq(Object[] a1, Object[] a2) { + if (a1 == null) { + return a2 == null || a2.length == 0; + } + + if (a2 == null) { + return a1.length == 0; + } + + if (a1.length != a2.length) { + return false; + } + + for (int i = 0; i < a1.length; i++) { + if (a1[i] != a2[i]) { + return false; + } + } + + return true; + } + + private static Field[] copyFields(Field[] arg) { + Field[] out = new Field[arg.length]; + ReflectionFactory fact = getReflectionFactory(); + for (int i = 0; i < arg.length; i++) { + out[i] = fact.copyField(arg[i]); + } + return out; + } + + private static Method[] copyMethods(Method[] arg) { + Method[] out = new Method[arg.length]; + ReflectionFactory fact = getReflectionFactory(); + for (int i = 0; i < arg.length; i++) { + out[i] = fact.copyMethod(arg[i]); + } + return out; + } + + private static Constructor[] copyConstructors(Constructor[] arg) { + Constructor[] out = arg.clone(); + ReflectionFactory fact = getReflectionFactory(); + for (int i = 0; i < out.length; i++) { + out[i] = fact.copyConstructor(out[i]); + } + return out; + } + + private native Field[] getDeclaredFields0(boolean publicOnly); + private native Method[] getDeclaredMethods0(boolean publicOnly); + private native Constructor[] getDeclaredConstructors0(boolean publicOnly); + private native Class[] getDeclaredClasses0(); + + private static String argumentTypesToString(Class[] argTypes) { + StringBuilder buf = new StringBuilder(); + buf.append("("); + if (argTypes != null) { + for (int i = 0; i < argTypes.length; i++) { + if (i > 0) { + buf.append(", "); + } + Class c = argTypes[i]; + buf.append((c == null) ? "null" : c.getName()); + } + } + buf.append(")"); + return buf.toString(); + } + + /** use serialVersionUID from JDK 1.1 for interoperability */ + private static final long serialVersionUID = 3206093459760846163L; + + + /** + * Class Class is special cased within the Serialization Stream Protocol. + * + * A Class instance is written initially into an ObjectOutputStream in the + * following format: + *

+     *      {@code TC_CLASS} ClassDescriptor
+     *      A ClassDescriptor is a special cased serialization of
+     *      a {@code java.io.ObjectStreamClass} instance.
+     * 
+ * A new handle is generated for the initial time the class descriptor + * is written into the stream. Future references to the class descriptor + * are written as references to the initial class descriptor instance. + * + * @see java.io.ObjectStreamClass + */ + + @ikvm.lang.Property(get="get_spf") + private static final ObjectStreamField[] serialPersistentFields = null; + + private static ObjectStreamField[] get_spf() { + return java.io.ObjectStreamClass.NO_FIELDS; + } + + + /** + * Returns the assertion status that would be assigned to this + * class if it were to be initialized at the time this method is invoked. + * If this class has had its assertion status set, the most recent + * setting will be returned; otherwise, if any package default assertion + * status pertains to this class, the most recent setting for the most + * specific pertinent package default assertion status is returned; + * otherwise, if this class is not a system class (i.e., it has a + * class loader) its class loader's default assertion status is returned; + * otherwise, the system class default assertion status is returned. + *

+ * Few programmers will have any need for this method; it is provided + * for the benefit of the JRE itself. (It allows a class to determine at + * the time that it is initialized whether assertions should be enabled.) + * Note that this method is not guaranteed to return the actual + * assertion status that was (or will be) associated with the specified + * class when it was (or will be) initialized. + * + * @return the desired assertion status of the specified class. + * @see java.lang.ClassLoader#setClassAssertionStatus + * @see java.lang.ClassLoader#setPackageAssertionStatus + * @see java.lang.ClassLoader#setDefaultAssertionStatus + * @since 1.4 + */ + public boolean desiredAssertionStatus() { + ClassLoader loader = getClassLoader(); + // If the loader is null this is a system class, so ask the VM + if (loader == null) + return desiredAssertionStatus0(this); + + // If the classloader has been initialized with the assertion + // directives, ask it. Otherwise, ask the VM. + synchronized(loader.assertionLock) { + if (loader.classAssertionStatus != null) { + return loader.desiredAssertionStatus(getName()); + } + } + return desiredAssertionStatus0(this); + } + + // Retrieves the desired assertion status of this class from the VM + private static native boolean desiredAssertionStatus0(Class clazz); + + /** + * Returns true if and only if this class was declared as an enum in the + * source code. + * + * @return true if and only if this class was declared as an enum in the + * source code + * @since 1.5 + */ + public boolean isEnum() { + // An enum must both directly extend java.lang.Enum and have + // the ENUM bit set; classes for specialized enum constants + // don't do the former. + return (this.getModifiers() & ENUM) != 0 && + this.getSuperclass() == java.lang.Enum.class; + } + + // Fetches the factory for reflective objects + private static ReflectionFactory getReflectionFactory() { + if (reflectionFactory == null) { + reflectionFactory = + java.security.AccessController.doPrivileged + (new sun.reflect.ReflectionFactory.GetReflectionFactoryAction()); + } + return reflectionFactory; + } + private static ReflectionFactory reflectionFactory; + + // To be able to query system properties as soon as they're available + private static boolean initted; + private static void checkInitted() { + if (initted) return; + useCaches = true; + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + // Tests to ensure the system properties table is fully + // initialized. This is needed because reflection code is + // called very early in the initialization process (before + // command-line arguments have been parsed and therefore + // these user-settable properties installed.) + + if (!sun.misc.VM.isBooted()) { + return null; + } + + // Doesn't use Boolean.getBoolean to avoid class init. + String val = + System.getProperty("sun.reflect.noCaches"); + if (val != null && val.equals("true")) { + useCaches = false; + } + + initted = true; + return null; + } + }); + } + + /** + * Returns the elements of this enum class or null if this + * Class object does not represent an enum type. + * + * @return an array containing the values comprising the enum class + * represented by this Class object in the order they're + * declared, or null if this Class object does not + * represent an enum type + * @since 1.5 + */ + public T[] getEnumConstants() { + T[] values = getEnumConstantsShared(); + return (values != null) ? values.clone() : null; + } + + /** + * Returns the elements of this enum class or null if this + * Class object does not represent an enum type; + * identical to getEnumConstants except that the result is + * uncloned, cached, and shared by all callers. + */ + T[] getEnumConstantsShared() { + if (enumConstants == null) { + if (!isEnum()) return null; + try { + final Method values = getMethod("values"); + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + values.setAccessible(true); + return null; + } + }); + @SuppressWarnings("unchecked") + T[] temporaryConstants = (T[])values.invoke(null); + enumConstants = temporaryConstants; + } + // These can happen when users concoct enum-like classes + // that don't comply with the enum spec. + catch (InvocationTargetException | NoSuchMethodException | + IllegalAccessException ex) { return null; } + } + return enumConstants; + } + private volatile transient T[] enumConstants; + + /** + * Returns a map from simple name to enum constant. This package-private + * method is used internally by Enum to implement + * {@code public static > T valueOf(Class, String)} + * efficiently. Note that the map is returned by this method is + * created lazily on first use. Typically it won't ever get created. + */ + Map enumConstantDirectory() { + if (enumConstantDirectory == null) { + T[] universe = getEnumConstantsShared(); + if (universe == null) + throw new IllegalArgumentException( + getName() + " is not an enum type"); + Map m = new HashMap<>(2 * universe.length); + for (T constant : universe) + m.put(((Enum)constant).name(), constant); + enumConstantDirectory = m; + } + return enumConstantDirectory; + } + private volatile transient Map enumConstantDirectory; + + /** + * Casts an object to the class or interface represented + * by this {@code Class} object. + * + * @param obj the object to be cast + * @return the object after casting, or null if obj is null + * + * @throws ClassCastException if the object is not + * null and is not assignable to the type T. + * + * @since 1.5 + */ + @SuppressWarnings("unchecked") + public T cast(Object obj) { + if (obj != null && !isInstance(obj)) + throw new ClassCastException(cannotCastMsg(obj)); + return (T) obj; + } + + private String cannotCastMsg(Object obj) { + return "Cannot cast " + obj.getClass().getName() + " to " + getName(); + } + + /** + * Casts this {@code Class} object to represent a subclass of the class + * represented by the specified class object. Checks that the cast + * is valid, and throws a {@code ClassCastException} if it is not. If + * this method succeeds, it always returns a reference to this class object. + * + *

This method is useful when a client needs to "narrow" the type of + * a {@code Class} object to pass it to an API that restricts the + * {@code Class} objects that it is willing to accept. A cast would + * generate a compile-time warning, as the correctness of the cast + * could not be checked at runtime (because generic types are implemented + * by erasure). + * + * @param the type to cast this class object to + * @param clazz the class of the type to cast this class object to + * @return this {@code Class} object, cast to represent a subclass of + * the specified class object. + * @throws ClassCastException if this {@code Class} object does not + * represent a subclass of the specified class (here "subclass" includes + * the class itself). + * @since 1.5 + */ + @SuppressWarnings("unchecked") + public Class asSubclass(Class clazz) { + if (clazz.isAssignableFrom(this)) + return (Class) this; + else + throw new ClassCastException(this.toString()); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + @SuppressWarnings("unchecked") + public A getAnnotation(Class annotationClass) { + Objects.requireNonNull(annotationClass); + + return (A) annotationData().annotations.get(annotationClass); + } + + /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + @Override + public boolean isAnnotationPresent(Class annotationClass) { + return GenericDeclaration.super.isAnnotationPresent(annotationClass); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + @Override + public A[] getAnnotationsByType(Class annotationClass) { + Objects.requireNonNull(annotationClass); + + AnnotationData annotationData = annotationData(); + return AnnotationSupport.getAssociatedAnnotations(annotationData.declaredAnnotations, + this, + annotationClass); + } + + /** + * @since 1.5 + */ + public Annotation[] getAnnotations() { + return AnnotationParser.toArray(annotationData().annotations); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + @Override + @SuppressWarnings("unchecked") + public A getDeclaredAnnotation(Class annotationClass) { + Objects.requireNonNull(annotationClass); + + return (A) annotationData().declaredAnnotations.get(annotationClass); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + @Override + public A[] getDeclaredAnnotationsByType(Class annotationClass) { + Objects.requireNonNull(annotationClass); + + return AnnotationSupport.getDirectlyAndIndirectlyPresent(annotationData().declaredAnnotations, + annotationClass); + } + + /** + * @since 1.5 + */ + public Annotation[] getDeclaredAnnotations() { + return AnnotationParser.toArray(annotationData().declaredAnnotations); + } + + // annotation data that might get invalidated when JVM TI RedefineClasses() is called + private static class AnnotationData { + final Map, Annotation> annotations; + final Map, Annotation> declaredAnnotations; + + // Value of classRedefinedCount when we created this AnnotationData instance + final int redefinedCount; + + AnnotationData(Map, Annotation> annotations, + Map, Annotation> declaredAnnotations, + int redefinedCount) { + this.annotations = annotations; + this.declaredAnnotations = declaredAnnotations; + this.redefinedCount = redefinedCount; + } + } + + // Annotations cache + @SuppressWarnings("UnusedDeclaration") + private volatile transient AnnotationData annotationData; + + private AnnotationData annotationData() { + while (true) { // retry loop + AnnotationData annotationData = this.annotationData; + int classRedefinedCount = this.classRedefinedCount; + if (annotationData != null && + annotationData.redefinedCount == classRedefinedCount) { + return annotationData; + } + // null or stale annotationData -> optimistically create new instance + AnnotationData newAnnotationData = createAnnotationData(classRedefinedCount); + // try to install it + if (Atomic.casAnnotationData(this, annotationData, newAnnotationData)) { + // successfully installed new AnnotationData + return newAnnotationData; + } + } + } + + private AnnotationData createAnnotationData(int classRedefinedCount) { + Map, Annotation> declaredAnnotations = + getDeclaredAnnotationsImpl(); + Class superClass = getSuperclass(); + Map, Annotation> annotations = null; + if (superClass != null) { + Map, Annotation> superAnnotations = + superClass.annotationData().annotations; + for (Map.Entry, Annotation> e : superAnnotations.entrySet()) { + Class annotationClass = e.getKey(); + if (AnnotationType.getInstance(annotationClass).isInherited()) { + if (annotations == null) { // lazy construction + annotations = new LinkedHashMap<>((Math.max( + declaredAnnotations.size(), + Math.min(12, declaredAnnotations.size() + superAnnotations.size()) + ) * 4 + 2) / 3 + ); + } + annotations.put(annotationClass, e.getValue()); + } + } + } + if (annotations == null) { + // no inherited annotations -> share the Map with declaredAnnotations + annotations = declaredAnnotations; + } else { + // at least one inherited annotation -> declared may override inherited + annotations.putAll(declaredAnnotations); + } + return new AnnotationData(annotations, declaredAnnotations, classRedefinedCount); + } + + // Annotation types cache their internal (AnnotationType) form + + @SuppressWarnings("UnusedDeclaration") + private volatile transient AnnotationType annotationType; + + boolean casAnnotationType(AnnotationType oldType, AnnotationType newType) { + return Atomic.casAnnotationType(this, oldType, newType); + } + + AnnotationType getAnnotationType() { + return annotationType; + } + + Map, Annotation> getDeclaredAnnotationMap() { + return annotationData().declaredAnnotations; + } + + /* Backing store of user-defined values pertaining to this class. + * Maintained by the ClassValue class. + */ + transient ClassValue.ClassValueMap classValueMap; + + /** + * Returns an {@code AnnotatedType} object that represents the use of a + * type to specify the superclass of the entity represented by this {@code + * Class} object. (The use of type Foo to specify the superclass + * in '... extends Foo' is distinct from the declaration of type + * Foo.) + * + *

If this {@code Class} object represents a type whose declaration + * does not explicitly indicate an annotated superclass, then the return + * value is an {@code AnnotatedType} object representing an element with no + * annotations. + * + *

If this {@code Class} represents either the {@code Object} class, an + * interface type, an array type, a primitive type, or void, the return + * value is {@code null}. + * + * @return an object representing the superclass + * @since 1.8 + */ + public AnnotatedType getAnnotatedSuperclass() { + if (this == Object.class || + isInterface() || + isArray() || + isPrimitive() || + this == Void.TYPE) { + return null; + } + + return TypeAnnotationParser.buildAnnotatedSuperclass(getRawTypeAnnotations(), getConstantPool(), this); + } + + /** + * Returns an array of {@code AnnotatedType} objects that represent the use + * of types to specify superinterfaces of the entity represented by this + * {@code Class} object. (The use of type Foo to specify a + * superinterface in '... implements Foo' is distinct from the + * declaration of type Foo.) + * + *

If this {@code Class} object represents a class, the return value is + * an array containing objects representing the uses of interface types to + * specify interfaces implemented by the class. The order of the objects in + * the array corresponds to the order of the interface types used in the + * 'implements' clause of the declaration of this {@code Class} object. + * + *

If this {@code Class} object represents an interface, the return + * value is an array containing objects representing the uses of interface + * types to specify interfaces directly extended by the interface. The + * order of the objects in the array corresponds to the order of the + * interface types used in the 'extends' clause of the declaration of this + * {@code Class} object. + * + *

If this {@code Class} object represents a class or interface whose + * declaration does not explicitly indicate any annotated superinterfaces, + * the return value is an array of length 0. + * + *

If this {@code Class} object represents either the {@code Object} + * class, an array type, a primitive type, or void, the return value is an + * array of length 0. + * + * @return an array representing the superinterfaces + * @since 1.8 + */ + public AnnotatedType[] getAnnotatedInterfaces() { + return TypeAnnotationParser.buildAnnotatedInterfaces(getRawTypeAnnotations(), getConstantPool(), this); + } +} diff --git a/openjdk/java/lang/ClassLoader.java b/openjdk/java/lang/ClassLoader.java new file mode 100644 index 0000000..280a688 --- /dev/null +++ b/openjdk/java/lang/ClassLoader.java @@ -0,0 +1,2240 @@ +/* + * Copyright (c) 2013, 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 java.lang; + +import java.io.InputStream; +import java.io.IOException; +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.AccessController; +import java.security.AccessControlContext; +import java.security.CodeSource; +import java.security.Policy; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.security.ProtectionDomain; +import java.security.cert.Certificate; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; +import java.util.Stack; +import java.util.Map; +import java.util.Vector; +import java.util.Hashtable; +import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentHashMap; +import sun.misc.CompoundEnumeration; +import sun.misc.Resource; +import sun.misc.URLClassPath; +import sun.misc.VM; +import sun.reflect.CallerSensitive; +import sun.reflect.Reflection; +import sun.reflect.misc.ReflectUtil; +import sun.security.util.SecurityConstants; + +/** + * A class loader is an object that is responsible for loading classes. The + * class ClassLoader is an abstract class. Given the binary name of a class, a class loader should attempt to + * locate or generate data that constitutes a definition for the class. A + * typical strategy is to transform the name into a file name and then read a + * "class file" of that name from a file system. + * + *

Every {@link Class Class} object contains a {@link + * Class#getClassLoader() reference} to the ClassLoader that defined + * it. + * + *

Class objects for array classes are not created by class + * loaders, but are created automatically as required by the Java runtime. + * The class loader for an array class, as returned by {@link + * Class#getClassLoader()} is the same as the class loader for its element + * type; if the element type is a primitive type, then the array class has no + * class loader. + * + *

Applications implement subclasses of ClassLoader in order to + * extend the manner in which the Java virtual machine dynamically loads + * classes. + * + *

Class loaders may typically be used by security managers to indicate + * security domains. + * + *

The ClassLoader class uses a delegation model to search for + * classes and resources. Each instance of ClassLoader has an + * associated parent class loader. When requested to find a class or + * resource, a ClassLoader instance will delegate the search for the + * class or resource to its parent class loader before attempting to find the + * class or resource itself. The virtual machine's built-in class loader, + * called the "bootstrap class loader", does not itself have a parent but may + * serve as the parent of a ClassLoader instance. + * + *

Class loaders that support concurrent loading of classes are known as + * parallel capable class loaders and are required to register + * themselves at their class initialization time by invoking the + * {@link + * #registerAsParallelCapable ClassLoader.registerAsParallelCapable} + * method. Note that the ClassLoader class is registered as parallel + * capable by default. However, its subclasses still need to register themselves + * if they are parallel capable.
+ * In environments in which the delegation model is not strictly + * hierarchical, class loaders need to be parallel capable, otherwise class + * loading can lead to deadlocks because the loader lock is held for the + * duration of the class loading process (see {@link #loadClass + * loadClass} methods). + * + *

Normally, the Java virtual machine loads classes from the local file + * system in a platform-dependent manner. For example, on UNIX systems, the + * virtual machine loads classes from the directory defined by the + * CLASSPATH environment variable. + * + *

However, some classes may not originate from a file; they may originate + * from other sources, such as the network, or they could be constructed by an + * application. The method {@link #defineClass(String, byte[], int, int) + * defineClass} converts an array of bytes into an instance of class + * Class. Instances of this newly defined class can be created using + * {@link Class#newInstance Class.newInstance}. + * + *

The methods and constructors of objects created by a class loader may + * reference other classes. To determine the class(es) referred to, the Java + * virtual machine invokes the {@link #loadClass loadClass} method of + * the class loader that originally created the class. + * + *

For example, an application could create a network class loader to + * download class files from a server. Sample code might look like: + * + *

+ *   ClassLoader loader = new NetworkClassLoader(host, port);
+ *   Object main = loader.loadClass("Main", true).newInstance();
+ *        . . .
+ * 
+ * + *

The network class loader subclass must define the methods {@link + * #findClass findClass} and loadClassData to load a class + * from the network. Once it has downloaded the bytes that make up the class, + * it should use the method {@link #defineClass defineClass} to + * create a class instance. A sample implementation is: + * + *

+ *     class NetworkClassLoader extends ClassLoader {
+ *         String host;
+ *         int port;
+ *
+ *         public Class findClass(String name) {
+ *             byte[] b = loadClassData(name);
+ *             return defineClass(name, b, 0, b.length);
+ *         }
+ *
+ *         private byte[] loadClassData(String name) {
+ *             // load the class data from the connection
+ *              . . .
+ *         }
+ *     }
+ * 
+ * + *

Binary names

+ * + *

Any class name provided as a {@link String} parameter to methods in + * ClassLoader must be a binary name as defined by + * The Java™ Language Specification. + * + *

Examples of valid class names include: + *

+ *   "java.lang.String"
+ *   "javax.swing.JSpinner$DefaultEditor"
+ *   "java.security.KeyStore$Builder$FileBuilder$1"
+ *   "java.net.URLClassLoader$3$1"
+ * 
+ * + * @see #resolveClass(Class) + * @since 1.0 + */ +public abstract class ClassLoader { + + // If initialization succeed this is set to true and security checks will + // succeed. Otherwise the object is not initialized and the object is + // useless. + private final boolean initialized; + + // The parent class loader for delegation + // Note: VM hardcoded the offset of this field, thus all new fields + // must be added *after* it. + private final ClassLoader parent; + + /** + * Encapsulates the set of parallel capable loader types. + */ + private static class ParallelLoaders { + private ParallelLoaders() {} + + // the set of parallel capable loader types + private static final Set> loaderTypes = + Collections.newSetFromMap( + new WeakHashMap, Boolean>()); + static { + synchronized (loaderTypes) { loaderTypes.add(ClassLoader.class); } + } + + /** + * Registers the given class loader type as parallel capabale. + * Returns {@code true} is successfully registered; {@code false} if + * loader's super class is not registered. + */ + static boolean register(Class c) { + synchronized (loaderTypes) { + if (loaderTypes.contains(c.getSuperclass())) { + // register the class loader as parallel capable + // if and only if all of its super classes are. + // Note: given current classloading sequence, if + // the immediate super class is parallel capable, + // all the super classes higher up must be too. + loaderTypes.add(c); + return true; + } else { + return false; + } + } + } + + /** + * Returns {@code true} if the given class loader type is + * registered as parallel capable. + */ + static boolean isRegistered(Class c) { + synchronized (loaderTypes) { + return loaderTypes.contains(c); + } + } + } + + // Maps class name to the corresponding lock object when the current + // class loader is parallel capable. + // Note: VM also uses this field to decide if the current class loader + // is parallel capable and the appropriate lock object for class loading. + private final ConcurrentHashMap parallelLockMap; + + // Hashtable that maps packages to certs + private final Map package2certs; + + // Shared among all packages with unsigned classes + private static final Certificate[] nocerts = new Certificate[0]; + + // The classes loaded by this class loader. The only purpose of this table + // is to keep the classes from being GC'ed until the loader is GC'ed. + private final Vector> classes = new Vector<>(); + + // The "default" domain. Set as the default ProtectionDomain on newly + // created classes. + private final ProtectionDomain defaultDomain = + new ProtectionDomain(new CodeSource(null, (Certificate[]) null), + null, this, null); + + // The initiating protection domains for all classes loaded by this loader + private final Set domains; + + // Invoked by the VM to record every loaded class with this loader. + void addClass(Class c) { + classes.addElement(c); + } + + // The packages defined in this class loader. Each package name is mapped + // to its corresponding Package object. + // @GuardedBy("itself") + private final HashMap packages = new HashMap<>(); + + @ikvm.lang.Internal + public static final ClassLoader DUMMY = new ClassLoader(false) { }; + + ClassLoader(boolean ignored) + { + // [IKVM] This constructor is IKVM specific and only used to construct DUMMY. + // Note that this body is replaced in map.xml with an empty body as + // we don't want to execute any of the instance field initializers. + this((Void)null, (ClassLoader)null); + } + + private static Void checkCreateClassLoader() { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkCreateClassLoader(); + } + return null; + } + + // [IKVM] this normally private constructor is also used by ikvm.runtime.AssemblyClassLoader + // to construct an assembly class loader without doing a security check + @ikvm.lang.Internal + protected ClassLoader(Void unused, ClassLoader parent) { + if (parent != null) { + parent.check(); + } + this.parent = parent; + if (ParallelLoaders.isRegistered(this.getClass())) { + parallelLockMap = new ConcurrentHashMap<>(); + package2certs = new ConcurrentHashMap<>(); + domains = + Collections.synchronizedSet(new HashSet()); + assertionLock = new Object(); + } else { + // no finer-grained lock; lock on the classloader instance + parallelLockMap = null; + package2certs = new Hashtable<>(); + domains = new HashSet<>(); + assertionLock = this; + } + initialized = true; + } + + /** + * Creates a new class loader using the specified parent class loader for + * delegation. + * + *

If there is a security manager, its {@link + * SecurityManager#checkCreateClassLoader() + * checkCreateClassLoader} method is invoked. This may result in + * a security exception.

+ * + * @param parent + * The parent class loader + * + * @throws SecurityException + * If a security manager exists and its + * checkCreateClassLoader method doesn't allow creation + * of a new class loader. + * + * @since 1.2 + */ + protected ClassLoader(ClassLoader parent) { + this(checkCreateClassLoader(), parent); + } + + /** + * Creates a new class loader using the ClassLoader returned by + * the method {@link #getSystemClassLoader() + * getSystemClassLoader()} as the parent class loader. + * + *

If there is a security manager, its {@link + * SecurityManager#checkCreateClassLoader() + * checkCreateClassLoader} method is invoked. This may result in + * a security exception.

+ * + * @throws SecurityException + * If a security manager exists and its + * checkCreateClassLoader method doesn't allow creation + * of a new class loader. + */ + protected ClassLoader() { + this(checkCreateClassLoader(), getSystemClassLoader()); + } + + // -- Class -- + + /** + * Loads the class with the specified binary name. + * This method searches for classes in the same manner as the {@link + * #loadClass(String, boolean)} method. It is invoked by the Java virtual + * machine to resolve class references. Invoking this method is equivalent + * to invoking {@link #loadClass(String, boolean) loadClass(name, + * false)}. + * + * @param name + * The binary name of the class + * + * @return The resulting Class object + * + * @throws ClassNotFoundException + * If the class was not found + */ + public Class loadClass(String name) throws ClassNotFoundException { + return loadClass(name, false); + } + + /** + * Loads the class with the specified binary name. The + * default implementation of this method searches for classes in the + * following order: + * + *
    + * + *
  1. Invoke {@link #findLoadedClass(String)} to check if the class + * has already been loaded.

  2. + * + *
  3. Invoke the {@link #loadClass(String) loadClass} method + * on the parent class loader. If the parent is null the class + * loader built-in to the virtual machine is used, instead.

  4. + * + *
  5. Invoke the {@link #findClass(String)} method to find the + * class.

  6. + * + *
+ * + *

If the class was found using the above steps, and the + * resolve flag is true, this method will then invoke the {@link + * #resolveClass(Class)} method on the resulting Class object. + * + *

Subclasses of ClassLoader are encouraged to override {@link + * #findClass(String)}, rather than this method.

+ * + *

Unless overridden, this method synchronizes on the result of + * {@link #getClassLoadingLock getClassLoadingLock} method + * during the entire class loading process. + * + * @param name + * The binary name of the class + * + * @param resolve + * If true then resolve the class + * + * @return The resulting Class object + * + * @throws ClassNotFoundException + * If the class could not be found + */ + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException + { + synchronized (getClassLoadingLock(name)) { + // First, check if the class has already been loaded + Class c = findLoadedClass(name); + if (c == null) { + try { + if (parent != null) { + c = parent.loadClass(name, false); + } else { + c = findBootstrapClassOrNull(name); + } + } catch (ClassNotFoundException e) { + // ClassNotFoundException thrown if class not found + // from the non-null parent class loader + } + + if (c == null) { + // If still not found, then invoke findClass in order + // to find the class. + c = findClass(name); + } + } + if (resolve) { + resolveClass(c); + } + return c; + } + } + + /** + * Returns the lock object for class loading operations. + * For backward compatibility, the default implementation of this method + * behaves as follows. If this ClassLoader object is registered as + * parallel capable, the method returns a dedicated object associated + * with the specified class name. Otherwise, the method returns this + * ClassLoader object. + * + * @param className + * The name of the to-be-loaded class + * + * @return the lock for class loading operations + * + * @throws NullPointerException + * If registered as parallel capable and className is null + * + * @see #loadClass(String, boolean) + * + * @since 1.7 + */ + protected Object getClassLoadingLock(String className) { + Object lock = this; + if (parallelLockMap != null) { + Object newLock = new Object(); + lock = parallelLockMap.putIfAbsent(className, newLock); + if (lock == null) { + lock = newLock; + } + } + return lock; + } + + // This method is invoked by the virtual machine to load a class. + final Class loadClassInternal(String name) + throws ClassNotFoundException + { + // For backward compatibility, explicitly lock on 'this' when + // the current class loader is not parallel capable. + if (parallelLockMap == null) { + synchronized (this) { + return loadClass(name); + } + } else { + return loadClass(name); + } + } + + // Invoked by the VM after loading class with this loader. + final void checkPackageAccess(Class cls, ProtectionDomain pd) { + final SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + if (ReflectUtil.isNonPublicProxyClass(cls)) { + for (Class intf: cls.getInterfaces()) { + checkPackageAccess(intf, pd); + } + return; + } + + final String name = cls.getName(); + final int i = name.lastIndexOf('.'); + if (i != -1) { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + sm.checkPackageAccess(name.substring(0, i)); + return null; + } + }, new AccessControlContext(new ProtectionDomain[] {pd})); + } + } + domains.add(pd); + } + + /** + * Finds the class with the specified binary name. + * This method should be overridden by class loader implementations that + * follow the delegation model for loading classes, and will be invoked by + * the {@link #loadClass loadClass} method after checking the + * parent class loader for the requested class. The default implementation + * throws a ClassNotFoundException. + * + * @param name + * The binary name of the class + * + * @return The resulting Class object + * + * @throws ClassNotFoundException + * If the class could not be found + * + * @since 1.2 + */ + protected Class findClass(String name) throws ClassNotFoundException { + throw new ClassNotFoundException(name); + } + + /** + * Converts an array of bytes into an instance of class Class. + * Before the Class can be used it must be resolved. This method + * is deprecated in favor of the version that takes a binary name as its first argument, and is more secure. + * + * @param b + * The bytes that make up the class data. The bytes in positions + * off through off+len-1 should have the format + * of a valid class file as defined by + * The Java™ Virtual Machine Specification. + * + * @param off + * The start offset in b of the class data + * + * @param len + * The length of the class data + * + * @return The Class object that was created from the specified + * class data + * + * @throws ClassFormatError + * If the data did not contain a valid class + * + * @throws IndexOutOfBoundsException + * If either off or len is negative, or if + * off+len is greater than b.length. + * + * @throws SecurityException + * If an attempt is made to add this class to a package that + * contains classes that were signed by a different set of + * certificates than this class, or if an attempt is made + * to define a class in a package with a fully-qualified name + * that starts with "{@code java.}". + * + * @see #loadClass(String, boolean) + * @see #resolveClass(Class) + * + * @deprecated Replaced by {@link #defineClass(String, byte[], int, int) + * defineClass(String, byte[], int, int)} + */ + @Deprecated + protected final Class defineClass(byte[] b, int off, int len) + throws ClassFormatError + { + return defineClass(null, b, off, len, null); + } + + /** + * Converts an array of bytes into an instance of class Class. + * Before the Class can be used it must be resolved. + * + *

This method assigns a default {@link java.security.ProtectionDomain + * ProtectionDomain} to the newly defined class. The + * ProtectionDomain is effectively granted the same set of + * permissions returned when {@link + * java.security.Policy#getPermissions(java.security.CodeSource) + * Policy.getPolicy().getPermissions(new CodeSource(null, null))} + * is invoked. The default domain is created on the first invocation of + * {@link #defineClass(String, byte[], int, int) defineClass}, + * and re-used on subsequent invocations. + * + *

To assign a specific ProtectionDomain to the class, use + * the {@link #defineClass(String, byte[], int, int, + * java.security.ProtectionDomain) defineClass} method that takes a + * ProtectionDomain as one of its arguments.

+ * + * @param name + * The expected binary name of the class, or + * null if not known + * + * @param b + * The bytes that make up the class data. The bytes in positions + * off through off+len-1 should have the format + * of a valid class file as defined by + * The Java™ Virtual Machine Specification. + * + * @param off + * The start offset in b of the class data + * + * @param len + * The length of the class data + * + * @return The Class object that was created from the specified + * class data. + * + * @throws ClassFormatError + * If the data did not contain a valid class + * + * @throws IndexOutOfBoundsException + * If either off or len is negative, or if + * off+len is greater than b.length. + * + * @throws SecurityException + * If an attempt is made to add this class to a package that + * contains classes that were signed by a different set of + * certificates than this class (which is unsigned), or if + * name begins with "java.". + * + * @see #loadClass(String, boolean) + * @see #resolveClass(Class) + * @see java.security.CodeSource + * @see java.security.SecureClassLoader + * + * @since 1.1 + */ + protected final Class defineClass(String name, byte[] b, int off, int len) + throws ClassFormatError + { + return defineClass(name, b, off, len, null); + } + + /* Determine protection domain, and check that: + - not define java.* class, + - signer of this class matches signers for the rest of the classes in + package. + */ + private ProtectionDomain preDefineClass(String name, + ProtectionDomain pd) + { + if (!checkName(name)) + throw new NoClassDefFoundError("IllegalName: " + name); + + if ((name != null) && name.startsWith("java.")) { + throw new SecurityException + ("Prohibited package name: " + + name.substring(0, name.lastIndexOf('.'))); + } + if (pd == null) { + pd = defaultDomain; + } + + if (name != null) checkCerts(name, pd.getCodeSource()); + + return pd; + } + + private String defineClassSourceLocation(ProtectionDomain pd) + { + CodeSource cs = pd.getCodeSource(); + String source = null; + if (cs != null && cs.getLocation() != null) { + source = cs.getLocation().toString(); + } + return source; + } + + private void postDefineClass(Class c, ProtectionDomain pd) + { + if (pd.getCodeSource() != null) { + Certificate certs[] = pd.getCodeSource().getCertificates(); + if (certs != null) + setSigners(c, certs); + } + } + + /** + * Converts an array of bytes into an instance of class Class, + * with an optional ProtectionDomain. If the domain is + * null, then a default domain will be assigned to the class as + * specified in the documentation for {@link #defineClass(String, byte[], + * int, int)}. Before the class can be used it must be resolved. + * + *

The first class defined in a package determines the exact set of + * certificates that all subsequent classes defined in that package must + * contain. The set of certificates for a class is obtained from the + * {@link java.security.CodeSource CodeSource} within the + * ProtectionDomain of the class. Any classes added to that + * package must contain the same set of certificates or a + * SecurityException will be thrown. Note that if + * name is null, this check is not performed. + * You should always pass in the binary name of the + * class you are defining as well as the bytes. This ensures that the + * class you are defining is indeed the class you think it is. + * + *

The specified name cannot begin with "java.", since + * all classes in the "java.* packages can only be defined by the + * bootstrap class loader. If name is not null, it + * must be equal to the binary name of the class + * specified by the byte array "b", otherwise a {@link + * NoClassDefFoundError NoClassDefFoundError} will be thrown.

+ * + * @param name + * The expected binary name of the class, or + * null if not known + * + * @param b + * The bytes that make up the class data. The bytes in positions + * off through off+len-1 should have the format + * of a valid class file as defined by + * The Java™ Virtual Machine Specification. + * + * @param off + * The start offset in b of the class data + * + * @param len + * The length of the class data + * + * @param protectionDomain + * The ProtectionDomain of the class + * + * @return The Class object created from the data, + * and optional ProtectionDomain. + * + * @throws ClassFormatError + * If the data did not contain a valid class + * + * @throws NoClassDefFoundError + * If name is not equal to the binary + * name of the class specified by b + * + * @throws IndexOutOfBoundsException + * If either off or len is negative, or if + * off+len is greater than b.length. + * + * @throws SecurityException + * If an attempt is made to add this class to a package that + * contains classes that were signed by a different set of + * certificates than this class, or if name begins with + * "java.". + */ + protected final Class defineClass(String name, byte[] b, int off, int len, + ProtectionDomain protectionDomain) + throws ClassFormatError + { + check(); + protectionDomain = preDefineClass(name, protectionDomain); + String source = defineClassSourceLocation(protectionDomain); + Class c = defineClass1(name, b, off, len, protectionDomain, source); + postDefineClass(c, protectionDomain); + return c; + } + + /** + * Converts a {@link java.nio.ByteBuffer ByteBuffer} + * into an instance of class Class, + * with an optional ProtectionDomain. If the domain is + * null, then a default domain will be assigned to the class as + * specified in the documentation for {@link #defineClass(String, byte[], + * int, int)}. Before the class can be used it must be resolved. + * + *

The rules about the first class defined in a package determining the + * set of certificates for the package, and the restrictions on class names + * are identical to those specified in the documentation for {@link + * #defineClass(String, byte[], int, int, ProtectionDomain)}. + * + *

An invocation of this method of the form + * cl.defineClass(name, + * bBuffer, pd) yields exactly the same + * result as the statements + * + *

+ * ...
+ * byte[] temp = new byte[bBuffer.{@link + * java.nio.ByteBuffer#remaining remaining}()];
+ * bBuffer.{@link java.nio.ByteBuffer#get(byte[]) + * get}(temp);
+ * return {@link #defineClass(String, byte[], int, int, ProtectionDomain) + * cl.defineClass}(name, temp, 0, + * temp.length, pd);
+ *

+ * + * @param name + * The expected binary name. of the class, or + * null if not known + * + * @param b + * The bytes that make up the class data. The bytes from positions + * b.position() through b.position() + b.limit() -1 + * should have the format of a valid class file as defined by + * The Java™ Virtual Machine Specification. + * + * @param protectionDomain + * The ProtectionDomain of the class, or null. + * + * @return The Class object created from the data, + * and optional ProtectionDomain. + * + * @throws ClassFormatError + * If the data did not contain a valid class. + * + * @throws NoClassDefFoundError + * If name is not equal to the binary + * name of the class specified by b + * + * @throws SecurityException + * If an attempt is made to add this class to a package that + * contains classes that were signed by a different set of + * certificates than this class, or if name begins with + * "java.". + * + * @see #defineClass(String, byte[], int, int, ProtectionDomain) + * + * @since 1.5 + */ + protected final Class defineClass(String name, java.nio.ByteBuffer b, + ProtectionDomain protectionDomain) + throws ClassFormatError + { + check(); + + int len = b.remaining(); + + // Use byte[] if not a direct ByteBufer: + if (!b.isDirect()) { + if (b.hasArray()) { + return defineClass(name, b.array(), + b.position() + b.arrayOffset(), len, + protectionDomain); + } else { + // no array, or read-only array + byte[] tb = new byte[len]; + b.get(tb); // get bytes out of byte buffer. + return defineClass(name, tb, 0, len, protectionDomain); + } + } + + protectionDomain = preDefineClass(name, protectionDomain); + String source = defineClassSourceLocation(protectionDomain); + Class c = defineClass2(name, b, b.position(), len, protectionDomain, source); + postDefineClass(c, protectionDomain); + return c; + } + + private native Class defineClass0(String name, byte[] b, int off, int len, + ProtectionDomain pd); + + private native Class defineClass1(String name, byte[] b, int off, int len, + ProtectionDomain pd, String source); + + private native Class defineClass2(String name, java.nio.ByteBuffer b, + int off, int len, ProtectionDomain pd, + String source); + + // true if the name is null or has the potential to be a valid binary name + static boolean checkName(String name) { + if ((name == null) || (name.length() == 0)) + return true; + if ((name.indexOf('/') != -1) + || (!VM.allowArraySyntax() && (name.charAt(0) == '['))) + return false; + return true; + } + + private void checkCerts(String name, CodeSource cs) { + int i = name.lastIndexOf('.'); + String pname = (i == -1) ? "" : name.substring(0, i); + + Certificate[] certs = null; + if (cs != null) { + certs = cs.getCertificates(); + } + Certificate[] pcerts = null; + if (parallelLockMap == null) { + synchronized (this) { + pcerts = package2certs.get(pname); + if (pcerts == null) { + package2certs.put(pname, (certs == null? nocerts:certs)); + } + } + } else { + pcerts = ((ConcurrentHashMap)package2certs). + putIfAbsent(pname, (certs == null? nocerts:certs)); + } + if (pcerts != null && !compareCerts(pcerts, certs)) { + throw new SecurityException("class \""+ name + + "\"'s signer information does not match signer information of other classes in the same package"); + } + } + + /** + * check to make sure the certs for the new class (certs) are the same as + * the certs for the first class inserted in the package (pcerts) + */ + private boolean compareCerts(Certificate[] pcerts, + Certificate[] certs) + { + // certs can be null, indicating no certs. + if ((certs == null) || (certs.length == 0)) { + return pcerts.length == 0; + } + + // the length must be the same at this point + if (certs.length != pcerts.length) + return false; + + // go through and make sure all the certs in one array + // are in the other and vice-versa. + boolean match; + for (int i = 0; i < certs.length; i++) { + match = false; + for (int j = 0; j < pcerts.length; j++) { + if (certs[i].equals(pcerts[j])) { + match = true; + break; + } + } + if (!match) return false; + } + + // now do the same for pcerts + for (int i = 0; i < pcerts.length; i++) { + match = false; + for (int j = 0; j < certs.length; j++) { + if (pcerts[i].equals(certs[j])) { + match = true; + break; + } + } + if (!match) return false; + } + + return true; + } + + /** + * Links the specified class. This (misleadingly named) method may be + * used by a class loader to link a class. If the class c has + * already been linked, then this method simply returns. Otherwise, the + * class is linked as described in the "Execution" chapter of + * The Java™ Language Specification. + * + * @param c + * The class to link + * + * @throws NullPointerException + * If c is null. + * + * @see #defineClass(String, byte[], int, int) + */ + protected final void resolveClass(Class c) { + check(); + resolveClass0(c); + } + + private native void resolveClass0(Class c); + + /** + * Finds a class with the specified binary name, + * loading it if necessary. + * + *

This method loads the class through the system class loader (see + * {@link #getSystemClassLoader()}). The Class object returned + * might have more than one ClassLoader associated with it. + * Subclasses of ClassLoader need not usually invoke this method, + * because most class loaders need to override just {@link + * #findClass(String)}.

+ * + * @param name + * The binary name of the class + * + * @return The Class object for the specified name + * + * @throws ClassNotFoundException + * If the class could not be found + * + * @see #ClassLoader(ClassLoader) + * @see #getParent() + */ + protected final Class findSystemClass(String name) + throws ClassNotFoundException + { + check(); + ClassLoader system = getSystemClassLoader(); + if (system == null) { + if (!checkName(name)) + throw new ClassNotFoundException(name); + Class cls = findBootstrapClass(name); + if (cls == null) { + throw new ClassNotFoundException(name); + } + return cls; + } + return system.loadClass(name); + } + + /** + * Returns a class loaded by the bootstrap class loader; + * or return null if not found. + */ + private Class findBootstrapClassOrNull(String name) + { + check(); + if (!checkName(name)) return null; + + return findBootstrapClass(name); + } + + // return null if not found + private native Class findBootstrapClass(String name); + + // Check to make sure the class loader has been initialized. + private void check() { + if (!initialized) { + throw new SecurityException("ClassLoader object not initialized"); + } + } + + /** + * Returns the class with the given binary name if this + * loader has been recorded by the Java virtual machine as an initiating + * loader of a class with that binary name. Otherwise + * null is returned. + * + * @param name + * The binary name of the class + * + * @return The Class object, or null if the class has + * not been loaded + * + * @since 1.1 + */ + protected final Class findLoadedClass(String name) { + check(); + if (!checkName(name)) + return null; + return findLoadedClass0(name); + } + + private native final Class findLoadedClass0(String name); + + /** + * Sets the signers of a class. This should be invoked after defining a + * class. + * + * @param c + * The Class object + * + * @param signers + * The signers for the class + * + * @since 1.1 + */ + protected final void setSigners(Class c, Object[] signers) { + check(); + c.setSigners(signers); + } + + + // -- Resource -- + + /** + * Finds the resource with the given name. A resource is some data + * (images, audio, text, etc) that can be accessed by class code in a way + * that is independent of the location of the code. + * + *

The name of a resource is a '/'-separated path name that + * identifies the resource. + * + *

This method will first search the parent class loader for the + * resource; if the parent is null the path of the class loader + * built-in to the virtual machine is searched. That failing, this method + * will invoke {@link #findResource(String)} to find the resource.

+ * + * @apiNote When overriding this method it is recommended that an + * implementation ensures that any delegation is consistent with the {@link + * #getResources(java.lang.String) getResources(String)} method. + * + * @param name + * The resource name + * + * @return A URL object for reading the resource, or + * null if the resource could not be found or the invoker + * doesn't have adequate privileges to get the resource. + * + * @since 1.1 + */ + public URL getResource(String name) { + URL url; + if (parent != null) { + url = parent.getResource(name); + } else { + url = getBootstrapResource(name); + } + if (url == null) { + url = findResource(name); + } + return url; + } + + /** + * Finds all the resources with the given name. A resource is some data + * (images, audio, text, etc) that can be accessed by class code in a way + * that is independent of the location of the code. + * + *

The name of a resource is a /-separated path name that + * identifies the resource. + * + *

The search order is described in the documentation for {@link + * #getResource(String)}.

+ * + * @apiNote When overriding this method it is recommended that an + * implementation ensures that any delegation is consistent with the {@link + * #getResource(java.lang.String) getResource(String)} method. This should + * ensure that the first element returned by the Enumeration's + * {@code nextElement} method is the same resource that the + * {@code getResource(String)} method would return. + * + * @param name + * The resource name + * + * @return An enumeration of {@link java.net.URL URL} objects for + * the resource. If no resources could be found, the enumeration + * will be empty. Resources that the class loader doesn't have + * access to will not be in the enumeration. + * + * @throws IOException + * If I/O errors occur + * + * @see #findResources(String) + * + * @since 1.2 + */ + public Enumeration getResources(String name) throws IOException { + @SuppressWarnings("unchecked") + Enumeration[] tmp = (Enumeration[]) new Enumeration[2]; + if (parent != null) { + tmp[0] = parent.getResources(name); + } else { + tmp[0] = getBootstrapResources(name); + } + tmp[1] = findResources(name); + + return new CompoundEnumeration<>(tmp); + } + + /** + * Finds the resource with the given name. Class loader implementations + * should override this method to specify where to find resources. + * + * @param name + * The resource name + * + * @return A URL object for reading the resource, or + * null if the resource could not be found + * + * @since 1.2 + */ + protected URL findResource(String name) { + return null; + } + + /** + * Returns an enumeration of {@link java.net.URL URL} objects + * representing all the resources with the given name. Class loader + * implementations should override this method to specify where to load + * resources from. + * + * @param name + * The resource name + * + * @return An enumeration of {@link java.net.URL URL} objects for + * the resources + * + * @throws IOException + * If I/O errors occur + * + * @since 1.2 + */ + protected Enumeration findResources(String name) throws IOException { + return java.util.Collections.emptyEnumeration(); + } + + /** + * Registers the caller as parallel capable. + * The registration succeeds if and only if all of the following + * conditions are met: + *
    + *
  1. no instance of the caller has been created
  2. + *
  3. all of the super classes (except class Object) of the caller are + * registered as parallel capable
  4. + *
+ *

Note that once a class loader is registered as parallel capable, there + * is no way to change it back.

+ * + * @return true if the caller is successfully registered as + * parallel capable and false if otherwise. + * + * @since 1.7 + */ + @CallerSensitive + protected static boolean registerAsParallelCapable() { + Class callerClass = + Reflection.getCallerClass().asSubclass(ClassLoader.class); + return ParallelLoaders.register(callerClass); + } + + /** + * Find a resource of the specified name from the search path used to load + * classes. This method locates the resource through the system class + * loader (see {@link #getSystemClassLoader()}). + * + * @param name + * The resource name + * + * @return A {@link java.net.URL URL} object for reading the + * resource, or null if the resource could not be found + * + * @since 1.1 + */ + public static URL getSystemResource(String name) { + ClassLoader system = getSystemClassLoader(); + if (system == null) { + return getBootstrapResource(name); + } + return system.getResource(name); + } + + /** + * Finds all resources of the specified name from the search path used to + * load classes. The resources thus found are returned as an + * {@link java.util.Enumeration Enumeration} of {@link + * java.net.URL URL} objects. + * + *

The search order is described in the documentation for {@link + * #getSystemResource(String)}.

+ * + * @param name + * The resource name + * + * @return An enumeration of resource {@link java.net.URL URL} + * objects + * + * @throws IOException + * If I/O errors occur + + * @since 1.2 + */ + public static Enumeration getSystemResources(String name) + throws IOException + { + ClassLoader system = getSystemClassLoader(); + if (system == null) { + return getBootstrapResources(name); + } + return system.getResources(name); + } + + /** + * Find resources from the VM's built-in classloader. + */ + private static native URL getBootstrapResource(String name); + + /** + * Find resources from the VM's built-in classloader. + */ + private static native Enumeration getBootstrapResources(String name) + throws IOException; + + // Returns the URLClassPath that is used for finding system resources. + static URLClassPath getBootstrapClassPath() { + return sun.misc.Launcher.getBootstrapClassPath(); + } + + + /** + * Returns an input stream for reading the specified resource. + * + *

The search order is described in the documentation for {@link + * #getResource(String)}.

+ * + * @param name + * The resource name + * + * @return An input stream for reading the resource, or null + * if the resource could not be found + * + * @since 1.1 + */ + public InputStream getResourceAsStream(String name) { + URL url = getResource(name); + try { + return url != null ? url.openStream() : null; + } catch (IOException e) { + return null; + } + } + + /** + * Open for reading, a resource of the specified name from the search path + * used to load classes. This method locates the resource through the + * system class loader (see {@link #getSystemClassLoader()}). + * + * @param name + * The resource name + * + * @return An input stream for reading the resource, or null + * if the resource could not be found + * + * @since 1.1 + */ + public static InputStream getSystemResourceAsStream(String name) { + URL url = getSystemResource(name); + try { + return url != null ? url.openStream() : null; + } catch (IOException e) { + return null; + } + } + + + // -- Hierarchy -- + + /** + * Returns the parent class loader for delegation. Some implementations may + * use null to represent the bootstrap class loader. This method + * will return null in such implementations if this class loader's + * parent is the bootstrap class loader. + * + *

If a security manager is present, and the invoker's class loader is + * not null and is not an ancestor of this class loader, then this + * method invokes the security manager's {@link + * SecurityManager#checkPermission(java.security.Permission) + * checkPermission} method with a {@link + * RuntimePermission#RuntimePermission(String) + * RuntimePermission("getClassLoader")} permission to verify + * access to the parent class loader is permitted. If not, a + * SecurityException will be thrown.

+ * + * @return The parent ClassLoader + * + * @throws SecurityException + * If a security manager exists and its checkPermission + * method doesn't allow access to this class loader's parent class + * loader. + * + * @since 1.2 + */ + @CallerSensitive + public final ClassLoader getParent() { + if (parent == null) + return null; + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + // Check access to the parent class loader + // If the caller's class loader is same as this class loader, + // permission check is performed. + checkClassLoaderPermission(parent, Reflection.getCallerClass()); + } + return parent; + } + + /** + * Returns the system class loader for delegation. This is the default + * delegation parent for new ClassLoader instances, and is + * typically the class loader used to start the application. + * + *

This method is first invoked early in the runtime's startup + * sequence, at which point it creates the system class loader and sets it + * as the context class loader of the invoking Thread. + * + *

The default system class loader is an implementation-dependent + * instance of this class. + * + *

If the system property "java.system.class.loader" is defined + * when this method is first invoked then the value of that property is + * taken to be the name of a class that will be returned as the system + * class loader. The class is loaded using the default system class loader + * and must define a public constructor that takes a single parameter of + * type ClassLoader which is used as the delegation parent. An + * instance is then created using this constructor with the default system + * class loader as the parameter. The resulting class loader is defined + * to be the system class loader. + * + *

If a security manager is present, and the invoker's class loader is + * not null and the invoker's class loader is not the same as or + * an ancestor of the system class loader, then this method invokes the + * security manager's {@link + * SecurityManager#checkPermission(java.security.Permission) + * checkPermission} method with a {@link + * RuntimePermission#RuntimePermission(String) + * RuntimePermission("getClassLoader")} permission to verify + * access to the system class loader. If not, a + * SecurityException will be thrown.

+ * + * @return The system ClassLoader for delegation, or + * null if none + * + * @throws SecurityException + * If a security manager exists and its checkPermission + * method doesn't allow access to the system class loader. + * + * @throws IllegalStateException + * If invoked recursively during the construction of the class + * loader specified by the "java.system.class.loader" + * property. + * + * @throws Error + * If the system property "java.system.class.loader" + * is defined but the named class could not be loaded, the + * provider class does not define the required constructor, or an + * exception is thrown by that constructor when it is invoked. The + * underlying cause of the error can be retrieved via the + * {@link Throwable#getCause()} method. + * + * @revised 1.4 + */ + @CallerSensitive + public static ClassLoader getSystemClassLoader() { + initSystemClassLoader(); + if (scl == null) { + return null; + } + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + checkClassLoaderPermission(scl, Reflection.getCallerClass()); + } + return scl; + } + + private static synchronized void initSystemClassLoader() { + if (!sclSet) { + if (scl != null) + throw new IllegalStateException("recursive invocation"); + sun.misc.Launcher l = sun.misc.Launcher.getLauncher(); + if (l != null) { + Throwable oops = null; + scl = l.getClassLoader(); + try { + scl = AccessController.doPrivileged( + new SystemClassLoaderAction(scl)); + } catch (PrivilegedActionException pae) { + oops = pae.getCause(); + if (oops instanceof InvocationTargetException) { + oops = oops.getCause(); + } + } + if (oops != null) { + if (oops instanceof Error) { + throw (Error) oops; + } else { + // wrap the exception + throw new Error(oops); + } + } + } + sclSet = true; + } + } + + // Returns true if the specified class loader can be found in this class + // loader's delegation chain. + boolean isAncestor(ClassLoader cl) { + ClassLoader acl = this; + do { + acl = acl.parent; + if (cl == acl) { + return true; + } + } while (acl != null); + return false; + } + + // Tests if class loader access requires "getClassLoader" permission + // check. A class loader 'from' can access class loader 'to' if + // class loader 'from' is same as class loader 'to' or an ancestor + // of 'to'. The class loader in a system domain can access + // any class loader. + private static boolean needsClassLoaderPermissionCheck(ClassLoader from, + ClassLoader to) + { + if (from == to) + return false; + + if (from == null) + return false; + + return !to.isAncestor(from); + } + + // Returns the class's class loader, or null if none. + static ClassLoader getClassLoader(Class caller) { + // This can be null if the VM is requesting it + if (caller == null) { + return null; + } + // Circumvent security check since this is package-private + return caller.getClassLoader0(); + } + + /* + * Checks RuntimePermission("getClassLoader") permission + * if caller's class loader is not null and caller's class loader + * is not the same as or an ancestor of the given cl argument. + */ + static void checkClassLoaderPermission(ClassLoader cl, Class caller) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + // caller can be null if the VM is requesting it + ClassLoader ccl = getClassLoader(caller); + if (needsClassLoaderPermissionCheck(ccl, cl)) { + sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); + } + } + } + + // The class loader for the system + // @GuardedBy("ClassLoader.class") + private static ClassLoader scl; + + // Set to true once the system class loader has been set + // @GuardedBy("ClassLoader.class") + private static boolean sclSet; + + + // -- Package -- + + /** + * Defines a package by name in this ClassLoader. This allows + * class loaders to define the packages for their classes. Packages must + * be created before the class is defined, and package names must be + * unique within a class loader and cannot be redefined or changed once + * created. + * + * @param name + * The package name + * + * @param specTitle + * The specification title + * + * @param specVersion + * The specification version + * + * @param specVendor + * The specification vendor + * + * @param implTitle + * The implementation title + * + * @param implVersion + * The implementation version + * + * @param implVendor + * The implementation vendor + * + * @param sealBase + * If not null, then this package is sealed with + * respect to the given code source {@link java.net.URL + * URL} object. Otherwise, the package is not sealed. + * + * @return The newly defined Package object + * + * @throws IllegalArgumentException + * If package name duplicates an existing package either in this + * class loader or one of its ancestors + * + * @since 1.2 + */ + protected Package definePackage(String name, String specTitle, + String specVersion, String specVendor, + String implTitle, String implVersion, + String implVendor, URL sealBase) + throws IllegalArgumentException + { + synchronized (packages) { + Package pkg = getPackage(name); + if (pkg != null) { + throw new IllegalArgumentException(name); + } + pkg = new Package(name, specTitle, specVersion, specVendor, + implTitle, implVersion, implVendor, + sealBase, this); + packages.put(name, pkg); + return pkg; + } + } + + /** + * Returns a Package that has been defined by this class loader + * or any of its ancestors. + * + * @param name + * The package name + * + * @return The Package corresponding to the given name, or + * null if not found + * + * @since 1.2 + */ + protected Package getPackage(String name) { + Package pkg; + synchronized (packages) { + pkg = packages.get(name); + } + if (pkg == null) { + if (parent != null) { + pkg = parent.getPackage(name); + } else { + pkg = Package.getSystemPackage(name); + } + if (pkg != null) { + synchronized (packages) { + Package pkg2 = packages.get(name); + if (pkg2 == null) { + packages.put(name, pkg); + } else { + pkg = pkg2; + } + } + } + } + return pkg; + } + + /** + * Returns all of the Packages defined by this class loader and + * its ancestors. + * + * @return The array of Package objects defined by this + * ClassLoader + * + * @since 1.2 + */ + protected Package[] getPackages() { + Map map; + synchronized (packages) { + map = new HashMap<>(packages); + } + Package[] pkgs; + if (parent != null) { + pkgs = parent.getPackages(); + } else { + pkgs = Package.getSystemPackages(); + } + if (pkgs != null) { + for (int i = 0; i < pkgs.length; i++) { + String pkgName = pkgs[i].getName(); + if (map.get(pkgName) == null) { + map.put(pkgName, pkgs[i]); + } + } + } + return map.values().toArray(new Package[map.size()]); + } + + + // -- Native library access -- + + /** + * Returns the absolute path name of a native library. The VM invokes this + * method to locate the native libraries that belong to classes loaded with + * this class loader. If this method returns null, the VM + * searches the library along the path specified as the + * "java.library.path" property. + * + * @param libname + * The library name + * + * @return The absolute path of the native library + * + * @see System#loadLibrary(String) + * @see System#mapLibraryName(String) + * + * @since 1.2 + */ + protected String findLibrary(String libname) { + return null; + } + + /** + * The inner class NativeLibrary denotes a loaded native library instance. + * Every classloader contains a vector of loaded native libraries in the + * private field nativeLibraries. The native libraries loaded + * into the system are entered into the systemNativeLibraries + * vector. + * + *

Every native library requires a particular version of JNI. This is + * denoted by the private jniVersion field. This field is set by + * the VM when it loads the library, and used by the VM to pass the correct + * version of JNI to the native methods.

+ * + * @see ClassLoader + * @since 1.2 + */ + static class NativeLibrary { + // opaque handle to native library, used in native code. + long handle; + // the version of JNI environment the native library requires. + private int jniVersion; + // the class from which the library is loaded, also indicates + // the loader this native library belongs. + private final Class fromClass; + // the canonicalized name of the native library. + // or static library name + String name; + // Indicates if the native library is linked into the VM + boolean isBuiltin; + // Indicates if the native library is loaded + boolean loaded; + native void load(String name, boolean isBuiltin); + + native long find(String name); + native void unload(String name, boolean isBuiltin); + static native String findBuiltinLib(String name); + + public NativeLibrary(Class fromClass, String name, boolean isBuiltin) { + this.name = name; + this.fromClass = fromClass; + this.isBuiltin = isBuiltin; + } + + protected void finalize() { + synchronized (loadedLibraryNames) { + if (fromClass.getClassLoader() != null && loaded) { + /* remove the native library name */ + int size = loadedLibraryNames.size(); + for (int i = 0; i < size; i++) { + if (name.equals(loadedLibraryNames.elementAt(i))) { + loadedLibraryNames.removeElementAt(i); + break; + } + } + /* unload the library. */ + ClassLoader.nativeLibraryContext.push(this); + try { + unload(name, isBuiltin); + } finally { + ClassLoader.nativeLibraryContext.pop(); + } + } + } + } + // Invoked in the VM to determine the context class in + // JNI_Load/JNI_Unload + static Class getFromClass() { + return ClassLoader.nativeLibraryContext.peek().fromClass; + } + } + + // All native library names we've loaded. + private static Vector loadedLibraryNames = new Vector<>(); + + // Native libraries belonging to system classes. + private static Vector systemNativeLibraries + = new Vector<>(); + + // Native libraries associated with the class loader. + private Vector nativeLibraries = new Vector<>(); + + // native libraries being loaded/unloaded. + private static Stack nativeLibraryContext = new Stack<>(); + + // The paths searched for libraries + private static String usr_paths[]; + private static String sys_paths[]; + + private static String[] initializePath(String ldpath) { + String ps = File.pathSeparator; + int ldlen = ldpath.length(); + int i, j, n; + // Count the separators in the path + i = ldpath.indexOf(ps); + n = 0; + while (i >= 0) { + n++; + i = ldpath.indexOf(ps, i + 1); + } + + // allocate the array of paths - n :'s = n + 1 path elements + String[] paths = new String[n + 1]; + + // Fill the array with paths from the ldpath + n = i = 0; + j = ldpath.indexOf(ps); + while (j >= 0) { + if (j - i > 0) { + paths[n++] = ldpath.substring(i, j); + } else if (j - i == 0) { + paths[n++] = "."; + } + i = j + 1; + j = ldpath.indexOf(ps, i); + } + paths[n] = ldpath.substring(i, ldlen); + return paths; + } + + private static String java_library_path; + private static String sun_boot_library_path; + + static void initializeLibraryPaths(java.util.Properties props) + { + java_library_path = props.getProperty("java.library.path", ""); + sun_boot_library_path = props.getProperty("sun.boot.library.path", ""); + } + + // Invoked in the java.lang.Runtime class to implement load and loadLibrary. + static void loadLibrary(Class fromClass, String name, + boolean isAbsolute) { + ClassLoader loader = + (fromClass == null) ? null : fromClass.getClassLoader(); + if (sys_paths == null) { + usr_paths = initializePath(java_library_path); + sys_paths = initializePath(sun_boot_library_path); + } + if (isAbsolute) { + if (loadLibrary0(fromClass, new File(name))) { + return; + } + throw new UnsatisfiedLinkError("Can't load library: " + name); + } + if (loader != null) { + String libfilename = loader.findLibrary(name); + if (libfilename != null) { + File libfile = new File(libfilename); + if (!libfile.isAbsolute()) { + throw new UnsatisfiedLinkError( + "ClassLoader.findLibrary failed to return an absolute path: " + libfilename); + } + if (loadLibrary0(fromClass, libfile)) { + return; + } + throw new UnsatisfiedLinkError("Can't load " + libfilename); + } + } + for (int i = 0 ; i < sys_paths.length ; i++) { + File libfile = new File(sys_paths[i], System.mapLibraryName(name)); + if (loadLibrary0(fromClass, libfile)) { + return; + } + libfile = ClassLoaderHelper.mapAlternativeName(libfile); + if (libfile != null && loadLibrary0(fromClass, libfile)) { + return; + } + } + if (loader != null) { + for (int i = 0 ; i < usr_paths.length ; i++) { + File libfile = new File(usr_paths[i], + System.mapLibraryName(name)); + if (loadLibrary0(fromClass, libfile)) { + return; + } + libfile = ClassLoaderHelper.mapAlternativeName(libfile); + if (libfile != null && loadLibrary0(fromClass, libfile)) { + return; + } + } + } + // Oops, it failed + throw new UnsatisfiedLinkError("no " + name + " in java.library.path"); + } + + private static boolean loadLibrary0(Class fromClass, final File file) { + // Check to see if we're attempting to access a static library + String name = NativeLibrary.findBuiltinLib(file.getName()); + boolean isBuiltin = (name != null); + if (!isBuiltin) { + boolean exists = AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + return file.exists() ? Boolean.TRUE : null; + }}) + != null; + if (!exists) { + return false; + } + try { + name = file.getCanonicalPath(); + } catch (IOException e) { + return false; + } + } + ClassLoader loader = + (fromClass == null) ? null : fromClass.getClassLoader(); + Vector libs = + loader != null ? loader.nativeLibraries : systemNativeLibraries; + synchronized (libs) { + int size = libs.size(); + for (int i = 0; i < size; i++) { + NativeLibrary lib = libs.elementAt(i); + if (name.equals(lib.name)) { + return true; + } + } + + synchronized (loadedLibraryNames) { + if (loadedLibraryNames.contains(name)) { + throw new UnsatisfiedLinkError + ("Native Library " + + name + + " already loaded in another classloader"); + } + /* If the library is being loaded (must be by the same thread, + * because Runtime.load and Runtime.loadLibrary are + * synchronous). The reason is can occur is that the JNI_OnLoad + * function can cause another loadLibrary invocation. + * + * Thus we can use a static stack to hold the list of libraries + * we are loading. + * + * If there is a pending load operation for the library, we + * immediately return success; otherwise, we raise + * UnsatisfiedLinkError. + */ + int n = nativeLibraryContext.size(); + for (int i = 0; i < n; i++) { + NativeLibrary lib = nativeLibraryContext.elementAt(i); + if (name.equals(lib.name)) { + if (loader == lib.fromClass.getClassLoader()) { + return true; + } else { + throw new UnsatisfiedLinkError + ("Native Library " + + name + + " is being loaded in another classloader"); + } + } + } + NativeLibrary lib = new NativeLibrary(fromClass, name, isBuiltin); + nativeLibraryContext.push(lib); + try { + lib.load(name, isBuiltin); + } finally { + nativeLibraryContext.pop(); + } + if (lib.loaded) { + loadedLibraryNames.addElement(name); + libs.addElement(lib); + return true; + } + return false; + } + } + } + + // Invoked in the VM class linking code. + static long findNative(ClassLoader loader, String name) { + Vector libs = + loader != null ? loader.nativeLibraries : systemNativeLibraries; + synchronized (libs) { + int size = libs.size(); + for (int i = 0; i < size; i++) { + NativeLibrary lib = libs.elementAt(i); + long entry = lib.find(name); + if (entry != 0) + return entry; + } + } + return 0; + } + + + // -- Assertion management -- + + final Object assertionLock; + + // The default toggle for assertion checking. + // @GuardedBy("assertionLock") + private boolean defaultAssertionStatus = false; + + // Maps String packageName to Boolean package default assertion status Note + // that the default package is placed under a null map key. If this field + // is null then we are delegating assertion status queries to the VM, i.e., + // none of this ClassLoader's assertion status modification methods have + // been invoked. + // @GuardedBy("assertionLock") + private Map packageAssertionStatus = null; + + // Maps String fullyQualifiedClassName to Boolean assertionStatus If this + // field is null then we are delegating assertion status queries to the VM, + // i.e., none of this ClassLoader's assertion status modification methods + // have been invoked. + // @GuardedBy("assertionLock") + Map classAssertionStatus = null; + + /** + * Sets the default assertion status for this class loader. This setting + * determines whether classes loaded by this class loader and initialized + * in the future will have assertions enabled or disabled by default. + * This setting may be overridden on a per-package or per-class basis by + * invoking {@link #setPackageAssertionStatus(String, boolean)} or {@link + * #setClassAssertionStatus(String, boolean)}. + * + * @param enabled + * true if classes loaded by this class loader will + * henceforth have assertions enabled by default, false + * if they will have assertions disabled by default. + * + * @since 1.4 + */ + public void setDefaultAssertionStatus(boolean enabled) { + synchronized (assertionLock) { + if (classAssertionStatus == null) + initializeJavaAssertionMaps(); + + defaultAssertionStatus = enabled; + } + } + + /** + * Sets the package default assertion status for the named package. The + * package default assertion status determines the assertion status for + * classes initialized in the future that belong to the named package or + * any of its "subpackages". + * + *

A subpackage of a package named p is any package whose name begins + * with "p.". For example, javax.swing.text is a + * subpackage of javax.swing, and both java.util and + * java.lang.reflect are subpackages of java. + * + *

In the event that multiple package defaults apply to a given class, + * the package default pertaining to the most specific package takes + * precedence over the others. For example, if javax.lang and + * javax.lang.reflect both have package defaults associated with + * them, the latter package default applies to classes in + * javax.lang.reflect. + * + *

Package defaults take precedence over the class loader's default + * assertion status, and may be overridden on a per-class basis by invoking + * {@link #setClassAssertionStatus(String, boolean)}.

+ * + * @param packageName + * The name of the package whose package default assertion status + * is to be set. A null value indicates the unnamed + * package that is "current" + * (see section 7.4.2 of + * The Java™ Language Specification.) + * + * @param enabled + * true if classes loaded by this classloader and + * belonging to the named package or any of its subpackages will + * have assertions enabled by default, false if they will + * have assertions disabled by default. + * + * @since 1.4 + */ + public void setPackageAssertionStatus(String packageName, + boolean enabled) { + synchronized (assertionLock) { + if (packageAssertionStatus == null) + initializeJavaAssertionMaps(); + + packageAssertionStatus.put(packageName, enabled); + } + } + + /** + * Sets the desired assertion status for the named top-level class in this + * class loader and any nested classes contained therein. This setting + * takes precedence over the class loader's default assertion status, and + * over any applicable per-package default. This method has no effect if + * the named class has already been initialized. (Once a class is + * initialized, its assertion status cannot change.) + * + *

If the named class is not a top-level class, this invocation will + * have no effect on the actual assertion status of any class.

+ * + * @param className + * The fully qualified class name of the top-level class whose + * assertion status is to be set. + * + * @param enabled + * true if the named class is to have assertions + * enabled when (and if) it is initialized, false if the + * class is to have assertions disabled. + * + * @since 1.4 + */ + public void setClassAssertionStatus(String className, boolean enabled) { + synchronized (assertionLock) { + if (classAssertionStatus == null) + initializeJavaAssertionMaps(); + + classAssertionStatus.put(className, enabled); + } + } + + /** + * Sets the default assertion status for this class loader to + * false and discards any package defaults or class assertion + * status settings associated with the class loader. This method is + * provided so that class loaders can be made to ignore any command line or + * persistent assertion status settings and "start with a clean slate." + * + * @since 1.4 + */ + public void clearAssertionStatus() { + /* + * Whether or not "Java assertion maps" are initialized, set + * them to empty maps, effectively ignoring any present settings. + */ + synchronized (assertionLock) { + classAssertionStatus = new HashMap<>(); + packageAssertionStatus = new HashMap<>(); + defaultAssertionStatus = false; + } + } + + /** + * Returns the assertion status that would be assigned to the specified + * class if it were to be initialized at the time this method is invoked. + * If the named class has had its assertion status set, the most recent + * setting will be returned; otherwise, if any package default assertion + * status pertains to this class, the most recent setting for the most + * specific pertinent package default assertion status is returned; + * otherwise, this class loader's default assertion status is returned. + *

+ * + * @param className + * The fully qualified class name of the class whose desired + * assertion status is being queried. + * + * @return The desired assertion status of the specified class. + * + * @see #setClassAssertionStatus(String, boolean) + * @see #setPackageAssertionStatus(String, boolean) + * @see #setDefaultAssertionStatus(boolean) + * + * @since 1.4 + */ + boolean desiredAssertionStatus(String className) { + synchronized (assertionLock) { + // assert classAssertionStatus != null; + // assert packageAssertionStatus != null; + + // Check for a class entry + Boolean result = classAssertionStatus.get(className); + if (result != null) + return result.booleanValue(); + + // Check for most specific package entry + int dotIndex = className.lastIndexOf("."); + if (dotIndex < 0) { // default package + result = packageAssertionStatus.get(null); + if (result != null) + return result.booleanValue(); + } + while(dotIndex > 0) { + className = className.substring(0, dotIndex); + result = packageAssertionStatus.get(className); + if (result != null) + return result.booleanValue(); + dotIndex = className.lastIndexOf(".", dotIndex-1); + } + + // Return the classloader default + return defaultAssertionStatus; + } + } + + // Set up the assertions with information provided by the VM. + // Note: Should only be called inside a synchronized block + private void initializeJavaAssertionMaps() { + // assert Thread.holdsLock(assertionLock); + + classAssertionStatus = new HashMap<>(); + packageAssertionStatus = new HashMap<>(); + AssertionStatusDirectives directives = retrieveDirectives(); + + for(int i = 0; i < directives.classes.length; i++) + classAssertionStatus.put(directives.classes[i], + directives.classEnabled[i]); + + for(int i = 0; i < directives.packages.length; i++) + packageAssertionStatus.put(directives.packages[i], + directives.packageEnabled[i]); + + defaultAssertionStatus = directives.deflt; + } + + // Retrieves the assertion directives from the VM. + private static native AssertionStatusDirectives retrieveDirectives(); + + // [IKVM] equivalent of HotSpot's java_lang_ClassLoader::is_trusted_loader() + static boolean isTrustedLoader(ClassLoader loader) { + ClassLoader cl = scl; + while (cl != null) { + if (cl == loader) return true; + cl = cl.parent; + } + return false; + } +} + + +class SystemClassLoaderAction + implements PrivilegedExceptionAction { + private ClassLoader parent; + + SystemClassLoaderAction(ClassLoader parent) { + this.parent = parent; + } + + public ClassLoader run() throws Exception { + String cls = System.getProperty("java.system.class.loader"); + if (cls == null) { + return parent; + } + + Constructor ctor = Class.forName(cls, true, parent) + .getDeclaredConstructor(new Class[] { ClassLoader.class }); + ClassLoader sys = (ClassLoader) ctor.newInstance( + new Object[] { parent }); + Thread.currentThread().setContextClassLoader(sys); + return sys; + } +} diff --git a/openjdk/java/lang/ClassLoaderHelper.java b/openjdk/java/lang/ClassLoaderHelper.java new file mode 100644 index 0000000..e4dc578 --- /dev/null +++ b/openjdk/java/lang/ClassLoaderHelper.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 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 java.lang; + +import java.io.File; + +class ClassLoaderHelper { + + private ClassLoaderHelper() {} + + /** + * Returns an alternate path name for the given file + * such that if the original pathname did not exist, then the + * file may be located at the alternate location. + * For mac, this replaces the final .dylib suffix with .jnilib + */ + static File mapAlternativeName(File lib) { + if (!ikvm.internal.Util.MACOSX) { + return null; + } + String name = lib.toString(); + int index = name.lastIndexOf('.'); + if (index < 0) { + return null; + } + return new File(name.substring(0, index) + ".jnilib"); + } +} diff --git a/openjdk/java/lang/ClassSerializationProxy.java b/openjdk/java/lang/ClassSerializationProxy.java new file mode 100644 index 0000000..aae7675 --- /dev/null +++ b/openjdk/java/lang/ClassSerializationProxy.java @@ -0,0 +1,85 @@ +/* + Copyright (C) 2009-2015 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package java.lang; + +import cli.System.Runtime.Serialization.IObjectReference; +import cli.System.Runtime.Serialization.SerializationException; +import cli.System.Runtime.Serialization.StreamingContext; + +@cli.System.SerializableAttribute.Annotation +final class ClassSerializationProxy implements IObjectReference +{ + private cli.System.Type type; + private String sig; + + @cli.System.Security.SecurityCriticalAttribute.Annotation + public Object GetRealObject(StreamingContext context) + { + if (sig != null) + { + if (sig.length() == 1) + { + switch (sig.charAt(0)) + { + case 'B': + return Byte.TYPE; + case 'C': + return Character.TYPE; + case 'D': + return Double.TYPE; + case 'F': + return Float.TYPE; + case 'I': + return Integer.TYPE; + case 'J': + return Long.TYPE; + case 'S': + return Short.TYPE; + case 'Z': + return Boolean.TYPE; + case 'V': + return Void.TYPE; + } + } + String className; + if (sig.charAt(0) == 'L') + { + className = sig.substring(1, sig.length() - 1); + } + else + { + className = sig; + } + try + { + return Class.forName(className, false, Thread.currentThread().getContextClassLoader()); + } + catch (ClassNotFoundException x) + { + ikvm.runtime.Util.throwException(new SerializationException(x.getMessage(), x)); + } + } + return ikvm.runtime.Util.getClassFromTypeHandle(type.get_TypeHandle()); + } +} diff --git a/openjdk/java/lang/Enum.java b/openjdk/java/lang/Enum.java new file mode 100644 index 0000000..7d56566 --- /dev/null +++ b/openjdk/java/lang/Enum.java @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2003, 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 java.lang; + +import java.io.Serializable; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.ObjectStreamException; +import cli.System.Runtime.Serialization.IObjectReference; +import cli.System.Runtime.Serialization.SerializationException; +import cli.System.Runtime.Serialization.SerializationInfo; +import cli.System.Runtime.Serialization.StreamingContext; + +/** + * This is the common base class of all Java language enumeration types. + * + * More information about enums, including descriptions of the + * implicitly declared methods synthesized by the compiler, can be + * found in section 8.9 of + * The Java™ Language Specification. + * + *

Note that when using an enumeration type as the type of a set + * or as the type of the keys in a map, specialized and efficient + * {@linkplain java.util.EnumSet set} and {@linkplain + * java.util.EnumMap map} implementations are available. + * + * @param The enum type subclass + * @author Josh Bloch + * @author Neal Gafter + * @see Class#getEnumConstants() + * @see java.util.EnumSet + * @see java.util.EnumMap + * @since 1.5 + */ +@cli.System.SerializableAttribute.Annotation +public abstract class Enum> + implements Comparable, Serializable { + /** + * The name of this enum constant, as declared in the enum declaration. + * Most programmers should use the {@link #toString} method rather than + * accessing this field. + */ + private final String name; + + /** + * Returns the name of this enum constant, exactly as declared in its + * enum declaration. + * + * Most programmers should use the {@link #toString} method in + * preference to this one, as the toString method may return + * a more user-friendly name. This method is designed primarily for + * use in specialized situations where correctness depends on getting the + * exact name, which will not vary from release to release. + * + * @return the name of this enum constant + */ + public final String name() { + return name; + } + + /** + * The ordinal of this enumeration constant (its position + * in the enum declaration, where the initial constant is assigned + * an ordinal of zero). + * + * Most programmers will have no use for this field. It is designed + * for use by sophisticated enum-based data structures, such as + * {@link java.util.EnumSet} and {@link java.util.EnumMap}. + */ + private final int ordinal; + + /** + * Returns the ordinal of this enumeration constant (its position + * in its enum declaration, where the initial constant is assigned + * an ordinal of zero). + * + * Most programmers will have no use for this method. It is + * designed for use by sophisticated enum-based data structures, such + * as {@link java.util.EnumSet} and {@link java.util.EnumMap}. + * + * @return the ordinal of this enumeration constant + */ + public final int ordinal() { + return ordinal; + } + + /** + * Sole constructor. Programmers cannot invoke this constructor. + * It is for use by code emitted by the compiler in response to + * enum type declarations. + * + * @param name - The name of this enum constant, which is the identifier + * used to declare it. + * @param ordinal - The ordinal of this enumeration constant (its position + * in the enum declaration, where the initial constant is assigned + * an ordinal of zero). + */ + protected Enum(String name, int ordinal) { + this.name = name; + this.ordinal = ordinal; + } + + /** + * Returns the name of this enum constant, as contained in the + * declaration. This method may be overridden, though it typically + * isn't necessary or desirable. An enum type should override this + * method when a more "programmer-friendly" string form exists. + * + * @return the name of this enum constant + */ + public String toString() { + return name; + } + + /** + * Returns true if the specified object is equal to this + * enum constant. + * + * @param other the object to be compared for equality with this object. + * @return true if the specified object is equal to this + * enum constant. + */ + public final boolean equals(Object other) { + return this==other; + } + + /** + * Returns a hash code for this enum constant. + * + * @return a hash code for this enum constant. + */ + public final int hashCode() { + return super.hashCode(); + } + + /** + * Throws CloneNotSupportedException. This guarantees that enums + * are never cloned, which is necessary to preserve their "singleton" + * status. + * + * @return (never returns) + */ + protected final Object clone() throws CloneNotSupportedException { + throw new CloneNotSupportedException(); + } + + /** + * Compares this enum with the specified object for order. Returns a + * negative integer, zero, or a positive integer as this object is less + * than, equal to, or greater than the specified object. + * + * Enum constants are only comparable to other enum constants of the + * same enum type. The natural order implemented by this + * method is the order in which the constants are declared. + */ + public final int compareTo(E o) { + Enum other = (Enum)o; + Enum self = this; + if (self.getClass() != other.getClass() && // optimization + self.getDeclaringClass() != other.getDeclaringClass()) + throw new ClassCastException(); + return self.ordinal - other.ordinal; + } + + /** + * Returns the Class object corresponding to this enum constant's + * enum type. Two enum constants e1 and e2 are of the + * same enum type if and only if + * e1.getDeclaringClass() == e2.getDeclaringClass(). + * (The value returned by this method may differ from the one returned + * by the {@link Object#getClass} method for enum constants with + * constant-specific class bodies.) + * + * @return the Class object corresponding to this enum constant's + * enum type + */ + @SuppressWarnings("unchecked") + public final Class getDeclaringClass() { + Class clazz = getClass(); + Class zuper = clazz.getSuperclass(); + return (zuper == Enum.class) ? (Class)clazz : (Class)zuper; + } + + /** + * Returns the enum constant of the specified enum type with the + * specified name. The name must match exactly an identifier used + * to declare an enum constant in this type. (Extraneous whitespace + * characters are not permitted.) + * + *

Note that for a particular enum type {@code T}, the + * implicitly declared {@code public static T valueOf(String)} + * method on that enum may be used instead of this method to map + * from a name to the corresponding enum constant. All the + * constants of an enum type can be obtained by calling the + * implicit {@code public static T[] values()} method of that + * type. + * + * @param The enum type whose constant is to be returned + * @param enumType the {@code Class} object of the enum type from which + * to return a constant + * @param name the name of the constant to return + * @return the enum constant of the specified enum type with the + * specified name + * @throws IllegalArgumentException if the specified enum type has + * no constant with the specified name, or the specified + * class object does not represent an enum type + * @throws NullPointerException if {@code enumType} or {@code name} + * is null + * @since 1.5 + */ + public static > T valueOf(Class enumType, + String name) { + T result = enumType.enumConstantDirectory().get(name); + if (result != null) + return result; + if (name == null) + throw new NullPointerException("Name is null"); + throw new IllegalArgumentException( + "No enum constant " + enumType.getCanonicalName() + "." + name); + } + + /** + * enum classes cannot have finalize methods. + */ + protected final void finalize() { } + + /** + * prevent default deserialization + */ + private void readObject(ObjectInputStream in) throws IOException, + ClassNotFoundException { + throw new InvalidObjectException("can't deserialize enum"); + } + + private void readObjectNoData() throws ObjectStreamException { + throw new InvalidObjectException("can't deserialize enum"); + } + + // [IKVM] .NET serialization support starts here + // Note that we don't have a security demand, because the info is harmless. + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + @cli.System.Security.SecurityCriticalAttribute.Annotation + public final void GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddValue("enumType", getDeclaringClass()); + info.AddValue("name", name); + info.SetType(ikvm.runtime.Util.getInstanceTypeFromClass(EnumSerializationProxy.class)); + } +} + +@cli.System.SerializableAttribute.Annotation +final class EnumSerializationProxy implements IObjectReference +{ + private Class enumType; + private String name; + + @cli.System.Security.SecurityCriticalAttribute.Annotation + public Object GetRealObject(StreamingContext context) + { + try + { + return Enum.valueOf(enumType, name); + } + catch (IllegalArgumentException x) + { + ikvm.runtime.Util.throwException(new SerializationException("Enum value " + name + " not found in " + enumType, x)); + return null; + } + } +} diff --git a/openjdk/java/lang/LangHelper.java b/openjdk/java/lang/LangHelper.java new file mode 100644 index 0000000..8d725d4 --- /dev/null +++ b/openjdk/java/lang/LangHelper.java @@ -0,0 +1,88 @@ +/* + Copyright (C) 2007-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package java.lang; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Executable; +import java.security.AccessControlContext; +import java.util.Map; +import sun.nio.ch.Interruptible; +import sun.reflect.annotation.AnnotationType; + +@ikvm.lang.Internal +public class LangHelper +{ + public static sun.misc.JavaLangAccess getJavaLangAccess() + { + return new sun.misc.JavaLangAccess() { + public sun.reflect.ConstantPool getConstantPool(Class klass) { + return klass.getConstantPool(); + } + public boolean casAnnotationType(Class klass, AnnotationType oldType, AnnotationType newType) { + return klass.casAnnotationType(oldType, newType); + } + public AnnotationType getAnnotationType(Class klass) { + return klass.getAnnotationType(); + } + public Map, Annotation> getDeclaredAnnotationMap(Class klass) { + return klass.getDeclaredAnnotationMap(); + } + public byte[] getRawClassAnnotations(Class klass) { + throw new InternalError(); + } + public byte[] getRawClassTypeAnnotations(Class klass) { + return klass.getRawTypeAnnotations(); + } + public byte[] getRawExecutableTypeAnnotations(Executable executable) { + return Class.getExecutableTypeAnnotationBytes(executable); + } + public > + E[] getEnumConstantsShared(Class klass) { + return klass.getEnumConstantsShared(); + } + public void blockedOn(Thread t, Interruptible b) { + t.blockedOn(b); + } + public void registerShutdownHook(int slot, boolean registerShutdownInProgress, Runnable hook) { + Shutdown.add(slot, registerShutdownInProgress, hook); + } + public int getStackTraceDepth(Throwable t) { + return t.getStackTraceDepth(); + } + public StackTraceElement getStackTraceElement(Throwable t, int i) { + return t.getStackTraceElement(i); + } + public String newStringUnsafe(char[] chars) { + return String.valueOf(chars); + } + public Thread newThreadWithAcc(Runnable target, AccessControlContext acc) { + return new Thread(target, acc); + } + public void invokeFinalize(Object o) throws Throwable { + // we don't actually support invoking the finalize method explicitly + } + }; + } +} diff --git a/openjdk/java/lang/ProcessImpl.java b/openjdk/java/lang/ProcessImpl.java new file mode 100644 index 0000000..0624dc1 --- /dev/null +++ b/openjdk/java/lang/ProcessImpl.java @@ -0,0 +1,834 @@ +/* + * Copyright (c) 1995, 2013, 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. + */ + +/*IKVM*/ +/* + * Modified for IKVM by Jeroen Frijters + */ + +package java.lang; + +import java.io.IOException; +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileDescriptor; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.lang.ProcessBuilder.Redirect; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import cli.System.AsyncCallback; +import cli.System.IAsyncResult; +import cli.System.Diagnostics.ProcessStartInfo; +import cli.System.EventArgs; +import cli.System.EventHandler; +import cli.System.IO.FileAccess; +import cli.System.IO.FileShare; +import cli.System.IO.FileMode; +import cli.System.IO.FileOptions; +import cli.System.IO.FileStream; +import cli.System.IO.Stream; +import cli.System.Security.AccessControl.FileSystemRights; + +/* This class is for the exclusive use of ProcessBuilder.start() to + * create new processes. + * + * @author Martin Buchholz + * @since 1.5 + */ + +final class ProcessImpl extends Process { + static class fdAccess { + static Stream getHandle(FileDescriptor fd) { + return fd.getStream(); + } + } + + /** + * Open a file for writing. If {@code append} is {@code true} then the file + * is opened for atomic append directly and a FileOutputStream constructed + * with the resulting handle. This is because a FileOutputStream created + * to append to a file does not open the file in a manner that guarantees + * that writes by the child process will be atomic. + */ + private static FileOutputStream newFileOutputStream(File f, boolean append) + throws IOException + { + if (append) { + String path = f.getPath(); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkWrite(path); + final FileDescriptor fd = openForAtomicAppend(path); + return AccessController.doPrivileged( + new PrivilegedAction() { + public FileOutputStream run() { + return new FileOutputStream(fd); + } + } + ); + } else { + return new FileOutputStream(f); + } + } + + // System-dependent portion of ProcessBuilder.start() + static Process start(String cmdarray[], + java.util.Map environment, + String dir, + ProcessBuilder.Redirect[] redirects, + boolean redirectErrorStream) + throws IOException + { + FileInputStream f0 = null; + FileOutputStream f1 = null; + FileOutputStream f2 = null; + + try { + Stream[] stdHandles; + if (redirects == null) { + stdHandles = new Stream[3]; + } else { + stdHandles = new Stream[3]; + + if (redirects[0] == Redirect.PIPE) + stdHandles[0] = null; + else if (redirects[0] == Redirect.INHERIT) + stdHandles[0] = fdAccess.getHandle(FileDescriptor.in); + else { + f0 = new FileInputStream(redirects[0].file()); + stdHandles[0] = fdAccess.getHandle(f0.getFD()); + } + + if (redirects[1] == Redirect.PIPE) + stdHandles[1] = null; + else if (redirects[1] == Redirect.INHERIT) + stdHandles[1] = fdAccess.getHandle(FileDescriptor.out); + else { + f1 = newFileOutputStream(redirects[1].file(), + redirects[1].append()); + stdHandles[1] = fdAccess.getHandle(f1.getFD()); + } + + if (redirects[2] == Redirect.PIPE) + stdHandles[2] = null; + else if (redirects[2] == Redirect.INHERIT) + stdHandles[2] = fdAccess.getHandle(FileDescriptor.err); + else { + f2 = newFileOutputStream(redirects[2].file(), + redirects[2].append()); + stdHandles[2] = fdAccess.getHandle(f2.getFD()); + } + } + + return new ProcessImpl(cmdarray, environment, dir, + stdHandles, redirectErrorStream); + } catch (Throwable t) { + if (f0 != null) + f0.close(); + if (f1 != null) + f1.close(); + if (f2 != null) + f2.close(); + throw t; + } finally { + // HACK prevent the File[In|Out]putStream objects from closing the streams + // (the System.IO.FileStream will eventually be closed explicitly or by its finalizer) + if (f0 != null) + cli.System.GC.SuppressFinalize(f0); + if (f1 != null) + cli.System.GC.SuppressFinalize(f1); + if (f2 != null) + cli.System.GC.SuppressFinalize(f2); + } + + } + + private static class LazyPattern { + // Escape-support version: + // "(\")((?:\\\\\\1|.)+?)\\1|([^\\s\"]+)"; + private static final Pattern PATTERN = + Pattern.compile("[^\\s\"]+|\"[^\"]*\""); + }; + + /* Parses the command string parameter into the executable name and + * program arguments. + * + * The command string is broken into tokens. The token separator is a space + * or quota character. The space inside quotation is not a token separator. + * There are no escape sequences. + */ + private static String[] getTokensFromCommand(String command) { + ArrayList matchList = new ArrayList<>(8); + Matcher regexMatcher = LazyPattern.PATTERN.matcher(command); + while (regexMatcher.find()) + matchList.add(regexMatcher.group()); + return matchList.toArray(new String[matchList.size()]); + } + + private static final int VERIFICATION_CMD_BAT = 0; + private static final int VERIFICATION_WIN32 = 1; + private static final int VERIFICATION_LEGACY = 2; + private static final char ESCAPE_VERIFICATION[][] = { + // We guarantee the only command file execution for implicit [cmd.exe] run. + // http://technet.microsoft.com/en-us/library/bb490954.aspx + {' ', '\t', '<', '>', '&', '|', '^'}, + + {' ', '\t', '<', '>'}, + {' ', '\t'} + }; + + private static String createCommandLine(int verificationType, + final String executablePath, + final String cmd[]) + { + StringBuilder cmdbuf = new StringBuilder(80); + + cmdbuf.append(executablePath); + + for (int i = 1; i < cmd.length; ++i) { + cmdbuf.append(' '); + String s = cmd[i]; + if (needsEscaping(verificationType, s)) { + cmdbuf.append('"').append(s); + + // The code protects the [java.exe] and console command line + // parser, that interprets the [\"] combination as an escape + // sequence for the ["] char. + // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx + // + // If the argument is an FS path, doubling of the tail [\] + // char is not a problem for non-console applications. + // + // The [\"] sequence is not an escape sequence for the [cmd.exe] + // command line parser. The case of the [""] tail escape + // sequence could not be realized due to the argument validation + // procedure. + if ((verificationType != VERIFICATION_CMD_BAT) && s.endsWith("\\")) { + cmdbuf.append('\\'); + } + cmdbuf.append('"'); + } else { + cmdbuf.append(s); + } + } + return cmdbuf.toString(); + } + + private static boolean isQuoted(boolean noQuotesInside, String arg, + String errorMessage) { + int lastPos = arg.length() - 1; + if (lastPos >=1 && arg.charAt(0) == '"' && arg.charAt(lastPos) == '"') { + // The argument has already been quoted. + if (noQuotesInside) { + if (arg.indexOf('"', 1) != lastPos) { + // There is ["] inside. + throw new IllegalArgumentException(errorMessage); + } + } + return true; + } + if (noQuotesInside) { + if (arg.indexOf('"') >= 0) { + // There is ["] inside. + throw new IllegalArgumentException(errorMessage); + } + } + return false; + } + + private static boolean needsEscaping(int verificationType, String arg) { + // Switch off MS heuristic for internal ["]. + // Please, use the explicit [cmd.exe] call + // if you need the internal ["]. + // Example: "cmd.exe", "/C", "Extended_MS_Syntax" + + // For [.exe] or [.com] file the unpaired/internal ["] + // in the argument is not a problem. + boolean argIsQuoted = isQuoted( + (verificationType == VERIFICATION_CMD_BAT), + arg, "Argument has embedded quote, use the explicit CMD.EXE call."); + + if (!argIsQuoted) { + char testEscape[] = ESCAPE_VERIFICATION[verificationType]; + for (int i = 0; i < testEscape.length; ++i) { + if (arg.indexOf(testEscape[i]) >= 0) { + return true; + } + } + } + return false; + } + + private static String getExecutablePath(String path) + throws IOException + { + boolean pathIsQuoted = isQuoted(true, path, + "Executable name has embedded quote, split the arguments"); + + // Win32 CreateProcess requires path to be normalized + File fileToRun = new File(pathIsQuoted + ? path.substring(1, path.length() - 1) + : path); + + // From the [CreateProcess] function documentation: + // + // "If the file name does not contain an extension, .exe is appended. + // Therefore, if the file name extension is .com, this parameter + // must include the .com extension. If the file name ends in + // a period (.) with no extension, or if the file name contains a path, + // .exe is not appended." + // + // "If the file name !does not contain a directory path!, + // the system searches for the executable file in the following + // sequence:..." + // + // In practice ANY non-existent path is extended by [.exe] extension + // in the [CreateProcess] funcion with the only exception: + // the path ends by (.) + + return fileToRun.getPath(); + } + + + private boolean isShellFile(String executablePath) { + String upPath = executablePath.toUpperCase(); + return (upPath.endsWith(".CMD") || upPath.endsWith(".BAT")); + } + + private String quoteString(String arg) { + StringBuilder argbuf = new StringBuilder(arg.length() + 2); + return argbuf.append('"').append(arg).append('"').toString(); + } + + + private cli.System.Diagnostics.Process handle; + private OutputStream stdin_stream; + private InputStream stdout_stream; + private InputStream stderr_stream; + + private ProcessImpl(String cmd[], + final java.util.Map envblock, + final String path, + final Stream[] stdHandles, + final boolean redirectErrorStream) + throws IOException + { + String cmdstr; + SecurityManager security = System.getSecurityManager(); + boolean allowAmbiguousCommands = false; + if (security == null) { + allowAmbiguousCommands = true; + String value = System.getProperty("jdk.lang.Process.allowAmbiguousCommands"); + if (value != null) + allowAmbiguousCommands = !"false".equalsIgnoreCase(value); + } + if (allowAmbiguousCommands) { + // Legacy mode. + + // Normalize path if possible. + String executablePath = new File(cmd[0]).getPath(); + + // No worry about internal, unpaired ["], and redirection/piping. + if (needsEscaping(VERIFICATION_LEGACY, executablePath) ) + executablePath = quoteString(executablePath); + + cmdstr = createCommandLine( + //legacy mode doesn't worry about extended verification + VERIFICATION_LEGACY, + executablePath, + cmd); + } else { + String executablePath; + try { + executablePath = getExecutablePath(cmd[0]); + } catch (IllegalArgumentException e) { + // Workaround for the calls like + // Runtime.getRuntime().exec("\"C:\\Program Files\\foo\" bar") + + // No chance to avoid CMD/BAT injection, except to do the work + // right from the beginning. Otherwise we have too many corner + // cases from + // Runtime.getRuntime().exec(String[] cmd [, ...]) + // calls with internal ["] and escape sequences. + + // Restore original command line. + StringBuilder join = new StringBuilder(); + // terminal space in command line is ok + for (String s : cmd) + join.append(s).append(' '); + + // Parse the command line again. + cmd = getTokensFromCommand(join.toString()); + executablePath = getExecutablePath(cmd[0]); + + // Check new executable name once more + if (security != null) + security.checkExec(executablePath); + } + + // Quotation protects from interpretation of the [path] argument as + // start of longer path with spaces. Quotation has no influence to + // [.exe] extension heuristic. + cmdstr = createCommandLine( + // We need the extended verification procedure for CMD files. + isShellFile(executablePath) + ? VERIFICATION_CMD_BAT + : VERIFICATION_WIN32, + quoteString(executablePath), + cmd); + } + + handle = create(cmdstr, envblock, path, + stdHandles, redirectErrorStream); + + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + if (stdHandles[0] == null) + stdin_stream = ProcessBuilder.NullOutputStream.INSTANCE; + else { + FileDescriptor stdin_fd = FileDescriptor.fromStream(stdHandles[0]); + stdin_stream = new BufferedOutputStream( + new FileOutputStream(stdin_fd)); + } + + if (stdHandles[1] == null) + stdout_stream = ProcessBuilder.NullInputStream.INSTANCE; + else { + FileDescriptor stdout_fd = FileDescriptor.fromStream(stdHandles[1]); + stdout_stream = new BufferedInputStream( + new FileInputStream(stdout_fd)); + } + + if (stdHandles[2] == null) + stderr_stream = ProcessBuilder.NullInputStream.INSTANCE; + else { + FileDescriptor stderr_fd = FileDescriptor.fromStream(stdHandles[2]); + stderr_stream = new FileInputStream(stderr_fd); + } + + return null; }}); + } + + private static native String mapVfsExecutable(String path); + + public OutputStream getOutputStream() { + return stdin_stream; + } + + public InputStream getInputStream() { + return stdout_stream; + } + + public InputStream getErrorStream() { + return stderr_stream; + } + + public int exitValue() { + if (!handle.get_HasExited()) + throw new IllegalThreadStateException("process has not exited"); + return handle.get_ExitCode(); + } + + public int waitFor() throws InterruptedException { + waitForInterruptibly(handle); + if (Thread.interrupted()) + throw new InterruptedException(); + return exitValue(); + } + + private static void waitForInterruptibly(cli.System.Diagnostics.Process handle) throws InterruptedException { + // to be interruptable we have to use polling + // (on .NET 2.0 WaitForExit is actually interruptible, but this isn't documented) + Thread current = Thread.currentThread(); + while (!current.isInterrupted() && !handle.WaitForExit(100)) + ; + } + + @Override + public boolean waitFor(long timeout, TimeUnit unit) + throws InterruptedException + { + if (handle.get_HasExited()) return true; + if (timeout <= 0) return false; + + long msTimeout = unit.toMillis(timeout); + + waitForTimeoutInterruptibly(handle, msTimeout); + if (Thread.interrupted()) + throw new InterruptedException(); + return handle.get_HasExited(); + } + + private static void waitForTimeoutInterruptibly( + cli.System.Diagnostics.Process handle, long timeout) { + long now = System.currentTimeMillis(); + long exp = now + timeout; + if (exp < now) { + // if we overflowed, just wait for a really long time + exp = Long.MAX_VALUE; + } + Thread current = Thread.currentThread(); + for (;;) { + if (current.isInterrupted()) { + return; + } + // wait for a maximum of 100 ms to be interruptible + if (handle.WaitForExit((int)Math.min(100, exp - now))) { + return; + } + now = System.currentTimeMillis(); + if (now >= exp) { + return; + } + } + } + + public void destroy() { terminateProcess(handle); } + + @Override + public Process destroyForcibly() { + destroy(); + return this; + } + + private static void terminateProcess(cli.System.Diagnostics.Process handle) { + try { + if (false) throw new cli.System.ComponentModel.Win32Exception(); + if (false) throw new cli.System.InvalidOperationException(); + handle.Kill(); + } catch (cli.System.ComponentModel.Win32Exception _) { + } catch (cli.System.InvalidOperationException _) { + } + } + + @Override + public boolean isAlive() { + return isProcessAlive(handle); + } + + private static boolean isProcessAlive(cli.System.Diagnostics.Process handle) { + return !handle.get_HasExited(); + } + + /** + * Create a process using the win32 function CreateProcess. + * The method is synchronized due to MS kb315939 problem. + * All native handles should restore the inherit flag at the end of call. + * + * @param cmdstr the Windows command line + * @param envblock NUL-separated, double-NUL-terminated list of + * environment strings in VAR=VALUE form + * @param dir the working directory of the process, or null if + * inheriting the current directory from the parent process + * @param stdHandles array of windows HANDLEs. Indexes 0, 1, and + * 2 correspond to standard input, standard output and + * standard error, respectively. On input, a value of -1 + * means to create a pipe to connect child and parent + * processes. On output, a value which is not -1 is the + * parent pipe handle corresponding to the pipe which has + * been created. An element of this array is -1 on input + * if and only if it is not -1 on output. + * @param redirectErrorStream redirectErrorStream attribute + * @return the native subprocess HANDLE returned by CreateProcess + */ + private static cli.System.Diagnostics.Process create(String cmdstr, + java.util.Map envblock, + String dir, + Stream[] stdHandles, + boolean redirectErrorStream) + throws IOException { + + int programEnd = parseCommandString(cmdstr); + int argumentsStart = programEnd; + if (cmdstr.length() > argumentsStart && cmdstr.charAt(argumentsStart) == ' ') { + argumentsStart++; + } + + String fileName = cmdstr.substring(0, programEnd); + ProcessStartInfo si = new ProcessStartInfo(mapVfsExecutable(fileName), cmdstr.substring(argumentsStart)); + si.set_UseShellExecute(false); + si.set_RedirectStandardError(true); + si.set_RedirectStandardOutput(true); + si.set_RedirectStandardInput(true); + si.set_CreateNoWindow(true); + if (dir != null) { + si.set_WorkingDirectory(dir); + } + if (envblock != null) { + si.get_EnvironmentVariables().Clear(); + for (String key : envblock.keySet()) { + si.get_EnvironmentVariables().set_Item(key, envblock.get(key)); + } + } + + cli.System.Diagnostics.Process proc; + try { + if (false) throw new cli.System.ComponentModel.Win32Exception(); + if (false) throw new cli.System.InvalidOperationException(); + proc = cli.System.Diagnostics.Process.Start(si); + } catch (cli.System.ComponentModel.Win32Exception x1) { + throw new IOException(x1.getMessage()); + } catch (cli.System.InvalidOperationException x2) { + throw new IOException(x2.getMessage()); + } + + // if any of the handles is redirected to/from a file, + // we need to close the files as soon as the process exits + if (stdHandles[0] instanceof FileStream + || stdHandles[1] instanceof FileStream + || stdHandles[2] instanceof FileStream) { + final Stream s0 = stdHandles[0]; + final Stream s1 = stdHandles[1]; + final Stream s2 = stdHandles[2]; + proc.set_EnableRaisingEvents(true); + proc.add_Exited(new EventHandler(new EventHandler.Method() { + public void Invoke(Object sender, EventArgs e) { + if (s0 instanceof FileStream) + s0.Close(); + if (s1 instanceof FileStream) + s1.Close(); + if (s2 instanceof FileStream) + s2.Close(); + } + })); + } + + Stream stdin = proc.get_StandardInput().get_BaseStream(); + Stream stdout = proc.get_StandardOutput().get_BaseStream(); + Stream stderr = proc.get_StandardError().get_BaseStream(); + + if (stdHandles[0] != null) { + connectPipe(stdHandles[0], stdin); + stdHandles[0] = null; + } else { + stdHandles[0] = stdin; + } + + Stream stdoutDrain = null; + if (stdHandles[1] != null) { + stdoutDrain = stdHandles[1]; + connectPipe(stdout, stdoutDrain); + stdHandles[1] = null; + } else if (redirectErrorStream) { + PipeStream pipe = new PipeStream(); + connectPipe(stdout, pipe); + connectPipe(stderr, pipe); + stdHandles[1] = pipe; + } else { + stdHandles[1] = stdout; + } + + if (redirectErrorStream) { + if (stdoutDrain != null) { + connectPipe(stderr, stdoutDrain); + } + stdHandles[2] = null; + } else if (stdHandles[2] != null) { + connectPipe(stderr, stdHandles[2]); + stdHandles[2] = null; + } else { + stdHandles[2] = stderr; + } + + return proc; + } + + private static final class PipeStream extends Stream + { + private final byte[] buf = new byte[4096]; + private int pos; + private int users = 2; + + @Override + public synchronized int Read(byte[] buffer, int offset, int count) + { + if (count == 0) + { + return 0; + } + while (pos == 0) + { + try + { + wait(); + } + catch (InterruptedException _) { } + } + if (pos == -1) + { + return 0; + } + count = Math.min(count, pos); + System.arraycopy(buf, 0, buffer, offset, count); + pos -= count; + System.arraycopy(buf, count, buf, 0, pos); + notifyAll(); + return count; + } + + @Override + public synchronized void Write(byte[] buffer, int offset, int count) + { + while (buf.length - pos < count) + { + try + { + wait(); + } + catch (InterruptedException _) { } + } + System.arraycopy(buffer, offset, buf, pos, count); + pos += count; + notifyAll(); + } + + @Override + public synchronized void Close() + { + if (--users == 0) + { + pos = -1; + notifyAll(); + } + } + + @Override + public boolean get_CanRead() + { + return true; + } + + @Override + public boolean get_CanSeek() + { + return false; + } + + @Override + public boolean get_CanWrite() + { + return true; + } + + @Override + public void Flush() + { + } + + @Override + public long get_Length() + { + ikvm.runtime.Util.throwException(new cli.System.NotSupportedException()); + return 0; + } + + @Override + public long get_Position() + { + ikvm.runtime.Util.throwException(new cli.System.NotSupportedException()); + return 0; + } + + @Override + public long Seek(long offset, cli.System.IO.SeekOrigin origin) + { + ikvm.runtime.Util.throwException(new cli.System.NotSupportedException()); + return 0; + } + + @Override + public void SetLength(long value) + { + ikvm.runtime.Util.throwException(new cli.System.NotSupportedException()); + } + + @Override + public void set_Position(long position) + { + ikvm.runtime.Util.throwException(new cli.System.NotSupportedException()); + } + } + + private static native int parseCommandString(String cmdstr); + + /** + * Opens a file for atomic append. The file is created if it doesn't + * already exist. + * + * @param file the file to open or create + * @return the native HANDLE + */ + private static FileDescriptor openForAtomicAppend(String path) + throws IOException { + try { + if (false) throw new cli.System.ArgumentException(); + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.Security.SecurityException(); + if (false) throw new cli.System.UnauthorizedAccessException(); + return FileDescriptor.fromStream(new FileStream(path, FileMode.wrap(FileMode.Append), FileSystemRights.wrap(FileSystemRights.AppendData), FileShare.wrap(FileShare.ReadWrite), 1, FileOptions.wrap(FileOptions.None))); + } catch (cli.System.ArgumentException x) { + throw new IOException(x.getMessage()); + } catch (cli.System.IO.IOException x) { + throw new IOException(x.getMessage()); + } catch (cli.System.Security.SecurityException x) { + throw new IOException(x.getMessage()); + } catch (cli.System.UnauthorizedAccessException x) { + throw new IOException(x.getMessage()); + } + } + + private static void connectPipe(final Stream in, final Stream out) { + final byte[] buf = new byte[4096]; + final AsyncCallback[] callback = new AsyncCallback[1]; + callback[0] = new AsyncCallback(new AsyncCallback.Method() { + public void Invoke(IAsyncResult ar) { + try { + int count = in.EndRead(ar); + if (count > 0) { + out.Write(buf, 0, count); + out.Flush(); + in.BeginRead(buf, 0, buf.length, callback[0], null); + } else { + out.Close(); + } + } catch (Throwable _) { + } + } + }); + try { + in.BeginRead(buf, 0, buf.length, callback[0], null); + } catch (Throwable _) { + } + } +} diff --git a/openjdk/java/lang/PropertyConstants.java b/openjdk/java/lang/PropertyConstants.java new file mode 100644 index 0000000..a50dcbc --- /dev/null +++ b/openjdk/java/lang/PropertyConstants.java @@ -0,0 +1,33 @@ +/* + Copyright (C) 2007, 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package java.lang; + +interface PropertyConstants +{ + String awt_toolkit = "ikvm.awt.NetToolkit, IKVM.AWT.WinForms, Version=8.1.5717.0, Culture=neutral, PublicKeyToken=13235d27fcbfff58"; + String java_awt_graphicsenv = "ikvm.awt.NetGraphicsEnvironment, IKVM.AWT.WinForms, Version=8.1.5717.0, Culture=neutral, PublicKeyToken=13235d27fcbfff58"; + String java_vm_version = "8.1.5717.0"; + String java_runtime_version = "8.1.5717.0"; + String openjdk_version = "OpenJDK 8u45 b14"; +} diff --git a/openjdk/java/lang/PropertyConstants.java.in b/openjdk/java/lang/PropertyConstants.java.in new file mode 100644 index 0000000..69e7796 --- /dev/null +++ b/openjdk/java/lang/PropertyConstants.java.in @@ -0,0 +1,33 @@ +/* + Copyright (C) 2007, 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package java.lang; + +interface PropertyConstants +{ + String awt_toolkit = "ikvm.awt.NetToolkit, @AWTASSEMBLY@"; + String java_awt_graphicsenv = "ikvm.awt.NetGraphicsEnvironment, @AWTASSEMBLY@"; + String java_vm_version = "@VERSION@"; + String java_runtime_version = "@VERSION@"; + String openjdk_version = "@OPENJDK_VERSION@"; +} diff --git a/openjdk/java/lang/Shutdown.java b/openjdk/java/lang/Shutdown.java new file mode 100644 index 0000000..947f0e3 --- /dev/null +++ b/openjdk/java/lang/Shutdown.java @@ -0,0 +1,284 @@ +/* + * Copyright (c) 1999, 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 java.lang; + +import cli.System.AppDomain; +import cli.System.EventArgs; +import cli.System.EventHandler; +import cli.System.Threading.Monitor; + +/** + * Package-private utility class containing data structures and logic + * governing the virtual-machine shutdown sequence. + * + * @author Mark Reinhold + * @since 1.3 + */ + +class Shutdown { + + /* Shutdown state */ + private static final int RUNNING = 0; + private static final int HOOKS = 1; + private static final int FINALIZERS = 2; + private static int state = RUNNING; + + /* Should we run all finalizers upon exit? */ + static volatile boolean runFinalizersOnExit = false; + + // The system shutdown hooks are registered with a predefined slot. + // The list of shutdown hooks is as follows: + // (0) Console restore hook + // (1) Application hooks + // (2) DeleteOnExit hook + private static final int MAX_SYSTEM_HOOKS = 10; + private static final Runnable[] hooks = new Runnable[MAX_SYSTEM_HOOKS]; + + // the index of the currently running shutdown hook to the hooks array + private static int currentRunningHook = 0; + + // [IKVM] have we registered the AppDomain.ProcessExit event handler? + private static boolean registeredProcessExit; + + /* The preceding static fields are protected by this lock */ + private static class Lock { }; + private static Object lock = new Lock(); + + /* Lock object for the native halt method */ + private static Object haltLock = new Lock(); + + /* Invoked by Runtime.runFinalizersOnExit */ + static void setRunFinalizersOnExit(boolean run) { + synchronized (lock) { + runFinalizersOnExit = run; + } + } + + private static void registerProcessExit() { + try { + // MONOBUG Mono doesn't support starting a new thread during ProcessExit + // (and application shutdown hooks are based on threads) + // see https://bugzilla.xamarin.com/show_bug.cgi?id=5650 + if (!ikvm.internal.Util.MONO) { + // AppDomain.ProcessExit has a LinkDemand, so we have to have a separate method + registerShutdownHook(); + if (false) throw new cli.System.Security.SecurityException(); + } + } + catch (cli.System.Security.SecurityException _) { + } + } + + private static void registerShutdownHook() + { + AppDomain.get_CurrentDomain().add_ProcessExit(new EventHandler(new EventHandler.Method() { + public void Invoke(Object sender, EventArgs e) { + shutdown(); + } + })); + } + + /** + * Add a new shutdown hook. Checks the shutdown state and the hook itself, + * but does not do any security checks. + * + * The registerShutdownInProgress parameter should be false except + * registering the DeleteOnExitHook since the first file may + * be added to the delete on exit list by the application shutdown + * hooks. + * + * @params slot the slot in the shutdown hook array, whose element + * will be invoked in order during shutdown + * @params registerShutdownInProgress true to allow the hook + * to be registered even if the shutdown is in progress. + * @params hook the hook to be registered + * + * @throw IllegalStateException + * if registerShutdownInProgress is false and shutdown is in progress; or + * if registerShutdownInProgress is true and the shutdown process + * already passes the given slot + */ + static void add(int slot, boolean registerShutdownInProgress, Runnable hook) { + synchronized (lock) { + if (hooks[slot] != null) + throw new InternalError("Shutdown hook at slot " + slot + " already registered"); + + if (!registerShutdownInProgress) { + if (state > RUNNING) + throw new IllegalStateException("Shutdown in progress"); + } else { + if (state > HOOKS || (state == HOOKS && slot <= currentRunningHook)) + throw new IllegalStateException("Shutdown in progress"); + } + + if (!registeredProcessExit) { + registeredProcessExit = true; + registerProcessExit(); + } + + hooks[slot] = hook; + } + } + + /* Run all registered shutdown hooks + */ + private static void runHooks() { + for (int i=0; i < MAX_SYSTEM_HOOKS; i++) { + try { + Runnable hook; + synchronized (lock) { + // acquire the lock to make sure the hook registered during + // shutdown is visible here. + currentRunningHook = i; + hook = hooks[i]; + } + if (hook != null) hook.run(); + } catch(Throwable t) { + if (t instanceof ThreadDeath) { + ThreadDeath td = (ThreadDeath)t; + throw td; + } + } + } + } + + /* The halt method is synchronized on the halt lock + * to avoid corruption of the delete-on-shutdown file list. + * It invokes the true native halt method. + */ + static void halt(int status) { + synchronized (haltLock) { + halt0(status); + } + } + + static void halt0(int status) { + cli.System.Environment.Exit(status); + } + + /* Wormhole for invoking java.lang.ref.Finalizer.runAllFinalizers */ + private static void runAllFinalizers() { /* [IKVM] Don't need to do anything here */ } + + + /* The actual shutdown sequence is defined here. + * + * If it weren't for runFinalizersOnExit, this would be simple -- we'd just + * run the hooks and then halt. Instead we need to keep track of whether + * we're running hooks or finalizers. In the latter case a finalizer could + * invoke exit(1) to cause immediate termination, while in the former case + * any further invocations of exit(n), for any n, simply stall. Note that + * if on-exit finalizers are enabled they're run iff the shutdown is + * initiated by an exit(0); they're never run on exit(n) for n != 0 or in + * response to SIGINT, SIGTERM, etc. + */ + private static void sequence() { + synchronized (lock) { + /* Guard against the possibility of a daemon thread invoking exit + * after DestroyJavaVM initiates the shutdown sequence + */ + if (state != HOOKS) return; + } + runHooks(); + boolean rfoe; + synchronized (lock) { + state = FINALIZERS; + rfoe = runFinalizersOnExit; + } + if (rfoe) runAllFinalizers(); + } + + + /* Invoked by Runtime.exit, which does all the security checks. + * Also invoked by handlers for system-provided termination events, + * which should pass a nonzero status code. + */ + static void exit(int status) { + boolean runMoreFinalizers = false; + synchronized (lock) { + if (status != 0) runFinalizersOnExit = false; + switch (state) { + case RUNNING: /* Initiate shutdown */ + state = HOOKS; + break; + case HOOKS: /* Stall and halt */ + break; + case FINALIZERS: + if (status != 0) { + /* Halt immediately on nonzero status */ + halt(status); + } else { + /* Compatibility with old behavior: + * Run more finalizers and then halt + */ + runMoreFinalizers = runFinalizersOnExit; + } + break; + } + } + if (runMoreFinalizers) { + runAllFinalizers(); + halt(status); + } + synchronized (Shutdown.class) { + /* Synchronize on the class object, causing any other thread + * that attempts to initiate shutdown to stall indefinitely + */ + sequence(); + halt(status); + } + } + + + /* Invoked by the JNI DestroyJavaVM procedure when the last non-daemon + * thread has finished. Unlike the exit method, this method does not + * actually halt the VM. + */ + static void shutdown() { + synchronized (lock) { + switch (state) { + case RUNNING: /* Initiate shutdown */ + state = HOOKS; + break; + case HOOKS: /* Stall and then return */ + case FINALIZERS: + break; + } + } + // [IKVM] We don't block here, because we're being called + // from the AppDomain.ProcessExit event and we don't want to + // deadlock with the thread that called exit. + // Note that our JNI DestroyJavaVM implementation doesn't + // call this method. + if (Monitor.TryEnter(Shutdown.class)) { + try { + sequence(); + } finally { + Monitor.Exit(Shutdown.class); + } + } + } + +} diff --git a/openjdk/java/lang/StringHelper.java b/openjdk/java/lang/StringHelper.java new file mode 100644 index 0000000..de31862 --- /dev/null +++ b/openjdk/java/lang/StringHelper.java @@ -0,0 +1,2727 @@ +/* + * Copyright (c) 1994, 2013, 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 java.lang; + +import java.io.ObjectStreamField; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Formatter; +import java.util.Locale; +import java.util.Objects; +import java.util.StringJoiner; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +/** + * The {@code String} class represents character strings. All + * string literals in Java programs, such as {@code "abc"}, are + * implemented as instances of this class. + *

+ * Strings are constant; their values cannot be changed after they + * are created. String buffers support mutable strings. + * Because String objects are immutable they can be shared. For example: + *

+ *     String str = "abc";
+ * 

+ * is equivalent to: + *

+ *     char data[] = {'a', 'b', 'c'};
+ *     String str = new String(data);
+ * 

+ * Here are some more examples of how strings can be used: + *

+ *     System.out.println("abc");
+ *     String cde = "cde";
+ *     System.out.println("abc" + cde);
+ *     String c = "abc".substring(2,3);
+ *     String d = cde.substring(1, 2);
+ * 
+ *

+ * The class {@code String} includes methods for examining + * individual characters of the sequence, for comparing strings, for + * searching strings, for extracting substrings, and for creating a + * copy of a string with all characters translated to uppercase or to + * lowercase. Case mapping is based on the Unicode Standard version + * specified by the {@link java.lang.Character Character} class. + *

+ * The Java language provides special support for the string + * concatenation operator ( + ), and for conversion of + * other objects to strings. String concatenation is implemented + * through the {@code StringBuilder}(or {@code StringBuffer}) + * class and its {@code append} method. + * String conversions are implemented through the method + * {@code toString}, defined by {@code Object} and + * inherited by all classes in Java. For additional information on + * string concatenation and conversion, see Gosling, Joy, and Steele, + * The Java Language Specification. + * + *

Unless otherwise noted, passing a null argument to a constructor + * or method in this class will cause a {@link NullPointerException} to be + * thrown. + * + *

A {@code String} represents a string in the UTF-16 format + * in which supplementary characters are represented by surrogate + * pairs (see the section Unicode + * Character Representations in the {@code Character} class for + * more information). + * Index values refer to {@code char} code units, so a supplementary + * character uses two positions in a {@code String}. + *

The {@code String} class provides methods for dealing with + * Unicode code points (i.e., characters), in addition to those for + * dealing with Unicode code units (i.e., {@code char} values). + * + * @author Lee Boynton + * @author Arthur van Hoff + * @author Martin Buchholz + * @author Ulf Zibis + * @see java.lang.Object#toString() + * @see java.lang.StringBuffer + * @see java.lang.StringBuilder + * @see java.nio.charset.Charset + * @since JDK1.0 + */ + +final class StringHelper +{ + /** + * Allocates a new {@code String} that contains characters from a subarray + * of the Unicode code point array + * argument. The {@code offset} argument is the index of the first code + * point of the subarray and the {@code count} argument specifies the + * length of the subarray. The contents of the subarray are converted to + * {@code char}s; subsequent modification of the {@code int} array does not + * affect the newly created string. + * + * @param codePoints + * Array that is the source of Unicode code points + * + * @param offset + * The initial offset + * + * @param count + * The length + * + * @throws IllegalArgumentException + * If any invalid Unicode code point is found in {@code + * codePoints} + * + * @throws IndexOutOfBoundsException + * If the {@code offset} and {@code count} arguments index + * characters outside the bounds of the {@code codePoints} array + * + * @since 1.5 + */ + static String NewString(int[] codePoints, int offset, int count) { + if (offset < 0) { + throw new StringIndexOutOfBoundsException(offset); + } + if (count < 0) { + throw new StringIndexOutOfBoundsException(count); + } + // Note: offset or count might be near -1>>>1. + if (offset > codePoints.length - count) { + throw new StringIndexOutOfBoundsException(offset + count); + } + + final int end = offset + count; + + // Pass 1: Compute precise size of char[] + int n = count; + for (int i = offset; i < end; i++) { + int c = codePoints[i]; + if (Character.isBmpCodePoint(c)) + continue; + else if (Character.isValidCodePoint(c)) + n++; + else throw new IllegalArgumentException(Integer.toString(c)); + } + + // Pass 2: Allocate and fill in char[] + final char[] v = new char[n]; + + for (int i = offset, j = 0; i < end; i++, j++) { + int c = codePoints[i]; + if (Character.isBmpCodePoint(c)) + v[j] = (char)c; + else + Character.toSurrogates(c, v, j++); + } + + return new String(v); + } + + /** + * Allocates a new {@code String} constructed from a subarray of an array + * of 8-bit integer values. + * + *

The {@code offset} argument is the index of the first byte of the + * subarray, and the {@code count} argument specifies the length of the + * subarray. + * + *

Each {@code byte} in the subarray is converted to a {@code char} as + * specified in the method above. + * + * @deprecated This method does not properly convert bytes into characters. + * As of JDK 1.1, the preferred way to do this is via the + * {@code String} constructors that take a {@link + * java.nio.charset.Charset}, charset name, or that use the platform's + * default charset. + * + * @param ascii + * The bytes to be converted to characters + * + * @param hibyte + * The top 8 bits of each 16-bit Unicode code unit + * + * @param offset + * The initial offset + * @param count + * The length + * + * @throws IndexOutOfBoundsException + * If the {@code offset} or {@code count} argument is invalid + * + * @see #String(byte[], int) + * @see #String(byte[], int, int, java.lang.String) + * @see #String(byte[], int, int, java.nio.charset.Charset) + * @see #String(byte[], int, int) + * @see #String(byte[], java.lang.String) + * @see #String(byte[], java.nio.charset.Charset) + * @see #String(byte[]) + */ + @Deprecated + static String NewString(byte ascii[], int hibyte, int offset, int count) { + checkBounds(ascii, offset, count); + char value[] = new char[count]; + + if (hibyte == 0) { + for (int i = count; i-- > 0;) { + value[i] = (char)(ascii[i + offset] & 0xff); + } + } else { + hibyte <<= 8; + for (int i = count; i-- > 0;) { + value[i] = (char)(hibyte | (ascii[i + offset] & 0xff)); + } + } + return new String(value, 0, count); + } + + /** + * Allocates a new {@code String} containing characters constructed from + * an array of 8-bit integer values. Each character cin the + * resulting string is constructed from the corresponding component + * b in the byte array such that: + * + *

+     *     c == (char)(((hibyte & 0xff) << 8)
+     *                         | (b & 0xff))
+     * 
+ * + * @deprecated This method does not properly convert bytes into + * characters. As of JDK 1.1, the preferred way to do this is via the + * {@code String} constructors that take a {@link + * java.nio.charset.Charset}, charset name, or that use the platform's + * default charset. + * + * @param ascii + * The bytes to be converted to characters + * + * @param hibyte + * The top 8 bits of each 16-bit Unicode code unit + * + * @see #String(byte[], int, int, java.lang.String) + * @see #String(byte[], int, int, java.nio.charset.Charset) + * @see #String(byte[], int, int) + * @see #String(byte[], java.lang.String) + * @see #String(byte[], java.nio.charset.Charset) + * @see #String(byte[]) + */ + @Deprecated + static String NewString(byte ascii[], int hibyte) { + return NewString(ascii, hibyte, 0, ascii.length); + } + + /* Common private utility method used to bounds check the byte array + * and requested offset & length values used by the String(byte[],..) + * constructors. + */ + private static void checkBounds(byte[] bytes, int offset, int length) { + if (length < 0) + throw new StringIndexOutOfBoundsException(length); + if (offset < 0) + throw new StringIndexOutOfBoundsException(offset); + if (offset > bytes.length - length) + throw new StringIndexOutOfBoundsException(offset + length); + } + + /** + * Constructs a new {@code String} by decoding the specified subarray of + * bytes using the specified charset. The length of the new {@code String} + * is a function of the charset, and hence may not be equal to the length + * of the subarray. + * + *

The behavior of this constructor when the given bytes are not valid + * in the given charset is unspecified. The {@link + * java.nio.charset.CharsetDecoder} class should be used when more control + * over the decoding process is required. + * + * @param bytes + * The bytes to be decoded into characters + * + * @param offset + * The index of the first byte to decode + * + * @param length + * The number of bytes to decode + + * @param charsetName + * The name of a supported {@linkplain java.nio.charset.Charset + * charset} + * + * @throws UnsupportedEncodingException + * If the named charset is not supported + * + * @throws IndexOutOfBoundsException + * If the {@code offset} and {@code length} arguments index + * characters outside the bounds of the {@code bytes} array + * + * @since JDK1.1 + */ + static String NewString(byte bytes[], int offset, int length, String charsetName) + throws UnsupportedEncodingException { + if (charsetName == null) + throw new NullPointerException("charsetName"); + checkBounds(bytes, offset, length); + char[] v = StringCoding.decode(charsetName, bytes, offset, length); + return new String(v); + } + + /** + * Constructs a new {@code String} by decoding the specified subarray of + * bytes using the specified {@linkplain java.nio.charset.Charset charset}. + * The length of the new {@code String} is a function of the charset, and + * hence may not be equal to the length of the subarray. + * + *

This method always replaces malformed-input and unmappable-character + * sequences with this charset's default replacement string. The {@link + * java.nio.charset.CharsetDecoder} class should be used when more control + * over the decoding process is required. + * + * @param bytes + * The bytes to be decoded into characters + * + * @param offset + * The index of the first byte to decode + * + * @param length + * The number of bytes to decode + * + * @param charset + * The {@linkplain java.nio.charset.Charset charset} to be used to + * decode the {@code bytes} + * + * @throws IndexOutOfBoundsException + * If the {@code offset} and {@code length} arguments index + * characters outside the bounds of the {@code bytes} array + * + * @since 1.6 + */ + static String NewString(byte bytes[], int offset, int length, Charset charset) { + if (charset == null) + throw new NullPointerException("charset"); + checkBounds(bytes, offset, length); + char[] v = StringCoding.decode(charset, bytes, offset, length); + return new String(v); + } + + /** + * Constructs a new {@code String} by decoding the specified array of bytes + * using the specified {@linkplain java.nio.charset.Charset charset}. The + * length of the new {@code String} is a function of the charset, and hence + * may not be equal to the length of the byte array. + * + *

The behavior of this constructor when the given bytes are not valid + * in the given charset is unspecified. The {@link + * java.nio.charset.CharsetDecoder} class should be used when more control + * over the decoding process is required. + * + * @param bytes + * The bytes to be decoded into characters + * + * @param charsetName + * The name of a supported {@linkplain java.nio.charset.Charset + * charset} + * + * @throws UnsupportedEncodingException + * If the named charset is not supported + * + * @since JDK1.1 + */ + static String NewString(byte bytes[], String charsetName) + throws UnsupportedEncodingException { + return NewString(bytes, 0, bytes.length, charsetName); + } + + /** + * Constructs a new {@code String} by decoding the specified array of + * bytes using the specified {@linkplain java.nio.charset.Charset charset}. + * The length of the new {@code String} is a function of the charset, and + * hence may not be equal to the length of the byte array. + * + *

This method always replaces malformed-input and unmappable-character + * sequences with this charset's default replacement string. The {@link + * java.nio.charset.CharsetDecoder} class should be used when more control + * over the decoding process is required. + * + * @param bytes + * The bytes to be decoded into characters + * + * @param charset + * The {@linkplain java.nio.charset.Charset charset} to be used to + * decode the {@code bytes} + * + * @since 1.6 + */ + static String NewString(byte bytes[], Charset charset) { + return NewString(bytes, 0, bytes.length, charset); + } + + /** + * Constructs a new {@code String} by decoding the specified subarray of + * bytes using the platform's default charset. The length of the new + * {@code String} is a function of the charset, and hence may not be equal + * to the length of the subarray. + * + *

The behavior of this constructor when the given bytes are not valid + * in the default charset is unspecified. The {@link + * java.nio.charset.CharsetDecoder} class should be used when more control + * over the decoding process is required. + * + * @param bytes + * The bytes to be decoded into characters + * + * @param offset + * The index of the first byte to decode + * + * @param length + * The number of bytes to decode + * + * @throws IndexOutOfBoundsException + * If the {@code offset} and the {@code length} arguments index + * characters outside the bounds of the {@code bytes} array + * + * @since JDK1.1 + */ + static String NewString(byte bytes[], int offset, int length) { + checkBounds(bytes, offset, length); + char[] v = StringCoding.decode(bytes, offset, length); + return new String(v); + } + + /** + * Constructs a new {@code String} by decoding the specified array of bytes + * using the platform's default charset. The length of the new {@code + * String} is a function of the charset, and hence may not be equal to the + * length of the byte array. + * + *

The behavior of this constructor when the given bytes are not valid + * in the default charset is unspecified. The {@link + * java.nio.charset.CharsetDecoder} class should be used when more control + * over the decoding process is required. + * + * @param bytes + * The bytes to be decoded into characters + * + * @since JDK1.1 + */ + static String NewString(byte bytes[]) { + return NewString(bytes, 0, bytes.length); + } + + /** + * Allocates a new string that contains the sequence of characters + * currently contained in the string buffer argument. The contents of the + * string buffer are copied; subsequent modification of the string buffer + * does not affect the newly created string. + * + * @param buffer + * A {@code StringBuffer} + */ + static String NewString(StringBuffer buffer) { + return buffer.toString(); + } + + /** + * Allocates a new string that contains the sequence of characters + * currently contained in the string builder argument. The contents of the + * string builder are copied; subsequent modification of the string builder + * does not affect the newly created string. + * + *

This constructor is provided to ease migration to {@code + * StringBuilder}. Obtaining a string from a string builder via the {@code + * toString} method is likely to run faster and is generally preferred. + * + * @param builder + * A {@code StringBuilder} + * + * @since 1.5 + */ + static String NewString(StringBuilder builder) { + return builder.toString(); + } + + /** + * Returns the character (Unicode code point) at the specified + * index. The index refers to {@code char} values + * (Unicode code units) and ranges from {@code 0} to + * {@link #length()}{@code - 1}. + * + *

If the {@code char} value specified at the given index + * is in the high-surrogate range, the following index is less + * than the length of this {@code String}, and the + * {@code char} value at the following index is in the + * low-surrogate range, then the supplementary code point + * corresponding to this surrogate pair is returned. Otherwise, + * the {@code char} value at the given index is returned. + * + * @param index the index to the {@code char} values + * @return the code point value of the character at the + * {@code index} + * @exception IndexOutOfBoundsException if the {@code index} + * argument is negative or not less than the length of this + * string. + * @since 1.5 + */ + static int codePointAt(String _this, int index) { + if ((index < 0) || (index >= _this.length())) { + throw new StringIndexOutOfBoundsException(index); + } + char c1 = _this.charAt(index++); + if (Character.isHighSurrogate(c1)) { + if (index < _this.length()) { + char c2 = _this.charAt(index); + if (Character.isLowSurrogate(c2)) { + return Character.toCodePoint(c1, c2); + } + } + } + return c1; + } + + /** + * Returns the character (Unicode code point) before the specified + * index. The index refers to {@code char} values + * (Unicode code units) and ranges from {@code 1} to {@link + * CharSequence#length() length}. + * + *

If the {@code char} value at {@code (index - 1)} + * is in the low-surrogate range, {@code (index - 2)} is not + * negative, and the {@code char} value at {@code (index - + * 2)} is in the high-surrogate range, then the + * supplementary code point value of the surrogate pair is + * returned. If the {@code char} value at {@code index - + * 1} is an unpaired low-surrogate or a high-surrogate, the + * surrogate value is returned. + * + * @param index the index following the code point that should be returned + * @return the Unicode code point value before the given index. + * @exception IndexOutOfBoundsException if the {@code index} + * argument is less than 1 or greater than the length + * of this string. + * @since 1.5 + */ + static int codePointBefore(String _this, int index) { + int i = index - 1; + if ((i < 0) || (i >= _this.length())) { + throw new StringIndexOutOfBoundsException(index); + } + char c2 = _this.charAt(--index); + if (Character.isLowSurrogate(c2)) { + if (index > 0) { + char c1 = _this.charAt(--index); + if (Character.isHighSurrogate(c1)) { + return Character.toCodePoint(c1, c2); + } + } + } + return c2; + } + + /** + * Returns the number of Unicode code points in the specified text + * range of this {@code String}. The text range begins at the + * specified {@code beginIndex} and extends to the + * {@code char} at index {@code endIndex - 1}. Thus the + * length (in {@code char}s) of the text range is + * {@code endIndex-beginIndex}. Unpaired surrogates within + * the text range count as one code point each. + * + * @param beginIndex the index to the first {@code char} of + * the text range. + * @param endIndex the index after the last {@code char} of + * the text range. + * @return the number of Unicode code points in the specified text + * range + * @exception IndexOutOfBoundsException if the + * {@code beginIndex} is negative, or {@code endIndex} + * is larger than the length of this {@code String}, or + * {@code beginIndex} is larger than {@code endIndex}. + * @since 1.5 + */ + static int codePointCount(String _this, int beginIndex, int endIndex) { + if (beginIndex < 0 || endIndex > _this.length() || beginIndex > endIndex) { + throw new IndexOutOfBoundsException(); + } + int n = 0; + for (int i = beginIndex; i < endIndex; ) { + n++; + if (Character.isHighSurrogate(_this.charAt(i++))) { + if (i < endIndex && Character.isLowSurrogate(_this.charAt(i))) { + i++; + } + } + } + return n; + } + + /** + * Returns the index within this {@code String} that is + * offset from the given {@code index} by + * {@code codePointOffset} code points. Unpaired surrogates + * within the text range given by {@code index} and + * {@code codePointOffset} count as one code point each. + * + * @param index the index to be offset + * @param codePointOffset the offset in code points + * @return the index within this {@code String} + * @exception IndexOutOfBoundsException if {@code index} + * is negative or larger then the length of this + * {@code String}, or if {@code codePointOffset} is positive + * and the substring starting with {@code index} has fewer + * than {@code codePointOffset} code points, + * or if {@code codePointOffset} is negative and the substring + * before {@code index} has fewer than the absolute value + * of {@code codePointOffset} code points. + * @since 1.5 + */ + static int offsetByCodePoints(String _this, int index, int codePointOffset) { + int count = _this.length(); + if (index < 0 || index > count) { + throw new IndexOutOfBoundsException(); + } + int x = index; + if (codePointOffset >= 0) { + int limit = count; + int i; + for (i = 0; x < limit && i < codePointOffset; i++) { + if (Character.isHighSurrogate(_this.charAt(x++))) { + if (x < limit && Character.isLowSurrogate(_this.charAt(x))) { + x++; + } + } + } + if (i < codePointOffset) { + throw new IndexOutOfBoundsException(); + } + } else { + int i; + for (i = codePointOffset; x > 0 && i < 0; i++) { + if (Character.isLowSurrogate(_this.charAt(--x))) { + if (x > 0 && Character.isHighSurrogate(_this.charAt(x-1))) { + x--; + } + } + } + if (i < 0) { + throw new IndexOutOfBoundsException(); + } + } + return x; + } + + /** + * Copy characters from this string into dst starting at dstBegin. + * This method doesn't perform any range checking. + */ + static void getChars(String _this, char dst[], int dstBegin) { + _this.getChars(0, _this.length(), dst, dstBegin); + } + + /** + * Copies characters from this string into the destination character + * array. + *

+ * The first character to be copied is at index {@code srcBegin}; + * the last character to be copied is at index {@code srcEnd-1} + * (thus the total number of characters to be copied is + * {@code srcEnd-srcBegin}). The characters are copied into the + * subarray of {@code dst} starting at index {@code dstBegin} + * and ending at index: + *

+     *     dstbegin + (srcEnd-srcBegin) - 1
+     * 
+ * + * @param srcBegin index of the first character in the string + * to copy. + * @param srcEnd index after the last character in the string + * to copy. + * @param dst the destination array. + * @param dstBegin the start offset in the destination array. + * @exception IndexOutOfBoundsException If any of the following + * is true: + *
  • {@code srcBegin} is negative. + *
  • {@code srcBegin} is greater than {@code srcEnd} + *
  • {@code srcEnd} is greater than the length of this + * string + *
  • {@code dstBegin} is negative + *
  • {@code dstBegin+(srcEnd-srcBegin)} is larger than + * {@code dst.length}
+ */ + static void getChars(cli.System.String _this, int srcBegin, int srcEnd, char dst[], int dstBegin) { + if (srcBegin < 0) { + throw new StringIndexOutOfBoundsException(srcBegin); + } + if (srcEnd > _this.get_Length()) { + throw new StringIndexOutOfBoundsException(srcEnd); + } + if (srcBegin > srcEnd) { + throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); + } + _this.CopyTo(srcBegin, dst, dstBegin, srcEnd - srcBegin); + } + + /** + * Copies characters from this string into the destination byte array. Each + * byte receives the 8 low-order bits of the corresponding character. The + * eight high-order bits of each character are not copied and do not + * participate in the transfer in any way. + * + *

The first character to be copied is at index {@code srcBegin}; the + * last character to be copied is at index {@code srcEnd-1}. The total + * number of characters to be copied is {@code srcEnd-srcBegin}. The + * characters, converted to bytes, are copied into the subarray of {@code + * dst} starting at index {@code dstBegin} and ending at index: + * + *

+     *     dstbegin + (srcEnd-srcBegin) - 1
+     * 
+ * + * @deprecated This method does not properly convert characters into + * bytes. As of JDK 1.1, the preferred way to do this is via the + * {@link #getBytes()} method, which uses the platform's default charset. + * + * @param srcBegin + * Index of the first character in the string to copy + * + * @param srcEnd + * Index after the last character in the string to copy + * + * @param dst + * The destination array + * + * @param dstBegin + * The start offset in the destination array + * + * @throws IndexOutOfBoundsException + * If any of the following is true: + *
    + *
  • {@code srcBegin} is negative + *
  • {@code srcBegin} is greater than {@code srcEnd} + *
  • {@code srcEnd} is greater than the length of this String + *
  • {@code dstBegin} is negative + *
  • {@code dstBegin+(srcEnd-srcBegin)} is larger than {@code + * dst.length} + *
+ */ + @Deprecated + static void getBytes(String _this, int srcBegin, int srcEnd, byte dst[], int dstBegin) { + if (srcBegin < 0) { + throw new StringIndexOutOfBoundsException(srcBegin); + } + if (srcEnd > _this.length()) { + throw new StringIndexOutOfBoundsException(srcEnd); + } + if (srcBegin > srcEnd) { + throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); + } + Objects.requireNonNull(dst); + + int j = dstBegin; + int n = srcEnd; + int i = srcBegin; + + while (i < n) { + dst[j++] = (byte)_this.charAt(i++); + } + } + + /** + * Encodes this {@code String} into a sequence of bytes using the named + * charset, storing the result into a new byte array. + * + *

The behavior of this method when this string cannot be encoded in + * the given charset is unspecified. The {@link + * java.nio.charset.CharsetEncoder} class should be used when more control + * over the encoding process is required. + * + * @param charsetName + * The name of a supported {@linkplain java.nio.charset.Charset + * charset} + * + * @return The resultant byte array + * + * @throws UnsupportedEncodingException + * If the named charset is not supported + * + * @since JDK1.1 + */ + static byte[] getBytes(String _this, String charsetName) + throws UnsupportedEncodingException { + if (charsetName == null) throw new NullPointerException(); + char[] value = _this.toCharArray(); + return StringCoding.encode(charsetName, value, 0, value.length); + } + + /** + * Encodes this {@code String} into a sequence of bytes using the given + * {@linkplain java.nio.charset.Charset charset}, storing the result into a + * new byte array. + * + *

This method always replaces malformed-input and unmappable-character + * sequences with this charset's default replacement byte array. The + * {@link java.nio.charset.CharsetEncoder} class should be used when more + * control over the encoding process is required. + * + * @param charset + * The {@linkplain java.nio.charset.Charset} to be used to encode + * the {@code String} + * + * @return The resultant byte array + * + * @since 1.6 + */ + static byte[] getBytes(String _this, Charset charset) { + if (charset == null) throw new NullPointerException(); + char[] value = _this.toCharArray(); + return StringCoding.encode(charset, value, 0, value.length); + } + + /** + * Encodes this {@code String} into a sequence of bytes using the + * platform's default charset, storing the result into a new byte array. + * + *

The behavior of this method when this string cannot be encoded in + * the default charset is unspecified. The {@link + * java.nio.charset.CharsetEncoder} class should be used when more control + * over the encoding process is required. + * + * @return The resultant byte array + * + * @since JDK1.1 + */ + static byte[] getBytes(String _this) { + char[] value = _this.toCharArray(); + return StringCoding.encode(value, 0, value.length); + } + + /** + * Compares this string to the specified {@code StringBuffer}. The result + * is {@code true} if and only if this {@code String} represents the same + * sequence of characters as the specified {@code StringBuffer}. This method + * synchronizes on the {@code StringBuffer}. + * + * @param sb + * The {@code StringBuffer} to compare this {@code String} against + * + * @return {@code true} if this {@code String} represents the same + * sequence of characters as the specified {@code StringBuffer}, + * {@code false} otherwise + * + * @since 1.4 + */ + static boolean contentEquals(String _this, StringBuffer sb) { + return contentEquals(_this, (CharSequence)sb); + } + + private static boolean nonSyncContentEquals(String _this, AbstractStringBuilder sb) { + char v2[] = sb.getValue(); + int n = _this.length(); + if (n != sb.length()) { + return false; + } + for (int i = 0; i < n; i++) { + if (_this.charAt(i) != v2[i]) { + return false; + } + } + return true; + } + + /** + * Compares this string to the specified {@code CharSequence}. The + * result is {@code true} if and only if this {@code String} represents the + * same sequence of char values as the specified sequence. Note that if the + * {@code CharSequence} is a {@code StringBuffer} then the method + * synchronizes on it. + * + * @param cs + * The sequence to compare this {@code String} against + * + * @return {@code true} if this {@code String} represents the same + * sequence of char values as the specified sequence, {@code + * false} otherwise + * + * @since 1.5 + */ + static boolean contentEquals(String _this, CharSequence cs) { + // Argument is a StringBuffer, StringBuilder + if (cs instanceof AbstractStringBuilder) { + if (cs instanceof StringBuffer) { + synchronized(cs) { + return nonSyncContentEquals(_this, (AbstractStringBuilder)cs); + } + } else { + return nonSyncContentEquals(_this, (AbstractStringBuilder)cs); + } + } + // Argument is a String + if (cs instanceof String) { + return _this.equals(cs); + } + // Argument is a generic CharSequence + int n = _this.length(); + if (n != cs.length()) { + return false; + } + for (int i = 0; i < n; i++) { + if (_this.charAt(i) != cs.charAt(i)) { + return false; + } + } + return true; + } + + /** + * Compares this {@code String} to another {@code String}, ignoring case + * considerations. Two strings are considered equal ignoring case if they + * are of the same length and corresponding characters in the two strings + * are equal ignoring case. + * + *

Two characters {@code c1} and {@code c2} are considered the same + * ignoring case if at least one of the following is true: + *

    + *
  • The two characters are the same (as compared by the + * {@code ==} operator) + *
  • Applying the method {@link + * java.lang.Character#toUpperCase(char)} to each character + * produces the same result + *
  • Applying the method {@link + * java.lang.Character#toLowerCase(char)} to each character + * produces the same result + *
+ * + * @param anotherString + * The {@code String} to compare this {@code String} against + * + * @return {@code true} if the argument is not {@code null} and it + * represents an equivalent {@code String} ignoring case; {@code + * false} otherwise + * + * @see #equals(Object) + */ + static boolean equalsIgnoreCase(String _this, String anotherString) { + return (_this == anotherString) ? true + : (anotherString != null) + && (anotherString.length() == _this.length()) + && regionMatches(_this, true, 0, anotherString, 0, _this.length()); + } + + /** + * Compares two strings lexicographically. + * The comparison is based on the Unicode value of each character in + * the strings. The character sequence represented by this + * {@code String} object is compared lexicographically to the + * character sequence represented by the argument string. The result is + * a negative integer if this {@code String} object + * lexicographically precedes the argument string. The result is a + * positive integer if this {@code String} object lexicographically + * follows the argument string. The result is zero if the strings + * are equal; {@code compareTo} returns {@code 0} exactly when + * the {@link #equals(Object)} method would return {@code true}. + *

+ * This is the definition of lexicographic ordering. If two strings are + * different, then either they have different characters at some index + * that is a valid index for both strings, or their lengths are different, + * or both. If they have different characters at one or more index + * positions, let k be the smallest such index; then the string + * whose character at position k has the smaller value, as + * determined by using the < operator, lexicographically precedes the + * other string. In this case, {@code compareTo} returns the + * difference of the two character values at position {@code k} in + * the two string -- that is, the value: + *

+     * this.charAt(k)-anotherString.charAt(k)
+     * 
+ * If there is no index position at which they differ, then the shorter + * string lexicographically precedes the longer string. In this case, + * {@code compareTo} returns the difference of the lengths of the + * strings -- that is, the value: + *
+     * this.length()-anotherString.length()
+     * 
+ * + * @param anotherString the {@code String} to be compared. + * @return the value {@code 0} if the argument string is equal to + * this string; a value less than {@code 0} if this string + * is lexicographically less than the string argument; and a + * value greater than {@code 0} if this string is + * lexicographically greater than the string argument. + */ + static int compareTo(String _this, String anotherString) { + int len = Math.min(_this.length(), anotherString.length()); + for (int i = 0; i < len; i++) + { + int diff = _this.charAt(i) - anotherString.charAt(i); + if (diff != 0) + { + return diff; + } + } + return _this.length() - anotherString.length(); + } + + /** + * Compares two strings lexicographically, ignoring case + * differences. This method returns an integer whose sign is that of + * calling {@code compareTo} with normalized versions of the strings + * where case differences have been eliminated by calling + * {@code Character.toLowerCase(Character.toUpperCase(character))} on + * each character. + *

+ * Note that this method does not take locale into account, + * and will result in an unsatisfactory ordering for certain locales. + * The java.text package provides collators to allow + * locale-sensitive ordering. + * + * @param str the {@code String} to be compared. + * @return a negative integer, zero, or a positive integer as the + * specified String is greater than, equal to, or less + * than this String, ignoring case considerations. + * @see java.text.Collator#compare(String, String) + * @since 1.2 + */ + static int compareToIgnoreCase(String _this, String str) { + return String.CASE_INSENSITIVE_ORDER.compare(_this, str); + } + + /** + * Tests if two string regions are equal. + *

+ * A substring of this {@code String} object is compared to a substring + * of the argument other. The result is true if these substrings + * represent identical character sequences. The substring of this + * {@code String} object to be compared begins at index {@code toffset} + * and has length {@code len}. The substring of other to be compared + * begins at index {@code ooffset} and has length {@code len}. The + * result is {@code false} if and only if at least one of the following + * is true: + *

  • {@code toffset} is negative. + *
  • {@code ooffset} is negative. + *
  • {@code toffset+len} is greater than the length of this + * {@code String} object. + *
  • {@code ooffset+len} is greater than the length of the other + * argument. + *
  • There is some nonnegative integer k less than {@code len} + * such that: + * {@code this.charAt(toffset + }k{@code ) != other.charAt(ooffset + } + * k{@code )} + *
+ * + * @param toffset the starting offset of the subregion in this string. + * @param other the string argument. + * @param ooffset the starting offset of the subregion in the string + * argument. + * @param len the number of characters to compare. + * @return {@code true} if the specified subregion of this string + * exactly matches the specified subregion of the string argument; + * {@code false} otherwise. + */ + static boolean regionMatches(String _this, int toffset, String other, int ooffset, + int len) { + int to = toffset; + int po = ooffset; + // Note: toffset, ooffset, or len might be near -1>>>1. + if ((ooffset < 0) || (toffset < 0) + || (toffset > (long)_this.length() - len) + || (ooffset > (long)other.length() - len)) { + return false; + } + while (len-- > 0) { + if (_this.charAt(to++) != other.charAt(po++)) { + return false; + } + } + return true; + } + + /** + * Tests if two string regions are equal. + *

+ * A substring of this {@code String} object is compared to a substring + * of the argument {@code other}. The result is {@code true} if these + * substrings represent character sequences that are the same, ignoring + * case if and only if {@code ignoreCase} is true. The substring of + * this {@code String} object to be compared begins at index + * {@code toffset} and has length {@code len}. The substring of + * {@code other} to be compared begins at index {@code ooffset} and + * has length {@code len}. The result is {@code false} if and only if + * at least one of the following is true: + *

  • {@code toffset} is negative. + *
  • {@code ooffset} is negative. + *
  • {@code toffset+len} is greater than the length of this + * {@code String} object. + *
  • {@code ooffset+len} is greater than the length of the other + * argument. + *
  • {@code ignoreCase} is {@code false} and there is some nonnegative + * integer k less than {@code len} such that: + *
    +     * this.charAt(toffset+k) != other.charAt(ooffset+k)
    +     * 
    + *
  • {@code ignoreCase} is {@code true} and there is some nonnegative + * integer k less than {@code len} such that: + *
    +     * Character.toLowerCase(this.charAt(toffset+k)) !=
    +     Character.toLowerCase(other.charAt(ooffset+k))
    +     * 
    + * and: + *
    +     * Character.toUpperCase(this.charAt(toffset+k)) !=
    +     *         Character.toUpperCase(other.charAt(ooffset+k))
    +     * 
    + *
+ * + * @param ignoreCase if {@code true}, ignore case when comparing + * characters. + * @param toffset the starting offset of the subregion in this + * string. + * @param other the string argument. + * @param ooffset the starting offset of the subregion in the string + * argument. + * @param len the number of characters to compare. + * @return {@code true} if the specified subregion of this string + * matches the specified subregion of the string argument; + * {@code false} otherwise. Whether the matching is exact + * or case insensitive depends on the {@code ignoreCase} + * argument. + */ + static boolean regionMatches(String _this, boolean ignoreCase, int toffset, + String other, int ooffset, int len) { + int to = toffset; + int po = ooffset; + // Note: toffset, ooffset, or len might be near -1>>>1. + if ((ooffset < 0) || (toffset < 0) + || (toffset > (long)_this.length() - len) + || (ooffset > (long)other.length() - len)) { + return false; + } + while (len-- > 0) { + char c1 = _this.charAt(to++); + char c2 = other.charAt(po++); + if (c1 == c2) { + continue; + } + if (ignoreCase) { + // If characters don't match but case may be ignored, + // try converting both characters to uppercase. + // If the results match, then the comparison scan should + // continue. + char u1 = Character.toUpperCase(c1); + char u2 = Character.toUpperCase(c2); + if (u1 == u2) { + continue; + } + // Unfortunately, conversion to uppercase does not work properly + // for the Georgian alphabet, which has strange rules about case + // conversion. So we need to make one last check before + // exiting. + if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) { + continue; + } + } + return false; + } + return true; + } + + /** + * Returns a hash code for this string. The hash code for a + * {@code String} object is computed as + *
+     * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
+     * 
+ * using {@code int} arithmetic, where {@code s[i]} is the + * ith character of the string, {@code n} is the length of + * the string, and {@code ^} indicates exponentiation. + * (The hash value of the empty string is zero.) + * + * @return a hash code value for this object. + */ + static int hashCode(cli.System.String _this) { + int h = 0; + // NOTE having the get_Length in the for condition is actually faster than hoisting it, + // the CLR JIT recognizes this pattern and optimizes the array bounds check in get_Chars. + for (int i = 0; i < _this.get_Length(); i++) + { + h = h * 31 + _this.get_Chars(i); + } + return h; + } + + /** + * Returns the index within this string of the first occurrence of + * the specified character. If a character with value + * {@code ch} occurs in the character sequence represented by + * this {@code String} object, then the index (in Unicode + * code units) of the first such occurrence is returned. For + * values of {@code ch} in the range from 0 to 0xFFFF + * (inclusive), this is the smallest value k such that: + *
+     * this.charAt(k) == ch
+     * 
+ * is true. For other values of {@code ch}, it is the + * smallest value k such that: + *
+     * this.codePointAt(k) == ch
+     * 
+ * is true. In either case, if no such character occurs in this + * string, then {@code -1} is returned. + * + * @param ch a character (Unicode code point). + * @return the index of the first occurrence of the character in the + * character sequence represented by this object, or + * {@code -1} if the character does not occur. + */ + static int indexOf(cli.System.String _this, int ch) { + return indexOf(_this, ch, 0); + } + + /** + * Returns the index within this string of the first occurrence of the + * specified character, starting the search at the specified index. + *

+ * If a character with value {@code ch} occurs in the + * character sequence represented by this {@code String} + * object at an index no smaller than {@code fromIndex}, then + * the index of the first such occurrence is returned. For values + * of {@code ch} in the range from 0 to 0xFFFF (inclusive), + * this is the smallest value k such that: + *

+     * (this.charAt(k) == ch) {@code &&} (k >= fromIndex)
+     * 
+ * is true. For other values of {@code ch}, it is the + * smallest value k such that: + *
+     * (this.codePointAt(k) == ch) {@code &&} (k >= fromIndex)
+     * 
+ * is true. In either case, if no such character occurs in this + * string at or after position {@code fromIndex}, then + * {@code -1} is returned. + * + *

+ * There is no restriction on the value of {@code fromIndex}. If it + * is negative, it has the same effect as if it were zero: this entire + * string may be searched. If it is greater than the length of this + * string, it has the same effect as if it were equal to the length of + * this string: {@code -1} is returned. + * + *

All indices are specified in {@code char} values + * (Unicode code units). + * + * @param ch a character (Unicode code point). + * @param fromIndex the index to start the search from. + * @return the index of the first occurrence of the character in the + * character sequence represented by this object that is greater + * than or equal to {@code fromIndex}, or {@code -1} + * if the character does not occur. + */ + static int indexOf(cli.System.String _this, int ch, int fromIndex) { + int max = _this.get_Length(); + + if (fromIndex < 0) { + fromIndex = 0; + } else if (fromIndex >= max) { + // Note: fromIndex might be near -1>>>1. + return -1; + } + + int i = fromIndex; + if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { + // handle most cases here (ch is a BMP code point or a + // negative value (invalid code point)) + for (; i < max ; i++) { + if (_this.get_Chars(i) == ch) { + return i; + } + } + return -1; + } else { + return indexOfSupplementary(_this, ch, fromIndex); + } + } + + /** + * Handles (rare) calls of indexOf with a supplementary character. + */ + private static int indexOfSupplementary(cli.System.String _this, int ch, int fromIndex) { + if (Character.isValidCodePoint(ch)) { + final char hi = Character.highSurrogate(ch); + final char lo = Character.lowSurrogate(ch); + final int max = _this.get_Length() - 1; + for (int i = fromIndex; i < max; i++) { + if (_this.get_Chars(i) == hi && _this.get_Chars(i+1) == lo) { + return i; + } + } + } + return -1; + } + + /** + * Returns the index within this string of the last occurrence of + * the specified character. For values of {@code ch} in the + * range from 0 to 0xFFFF (inclusive), the index (in Unicode code + * units) returned is the largest value k such that: + *

+     * this.charAt(k) == ch
+     * 
+ * is true. For other values of {@code ch}, it is the + * largest value k such that: + *
+     * this.codePointAt(k) == ch
+     * 
+ * is true. In either case, if no such character occurs in this + * string, then {@code -1} is returned. The + * {@code String} is searched backwards starting at the last + * character. + * + * @param ch a character (Unicode code point). + * @return the index of the last occurrence of the character in the + * character sequence represented by this object, or + * {@code -1} if the character does not occur. + */ + static int lastIndexOf(cli.System.String _this, int ch) { + return lastIndexOf(_this, ch, _this.get_Length() - 1); + } + + /** + * Returns the index within this string of the last occurrence of + * the specified character, searching backward starting at the + * specified index. For values of {@code ch} in the range + * from 0 to 0xFFFF (inclusive), the index returned is the largest + * value k such that: + *
+     * (this.charAt(k) == ch) {@code &&} (k <= fromIndex)
+     * 
+ * is true. For other values of {@code ch}, it is the + * largest value k such that: + *
+     * (this.codePointAt(k) == ch) {@code &&} (k <= fromIndex)
+     * 
+ * is true. In either case, if no such character occurs in this + * string at or before position {@code fromIndex}, then + * {@code -1} is returned. + * + *

All indices are specified in {@code char} values + * (Unicode code units). + * + * @param ch a character (Unicode code point). + * @param fromIndex the index to start the search from. There is no + * restriction on the value of {@code fromIndex}. If it is + * greater than or equal to the length of this string, it has + * the same effect as if it were equal to one less than the + * length of this string: this entire string may be searched. + * If it is negative, it has the same effect as if it were -1: + * -1 is returned. + * @return the index of the last occurrence of the character in the + * character sequence represented by this object that is less + * than or equal to {@code fromIndex}, or {@code -1} + * if the character does not occur before that point. + */ + static int lastIndexOf(cli.System.String _this, int ch, int fromIndex) { + if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { + // handle most cases here (ch is a BMP code point or a + // negative value (invalid code point)) + int i = Math.min(fromIndex, _this.get_Length() - 1); + for (; i >= 0; i--) { + if (_this.get_Chars(i) == ch) { + return i; + } + } + return -1; + } else { + return lastIndexOfSupplementary(_this, ch, fromIndex); + } + } + + /** + * Handles (rare) calls of lastIndexOf with a supplementary character. + */ + private static int lastIndexOfSupplementary(cli.System.String _this, int ch, int fromIndex) { + if (Character.isValidCodePoint(ch)) { + char hi = Character.highSurrogate(ch); + char lo = Character.lowSurrogate(ch); + int i = Math.min(fromIndex, _this.get_Length() - 2); + for (; i >= 0; i--) { + if (_this.get_Chars(i) == hi && _this.get_Chars(i+1) == lo) { + return i; + } + } + } + return -1; + } + + /** + * Returns the index within this string of the first occurrence of the + * specified substring. + * + *

The returned index is the smallest value k for which: + *

+     * this.startsWith(str, k)
+     * 
+ * If no such value of k exists, then {@code -1} is returned. + * + * @param str the substring to search for. + * @return the index of the first occurrence of the specified substring, + * or {@code -1} if there is no such occurrence. + */ + static int indexOf(String _this, String str) { + return indexOf(_this, str, 0); + } + + /** + * Returns the index within this string of the first occurrence of the + * specified substring, starting at the specified index. + * + *

The returned index is the smallest value k for which: + *

+     * k >= fromIndex {@code &&} this.startsWith(str, k)
+     * 
+ * If no such value of k exists, then {@code -1} is returned. + * + * @param str the substring to search for. + * @param fromIndex the index from which to start the search. + * @return the index of the first occurrence of the specified substring, + * starting at the specified index, + * or {@code -1} if there is no such occurrence. + */ + static int indexOf(String _this, String str, int fromIndex) { + // start by dereferencing _this, to make sure we throw a NullPointerException if _this is null + int slen = _this.length(); + int olen = str.length(); + if (olen == 0) + { + return Math.max(0, Math.min(fromIndex, slen)); + } + if (olen > slen) + { + return -1; + } + char firstChar = str.charAt(0); + // Java allows fromIndex to both below zero or above the length of the string, .NET doesn't + int index = Math.max(0, Math.min(slen, fromIndex)); + int end = slen - olen; + while (index >= 0 && index <= end) + { + if (cli.System.String.CompareOrdinal(_this, index, str, 0, olen) == 0) + { + return index; + } + index = _this.indexOf(firstChar, index + 1); + } + return -1; + } + + /** + * Code shared by String and AbstractStringBuilder to do searches. The + * source is the character array being searched, and the target + * is the string being searched for. + * + * @param source the characters being searched. + * @param sourceOffset offset of the source string. + * @param sourceCount count of the source string. + * @param target the characters being searched for. + * @param fromIndex the index to begin searching from. + */ + static int indexOf(char[] source, int sourceOffset, int sourceCount, + String target, int fromIndex) { + final int targetOffset = 0; + final int targetCount = target.length(); + if (fromIndex >= sourceCount) { + return (targetCount == 0 ? sourceCount : -1); + } + if (fromIndex < 0) { + fromIndex = 0; + } + if (targetCount == 0) { + return fromIndex; + } + + char first = target.charAt(targetOffset); + int max = sourceOffset + (sourceCount - targetCount); + + for (int i = sourceOffset + fromIndex; i <= max; i++) { + /* Look for first character. */ + if (source[i] != first) { + while (++i <= max && source[i] != first); + } + + /* Found first character, now look at the rest of v2 */ + if (i <= max) { + int j = i + 1; + int end = j + targetCount - 1; + for (int k = targetOffset + 1; j < end && source[j] + == target.charAt(k); j++, k++); + + if (j == end) { + /* Found whole string. */ + return i - sourceOffset; + } + } + } + return -1; + } + + /** + * Code shared by String and StringBuffer to do searches. The + * source is the character array being searched, and the target + * is the string being searched for. + * + * @param source the characters being searched. + * @param sourceOffset offset of the source string. + * @param sourceCount count of the source string. + * @param target the characters being searched for. + * @param targetOffset offset of the target string. + * @param targetCount count of the target string. + * @param fromIndex the index to begin searching from. + */ + static int indexOf(char[] source, int sourceOffset, int sourceCount, + char[] target, int targetOffset, int targetCount, + int fromIndex) { + if (fromIndex >= sourceCount) { + return (targetCount == 0 ? sourceCount : -1); + } + if (fromIndex < 0) { + fromIndex = 0; + } + if (targetCount == 0) { + return fromIndex; + } + + char first = target[targetOffset]; + int max = sourceOffset + (sourceCount - targetCount); + + for (int i = sourceOffset + fromIndex; i <= max; i++) { + /* Look for first character. */ + if (source[i] != first) { + while (++i <= max && source[i] != first); + } + + /* Found first character, now look at the rest of v2 */ + if (i <= max) { + int j = i + 1; + int end = j + targetCount - 1; + for (int k = targetOffset + 1; j < end && source[j] + == target[k]; j++, k++); + + if (j == end) { + /* Found whole string. */ + return i - sourceOffset; + } + } + } + return -1; + } + + /** + * Returns the index within this string of the last occurrence of the + * specified substring. The last occurrence of the empty string "" + * is considered to occur at the index value {@code this.length()}. + * + *

The returned index is the largest value k for which: + *

+     * this.startsWith(str, k)
+     * 
+ * If no such value of k exists, then {@code -1} is returned. + * + * @param str the substring to search for. + * @return the index of the last occurrence of the specified substring, + * or {@code -1} if there is no such occurrence. + */ + static int lastIndexOf(String _this, String str) { + return lastIndexOf(_this, str, _this.length()); + } + + /** + * Returns the index within this string of the last occurrence of the + * specified substring, searching backward starting at the specified index. + * + *

The returned index is the largest value k for which: + *

+     * k {@code <=} fromIndex {@code &&} this.startsWith(str, k)
+     * 
+ * If no such value of k exists, then {@code -1} is returned. + * + * @param str the substring to search for. + * @param fromIndex the index to start the search from. + * @return the index of the last occurrence of the specified substring, + * searching backward from the specified index, + * or {@code -1} if there is no such occurrence. + */ + static int lastIndexOf(String _this, String str, int fromIndex) { + // start by dereferencing s, to make sure we throw a NullPointerException if s is null + int slen = _this.length(); + if (fromIndex < 0) + { + return -1; + } + int olen = str.length(); + if (olen == 0) + { + return Math.min(slen, fromIndex); + } + if (olen > slen) + { + return -1; + } + cli.System.String cliStr = (cli.System.String)(Object)_this; + char firstChar = str.charAt(0); + // Java allows fromIndex to both below zero or above the length of the string, .NET doesn't + int index = Math.max(0, Math.min(slen - olen, fromIndex)); + while (index > 0) + { + if (cli.System.String.CompareOrdinal(_this, index, str, 0, olen) == 0) + { + return index; + } + index = cliStr.LastIndexOf(firstChar, index - 1); + } + return cli.System.String.CompareOrdinal(_this, 0, str, 0, olen) == 0 ? 0 : -1; + } + + + /** + * Code shared by String and AbstractStringBuilder to do searches. The + * source is the character array being searched, and the target + * is the string being searched for. + * + * @param source the characters being searched. + * @param sourceOffset offset of the source string. + * @param sourceCount count of the source string. + * @param target the characters being searched for. + * @param fromIndex the index to begin searching from. + */ + static int lastIndexOf(char[] source, int sourceOffset, int sourceCount, + String target, int fromIndex) { + final int targetOffset = 0; + final int targetCount = target.length(); + /* + * Check arguments; return immediately where possible. For + * consistency, don't check for null str. + */ + int rightIndex = sourceCount - targetCount; + if (fromIndex < 0) { + return -1; + } + if (fromIndex > rightIndex) { + fromIndex = rightIndex; + } + /* Empty string always matches. */ + if (targetCount == 0) { + return fromIndex; + } + + int strLastIndex = targetOffset + targetCount - 1; + char strLastChar = target.charAt(strLastIndex); + int min = sourceOffset + targetCount - 1; + int i = min + fromIndex; + + startSearchForLastChar: + while (true) { + while (i >= min && source[i] != strLastChar) { + i--; + } + if (i < min) { + return -1; + } + int j = i - 1; + int start = j - (targetCount - 1); + int k = strLastIndex - 1; + + while (j > start) { + if (source[j--] != target.charAt(k--)) { + i--; + continue startSearchForLastChar; + } + } + return start - sourceOffset + 1; + } + } + + /** + * Code shared by String and StringBuffer to do searches. The + * source is the character array being searched, and the target + * is the string being searched for. + * + * @param source the characters being searched. + * @param sourceOffset offset of the source string. + * @param sourceCount count of the source string. + * @param target the characters being searched for. + * @param targetOffset offset of the target string. + * @param targetCount count of the target string. + * @param fromIndex the index to begin searching from. + */ + static int lastIndexOf(char[] source, int sourceOffset, int sourceCount, + char[] target, int targetOffset, int targetCount, + int fromIndex) { + /* + * Check arguments; return immediately where possible. For + * consistency, don't check for null str. + */ + int rightIndex = sourceCount - targetCount; + if (fromIndex < 0) { + return -1; + } + if (fromIndex > rightIndex) { + fromIndex = rightIndex; + } + /* Empty string always matches. */ + if (targetCount == 0) { + return fromIndex; + } + + int strLastIndex = targetOffset + targetCount - 1; + char strLastChar = target[strLastIndex]; + int min = sourceOffset + targetCount - 1; + int i = min + fromIndex; + + startSearchForLastChar: + while (true) { + while (i >= min && source[i] != strLastChar) { + i--; + } + if (i < min) { + return -1; + } + int j = i - 1; + int start = j - (targetCount - 1); + int k = strLastIndex - 1; + + while (j > start) { + if (source[j--] != target[k--]) { + i--; + continue startSearchForLastChar; + } + } + return start - sourceOffset + 1; + } + } + + /** + * Returns a string that is a substring of this string. The + * substring begins at the specified {@code beginIndex} and + * extends to the character at index {@code endIndex - 1}. + * Thus the length of the substring is {@code endIndex-beginIndex}. + *

+ * Examples: + *

+     * "hamburger".substring(4, 8) returns "urge"
+     * "smiles".substring(1, 5) returns "mile"
+     * 
+ * + * @param beginIndex the beginning index, inclusive. + * @param endIndex the ending index, exclusive. + * @return the specified substring. + * @exception IndexOutOfBoundsException if the + * {@code beginIndex} is negative, or + * {@code endIndex} is larger than the length of + * this {@code String} object, or + * {@code beginIndex} is larger than + * {@code endIndex}. + */ + static String substring(cli.System.String _this, int beginIndex, int endIndex) { + if (beginIndex < 0) { + throw new StringIndexOutOfBoundsException(beginIndex); + } + if (endIndex > _this.get_Length()) { + throw new StringIndexOutOfBoundsException(endIndex); + } + int subLen = endIndex - beginIndex; + if (subLen < 0) { + throw new StringIndexOutOfBoundsException(subLen); + } + return ((beginIndex == 0) && (endIndex == _this.get_Length())) ? (String)(Object)_this + : _this.Substring(beginIndex, subLen); + } + + /** + * Concatenates the specified string to the end of this string. + *

+ * If the length of the argument string is {@code 0}, then this + * {@code String} object is returned. Otherwise, a + * {@code String} object is returned that represents a character + * sequence that is the concatenation of the character sequence + * represented by this {@code String} object and the character + * sequence represented by the argument string.

+ * Examples: + *

+     * "cares".concat("s") returns "caress"
+     * "to".concat("get").concat("her") returns "together"
+     * 
+ * + * @param str the {@code String} that is concatenated to the end + * of this {@code String}. + * @return a string that represents the concatenation of this object's + * characters followed by the string argument's characters. + */ + static String concat(String _this, String str) { + int otherLen = str.length(); + if (otherLen == 0) { + return _this; + } + return cli.System.String.Concat(_this, str); + } + + /** + * Returns a string resulting from replacing all occurrences of + * {@code oldChar} in this string with {@code newChar}. + *

+ * If the character {@code oldChar} does not occur in the + * character sequence represented by this {@code String} object, + * then a reference to this {@code String} object is returned. + * Otherwise, a {@code String} object is returned that + * represents a character sequence identical to the character sequence + * represented by this {@code String} object, except that every + * occurrence of {@code oldChar} is replaced by an occurrence + * of {@code newChar}. + *

+ * Examples: + *

+     * "mesquite in your cellar".replace('e', 'o')
+     *         returns "mosquito in your collar"
+     * "the war of baronets".replace('r', 'y')
+     *         returns "the way of bayonets"
+     * "sparring with a purple porpoise".replace('p', 't')
+     *         returns "starring with a turtle tortoise"
+     * "JonL".replace('q', 'x') returns "JonL" (no change)
+     * 
+ * + * @param oldChar the old character. + * @param newChar the new character. + * @return a string derived from this string by replacing every + * occurrence of {@code oldChar} with {@code newChar}. + */ + static String replace(String _this, char oldChar, char newChar) { + if (oldChar != newChar) { + int len = _this.length(); + int i = -1; + + while (++i < len) { + if (_this.charAt(i) == oldChar) { + break; + } + } + if (i < len) { + char buf[] = new char[len]; + for (int j = 0 ; j < i ; j++) { + buf[j] = _this.charAt(j); + } + while (i < len) { + char c = _this.charAt(i); + buf[i] = (c == oldChar) ? newChar : c; + i++; + } + return new String(buf, true); + } + } + return _this; + } + + /** + * Returns true if and only if this string contains the specified + * sequence of char values. + * + * @param s the sequence to search for + * @return true if this string contains {@code s}, false otherwise + * @since 1.5 + */ + static boolean contains(String _this, CharSequence s) { + return indexOf(_this, s.toString()) > -1; + } + + /** + * Replaces each substring of this string that matches the literal target + * sequence with the specified literal replacement sequence. The + * replacement proceeds from the beginning of the string to the end, for + * example, replacing "aa" with "b" in the string "aaa" will result in + * "ba" rather than "ab". + * + * @param target The sequence of char values to be replaced + * @param replacement The replacement sequence of char values + * @return The resulting string + * @since 1.5 + */ + static String replace(String _this, CharSequence target, CharSequence replacement) { + return Pattern.compile(target.toString(), Pattern.LITERAL).matcher( + _this).replaceAll(Matcher.quoteReplacement(replacement.toString())); + } + + /** + * Splits this string around matches of the given + * regular expression. + * + *

The array returned by this method contains each substring of this + * string that is terminated by another substring that matches the given + * expression or is terminated by the end of the string. The substrings in + * the array are in the order in which they occur in this string. If the + * expression does not match any part of the input then the resulting array + * has just one element, namely this string. + * + *

When there is a positive-width match at the beginning of this + * string then an empty leading substring is included at the beginning + * of the resulting array. A zero-width match at the beginning however + * never produces such empty leading substring. + * + *

The {@code limit} parameter controls the number of times the + * pattern is applied and therefore affects the length of the resulting + * array. If the limit n is greater than zero then the pattern + * will be applied at most n - 1 times, the array's + * length will be no greater than n, and the array's last entry + * will contain all input beyond the last matched delimiter. If n + * is non-positive then the pattern will be applied as many times as + * possible and the array can have any length. If n is zero then + * the pattern will be applied as many times as possible, the array can + * have any length, and trailing empty strings will be discarded. + * + *

The string {@code "boo:and:foo"}, for example, yields the + * following results with these parameters: + * + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
RegexLimitResult
:2{@code { "boo", "and:foo" }}
:5{@code { "boo", "and", "foo" }}
:-2{@code { "boo", "and", "foo" }}
o5{@code { "b", "", ":and:f", "", "" }}
o-2{@code { "b", "", ":and:f", "", "" }}
o0{@code { "b", "", ":and:f" }}
+ * + *

An invocation of this method of the form + * str.{@code split(}regex{@code ,} n{@code )} + * yields the same result as the expression + * + *

+ * + * {@link java.util.regex.Pattern}.{@link + * java.util.regex.Pattern#compile compile}(regex).{@link + * java.util.regex.Pattern#split(java.lang.CharSequence,int) split}(strn) + * + *
+ * + * + * @param regex + * the delimiting regular expression + * + * @param limit + * the result threshold, as described above + * + * @return the array of strings computed by splitting this string + * around matches of the given regular expression + * + * @throws PatternSyntaxException + * if the regular expression's syntax is invalid + * + * @see java.util.regex.Pattern + * + * @since 1.4 + * @spec JSR-51 + */ + static String[] split(String _this, String regex, int limit) { + /* fastpath if the regex is a + (1)one-char String and this character is not one of the + RegEx's meta characters ".$|()[{^?*+\\", or + (2)two-char String and the first char is the backslash and + the second is not the ascii digit or ascii letter. + */ + char ch = 0; + if (((regex.length() == 1 && + ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) || + (regex.length() == 2 && + regex.charAt(0) == '\\' && + (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 && + ((ch-'a')|('z'-ch)) < 0 && + ((ch-'A')|('Z'-ch)) < 0)) && + (ch < Character.MIN_HIGH_SURROGATE || + ch > Character.MAX_LOW_SURROGATE)) + { + int off = 0; + int next = 0; + boolean limited = limit > 0; + ArrayList list = new ArrayList<>(); + while ((next = _this.indexOf(ch, off)) != -1) { + if (!limited || list.size() < limit - 1) { + list.add(_this.substring(off, next)); + off = next + 1; + } else { // last one + //assert (list.size() == limit - 1); + list.add(_this.substring(off, _this.length())); + off = _this.length(); + break; + } + } + // If no match was found, return this + if (off == 0) + return new String[]{_this}; + + // Add remaining segment + if (!limited || list.size() < limit) + list.add(_this.substring(off, _this.length())); + + // Construct result + int resultSize = list.size(); + if (limit == 0) { + while (resultSize > 0 && list.get(resultSize - 1).length() == 0) { + resultSize--; + } + } + String[] result = new String[resultSize]; + return list.subList(0, resultSize).toArray(result); + } + return Pattern.compile(regex).split(_this, limit); + } + + /** + * Returns a new String composed of copies of the + * {@code CharSequence elements} joined together with a copy of + * the specified {@code delimiter}. + * + *
For example, + *
{@code
+     *     String message = String.join("-", "Java", "is", "cool");
+     *     // message returned is: "Java-is-cool"
+     * }
+ * + * Note that if an element is null, then {@code "null"} is added. + * + * @param delimiter the delimiter that separates each element + * @param elements the elements to join together. + * + * @return a new {@code String} that is composed of the {@code elements} + * separated by the {@code delimiter} + * + * @throws NullPointerException If {@code delimiter} or {@code elements} + * is {@code null} + * + * @see java.util.StringJoiner + * @since 1.8 + */ + public static String join(CharSequence delimiter, CharSequence... elements) { + Objects.requireNonNull(delimiter); + Objects.requireNonNull(elements); + // Number of elements not likely worth Arrays.stream overhead. + StringJoiner joiner = new StringJoiner(delimiter); + for (CharSequence cs: elements) { + joiner.add(cs); + } + return joiner.toString(); + } + + /** + * Returns a new {@code String} composed of copies of the + * {@code CharSequence elements} joined together with a copy of the + * specified {@code delimiter}. + * + *
For example, + *
{@code
+     *     List strings = new LinkedList<>();
+     *     strings.add("Java");strings.add("is");
+     *     strings.add("cool");
+     *     String message = String.join(" ", strings);
+     *     //message returned is: "Java is cool"
+     *
+     *     Set strings = new LinkedHashSet<>();
+     *     strings.add("Java"); strings.add("is");
+     *     strings.add("very"); strings.add("cool");
+     *     String message = String.join("-", strings);
+     *     //message returned is: "Java-is-very-cool"
+     * }
+ * + * Note that if an individual element is {@code null}, then {@code "null"} is added. + * + * @param delimiter a sequence of characters that is used to separate each + * of the {@code elements} in the resulting {@code String} + * @param elements an {@code Iterable} that will have its {@code elements} + * joined together. + * + * @return a new {@code String} that is composed from the {@code elements} + * argument + * + * @throws NullPointerException If {@code delimiter} or {@code elements} + * is {@code null} + * + * @see #join(CharSequence,CharSequence...) + * @see java.util.StringJoiner + * @since 1.8 + */ + public static String join(CharSequence delimiter, + Iterable elements) { + Objects.requireNonNull(delimiter); + Objects.requireNonNull(elements); + StringJoiner joiner = new StringJoiner(delimiter); + for (CharSequence cs: elements) { + joiner.add(cs); + } + return joiner.toString(); + } + + /** + * Converts all of the characters in this {@code String} to lower + * case using the rules of the given {@code Locale}. Case mapping is based + * on the Unicode Standard version specified by the {@link java.lang.Character Character} + * class. Since case mappings are not always 1:1 char mappings, the resulting + * {@code String} may be a different length than the original {@code String}. + *

+ * Examples of lowercase mappings are in the following table: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Language Code of LocaleUpper CaseLower CaseDescription
tr (Turkish)\u0130\u0069capital letter I with dot above -> small letter i
tr (Turkish)\u0049\u0131capital letter I -> small letter dotless i
(all)French Friesfrench frieslowercased all chars in String
(all)capiotacapchi + * capthetacapupsil + * capsigmaiotachi + * thetaupsilon + * sigmalowercased all chars in String
+ * + * @param locale use the case transformation rules for this locale + * @return the {@code String}, converted to lowercase. + * @see java.lang.String#toLowerCase() + * @see java.lang.String#toUpperCase() + * @see java.lang.String#toUpperCase(Locale) + * @since 1.1 + */ + static String toLowerCase(String _this, Locale locale) { + if (locale == null) { + throw new NullPointerException(); + } + + int firstUpper; + final int len = _this.length(); + + /* Now check if there are any characters that need to be changed. */ + scan: { + for (firstUpper = 0 ; firstUpper < len; ) { + char c = _this.charAt(firstUpper); + if ((c >= Character.MIN_HIGH_SURROGATE) + && (c <= Character.MAX_HIGH_SURROGATE)) { + int supplChar = _this.codePointAt(firstUpper); + if (supplChar != Character.toLowerCase(supplChar)) { + break scan; + } + firstUpper += Character.charCount(supplChar); + } else { + if (c != Character.toLowerCase(c)) { + break scan; + } + firstUpper++; + } + } + return _this; + } + + char[] result = new char[len]; + int resultOffset = 0; /* result may grow, so i+resultOffset + * is the write location in result */ + + /* Just copy the first few lowerCase characters. */ + _this.getChars(0, firstUpper, result, 0); + + String lang = locale.getLanguage(); + boolean localeDependent = + (lang == "tr" || lang == "az" || lang == "lt"); + char[] lowerCharArray; + int lowerChar; + int srcChar; + int srcCount; + for (int i = firstUpper; i < len; i += srcCount) { + srcChar = (int)_this.charAt(i); + if ((char)srcChar >= Character.MIN_HIGH_SURROGATE + && (char)srcChar <= Character.MAX_HIGH_SURROGATE) { + srcChar = _this.codePointAt(i); + srcCount = Character.charCount(srcChar); + } else { + srcCount = 1; + } + if (localeDependent || + srcChar == '\u03A3' || // GREEK CAPITAL LETTER SIGMA + srcChar == '\u0130') { // LATIN CAPITAL LETTER I WITH DOT ABOVE + lowerChar = ConditionalSpecialCasing.toLowerCaseEx(_this, i, locale); + } else { + lowerChar = Character.toLowerCase(srcChar); + } + if ((lowerChar == Character.ERROR) + || (lowerChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) { + if (lowerChar == Character.ERROR) { + lowerCharArray = + ConditionalSpecialCasing.toLowerCaseCharArray(_this, i, locale); + } else if (srcCount == 2) { + resultOffset += Character.toChars(lowerChar, result, i + resultOffset) - srcCount; + continue; + } else { + lowerCharArray = Character.toChars(lowerChar); + } + + /* Grow result if needed */ + int mapLen = lowerCharArray.length; + if (mapLen > srcCount) { + char[] result2 = new char[result.length + mapLen - srcCount]; + System.arraycopy(result, 0, result2, 0, i + resultOffset); + result = result2; + } + for (int x = 0; x < mapLen; ++x) { + result[i + resultOffset + x] = lowerCharArray[x]; + } + resultOffset += (mapLen - srcCount); + } else { + result[i + resultOffset] = (char)lowerChar; + } + } + return new String(result, 0, len + resultOffset); + } + + /** + * Converts all of the characters in this {@code String} to lower + * case using the rules of the default locale. This is equivalent to calling + * {@code toLowerCase(Locale.getDefault())}. + *

+ * Note: This method is locale sensitive, and may produce unexpected + * results if used for strings that are intended to be interpreted locale + * independently. + * Examples are programming language identifiers, protocol keys, and HTML + * tags. + * For instance, {@code "TITLE".toLowerCase()} in a Turkish locale + * returns {@code "t\u005Cu0131tle"}, where '\u005Cu0131' is the + * LATIN SMALL LETTER DOTLESS I character. + * To obtain correct results for locale insensitive strings, use + * {@code toLowerCase(Locale.ROOT)}. + *

+ * @return the {@code String}, converted to lowercase. + * @see java.lang.String#toLowerCase(Locale) + */ + static String toLowerCase(String _this) { + return toLowerCase(_this, Locale.getDefault()); + } + + /** + * Converts all of the characters in this {@code String} to upper + * case using the rules of the given {@code Locale}. Case mapping is based + * on the Unicode Standard version specified by the {@link java.lang.Character Character} + * class. Since case mappings are not always 1:1 char mappings, the resulting + * {@code String} may be a different length than the original {@code String}. + *

+ * Examples of locale-sensitive and 1:M case mappings are in the following table. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Language Code of LocaleLower CaseUpper CaseDescription
tr (Turkish)\u0069\u0130small letter i -> capital letter I with dot above
tr (Turkish)\u0131\u0049small letter dotless i -> capital letter I
(all)\u00df\u0053 \u0053small letter sharp s -> two letters: SS
(all)FahrvergnügenFAHRVERGNÜGEN
+ * @param locale use the case transformation rules for this locale + * @return the {@code String}, converted to uppercase. + * @see java.lang.String#toUpperCase() + * @see java.lang.String#toLowerCase() + * @see java.lang.String#toLowerCase(Locale) + * @since 1.1 + */ + static String toUpperCase(String _this, Locale locale) { + if (locale == null) { + throw new NullPointerException(); + } + + int firstLower; + final int len = _this.length(); + + /* Now check if there are any characters that need to be changed. */ + scan: { + for (firstLower = 0 ; firstLower < len; ) { + int c = (int)_this.charAt(firstLower); + int srcCount; + if ((c >= Character.MIN_HIGH_SURROGATE) + && (c <= Character.MAX_HIGH_SURROGATE)) { + c = _this.codePointAt(firstLower); + srcCount = Character.charCount(c); + } else { + srcCount = 1; + } + int upperCaseChar = Character.toUpperCaseEx(c); + if ((upperCaseChar == Character.ERROR) + || (c != upperCaseChar)) { + break scan; + } + firstLower += srcCount; + } + return _this; + } + + /* result may grow, so i+resultOffset is the write location in result */ + int resultOffset = 0; + char[] result = new char[len]; /* may grow */ + + /* Just copy the first few upperCase characters. */ + _this.getChars(0, firstLower, result, 0); + + String lang = locale.getLanguage(); + boolean localeDependent = + (lang == "tr" || lang == "az" || lang == "lt"); + char[] upperCharArray; + int upperChar; + int srcChar; + int srcCount; + for (int i = firstLower; i < len; i += srcCount) { + srcChar = (int)_this.charAt(i); + if ((char)srcChar >= Character.MIN_HIGH_SURROGATE && + (char)srcChar <= Character.MAX_HIGH_SURROGATE) { + srcChar = _this.codePointAt(i); + srcCount = Character.charCount(srcChar); + } else { + srcCount = 1; + } + if (localeDependent) { + upperChar = ConditionalSpecialCasing.toUpperCaseEx(_this, i, locale); + } else { + upperChar = Character.toUpperCaseEx(srcChar); + } + if ((upperChar == Character.ERROR) + || (upperChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) { + if (upperChar == Character.ERROR) { + if (localeDependent) { + upperCharArray = + ConditionalSpecialCasing.toUpperCaseCharArray(_this, i, locale); + } else { + upperCharArray = Character.toUpperCaseCharArray(srcChar); + } + } else if (srcCount == 2) { + resultOffset += Character.toChars(upperChar, result, i + resultOffset) - srcCount; + continue; + } else { + upperCharArray = Character.toChars(upperChar); + } + + /* Grow result if needed */ + int mapLen = upperCharArray.length; + if (mapLen > srcCount) { + char[] result2 = new char[result.length + mapLen - srcCount]; + System.arraycopy(result, 0, result2, 0, i + resultOffset); + result = result2; + } + for (int x = 0; x < mapLen; ++x) { + result[i + resultOffset + x] = upperCharArray[x]; + } + resultOffset += (mapLen - srcCount); + } else { + result[i + resultOffset] = (char)upperChar; + } + } + return new String(result, 0, len + resultOffset); + } + + /** + * Converts all of the characters in this {@code String} to upper + * case using the rules of the default locale. This method is equivalent to + * {@code toUpperCase(Locale.getDefault())}. + *

+ * Note: This method is locale sensitive, and may produce unexpected + * results if used for strings that are intended to be interpreted locale + * independently. + * Examples are programming language identifiers, protocol keys, and HTML + * tags. + * For instance, {@code "title".toUpperCase()} in a Turkish locale + * returns {@code "T\u005Cu0130TLE"}, where '\u005Cu0130' is the + * LATIN CAPITAL LETTER I WITH DOT ABOVE character. + * To obtain correct results for locale insensitive strings, use + * {@code toUpperCase(Locale.ROOT)}. + *

+ * @return the {@code String}, converted to uppercase. + * @see java.lang.String#toUpperCase(Locale) + */ + static String toUpperCase(String _this) { + return toUpperCase(_this, Locale.getDefault()); + } + + /** + * Returns a string whose value is this string, with any leading and trailing + * whitespace removed. + *

+ * If this {@code String} object represents an empty character + * sequence, or the first and last characters of character sequence + * represented by this {@code String} object both have codes + * greater than {@code '\u005Cu0020'} (the space character), then a + * reference to this {@code String} object is returned. + *

+ * Otherwise, if there is no character with a code greater than + * {@code '\u005Cu0020'} in the string, then a + * {@code String} object representing an empty string is + * returned. + *

+ * Otherwise, let k be the index of the first character in the + * string whose code is greater than {@code '\u005Cu0020'}, and let + * m be the index of the last character in the string whose code + * is greater than {@code '\u005Cu0020'}. A {@code String} + * object is returned, representing the substring of this string that + * begins with the character at index k and ends with the + * character at index m-that is, the result of + * {@code this.substring(k, m + 1)}. + *

+ * This method may be used to trim whitespace (as defined above) from + * the beginning and end of a string. + * + * @return A string whose value is this string, with any leading and trailing white + * space removed, or this string if it has no leading or + * trailing white space. + */ + static String trim(String _this) { + int len = _this.length(); + int st = 0; + + while ((st < len) && (_this.charAt(st) <= ' ')) { + st++; + } + while ((st < len) && (_this.charAt(len - 1) <= ' ')) { + len--; + } + return ((st > 0) || (len < _this.length())) ? _this.substring(st, len) : _this; + } + + /** + * Returns a formatted string using the specified format string and + * arguments. + * + *

The locale always used is the one returned by {@link + * java.util.Locale#getDefault() Locale.getDefault()}. + * + * @param format + * A format string + * + * @param args + * Arguments referenced by the format specifiers in the format + * string. If there are more arguments than format specifiers, the + * extra arguments are ignored. The number of arguments is + * variable and may be zero. The maximum number of arguments is + * limited by the maximum dimension of a Java array as defined by + * The Java™ Virtual Machine Specification. + * The behaviour on a + * {@code null} argument depends on the conversion. + * + * @throws java.util.IllegalFormatException + * If a format string contains an illegal syntax, a format + * specifier that is incompatible with the given arguments, + * insufficient arguments given the format string, or other + * illegal conditions. For specification of all possible + * formatting errors, see the Details section of the + * formatter class specification. + * + * @return A formatted string + * + * @see java.util.Formatter + * @since 1.5 + */ + public static String format(String format, Object... args) { + return new Formatter().format(format, args).toString(); + } + + /** + * Returns a formatted string using the specified locale, format string, + * and arguments. + * + * @param l + * The {@linkplain java.util.Locale locale} to apply during + * formatting. If {@code l} is {@code null} then no localization + * is applied. + * + * @param format + * A format string + * + * @param args + * Arguments referenced by the format specifiers in the format + * string. If there are more arguments than format specifiers, the + * extra arguments are ignored. The number of arguments is + * variable and may be zero. The maximum number of arguments is + * limited by the maximum dimension of a Java array as defined by + * The Java™ Virtual Machine Specification. + * The behaviour on a + * {@code null} argument depends on the + * conversion. + * + * @throws java.util.IllegalFormatException + * If a format string contains an illegal syntax, a format + * specifier that is incompatible with the given arguments, + * insufficient arguments given the format string, or other + * illegal conditions. For specification of all possible + * formatting errors, see the Details section of the + * formatter class specification + * + * @return A formatted string + * + * @see java.util.Formatter + * @since 1.5 + */ + public static String format(Locale l, String format, Object... args) { + return new Formatter(l).format(format, args).toString(); + } + + /** + * Returns the string representation of the {@code Object} argument. + * + * @param obj an {@code Object}. + * @return if the argument is {@code null}, then a string equal to + * {@code "null"}; otherwise, the value of + * {@code obj.toString()} is returned. + * @see java.lang.Object#toString() + */ + public static String valueOf(Object obj) { + return (obj == null) ? "null" : obj.toString(); + } + + /** + * Returns the string representation of the {@code char} array + * argument. The contents of the character array are copied; subsequent + * modification of the character array does not affect the returned + * string. + * + * @param data the character array. + * @return a {@code String} that contains the characters of the + * character array. + */ + public static String valueOf(char data[]) { + return new String(data); + } + + /** + * Returns the string representation of a specific subarray of the + * {@code char} array argument. + *

+ * The {@code offset} argument is the index of the first + * character of the subarray. The {@code count} argument + * specifies the length of the subarray. The contents of the subarray + * are copied; subsequent modification of the character array does not + * affect the returned string. + * + * @param data the character array. + * @param offset initial offset of the subarray. + * @param count length of the subarray. + * @return a {@code String} that contains the characters of the + * specified subarray of the character array. + * @exception IndexOutOfBoundsException if {@code offset} is + * negative, or {@code count} is negative, or + * {@code offset+count} is larger than + * {@code data.length}. + */ + public static String valueOf(char data[], int offset, int count) { + return new String(data, offset, count); + } + + /** + * Equivalent to {@link #valueOf(char[], int, int)}. + * + * @param data the character array. + * @param offset initial offset of the subarray. + * @param count length of the subarray. + * @return a {@code String} that contains the characters of the + * specified subarray of the character array. + * @exception IndexOutOfBoundsException if {@code offset} is + * negative, or {@code count} is negative, or + * {@code offset+count} is larger than + * {@code data.length}. + */ + public static String copyValueOf(char data[], int offset, int count) { + return new String(data, offset, count); + } + + /** + * Equivalent to {@link #valueOf(char[])}. + * + * @param data the character array. + * @return a {@code String} that contains the characters of the + * character array. + */ + public static String copyValueOf(char data[]) { + return new String(data); + } + + /** + * Returns the string representation of the {@code boolean} argument. + * + * @param b a {@code boolean}. + * @return if the argument is {@code true}, a string equal to + * {@code "true"} is returned; otherwise, a string equal to + * {@code "false"} is returned. + */ + public static String valueOf(boolean b) { + return b ? "true" : "false"; + } + + /** + * Returns the string representation of the {@code int} argument. + *

+ * The representation is exactly the one returned by the + * {@code Integer.toString} method of one argument. + * + * @param i an {@code int}. + * @return a string representation of the {@code int} argument. + * @see java.lang.Integer#toString(int, int) + */ + public static String valueOf(int i) { + return Integer.toString(i); + } + + /** + * Returns the string representation of the {@code long} argument. + *

+ * The representation is exactly the one returned by the + * {@code Long.toString} method of one argument. + * + * @param l a {@code long}. + * @return a string representation of the {@code long} argument. + * @see java.lang.Long#toString(long) + */ + public static String valueOf(long l) { + return Long.toString(l); + } + + /** + * Returns the string representation of the {@code float} argument. + *

+ * The representation is exactly the one returned by the + * {@code Float.toString} method of one argument. + * + * @param f a {@code float}. + * @return a string representation of the {@code float} argument. + * @see java.lang.Float#toString(float) + */ + public static String valueOf(float f) { + return Float.toString(f); + } + + /** + * Returns the string representation of the {@code double} argument. + *

+ * The representation is exactly the one returned by the + * {@code Double.toString} method of one argument. + * + * @param d a {@code double}. + * @return a string representation of the {@code double} argument. + * @see java.lang.Double#toString(double) + */ + public static String valueOf(double d) { + return Double.toString(d); + } +} diff --git a/openjdk/java/lang/System.java b/openjdk/java/lang/System.java new file mode 100644 index 0000000..796d99d --- /dev/null +++ b/openjdk/java/lang/System.java @@ -0,0 +1,1222 @@ +/* + * Copyright (c) 1994, 2013, 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 java.lang; + +import java.io.*; +import java.lang.reflect.Executable; +import java.lang.annotation.Annotation; +import java.security.AccessControlContext; +import java.util.Properties; +import java.util.PropertyPermission; +import java.util.StringTokenizer; +import java.util.Map; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.AllPermission; +import java.nio.channels.Channel; +import java.nio.channels.spi.SelectorProvider; +import sun.nio.ch.Interruptible; +import sun.reflect.CallerSensitive; +import sun.reflect.Reflection; +import sun.security.util.SecurityConstants; +import sun.reflect.annotation.AnnotationType; + +final class StdIO +{ + private StdIO() { } + static InputStream in = new BufferedInputStream(new FileInputStream(FileDescriptor.in)); + static PrintStream out = System.newPrintStream(new FileOutputStream(FileDescriptor.out), Props.props.getProperty("sun.stdout.encoding")); + static PrintStream err = System.newPrintStream(new FileOutputStream(FileDescriptor.err), Props.props.getProperty("sun.stderr.encoding")); +} + +final class Props +{ + private Props() { } + + static Properties props; + static String lineSeparator; + + static + { + props = new Properties(); + VMSystemProperties.initProperties(props); + lineSeparator = props.getProperty("line.separator"); + + // after we've initialized the system properties, we need to fixate certain + // results that depend on system properties, because we don't want Java code to + // be able to change the behavior by setting these system properties. + ClassLoader.initializeLibraryPaths(props); + sun.misc.VM.saveAndRemoveProperties(props); + + // now that we've initialized the system properties (which are our only + // notion of "booting" the VM) we set the booted flag. + sun.misc.VM.booted(); + } +} + +/** + * The System class contains several useful class fields + * and methods. It cannot be instantiated. + * + *

Among the facilities provided by the System class + * are standard input, standard output, and error output streams; + * access to externally defined properties and environment + * variables; a means of loading files and libraries; and a utility + * method for quickly copying a portion of an array. + * + * @author unascribed + * @since JDK1.0 + */ +public final class System { + + /* register the natives via the static initializer. + * + * VM will invoke the initializeSystemClass method to complete + * the initialization for this class separated from clinit. + * Note that to use properties set by the VM, see the constraints + * described in the initializeSystemClass method. + */ + private static native void registerNatives(); + static { + //registerNatives(); + } + + /** Don't let anyone instantiate this class */ + private System() { + } + + /** + * The "standard" input stream. This stream is already + * open and ready to supply input data. Typically this stream + * corresponds to keyboard input or another input source specified by + * the host environment or user. + */ + @ikvm.lang.Property(get="get_in") + public final static InputStream in = null; + + private static InputStream get_in() + { + return StdIO.in; + } + + /** + * The "standard" output stream. This stream is already + * open and ready to accept output data. Typically this stream + * corresponds to display output or another output destination + * specified by the host environment or user. + *

+ * For simple stand-alone Java applications, a typical way to write + * a line of output data is: + *

+     *     System.out.println(data)
+     * 
+ *

+ * See the println methods in class PrintStream. + * + * @see java.io.PrintStream#println() + * @see java.io.PrintStream#println(boolean) + * @see java.io.PrintStream#println(char) + * @see java.io.PrintStream#println(char[]) + * @see java.io.PrintStream#println(double) + * @see java.io.PrintStream#println(float) + * @see java.io.PrintStream#println(int) + * @see java.io.PrintStream#println(long) + * @see java.io.PrintStream#println(java.lang.Object) + * @see java.io.PrintStream#println(java.lang.String) + */ + @ikvm.lang.Property(get="get_out") + public final static PrintStream out = null; + + private static PrintStream get_out() + { + return StdIO.out; + } + + /** + * The "standard" error output stream. This stream is already + * open and ready to accept output data. + *

+ * Typically this stream corresponds to display output or another + * output destination specified by the host environment or user. By + * convention, this output stream is used to display error messages + * or other information that should come to the immediate attention + * of a user even if the principal output stream, the value of the + * variable out, has been redirected to a file or other + * destination that is typically not continuously monitored. + */ + @ikvm.lang.Property(get="get_err") + public final static PrintStream err = null; + + private static PrintStream get_err() + { + return StdIO.err; + } + + /* The security manager for the system. + */ + private static volatile SecurityManager security = null; + + /** + * Reassigns the "standard" input stream. + * + *

First, if there is a security manager, its checkPermission + * method is called with a RuntimePermission("setIO") permission + * to see if it's ok to reassign the "standard" input stream. + *

+ * + * @param in the new standard input stream. + * + * @throws SecurityException + * if a security manager exists and its + * checkPermission method doesn't allow + * reassigning of the standard input stream. + * + * @see SecurityManager#checkPermission + * @see java.lang.RuntimePermission + * + * @since JDK1.1 + */ + public static void setIn(InputStream in) { + checkIO(); + setIn0(in); + } + + /** + * Reassigns the "standard" output stream. + * + *

First, if there is a security manager, its checkPermission + * method is called with a RuntimePermission("setIO") permission + * to see if it's ok to reassign the "standard" output stream. + * + * @param out the new standard output stream + * + * @throws SecurityException + * if a security manager exists and its + * checkPermission method doesn't allow + * reassigning of the standard output stream. + * + * @see SecurityManager#checkPermission + * @see java.lang.RuntimePermission + * + * @since JDK1.1 + */ + public static void setOut(PrintStream out) { + checkIO(); + setOut0(out); + } + + /** + * Reassigns the "standard" error output stream. + * + *

First, if there is a security manager, its checkPermission + * method is called with a RuntimePermission("setIO") permission + * to see if it's ok to reassign the "standard" error output stream. + * + * @param err the new standard error output stream. + * + * @throws SecurityException + * if a security manager exists and its + * checkPermission method doesn't allow + * reassigning of the standard error output stream. + * + * @see SecurityManager#checkPermission + * @see java.lang.RuntimePermission + * + * @since JDK1.1 + */ + public static void setErr(PrintStream err) { + checkIO(); + setErr0(err); + } + + private static volatile Console cons = null; + /** + * Returns the unique {@link java.io.Console Console} object associated + * with the current Java virtual machine, if any. + * + * @return The system console, if any, otherwise null. + * + * @since 1.6 + */ + public static Console console() { + if (cons == null) { + synchronized (System.class) { + cons = sun.misc.SharedSecrets.getJavaIOAccess().console(); + } + } + return cons; + } + + /** + * Returns the channel inherited from the entity that created this + * Java virtual machine. + * + *

This method returns the channel obtained by invoking the + * {@link java.nio.channels.spi.SelectorProvider#inheritedChannel + * inheritedChannel} method of the system-wide default + * {@link java.nio.channels.spi.SelectorProvider} object.

+ * + *

In addition to the network-oriented channels described in + * {@link java.nio.channels.spi.SelectorProvider#inheritedChannel + * inheritedChannel}, this method may return other kinds of + * channels in the future. + * + * @return The inherited channel, if any, otherwise null. + * + * @throws IOException + * If an I/O error occurs + * + * @throws SecurityException + * If a security manager is present and it does not + * permit access to the channel. + * + * @since 1.5 + */ + public static Channel inheritedChannel() throws IOException { + return SelectorProvider.provider().inheritedChannel(); + } + + private static void checkIO() { + SecurityManager sm = getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("setIO")); + } + } + + private static native void setIn0(InputStream in); + private static native void setOut0(PrintStream out); + private static native void setErr0(PrintStream err); + + /** + * Sets the System security. + * + *

If there is a security manager already installed, this method first + * calls the security manager's checkPermission method + * with a RuntimePermission("setSecurityManager") + * permission to ensure it's ok to replace the existing + * security manager. + * This may result in throwing a SecurityException. + * + *

Otherwise, the argument is established as the current + * security manager. If the argument is null and no + * security manager has been established, then no action is taken and + * the method simply returns. + * + * @param s the security manager. + * @exception SecurityException if the security manager has already + * been set and its checkPermission method + * doesn't allow it to be replaced. + * @see #getSecurityManager + * @see SecurityManager#checkPermission + * @see java.lang.RuntimePermission + */ + public static + void setSecurityManager(final SecurityManager s) { + try { + s.checkPackageAccess("java.lang"); + } catch (Exception e) { + // no-op + } + setSecurityManager0(s); + } + + private static synchronized + void setSecurityManager0(final SecurityManager s) { + // [IKVM] force sun.misc.Launcher to initialize, because it assumes that it runs without a SecurityManager + sun.misc.Launcher.getLauncher(); + + SecurityManager sm = getSecurityManager(); + if (sm != null) { + // ask the currently installed security manager if we + // can replace it. + sm.checkPermission(new RuntimePermission + ("setSecurityManager")); + } + + if ((s != null) && (s.getClass().getClassLoader() != null)) { + // New security manager class is not on bootstrap classpath. + // Cause policy to get initialized before we install the new + // security manager, in order to prevent infinite loops when + // trying to initialize the policy (which usually involves + // accessing some security and/or system properties, which in turn + // calls the installed security manager's checkPermission method + // which will loop infinitely if there is a non-system class + // (in this case: the new security manager class) on the stack). + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + s.getClass().getProtectionDomain().implies + (SecurityConstants.ALL_PERMISSION); + return null; + } + }); + } + + security = s; + } + + /** + * Gets the system security interface. + * + * @return if a security manager has already been established for the + * current application, then that security manager is returned; + * otherwise, null is returned. + * @see #setSecurityManager + */ + public static SecurityManager getSecurityManager() { + return security; + } + + /** + * Returns the current time in milliseconds. Note that + * while the unit of time of the return value is a millisecond, + * the granularity of the value depends on the underlying + * operating system and may be larger. For example, many + * operating systems measure time in units of tens of + * milliseconds. + * + *

See the description of the class Date for + * a discussion of slight discrepancies that may arise between + * "computer time" and coordinated universal time (UTC). + * + * @return the difference, measured in milliseconds, between + * the current time and midnight, January 1, 1970 UTC. + * @see java.util.Date + */ + public static long currentTimeMillis() { + long january_1st_1970 = 62135596800000L; + return cli.System.DateTime.get_UtcNow().get_Ticks() / 10000L - january_1st_1970; + } + + /** + * Returns the current value of the running Java Virtual Machine's + * high-resolution time source, in nanoseconds. + * + *

This method can only be used to measure elapsed time and is + * not related to any other notion of system or wall-clock time. + * The value returned represents nanoseconds since some fixed but + * arbitrary origin time (perhaps in the future, so values + * may be negative). The same origin is used by all invocations of + * this method in an instance of a Java virtual machine; other + * virtual machine instances are likely to use a different origin. + * + *

This method provides nanosecond precision, but not necessarily + * nanosecond resolution (that is, how frequently the value changes) + * - no guarantees are made except that the resolution is at least as + * good as that of {@link #currentTimeMillis()}. + * + *

Differences in successive calls that span greater than + * approximately 292 years (263 nanoseconds) will not + * correctly compute elapsed time due to numerical overflow. + * + *

The values returned by this method become meaningful only when + * the difference between two such values, obtained within the same + * instance of a Java virtual machine, is computed. + * + *

For example, to measure how long some code takes to execute: + *

 {@code
+     * long startTime = System.nanoTime();
+     * // ... the code being measured ...
+     * long estimatedTime = System.nanoTime() - startTime;}
+ * + *

To compare two nanoTime values + *

 {@code
+     * long t0 = System.nanoTime();
+     * ...
+     * long t1 = System.nanoTime();}
+ * + * one should use {@code t1 - t0 < 0}, not {@code t1 < t0}, + * because of the possibility of numerical overflow. + * + * @return the current value of the running Java Virtual Machine's + * high-resolution time source, in nanoseconds + * @since 1.5 + */ + public static long nanoTime() { + long NANOS_PER_SEC = 1000000000; + double current = cli.System.Diagnostics.Stopwatch.GetTimestamp(); + double freq = cli.System.Diagnostics.Stopwatch.Frequency; + return (long)((current / freq) * NANOS_PER_SEC); + } + + /** + * Copies an array from the specified source array, beginning at the + * specified position, to the specified position of the destination array. + * A subsequence of array components are copied from the source + * array referenced by src to the destination array + * referenced by dest. The number of components copied is + * equal to the length argument. The components at + * positions srcPos through + * srcPos+length-1 in the source array are copied into + * positions destPos through + * destPos+length-1, respectively, of the destination + * array. + *

+ * If the src and dest arguments refer to the + * same array object, then the copying is performed as if the + * components at positions srcPos through + * srcPos+length-1 were first copied to a temporary + * array with length components and then the contents of + * the temporary array were copied into positions + * destPos through destPos+length-1 of the + * destination array. + *

+ * If dest is null, then a + * NullPointerException is thrown. + *

+ * If src is null, then a + * NullPointerException is thrown and the destination + * array is not modified. + *

+ * Otherwise, if any of the following is true, an + * ArrayStoreException is thrown and the destination is + * not modified: + *

    + *
  • The src argument refers to an object that is not an + * array. + *
  • The dest argument refers to an object that is not an + * array. + *
  • The src argument and dest argument refer + * to arrays whose component types are different primitive types. + *
  • The src argument refers to an array with a primitive + * component type and the dest argument refers to an array + * with a reference component type. + *
  • The src argument refers to an array with a reference + * component type and the dest argument refers to an array + * with a primitive component type. + *
+ *

+ * Otherwise, if any of the following is true, an + * IndexOutOfBoundsException is + * thrown and the destination is not modified: + *

    + *
  • The srcPos argument is negative. + *
  • The destPos argument is negative. + *
  • The length argument is negative. + *
  • srcPos+length is greater than + * src.length, the length of the source array. + *
  • destPos+length is greater than + * dest.length, the length of the destination array. + *
+ *

+ * Otherwise, if any actual component of the source array from + * position srcPos through + * srcPos+length-1 cannot be converted to the component + * type of the destination array by assignment conversion, an + * ArrayStoreException is thrown. In this case, let + * k be the smallest nonnegative integer less than + * length such that src[srcPos+k] + * cannot be converted to the component type of the destination + * array; when the exception is thrown, source array components from + * positions srcPos through + * srcPos+k-1 + * will already have been copied to destination array positions + * destPos through + * destPos+k-1 and no other + * positions of the destination array will have been modified. + * (Because of the restrictions already itemized, this + * paragraph effectively applies only to the situation where both + * arrays have component types that are reference types.) + * + * @param src the source array. + * @param srcPos starting position in the source array. + * @param dest the destination array. + * @param destPos starting position in the destination data. + * @param length the number of array elements to be copied. + * @exception IndexOutOfBoundsException if copying would cause + * access of data outside array bounds. + * @exception ArrayStoreException if an element in the src + * array could not be stored into the dest array + * because of a type mismatch. + * @exception NullPointerException if either src or + * dest is null. + */ + public static native void arraycopy(Object src, int srcPos, + Object dest, int destPos, + int length); + + /** + * Returns the same hash code for the given object as + * would be returned by the default method hashCode(), + * whether or not the given object's class overrides + * hashCode(). + * The hash code for the null reference is zero. + * + * @param x object for which the hashCode is to be calculated + * @return the hashCode + * @since JDK1.1 + */ + public static int identityHashCode(Object x) { + return cli.System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(x); + } + + /** + * System properties. The following properties are guaranteed to be defined: + *

+ *
java.version
Java version number + *
java.vendor
Java vendor specific string + *
java.vendor.url
Java vendor URL + *
java.home
Java installation directory + *
java.class.version
Java class version number + *
java.class.path
Java classpath + *
os.name
Operating System Name + *
os.arch
Operating System Architecture + *
os.version
Operating System Version + *
file.separator
File separator ("/" on Unix) + *
path.separator
Path separator (":" on Unix) + *
line.separator
Line separator ("\n" on Unix) + *
user.name
User account name + *
user.home
User home directory + *
user.dir
User's current working directory + *
+ */ + + @ikvm.lang.Property(get="get_props", set="set_props") + private static Properties props; + private static native Properties initProperties(Properties props); + + private static Properties get_props() { return Props.props; } + private static void set_props(Properties value) { Props.props = value; } + + /** + * Determines the current system properties. + *

+ * First, if there is a security manager, its + * checkPropertiesAccess method is called with no + * arguments. This may result in a security exception. + *

+ * The current set of system properties for use by the + * {@link #getProperty(String)} method is returned as a + * Properties object. If there is no current set of + * system properties, a set of system properties is first created and + * initialized. This set of system properties always includes values + * for the following keys: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
KeyDescription of Associated Value
java.versionJava Runtime Environment version
java.vendorJava Runtime Environment vendor
java.vendor.urlJava vendor URL
java.homeJava installation directory
java.vm.specification.versionJava Virtual Machine specification version
java.vm.specification.vendorJava Virtual Machine specification vendor
java.vm.specification.nameJava Virtual Machine specification name
java.vm.versionJava Virtual Machine implementation version
java.vm.vendorJava Virtual Machine implementation vendor
java.vm.nameJava Virtual Machine implementation name
java.specification.versionJava Runtime Environment specification version
java.specification.vendorJava Runtime Environment specification vendor
java.specification.nameJava Runtime Environment specification name
java.class.versionJava class format version number
java.class.pathJava class path
java.library.pathList of paths to search when loading libraries
java.io.tmpdirDefault temp file path
java.compilerName of JIT compiler to use
java.ext.dirsPath of extension directory or directories + * Deprecated. This property, and the mechanism + * which implements it, may be removed in a future + * release.
os.nameOperating system name
os.archOperating system architecture
os.versionOperating system version
file.separatorFile separator ("/" on UNIX)
path.separatorPath separator (":" on UNIX)
line.separatorLine separator ("\n" on UNIX)
user.nameUser's account name
user.homeUser's home directory
user.dirUser's current working directory
+ *

+ * Multiple paths in a system property value are separated by the path + * separator character of the platform. + *

+ * Note that even if the security manager does not permit the + * getProperties operation, it may choose to permit the + * {@link #getProperty(String)} operation. + * + * @return the system properties + * @exception SecurityException if a security manager exists and its + * checkPropertiesAccess method doesn't allow access + * to the system properties. + * @see #setProperties + * @see java.lang.SecurityException + * @see java.lang.SecurityManager#checkPropertiesAccess() + * @see java.util.Properties + */ + public static Properties getProperties() { + SecurityManager sm = getSecurityManager(); + if (sm != null) { + sm.checkPropertiesAccess(); + } + + return props; + } + + /** + * Returns the system-dependent line separator string. It always + * returns the same value - the initial value of the {@linkplain + * #getProperty(String) system property} {@code line.separator}. + * + *

On UNIX systems, it returns {@code "\n"}; on Microsoft + * Windows systems it returns {@code "\r\n"}. + * + * @return the system-dependent line separator string + * @since 1.7 + */ + public static String lineSeparator() { + return lineSeparator; + } + + @ikvm.lang.Property(get="get_lineSeparator", set="set_lineSeparator") + private static String lineSeparator; + + private static String get_lineSeparator() { return Props.lineSeparator; } + private static void set_lineSeparator(String value) { Props.lineSeparator = value; } + + /** + * Sets the system properties to the Properties + * argument. + *

+ * First, if there is a security manager, its + * checkPropertiesAccess method is called with no + * arguments. This may result in a security exception. + *

+ * The argument becomes the current set of system properties for use + * by the {@link #getProperty(String)} method. If the argument is + * null, then the current set of system properties is + * forgotten. + * + * @param props the new system properties. + * @exception SecurityException if a security manager exists and its + * checkPropertiesAccess method doesn't allow access + * to the system properties. + * @see #getProperties + * @see java.util.Properties + * @see java.lang.SecurityException + * @see java.lang.SecurityManager#checkPropertiesAccess() + */ + public static void setProperties(Properties props) { + SecurityManager sm = getSecurityManager(); + if (sm != null) { + sm.checkPropertiesAccess(); + } + if (props == null) { + props = new Properties(); + initProperties(props); + } + System.props = props; + } + + /** + * Gets the system property indicated by the specified key. + *

+ * First, if there is a security manager, its + * checkPropertyAccess method is called with the key as + * its argument. This may result in a SecurityException. + *

+ * If there is no current set of system properties, a set of system + * properties is first created and initialized in the same manner as + * for the getProperties method. + * + * @param key the name of the system property. + * @return the string value of the system property, + * or null if there is no property with that key. + * + * @exception SecurityException if a security manager exists and its + * checkPropertyAccess method doesn't allow + * access to the specified system property. + * @exception NullPointerException if key is + * null. + * @exception IllegalArgumentException if key is empty. + * @see #setProperty + * @see java.lang.SecurityException + * @see java.lang.SecurityManager#checkPropertyAccess(java.lang.String) + * @see java.lang.System#getProperties() + */ + public static String getProperty(String key) { + checkKey(key); + SecurityManager sm = getSecurityManager(); + if (sm != null) { + sm.checkPropertyAccess(key); + } + + return props.getProperty(key); + } + + /** + * Gets the system property indicated by the specified key. + *

+ * First, if there is a security manager, its + * checkPropertyAccess method is called with the + * key as its argument. + *

+ * If there is no current set of system properties, a set of system + * properties is first created and initialized in the same manner as + * for the getProperties method. + * + * @param key the name of the system property. + * @param def a default value. + * @return the string value of the system property, + * or the default value if there is no property with that key. + * + * @exception SecurityException if a security manager exists and its + * checkPropertyAccess method doesn't allow + * access to the specified system property. + * @exception NullPointerException if key is + * null. + * @exception IllegalArgumentException if key is empty. + * @see #setProperty + * @see java.lang.SecurityManager#checkPropertyAccess(java.lang.String) + * @see java.lang.System#getProperties() + */ + public static String getProperty(String key, String def) { + checkKey(key); + SecurityManager sm = getSecurityManager(); + if (sm != null) { + sm.checkPropertyAccess(key); + } + + return props.getProperty(key, def); + } + + /** + * Sets the system property indicated by the specified key. + *

+ * First, if a security manager exists, its + * SecurityManager.checkPermission method + * is called with a PropertyPermission(key, "write") + * permission. This may result in a SecurityException being thrown. + * If no exception is thrown, the specified property is set to the given + * value. + *

+ * + * @param key the name of the system property. + * @param value the value of the system property. + * @return the previous value of the system property, + * or null if it did not have one. + * + * @exception SecurityException if a security manager exists and its + * checkPermission method doesn't allow + * setting of the specified property. + * @exception NullPointerException if key or + * value is null. + * @exception IllegalArgumentException if key is empty. + * @see #getProperty + * @see java.lang.System#getProperty(java.lang.String) + * @see java.lang.System#getProperty(java.lang.String, java.lang.String) + * @see java.util.PropertyPermission + * @see SecurityManager#checkPermission + * @since 1.2 + */ + public static String setProperty(String key, String value) { + checkKey(key); + SecurityManager sm = getSecurityManager(); + if (sm != null) { + sm.checkPermission(new PropertyPermission(key, + SecurityConstants.PROPERTY_WRITE_ACTION)); + } + + return (String) props.setProperty(key, value); + } + + /** + * Removes the system property indicated by the specified key. + *

+ * First, if a security manager exists, its + * SecurityManager.checkPermission method + * is called with a PropertyPermission(key, "write") + * permission. This may result in a SecurityException being thrown. + * If no exception is thrown, the specified property is removed. + *

+ * + * @param key the name of the system property to be removed. + * @return the previous string value of the system property, + * or null if there was no property with that key. + * + * @exception SecurityException if a security manager exists and its + * checkPropertyAccess method doesn't allow + * access to the specified system property. + * @exception NullPointerException if key is + * null. + * @exception IllegalArgumentException if key is empty. + * @see #getProperty + * @see #setProperty + * @see java.util.Properties + * @see java.lang.SecurityException + * @see java.lang.SecurityManager#checkPropertiesAccess() + * @since 1.5 + */ + public static String clearProperty(String key) { + checkKey(key); + SecurityManager sm = getSecurityManager(); + if (sm != null) { + sm.checkPermission(new PropertyPermission(key, "write")); + } + + return (String) props.remove(key); + } + + private static void checkKey(String key) { + if (key == null) { + throw new NullPointerException("key can't be null"); + } + if (key.equals("")) { + throw new IllegalArgumentException("key can't be empty"); + } + } + + /** + * Gets the value of the specified environment variable. An + * environment variable is a system-dependent external named + * value. + * + *

If a security manager exists, its + * {@link SecurityManager#checkPermission checkPermission} + * method is called with a + * {@link RuntimePermission}("getenv."+name) + * permission. This may result in a {@link SecurityException} + * being thrown. If no exception is thrown the value of the + * variable name is returned. + * + *

System + * properties and environment variables are both + * conceptually mappings between names and values. Both + * mechanisms can be used to pass user-defined information to a + * Java process. Environment variables have a more global effect, + * because they are visible to all descendants of the process + * which defines them, not just the immediate Java subprocess. + * They can have subtly different semantics, such as case + * insensitivity, on different operating systems. For these + * reasons, environment variables are more likely to have + * unintended side effects. It is best to use system properties + * where possible. Environment variables should be used when a + * global effect is desired, or when an external system interface + * requires an environment variable (such as PATH). + * + *

On UNIX systems the alphabetic case of name is + * typically significant, while on Microsoft Windows systems it is + * typically not. For example, the expression + * System.getenv("FOO").equals(System.getenv("foo")) + * is likely to be true on Microsoft Windows. + * + * @param name the name of the environment variable + * @return the string value of the variable, or null + * if the variable is not defined in the system environment + * @throws NullPointerException if name is null + * @throws SecurityException + * if a security manager exists and its + * {@link SecurityManager#checkPermission checkPermission} + * method doesn't allow access to the environment variable + * name + * @see #getenv() + * @see ProcessBuilder#environment() + */ + public static String getenv(String name) { + SecurityManager sm = getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("getenv."+name)); + } + + return ProcessEnvironment.getenv(name); + } + + + /** + * Returns an unmodifiable string map view of the current system environment. + * The environment is a system-dependent mapping from names to + * values which is passed from parent to child processes. + * + *

If the system does not support environment variables, an + * empty map is returned. + * + *

The returned map will never contain null keys or values. + * Attempting to query the presence of a null key or value will + * throw a {@link NullPointerException}. Attempting to query + * the presence of a key or value which is not of type + * {@link String} will throw a {@link ClassCastException}. + * + *

The returned map and its collection views may not obey the + * general contract of the {@link Object#equals} and + * {@link Object#hashCode} methods. + * + *

The returned map is typically case-sensitive on all platforms. + * + *

If a security manager exists, its + * {@link SecurityManager#checkPermission checkPermission} + * method is called with a + * {@link RuntimePermission}("getenv.*") + * permission. This may result in a {@link SecurityException} being + * thrown. + * + *

When passing information to a Java subprocess, + * system properties + * are generally preferred over environment variables. + * + * @return the environment as a map of variable names to values + * @throws SecurityException + * if a security manager exists and its + * {@link SecurityManager#checkPermission checkPermission} + * method doesn't allow access to the process environment + * @see #getenv(String) + * @see ProcessBuilder#environment() + * @since 1.5 + */ + public static java.util.Map getenv() { + SecurityManager sm = getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("getenv.*")); + } + + return ProcessEnvironment.getenv(); + } + + /** + * Terminates the currently running Java Virtual Machine. The + * argument serves as a status code; by convention, a nonzero status + * code indicates abnormal termination. + *

+ * This method calls the exit method in class + * Runtime. This method never returns normally. + *

+ * The call System.exit(n) is effectively equivalent to + * the call: + *

+     * Runtime.getRuntime().exit(n)
+     * 
+ * + * @param status exit status. + * @throws SecurityException + * if a security manager exists and its checkExit + * method doesn't allow exit with the specified status. + * @see java.lang.Runtime#exit(int) + */ + public static void exit(int status) { + Runtime.getRuntime().exit(status); + } + + /** + * Runs the garbage collector. + *

+ * Calling the gc method suggests that the Java Virtual + * Machine expend effort toward recycling unused objects in order to + * make the memory they currently occupy available for quick reuse. + * When control returns from the method call, the Java Virtual + * Machine has made a best effort to reclaim space from all discarded + * objects. + *

+ * The call System.gc() is effectively equivalent to the + * call: + *

+     * Runtime.getRuntime().gc()
+     * 
+ * + * @see java.lang.Runtime#gc() + */ + public static void gc() { + Runtime.getRuntime().gc(); + } + + /** + * Runs the finalization methods of any objects pending finalization. + *

+ * Calling this method suggests that the Java Virtual Machine expend + * effort toward running the finalize methods of objects + * that have been found to be discarded but whose finalize + * methods have not yet been run. When control returns from the + * method call, the Java Virtual Machine has made a best effort to + * complete all outstanding finalizations. + *

+ * The call System.runFinalization() is effectively + * equivalent to the call: + *

+     * Runtime.getRuntime().runFinalization()
+     * 
+ * + * @see java.lang.Runtime#runFinalization() + */ + public static void runFinalization() { + Runtime.getRuntime().runFinalization(); + } + + /** + * Enable or disable finalization on exit; doing so specifies that the + * finalizers of all objects that have finalizers that have not yet been + * automatically invoked are to be run before the Java runtime exits. + * By default, finalization on exit is disabled. + * + *

If there is a security manager, + * its checkExit method is first called + * with 0 as its argument to ensure the exit is allowed. + * This could result in a SecurityException. + * + * @deprecated This method is inherently unsafe. It may result in + * finalizers being called on live objects while other threads are + * concurrently manipulating those objects, resulting in erratic + * behavior or deadlock. + * @param value indicating enabling or disabling of finalization + * @throws SecurityException + * if a security manager exists and its checkExit + * method doesn't allow the exit. + * + * @see java.lang.Runtime#exit(int) + * @see java.lang.Runtime#gc() + * @see java.lang.SecurityManager#checkExit(int) + * @since JDK1.1 + */ + @Deprecated + public static void runFinalizersOnExit(boolean value) { + Runtime.runFinalizersOnExit(value); + } + + /** + * Loads the native library specified by the filename argument. The filename + * argument must be an absolute path name. + * + * If the filename argument, when stripped of any platform-specific library + * prefix, path, and file extension, indicates a library whose name is, + * for example, L, and a native library called L is statically linked + * with the VM, then the JNI_OnLoad_L function exported by the library + * is invoked rather than attempting to load a dynamic library. + * A filename matching the argument does not have to exist in the + * file system. + * See the JNI Specification for more details. + * + * Otherwise, the filename argument is mapped to a native library image in + * an implementation-dependent manner. + * + *

+ * The call System.load(name) is effectively equivalent + * to the call: + *

+     * Runtime.getRuntime().load(name)
+     * 
+ * + * @param filename the file to load. + * @exception SecurityException if a security manager exists and its + * checkLink method doesn't allow + * loading of the specified dynamic library + * @exception UnsatisfiedLinkError if either the filename is not an + * absolute path name, the native library is not statically + * linked with the VM, or the library cannot be mapped to + * a native library image by the host system. + * @exception NullPointerException if filename is + * null + * @see java.lang.Runtime#load(java.lang.String) + * @see java.lang.SecurityManager#checkLink(java.lang.String) + */ + @CallerSensitive + public static void load(String filename) { + Runtime.getRuntime().load0(Reflection.getCallerClass(), filename); + } + + /** + * Loads the native library specified by the libname + * argument. The libname argument must not contain any platform + * specific prefix, file extension or path. If a native library + * called libname is statically linked with the VM, then the + * JNI_OnLoad_libname function exported by the library is invoked. + * See the JNI Specification for more details. + * + * Otherwise, the libname argument is loaded from a system library + * location and mapped to a native library image in an implementation- + * dependent manner. + *

+ * The call System.loadLibrary(name) is effectively + * equivalent to the call + *

+     * Runtime.getRuntime().loadLibrary(name)
+     * 
+ * + * @param libname the name of the library. + * @exception SecurityException if a security manager exists and its + * checkLink method doesn't allow + * loading of the specified dynamic library + * @exception UnsatisfiedLinkError if either the libname argument + * contains a file path, the native library is not statically + * linked with the VM, or the library cannot be mapped to a + * native library image by the host system. + * @exception NullPointerException if libname is + * null + * @see java.lang.Runtime#loadLibrary(java.lang.String) + * @see java.lang.SecurityManager#checkLink(java.lang.String) + */ + @CallerSensitive + public static void loadLibrary(String libname) { + Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname); + } + + /** + * Maps a library name into a platform-specific string representing + * a native library. + * + * @param libname the name of the library. + * @return a platform-dependent native library name. + * @exception NullPointerException if libname is + * null + * @see java.lang.System#loadLibrary(java.lang.String) + * @see java.lang.ClassLoader#findLibrary(java.lang.String) + * @since 1.2 + */ + public static native String mapLibraryName(String libname); + + /** + * Create PrintStream for stdout/err based on encoding. + */ + /*private*/ static PrintStream newPrintStream(FileOutputStream fos, String enc) { + if (enc != null) { + try { + return new PrintStream(new BufferedOutputStream(fos, 128), true, enc); + } catch (UnsupportedEncodingException uee) {} + } + return new PrintStream(new BufferedOutputStream(fos, 128), true); + } +} diff --git a/openjdk/java/lang/Thread.java b/openjdk/java/lang/Thread.java new file mode 100644 index 0000000..1341a01 --- /dev/null +++ b/openjdk/java/lang/Thread.java @@ -0,0 +1,2593 @@ +/* + * Copyright (c) 1994, 2013, 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 java.lang; + +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.security.AccessController; +import java.security.AccessControlContext; +import java.security.PrivilegedAction; +import java.util.Map; +import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.locks.LockSupport; +import sun.nio.ch.Interruptible; +import sun.reflect.CallerSensitive; +import sun.reflect.Reflection; +import sun.security.util.SecurityConstants; + + +/** + * A thread is a thread of execution in a program. The Java + * Virtual Machine allows an application to have multiple threads of + * execution running concurrently. + *

+ * Every thread has a priority. Threads with higher priority are + * executed in preference to threads with lower priority. Each thread + * may or may not also be marked as a daemon. When code running in + * some thread creates a new Thread object, the new + * thread has its priority initially set equal to the priority of the + * creating thread, and is a daemon thread if and only if the + * creating thread is a daemon. + *

+ * When a Java Virtual Machine starts up, there is usually a single + * non-daemon thread (which typically calls the method named + * main of some designated class). The Java Virtual + * Machine continues to execute threads until either of the following + * occurs: + *

    + *
  • The exit method of class Runtime has been + * called and the security manager has permitted the exit operation + * to take place. + *
  • All threads that are not daemon threads have died, either by + * returning from the call to the run method or by + * throwing an exception that propagates beyond the run + * method. + *
+ *

+ * There are two ways to create a new thread of execution. One is to + * declare a class to be a subclass of Thread. This + * subclass should override the run method of class + * Thread. An instance of the subclass can then be + * allocated and started. For example, a thread that computes primes + * larger than a stated value could be written as follows: + *


+ *     class PrimeThread extends Thread {
+ *         long minPrime;
+ *         PrimeThread(long minPrime) {
+ *             this.minPrime = minPrime;
+ *         }
+ *
+ *         public void run() {
+ *             // compute primes larger than minPrime
+ *              . . .
+ *         }
+ *     }
+ * 

+ *

+ * The following code would then create a thread and start it running: + *

+ *     PrimeThread p = new PrimeThread(143);
+ *     p.start();
+ * 
+ *

+ * The other way to create a thread is to declare a class that + * implements the Runnable interface. That class then + * implements the run method. An instance of the class can + * then be allocated, passed as an argument when creating + * Thread, and started. The same example in this other + * style looks like the following: + *


+ *     class PrimeRun implements Runnable {
+ *         long minPrime;
+ *         PrimeRun(long minPrime) {
+ *             this.minPrime = minPrime;
+ *         }
+ *
+ *         public void run() {
+ *             // compute primes larger than minPrime
+ *              . . .
+ *         }
+ *     }
+ * 

+ *

+ * The following code would then create a thread and start it running: + *

+ *     PrimeRun p = new PrimeRun(143);
+ *     new Thread(p).start();
+ * 
+ *

+ * Every thread has a name for identification purposes. More than + * one thread may have the same name. If a name is not specified when + * a thread is created, a new name is generated for it. + *

+ * Unless otherwise noted, passing a {@code null} argument to a constructor + * or method in this class will cause a {@link NullPointerException} to be + * thrown. + * + * @author unascribed + * @see Runnable + * @see Runtime#exit(int) + * @see #run() + * @see #stop() + * @since JDK1.0 + */ +public +class Thread implements Runnable { + // [IKVM] + static { + // force the set/getContextClassLoader methods to be JIT compiled, because isCCLOverridden(Thread) depends on it + // (we don't want to use RuntimeHelpers.PrepareMethod() because it requires full trust) + Thread dummy = new Thread((Void)null); + dummy.getContextClassLoader(); + dummy.setContextClassLoader(ClassLoader.DUMMY); + } + private Thread(Void _) { + // body replaced in map.xml + } + final class Cleanup { + protected void finalize() { + Thread.this.die(); + } + } + /* --- start IKVM specific state --- */ + static final int[] nonDaemonCount = new int[1]; + @cli.System.ThreadStaticAttribute.Annotation + static Thread current; + @cli.System.ThreadStaticAttribute.Annotation + private static Cleanup cleanup; + private final Object lock = new Object(); + private cli.System.Threading.Thread nativeThread; + private Throwable stillborn; + private boolean running; // used only for coordination with stop0(), is never set to false + private volatile boolean interruptPending; + private volatile boolean nativeInterruptPending; + private volatile boolean interruptableWait; + private boolean timedWait; + volatile Object parkLock; // used by get/setParkLock in map.xml + int parkState; // used by cmpxchgParkState in map.xml + /* --- end IKVM specific state --- */ + + private volatile char name[]; + private int priority; + private Thread threadQ; + private long eetop; + + /* Whether or not to single_step this thread. */ + private boolean single_step; + + /* Whether or not the thread is a daemon thread. */ + private boolean daemon = false; + + /* What will be run. */ + private Runnable target; + + /* The group of this thread */ + private ThreadGroup group; + + /* The context ClassLoader for this thread */ + private volatile ClassLoader contextClassLoader; + + /* The inherited AccessControlContext of this thread */ + /* [IKVM] this contains either an AccessControlContext or an AccessController.LazyContext */ + Object inheritedAccessControlContext; + + /* For autonumbering anonymous threads. */ + private static int threadInitNumber; + private static synchronized int nextThreadNum() { + return threadInitNumber++; + } + + /* ThreadLocal values pertaining to this thread. This map is maintained + * by the ThreadLocal class. */ + ThreadLocal.ThreadLocalMap threadLocals = null; + + /* + * InheritableThreadLocal values pertaining to this thread. This map is + * maintained by the InheritableThreadLocal class. + */ + ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; + + /* + * The requested stack size for this thread, or 0 if the creator did + * not specify a stack size. It is up to the VM to do whatever it + * likes with this number; some VMs will ignore it. + */ + private long stackSize; + + /* + * JVM-private state that persists after native thread termination. + */ + private long nativeParkEventPointer; + + /* + * Thread ID + */ + private long tid; + + /* For generating thread ID */ + private static long threadSeqNumber; + + /* Java thread status for tools, + * initialized to indicate thread 'not yet started' + */ + + private volatile int threadStatus = 0; + + + private static synchronized long nextThreadID() { + return ++threadSeqNumber; + } + + /** + * The argument supplied to the current call to + * java.util.concurrent.locks.LockSupport.park. + * Set by (private) java.util.concurrent.locks.LockSupport.setBlocker + * Accessed using java.util.concurrent.locks.LockSupport.getBlocker + */ + @ikvm.lang.Internal // [IKVM] accessed from java.util.concurrent + public volatile Object parkBlocker; + + /* The object in which this thread is blocked in an interruptible I/O + * operation, if any. The blocker's interrupt method should be invoked + * after setting this thread's interrupt status. + */ + private volatile Interruptible blocker; + private final Object blockerLock = new Object(); + + /* Set the blocker field; invoked via sun.misc.SharedSecrets from java.nio code + */ + void blockedOn(Interruptible b) { + synchronized (blockerLock) { + blocker = b; + } + } + + /** + * The minimum priority that a thread can have. + */ + public final static int MIN_PRIORITY = 1; + + /** + * The default priority that is assigned to a thread. + */ + public final static int NORM_PRIORITY = 5; + + /** + * The maximum priority that a thread can have. + */ + public final static int MAX_PRIORITY = 10; + + /** + * Returns a reference to the currently executing thread object. + * + * @return the currently executing thread. + */ + public static Thread currentThread() { + Thread c = current; + if (c == null) { + c = new Thread(getMainThreadGroup()); + } + return c; + } + + private static native ThreadGroup getMainThreadGroup(); + + /** + * A hint to the scheduler that the current thread is willing to yield + * its current use of a processor. The scheduler is free to ignore this + * hint. + * + *

Yield is a heuristic attempt to improve relative progression + * between threads that would otherwise over-utilise a CPU. Its use + * should be combined with detailed profiling and benchmarking to + * ensure that it actually has the desired effect. + * + *

It is rarely appropriate to use this method. It may be useful + * for debugging or testing purposes, where it may help to reproduce + * bugs due to race conditions. It may also be useful when designing + * concurrency control constructs such as the ones in the + * {@link java.util.concurrent.locks} package. + */ + public static void yield() { + cli.System.Threading.Thread.Sleep(0); + } + + private void enterInterruptableWait(boolean timedWait) throws InterruptedException { + synchronized (lock) { + if (interruptPending) { + interruptPending = false; + throw new InterruptedException(); + } + interruptableWait = true; + this.timedWait = timedWait; + } + } + + private void leaveInterruptableWait() throws InterruptedException { + cli.System.Threading.ThreadInterruptedException dotnetInterrupt = null; + interruptableWait = false; + for (; ; ) { + try { + if (false) throw new cli.System.Threading.ThreadInterruptedException(); + synchronized (lock) { + if (nativeInterruptPending) { + nativeInterruptPending = false; + // HACK if there is a pending Interrupt (on the .NET thread), we need to consume that + // (if there was no contention on "lock (this)" above the interrupted state isn't checked) + try { + if (false) throw new cli.System.Threading.ThreadInterruptedException(); + cli.System.Threading.Thread t = cli.System.Threading.Thread.get_CurrentThread(); + // the obvious thing to do would be t.Interrupt() / t.Join(), + // but for some reason that causes a regression in JSR166TestCase (probably a CLR bug) + // so we waste a time slice... sigh. + t.Join(1); + } + catch (cli.System.Threading.ThreadInterruptedException _) { + } + } + if (interruptPending) { + interruptPending = false; + throw new InterruptedException(); + } + } + break; + } + catch (cli.System.Threading.ThreadInterruptedException x) { + dotnetInterrupt = x; + nativeInterruptPending = false; + } + } + if (dotnetInterrupt != null) { + ikvm.runtime.Util.throwException(dotnetInterrupt); + } + } + + /** + * Causes the currently executing thread to sleep (temporarily cease + * execution) for the specified number of milliseconds, subject to + * the precision and accuracy of system timers and schedulers. The thread + * does not lose ownership of any monitors. + * + * @param millis + * the length of time to sleep in milliseconds + * + * @throws IllegalArgumentException + * if the value of {@code millis} is negative + * + * @throws InterruptedException + * if any thread has interrupted the current thread. The + * interrupted status of the current thread is + * cleared when this exception is thrown. + */ + public static void sleep(long millis) throws InterruptedException { + if (millis < 0) { + throw new IllegalArgumentException("timeout value is negative"); + } + Thread c = currentThread(); + c.enterInterruptableWait(true); + try { + if (false) throw new cli.System.Threading.ThreadInterruptedException(); + for (long iter = millis / Integer.MAX_VALUE; iter != 0; iter--) + { + cli.System.Threading.Thread.Sleep(Integer.MAX_VALUE); + } + cli.System.Threading.Thread.Sleep((int)(millis % Integer.MAX_VALUE)); + } + catch (cli.System.Threading.ThreadInterruptedException _) { + } + finally { + c.leaveInterruptableWait(); + } + } + + /** + * Causes the currently executing thread to sleep (temporarily cease + * execution) for the specified number of milliseconds plus the specified + * number of nanoseconds, subject to the precision and accuracy of system + * timers and schedulers. The thread does not lose ownership of any + * monitors. + * + * @param millis + * the length of time to sleep in milliseconds + * + * @param nanos + * {@code 0-999999} additional nanoseconds to sleep + * + * @throws IllegalArgumentException + * if the value of {@code millis} is negative, or the value of + * {@code nanos} is not in the range {@code 0-999999} + * + * @throws InterruptedException + * if any thread has interrupted the current thread. The + * interrupted status of the current thread is + * cleared when this exception is thrown. + */ + public static void sleep(long millis, int nanos) + throws InterruptedException { + if (millis < 0) { + throw new IllegalArgumentException("timeout value is negative"); + } + + if (nanos < 0 || nanos > 999999) { + throw new IllegalArgumentException( + "nanosecond timeout value out of range"); + } + + if (nanos >= 500000 || (nanos != 0 && millis == 0)) { + millis++; + } + + sleep(millis); + } + + /** + * Initializes a Thread with the current AccessControlContext. + * @see #init(ThreadGroup,Runnable,String,long,AccessControlContext) + */ + private void init(ThreadGroup g, Runnable target, String name, + long stackSize) { + init(g, target, name, stackSize, null); + } + + /** + * Initializes a Thread. + * + * @param g the Thread group + * @param target the object whose run() method gets called + * @param name the name of the new Thread + * @param stackSize the desired stack size for the new thread, or + * zero to indicate that this parameter is to be ignored. + * @param acc the AccessControlContext to inherit, or + * AccessController.getContext() if null + */ + private void init(ThreadGroup g, Runnable target, String name, + long stackSize, AccessControlContext acc) { + if (name == null) { + throw new NullPointerException("name cannot be null"); + } + + this.name = name.toCharArray(); + + Thread parent = currentThread(); + SecurityManager security = System.getSecurityManager(); + if (g == null) { + /* Determine if it's an applet or not */ + + /* If there is a security manager, ask the security manager + what to do. */ + if (security != null) { + g = security.getThreadGroup(); + } + + /* If the security doesn't have a strong opinion of the matter + use the parent thread group. */ + if (g == null) { + g = parent.getThreadGroup(); + } + } + + /* checkAccess regardless of whether or not threadgroup is + explicitly passed in. */ + g.checkAccess(); + + /* + * Do we have the required permissions? + */ + if (security != null) { + if (isCCLOverridden(this)) { + security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); + } + } + + g.addUnstarted(); + + this.group = g; + this.daemon = parent.isDaemon(); + this.priority = parent.getPriority(); + if (isCCLOverridden(parent)) + this.contextClassLoader = parent.getContextClassLoader(); + else + this.contextClassLoader = parent.contextClassLoader; + this.inheritedAccessControlContext = + acc != null ? acc : AccessController.getLazyContext(parent.inheritedAccessControlContext); + this.target = target; + setPriority(priority); + if (parent.inheritableThreadLocals != null) + this.inheritableThreadLocals = + ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); + /* Stash the specified stack size in case the VM cares */ + this.stackSize = stackSize; + + /* Set thread ID */ + tid = nextThreadID(); + } + + // [IKVM] constructor for attaching to a .NET thread + Thread(ThreadGroup g) { + this.running = true; + cli.System.Threading.Thread thread = cli.System.Threading.Thread.get_CurrentThread(); + nativeThread = thread; + String name = thread.get_Name(); + if (name == null) { + name = "Thread-" + nextThreadNum(); + } + + this.group = g; + this.daemon = thread.get_IsBackground(); + this.priority = mapClrPriorityToJava(thread.get_Priority().Value); + this.name = name.toCharArray(); + this.contextClassLoader = ClassLoader.DUMMY; + this.threadStatus = 0x0005; /* JVMTI_THREAD_STATE_ALIVE + JVMTI_THREAD_STATE_RUNNABLE */ + + /* Set thread ID */ + tid = nextThreadID(); + + synchronized (g) { + g.addUnstarted(); + g.add(this); + } + + current = this; + cleanup = new Cleanup(); + + if (!daemon) { + cli.System.Threading.Interlocked.Increment(nonDaemonCount); + } + } + + private static int mapClrPriorityToJava(int priority) { + // TODO consider supporting -XX:JavaPriorityX_To_OSPriority settings + switch (priority) { + case cli.System.Threading.ThreadPriority.Lowest: + return MIN_PRIORITY; + case cli.System.Threading.ThreadPriority.BelowNormal: + return 3; + default: + case cli.System.Threading.ThreadPriority.Normal: + return NORM_PRIORITY; + case cli.System.Threading.ThreadPriority.AboveNormal: + return 7; + case cli.System.Threading.ThreadPriority.Highest: + return MAX_PRIORITY; + } + } + + private static int mapJavaPriorityToClr(int priority) { + // TODO consider supporting -XX:JavaPriorityX_To_OSPriority settings + if (priority == MIN_PRIORITY) { + return cli.System.Threading.ThreadPriority.Lowest; + } + else if (priority > Thread.MIN_PRIORITY && priority < Thread.NORM_PRIORITY) { + return cli.System.Threading.ThreadPriority.BelowNormal; + } + else if (priority == Thread.NORM_PRIORITY) { + return cli.System.Threading.ThreadPriority.Normal; + } + else if (priority > Thread.NORM_PRIORITY && priority < Thread.MAX_PRIORITY) { + return cli.System.Threading.ThreadPriority.AboveNormal; + } + else if (priority == Thread.MAX_PRIORITY) { + return cli.System.Threading.ThreadPriority.Highest; + } + else { + // can't happen + return cli.System.Threading.ThreadPriority.Normal; + } + } + + /** + * Throws CloneNotSupportedException as a Thread can not be meaningfully + * cloned. Construct a new Thread instead. + * + * @throws CloneNotSupportedException + * always + */ + @Override + protected Object clone() throws CloneNotSupportedException { + throw new CloneNotSupportedException(); + } + + /** + * Allocates a new {@code Thread} object. This constructor has the same + * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} + * {@code (null, null, gname)}, where {@code gname} is a newly generated + * name. Automatically generated names are of the form + * {@code "Thread-"+}n, where n is an integer. + */ + public Thread() { + init(null, null, "Thread-" + nextThreadNum(), 0); + } + + /** + * Allocates a new {@code Thread} object. This constructor has the same + * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} + * {@code (null, target, gname)}, where {@code gname} is a newly generated + * name. Automatically generated names are of the form + * {@code "Thread-"+}n, where n is an integer. + * + * @param target + * the object whose {@code run} method is invoked when this thread + * is started. If {@code null}, this classes {@code run} method does + * nothing. + */ + public Thread(Runnable target) { + init(null, target, "Thread-" + nextThreadNum(), 0); + } + + /** + * Creates a new Thread that inherits the given AccessControlContext. + * This is not a public constructor. + */ + Thread(Runnable target, AccessControlContext acc) { + init(null, target, "Thread-" + nextThreadNum(), 0, acc); + } + + /** + * Allocates a new {@code Thread} object. This constructor has the same + * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} + * {@code (group, target, gname)} ,where {@code gname} is a newly generated + * name. Automatically generated names are of the form + * {@code "Thread-"+}n, where n is an integer. + * + * @param group + * the thread group. If {@code null} and there is a security + * manager, the group is determined by {@linkplain + * SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}. + * If there is not a security manager or {@code + * SecurityManager.getThreadGroup()} returns {@code null}, the group + * is set to the current thread's thread group. + * + * @param target + * the object whose {@code run} method is invoked when this thread + * is started. If {@code null}, this thread's run method is invoked. + * + * @throws SecurityException + * if the current thread cannot create a thread in the specified + * thread group + */ + public Thread(ThreadGroup group, Runnable target) { + init(group, target, "Thread-" + nextThreadNum(), 0); + } + + /** + * Allocates a new {@code Thread} object. This constructor has the same + * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} + * {@code (null, null, name)}. + * + * @param name + * the name of the new thread + */ + public Thread(String name) { + init(null, null, name, 0); + } + + /** + * Allocates a new {@code Thread} object. This constructor has the same + * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} + * {@code (group, null, name)}. + * + * @param group + * the thread group. If {@code null} and there is a security + * manager, the group is determined by {@linkplain + * SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}. + * If there is not a security manager or {@code + * SecurityManager.getThreadGroup()} returns {@code null}, the group + * is set to the current thread's thread group. + * + * @param name + * the name of the new thread + * + * @throws SecurityException + * if the current thread cannot create a thread in the specified + * thread group + */ + public Thread(ThreadGroup group, String name) { + init(group, null, name, 0); + } + + /** + * Allocates a new {@code Thread} object. This constructor has the same + * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} + * {@code (null, target, name)}. + * + * @param target + * the object whose {@code run} method is invoked when this thread + * is started. If {@code null}, this thread's run method is invoked. + * + * @param name + * the name of the new thread + */ + public Thread(Runnable target, String name) { + init(null, target, name, 0); + } + + /** + * Allocates a new {@code Thread} object so that it has {@code target} + * as its run object, has the specified {@code name} as its name, + * and belongs to the thread group referred to by {@code group}. + * + *

If there is a security manager, its + * {@link SecurityManager#checkAccess(ThreadGroup) checkAccess} + * method is invoked with the ThreadGroup as its argument. + * + *

In addition, its {@code checkPermission} method is invoked with + * the {@code RuntimePermission("enableContextClassLoaderOverride")} + * permission when invoked directly or indirectly by the constructor + * of a subclass which overrides the {@code getContextClassLoader} + * or {@code setContextClassLoader} methods. + * + *

The priority of the newly created thread is set equal to the + * priority of the thread creating it, that is, the currently running + * thread. The method {@linkplain #setPriority setPriority} may be + * used to change the priority to a new value. + * + *

The newly created thread is initially marked as being a daemon + * thread if and only if the thread creating it is currently marked + * as a daemon thread. The method {@linkplain #setDaemon setDaemon} + * may be used to change whether or not a thread is a daemon. + * + * @param group + * the thread group. If {@code null} and there is a security + * manager, the group is determined by {@linkplain + * SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}. + * If there is not a security manager or {@code + * SecurityManager.getThreadGroup()} returns {@code null}, the group + * is set to the current thread's thread group. + * + * @param target + * the object whose {@code run} method is invoked when this thread + * is started. If {@code null}, this thread's run method is invoked. + * + * @param name + * the name of the new thread + * + * @throws SecurityException + * if the current thread cannot create a thread in the specified + * thread group or cannot override the context class loader methods. + */ + public Thread(ThreadGroup group, Runnable target, String name) { + init(group, target, name, 0); + } + + /** + * Allocates a new {@code Thread} object so that it has {@code target} + * as its run object, has the specified {@code name} as its name, + * and belongs to the thread group referred to by {@code group}, and has + * the specified stack size. + * + *

This constructor is identical to {@link + * #Thread(ThreadGroup,Runnable,String)} with the exception of the fact + * that it allows the thread stack size to be specified. The stack size + * is the approximate number of bytes of address space that the virtual + * machine is to allocate for this thread's stack. The effect of the + * {@code stackSize} parameter, if any, is highly platform dependent. + * + *

On some platforms, specifying a higher value for the + * {@code stackSize} parameter may allow a thread to achieve greater + * recursion depth before throwing a {@link StackOverflowError}. + * Similarly, specifying a lower value may allow a greater number of + * threads to exist concurrently without throwing an {@link + * OutOfMemoryError} (or other internal error). The details of + * the relationship between the value of the stackSize parameter + * and the maximum recursion depth and concurrency level are + * platform-dependent. On some platforms, the value of the + * {@code stackSize} parameter may have no effect whatsoever. + * + *

The virtual machine is free to treat the {@code stackSize} + * parameter as a suggestion. If the specified value is unreasonably low + * for the platform, the virtual machine may instead use some + * platform-specific minimum value; if the specified value is unreasonably + * high, the virtual machine may instead use some platform-specific + * maximum. Likewise, the virtual machine is free to round the specified + * value up or down as it sees fit (or to ignore it completely). + * + *

Specifying a value of zero for the {@code stackSize} parameter will + * cause this constructor to behave exactly like the + * {@code Thread(ThreadGroup, Runnable, String)} constructor. + * + *

Due to the platform-dependent nature of the behavior of this + * constructor, extreme care should be exercised in its use. + * The thread stack size necessary to perform a given computation will + * likely vary from one JRE implementation to another. In light of this + * variation, careful tuning of the stack size parameter may be required, + * and the tuning may need to be repeated for each JRE implementation on + * which an application is to run. + * + *

Implementation note: Java platform implementers are encouraged to + * document their implementation's behavior with respect to the + * {@code stackSize} parameter. + * + * + * @param group + * the thread group. If {@code null} and there is a security + * manager, the group is determined by {@linkplain + * SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}. + * If there is not a security manager or {@code + * SecurityManager.getThreadGroup()} returns {@code null}, the group + * is set to the current thread's thread group. + * + * @param target + * the object whose {@code run} method is invoked when this thread + * is started. If {@code null}, this thread's run method is invoked. + * + * @param name + * the name of the new thread + * + * @param stackSize + * the desired stack size for the new thread, or zero to indicate + * that this parameter is to be ignored. + * + * @throws SecurityException + * if the current thread cannot create a thread in the specified + * thread group + * + * @since 1.4 + */ + public Thread(ThreadGroup group, Runnable target, String name, + long stackSize) { + init(group, target, name, stackSize); + } + + /** + * Causes this thread to begin execution; the Java Virtual Machine + * calls the run method of this thread. + *

+ * The result is that two threads are running concurrently: the + * current thread (which returns from the call to the + * start method) and the other thread (which executes its + * run method). + *

+ * It is never legal to start a thread more than once. + * In particular, a thread may not be restarted once it has completed + * execution. + * + * @exception IllegalThreadStateException if the thread was already + * started. + * @see #run() + * @see #stop() + */ + public synchronized void start() { + /** + * This method is not invoked for the main method thread or "system" + * group threads created/set up by the VM. Any new functionality added + * to this method in the future may have to also be added to the VM. + * + * A zero status value corresponds to state "NEW". + */ + if (threadStatus != 0) + throw new IllegalThreadStateException(); + + /* Notify the group that this thread is about to be started + * so that it can be added to the group's list of threads + * and the group's unstarted count can be decremented. */ + group.add(this); + + boolean started = false; + try { + start0(); + started = true; + } finally { + try { + if (!started) { + group.threadStartFailed(this); + } + } catch (Throwable ignore) { + /* do nothing. If start0 threw a Throwable then + it will be passed up the call stack */ + } + } + } + + private void start0() { + cli.System.Threading.ThreadStart threadStart = new cli.System.Threading.ThreadStart(new cli.System.Threading.ThreadStart.Method() { + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + public void Invoke() { + threadProc(); + } + }); + if (stackSize <= 0) { + nativeThread = new cli.System.Threading.Thread(threadStart); + } + else { + int maxStackSize = (int)Math.min(Math.max(128 * 1024, stackSize), Integer.MAX_VALUE); + nativeThread = new cli.System.Threading.Thread(threadStart, maxStackSize); + } + nativeThread.set_Name(getName()); + nativeThread.set_IsBackground(daemon); + nativeThread.set_Priority(cli.System.Threading.ThreadPriority.wrap(mapJavaPriorityToClr(priority))); + String apartment = Props.props.getProperty("ikvm.apartmentstate", "").toLowerCase(); + if ("mta".equals(apartment)) { + nativeThread.SetApartmentState(cli.System.Threading.ApartmentState.wrap(cli.System.Threading.ApartmentState.MTA)); + } + else if ("sta".equals(apartment)) { + nativeThread.SetApartmentState(cli.System.Threading.ApartmentState.wrap(cli.System.Threading.ApartmentState.STA)); + } + threadStatus = 0x0005; // JVMTI_THREAD_STATE_ALIVE + JVMTI_THREAD_STATE_RUNNABLE + nativeThread.Start(); + if (!daemon) { + cli.System.Threading.Interlocked.Increment(nonDaemonCount); + } + } + + /** + * If this thread was constructed using a separate + * Runnable run object, then that + * Runnable object's run method is called; + * otherwise, this method does nothing and returns. + *

+ * Subclasses of Thread should override this method. + * + * @see #start() + * @see #stop() + * @see #Thread(ThreadGroup, Runnable, String) + */ + @Override + public void run() { + if (target != null) { + target.run(); + } + } + + // [IKVM] for threads started from Java, this method is called on the thread itself, + // but for .NET threads it will be called by the finalizer of the Cleanup object. + // NOTE there might be a race condition here (when the thread's Cleanup object + // is finalized during AppDomain shutdown while the thread is also exiting on its own), + // but that doesn't matter because Thread.exit() is safe to call multiple times. + void die() { + exit(); + synchronized (lock) { + nativeThread = null; + threadStatus = 0x0002; // JVMTI_THREAD_STATE_TERMINATED + } + wakeupJoinedThreads(); + if (!daemon) { + // TODO there is a race condition in the non-daemon counting + // (setDaemon() isn't synchronized so it may clear/set the daemon flag without the count being affected) + cli.System.Threading.Interlocked.Decrement(nonDaemonCount); + } + if (current == this) { + current = null; + // check if we have a cleanup object, this happens if we attach and subsequently detach from JNI code + if (cleanup != null) { + cli.System.GC.SuppressFinalize(cleanup); + cleanup = null; + } + } + } + + private void wakeupJoinedThreads() { + // HACK locking this here isn't ideal, because we might be invoked from + // the Cleanup object's finalizer and some user code might own the lock and hence + // block the finalizer thread. + // A second scenario is that another thread is currently blocking inside stop() + // (the Thread.Abort() call will block while we are running the finally block) + // and that thread will own the lock on our thread object. + boolean locked = false; + try { + locked = cli.System.Threading.Monitor.TryEnter(this); + if (locked) { + notifyAll(); + } else { + // HACK schedule an asynchronous notification + cli.System.Threading.ThreadPool.QueueUserWorkItem( + new cli.System.Threading.WaitCallback( + new cli.System.Threading.WaitCallback.Method() { + public void Invoke(Object thread) { + synchronized (thread) { + thread.notifyAll(); + } + } + }), this); + } + } + finally { + if (locked) + cli.System.Threading.Monitor.Exit(this); + } + } + + /** + * This method is called by the system to give a Thread + * a chance to clean up before it actually exits. + */ + private void exit() { + if (group != null) { + group.threadTerminated(this); + group = null; + } + /* Aggressively null out all reference fields: see bug 4006245 */ + target = null; + /* Speed the release of some of these resources */ + threadLocals = null; + inheritableThreadLocals = null; + inheritedAccessControlContext = null; + blocker = null; + uncaughtExceptionHandler = null; + } + + /** + * Forces the thread to stop executing. + *

+ * If there is a security manager installed, its checkAccess + * method is called with this + * as its argument. This may result in a + * SecurityException being raised (in the current thread). + *

+ * If this thread is different from the current thread (that is, the current + * thread is trying to stop a thread other than itself), the + * security manager's checkPermission method (with a + * RuntimePermission("stopThread") argument) is called in + * addition. + * Again, this may result in throwing a + * SecurityException (in the current thread). + *

+ * The thread represented by this thread is forced to stop whatever + * it is doing abnormally and to throw a newly created + * ThreadDeath object as an exception. + *

+ * It is permitted to stop a thread that has not yet been started. + * If the thread is eventually started, it immediately terminates. + *

+ * An application should not normally try to catch + * ThreadDeath unless it must do some extraordinary + * cleanup operation (note that the throwing of + * ThreadDeath causes finally clauses of + * try statements to be executed before the thread + * officially dies). If a catch clause catches a + * ThreadDeath object, it is important to rethrow the + * object so that the thread actually dies. + *

+ * The top-level error handler that reacts to otherwise uncaught + * exceptions does not print out a message or otherwise notify the + * application if the uncaught exception is an instance of + * ThreadDeath. + * + * @exception SecurityException if the current thread cannot + * modify this thread. + * @see #interrupt() + * @see #checkAccess() + * @see #run() + * @see #start() + * @see ThreadDeath + * @see ThreadGroup#uncaughtException(Thread,Throwable) + * @see SecurityManager#checkAccess(Thread) + * @see SecurityManager#checkPermission + * @deprecated This method is inherently unsafe. Stopping a thread with + * Thread.stop causes it to unlock all of the monitors that it + * has locked (as a natural consequence of the unchecked + * ThreadDeath exception propagating up the stack). If + * any of the objects previously protected by these monitors were in + * an inconsistent state, the damaged objects become visible to + * other threads, potentially resulting in arbitrary behavior. Many + * uses of stop should be replaced by code that simply + * modifies some variable to indicate that the target thread should + * stop running. The target thread should check this variable + * regularly, and return from its run method in an orderly fashion + * if the variable indicates that it is to stop running. If the + * target thread waits for long periods (on a condition variable, + * for example), the interrupt method should be used to + * interrupt the wait. + * For more information, see + * Why + * are Thread.stop, Thread.suspend and Thread.resume Deprecated?. + */ + @Deprecated + public final void stop() { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + checkAccess(); + if (this != Thread.currentThread()) { + security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION); + } + } + // A zero status value corresponds to "NEW", it can't change to + // not-NEW because we hold the lock. + if (threadStatus != 0) { + resume(); // Wake up thread if it was suspended; no-op otherwise + } + + // The VM can handle all thread states + stop0(new ThreadDeath()); + } + + /** + * Throws {@code UnsupportedOperationException}. + * + * @param obj ignored + * + * @deprecated This method was originally designed to force a thread to stop + * and throw a given {@code Throwable} as an exception. It was + * inherently unsafe (see {@link #stop()} for details), and furthermore + * could be used to generate exceptions that the target thread was + * not prepared to handle. + * For more information, see + * Why + * are Thread.stop, Thread.suspend and Thread.resume Deprecated?. + */ + @Deprecated + public final synchronized void stop(Throwable obj) { + throw new UnsupportedOperationException(); + } + + /** + * Interrupts this thread. + * + *

Unless the current thread is interrupting itself, which is + * always permitted, the {@link #checkAccess() checkAccess} method + * of this thread is invoked, which may cause a {@link + * SecurityException} to be thrown. + * + *

If this thread is blocked in an invocation of the {@link + * Object#wait() wait()}, {@link Object#wait(long) wait(long)}, or {@link + * Object#wait(long, int) wait(long, int)} methods of the {@link Object} + * class, or of the {@link #join()}, {@link #join(long)}, {@link + * #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)}, + * methods of this class, then its interrupt status will be cleared and it + * will receive an {@link InterruptedException}. + * + *

If this thread is blocked in an I/O operation upon an {@link + * java.nio.channels.InterruptibleChannel InterruptibleChannel} + * then the channel will be closed, the thread's interrupt + * status will be set, and the thread will receive a {@link + * java.nio.channels.ClosedByInterruptException}. + * + *

If this thread is blocked in a {@link java.nio.channels.Selector} + * then the thread's interrupt status will be set and it will return + * immediately from the selection operation, possibly with a non-zero + * value, just as if the selector's {@link + * java.nio.channels.Selector#wakeup wakeup} method were invoked. + * + *

If none of the previous conditions hold then this thread's interrupt + * status will be set.

+ * + *

Interrupting a thread that is not alive need not have any effect. + * + * @throws SecurityException + * if the current thread cannot modify this thread + * + * @revised 6.0 + * @spec JSR-51 + */ + public void interrupt() { + if (this != Thread.currentThread()) + checkAccess(); + + synchronized (blockerLock) { + Interruptible b = blocker; + if (b != null) { + interrupt0(); // Just to set the interrupt flag + b.interrupt(this); + return; + } + } + interrupt0(); + } + + /** + * Tests whether the current thread has been interrupted. The + * interrupted status of the thread is cleared by this method. In + * other words, if this method were to be called twice in succession, the + * second call would return false (unless the current thread were + * interrupted again, after the first call had cleared its interrupted + * status and before the second call had examined it). + * + *

A thread interruption ignored because a thread was not alive + * at the time of the interrupt will be reflected by this method + * returning false. + * + * @return true if the current thread has been interrupted; + * false otherwise. + * @see #isInterrupted() + * @revised 6.0 + */ + public static boolean interrupted() { + Thread current = currentThread(); + if (!current.interruptPending) { + return false; + } + current.interruptPending = false; + return true; + } + + /** + * Tests whether this thread has been interrupted. The interrupted + * status of the thread is unaffected by this method. + * + *

A thread interruption ignored because a thread was not alive + * at the time of the interrupt will be reflected by this method + * returning false. + * + * @return true if this thread has been interrupted; + * false otherwise. + * @see #interrupted() + * @revised 6.0 + */ + public boolean isInterrupted() { + return interruptPending; + } + + /** + * Throws {@link NoSuchMethodError}. + * + * @deprecated This method was originally designed to destroy this + * thread without any cleanup. Any monitors it held would have + * remained locked. However, the method was never implemented. + * If if were to be implemented, it would be deadlock-prone in + * much the manner of {@link #suspend}. If the target thread held + * a lock protecting a critical system resource when it was + * destroyed, no thread could ever access this resource again. + * If another thread ever attempted to lock this resource, deadlock + * would result. Such deadlocks typically manifest themselves as + * "frozen" processes. For more information, see + * + * Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?. + * @throws NoSuchMethodError always + */ + @Deprecated + public void destroy() { + throw new NoSuchMethodError(); + } + + /** + * Tests if this thread is alive. A thread is alive if it has + * been started and has not yet died. + * + * @return true if this thread is alive; + * false otherwise. + */ + public final boolean isAlive() { + return (threadStatus & 0x0001) != 0; + } + + /** + * Suspends this thread. + *

+ * First, the checkAccess method of this thread is called + * with no arguments. This may result in throwing a + * SecurityException (in the current thread). + *

+ * If the thread is alive, it is suspended and makes no further + * progress unless and until it is resumed. + * + * @exception SecurityException if the current thread cannot modify + * this thread. + * @see #checkAccess + * @deprecated This method has been deprecated, as it is + * inherently deadlock-prone. If the target thread holds a lock on the + * monitor protecting a critical system resource when it is suspended, no + * thread can access this resource until the target thread is resumed. If + * the thread that would resume the target thread attempts to lock this + * monitor prior to calling resume, deadlock results. Such + * deadlocks typically manifest themselves as "frozen" processes. + * For more information, see + * Why + * are Thread.stop, Thread.suspend and Thread.resume Deprecated?. + */ + @Deprecated + public final void suspend() { + checkAccess(); + suspend0(); + } + + /** + * Resumes a suspended thread. + *

+ * First, the checkAccess method of this thread is called + * with no arguments. This may result in throwing a + * SecurityException (in the current thread). + *

+ * If the thread is alive but suspended, it is resumed and is + * permitted to make progress in its execution. + * + * @exception SecurityException if the current thread cannot modify this + * thread. + * @see #checkAccess + * @see #suspend() + * @deprecated This method exists solely for use with {@link #suspend}, + * which has been deprecated because it is deadlock-prone. + * For more information, see + * Why + * are Thread.stop, Thread.suspend and Thread.resume Deprecated?. + */ + @Deprecated + public final void resume() { + checkAccess(); + resume0(); + } + + /** + * Changes the priority of this thread. + *

+ * First the checkAccess method of this thread is called + * with no arguments. This may result in throwing a + * SecurityException. + *

+ * Otherwise, the priority of this thread is set to the smaller of + * the specified newPriority and the maximum permitted + * priority of the thread's thread group. + * + * @param newPriority priority to set this thread to + * @exception IllegalArgumentException If the priority is not in the + * range MIN_PRIORITY to + * MAX_PRIORITY. + * @exception SecurityException if the current thread cannot modify + * this thread. + * @see #getPriority + * @see #checkAccess() + * @see #getThreadGroup() + * @see #MAX_PRIORITY + * @see #MIN_PRIORITY + * @see ThreadGroup#getMaxPriority() + */ + public final void setPriority(int newPriority) { + ThreadGroup g; + checkAccess(); + if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) { + throw new IllegalArgumentException(); + } + if((g = getThreadGroup()) != null) { + if (newPriority > g.getMaxPriority()) { + newPriority = g.getMaxPriority(); + } + setPriority0(priority = newPriority); + } + } + + /** + * Returns this thread's priority. + * + * @return this thread's priority. + * @see #setPriority + */ + public final int getPriority() { + return priority; + } + + /** + * Changes the name of this thread to be equal to the argument + * name. + *

+ * First the checkAccess method of this thread is called + * with no arguments. This may result in throwing a + * SecurityException. + * + * @param name the new name for this thread. + * @exception SecurityException if the current thread cannot modify this + * thread. + * @see #getName + * @see #checkAccess() + */ + public final synchronized void setName(String name) { + checkAccess(); + this.name = name.toCharArray(); + if (threadStatus != 0) { + setNativeName(name); + } + } + + /** + * Returns this thread's name. + * + * @return this thread's name. + * @see #setName(String) + */ + public final String getName() { + return String.valueOf(name); + } + + /** + * Returns the thread group to which this thread belongs. + * This method returns null if this thread has died + * (been stopped). + * + * @return this thread's thread group. + */ + public final ThreadGroup getThreadGroup() { + return group; + } + + /** + * Returns an estimate of the number of active threads in the current + * thread's {@linkplain java.lang.ThreadGroup thread group} and its + * subgroups. Recursively iterates over all subgroups in the current + * thread's thread group. + * + *

The value returned is only an estimate because the number of + * threads may change dynamically while this method traverses internal + * data structures, and might be affected by the presence of certain + * system threads. This method is intended primarily for debugging + * and monitoring purposes. + * + * @return an estimate of the number of active threads in the current + * thread's thread group and in any other thread group that + * has the current thread's thread group as an ancestor + */ + public static int activeCount() { + return currentThread().getThreadGroup().activeCount(); + } + + /** + * Copies into the specified array every active thread in the current + * thread's thread group and its subgroups. This method simply + * invokes the {@link java.lang.ThreadGroup#enumerate(Thread[])} + * method of the current thread's thread group. + * + *

An application might use the {@linkplain #activeCount activeCount} + * method to get an estimate of how big the array should be, however + * if the array is too short to hold all the threads, the extra threads + * are silently ignored. If it is critical to obtain every active + * thread in the current thread's thread group and its subgroups, the + * invoker should verify that the returned int value is strictly less + * than the length of {@code tarray}. + * + *

Due to the inherent race condition in this method, it is recommended + * that the method only be used for debugging and monitoring purposes. + * + * @param tarray + * an array into which to put the list of threads + * + * @return the number of threads put into the array + * + * @throws SecurityException + * if {@link java.lang.ThreadGroup#checkAccess} determines that + * the current thread cannot access its thread group + */ + public static int enumerate(Thread tarray[]) { + return currentThread().getThreadGroup().enumerate(tarray); + } + + /** + * Counts the number of stack frames in this thread. The thread must + * be suspended. + * + * @return the number of stack frames in this thread. + * @exception IllegalThreadStateException if this thread is not + * suspended. + * @deprecated The definition of this call depends on {@link #suspend}, + * which is deprecated. Further, the results of this call + * were never well-defined. + */ + @Deprecated + public int countStackFrames() { + return 0; + } + + /** + * Waits at most {@code millis} milliseconds for this thread to + * die. A timeout of {@code 0} means to wait forever. + * + *

This implementation uses a loop of {@code this.wait} calls + * conditioned on {@code this.isAlive}. As a thread terminates the + * {@code this.notifyAll} method is invoked. It is recommended that + * applications not use {@code wait}, {@code notify}, or + * {@code notifyAll} on {@code Thread} instances. + * + * @param millis + * the time to wait in milliseconds + * + * @throws IllegalArgumentException + * if the value of {@code millis} is negative + * + * @throws InterruptedException + * if any thread has interrupted the current thread. The + * interrupted status of the current thread is + * cleared when this exception is thrown. + */ + public final synchronized void join(long millis) + throws InterruptedException { + long base = System.currentTimeMillis(); + long now = 0; + + if (millis < 0) { + throw new IllegalArgumentException("timeout value is negative"); + } + + if (millis == 0) { + while (isAlive()) { + wait(0); + } + } else { + while (isAlive()) { + long delay = millis - now; + if (delay <= 0) { + break; + } + wait(delay); + now = System.currentTimeMillis() - base; + } + } + } + + /** + * Waits at most {@code millis} milliseconds plus + * {@code nanos} nanoseconds for this thread to die. + * + *

This implementation uses a loop of {@code this.wait} calls + * conditioned on {@code this.isAlive}. As a thread terminates the + * {@code this.notifyAll} method is invoked. It is recommended that + * applications not use {@code wait}, {@code notify}, or + * {@code notifyAll} on {@code Thread} instances. + * + * @param millis + * the time to wait in milliseconds + * + * @param nanos + * {@code 0-999999} additional nanoseconds to wait + * + * @throws IllegalArgumentException + * if the value of {@code millis} is negative, or the value + * of {@code nanos} is not in the range {@code 0-999999} + * + * @throws InterruptedException + * if any thread has interrupted the current thread. The + * interrupted status of the current thread is + * cleared when this exception is thrown. + */ + public final synchronized void join(long millis, int nanos) + throws InterruptedException { + + if (millis < 0) { + throw new IllegalArgumentException("timeout value is negative"); + } + + if (nanos < 0 || nanos > 999999) { + throw new IllegalArgumentException( + "nanosecond timeout value out of range"); + } + + if (nanos >= 500000 || (nanos != 0 && millis == 0)) { + millis++; + } + + join(millis); + } + + /** + * Waits for this thread to die. + * + *

An invocation of this method behaves in exactly the same + * way as the invocation + * + *

+ * {@linkplain #join(long) join}{@code (0)} + *
+ * + * @throws InterruptedException + * if any thread has interrupted the current thread. The + * interrupted status of the current thread is + * cleared when this exception is thrown. + */ + public final void join() throws InterruptedException { + join(0); + } + + /** + * Prints a stack trace of the current thread to the standard error stream. + * This method is used only for debugging. + * + * @see Throwable#printStackTrace() + */ + public static void dumpStack() { + new Exception("Stack trace").printStackTrace(); + } + + /** + * Marks this thread as either a {@linkplain #isDaemon daemon} thread + * or a user thread. The Java Virtual Machine exits when the only + * threads running are all daemon threads. + * + *

This method must be invoked before the thread is started. + * + * @param on + * if {@code true}, marks this thread as a daemon thread + * + * @throws IllegalThreadStateException + * if this thread is {@linkplain #isAlive alive} + * + * @throws SecurityException + * if {@link #checkAccess} determines that the current + * thread cannot modify this thread + */ + public final void setDaemon(boolean on) { + checkAccess(); + if (isAlive()) { + throw new IllegalThreadStateException(); + } + daemon = on; + } + + /** + * Tests if this thread is a daemon thread. + * + * @return true if this thread is a daemon thread; + * false otherwise. + * @see #setDaemon(boolean) + */ + public final boolean isDaemon() { + return daemon; + } + + /** + * Determines if the currently running thread has permission to + * modify this thread. + *

+ * If there is a security manager, its checkAccess method + * is called with this thread as its argument. This may result in + * throwing a SecurityException. + * + * @exception SecurityException if the current thread is not allowed to + * access this thread. + * @see SecurityManager#checkAccess(Thread) + */ + public final void checkAccess() { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkAccess(this); + } + } + + /** + * Returns a string representation of this thread, including the + * thread's name, priority, and thread group. + * + * @return a string representation of this thread. + */ + public String toString() { + ThreadGroup group = getThreadGroup(); + if (group != null) { + return "Thread[" + getName() + "," + getPriority() + "," + + group.getName() + "]"; + } else { + return "Thread[" + getName() + "," + getPriority() + "," + + "" + "]"; + } + } + + /** + * Returns the context ClassLoader for this Thread. The context + * ClassLoader is provided by the creator of the thread for use + * by code running in this thread when loading classes and resources. + * If not {@linkplain #setContextClassLoader set}, the default is the + * ClassLoader context of the parent Thread. The context ClassLoader of the + * primordial thread is typically set to the class loader used to load the + * application. + * + *

If a security manager is present, and the invoker's class loader is not + * {@code null} and is not the same as or an ancestor of the context class + * loader, then this method invokes the security manager's {@link + * SecurityManager#checkPermission(java.security.Permission) checkPermission} + * method with a {@link RuntimePermission RuntimePermission}{@code + * ("getClassLoader")} permission to verify that retrieval of the context + * class loader is permitted. + * + * @return the context ClassLoader for this Thread, or {@code null} + * indicating the system class loader (or, failing that, the + * bootstrap class loader) + * + * @throws SecurityException + * if the current thread cannot get the context ClassLoader + * + * @since 1.2 + */ + @CallerSensitive + public ClassLoader getContextClassLoader() { + if (contextClassLoader == ClassLoader.DUMMY) { + contextClassLoader = ClassLoader.getSystemClassLoader(); + } + if (contextClassLoader == null) + return null; + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + ClassLoader.checkClassLoaderPermission(contextClassLoader, + Reflection.getCallerClass()); + } + return contextClassLoader; + } + + /** + * Sets the context ClassLoader for this Thread. The context + * ClassLoader can be set when a thread is created, and allows + * the creator of the thread to provide the appropriate class loader, + * through {@code getContextClassLoader}, to code running in the thread + * when loading classes and resources. + * + *

If a security manager is present, its {@link + * SecurityManager#checkPermission(java.security.Permission) checkPermission} + * method is invoked with a {@link RuntimePermission RuntimePermission}{@code + * ("setContextClassLoader")} permission to see if setting the context + * ClassLoader is permitted. + * + * @param cl + * the context ClassLoader for this Thread, or null indicating the + * system class loader (or, failing that, the bootstrap class loader) + * + * @throws SecurityException + * if the current thread cannot set the context ClassLoader + * + * @since 1.2 + */ + public void setContextClassLoader(ClassLoader cl) { + if (cl == ClassLoader.DUMMY) { + // we're being called by Thread. to force this method to be JIT compiled + return; + } + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("setContextClassLoader")); + } + contextClassLoader = cl; + } + + // [IKVM] called by sun.misc.Launcher (via map.xml patch) to initialize the context class loader + final void initContextClassLoader(ClassLoader cl) { + // we only set contextClassLoader if it hasn't been set (by user code) previously + casContextClassLoader(ClassLoader.DUMMY, cl); + } + + @ikvm.internal.InterlockedCompareAndSet("contextClassLoader") + private native boolean casContextClassLoader(ClassLoader oldValue, ClassLoader newValue); + + /** + * Returns true if and only if the current thread holds the + * monitor lock on the specified object. + * + *

This method is designed to allow a program to assert that + * the current thread already holds a specified lock: + *

+     *     assert Thread.holdsLock(obj);
+     * 
+ * + * @param obj the object on which to test lock ownership + * @throws NullPointerException if obj is null + * @return true if the current thread holds the monitor lock on + * the specified object. + * @since 1.4 + */ + public static boolean holdsLock(Object obj) { + if (obj == null) { + throw new NullPointerException(); + } + try { + if (false) throw new cli.System.Threading.SynchronizationLockException(); + // The 1.5 memory model (JSR133) explicitly allows spurious wake-ups from Object.wait, + // so we abuse Pulse to check if we own the monitor. + cli.System.Threading.Monitor.Pulse(obj); + return true; + } + catch (cli.System.Threading.SynchronizationLockException _) { + return false; + } + } + + private static final StackTraceElement[] EMPTY_STACK_TRACE + = new StackTraceElement[0]; + + /** + * Returns an array of stack trace elements representing the stack dump + * of this thread. This method will return a zero-length array if + * this thread has not started, has started but has not yet been + * scheduled to run by the system, or has terminated. + * If the returned array is of non-zero length then the first element of + * the array represents the top of the stack, which is the most recent + * method invocation in the sequence. The last element of the array + * represents the bottom of the stack, which is the least recent method + * invocation in the sequence. + * + *

If there is a security manager, and this thread is not + * the current thread, then the security manager's + * checkPermission method is called with a + * RuntimePermission("getStackTrace") permission + * to see if it's ok to get the stack trace. + * + *

Some virtual machines may, under some circumstances, omit one + * or more stack frames from the stack trace. In the extreme case, + * a virtual machine that has no stack trace information concerning + * this thread is permitted to return a zero-length array from this + * method. + * + * @return an array of StackTraceElement, + * each represents one stack frame. + * + * @throws SecurityException + * if a security manager exists and its + * checkPermission method doesn't allow + * getting the stack trace of thread. + * @see SecurityManager#checkPermission + * @see RuntimePermission + * @see Throwable#getStackTrace + * + * @since 1.5 + */ + public StackTraceElement[] getStackTrace() { + if (this != Thread.currentThread()) { + // check for getStackTrace permission + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkPermission( + SecurityConstants.GET_STACK_TRACE_PERMISSION); + } + // optimization so we do not call into the vm for threads that + // have not yet started or have terminated + if (!isAlive()) { + return EMPTY_STACK_TRACE; + } + StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {this}); + StackTraceElement[] stackTrace = stackTraceArray[0]; + // a thread that was alive during the previous isAlive call may have + // since terminated, therefore not having a stacktrace. + if (stackTrace == null) { + stackTrace = EMPTY_STACK_TRACE; + } + return stackTrace; + } else { + // Don't need JVM help for current thread + return (new Exception()).getStackTrace(); + } + } + + /** + * Returns a map of stack traces for all live threads. + * The map keys are threads and each map value is an array of + * StackTraceElement that represents the stack dump + * of the corresponding Thread. + * The returned stack traces are in the format specified for + * the {@link #getStackTrace getStackTrace} method. + * + *

The threads may be executing while this method is called. + * The stack trace of each thread only represents a snapshot and + * each stack trace may be obtained at different time. A zero-length + * array will be returned in the map value if the virtual machine has + * no stack trace information about a thread. + * + *

If there is a security manager, then the security manager's + * checkPermission method is called with a + * RuntimePermission("getStackTrace") permission as well as + * RuntimePermission("modifyThreadGroup") permission + * to see if it is ok to get the stack trace of all threads. + * + * @return a Map from Thread to an array of + * StackTraceElement that represents the stack trace of + * the corresponding thread. + * + * @throws SecurityException + * if a security manager exists and its + * checkPermission method doesn't allow + * getting the stack trace of thread. + * @see #getStackTrace + * @see SecurityManager#checkPermission + * @see RuntimePermission + * @see Throwable#getStackTrace + * + * @since 1.5 + */ + public static Map getAllStackTraces() { + // check for getStackTrace permission + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkPermission( + SecurityConstants.GET_STACK_TRACE_PERMISSION); + security.checkPermission( + SecurityConstants.MODIFY_THREADGROUP_PERMISSION); + } + + // Get a snapshot of the list of all threads + Thread[] threads = getThreads(); + StackTraceElement[][] traces = dumpThreads(threads); + Map m = new HashMap<>(threads.length); + for (int i = 0; i < threads.length; i++) { + StackTraceElement[] stackTrace = traces[i]; + if (stackTrace != null) { + m.put(threads[i], stackTrace); + } + // else terminated so we don't put it in the map + } + return m; + } + + + private static final RuntimePermission SUBCLASS_IMPLEMENTATION_PERMISSION = + new RuntimePermission("enableContextClassLoaderOverride"); + + /** cache of subclass security audit results */ + /* Replace with ConcurrentReferenceHashMap when/if it appears in a future + * release */ + private static class Caches { + /** cache of subclass security audit results */ + static final ConcurrentMap subclassAudits = + new ConcurrentHashMap<>(); + + /** queue for WeakReferences to audited subclasses */ + static final ReferenceQueue> subclassAuditsQueue = + new ReferenceQueue<>(); + } + + /** + * Verifies that this (possibly subclass) instance can be constructed + * without violating security constraints: the subclass must not override + * security-sensitive non-final methods, or else the + * "enableContextClassLoaderOverride" RuntimePermission is checked. + */ + @cli.System.Runtime.CompilerServices.MethodImplAttribute.Annotation(value = cli.System.Runtime.CompilerServices.MethodImplOptions.__Enum.NoInlining) + private static native boolean isCCLOverridden(Thread thread); // [IKVM] implemented in map.xml + + private static boolean isCCLOverridden(Class cl) { + if (cl == Thread.class) + return false; + + processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits); + WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue); + Boolean result = Caches.subclassAudits.get(key); + if (result == null) { + result = Boolean.valueOf(auditSubclass(cl)); + Caches.subclassAudits.putIfAbsent(key, result); + } + + return result.booleanValue(); + } + + /** + * Performs reflective checks on given subclass to verify that it doesn't + * override security-sensitive non-final methods. Returns true if the + * subclass overrides any of the methods, false otherwise. + */ + private static boolean auditSubclass(final Class subcl) { + Boolean result = AccessController.doPrivileged( + new PrivilegedAction() { + public Boolean run() { + for (Class cl = subcl; + cl != Thread.class; + cl = cl.getSuperclass()) + { + try { + cl.getDeclaredMethod("getContextClassLoader", new Class[0]); + return Boolean.TRUE; + } catch (NoSuchMethodException ex) { + } + try { + Class[] params = {ClassLoader.class}; + cl.getDeclaredMethod("setContextClassLoader", params); + return Boolean.TRUE; + } catch (NoSuchMethodException ex) { + } + } + return Boolean.FALSE; + } + } + ); + return result.booleanValue(); + } + + private static StackTraceElement[][] dumpThreads(Thread[] threads) { + StackTraceElement[][] stacks = new StackTraceElement[threads.length][]; + for (int i = 0; i < threads.length; i++) { + cli.System.Threading.Thread nativeThread = threads[i].nativeThread; + if (nativeThread == null) { + stacks[i] = new StackTraceElement[0]; + } else { + try { + if (false) throw new cli.System.Threading.ThreadStateException(); + boolean suspended = false; + if ((nativeThread.get_ThreadState().Value & cli.System.Threading.ThreadState.Suspended) == 0 && nativeThread != cli.System.Threading.Thread.get_CurrentThread()) { + suspended = true; + nativeThread.Suspend(); + } + cli.System.Diagnostics.StackTrace stack; + try { + stack = new cli.System.Diagnostics.StackTrace(nativeThread, true); + } + finally { + if (suspended) { + nativeThread.Resume(); + } + } + stacks[i] = getStackTrace(stack); + } + catch (cli.System.Threading.ThreadStateException _) { + stacks[i] = new StackTraceElement[0]; + } + } + } + return stacks; + } + + private static native StackTraceElement[] getStackTrace(cli.System.Diagnostics.StackTrace stack); + + private static native Thread[] getThreads(); + + /** + * Returns the identifier of this Thread. The thread ID is a positive + * long number generated when this thread was created. + * The thread ID is unique and remains unchanged during its lifetime. + * When a thread is terminated, this thread ID may be reused. + * + * @return this thread's ID. + * @since 1.5 + */ + public long getId() { + return tid; + } + + /** + * A thread state. A thread can be in one of the following states: + *

    + *
  • {@link #NEW}
    + * A thread that has not yet started is in this state. + *
  • + *
  • {@link #RUNNABLE}
    + * A thread executing in the Java virtual machine is in this state. + *
  • + *
  • {@link #BLOCKED}
    + * A thread that is blocked waiting for a monitor lock + * is in this state. + *
  • + *
  • {@link #WAITING}
    + * A thread that is waiting indefinitely for another thread to + * perform a particular action is in this state. + *
  • + *
  • {@link #TIMED_WAITING}
    + * A thread that is waiting for another thread to perform an action + * for up to a specified waiting time is in this state. + *
  • + *
  • {@link #TERMINATED}
    + * A thread that has exited is in this state. + *
  • + *
+ * + *

+ * A thread can be in only one state at a given point in time. + * These states are virtual machine states which do not reflect + * any operating system thread states. + * + * @since 1.5 + * @see #getState + */ + public enum State { + /** + * Thread state for a thread which has not yet started. + */ + NEW, + + /** + * Thread state for a runnable thread. A thread in the runnable + * state is executing in the Java virtual machine but it may + * be waiting for other resources from the operating system + * such as processor. + */ + RUNNABLE, + + /** + * Thread state for a thread blocked waiting for a monitor lock. + * A thread in the blocked state is waiting for a monitor lock + * to enter a synchronized block/method or + * reenter a synchronized block/method after calling + * {@link Object#wait() Object.wait}. + */ + BLOCKED, + + /** + * Thread state for a waiting thread. + * A thread is in the waiting state due to calling one of the + * following methods: + *

    + *
  • {@link Object#wait() Object.wait} with no timeout
  • + *
  • {@link #join() Thread.join} with no timeout
  • + *
  • {@link LockSupport#park() LockSupport.park}
  • + *
+ * + *

A thread in the waiting state is waiting for another thread to + * perform a particular action. + * + * For example, a thread that has called Object.wait() + * on an object is waiting for another thread to call + * Object.notify() or Object.notifyAll() on + * that object. A thread that has called Thread.join() + * is waiting for a specified thread to terminate. + */ + WAITING, + + /** + * Thread state for a waiting thread with a specified waiting time. + * A thread is in the timed waiting state due to calling one of + * the following methods with a specified positive waiting time: + *

    + *
  • {@link #sleep Thread.sleep}
  • + *
  • {@link Object#wait(long) Object.wait} with timeout
  • + *
  • {@link #join(long) Thread.join} with timeout
  • + *
  • {@link LockSupport#parkNanos LockSupport.parkNanos}
  • + *
  • {@link LockSupport#parkUntil LockSupport.parkUntil}
  • + *
+ */ + TIMED_WAITING, + + /** + * Thread state for a terminated thread. + * The thread has completed execution. + */ + TERMINATED; + } + + /** + * Returns the state of this thread. + * This method is designed for use in monitoring of the system state, + * not for synchronization control. + * + * @return this thread's state. + * @since 1.5 + */ + public State getState() { + // get current thread state + switch (threadStatus) { + case 0: + return State.NEW; + case 0x0002: + return State.TERMINATED; + } + synchronized (lock) { + if (interruptableWait) { + // NOTE if objectWait has satisfied the wait condition (or has been interrupted or has timed-out), + // it can be blocking on the re-acquire of the monitor, but we have no way of detecting that. + return timedWait ? State.TIMED_WAITING : State.WAITING; + } + } + cli.System.Threading.Thread nativeThread = this.nativeThread; + if (nativeThread == null) { + return State.TERMINATED; + } + if ((nativeThread.get_ThreadState().Value & cli.System.Threading.ThreadState.WaitSleepJoin) != 0) { + return State.BLOCKED; + } + return State.RUNNABLE; + } + + // Added in JSR-166 + + /** + * Interface for handlers invoked when a Thread abruptly + * terminates due to an uncaught exception. + *

When a thread is about to terminate due to an uncaught exception + * the Java Virtual Machine will query the thread for its + * UncaughtExceptionHandler using + * {@link #getUncaughtExceptionHandler} and will invoke the handler's + * uncaughtException method, passing the thread and the + * exception as arguments. + * If a thread has not had its UncaughtExceptionHandler + * explicitly set, then its ThreadGroup object acts as its + * UncaughtExceptionHandler. If the ThreadGroup object + * has no + * special requirements for dealing with the exception, it can forward + * the invocation to the {@linkplain #getDefaultUncaughtExceptionHandler + * default uncaught exception handler}. + * + * @see #setDefaultUncaughtExceptionHandler + * @see #setUncaughtExceptionHandler + * @see ThreadGroup#uncaughtException + * @since 1.5 + */ + @FunctionalInterface + public interface UncaughtExceptionHandler { + /** + * Method invoked when the given thread terminates due to the + * given uncaught exception. + *

Any exception thrown by this method will be ignored by the + * Java Virtual Machine. + * @param t the thread + * @param e the exception + */ + void uncaughtException(Thread t, Throwable e); + } + + // null unless explicitly set + private volatile UncaughtExceptionHandler uncaughtExceptionHandler; + + // null unless explicitly set + private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler; + + /** + * Set the default handler invoked when a thread abruptly terminates + * due to an uncaught exception, and no other handler has been defined + * for that thread. + * + *

Uncaught exception handling is controlled first by the thread, then + * by the thread's {@link ThreadGroup} object and finally by the default + * uncaught exception handler. If the thread does not have an explicit + * uncaught exception handler set, and the thread's thread group + * (including parent thread groups) does not specialize its + * uncaughtException method, then the default handler's + * uncaughtException method will be invoked. + *

By setting the default uncaught exception handler, an application + * can change the way in which uncaught exceptions are handled (such as + * logging to a specific device, or file) for those threads that would + * already accept whatever "default" behavior the system + * provided. + * + *

Note that the default uncaught exception handler should not usually + * defer to the thread's ThreadGroup object, as that could cause + * infinite recursion. + * + * @param eh the object to use as the default uncaught exception handler. + * If null then there is no default handler. + * + * @throws SecurityException if a security manager is present and it + * denies {@link RuntimePermission} + * ("setDefaultUncaughtExceptionHandler") + * + * @see #setUncaughtExceptionHandler + * @see #getUncaughtExceptionHandler + * @see ThreadGroup#uncaughtException + * @since 1.5 + */ + public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission( + new RuntimePermission("setDefaultUncaughtExceptionHandler") + ); + } + + defaultUncaughtExceptionHandler = eh; + } + + /** + * Returns the default handler invoked when a thread abruptly terminates + * due to an uncaught exception. If the returned value is null, + * there is no default. + * @since 1.5 + * @see #setDefaultUncaughtExceptionHandler + * @return the default uncaught exception handler for all threads + */ + public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){ + return defaultUncaughtExceptionHandler; + } + + /** + * Returns the handler invoked when this thread abruptly terminates + * due to an uncaught exception. If this thread has not had an + * uncaught exception handler explicitly set then this thread's + * ThreadGroup object is returned, unless this thread + * has terminated, in which case null is returned. + * @since 1.5 + * @return the uncaught exception handler for this thread + */ + public UncaughtExceptionHandler getUncaughtExceptionHandler() { + return uncaughtExceptionHandler != null ? + uncaughtExceptionHandler : group; + } + + /** + * Set the handler invoked when this thread abruptly terminates + * due to an uncaught exception. + *

A thread can take full control of how it responds to uncaught + * exceptions by having its uncaught exception handler explicitly set. + * If no such handler is set then the thread's ThreadGroup + * object acts as its handler. + * @param eh the object to use as this thread's uncaught exception + * handler. If null then this thread has no explicit handler. + * @throws SecurityException if the current thread is not allowed to + * modify this thread. + * @see #setDefaultUncaughtExceptionHandler + * @see ThreadGroup#uncaughtException + * @since 1.5 + */ + public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) { + checkAccess(); + uncaughtExceptionHandler = eh; + } + + /** + * Dispatch an uncaught exception to the handler. This method is + * intended to be called only by the JVM. + */ + private void dispatchUncaughtException(Throwable e) { + getUncaughtExceptionHandler().uncaughtException(this, e); + } + + /** + * Removes from the specified map any keys that have been enqueued + * on the specified reference queue. + */ + static void processQueue(ReferenceQueue> queue, + ConcurrentMap>, ?> map) + { + Reference> ref; + while((ref = queue.poll()) != null) { + map.remove(ref); + } + } + + /** + * Weak key for Class objects. + **/ + static class WeakClassKey extends WeakReference> { + /** + * saved value of the referent's identity hash code, to maintain + * a consistent hash code after the referent has been cleared + */ + private final int hash; + + /** + * Create a new WeakClassKey to the given object, registered + * with a queue. + */ + WeakClassKey(Class cl, ReferenceQueue> refQueue) { + super(cl, refQueue); + hash = System.identityHashCode(cl); + } + + /** + * Returns the identity hash code of the original referent. + */ + @Override + public int hashCode() { + return hash; + } + + /** + * Returns true if the given object is this identical + * WeakClassKey instance, or, if this object's referent has not + * been cleared, if the given object is another WeakClassKey + * instance with the identical non-null referent as this one. + */ + @Override + public boolean equals(Object obj) { + if (obj == this) + return true; + + if (obj instanceof WeakClassKey) { + Object referent = get(); + return (referent != null) && + (referent == ((WeakClassKey) obj).get()); + } else { + return false; + } + } + } + + + // The following three initially uninitialized fields are exclusively + // managed by class java.util.concurrent.ThreadLocalRandom. These + // fields are used to build the high-performance PRNGs in the + // concurrent code, and we can not risk accidental false sharing. + // Hence, the fields are isolated with @Contended. + + /** The current seed for a ThreadLocalRandom */ + @sun.misc.Contended("tlr") + long threadLocalRandomSeed; + + /** Probe hash value; nonzero if threadLocalRandomSeed initialized */ + @sun.misc.Contended("tlr") + @ikvm.lang.Internal // [IKVM] accessed from java.util.concurrent.atomic.Striped64 + public int threadLocalRandomProbe; + + /** Secondary seed isolated from public ThreadLocalRandom sequence */ + @sun.misc.Contended("tlr") + @ikvm.lang.Internal // [IKVM] accessed from java.util.concurrent.locks.LockSupport + public int threadLocalRandomSecondarySeed; + + /* Some private helper methods */ + private synchronized void setPriority0(int newPriority) { + cli.System.Threading.Thread nativeThread = this.nativeThread; + if (nativeThread != null) { + try { + if (false) throw new cli.System.Threading.ThreadStateException(); + nativeThread.set_Priority(cli.System.Threading.ThreadPriority.wrap(mapJavaPriorityToClr(newPriority))); + } + catch (cli.System.Threading.ThreadStateException _) { + } + } + } + + private void stop0(Throwable x) { + synchronized (lock) { + if (!running) { + stillborn = x; + x = null; + } + } + if (x != null) { + // NOTE we allow ThreadDeath (and its subclasses) to be thrown on every thread, but any + // other exception is ignored, except if we're throwing it on the current Thread. This + // is done to allow exception handlers to be type specific, otherwise every exception + // handler would have to catch ThreadAbortException and look inside it to see if it + // contains the real exception that we wish to handle. + // I hope we can get away with this behavior, because Thread.stop() is deprecated + // anyway. Note that we do allow arbitrary exceptions to be thrown on the current + // thread, since this is harmless (because they aren't wrapped) and also because it + // provides some real value, because it is one of the ways you can throw arbitrary checked + // exceptions from Java. + if (this == current) { + sun.misc.Unsafe.getUnsafe().throwException(x); + } + else if (x instanceof ThreadDeath) { + cli.System.Threading.Thread nativeThread = this.nativeThread; + if (nativeThread == null) { + return; + } + try { + if (false) throw new cli.System.Threading.ThreadStateException(); + nativeThread.Abort(x); + } + catch (cli.System.Threading.ThreadStateException _) { + // .NET 2.0 throws a ThreadStateException if the target thread is currently suspended + // (but it does record the Abort request) + } + try { + if (false) throw new cli.System.Threading.ThreadStateException(); + int suspend = cli.System.Threading.ThreadState.Suspended | cli.System.Threading.ThreadState.SuspendRequested; + while ((nativeThread.get_ThreadState().Value & suspend) != 0) { + nativeThread.Resume(); + } + } + catch (cli.System.Threading.ThreadStateException _) { + } + } + } + } + + private void suspend0() { + try { + if (false) throw new cli.System.Threading.ThreadStateException(); + cli.System.Threading.Thread nativeThread = this.nativeThread; + if (nativeThread != null) { + nativeThread.Suspend(); + } + } + catch (cli.System.Threading.ThreadStateException _) { + } + } + + private void resume0() { + try { + if (false) throw new cli.System.Threading.ThreadStateException(); + cli.System.Threading.Thread nativeThread = this.nativeThread; + if (nativeThread != null) { + nativeThread.Resume(); + } + } + catch (cli.System.Threading.ThreadStateException _) { + } + } + + private void interrupt0() { + synchronized (lock) { + // if the thread hasn't been started yet or has been terminated, the interrupt is ignored + // (like on the reference implementation) + if (nativeThread == null) { + return; + } + if (!interruptPending) { + interruptPending = true; + if (interruptableWait) { + nativeInterruptPending = true; + nativeThread.Interrupt(); + } + } + } + } + + private void setRunningAndCheckStillborn() throws Throwable { + Throwable x; + synchronized (lock) { + running = true; + x = stillborn; + stillborn = null; + } + if (x != null) { + throw x; + } + } + + // [IKVM] this the entry point of thread started from Java + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + void threadProc() { + current = this; + try { + // the body of the try block is in another method to allow the (limited) try/finally optimizer + // to properly recognize the try/finally block, because we want to make sure that die() + // runs in a finally block to prevent it from being asynchronously aborted. + threadProc2(); + } + finally { + die(); + } + } + + @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation + private void threadProc2() { + try { + setRunningAndCheckStillborn(); + run(); + } + catch (Throwable x) { + try { + getUncaughtExceptionHandler().uncaughtException(this, x); + } + catch (Throwable _) { + } + } + } + + // [IKVM] this the implementation of Object.wait(long timeout, int nanos). It is hooked up in map.xml. + static void objectWait(Object o, long timeout, int nanos) throws InterruptedException { + if (o == null) { + throw new NullPointerException(); + } + if (timeout < 0) { + throw new IllegalArgumentException("timeout value is negative"); + } + if (nanos < 0 || nanos > 999999) { + throw new IllegalArgumentException("nanosecond timeout value out of range"); + } + if (nanos >= 500000 || (nanos != 0 && timeout == 0)) { + timeout++; + } + objectWait(o, timeout); + } + + // [IKVM] this the implementation of Object.wait(long timeout). It is hooked up in map.xml. + static void objectWait(Object o, long timeout) throws InterruptedException { + if (o == null) { + throw new NullPointerException(); + } + if (timeout < 0) { + throw new IllegalArgumentException("timeout value is negative"); + } + Thread t = currentThread(); + t.enterInterruptableWait(timeout != 0); + try { + if (false) throw new cli.System.Threading.ThreadInterruptedException(); + if (timeout == 0 || timeout > 922337203685476L) { + cli.System.Threading.Monitor.Wait(o); + } + else { + // We wait a maximum of Integer.MAX_VALUE milliseconds, because that is the maximum that Monitor.Wait will wait. + // Note that the Object.wait() specification allows for spurious wakeups, so this isn't a problem. Trying to + // emulate a longer wait with multiple Monitor.Wait() calls is not allowed, because that would mean that + // we acquire and release the synchronization lock multiple times during the wait. + cli.System.Threading.Monitor.Wait(o, (int)Math.min(timeout, Integer.MAX_VALUE)); + } + } + catch (cli.System.Threading.ThreadInterruptedException _) { + } + finally { + t.leaveInterruptableWait(); + } + } + + private void setNativeName(String name) { + cli.System.Threading.Thread thread = nativeThread; + if (thread != null) { + try { + if (false) throw new cli.System.InvalidOperationException(); + thread.set_Name(name); + } catch (cli.System.InvalidOperationException _) { + } + } + } +} diff --git a/openjdk/java/lang/ThrowableHelper.java b/openjdk/java/lang/ThrowableHelper.java new file mode 100644 index 0000000..ef439ed --- /dev/null +++ b/openjdk/java/lang/ThrowableHelper.java @@ -0,0 +1,345 @@ +/* + * Copyright (c) 1994, 2013, 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 java.lang; +import java.io.*; +import java.util.*; + +final class ThrowableHelper { + /** + * Holder class to defer initializing sentinel objects only used + * for serialization. + */ + private static class SentinelHolder { + /** + * {@linkplain #setStackTrace(StackTraceElement[]) Setting the + * stack trace} to a one-element array containing this sentinel + * value indicates future attempts to set the stack trace will be + * ignored. The sentinal is equal to the result of calling:
+ * {@code new StackTraceElement("", "", null, Integer.MIN_VALUE)} + */ + public static final StackTraceElement STACK_TRACE_ELEMENT_SENTINEL = + new StackTraceElement("", "", null, Integer.MIN_VALUE); + + /** + * Sentinel value used in the serial form to indicate an immutable + * stack trace. + */ + public static final StackTraceElement[] STACK_TRACE_SENTINEL = + new StackTraceElement[] {STACK_TRACE_ELEMENT_SENTINEL}; + } + + /** Caption for labeling causative exception stack traces */ + private static final String CAUSE_CAPTION = "Caused by: "; + + /** Caption for labeling suppressed exception stack traces */ + private static final String SUPPRESSED_CAPTION = "Suppressed: "; + + /** + * Prints this throwable and its backtrace to the + * standard error stream. This method prints a stack trace for this + * {@code Throwable} object on the error output stream that is + * the value of the field {@code System.err}. The first line of + * output contains the result of the {@link #toString()} method for + * this object. Remaining lines represent data previously recorded by + * the method {@link #fillInStackTrace()}. The format of this + * information depends on the implementation, but the following + * example may be regarded as typical: + *

+     * java.lang.NullPointerException
+     *         at MyClass.mash(MyClass.java:9)
+     *         at MyClass.crunch(MyClass.java:6)
+     *         at MyClass.main(MyClass.java:3)
+     * 
+ * This example was produced by running the program: + *
+     * class MyClass {
+     *     public static void main(String[] args) {
+     *         crunch(null);
+     *     }
+     *     static void crunch(int[] a) {
+     *         mash(a);
+     *     }
+     *     static void mash(int[] b) {
+     *         System.out.println(b[0]);
+     *     }
+     * }
+     * 
+ * The backtrace for a throwable with an initialized, non-null cause + * should generally include the backtrace for the cause. The format + * of this information depends on the implementation, but the following + * example may be regarded as typical: + *
+     * HighLevelException: MidLevelException: LowLevelException
+     *         at Junk.a(Junk.java:13)
+     *         at Junk.main(Junk.java:4)
+     * Caused by: MidLevelException: LowLevelException
+     *         at Junk.c(Junk.java:23)
+     *         at Junk.b(Junk.java:17)
+     *         at Junk.a(Junk.java:11)
+     *         ... 1 more
+     * Caused by: LowLevelException
+     *         at Junk.e(Junk.java:30)
+     *         at Junk.d(Junk.java:27)
+     *         at Junk.c(Junk.java:21)
+     *         ... 3 more
+     * 
+ * Note the presence of lines containing the characters {@code "..."}. + * These lines indicate that the remainder of the stack trace for this + * exception matches the indicated number of frames from the bottom of the + * stack trace of the exception that was caused by this exception (the + * "enclosing" exception). This shorthand can greatly reduce the length + * of the output in the common case where a wrapped exception is thrown + * from same method as the "causative exception" is caught. The above + * example was produced by running the program: + *
+     * public class Junk {
+     *     public static void main(String args[]) {
+     *         try {
+     *             a();
+     *         } catch(HighLevelException e) {
+     *             e.printStackTrace();
+     *         }
+     *     }
+     *     static void a() throws HighLevelException {
+     *         try {
+     *             b();
+     *         } catch(MidLevelException e) {
+     *             throw new HighLevelException(e);
+     *         }
+     *     }
+     *     static void b() throws MidLevelException {
+     *         c();
+     *     }
+     *     static void c() throws MidLevelException {
+     *         try {
+     *             d();
+     *         } catch(LowLevelException e) {
+     *             throw new MidLevelException(e);
+     *         }
+     *     }
+     *     static void d() throws LowLevelException {
+     *        e();
+     *     }
+     *     static void e() throws LowLevelException {
+     *         throw new LowLevelException();
+     *     }
+     * }
+     *
+     * class HighLevelException extends Exception {
+     *     HighLevelException(Throwable cause) { super(cause); }
+     * }
+     *
+     * class MidLevelException extends Exception {
+     *     MidLevelException(Throwable cause)  { super(cause); }
+     * }
+     *
+     * class LowLevelException extends Exception {
+     * }
+     * 
+ * As of release 7, the platform supports the notion of + * suppressed exceptions (in conjunction with the {@code + * try}-with-resources statement). Any exceptions that were + * suppressed in order to deliver an exception are printed out + * beneath the stack trace. The format of this information + * depends on the implementation, but the following example may be + * regarded as typical: + * + *
+     * Exception in thread "main" java.lang.Exception: Something happened
+     *  at Foo.bar(Foo.java:10)
+     *  at Foo.main(Foo.java:5)
+     *  Suppressed: Resource$CloseFailException: Resource ID = 0
+     *          at Resource.close(Resource.java:26)
+     *          at Foo.bar(Foo.java:9)
+     *          ... 1 more
+     * 
+ * Note that the "... n more" notation is used on suppressed exceptions + * just at it is used on causes. Unlike causes, suppressed exceptions are + * indented beyond their "containing exceptions." + * + *

An exception can have both a cause and one or more suppressed + * exceptions: + *

+     * Exception in thread "main" java.lang.Exception: Main block
+     *  at Foo3.main(Foo3.java:7)
+     *  Suppressed: Resource$CloseFailException: Resource ID = 2
+     *          at Resource.close(Resource.java:26)
+     *          at Foo3.main(Foo3.java:5)
+     *  Suppressed: Resource$CloseFailException: Resource ID = 1
+     *          at Resource.close(Resource.java:26)
+     *          at Foo3.main(Foo3.java:5)
+     * Caused by: java.lang.Exception: I did it
+     *  at Foo3.main(Foo3.java:8)
+     * 
+ * Likewise, a suppressed exception can have a cause: + *
+     * Exception in thread "main" java.lang.Exception: Main block
+     *  at Foo4.main(Foo4.java:6)
+     *  Suppressed: Resource2$CloseFailException: Resource ID = 1
+     *          at Resource2.close(Resource2.java:20)
+     *          at Foo4.main(Foo4.java:5)
+     *  Caused by: java.lang.Exception: Rats, you caught me
+     *          at Resource2$CloseFailException.<init>(Resource2.java:45)
+     *          ... 2 more
+     * 
+ */ + public static void printStackTrace(Throwable _this) { + _this.printStackTrace(System.err); + } + + /** + * Prints this throwable and its backtrace to the specified print stream. + * + * @param s {@code PrintStream} to use for output + */ + public static void printStackTrace(Throwable _this, PrintStream s) { + printStackTrace(_this, new WrappedPrintStream(s)); + } + + private static void printStackTrace(Throwable _this, PrintStreamOrWriter s) { + // Guard against malicious overrides of Throwable.equals by + // using a Set with identity equality semantics. + Set dejaVu = + Collections.newSetFromMap(new IdentityHashMap()); + dejaVu.add(_this); + + synchronized (s.lock()) { + // Print our stack trace + s.println(_this); + StackTraceElement[] trace = getOurStackTrace(_this); + for (StackTraceElement traceElement : trace) + s.println("\tat " + traceElement); + + // Print suppressed exceptions, if any + for (Throwable se : _this.getSuppressed()) + printEnclosedStackTrace(se, s, trace, SUPPRESSED_CAPTION, "\t", dejaVu); + + // Print cause, if any + Throwable ourCause = _this.getCause(); + if (ourCause != null) + printEnclosedStackTrace(ourCause, s, trace, CAUSE_CAPTION, "", dejaVu); + } + } + + /** + * Print our stack trace as an enclosed exception for the specified + * stack trace. + */ + private static void printEnclosedStackTrace(Throwable _this, PrintStreamOrWriter s, + StackTraceElement[] enclosingTrace, + String caption, + String prefix, + Set dejaVu) { + assert Thread.holdsLock(s.lock()); + if (dejaVu.contains(_this)) { + s.println("\t[CIRCULAR REFERENCE:" + _this + "]"); + } else { + dejaVu.add(_this); + // Compute number of frames in common between this and enclosing trace + StackTraceElement[] trace = getOurStackTrace(_this); + int m = trace.length - 1; + int n = enclosingTrace.length - 1; + while (m >= 0 && n >=0 && trace[m].equals(enclosingTrace[n])) { + m--; n--; + } + int framesInCommon = trace.length - 1 - m; + + // Print our stack trace + s.println(prefix + caption + _this); + for (int i = 0; i <= m; i++) + s.println(prefix + "\tat " + trace[i]); + if (framesInCommon != 0) + s.println(prefix + "\t... " + framesInCommon + " more"); + + // Print suppressed exceptions, if any + for (Throwable se : _this.getSuppressed()) + printEnclosedStackTrace(se, s, trace, SUPPRESSED_CAPTION, + prefix +"\t", dejaVu); + + // Print cause, if any + Throwable ourCause = _this.getCause(); + if (ourCause != null) + printEnclosedStackTrace(ourCause, s, trace, CAUSE_CAPTION, prefix, dejaVu); + } + } + + private static native StackTraceElement[] getOurStackTrace(Throwable _this); + + /** + * Prints this throwable and its backtrace to the specified + * print writer. + * + * @param s {@code PrintWriter} to use for output + * @since JDK1.1 + */ + public static void printStackTrace(Throwable _this, PrintWriter s) { + printStackTrace(_this, new WrappedPrintWriter(s)); + } + + /** + * Wrapper class for PrintStream and PrintWriter to enable a single + * implementation of printStackTrace. + */ + private abstract static class PrintStreamOrWriter { + /** Returns the object to be locked when using this StreamOrWriter */ + abstract Object lock(); + + /** Prints the specified string as a line on this StreamOrWriter */ + abstract void println(Object o); + } + + private static class WrappedPrintStream extends PrintStreamOrWriter { + private final PrintStream printStream; + + WrappedPrintStream(PrintStream printStream) { + this.printStream = printStream; + } + + Object lock() { + return printStream; + } + + void println(Object o) { + printStream.println(o); + } + } + + private static class WrappedPrintWriter extends PrintStreamOrWriter { + private final PrintWriter printWriter; + + WrappedPrintWriter(PrintWriter printWriter) { + this.printWriter = printWriter; + } + + Object lock() { + return printWriter; + } + + void println(Object o) { + printWriter.println(o); + } + } +} diff --git a/openjdk/java/lang/VMSystemProperties.java b/openjdk/java/lang/VMSystemProperties.java new file mode 100644 index 0000000..5c79248 --- /dev/null +++ b/openjdk/java/lang/VMSystemProperties.java @@ -0,0 +1,469 @@ +/* + Copyright (C) 2004-2015 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package java.lang; + +import java.util.Properties; +import cli.System.Diagnostics.FileVersionInfo; +import static ikvm.internal.Util.SafeGetEnvironmentVariable; + +final class VMSystemProperties +{ + private VMSystemProperties() { } + + public static final String SPEC_TITLE = "Java Platform API Specification"; + public static final String SPEC_VERSION = "1.8"; + public static final String SPEC_VENDOR = "Oracle Corporation"; + + private static String getLibraryPath() + { + String libraryPath; + if(ikvm.internal.Util.WINDOWS) + { + // see /hotspot/src/os/windows/vm/os_windows.cpp for the comment that describes how we build the path + String windir = SafeGetEnvironmentVariable("SystemRoot"); + if(windir != null) + { + libraryPath = cli.System.IO.Path.PathSeparator + windir + "\\Sun\\Java\\bin"; + } + else + { + libraryPath = null; + } + try + { + if(false) throw new cli.System.Security.SecurityException(); + if (libraryPath == null) + { + libraryPath = cli.System.Environment.get_SystemDirectory(); + } + else + { + libraryPath += cli.System.IO.Path.PathSeparator + cli.System.Environment.get_SystemDirectory(); + } + } + catch(cli.System.Security.SecurityException _) + { + } + if(windir != null) + { + libraryPath += cli.System.IO.Path.PathSeparator + windir; + } + String path = SafeGetEnvironmentVariable("PATH"); + if(path != null) + { + libraryPath += cli.System.IO.Path.PathSeparator + path; + } + } + else if(ikvm.internal.Util.MACOSX) + { + libraryPath = "."; + } + else /* assume Linux, since that's the only other platform we support */ + { + // on Linux we have some hardcoded paths (from /hotspot/src/os/linux/vm/os_linux.cpp) + // and we can only guess the cpu arch based on bitness (that means only x86 and x64) + String cpu_arch = cli.System.IntPtr.get_Size() == 4 ? "i386" : "amd64"; + libraryPath = "/usr/java/packages/lib/" + cpu_arch + ":/lib:/usr/lib"; + String ld_library_path = SafeGetEnvironmentVariable("LD_LIBRARY_PATH"); + if(ld_library_path != null) + { + libraryPath = ld_library_path + ":" + libraryPath; + } + } + try + { + cli.System.Reflection.Assembly entryAsm = cli.System.Reflection.Assembly.GetEntryAssembly(); + // If the CLR was started by a native app (e.g. via COM interop) there is no entry assembly + if (entryAsm != null) + { + // the application (or launcher) directory is prepended to the library path + // (similar to how the JDK prepends its directory to the path) + libraryPath = new cli.System.IO.FileInfo(entryAsm.get_Location()).get_DirectoryName() + cli.System.IO.Path.PathSeparator + libraryPath; + } + } + catch(Throwable _) + { + // ignore + } + if(ikvm.internal.Util.WINDOWS) + { + libraryPath += cli.System.IO.Path.PathSeparator + "."; + } + return libraryPath; + } + + private static void initCommonProperties(Properties p) + { + p.setProperty("java.version", "1.8.0"); + p.setProperty("java.vendor", "Jeroen Frijters"); + p.setProperty("java.vendor.url", "http://ikvm.net/"); + p.setProperty("java.vendor.url.bug", "http://www.ikvm.net/bugs"); + p.setProperty("java.vm.specification.version", "1.8"); + p.setProperty("java.vm.specification.vendor", "Oracle Corporation"); + p.setProperty("java.vm.specification.name", "Java Virtual Machine Specification"); + p.setProperty("java.vm.version", PropertyConstants.java_vm_version); + p.setProperty("java.vm.vendor", "Jeroen Frijters"); + p.setProperty("java.vm.name", "IKVM.NET"); + p.setProperty("java.runtime.name", "IKVM.NET"); + p.setProperty("java.runtime.version", PropertyConstants.java_runtime_version); + p.setProperty("java.specification.version", SPEC_VERSION); + p.setProperty("java.specification.vendor", SPEC_VENDOR); + p.setProperty("java.specification.name", SPEC_TITLE); + p.setProperty("java.class.version", "52.0"); + p.setProperty("java.class.path", ""); + p.setProperty("java.library.path", getLibraryPath()); + try + { + if(false) throw new cli.System.Security.SecurityException(); + p.setProperty("java.io.tmpdir", cli.System.IO.Path.GetTempPath()); + } + catch(cli.System.Security.SecurityException _) + { + // TODO should we set another value? + p.setProperty("java.io.tmpdir", "."); + } + p.setProperty("java.ext.dirs", ""); + // NOTE os.name *must* contain "Windows" when running on Windows, because Classpath tests on that + String osname = null; + String osver = null; + cli.System.OperatingSystem os = cli.System.Environment.get_OSVersion(); + int major = os.get_Version().get_Major(); + int minor = os.get_Version().get_Minor(); + switch(os.get_Platform().Value) + { + case cli.System.PlatformID.Win32NT: + // Windows lies about the version, so we extract the real version from kernel32.dll + FileVersionInfo kernel32 = getKernel32FileVersionInfo(); + if (kernel32 != null) + { + major = kernel32.get_ProductMajorPart(); + minor = kernel32.get_ProductMinorPart(); + } + osname = "Windows NT (unknown)"; + switch(major) + { + case 3: + case 4: + osver = major + "." + minor; + osname = "Windows NT"; + break; + case 5: + switch(minor) + { + case 0: + osver = "5.0"; + osname = "Windows 2000"; + break; + case 1: + osver = "5.1"; + osname = "Windows XP"; + break; + case 2: + osver = "5.2"; + osname = "Windows 2003"; + break; + } + break; + case 6: + // since there appears to be no managed way to differentiate between Client/Server, we report client names + switch(minor) + { + case 0: + osver = "6.0"; + osname = "Windows Vista"; + break; + case 1: + osver = "6.1"; + osname = "Windows 7"; + break; + case 2: + osver = "6.2"; + osname = "Windows 8"; + break; + case 3: + osver = "6.3"; + osname = "Windows 8.1"; + break; + } + break; + case 10: + switch(minor) + { + case 0: + osver = "10.0"; + osname = "Windows 10"; + break; + } + break; + } + break; + case cli.System.PlatformID.Win32Windows: + if(major == 4) + { + switch(minor) + { + case 0: + osver = "4.0"; + osname = "Windows 95"; + break; + case 10: + osver = "4.10"; + osname = "Windows 98"; + break; + case 90: + osver = "4.90"; + osname = "Windows Me"; + break; + } + } + break; + case cli.System.PlatformID.Unix: + if(ikvm.internal.Util.MACOSX) + { + // for back compat Mono will return PlatformID.Unix when running on the Mac, + // so we handle that explicitly here + osname = "Mac OS X"; + // HACK this tries to map the Darwin version to the OS X version + // (based on http://en.wikipedia.org/wiki/Darwin_(operating_system)#Releases) + cli.System.Version ver = cli.System.Environment.get_OSVersion().get_Version(); + osver = "10." + (ver.get_Major() - 4) + "." + ver.get_Minor(); + } + break; + } + if(osname == null) + { + osname = cli.System.Environment.get_OSVersion().ToString(); + } + if(osver == null) + { + osver = major + "." + minor; + } + p.setProperty("os.name", osname); + p.setProperty("os.version", osver); + String arch = SafeGetEnvironmentVariable("PROCESSOR_ARCHITECTURE"); + if(arch == null) + { + // we don't know, so we make a guess + if(cli.System.IntPtr.get_Size() == 4) + { + arch = ikvm.internal.Util.WINDOWS ? "x86" : "i386"; + } + else + { + arch = "amd64"; + } + } + if(arch.equals("AMD64")) + { + arch = "amd64"; + } + p.setProperty("os.arch", arch); + p.setProperty("sun.arch.data.model", "" + (cli.System.IntPtr.get_Size() * 8)); + p.setProperty("file.separator", "" + cli.System.IO.Path.DirectorySeparatorChar); + p.setProperty("file.encoding", cli.System.Text.Encoding.get_Default().get_WebName()); + p.setProperty("path.separator", "" + cli.System.IO.Path.PathSeparator); + p.setProperty("line.separator", cli.System.Environment.get_NewLine()); + try + { + if(false) throw new cli.System.Security.SecurityException(); + p.setProperty("user.name", cli.System.Environment.get_UserName()); + } + catch(cli.System.Security.SecurityException _) + { + p.setProperty("user.name", "(unknown)"); + } + String home = SafeGetEnvironmentVariable("USERPROFILE"); + if(home == null) + { + // maybe we're on *nix + home = SafeGetEnvironmentVariable("HOME"); + if(home == null) + { + // TODO maybe there is a better way + // NOTE on MS .NET this doesn't return the correct path + // (it returns "C:\\Documents and Settings\\username\\My Documents", but we really need + // "C:\\Documents and Settings\\username" to be compatible with Sun, that's why we use %USERPROFILE% if it exists) + try + { + if(false) throw new cli.System.Security.SecurityException(); + home = cli.System.Environment.GetFolderPath(cli.System.Environment.SpecialFolder.wrap(cli.System.Environment.SpecialFolder.Personal)); + } + catch(cli.System.Security.SecurityException _) + { + home = "."; + } + } + } + p.setProperty("user.home", home); + try + { + if(false) throw new cli.System.Security.SecurityException(); + p.setProperty("user.dir", cli.System.Environment.get_CurrentDirectory()); + } + catch(cli.System.Security.SecurityException _) + { + p.setProperty("user.dir", "."); + } + p.setProperty("awt.toolkit", PropertyConstants.awt_toolkit); + } + + public static void initProperties(Properties p) + { + p.setProperty("openjdk.version", PropertyConstants.openjdk_version); + String vfsroot = getVirtualFileSystemRoot(); + p.setProperty("java.home", vfsroot.substring(0, vfsroot.length() - 1)); + // the %home%\lib\endorsed directory does not exist, but neither does it on JDK 1.7 + p.setProperty("java.endorsed.dirs", vfsroot + "lib" + cli.System.IO.Path.DirectorySeparatorChar + "endorsed"); + p.setProperty("sun.boot.library.path", vfsroot + "bin"); + p.setProperty("sun.boot.class.path", getBootClassPath()); + initCommonProperties(p); + setupI18N(p); + p.setProperty("sun.cpu.endian", cli.System.BitConverter.IsLittleEndian ? "little" : "big"); + p.setProperty("file.encoding.pkg", "sun.io"); + p.setProperty("user.timezone", ""); + p.setProperty("sun.os.patch.level", cli.System.Environment.get_OSVersion().get_ServicePack()); + p.setProperty("java.vm.info", "compiled mode"); + p.setProperty("sun.nio.MaxDirectMemorySize", "-1"); + p.setProperty("java.awt.graphicsenv", PropertyConstants.java_awt_graphicsenv); + p.setProperty("java.awt.printerjob", "sun.awt.windows.WPrinterJob"); + + String stdoutEncoding = getStdoutEncoding(); + if(stdoutEncoding != null) + { + p.setProperty("sun.stdout.encoding", stdoutEncoding); + } + String stderrEncoding = getStderrEncoding(); + if(stderrEncoding != null) + { + p.setProperty("sun.stderr.encoding", stderrEncoding); + } + + if(ikvm.internal.Util.MACOSX) + { + p.setProperty("sun.jnu.encoding", "UTF-8"); + } + else + { + p.setProperty("sun.jnu.encoding", cli.System.Text.Encoding.get_Default().get_WebName()); + } + + + // TODO + // sun.cpu.isalist:=pentium_pro+mmx pentium_pro pentium+mmx pentium i486 i386 i86 + // sun.desktop:=windows + // sun.io.unicode.encoding:=UnicodeLittle + // sun.management.compiler:=HotSpot Client Compiler + try + { + // read properties from app.config + if(false) throw new cli.System.Configuration.ConfigurationException(); + cli.System.Collections.Specialized.NameValueCollection appSettings = cli.System.Configuration.ConfigurationSettings.get_AppSettings(); + cli.System.Collections.IEnumerator keys = appSettings.GetEnumerator(); + while(keys.MoveNext()) + { + String key = (String)keys.get_Current(); + if(key.startsWith("ikvm:")) + { + p.setProperty(key.substring(5), appSettings.get_Item(key)); + } + } + } + catch(cli.System.Configuration.ConfigurationException _) + { + // app.config is invalid, ignore + } + // set the properties that were specified with ikvm.runtime.Startup.setProperties() + cli.System.Collections.IDictionary props = ikvm.runtime.Startup.props; + if(props != null) + { + cli.System.Collections.IDictionaryEnumerator entries = props.GetEnumerator(); + while(entries.MoveNext()) + { + p.setProperty((String)entries.get_Key(), (String)entries.get_Value()); + } + } + } + + private static void setupI18N(Properties p) + { + String[] culture = ((cli.System.String)(Object)cli.System.Globalization.CultureInfo.get_CurrentCulture().get_Name()).Split(new char[] { '-' }); + String language; + String script; + String region; + String variant; + if (culture.length == 2) + { + language = culture[0]; + if (culture[1].length() == 4) + { + script = culture[1]; + region = ""; + } + else + { + script = ""; + region = culture[1]; + } + } + else if (culture.length == 3) + { + language = culture[0]; + script = culture[1]; + region = culture[2]; + } + else + { + language = "en"; + script = ""; + region = "US"; + } + // Norwegian + if (language.equals("nb")) + { + language = "no"; + region = "NO"; + variant = ""; + } + else if (language.equals("nn")) + { + language = "no"; + region = "NO"; + variant = "NY"; + } + else + { + variant = ""; + } + p.setProperty("user.language", language); + p.setProperty("user.country", region); + p.setProperty("user.variant", variant); + p.setProperty("user.script", script); + } + + private static native String getVirtualFileSystemRoot(); + private static native String getBootClassPath(); + private static native String getStdoutEncoding(); + private static native String getStderrEncoding(); + private static native FileVersionInfo getKernel32FileVersionInfo(); +} diff --git a/openjdk/java/lang/invoke/LightWeightMethodHandle.java b/openjdk/java/lang/invoke/LightWeightMethodHandle.java new file mode 100644 index 0000000..7476ab7 --- /dev/null +++ b/openjdk/java/lang/invoke/LightWeightMethodHandle.java @@ -0,0 +1,47 @@ +/* + Copyright (C) 2015 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package java.lang.invoke; + +/* + * This class represents a MethodHandle to an IKVM specific LambdaForm. + */ +final class LightWeightMethodHandle extends MethodHandle +{ + LightWeightMethodHandle(MethodType type, LambdaForm form) + { + super(type, form); + } + + @Override + BoundMethodHandle rebind() + { + return BoundMethodHandle.makeReinvoker(this); + } + + @Override + MethodHandle copyWith(MethodType type, LambdaForm form) + { + return new LightWeightMethodHandle(type, form); + } +} diff --git a/openjdk/java/lang/management/PlatformComponent.java b/openjdk/java/lang/management/PlatformComponent.java new file mode 100644 index 0000000..54ac5d3 --- /dev/null +++ b/openjdk/java/lang/management/PlatformComponent.java @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2008, 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 java.lang.management; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.HashSet; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; + +import sun.management.ManagementFactoryHelper; +import sun.management.Util; + +/** + * This enum class defines the list of platform components + * that provides monitoring and management support. + * Each enum represents one MXBean interface. A MXBean + * instance could implement one or more MXBean interfaces. + * + * For example, com.sun.management.GarbageCollectorMXBean + * extends java.lang.management.GarbageCollectorMXBean + * and there is one set of garbage collection MXBean instances, + * each of which implements both c.s.m. and j.l.m. interfaces. + * There are two separate enums GARBAGE_COLLECTOR + * and SUN_GARBAGE_COLLECTOR so that ManagementFactory.getPlatformMXBeans(Class) + * will return the list of MXBeans of the specified type. + * + * To add a new MXBean interface for the Java platform, + * add a new enum constant and implement the MXBeanFetcher. + */ +enum PlatformComponent { + + /** + * Class loading system of the Java virtual machine. + */ + CLASS_LOADING( + "java.lang.management.ClassLoadingMXBean", + "java.lang", "ClassLoading", defaultKeyProperties(), + true, // singleton + new MXBeanFetcher() { + public List getMXBeans() { + return Collections.singletonList(ManagementFactoryHelper.getClassLoadingMXBean()); + } + }), + + /** + * Compilation system of the Java virtual machine. + */ + COMPILATION( + "java.lang.management.CompilationMXBean", + "java.lang", "Compilation", defaultKeyProperties(), + true, // singleton + new MXBeanFetcher() { + public List getMXBeans() { + CompilationMXBean m = ManagementFactoryHelper.getCompilationMXBean(); + if (m == null) { + return Collections.emptyList(); + } else { + return Collections.singletonList(m); + } + } + }), + + /** + * Memory system of the Java virtual machine. + */ + MEMORY( + "java.lang.management.MemoryMXBean", + "java.lang", "Memory", defaultKeyProperties(), + true, // singleton + new MXBeanFetcher() { + public List getMXBeans() { + return Collections.singletonList(ManagementFactoryHelper.getMemoryMXBean()); + } + }), + + /** + * Garbage Collector in the Java virtual machine. + */ + GARBAGE_COLLECTOR( + "java.lang.management.GarbageCollectorMXBean", + "java.lang", "GarbageCollector", keyProperties("name"), + false, // zero or more instances + new MXBeanFetcher() { + public List getMXBeans() { + return ManagementFactoryHelper. + getGarbageCollectorMXBeans(); + } + }), + + /** + * Memory manager in the Java virtual machine. + */ + MEMORY_MANAGER( + "java.lang.management.MemoryManagerMXBean", + "java.lang", "MemoryManager", keyProperties("name"), + false, // zero or more instances + new MXBeanFetcher() { + public List getMXBeans() { + return ManagementFactoryHelper.getMemoryManagerMXBeans(); + } + }, + GARBAGE_COLLECTOR), + + /** + * Memory pool in the Java virtual machine. + */ + MEMORY_POOL( + "java.lang.management.MemoryPoolMXBean", + "java.lang", "MemoryPool", keyProperties("name"), + false, // zero or more instances + new MXBeanFetcher() { + public List getMXBeans() { + return ManagementFactoryHelper.getMemoryPoolMXBeans(); + } + }), + + /** + * Operating system on which the Java virtual machine is running + */ + OPERATING_SYSTEM( + "java.lang.management.OperatingSystemMXBean", + "java.lang", "OperatingSystem", defaultKeyProperties(), + true, // singleton + new MXBeanFetcher() { + public List getMXBeans() { + return Collections.singletonList(ManagementFactoryHelper.getOperatingSystemMXBean()); + } + }), + + /** + * Runtime system of the Java virtual machine. + */ + RUNTIME( + "java.lang.management.RuntimeMXBean", + "java.lang", "Runtime", defaultKeyProperties(), + true, // singleton + new MXBeanFetcher() { + public List getMXBeans() { + return Collections.singletonList(ManagementFactoryHelper.getRuntimeMXBean()); + } + }), + + /** + * Threading system of the Java virtual machine. + */ + THREADING( + "java.lang.management.ThreadMXBean", + "java.lang", "Threading", defaultKeyProperties(), + true, // singleton + new MXBeanFetcher() { + public List getMXBeans() { + return Collections.singletonList(ManagementFactoryHelper.getThreadMXBean()); + } + }), + + + /** + * Logging facility. + */ + LOGGING( + "java.lang.management.PlatformLoggingMXBean", + "java.util.logging", "Logging", defaultKeyProperties(), + true, // singleton + new MXBeanFetcher() { + public List getMXBeans() { + PlatformLoggingMXBean m = ManagementFactoryHelper.getPlatformLoggingMXBean(); + if (m == null) { + return Collections.emptyList(); + } else { + return Collections.singletonList(m); + } + } + }), + + /** + * Buffer pools. + */ + BUFFER_POOL( + "java.lang.management.BufferPoolMXBean", + "java.nio", "BufferPool", keyProperties("name"), + false, // zero or more instances + new MXBeanFetcher() { + public List getMXBeans() { + return ManagementFactoryHelper.getBufferPoolMXBeans(); + } + }); + + /** + * A task that returns the MXBeans for a component. + */ + interface MXBeanFetcher { + public List getMXBeans(); + } + + /* + * Returns a list of the GC MXBeans of the given type. + */ + private static + List getGcMXBeanList(Class gcMXBeanIntf) { + List list = + ManagementFactoryHelper.getGarbageCollectorMXBeans(); + List result = new ArrayList<>(list.size()); + for (GarbageCollectorMXBean m : list) { + if (gcMXBeanIntf.isInstance(m)) { + result.add(gcMXBeanIntf.cast(m)); + } + } + return result; + } + + /* + * Returns the OS mxbean instance of the given type. + */ + private static + List getOSMXBeanList(Class osMXBeanIntf) { + OperatingSystemMXBean m = + ManagementFactoryHelper.getOperatingSystemMXBean(); + if (osMXBeanIntf.isInstance(m)) { + return Collections.singletonList(osMXBeanIntf.cast(m)); + } else { + return Collections.emptyList(); + } + } + + private final String mxbeanInterfaceName; + private final String domain; + private final String type; + private final Set keyProperties; + private final MXBeanFetcher fetcher; + private final PlatformComponent[] subComponents; + private final boolean singleton; + + private PlatformComponent(String intfName, + String domain, String type, + Set keyProperties, + boolean singleton, + MXBeanFetcher fetcher, + PlatformComponent... subComponents) { + this.mxbeanInterfaceName = intfName; + this.domain = domain; + this.type = type; + this.keyProperties = keyProperties; + this.singleton = singleton; + this.fetcher = fetcher; + this.subComponents = subComponents; + } + + private static Set defaultKeyProps; + private static Set defaultKeyProperties() { + if (defaultKeyProps == null) { + defaultKeyProps = Collections.singleton("type"); + } + return defaultKeyProps; + } + + private static Set keyProperties(String... keyNames) { + Set set = new HashSet<>(); + set.add("type"); + for (String s : keyNames) { + set.add(s); + } + return set; + } + + boolean isSingleton() { + return singleton; + } + + String getMXBeanInterfaceName() { + return mxbeanInterfaceName; + } + + @SuppressWarnings("unchecked") + Class getMXBeanInterface() { + try { + // Lazy loading the MXBean interface only when it is needed + return (Class) + Class.forName(mxbeanInterfaceName, false, + PlatformManagedObject.class.getClassLoader()); + } catch (ClassNotFoundException x) { + throw new AssertionError(x); + } + } + + @SuppressWarnings("unchecked") + + List getMXBeans(Class mxbeanInterface) + { + return (List) fetcher.getMXBeans(); + } + + T getSingletonMXBean(Class mxbeanInterface) + { + if (!singleton) + throw new IllegalArgumentException(mxbeanInterfaceName + + " can have zero or more than one instances"); + + List list = getMXBeans(mxbeanInterface); + assert list.size() == 1; + return list.isEmpty() ? null : list.get(0); + } + + + T getSingletonMXBean(MBeanServerConnection mbs, Class mxbeanInterface) + throws java.io.IOException + { + if (!singleton) + throw new IllegalArgumentException(mxbeanInterfaceName + + " can have zero or more than one instances"); + + // ObjectName of a singleton MXBean contains only domain and type + assert keyProperties.size() == 1; + String on = domain + ":type=" + type; + return ManagementFactory.newPlatformMXBeanProxy(mbs, + on, + mxbeanInterface); + } + + + List getMXBeans(MBeanServerConnection mbs, Class mxbeanInterface) + throws java.io.IOException + { + List result = new ArrayList<>(); + for (ObjectName on : getObjectNames(mbs)) { + result.add(ManagementFactory. + newPlatformMXBeanProxy(mbs, + on.getCanonicalName(), + mxbeanInterface) + ); + } + return result; + } + + private Set getObjectNames(MBeanServerConnection mbs) + throws java.io.IOException + { + String domainAndType = domain + ":type=" + type; + if (keyProperties.size() > 1) { + // if there are more than 1 key properties (i.e. other than "type") + domainAndType += ",*"; + } + ObjectName on = Util.newObjectName(domainAndType); + Set set = mbs.queryNames(on, null); + for (PlatformComponent pc : subComponents) { + set.addAll(pc.getObjectNames(mbs)); + } + return set; + } + + // a map from MXBean interface name to PlatformComponent + private static Map enumMap; + private static synchronized void ensureInitialized() { + if (enumMap == null) { + enumMap = new HashMap<>(); + for (PlatformComponent pc: PlatformComponent.values()) { + // Use String as the key rather than Class to avoid + // causing unnecessary class loading of management interface + enumMap.put(pc.getMXBeanInterfaceName(), pc); + } + } + } + + static boolean isPlatformMXBean(String cn) { + ensureInitialized(); + return enumMap.containsKey(cn); + } + + static + PlatformComponent getPlatformComponent(Class mxbeanInterface) + { + ensureInitialized(); + String cn = mxbeanInterface.getName(); + PlatformComponent pc = enumMap.get(cn); + if (pc != null && pc.getMXBeanInterface() == mxbeanInterface) + return pc; + return null; + } + + private static final long serialVersionUID = 6992337162326171013L; +} diff --git a/openjdk/java/lang/ref/Reference.java b/openjdk/java/lang/ref/Reference.java new file mode 100644 index 0000000..ba8f330 --- /dev/null +++ b/openjdk/java/lang/ref/Reference.java @@ -0,0 +1,137 @@ +/* + Copyright (C) 2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package java.lang.ref; + +import sun.misc.Cleaner; + +public abstract class Reference +{ + private final cli.System.WeakReference weakRef; + T strongRef; + ReferenceQueue queue; + Reference next; + + Reference(T referent) + { + this(referent, null); + } + + Reference(T referent, ReferenceQueue queue) + { + this.queue = queue == null ? ReferenceQueue.NULL : queue; + if (referent instanceof Class && noclassgc()) + { + // We don't do Class gc, so no point in using a weak reference for classes. + weakRef = null; + strongRef = referent; + } + else if (referent == null) + { + weakRef = null; + } + else + { + weakRef = new cli.System.WeakReference(referent, this instanceof PhantomReference); + if (queue != null) + { + queue.addToActiveList(this); + } + if (this instanceof Cleaner) + { + new CleanerGuard(); + } + } + } + + private final class CleanerGuard + { + protected void finalize() + { + if (isActive()) { + cli.System.GC.ReRegisterForFinalize(this); + } else { + ((Cleaner)Reference.this).clean(); + } + } + } + + public T get() + { + if (weakRef == null) + { + return strongRef; + } + return (T)weakRef.get_Target(); + } + + public void clear() + { + if (weakRef != null) + { + try + { + if (false) throw new cli.System.InvalidOperationException(); + weakRef.set_Target(null); + } + catch (cli.System.InvalidOperationException x) + { + // we were already finalized + } + } + strongRef = null; + queue.clear(this); + } + + public boolean isEnqueued() + { + if (queue == ReferenceQueue.ENQUEUED) { + return true; + } + if (queue == ReferenceQueue.NULL) { + return false; + } + if (isStrongOrNullRef() || isActive()) { + return false; + } + queue.enqueue(this); + return queue == ReferenceQueue.ENQUEUED; + } + + public boolean enqueue() + { + return queue.enqueue(this); + } + + final boolean isActive() + { + return strongRef != null || (weakRef != null && weakRef.get_IsAlive()); + } + + final boolean isStrongOrNullRef() + { + return weakRef == null; + } + + static native boolean noclassgc(); +} diff --git a/openjdk/java/lang/ref/ReferenceQueue.java b/openjdk/java/lang/ref/ReferenceQueue.java new file mode 100644 index 0000000..1d58d9b --- /dev/null +++ b/openjdk/java/lang/ref/ReferenceQueue.java @@ -0,0 +1,208 @@ +/* + Copyright (C) 2014-2015 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package java.lang.ref; + +public class ReferenceQueue +{ + static final ReferenceQueue ENQUEUED = new ReferenceQueue(); + static final ReferenceQueue NULL = new ReferenceQueue(); + private volatile Link activeHead; + private volatile Reference head; + final Object lock = new Object(); + volatile boolean waitingForGC; + + private final class GCNotification { + protected void finalize() { + waitingForGC = false; + synchronized (lock) { + lock.notifyAll(); + } + } + } + + // NOTE a known problem with this approach is that the WeakReference will not be available + // after we've become only finalizer reachable + private static class Link extends cli.System.WeakReference { + Link next; + + Link(Reference ref) { + super(ref); + } + + Reference get() { + return (Reference)get_Target(); + } + } + + public Reference poll() + { + if (head == null && (activeHead == null || waitingForGC)) { + return null; + } + synchronized (lock) { + return pollImpl(); + } + } + + private Reference pollImpl() + { + if (head == null) { + if (activeHead == null || waitingForGC) { + return null; + } + scanActiveList(); + if (head == null) { + waitingForGC = true; + new GCNotification(); + return null; + } + } + Reference ref = head; + head = ref.next; + ref.next = null; + ref.queue = NULL; + return ref; + } + + public Reference remove(long timeout) throws IllegalArgumentException, InterruptedException + { + if (timeout < 0) + throw new IllegalArgumentException("Negative timeout value"); + + synchronized (lock) { + long expiration = 0; + for (;;) { + Reference ref = pollImpl(); + if (ref != null) + return ref; + + if (timeout == 0) { + lock.wait(); + } else { + long now = System.currentTimeMillis(); + if (expiration == 0) { + expiration = now + timeout; + if (expiration < 0) { + expiration = Long.MAX_VALUE; + } + } + if (now >= expiration) { + return null; + } + lock.wait(expiration - now); + } + } + } + } + + public Reference remove() throws InterruptedException + { + return remove(0); + } + + final void clear(Reference ref) + { + synchronized (lock) { + if (ref.queue != ENQUEUED) { + ref.queue = NULL; + } + } + } + + final boolean enqueue(Reference ref) + { + synchronized (lock) { + if (ref.queue != ENQUEUED && ref.queue != NULL) { + ref.queue = ENQUEUED; + + if (ref.isStrongOrNullRef()) { + ref.next = head; + head = ref; + lock.notifyAll(); + return true; + } + + Link prev = null; + Link curr = activeHead; + + while (curr != null) { + if (curr.get() == ref) { + if (prev == null) { + activeHead = curr.next; + } else { + prev.next = curr.next; + } + ref.next = head; + head = ref; + lock.notifyAll(); + return true; + } + prev = curr; + curr = curr.next; + } + } + } + return false; + } + + final void addToActiveList(Reference ref) + { + Link link = new Link(ref); + synchronized (lock) { + link.next = activeHead; + activeHead = link; + if (link.next == null) { + lock.notifyAll(); + } + } + } + + private void scanActiveList() + { + Link prev = null; + Link curr = activeHead; + + while (curr != null) { + Reference ref = curr.get(); + if (ref == null || !ref.isActive()) { + Link next = curr.next; + if (prev == null) { + activeHead = next; + } else { + prev.next = next; + } + if (ref != null) { + ref.next = head; + ref.queue = ENQUEUED; + head = ref; + } + curr = next; + continue; + } + prev = curr; + curr = curr.next; + } + } +} diff --git a/openjdk/java/lang/ref/SoftReference.java b/openjdk/java/lang/ref/SoftReference.java new file mode 100644 index 0000000..518ae44 --- /dev/null +++ b/openjdk/java/lang/ref/SoftReference.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 1997, 2003, 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 java.lang.ref; + + +/** + * Soft reference objects, which are cleared at the discretion of the garbage + * collector in response to memory demand. Soft references are most often used + * to implement memory-sensitive caches. + * + *

Suppose that the garbage collector determines at a certain point in time + * that an object is softly + * reachable. At that time it may choose to clear atomically all soft + * references to that object and all soft references to any other + * softly-reachable objects from which that object is reachable through a chain + * of strong references. At the same time or at some later time it will + * enqueue those newly-cleared soft references that are registered with + * reference queues. + * + *

All soft references to softly-reachable objects are guaranteed to have + * been cleared before the virtual machine throws an + * OutOfMemoryError. Otherwise no constraints are placed upon the + * time at which a soft reference will be cleared or the order in which a set + * of such references to different objects will be cleared. Virtual machine + * implementations are, however, encouraged to bias against clearing + * recently-created or recently-used soft references. + * + *

Direct instances of this class may be used to implement simple caches; + * this class or derived subclasses may also be used in larger data structures + * to implement more sophisticated caches. As long as the referent of a soft + * reference is strongly reachable, that is, is actually in use, the soft + * reference will not be cleared. Thus a sophisticated cache can, for example, + * prevent its most recently used entries from being discarded by keeping + * strong referents to those entries, leaving the remaining entries to be + * discarded at the discretion of the garbage collector. + * + * @author Mark Reinhold + * @since 1.2 + */ + +public class SoftReference extends Reference { + + /** + * Timestamp clock, updated by the garbage collector + */ + static private long clock; + + /** + * Timestamp updated by each invocation of the get method. The VM may use + * this field when selecting soft references to be cleared, but it is not + * required to do so. + */ + private long timestamp; + + /** + * Creates a new soft reference that refers to the given object. The new + * reference is not registered with any queue. + * + * @param referent object the new soft reference will refer to + */ + public SoftReference(T referent) { + this(referent, null); + } + + /** + * Creates a new soft reference that refers to the given object and is + * registered with the given queue. + * + * @param referent object the new soft reference will refer to + * @param q the queue with which the reference is to be registered, + * or null if registration is not required + * + */ + public SoftReference(T referent, ReferenceQueue q) { + super(referent, q); + setStrongRef(referent); + } + + /** + * Returns this reference object's referent. If this reference object has + * been cleared, either by the program or by the garbage collector, then + * this method returns null. + * + * @return The object to which this reference refers, or + * null if this reference object has been cleared + */ + public T get() { + T o = strongRef; + if (o != null) { + return o; + } + o = super.get(); + setStrongRef(o); + return o; + } + + private void setStrongRef(T referent) + { + if (referent != null) { + strongRef = referent; + if (!(referent instanceof Class && noclassgc())) { + new Object() { + protected void finalize() { + strongRef = null; + } + }; + } + } + } +} diff --git a/openjdk/java/lang/reflect/Constructor.java b/openjdk/java/lang/reflect/Constructor.java new file mode 100644 index 0000000..9e01975 --- /dev/null +++ b/openjdk/java/lang/reflect/Constructor.java @@ -0,0 +1,562 @@ +/* + * Copyright (c) 1996, 2013, 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 java.lang.reflect; + +import sun.reflect.CallerSensitive; +import sun.reflect.ConstructorAccessor; +import sun.reflect.Reflection; +import sun.reflect.annotation.TypeAnnotation; +import sun.reflect.annotation.TypeAnnotationParser; +import sun.reflect.generics.repository.ConstructorRepository; +import sun.reflect.generics.factory.CoreReflectionFactory; +import sun.reflect.generics.factory.GenericsFactory; +import sun.reflect.generics.scope.ConstructorScope; +import java.lang.annotation.Annotation; +import java.lang.annotation.AnnotationFormatError; + +/** + * {@code Constructor} provides information about, and access to, a single + * constructor for a class. + * + *

{@code Constructor} permits widening conversions to occur when matching the + * actual parameters to newInstance() with the underlying + * constructor's formal parameters, but throws an + * {@code IllegalArgumentException} if a narrowing conversion would occur. + * + * @param the class in which the constructor is declared + * + * @see Member + * @see java.lang.Class + * @see java.lang.Class#getConstructors() + * @see java.lang.Class#getConstructor(Class[]) + * @see java.lang.Class#getDeclaredConstructors() + * + * @author Kenneth Russell + * @author Nakul Saraiya + */ +public final class Constructor extends Executable { + private Class clazz; + private int slot; + private Class[] parameterTypes; + private Class[] exceptionTypes; + private int modifiers; + // Generics and annotations support + private transient String signature; + // generic info repository; lazily initialized + private transient ConstructorRepository genericInfo; + + // Generics infrastructure + // Accessor for factory + private GenericsFactory getFactory() { + // create scope and factory + return CoreReflectionFactory.make(this, ConstructorScope.make(this)); + } + + // Accessor for generic info repository + @Override + ConstructorRepository getGenericInfo() { + // lazily initialize repository if necessary + if (genericInfo == null) { + // create and cache generic info repository + genericInfo = + ConstructorRepository.make(getSignature(), + getFactory()); + } + return genericInfo; //return cached repository + } + + private volatile ConstructorAccessor constructorAccessor; + // For sharing of ConstructorAccessors. This branching structure + // is currently only two levels deep (i.e., one root Constructor + // and potentially many Constructor objects pointing to it.) + // + // If this branching structure would ever contain cycles, deadlocks can + // occur in annotation code. + private Constructor root; + + /** + * Used by Excecutable for annotation sharing. + */ + @Override + Executable getRoot() { + return root; + } + + /** + * Package-private constructor used by ReflectAccess to enable + * instantiation of these objects in Java code from the java.lang + * package via sun.reflect.LangReflectAccess. + */ + Constructor(Class declaringClass, + Class[] parameterTypes, + Class[] checkedExceptions, + int modifiers, + int slot, + String signature, + byte[] unused1, + byte[] unused2) { + this.clazz = declaringClass; + this.parameterTypes = parameterTypes; + this.exceptionTypes = checkedExceptions; + this.modifiers = modifiers; + this.slot = slot; + this.signature = signature; + } + + /** + * Package-private routine (exposed to java.lang.Class via + * ReflectAccess) which returns a copy of this Constructor. The copy's + * "root" field points to this Constructor. + */ + Constructor copy() { + // This routine enables sharing of ConstructorAccessor objects + // among Constructor objects which refer to the same underlying + // method in the VM. (All of this contortion is only necessary + // because of the "accessibility" bit in AccessibleObject, + // which implicitly requires that new java.lang.reflect + // objects be fabricated for each reflective call on Class + // objects.) + if (this.root != null) + throw new IllegalArgumentException("Can not copy a non-root Constructor"); + + Constructor res = new Constructor<>(clazz, + parameterTypes, + exceptionTypes, modifiers, slot, + signature, + null, + null); + res.root = this; + // Might as well eagerly propagate this if already present + res.constructorAccessor = constructorAccessor; + return res; + } + + @Override + boolean hasGenericInformation() { + return (getSignature() != null); + } + + /** + * {@inheritDoc} + */ + @Override + public Class getDeclaringClass() { + return clazz; + } + + /** + * Returns the name of this constructor, as a string. This is + * the binary name of the constructor's declaring class. + */ + @Override + public String getName() { + return getDeclaringClass().getName(); + } + + /** + * {@inheritDoc} + */ + @Override + public int getModifiers() { + return modifiers; + } + + /** + * {@inheritDoc} + * @throws GenericSignatureFormatError {@inheritDoc} + * @since 1.5 + */ + @Override + @SuppressWarnings({"rawtypes", "unchecked"}) + public TypeVariable>[] getTypeParameters() { + if (getSignature() != null) { + return (TypeVariable>[])getGenericInfo().getTypeParameters(); + } else + return (TypeVariable>[])new TypeVariable[0]; + } + + + /** + * {@inheritDoc} + */ + @Override + public Class[] getParameterTypes() { + return parameterTypes.clone(); + } + + /** + * {@inheritDoc} + */ + public int getParameterCount() { return parameterTypes.length; } + + /** + * {@inheritDoc} + * @throws GenericSignatureFormatError {@inheritDoc} + * @throws TypeNotPresentException {@inheritDoc} + * @throws MalformedParameterizedTypeException {@inheritDoc} + * @since 1.5 + */ + @Override + public Type[] getGenericParameterTypes() { + return super.getGenericParameterTypes(); + } + + /** + * {@inheritDoc} + */ + @Override + public Class[] getExceptionTypes() { + return exceptionTypes.clone(); + } + + + /** + * {@inheritDoc} + * @throws GenericSignatureFormatError {@inheritDoc} + * @throws TypeNotPresentException {@inheritDoc} + * @throws MalformedParameterizedTypeException {@inheritDoc} + * @since 1.5 + */ + @Override + public Type[] getGenericExceptionTypes() { + return super.getGenericExceptionTypes(); + } + + /** + * Compares this {@code Constructor} against the specified object. + * Returns true if the objects are the same. Two {@code Constructor} objects are + * the same if they were declared by the same class and have the + * same formal parameter types. + */ + public boolean equals(Object obj) { + if (obj != null && obj instanceof Constructor) { + Constructor other = (Constructor)obj; + if (getDeclaringClass() == other.getDeclaringClass()) { + return equalParamTypes(parameterTypes, other.parameterTypes); + } + } + return false; + } + + /** + * Returns a hashcode for this {@code Constructor}. The hashcode is + * the same as the hashcode for the underlying constructor's + * declaring class name. + */ + public int hashCode() { + return getDeclaringClass().getName().hashCode(); + } + + /** + * Returns a string describing this {@code Constructor}. The string is + * formatted as the constructor access modifiers, if any, + * followed by the fully-qualified name of the declaring class, + * followed by a parenthesized, comma-separated list of the + * constructor's formal parameter types. For example: + *

+     *    public java.util.Hashtable(int,float)
+     * 
+ * + *

The only possible modifiers for constructors are the access + * modifiers {@code public}, {@code protected} or + * {@code private}. Only one of these may appear, or none if the + * constructor has default (package) access. + * + * @return a string describing this {@code Constructor} + * @jls 8.8.3. Constructor Modifiers + */ + public String toString() { + return sharedToString(Modifier.constructorModifiers(), + false, + parameterTypes, + exceptionTypes); + } + + @Override + void specificToStringHeader(StringBuilder sb) { + sb.append(getDeclaringClass().getTypeName()); + } + + /** + * Returns a string describing this {@code Constructor}, + * including type parameters. The string is formatted as the + * constructor access modifiers, if any, followed by an + * angle-bracketed comma separated list of the constructor's type + * parameters, if any, followed by the fully-qualified name of the + * declaring class, followed by a parenthesized, comma-separated + * list of the constructor's generic formal parameter types. + * + * If this constructor was declared to take a variable number of + * arguments, instead of denoting the last parameter as + * "Type[]", it is denoted as + * "Type...". + * + * A space is used to separate access modifiers from one another + * and from the type parameters or return type. If there are no + * type parameters, the type parameter list is elided; if the type + * parameter list is present, a space separates the list from the + * class name. If the constructor is declared to throw + * exceptions, the parameter list is followed by a space, followed + * by the word "{@code throws}" followed by a + * comma-separated list of the thrown exception types. + * + *

The only possible modifiers for constructors are the access + * modifiers {@code public}, {@code protected} or + * {@code private}. Only one of these may appear, or none if the + * constructor has default (package) access. + * + * @return a string describing this {@code Constructor}, + * include type parameters + * + * @since 1.5 + * @jls 8.8.3. Constructor Modifiers + */ + @Override + public String toGenericString() { + return sharedToGenericString(Modifier.constructorModifiers(), false); + } + + @Override + void specificToGenericStringHeader(StringBuilder sb) { + specificToStringHeader(sb); + } + + /** + * Uses the constructor represented by this {@code Constructor} object to + * create and initialize a new instance of the constructor's + * declaring class, with the specified initialization parameters. + * Individual parameters are automatically unwrapped to match + * primitive formal parameters, and both primitive and reference + * parameters are subject to method invocation conversions as necessary. + * + *

If the number of formal parameters required by the underlying constructor + * is 0, the supplied {@code initargs} array may be of length 0 or null. + * + *

If the constructor's declaring class is an inner class in a + * non-static context, the first argument to the constructor needs + * to be the enclosing instance; see section 15.9.3 of + * The Java™ Language Specification. + * + *

If the required access and argument checks succeed and the + * instantiation will proceed, the constructor's declaring class + * is initialized if it has not already been initialized. + * + *

If the constructor completes normally, returns the newly + * created and initialized instance. + * + * @param initargs array of objects to be passed as arguments to + * the constructor call; values of primitive types are wrapped in + * a wrapper object of the appropriate type (e.g. a {@code float} + * in a {@link java.lang.Float Float}) + * + * @return a new object created by calling the constructor + * this object represents + * + * @exception IllegalAccessException if this {@code Constructor} object + * is enforcing Java language access control and the underlying + * constructor is inaccessible. + * @exception IllegalArgumentException if the number of actual + * and formal parameters differ; if an unwrapping + * conversion for primitive arguments fails; or if, + * after possible unwrapping, a parameter value + * cannot be converted to the corresponding formal + * parameter type by a method invocation conversion; if + * this constructor pertains to an enum type. + * @exception InstantiationException if the class that declares the + * underlying constructor represents an abstract class. + * @exception InvocationTargetException if the underlying constructor + * throws an exception. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + */ + @CallerSensitive + public T newInstance(Object ... initargs) + throws InstantiationException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, null, modifiers); + } + } + if ((clazz.getModifiers() & Modifier.ENUM) != 0) + throw new IllegalArgumentException("Cannot reflectively create enum objects"); + ConstructorAccessor ca = constructorAccessor; // read volatile + if (ca == null) { + ca = acquireConstructorAccessor(); + } + @SuppressWarnings("unchecked") + T inst = (T) ca.newInstance(initargs); + return inst; + } + + /** + * {@inheritDoc} + * @since 1.5 + */ + @Override + public boolean isVarArgs() { + return super.isVarArgs(); + } + + /** + * {@inheritDoc} + * @jls 13.1 The Form of a Binary + * @since 1.5 + */ + @Override + public boolean isSynthetic() { + return super.isSynthetic(); + } + + // NOTE that there is no synchronization used here. It is correct + // (though not efficient) to generate more than one + // ConstructorAccessor for a given Constructor. However, avoiding + // synchronization will probably make the implementation more + // scalable. + private ConstructorAccessor acquireConstructorAccessor() { + // First check to see if one has been created yet, and take it + // if so. + ConstructorAccessor tmp = null; + if (root != null) tmp = root.getConstructorAccessor(); + if (tmp != null) { + constructorAccessor = tmp; + } else { + // Otherwise fabricate one and propagate it up to the root + tmp = reflectionFactory.newConstructorAccessor(this); + setConstructorAccessor(tmp); + } + + return tmp; + } + + // Returns ConstructorAccessor for this Constructor object, not + // looking up the chain to the root + ConstructorAccessor getConstructorAccessor() { + return constructorAccessor; + } + + // Sets the ConstructorAccessor for this Constructor object and + // (recursively) its root + void setConstructorAccessor(ConstructorAccessor accessor) { + constructorAccessor = accessor; + // Propagate up + if (root != null) { + root.setConstructorAccessor(accessor); + } + } + + int getSlot() { + return slot; + } + + String getSignature() { + return signature; + } + + byte[] getRawAnnotations() { + return null; + } + + byte[] getRawParameterAnnotations() { + return null; + } + + + /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + public T getAnnotation(Class annotationClass) { + return super.getAnnotation(annotationClass); + } + + /** + * {@inheritDoc} + * @since 1.5 + */ + public Annotation[] getDeclaredAnnotations() { + return super.getDeclaredAnnotations(); + } + + /** + * {@inheritDoc} + * @since 1.5 + */ + @Override + public Annotation[][] getParameterAnnotations() { + return sharedGetParameterAnnotations(parameterTypes); + } + + @Override + void handleParameterNumberMismatch(int resultLength, int numParameters) { + Class declaringClass = getDeclaringClass(); + if (declaringClass.isEnum() || + declaringClass.isAnonymousClass() || + declaringClass.isLocalClass() ) + return ; // Can't do reliable parameter counting + else { + if (!declaringClass.isMemberClass() || // top-level + // Check for the enclosing instance parameter for + // non-static member classes + (declaringClass.isMemberClass() && + ((declaringClass.getModifiers() & Modifier.STATIC) == 0) && + resultLength + 1 != numParameters) ) { + throw new AnnotationFormatError( + "Parameter annotations don't match number of parameters"); + } + } + } + + /** + * {@inheritDoc} + * @since 1.8 + */ + @Override + public AnnotatedType getAnnotatedReturnType() { + return getAnnotatedReturnType0(getDeclaringClass()); + } + + /** + * {@inheritDoc} + * @since 1.8 + */ + @Override + public AnnotatedType getAnnotatedReceiverType() { + if (getDeclaringClass().getEnclosingClass() == null) + return super.getAnnotatedReceiverType(); + + return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(), + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + getDeclaringClass().getEnclosingClass(), + TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER); + } +} diff --git a/openjdk/java/lang/reflect/Executable.java b/openjdk/java/lang/reflect/Executable.java new file mode 100644 index 0000000..be6ac0d --- /dev/null +++ b/openjdk/java/lang/reflect/Executable.java @@ -0,0 +1,720 @@ +/* + * Copyright (c) 2012, 2013, 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 java.lang.reflect; + +import java.lang.annotation.*; +import java.util.Map; +import java.util.Objects; +import sun.reflect.annotation.AnnotationParser; +import sun.reflect.annotation.AnnotationSupport; +import sun.reflect.annotation.TypeAnnotationParser; +import sun.reflect.annotation.TypeAnnotation; +import sun.reflect.generics.repository.ConstructorRepository; + +/** + * A shared superclass for the common functionality of {@link Method} + * and {@link Constructor}. + * + * @since 1.8 + */ +public abstract class Executable extends AccessibleObject + implements Member, GenericDeclaration { + /* + * Only grant package-visibility to the constructor. + */ + Executable() {} + + /** + * Accessor method to allow code sharing + */ + abstract Executable getRoot(); + + /** + * Does the Executable have generic information. + */ + abstract boolean hasGenericInformation(); + + abstract ConstructorRepository getGenericInfo(); + + boolean equalParamTypes(Class[] params1, Class[] params2) { + /* Avoid unnecessary cloning */ + if (params1.length == params2.length) { + for (int i = 0; i < params1.length; i++) { + if (params1[i] != params2[i]) + return false; + } + return true; + } + return false; + } + + void separateWithCommas(Class[] types, StringBuilder sb) { + for (int j = 0; j < types.length; j++) { + sb.append(types[j].getTypeName()); + if (j < (types.length - 1)) + sb.append(","); + } + + } + + void printModifiersIfNonzero(StringBuilder sb, int mask, boolean isDefault) { + int mod = getModifiers() & mask; + + if (mod != 0 && !isDefault) { + sb.append(Modifier.toString(mod)).append(' '); + } else { + int access_mod = mod & Modifier.ACCESS_MODIFIERS; + if (access_mod != 0) + sb.append(Modifier.toString(access_mod)).append(' '); + if (isDefault) + sb.append("default "); + mod = (mod & ~Modifier.ACCESS_MODIFIERS); + if (mod != 0) + sb.append(Modifier.toString(mod)).append(' '); + } + } + + String sharedToString(int modifierMask, + boolean isDefault, + Class[] parameterTypes, + Class[] exceptionTypes) { + try { + StringBuilder sb = new StringBuilder(); + + printModifiersIfNonzero(sb, modifierMask, isDefault); + specificToStringHeader(sb); + + sb.append('('); + separateWithCommas(parameterTypes, sb); + sb.append(')'); + if (exceptionTypes.length > 0) { + sb.append(" throws "); + separateWithCommas(exceptionTypes, sb); + } + return sb.toString(); + } catch (Exception e) { + return "<" + e + ">"; + } + } + + /** + * Generate toString header information specific to a method or + * constructor. + */ + abstract void specificToStringHeader(StringBuilder sb); + + String sharedToGenericString(int modifierMask, boolean isDefault) { + try { + StringBuilder sb = new StringBuilder(); + + printModifiersIfNonzero(sb, modifierMask, isDefault); + + TypeVariable[] typeparms = getTypeParameters(); + if (typeparms.length > 0) { + boolean first = true; + sb.append('<'); + for(TypeVariable typeparm: typeparms) { + if (!first) + sb.append(','); + // Class objects can't occur here; no need to test + // and call Class.getName(). + sb.append(typeparm.toString()); + first = false; + } + sb.append("> "); + } + + specificToGenericStringHeader(sb); + + sb.append('('); + Type[] params = getGenericParameterTypes(); + for (int j = 0; j < params.length; j++) { + String param = params[j].getTypeName(); + if (isVarArgs() && (j == params.length - 1)) // replace T[] with T... + param = param.replaceFirst("\\[\\]$", "..."); + sb.append(param); + if (j < (params.length - 1)) + sb.append(','); + } + sb.append(')'); + Type[] exceptions = getGenericExceptionTypes(); + if (exceptions.length > 0) { + sb.append(" throws "); + for (int k = 0; k < exceptions.length; k++) { + sb.append((exceptions[k] instanceof Class)? + ((Class)exceptions[k]).getName(): + exceptions[k].toString()); + if (k < (exceptions.length - 1)) + sb.append(','); + } + } + return sb.toString(); + } catch (Exception e) { + return "<" + e + ">"; + } + } + + /** + * Generate toGenericString header information specific to a + * method or constructor. + */ + abstract void specificToGenericStringHeader(StringBuilder sb); + + /** + * Returns the {@code Class} object representing the class or interface + * that declares the executable represented by this object. + */ + public abstract Class getDeclaringClass(); + + /** + * Returns the name of the executable represented by this object. + */ + public abstract String getName(); + + /** + * Returns the Java language {@linkplain Modifier modifiers} for + * the executable represented by this object. + */ + public abstract int getModifiers(); + + /** + * Returns an array of {@code TypeVariable} objects that represent the + * type variables declared by the generic declaration represented by this + * {@code GenericDeclaration} object, in declaration order. Returns an + * array of length 0 if the underlying generic declaration declares no type + * variables. + * + * @return an array of {@code TypeVariable} objects that represent + * the type variables declared by this generic declaration + * @throws GenericSignatureFormatError if the generic + * signature of this generic declaration does not conform to + * the format specified in + * The Java™ Virtual Machine Specification + */ + public abstract TypeVariable[] getTypeParameters(); + + /** + * Returns an array of {@code Class} objects that represent the formal + * parameter types, in declaration order, of the executable + * represented by this object. Returns an array of length + * 0 if the underlying executable takes no parameters. + * + * @return the parameter types for the executable this object + * represents + */ + public abstract Class[] getParameterTypes(); + + /** + * Returns the number of formal parameters (whether explicitly + * declared or implicitly declared or neither) for the executable + * represented by this object. + * + * @since 1.8 + * @return The number of formal parameters for the executable this + * object represents + */ + public int getParameterCount() { + throw new AbstractMethodError(); + } + + /** + * Returns an array of {@code Type} objects that represent the formal + * parameter types, in declaration order, of the executable represented by + * this object. Returns an array of length 0 if the + * underlying executable takes no parameters. + * + *

If a formal parameter type is a parameterized type, + * the {@code Type} object returned for it must accurately reflect + * the actual type parameters used in the source code. + * + *

If a formal parameter type is a type variable or a parameterized + * type, it is created. Otherwise, it is resolved. + * + * @return an array of {@code Type}s that represent the formal + * parameter types of the underlying executable, in declaration order + * @throws GenericSignatureFormatError + * if the generic method signature does not conform to the format + * specified in + * The Java™ Virtual Machine Specification + * @throws TypeNotPresentException if any of the parameter + * types of the underlying executable refers to a non-existent type + * declaration + * @throws MalformedParameterizedTypeException if any of + * the underlying executable's parameter types refer to a parameterized + * type that cannot be instantiated for any reason + */ + public Type[] getGenericParameterTypes() { + if (hasGenericInformation()) + return getGenericInfo().getParameterTypes(); + else + return getParameterTypes(); + } + + /** + * Behaves like {@code getGenericParameterTypes}, but returns type + * information for all parameters, including synthetic parameters. + */ + Type[] getAllGenericParameterTypes() { + final boolean genericInfo = hasGenericInformation(); + + // Easy case: we don't have generic parameter information. In + // this case, we just return the result of + // getParameterTypes(). + if (!genericInfo) { + return getParameterTypes(); + } else { + final boolean realParamData = hasRealParameterData(); + final Type[] genericParamTypes = getGenericParameterTypes(); + final Type[] nonGenericParamTypes = getParameterTypes(); + final Type[] out = new Type[nonGenericParamTypes.length]; + final Parameter[] params = getParameters(); + int fromidx = 0; + // If we have real parameter data, then we use the + // synthetic and mandate flags to our advantage. + if (realParamData) { + for (int i = 0; i < out.length; i++) { + final Parameter param = params[i]; + if (param.isSynthetic() || param.isImplicit()) { + // If we hit a synthetic or mandated parameter, + // use the non generic parameter info. + out[i] = nonGenericParamTypes[i]; + } else { + // Otherwise, use the generic parameter info. + out[i] = genericParamTypes[fromidx]; + fromidx++; + } + } + } else { + // Otherwise, use the non-generic parameter data. + // Without method parameter reflection data, we have + // no way to figure out which parameters are + // synthetic/mandated, thus, no way to match up the + // indexes. + return genericParamTypes.length == nonGenericParamTypes.length ? + genericParamTypes : nonGenericParamTypes; + } + return out; + } + } + + /** + * Returns an array of {@code Parameter} objects that represent + * all the parameters to the underlying executable represented by + * this object. Returns an array of length 0 if the executable + * has no parameters. + * + *

The parameters of the underlying executable do not necessarily + * have unique names, or names that are legal identifiers in the + * Java programming language (JLS 3.8). + * + * @since 1.8 + * @throws MalformedParametersException if the class file contains + * a MethodParameters attribute that is improperly formatted. + * @return an array of {@code Parameter} objects representing all + * the parameters to the executable this object represents. + */ + public Parameter[] getParameters() { + // TODO: This may eventually need to be guarded by security + // mechanisms similar to those in Field, Method, etc. + // + // Need to copy the cached array to prevent users from messing + // with it. Since parameters are immutable, we can + // shallow-copy. + return privateGetParameters().clone(); + } + + private Parameter[] synthesizeAllParams() { + final int realparams = getParameterCount(); + final Parameter[] out = new Parameter[realparams]; + for (int i = 0; i < realparams; i++) + // TODO: is there a way to synthetically derive the + // modifiers? Probably not in the general case, since + // we'd have no way of knowing about them, but there + // may be specific cases. + out[i] = new Parameter("arg" + i, 0, this, i); + return out; + } + + private void verifyParameters(final Parameter[] parameters) { + final int mask = Modifier.FINAL | Modifier.SYNTHETIC | Modifier.MANDATED; + + if (getParameterTypes().length != parameters.length) + throw new MalformedParametersException("Wrong number of parameters in MethodParameters attribute"); + + for (Parameter parameter : parameters) { + final String name = parameter.getRealName(); + final int mods = parameter.getModifiers(); + + if (name != null) { + if (name.isEmpty() || name.indexOf('.') != -1 || + name.indexOf(';') != -1 || name.indexOf('[') != -1 || + name.indexOf('/') != -1) { + throw new MalformedParametersException("Invalid parameter name \"" + name + "\""); + } + } + + if (mods != (mods & mask)) { + throw new MalformedParametersException("Invalid parameter modifiers"); + } + } + } + + private Parameter[] privateGetParameters() { + // Use tmp to avoid multiple writes to a volatile. + Parameter[] tmp = parameters; + + if (tmp == null) { + + // Otherwise, go to the JVM to get them + try { + tmp = getParameters0(); + } catch(IllegalArgumentException e) { + // Rethrow ClassFormatErrors + throw new MalformedParametersException("Invalid constant pool index"); + } + + // If we get back nothing, then synthesize parameters + if (tmp == null) { + hasRealParameterData = false; + tmp = synthesizeAllParams(); + } else { + hasRealParameterData = true; + verifyParameters(tmp); + } + + parameters = tmp; + } + + return tmp; + } + + boolean hasRealParameterData() { + // If this somehow gets called before parameters gets + // initialized, force it into existence. + if (parameters == null) { + privateGetParameters(); + } + return hasRealParameterData; + } + + private transient volatile boolean hasRealParameterData; + private transient volatile Parameter[] parameters; + + private native Parameter[] getParameters0(); + native byte[] getTypeAnnotationBytes0(); + + // Needed by reflectaccess + byte[] getTypeAnnotationBytes() { + return getTypeAnnotationBytes0(); + } + + /** + * Returns an array of {@code Class} objects that represent the + * types of exceptions declared to be thrown by the underlying + * executable represented by this object. Returns an array of + * length 0 if the executable declares no exceptions in its {@code + * throws} clause. + * + * @return the exception types declared as being thrown by the + * executable this object represents + */ + public abstract Class[] getExceptionTypes(); + + /** + * Returns an array of {@code Type} objects that represent the + * exceptions declared to be thrown by this executable object. + * Returns an array of length 0 if the underlying executable declares + * no exceptions in its {@code throws} clause. + * + *

If an exception type is a type variable or a parameterized + * type, it is created. Otherwise, it is resolved. + * + * @return an array of Types that represent the exception types + * thrown by the underlying executable + * @throws GenericSignatureFormatError + * if the generic method signature does not conform to the format + * specified in + * The Java™ Virtual Machine Specification + * @throws TypeNotPresentException if the underlying executable's + * {@code throws} clause refers to a non-existent type declaration + * @throws MalformedParameterizedTypeException if + * the underlying executable's {@code throws} clause refers to a + * parameterized type that cannot be instantiated for any reason + */ + public Type[] getGenericExceptionTypes() { + Type[] result; + if (hasGenericInformation() && + ((result = getGenericInfo().getExceptionTypes()).length > 0)) + return result; + else + return getExceptionTypes(); + } + + /** + * Returns a string describing this {@code Executable}, including + * any type parameters. + * @return a string describing this {@code Executable}, including + * any type parameters + */ + public abstract String toGenericString(); + + /** + * Returns {@code true} if this executable was declared to take a + * variable number of arguments; returns {@code false} otherwise. + * + * @return {@code true} if an only if this executable was declared + * to take a variable number of arguments. + */ + public boolean isVarArgs() { + return (getModifiers() & Modifier.VARARGS) != 0; + } + + /** + * Returns {@code true} if this executable is a synthetic + * construct; returns {@code false} otherwise. + * + * @return true if and only if this executable is a synthetic + * construct as defined by + * The Java™ Language Specification. + * @jls 13.1 The Form of a Binary + */ + public boolean isSynthetic() { + return Modifier.isSynthetic(getModifiers()); + } + + /** + * Returns an array of arrays of {@code Annotation}s that + * represent the annotations on the formal parameters, in + * declaration order, of the {@code Executable} represented by + * this object. Synthetic and mandated parameters (see + * explanation below), such as the outer "this" parameter to an + * inner class constructor will be represented in the returned + * array. If the executable has no parameters (meaning no formal, + * no synthetic, and no mandated parameters), a zero-length array + * will be returned. If the {@code Executable} has one or more + * parameters, a nested array of length zero is returned for each + * parameter with no annotations. The annotation objects contained + * in the returned arrays are serializable. The caller of this + * method is free to modify the returned arrays; it will have no + * effect on the arrays returned to other callers. + * + * A compiler may add extra parameters that are implicitly + * declared in source ("mandated"), as well as parameters that + * are neither implicitly nor explicitly declared in source + * ("synthetic") to the parameter list for a method. See {@link + * java.lang.reflect.Parameter} for more information. + * + * @see java.lang.reflect.Parameter + * @see java.lang.reflect.Parameter#getAnnotations + * @return an array of arrays that represent the annotations on + * the formal and implicit parameters, in declaration order, of + * the executable represented by this object + */ + public abstract Annotation[][] getParameterAnnotations(); + + Annotation[][] sharedGetParameterAnnotations(Class[] parameterTypes) { + int numParameters = parameterTypes.length; + + Annotation[][] result = sharedGetParameterAnnotationsImpl(); + if (result == null) + return new Annotation[numParameters][0]; + + if (result.length != numParameters) + handleParameterNumberMismatch(result.length, numParameters); + return result; + } + + private native Annotation[][] sharedGetParameterAnnotationsImpl(); + + abstract void handleParameterNumberMismatch(int resultLength, int numParameters); + + /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + */ + public T getAnnotation(Class annotationClass) { + Objects.requireNonNull(annotationClass); + return annotationClass.cast(declaredAnnotations().get(annotationClass)); + } + + /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + @Override + public T[] getAnnotationsByType(Class annotationClass) { + Objects.requireNonNull(annotationClass); + + return AnnotationSupport.getDirectlyAndIndirectlyPresent(declaredAnnotations(), annotationClass); + } + + /** + * {@inheritDoc} + */ + public Annotation[] getDeclaredAnnotations() { + return AnnotationParser.toArray(declaredAnnotations()); + } + + private transient Map, Annotation> declaredAnnotations; + + private synchronized Map, Annotation> declaredAnnotations() { + if (declaredAnnotations == null) { + Executable root = getRoot(); + if (root != null) { + declaredAnnotations = root.declaredAnnotations(); + } else { + declaredAnnotations = declaredAnnotationsImpl(); + } + } + return declaredAnnotations; + } + + private native Map, Annotation> declaredAnnotationsImpl(); + + /** + * Returns an {@code AnnotatedType} object that represents the use of a type to + * specify the return type of the method/constructor represented by this + * Executable. + * + * If this {@code Executable} object represents a constructor, the {@code + * AnnotatedType} object represents the type of the constructed object. + * + * If this {@code Executable} object represents a method, the {@code + * AnnotatedType} object represents the use of a type to specify the return + * type of the method. + * + * @return an object representing the return type of the method + * or constructor represented by this {@code Executable} + * + * @since 1.8 + */ + public abstract AnnotatedType getAnnotatedReturnType(); + + /* Helper for subclasses of Executable. + * + * Returns an AnnotatedType object that represents the use of a type to + * specify the return type of the method/constructor represented by this + * Executable. + * + * @since 1.8 + */ + AnnotatedType getAnnotatedReturnType0(Type returnType) { + return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(), + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + returnType, + TypeAnnotation.TypeAnnotationTarget.METHOD_RETURN); + } + + /** + * Returns an {@code AnnotatedType} object that represents the use of a + * type to specify the receiver type of the method/constructor represented + * by this Executable object. The receiver type of a method/constructor is + * available only if the method/constructor has a receiver + * parameter (JLS 8.4.1). + * + * If this {@code Executable} object represents a constructor or instance + * method that does not have a receiver parameter, or has a receiver + * parameter with no annotations on its type, then the return value is an + * {@code AnnotatedType} object representing an element with no + * annotations. + * + * If this {@code Executable} object represents a static method, then the + * return value is null. + * + * @return an object representing the receiver type of the method or + * constructor represented by this {@code Executable} + * + * @since 1.8 + */ + public AnnotatedType getAnnotatedReceiverType() { + if (Modifier.isStatic(this.getModifiers())) + return null; + return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(), + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + getDeclaringClass(), + TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER); + } + + /** + * Returns an array of {@code AnnotatedType} objects that represent the use + * of types to specify formal parameter types of the method/constructor + * represented by this Executable. The order of the objects in the array + * corresponds to the order of the formal parameter types in the + * declaration of the method/constructor. + * + * Returns an array of length 0 if the method/constructor declares no + * parameters. + * + * @return an array of objects representing the types of the + * formal parameters of the method or constructor represented by this + * {@code Executable} + * + * @since 1.8 + */ + public AnnotatedType[] getAnnotatedParameterTypes() { + return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes0(), + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + getAllGenericParameterTypes(), + TypeAnnotation.TypeAnnotationTarget.METHOD_FORMAL_PARAMETER); + } + + /** + * Returns an array of {@code AnnotatedType} objects that represent the use + * of types to specify the declared exceptions of the method/constructor + * represented by this Executable. The order of the objects in the array + * corresponds to the order of the exception types in the declaration of + * the method/constructor. + * + * Returns an array of length 0 if the method/constructor declares no + * exceptions. + * + * @return an array of objects representing the declared + * exceptions of the method or constructor represented by this {@code + * Executable} + * + * @since 1.8 + */ + public AnnotatedType[] getAnnotatedExceptionTypes() { + return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes0(), + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + getGenericExceptionTypes(), + TypeAnnotation.TypeAnnotationTarget.THROWS); + } + +} diff --git a/openjdk/java/lang/reflect/Field.java b/openjdk/java/lang/reflect/Field.java new file mode 100644 index 0000000..a683e59 --- /dev/null +++ b/openjdk/java/lang/reflect/Field.java @@ -0,0 +1,1174 @@ +/* + * Copyright (c) 1996, 2013, 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 java.lang.reflect; + +import sun.reflect.CallerSensitive; +import sun.reflect.FieldAccessor; +import sun.reflect.Reflection; +import sun.reflect.generics.repository.FieldRepository; +import sun.reflect.generics.factory.CoreReflectionFactory; +import sun.reflect.generics.factory.GenericsFactory; +import sun.reflect.generics.scope.ClassScope; +import java.lang.annotation.Annotation; +import java.util.Map; +import java.util.Objects; +import sun.reflect.annotation.AnnotationParser; +import sun.reflect.annotation.AnnotationSupport; +import sun.reflect.annotation.TypeAnnotation; +import sun.reflect.annotation.TypeAnnotationParser; + +/** + * A {@code Field} provides information about, and dynamic access to, a + * single field of a class or an interface. The reflected field may + * be a class (static) field or an instance field. + * + *

A {@code Field} permits widening conversions to occur during a get or + * set access operation, but throws an {@code IllegalArgumentException} if a + * narrowing conversion would occur. + * + * @see Member + * @see java.lang.Class + * @see java.lang.Class#getFields() + * @see java.lang.Class#getField(String) + * @see java.lang.Class#getDeclaredFields() + * @see java.lang.Class#getDeclaredField(String) + * + * @author Kenneth Russell + * @author Nakul Saraiya + */ +public final +class Field extends AccessibleObject implements Member { + + private Class clazz; + private int slot; + // This is guaranteed to be interned by the VM in the 1.4 + // reflection implementation + private String name; + private Class type; + private int modifiers; + // Generics and annotations support + private transient String signature; + // generic info repository; lazily initialized + private transient FieldRepository genericInfo; + // Cached field accessor created without override + private FieldAccessor fieldAccessor; + // Cached field accessor created with override + private FieldAccessor overrideFieldAccessor; + // For sharing of FieldAccessors. This branching structure is + // currently only two levels deep (i.e., one root Field and + // potentially many Field objects pointing to it.) + // + // If this branching structure would ever contain cycles, deadlocks can + // occur in annotation code. + private Field root; + + // Generics infrastructure + + private String getGenericSignature() {return signature;} + + // Accessor for factory + private GenericsFactory getFactory() { + Class c = getDeclaringClass(); + // create scope and factory + return CoreReflectionFactory.make(c, ClassScope.make(c)); + } + + // Accessor for generic info repository + private FieldRepository getGenericInfo() { + // lazily initialize repository if necessary + if (genericInfo == null) { + // create and cache generic info repository + genericInfo = FieldRepository.make(getGenericSignature(), + getFactory()); + } + return genericInfo; //return cached repository + } + + + /** + * Package-private constructor used by ReflectAccess to enable + * instantiation of these objects in Java code from the java.lang + * package via sun.reflect.LangReflectAccess. + */ + Field(Class declaringClass, + String name, + Class type, + int modifiers, + int slot, + String signature, + byte[] unused) + { + this.clazz = declaringClass; + this.name = name; + this.type = type; + this.modifiers = modifiers; + this.slot = slot; + this.signature = signature; + } + + /** + * Package-private routine (exposed to java.lang.Class via + * ReflectAccess) which returns a copy of this Field. The copy's + * "root" field points to this Field. + */ + Field copy() { + // This routine enables sharing of FieldAccessor objects + // among Field objects which refer to the same underlying + // method in the VM. (All of this contortion is only necessary + // because of the "accessibility" bit in AccessibleObject, + // which implicitly requires that new java.lang.reflect + // objects be fabricated for each reflective call on Class + // objects.) + if (this.root != null) + throw new IllegalArgumentException("Can not copy a non-root Field"); + + Field res = new Field(clazz, name, type, modifiers, slot, signature, null); + res.root = this; + // Might as well eagerly propagate this if already present + res.fieldAccessor = fieldAccessor; + res.overrideFieldAccessor = overrideFieldAccessor; + + return res; + } + + /** + * Returns the {@code Class} object representing the class or interface + * that declares the field represented by this {@code Field} object. + */ + public Class getDeclaringClass() { + return clazz; + } + + /** + * Returns the name of the field represented by this {@code Field} object. + */ + public String getName() { + return name; + } + + /** + * Returns the Java language modifiers for the field represented + * by this {@code Field} object, as an integer. The {@code Modifier} class should + * be used to decode the modifiers. + * + * @see Modifier + */ + public int getModifiers() { + return modifiers; + } + + /** + * Returns {@code true} if this field represents an element of + * an enumerated type; returns {@code false} otherwise. + * + * @return {@code true} if and only if this field represents an element of + * an enumerated type. + * @since 1.5 + */ + public boolean isEnumConstant() { + return (getModifiers() & Modifier.ENUM) != 0; + } + + /** + * Returns {@code true} if this field is a synthetic + * field; returns {@code false} otherwise. + * + * @return true if and only if this field is a synthetic + * field as defined by the Java Language Specification. + * @since 1.5 + */ + public boolean isSynthetic() { + return Modifier.isSynthetic(getModifiers()); + } + + /** + * Returns a {@code Class} object that identifies the + * declared type for the field represented by this + * {@code Field} object. + * + * @return a {@code Class} object identifying the declared + * type of the field represented by this object + */ + public Class getType() { + return type; + } + + /** + * Returns a {@code Type} object that represents the declared type for + * the field represented by this {@code Field} object. + * + *

If the {@code Type} is a parameterized type, the + * {@code Type} object returned must accurately reflect the + * actual type parameters used in the source code. + * + *

If the type of the underlying field is a type variable or a + * parameterized type, it is created. Otherwise, it is resolved. + * + * @return a {@code Type} object that represents the declared type for + * the field represented by this {@code Field} object + * @throws GenericSignatureFormatError if the generic field + * signature does not conform to the format specified in + * The Java™ Virtual Machine Specification + * @throws TypeNotPresentException if the generic type + * signature of the underlying field refers to a non-existent + * type declaration + * @throws MalformedParameterizedTypeException if the generic + * signature of the underlying field refers to a parameterized type + * that cannot be instantiated for any reason + * @since 1.5 + */ + public Type getGenericType() { + if (getGenericSignature() != null) + return getGenericInfo().getGenericType(); + else + return getType(); + } + + + /** + * Compares this {@code Field} against the specified object. Returns + * true if the objects are the same. Two {@code Field} objects are the same if + * they were declared by the same class and have the same name + * and type. + */ + public boolean equals(Object obj) { + if (obj != null && obj instanceof Field) { + Field other = (Field)obj; + return (getDeclaringClass() == other.getDeclaringClass()) + && (getName() == other.getName()) + && (getType() == other.getType()); + } + return false; + } + + /** + * Returns a hashcode for this {@code Field}. This is computed as the + * exclusive-or of the hashcodes for the underlying field's + * declaring class name and its name. + */ + public int hashCode() { + return getDeclaringClass().getName().hashCode() ^ getName().hashCode(); + } + + /** + * Returns a string describing this {@code Field}. The format is + * the access modifiers for the field, if any, followed + * by the field type, followed by a space, followed by + * the fully-qualified name of the class declaring the field, + * followed by a period, followed by the name of the field. + * For example: + *

+     *    public static final int java.lang.Thread.MIN_PRIORITY
+     *    private int java.io.FileDescriptor.fd
+     * 
+ * + *

The modifiers are placed in canonical order as specified by + * "The Java Language Specification". This is {@code public}, + * {@code protected} or {@code private} first, and then other + * modifiers in the following order: {@code static}, {@code final}, + * {@code transient}, {@code volatile}. + * + * @return a string describing this {@code Field} + * @jls 8.3.1 Field Modifiers + */ + public String toString() { + int mod = getModifiers(); + return (((mod == 0) ? "" : (Modifier.toString(mod) + " ")) + + getType().getTypeName() + " " + + getDeclaringClass().getTypeName() + "." + + getName()); + } + + /** + * Returns a string describing this {@code Field}, including + * its generic type. The format is the access modifiers for the + * field, if any, followed by the generic field type, followed by + * a space, followed by the fully-qualified name of the class + * declaring the field, followed by a period, followed by the name + * of the field. + * + *

The modifiers are placed in canonical order as specified by + * "The Java Language Specification". This is {@code public}, + * {@code protected} or {@code private} first, and then other + * modifiers in the following order: {@code static}, {@code final}, + * {@code transient}, {@code volatile}. + * + * @return a string describing this {@code Field}, including + * its generic type + * + * @since 1.5 + * @jls 8.3.1 Field Modifiers + */ + public String toGenericString() { + int mod = getModifiers(); + Type fieldType = getGenericType(); + return (((mod == 0) ? "" : (Modifier.toString(mod) + " ")) + + fieldType.getTypeName() + " " + + getDeclaringClass().getTypeName() + "." + + getName()); + } + + /** + * Returns the value of the field represented by this {@code Field}, on + * the specified object. The value is automatically wrapped in an + * object if it has a primitive type. + * + *

The underlying field's value is obtained as follows: + * + *

If the underlying field is a static field, the {@code obj} argument + * is ignored; it may be null. + * + *

Otherwise, the underlying field is an instance field. If the + * specified {@code obj} argument is null, the method throws a + * {@code NullPointerException}. If the specified object is not an + * instance of the class or interface declaring the underlying + * field, the method throws an {@code IllegalArgumentException}. + * + *

If this {@code Field} object is enforcing Java language access control, and + * the underlying field is inaccessible, the method throws an + * {@code IllegalAccessException}. + * If the underlying field is static, the class that declared the + * field is initialized if it has not already been initialized. + * + *

Otherwise, the value is retrieved from the underlying instance + * or static field. If the field has a primitive type, the value + * is wrapped in an object before being returned, otherwise it is + * returned as is. + * + *

If the field is hidden in the type of {@code obj}, + * the field's value is obtained according to the preceding rules. + * + * @param obj object from which the represented field's value is + * to be extracted + * @return the value of the represented field in object + * {@code obj}; primitive values are wrapped in an appropriate + * object before being returned + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof). + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + */ + @CallerSensitive + public Object get(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } + return getFieldAccessor(obj).get(obj); + } + + /** + * Gets the value of a static or instance {@code boolean} field. + * + * @param obj the object to extract the {@code boolean} value + * from + * @return the value of the {@code boolean} field + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code boolean} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + @CallerSensitive + public boolean getBoolean(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } + return getFieldAccessor(obj).getBoolean(obj); + } + + /** + * Gets the value of a static or instance {@code byte} field. + * + * @param obj the object to extract the {@code byte} value + * from + * @return the value of the {@code byte} field + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code byte} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + @CallerSensitive + public byte getByte(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } + return getFieldAccessor(obj).getByte(obj); + } + + /** + * Gets the value of a static or instance field of type + * {@code char} or of another primitive type convertible to + * type {@code char} via a widening conversion. + * + * @param obj the object to extract the {@code char} value + * from + * @return the value of the field converted to type {@code char} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code char} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + @CallerSensitive + public char getChar(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } + return getFieldAccessor(obj).getChar(obj); + } + + /** + * Gets the value of a static or instance field of type + * {@code short} or of another primitive type convertible to + * type {@code short} via a widening conversion. + * + * @param obj the object to extract the {@code short} value + * from + * @return the value of the field converted to type {@code short} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code short} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + @CallerSensitive + public short getShort(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } + return getFieldAccessor(obj).getShort(obj); + } + + /** + * Gets the value of a static or instance field of type + * {@code int} or of another primitive type convertible to + * type {@code int} via a widening conversion. + * + * @param obj the object to extract the {@code int} value + * from + * @return the value of the field converted to type {@code int} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code int} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + @CallerSensitive + public int getInt(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } + return getFieldAccessor(obj).getInt(obj); + } + + /** + * Gets the value of a static or instance field of type + * {@code long} or of another primitive type convertible to + * type {@code long} via a widening conversion. + * + * @param obj the object to extract the {@code long} value + * from + * @return the value of the field converted to type {@code long} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code long} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + @CallerSensitive + public long getLong(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } + return getFieldAccessor(obj).getLong(obj); + } + + /** + * Gets the value of a static or instance field of type + * {@code float} or of another primitive type convertible to + * type {@code float} via a widening conversion. + * + * @param obj the object to extract the {@code float} value + * from + * @return the value of the field converted to type {@code float} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code float} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + @CallerSensitive + public float getFloat(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } + return getFieldAccessor(obj).getFloat(obj); + } + + /** + * Gets the value of a static or instance field of type + * {@code double} or of another primitive type convertible to + * type {@code double} via a widening conversion. + * + * @param obj the object to extract the {@code double} value + * from + * @return the value of the field converted to type {@code double} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code double} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + @CallerSensitive + public double getDouble(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } + return getFieldAccessor(obj).getDouble(obj); + } + + /** + * Sets the field represented by this {@code Field} object on the + * specified object argument to the specified new value. The new + * value is automatically unwrapped if the underlying field has a + * primitive type. + * + *

The operation proceeds as follows: + * + *

If the underlying field is static, the {@code obj} argument is + * ignored; it may be null. + * + *

Otherwise the underlying field is an instance field. If the + * specified object argument is null, the method throws a + * {@code NullPointerException}. If the specified object argument is not + * an instance of the class or interface declaring the underlying + * field, the method throws an {@code IllegalArgumentException}. + * + *

If this {@code Field} object is enforcing Java language access control, and + * the underlying field is inaccessible, the method throws an + * {@code IllegalAccessException}. + * + *

If the underlying field is final, the method throws an + * {@code IllegalAccessException} unless {@code setAccessible(true)} + * has succeeded for this {@code Field} object + * and the field is non-static. Setting a final field in this way + * is meaningful only during deserialization or reconstruction of + * instances of classes with blank final fields, before they are + * made available for access by other parts of a program. Use in + * any other context may have unpredictable effects, including cases + * in which other parts of a program continue to use the original + * value of this field. + * + *

If the underlying field is of a primitive type, an unwrapping + * conversion is attempted to convert the new value to a value of + * a primitive type. If this attempt fails, the method throws an + * {@code IllegalArgumentException}. + * + *

If, after possible unwrapping, the new value cannot be + * converted to the type of the underlying field by an identity or + * widening conversion, the method throws an + * {@code IllegalArgumentException}. + * + *

If the underlying field is static, the class that declared the + * field is initialized if it has not already been initialized. + * + *

The field is set to the possibly unwrapped and widened new value. + * + *

If the field is hidden in the type of {@code obj}, + * the field's value is set according to the preceding rules. + * + * @param obj the object whose field should be modified + * @param value the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + */ + @CallerSensitive + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } + getFieldAccessor(obj).set(obj, value); + } + + /** + * Sets the value of a field as a {@code boolean} on the specified object. + * This method is equivalent to + * {@code set(obj, zObj)}, + * where {@code zObj} is a {@code Boolean} object and + * {@code zObj.booleanValue() == z}. + * + * @param obj the object whose field should be modified + * @param z the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + @CallerSensitive + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } + getFieldAccessor(obj).setBoolean(obj, z); + } + + /** + * Sets the value of a field as a {@code byte} on the specified object. + * This method is equivalent to + * {@code set(obj, bObj)}, + * where {@code bObj} is a {@code Byte} object and + * {@code bObj.byteValue() == b}. + * + * @param obj the object whose field should be modified + * @param b the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + @CallerSensitive + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } + getFieldAccessor(obj).setByte(obj, b); + } + + /** + * Sets the value of a field as a {@code char} on the specified object. + * This method is equivalent to + * {@code set(obj, cObj)}, + * where {@code cObj} is a {@code Character} object and + * {@code cObj.charValue() == c}. + * + * @param obj the object whose field should be modified + * @param c the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + @CallerSensitive + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } + getFieldAccessor(obj).setChar(obj, c); + } + + /** + * Sets the value of a field as a {@code short} on the specified object. + * This method is equivalent to + * {@code set(obj, sObj)}, + * where {@code sObj} is a {@code Short} object and + * {@code sObj.shortValue() == s}. + * + * @param obj the object whose field should be modified + * @param s the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + @CallerSensitive + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } + getFieldAccessor(obj).setShort(obj, s); + } + + /** + * Sets the value of a field as an {@code int} on the specified object. + * This method is equivalent to + * {@code set(obj, iObj)}, + * where {@code iObj} is a {@code Integer} object and + * {@code iObj.intValue() == i}. + * + * @param obj the object whose field should be modified + * @param i the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + @CallerSensitive + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } + getFieldAccessor(obj).setInt(obj, i); + } + + /** + * Sets the value of a field as a {@code long} on the specified object. + * This method is equivalent to + * {@code set(obj, lObj)}, + * where {@code lObj} is a {@code Long} object and + * {@code lObj.longValue() == l}. + * + * @param obj the object whose field should be modified + * @param l the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + @CallerSensitive + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } + getFieldAccessor(obj).setLong(obj, l); + } + + /** + * Sets the value of a field as a {@code float} on the specified object. + * This method is equivalent to + * {@code set(obj, fObj)}, + * where {@code fObj} is a {@code Float} object and + * {@code fObj.floatValue() == f}. + * + * @param obj the object whose field should be modified + * @param f the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + @CallerSensitive + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } + getFieldAccessor(obj).setFloat(obj, f); + } + + /** + * Sets the value of a field as a {@code double} on the specified object. + * This method is equivalent to + * {@code set(obj, dObj)}, + * where {@code dObj} is a {@code Double} object and + * {@code dObj.doubleValue() == d}. + * + * @param obj the object whose field should be modified + * @param d the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + @CallerSensitive + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } + getFieldAccessor(obj).setDouble(obj, d); + } + + // security check is done before calling this method + private FieldAccessor getFieldAccessor(Object obj) + throws IllegalAccessException + { + boolean ov = override; + FieldAccessor a = (ov) ? overrideFieldAccessor : fieldAccessor; + return (a != null) ? a : acquireFieldAccessor(ov); + } + + // NOTE that there is no synchronization used here. It is correct + // (though not efficient) to generate more than one FieldAccessor + // for a given Field. However, avoiding synchronization will + // probably make the implementation more scalable. + private FieldAccessor acquireFieldAccessor(boolean overrideFinalCheck) { + // First check to see if one has been created yet, and take it + // if so + FieldAccessor tmp = null; + if (root != null) tmp = root.getFieldAccessor(overrideFinalCheck); + if (tmp != null) { + if (overrideFinalCheck) + overrideFieldAccessor = tmp; + else + fieldAccessor = tmp; + } else { + // Otherwise fabricate one and propagate it up to the root + tmp = reflectionFactory.newFieldAccessor(this, overrideFinalCheck); + setFieldAccessor(tmp, overrideFinalCheck); + } + + return tmp; + } + + // Returns FieldAccessor for this Field object, not looking up + // the chain to the root + private FieldAccessor getFieldAccessor(boolean overrideFinalCheck) { + return (overrideFinalCheck)? overrideFieldAccessor : fieldAccessor; + } + + // Sets the FieldAccessor for this Field object and + // (recursively) its root + private void setFieldAccessor(FieldAccessor accessor, boolean overrideFinalCheck) { + if (overrideFinalCheck) + overrideFieldAccessor = accessor; + else + fieldAccessor = accessor; + // Propagate up + if (root != null) { + root.setFieldAccessor(accessor, overrideFinalCheck); + } + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + public T getAnnotation(Class annotationClass) { + Objects.requireNonNull(annotationClass); + return annotationClass.cast(declaredAnnotations().get(annotationClass)); + } + + /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + @Override + public T[] getAnnotationsByType(Class annotationClass) { + Objects.requireNonNull(annotationClass); + + return AnnotationSupport.getDirectlyAndIndirectlyPresent(declaredAnnotations(), annotationClass); + } + + /** + * {@inheritDoc} + */ + public Annotation[] getDeclaredAnnotations() { + return AnnotationParser.toArray(declaredAnnotations()); + } + + private transient Map, Annotation> declaredAnnotations; + + private synchronized Map, Annotation> declaredAnnotations() { + if (declaredAnnotations == null) { + Field root = this.root; + if (root != null) { + declaredAnnotations = root.declaredAnnotations(); + } else { + declaredAnnotations = getDeclaredAnnotationsImpl(); + } + } + return declaredAnnotations; + } + + private native Map, Annotation> getDeclaredAnnotationsImpl(); + private native byte[] getTypeAnnotationBytes0(); + + /** + * Returns an AnnotatedType object that represents the use of a type to specify + * the declared type of the field represented by this Field. + * @return an object representing the declared type of the field + * represented by this Field + * + * @since 1.8 + */ + public AnnotatedType getAnnotatedType() { + return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(), + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + getGenericType(), + TypeAnnotation.TypeAnnotationTarget.FIELD); +} +} diff --git a/openjdk/java/lang/reflect/Method.java b/openjdk/java/lang/reflect/Method.java new file mode 100644 index 0000000..c8705ba --- /dev/null +++ b/openjdk/java/lang/reflect/Method.java @@ -0,0 +1,630 @@ +/* + * Copyright (c) 1996, 2013, 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 java.lang.reflect; + +import sun.reflect.CallerSensitive; +import sun.reflect.MethodAccessor; +import sun.reflect.Reflection; +import sun.reflect.generics.repository.MethodRepository; +import sun.reflect.generics.factory.CoreReflectionFactory; +import sun.reflect.generics.factory.GenericsFactory; +import sun.reflect.generics.scope.MethodScope; +import sun.reflect.annotation.AnnotationType; +import sun.reflect.annotation.AnnotationParser; +import java.lang.annotation.Annotation; +import java.lang.annotation.AnnotationFormatError; +import java.nio.ByteBuffer; + +/** + * A {@code Method} provides information about, and access to, a single method + * on a class or interface. The reflected method may be a class method + * or an instance method (including an abstract method). + * + *

A {@code Method} permits widening conversions to occur when matching the + * actual parameters to invoke with the underlying method's formal + * parameters, but it throws an {@code IllegalArgumentException} if a + * narrowing conversion would occur. + * + * @see Member + * @see java.lang.Class + * @see java.lang.Class#getMethods() + * @see java.lang.Class#getMethod(String, Class[]) + * @see java.lang.Class#getDeclaredMethods() + * @see java.lang.Class#getDeclaredMethod(String, Class[]) + * + * @author Kenneth Russell + * @author Nakul Saraiya + */ +public final class Method extends Executable { + private Class clazz; + private int slot; + // This is guaranteed to be interned by the VM in the 1.4 + // reflection implementation + private String name; + private Class returnType; + private Class[] parameterTypes; + private Class[] exceptionTypes; + private int modifiers; + // Generics and annotations support + private transient String signature; + // generic info repository; lazily initialized + private transient MethodRepository genericInfo; + private volatile MethodAccessor methodAccessor; + // For sharing of MethodAccessors. This branching structure is + // currently only two levels deep (i.e., one root Method and + // potentially many Method objects pointing to it.) + // + // If this branching structure would ever contain cycles, deadlocks can + // occur in annotation code. + private Method root; + + // Generics infrastructure + private String getGenericSignature() {return signature;} + + // Accessor for factory + private GenericsFactory getFactory() { + // create scope and factory + return CoreReflectionFactory.make(this, MethodScope.make(this)); + } + + // Accessor for generic info repository + @Override + MethodRepository getGenericInfo() { + // lazily initialize repository if necessary + if (genericInfo == null) { + // create and cache generic info repository + genericInfo = MethodRepository.make(getGenericSignature(), + getFactory()); + } + return genericInfo; //return cached repository + } + + /** + * Package-private constructor used by ReflectAccess to enable + * instantiation of these objects in Java code from the java.lang + * package via sun.reflect.LangReflectAccess. + */ + Method(Class declaringClass, + String name, + Class[] parameterTypes, + Class returnType, + Class[] checkedExceptions, + int modifiers, + int slot, + String signature, + byte[] unused1, + byte[] unused2, + byte[] unused3) { + this.clazz = declaringClass; + this.name = name; + this.parameterTypes = parameterTypes; + this.returnType = returnType; + this.exceptionTypes = checkedExceptions; + this.modifiers = modifiers; + this.slot = slot; + this.signature = signature; + } + + /** + * Package-private routine (exposed to java.lang.Class via + * ReflectAccess) which returns a copy of this Method. The copy's + * "root" field points to this Method. + */ + Method copy() { + // This routine enables sharing of MethodAccessor objects + // among Method objects which refer to the same underlying + // method in the VM. (All of this contortion is only necessary + // because of the "accessibility" bit in AccessibleObject, + // which implicitly requires that new java.lang.reflect + // objects be fabricated for each reflective call on Class + // objects.) + if (this.root != null) + throw new IllegalArgumentException("Can not copy a non-root Method"); + + Method res = new Method(clazz, name, parameterTypes, returnType, + exceptionTypes, modifiers, slot, signature, + null, null, null); + res.root = this; + // Might as well eagerly propagate this if already present + res.methodAccessor = methodAccessor; + return res; + } + + /** + * Used by Excecutable for annotation sharing. + */ + @Override + Executable getRoot() { + return root; + } + + @Override + boolean hasGenericInformation() { + return (getGenericSignature() != null); + } + + /** + * {@inheritDoc} + */ + @Override + public Class getDeclaringClass() { + return clazz; + } + + /** + * Returns the name of the method represented by this {@code Method} + * object, as a {@code String}. + */ + @Override + public String getName() { + return name; + } + + /** + * {@inheritDoc} + */ + @Override + public int getModifiers() { + return modifiers; + } + + /** + * {@inheritDoc} + * @throws GenericSignatureFormatError {@inheritDoc} + * @since 1.5 + */ + @Override + @SuppressWarnings({"rawtypes", "unchecked"}) + public TypeVariable[] getTypeParameters() { + if (getGenericSignature() != null) + return (TypeVariable[])getGenericInfo().getTypeParameters(); + else + return (TypeVariable[])new TypeVariable[0]; + } + + /** + * Returns a {@code Class} object that represents the formal return type + * of the method represented by this {@code Method} object. + * + * @return the return type for the method this object represents + */ + public Class getReturnType() { + return returnType; + } + + /** + * Returns a {@code Type} object that represents the formal return + * type of the method represented by this {@code Method} object. + * + *

If the return type is a parameterized type, + * the {@code Type} object returned must accurately reflect + * the actual type parameters used in the source code. + * + *

If the return type is a type variable or a parameterized type, it + * is created. Otherwise, it is resolved. + * + * @return a {@code Type} object that represents the formal return + * type of the underlying method + * @throws GenericSignatureFormatError + * if the generic method signature does not conform to the format + * specified in + * The Java™ Virtual Machine Specification + * @throws TypeNotPresentException if the underlying method's + * return type refers to a non-existent type declaration + * @throws MalformedParameterizedTypeException if the + * underlying method's return typed refers to a parameterized + * type that cannot be instantiated for any reason + * @since 1.5 + */ + public Type getGenericReturnType() { + if (getGenericSignature() != null) { + return getGenericInfo().getReturnType(); + } else { return getReturnType();} + } + + /** + * {@inheritDoc} + */ + @Override + public Class[] getParameterTypes() { + return parameterTypes.clone(); + } + + /** + * {@inheritDoc} + */ + public int getParameterCount() { return parameterTypes.length; } + + + /** + * {@inheritDoc} + * @throws GenericSignatureFormatError {@inheritDoc} + * @throws TypeNotPresentException {@inheritDoc} + * @throws MalformedParameterizedTypeException {@inheritDoc} + * @since 1.5 + */ + @Override + public Type[] getGenericParameterTypes() { + return super.getGenericParameterTypes(); + } + + /** + * {@inheritDoc} + */ + @Override + public Class[] getExceptionTypes() { + return exceptionTypes.clone(); + } + + /** + * {@inheritDoc} + * @throws GenericSignatureFormatError {@inheritDoc} + * @throws TypeNotPresentException {@inheritDoc} + * @throws MalformedParameterizedTypeException {@inheritDoc} + * @since 1.5 + */ + @Override + public Type[] getGenericExceptionTypes() { + return super.getGenericExceptionTypes(); + } + + /** + * Compares this {@code Method} against the specified object. Returns + * true if the objects are the same. Two {@code Methods} are the same if + * they were declared by the same class and have the same name + * and formal parameter types and return type. + */ + public boolean equals(Object obj) { + if (obj != null && obj instanceof Method) { + Method other = (Method)obj; + if ((getDeclaringClass() == other.getDeclaringClass()) + && (getName() == other.getName())) { + if (!returnType.equals(other.getReturnType())) + return false; + return equalParamTypes(parameterTypes, other.parameterTypes); + } + } + return false; + } + + /** + * Returns a hashcode for this {@code Method}. The hashcode is computed + * as the exclusive-or of the hashcodes for the underlying + * method's declaring class name and the method's name. + */ + public int hashCode() { + return getDeclaringClass().getName().hashCode() ^ getName().hashCode(); + } + + /** + * Returns a string describing this {@code Method}. The string is + * formatted as the method access modifiers, if any, followed by + * the method return type, followed by a space, followed by the + * class declaring the method, followed by a period, followed by + * the method name, followed by a parenthesized, comma-separated + * list of the method's formal parameter types. If the method + * throws checked exceptions, the parameter list is followed by a + * space, followed by the word throws followed by a + * comma-separated list of the thrown exception types. + * For example: + *

+     *    public boolean java.lang.Object.equals(java.lang.Object)
+     * 
+ * + *

The access modifiers are placed in canonical order as + * specified by "The Java Language Specification". This is + * {@code public}, {@code protected} or {@code private} first, + * and then other modifiers in the following order: + * {@code abstract}, {@code default}, {@code static}, {@code final}, + * {@code synchronized}, {@code native}, {@code strictfp}. + * + * @return a string describing this {@code Method} + * + * @jls 8.4.3 Method Modifiers + */ + public String toString() { + return sharedToString(Modifier.methodModifiers(), + isDefault(), + parameterTypes, + exceptionTypes); + } + + @Override + void specificToStringHeader(StringBuilder sb) { + sb.append(getReturnType().getTypeName()).append(' '); + sb.append(getDeclaringClass().getTypeName()).append('.'); + sb.append(getName()); + } + + /** + * Returns a string describing this {@code Method}, including + * type parameters. The string is formatted as the method access + * modifiers, if any, followed by an angle-bracketed + * comma-separated list of the method's type parameters, if any, + * followed by the method's generic return type, followed by a + * space, followed by the class declaring the method, followed by + * a period, followed by the method name, followed by a + * parenthesized, comma-separated list of the method's generic + * formal parameter types. + * + * If this method was declared to take a variable number of + * arguments, instead of denoting the last parameter as + * "Type[]", it is denoted as + * "Type...". + * + * A space is used to separate access modifiers from one another + * and from the type parameters or return type. If there are no + * type parameters, the type parameter list is elided; if the type + * parameter list is present, a space separates the list from the + * class name. If the method is declared to throw exceptions, the + * parameter list is followed by a space, followed by the word + * throws followed by a comma-separated list of the generic thrown + * exception types. + * + *

The access modifiers are placed in canonical order as + * specified by "The Java Language Specification". This is + * {@code public}, {@code protected} or {@code private} first, + * and then other modifiers in the following order: + * {@code abstract}, {@code default}, {@code static}, {@code final}, + * {@code synchronized}, {@code native}, {@code strictfp}. + * + * @return a string describing this {@code Method}, + * include type parameters + * + * @since 1.5 + * + * @jls 8.4.3 Method Modifiers + */ + @Override + public String toGenericString() { + return sharedToGenericString(Modifier.methodModifiers(), isDefault()); + } + + @Override + void specificToGenericStringHeader(StringBuilder sb) { + Type genRetType = getGenericReturnType(); + sb.append(genRetType.getTypeName()).append(' '); + sb.append(getDeclaringClass().getTypeName()).append('.'); + sb.append(getName()); + } + + /** + * Invokes the underlying method represented by this {@code Method} + * object, on the specified object with the specified parameters. + * Individual parameters are automatically unwrapped to match + * primitive formal parameters, and both primitive and reference + * parameters are subject to method invocation conversions as + * necessary. + * + *

If the underlying method is static, then the specified {@code obj} + * argument is ignored. It may be null. + * + *

If the number of formal parameters required by the underlying method is + * 0, the supplied {@code args} array may be of length 0 or null. + * + *

If the underlying method is an instance method, it is invoked + * using dynamic method lookup as documented in The Java Language + * Specification, Second Edition, section 15.12.4.4; in particular, + * overriding based on the runtime type of the target object will occur. + * + *

If the underlying method is static, the class that declared + * the method is initialized if it has not already been initialized. + * + *

If the method completes normally, the value it returns is + * returned to the caller of invoke; if the value has a primitive + * type, it is first appropriately wrapped in an object. However, + * if the value has the type of an array of a primitive type, the + * elements of the array are not wrapped in objects; in + * other words, an array of primitive type is returned. If the + * underlying method return type is void, the invocation returns + * null. + * + * @param obj the object the underlying method is invoked from + * @param args the arguments used for the method call + * @return the result of dispatching the method represented by + * this object on {@code obj} with parameters + * {@code args} + * + * @exception IllegalAccessException if this {@code Method} object + * is enforcing Java language access control and the underlying + * method is inaccessible. + * @exception IllegalArgumentException if the method is an + * instance method and the specified object argument + * is not an instance of the class or interface + * declaring the underlying method (or of a subclass + * or implementor thereof); if the number of actual + * and formal parameters differ; if an unwrapping + * conversion for primitive arguments fails; or if, + * after possible unwrapping, a parameter value + * cannot be converted to the corresponding formal + * parameter type by a method invocation conversion. + * @exception InvocationTargetException if the underlying method + * throws an exception. + * @exception NullPointerException if the specified object is null + * and the method is an instance method. + * @exception ExceptionInInitializerError if the initialization + * provoked by this method fails. + */ + @CallerSensitive + public Object invoke(Object obj, Object... args) + throws IllegalAccessException, IllegalArgumentException, + InvocationTargetException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } + MethodAccessor ma = methodAccessor; // read volatile + if (ma == null) { + ma = acquireMethodAccessor(); + } + return ma.invoke(obj, args, ikvm.internal.CallerID.getCallerID()); + } + + /** + * Returns {@code true} if this method is a bridge + * method; returns {@code false} otherwise. + * + * @return true if and only if this method is a bridge + * method as defined by the Java Language Specification. + * @since 1.5 + */ + public boolean isBridge() { + return (getModifiers() & Modifier.BRIDGE) != 0; + } + + /** + * {@inheritDoc} + * @since 1.5 + */ + @Override + public boolean isVarArgs() { + return super.isVarArgs(); + } + + /** + * {@inheritDoc} + * @jls 13.1 The Form of a Binary + * @since 1.5 + */ + @Override + public boolean isSynthetic() { + return super.isSynthetic(); + } + + /** + * Returns {@code true} if this method is a default + * method; returns {@code false} otherwise. + * + * A default method is a public non-abstract instance method, that + * is, a non-static method with a body, declared in an interface + * type. + * + * @return true if and only if this method is a default + * method as defined by the Java Language Specification. + * @since 1.8 + */ + public boolean isDefault() { + // Default methods are public non-abstract instance methods + // declared in an interface. + return ((getModifiers() & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC)) == + Modifier.PUBLIC) && getDeclaringClass().isInterface(); + } + + // NOTE that there is no synchronization used here. It is correct + // (though not efficient) to generate more than one MethodAccessor + // for a given Method. However, avoiding synchronization will + // probably make the implementation more scalable. + private MethodAccessor acquireMethodAccessor() { + // First check to see if one has been created yet, and take it + // if so + MethodAccessor tmp = null; + if (root != null) tmp = root.getMethodAccessor(); + if (tmp != null) { + methodAccessor = tmp; + } else { + // Otherwise fabricate one and propagate it up to the root + tmp = reflectionFactory.newMethodAccessor(this); + setMethodAccessor(tmp); + } + + return tmp; + } + + // Returns MethodAccessor for this Method object, not looking up + // the chain to the root + MethodAccessor getMethodAccessor() { + return methodAccessor; + } + + // Sets the MethodAccessor for this Method object and + // (recursively) its root + void setMethodAccessor(MethodAccessor accessor) { + methodAccessor = accessor; + // Propagate up + if (root != null) { + root.setMethodAccessor(accessor); + } + } + + /** + * Returns the default value for the annotation member represented by + * this {@code Method} instance. If the member is of a primitive type, + * an instance of the corresponding wrapper type is returned. Returns + * null if no default is associated with the member, or if the method + * instance does not represent a declared member of an annotation type. + * + * @return the default value for the annotation member represented + * by this {@code Method} instance. + * @throws TypeNotPresentException if the annotation is of type + * {@link Class} and no definition can be found for the + * default class value. + * @since 1.5 + */ + public native Object getDefaultValue(); + + /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + public T getAnnotation(Class annotationClass) { + return super.getAnnotation(annotationClass); + } + + /** + * {@inheritDoc} + * @since 1.5 + */ + public Annotation[] getDeclaredAnnotations() { + return super.getDeclaredAnnotations(); + } + + /** + * {@inheritDoc} + * @since 1.5 + */ + @Override + public Annotation[][] getParameterAnnotations() { + return sharedGetParameterAnnotations(parameterTypes); + } + + /** + * {@inheritDoc} + * @since 1.8 + */ + @Override + public AnnotatedType getAnnotatedReturnType() { + return getAnnotatedReturnType0(getGenericReturnType()); + } + + @Override + void handleParameterNumberMismatch(int resultLength, int numParameters) { + throw new AnnotationFormatError("Parameter annotations don't match number of parameters"); + } +} diff --git a/openjdk/java/lang/reflect/Proxy.java b/openjdk/java/lang/reflect/Proxy.java new file mode 100644 index 0000000..de7416d --- /dev/null +++ b/openjdk/java/lang/reflect/Proxy.java @@ -0,0 +1,843 @@ +/* + * Copyright (c) 1999, 2013, 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 java.lang.reflect; + +import java.lang.ref.WeakReference; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Arrays; +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.BiFunction; +import sun.misc.ProxyGenerator; +import sun.misc.VM; +import sun.reflect.CallerSensitive; +import sun.reflect.Reflection; +import sun.reflect.misc.ReflectUtil; +import sun.security.util.SecurityConstants; + +/** + * {@code Proxy} provides static methods for creating dynamic proxy + * classes and instances, and it is also the superclass of all + * dynamic proxy classes created by those methods. + * + *

To create a proxy for some interface {@code Foo}: + *

+ *     InvocationHandler handler = new MyInvocationHandler(...);
+ *     Class<?> proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), Foo.class);
+ *     Foo f = (Foo) proxyClass.getConstructor(InvocationHandler.class).
+ *                     newInstance(handler);
+ * 
+ * or more simply: + *
+ *     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
+ *                                          new Class<?>[] { Foo.class },
+ *                                          handler);
+ * 
+ * + *

A dynamic proxy class (simply referred to as a proxy + * class below) is a class that implements a list of interfaces + * specified at runtime when the class is created, with behavior as + * described below. + * + * A proxy interface is such an interface that is implemented + * by a proxy class. + * + * A proxy instance is an instance of a proxy class. + * + * Each proxy instance has an associated invocation handler + * object, which implements the interface {@link InvocationHandler}. + * A method invocation on a proxy instance through one of its proxy + * interfaces will be dispatched to the {@link InvocationHandler#invoke + * invoke} method of the instance's invocation handler, passing the proxy + * instance, a {@code java.lang.reflect.Method} object identifying + * the method that was invoked, and an array of type {@code Object} + * containing the arguments. The invocation handler processes the + * encoded method invocation as appropriate and the result that it + * returns will be returned as the result of the method invocation on + * the proxy instance. + * + *

A proxy class has the following properties: + * + *

    + *
  • Proxy classes are public, final, and not abstract if + * all proxy interfaces are public.
  • + * + *
  • Proxy classes are non-public, final, and not abstract if + * any of the proxy interfaces is non-public.
  • + * + *
  • The unqualified name of a proxy class is unspecified. The space + * of class names that begin with the string {@code "$Proxy"} + * should be, however, reserved for proxy classes. + * + *
  • A proxy class extends {@code java.lang.reflect.Proxy}. + * + *
  • A proxy class implements exactly the interfaces specified at its + * creation, in the same order. + * + *
  • If a proxy class implements a non-public interface, then it will + * be defined in the same package as that interface. Otherwise, the + * package of a proxy class is also unspecified. Note that package + * sealing will not prevent a proxy class from being successfully defined + * in a particular package at runtime, and neither will classes already + * defined by the same class loader and the same package with particular + * signers. + * + *
  • Since a proxy class implements all of the interfaces specified at + * its creation, invoking {@code getInterfaces} on its + * {@code Class} object will return an array containing the same + * list of interfaces (in the order specified at its creation), invoking + * {@code getMethods} on its {@code Class} object will return + * an array of {@code Method} objects that include all of the + * methods in those interfaces, and invoking {@code getMethod} will + * find methods in the proxy interfaces as would be expected. + * + *
  • The {@link Proxy#isProxyClass Proxy.isProxyClass} method will + * return true if it is passed a proxy class-- a class returned by + * {@code Proxy.getProxyClass} or the class of an object returned by + * {@code Proxy.newProxyInstance}-- and false otherwise. + * + *
  • The {@code java.security.ProtectionDomain} of a proxy class + * is the same as that of system classes loaded by the bootstrap class + * loader, such as {@code java.lang.Object}, because the code for a + * proxy class is generated by trusted system code. This protection + * domain will typically be granted + * {@code java.security.AllPermission}. + * + *
  • Each proxy class has one public constructor that takes one argument, + * an implementation of the interface {@link InvocationHandler}, to set + * the invocation handler for a proxy instance. Rather than having to use + * the reflection API to access the public constructor, a proxy instance + * can be also be created by calling the {@link Proxy#newProxyInstance + * Proxy.newProxyInstance} method, which combines the actions of calling + * {@link Proxy#getProxyClass Proxy.getProxyClass} with invoking the + * constructor with an invocation handler. + *
+ * + *

A proxy instance has the following properties: + * + *

    + *
  • Given a proxy instance {@code proxy} and one of the + * interfaces implemented by its proxy class {@code Foo}, the + * following expression will return true: + *
    + *     {@code proxy instanceof Foo}
    + * 
    + * and the following cast operation will succeed (rather than throwing + * a {@code ClassCastException}): + *
    + *     {@code (Foo) proxy}
    + * 
    + * + *
  • Each proxy instance has an associated invocation handler, the one + * that was passed to its constructor. The static + * {@link Proxy#getInvocationHandler Proxy.getInvocationHandler} method + * will return the invocation handler associated with the proxy instance + * passed as its argument. + * + *
  • An interface method invocation on a proxy instance will be + * encoded and dispatched to the invocation handler's {@link + * InvocationHandler#invoke invoke} method as described in the + * documentation for that method. + * + *
  • An invocation of the {@code hashCode}, + * {@code equals}, or {@code toString} methods declared in + * {@code java.lang.Object} on a proxy instance will be encoded and + * dispatched to the invocation handler's {@code invoke} method in + * the same manner as interface method invocations are encoded and + * dispatched, as described above. The declaring class of the + * {@code Method} object passed to {@code invoke} will be + * {@code java.lang.Object}. Other public methods of a proxy + * instance inherited from {@code java.lang.Object} are not + * overridden by a proxy class, so invocations of those methods behave + * like they do for instances of {@code java.lang.Object}. + *
+ * + *

Methods Duplicated in Multiple Proxy Interfaces

+ * + *

When two or more interfaces of a proxy class contain a method with + * the same name and parameter signature, the order of the proxy class's + * interfaces becomes significant. When such a duplicate method + * is invoked on a proxy instance, the {@code Method} object passed + * to the invocation handler will not necessarily be the one whose + * declaring class is assignable from the reference type of the interface + * that the proxy's method was invoked through. This limitation exists + * because the corresponding method implementation in the generated proxy + * class cannot determine which interface it was invoked through. + * Therefore, when a duplicate method is invoked on a proxy instance, + * the {@code Method} object for the method in the foremost interface + * that contains the method (either directly or inherited through a + * superinterface) in the proxy class's list of interfaces is passed to + * the invocation handler's {@code invoke} method, regardless of the + * reference type through which the method invocation occurred. + * + *

If a proxy interface contains a method with the same name and + * parameter signature as the {@code hashCode}, {@code equals}, + * or {@code toString} methods of {@code java.lang.Object}, + * when such a method is invoked on a proxy instance, the + * {@code Method} object passed to the invocation handler will have + * {@code java.lang.Object} as its declaring class. In other words, + * the public, non-final methods of {@code java.lang.Object} + * logically precede all of the proxy interfaces for the determination of + * which {@code Method} object to pass to the invocation handler. + * + *

Note also that when a duplicate method is dispatched to an + * invocation handler, the {@code invoke} method may only throw + * checked exception types that are assignable to one of the exception + * types in the {@code throws} clause of the method in all of + * the proxy interfaces that it can be invoked through. If the + * {@code invoke} method throws a checked exception that is not + * assignable to any of the exception types declared by the method in one + * of the proxy interfaces that it can be invoked through, then an + * unchecked {@code UndeclaredThrowableException} will be thrown by + * the invocation on the proxy instance. This restriction means that not + * all of the exception types returned by invoking + * {@code getExceptionTypes} on the {@code Method} object + * passed to the {@code invoke} method can necessarily be thrown + * successfully by the {@code invoke} method. + * + * @author Peter Jones + * @see InvocationHandler + * @since 1.3 + */ +public class Proxy implements java.io.Serializable { + + private static final long serialVersionUID = -2222568056686623797L; + + /** parameter types of a proxy class constructor */ + private static final Class[] constructorParams = + { InvocationHandler.class }; + + /** + * a cache of proxy classes + */ + private static final WeakCache[], Class> + proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory()); + + /** + * the invocation handler for this proxy instance. + * @serial + */ + protected InvocationHandler h; + + /** + * Prohibits instantiation. + */ + private Proxy() { + } + + /** + * Constructs a new {@code Proxy} instance from a subclass + * (typically, a dynamic proxy class) with the specified value + * for its invocation handler. + * + * @param h the invocation handler for this proxy instance + * + * @throws NullPointerException if the given invocation handler, {@code h}, + * is {@code null}. + */ + protected Proxy(InvocationHandler h) { + Objects.requireNonNull(h); + this.h = h; + } + + /** + * Returns the {@code java.lang.Class} object for a proxy class + * given a class loader and an array of interfaces. The proxy class + * will be defined by the specified class loader and will implement + * all of the supplied interfaces. If any of the given interfaces + * is non-public, the proxy class will be non-public. If a proxy class + * for the same permutation of interfaces has already been defined by the + * class loader, then the existing proxy class will be returned; otherwise, + * a proxy class for those interfaces will be generated dynamically + * and defined by the class loader. + * + *

There are several restrictions on the parameters that may be + * passed to {@code Proxy.getProxyClass}: + * + *

    + *
  • All of the {@code Class} objects in the + * {@code interfaces} array must represent interfaces, not + * classes or primitive types. + * + *
  • No two elements in the {@code interfaces} array may + * refer to identical {@code Class} objects. + * + *
  • All of the interface types must be visible by name through the + * specified class loader. In other words, for class loader + * {@code cl} and every interface {@code i}, the following + * expression must be true: + *
    +     *     Class.forName(i.getName(), false, cl) == i
    +     * 
    + * + *
  • All non-public interfaces must be in the same package; + * otherwise, it would not be possible for the proxy class to + * implement all of the interfaces, regardless of what package it is + * defined in. + * + *
  • For any set of member methods of the specified interfaces + * that have the same signature: + *
      + *
    • If the return type of any of the methods is a primitive + * type or void, then all of the methods must have that same + * return type. + *
    • Otherwise, one of the methods must have a return type that + * is assignable to all of the return types of the rest of the + * methods. + *
    + * + *
  • The resulting proxy class must not exceed any limits imposed + * on classes by the virtual machine. For example, the VM may limit + * the number of interfaces that a class may implement to 65535; in + * that case, the size of the {@code interfaces} array must not + * exceed 65535. + *
+ * + *

If any of these restrictions are violated, + * {@code Proxy.getProxyClass} will throw an + * {@code IllegalArgumentException}. If the {@code interfaces} + * array argument or any of its elements are {@code null}, a + * {@code NullPointerException} will be thrown. + * + *

Note that the order of the specified proxy interfaces is + * significant: two requests for a proxy class with the same combination + * of interfaces but in a different order will result in two distinct + * proxy classes. + * + * @param loader the class loader to define the proxy class + * @param interfaces the list of interfaces for the proxy class + * to implement + * @return a proxy class that is defined in the specified class loader + * and that implements the specified interfaces + * @throws IllegalArgumentException if any of the restrictions on the + * parameters that may be passed to {@code getProxyClass} + * are violated + * @throws SecurityException if a security manager, s, is present + * and any of the following conditions is met: + *

    + *
  • the given {@code loader} is {@code null} and + * the caller's class loader is not {@code null} and the + * invocation of {@link SecurityManager#checkPermission + * s.checkPermission} with + * {@code RuntimePermission("getClassLoader")} permission + * denies access.
  • + *
  • for each proxy interface, {@code intf}, + * the caller's class loader is not the same as or an + * ancestor of the class loader for {@code intf} and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to {@code intf}.
  • + *
+ + * @throws NullPointerException if the {@code interfaces} array + * argument or any of its elements are {@code null} + */ + @CallerSensitive + public static Class getProxyClass(ClassLoader loader, + Class... interfaces) + throws IllegalArgumentException + { + final Class[] intfs = interfaces.clone(); + final SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + checkProxyAccess(Reflection.getCallerClass(), loader, intfs); + } + + return getProxyClass0(loader, intfs); + } + + /* + * Check permissions required to create a Proxy class. + * + * To define a proxy class, it performs the access checks as in + * Class.forName (VM will invoke ClassLoader.checkPackageAccess): + * 1. "getClassLoader" permission check if loader == null + * 2. checkPackageAccess on the interfaces it implements + * + * To get a constructor and new instance of a proxy class, it performs + * the package access check on the interfaces it implements + * as in Class.getConstructor. + * + * If an interface is non-public, the proxy class must be defined by + * the defining loader of the interface. If the caller's class loader + * is not the same as the defining loader of the interface, the VM + * will throw IllegalAccessError when the generated proxy class is + * being defined via the defineClass0 method. + */ + private static void checkProxyAccess(Class caller, + ClassLoader loader, + Class... interfaces) + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + ClassLoader ccl = caller.getClassLoader(); + if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) { + sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); + } + ReflectUtil.checkProxyPackageAccess(ccl, interfaces); + } + } + + /** + * Generate a proxy class. Must call the checkProxyAccess method + * to perform permission checks before calling this. + */ + private static Class getProxyClass0(ClassLoader loader, + Class... interfaces) { + if (interfaces.length > 65535) { + throw new IllegalArgumentException("interface limit exceeded"); + } + + // If the proxy class defined by the given loader implementing + // the given interfaces exists, this will simply return the cached copy; + // otherwise, it will create the proxy class via the ProxyClassFactory + return proxyClassCache.get(loader, interfaces); + } + + /* + * a key used for proxy class with 0 implemented interfaces + */ + private static final Object key0 = new Object(); + + /* + * Key1 and Key2 are optimized for the common use of dynamic proxies + * that implement 1 or 2 interfaces. + */ + + /* + * a key used for proxy class with 1 implemented interface + */ + private static final class Key1 extends WeakReference> { + private final int hash; + + Key1(Class intf) { + super(intf); + this.hash = intf.hashCode(); + } + + @Override + public int hashCode() { + return hash; + } + + @Override + public boolean equals(Object obj) { + Class intf; + return this == obj || + obj != null && + obj.getClass() == Key1.class && + (intf = get()) != null && + intf == ((Key1) obj).get(); + } + } + + /* + * a key used for proxy class with 2 implemented interfaces + */ + private static final class Key2 extends WeakReference> { + private final int hash; + private final WeakReference> ref2; + + Key2(Class intf1, Class intf2) { + super(intf1); + hash = 31 * intf1.hashCode() + intf2.hashCode(); + ref2 = new WeakReference>(intf2); + } + + @Override + public int hashCode() { + return hash; + } + + @Override + public boolean equals(Object obj) { + Class intf1, intf2; + return this == obj || + obj != null && + obj.getClass() == Key2.class && + (intf1 = get()) != null && + intf1 == ((Key2) obj).get() && + (intf2 = ref2.get()) != null && + intf2 == ((Key2) obj).ref2.get(); + } + } + + /* + * a key used for proxy class with any number of implemented interfaces + * (used here for 3 or more only) + */ + private static final class KeyX { + private final int hash; + private final WeakReference>[] refs; + + @SuppressWarnings("unchecked") + KeyX(Class[] interfaces) { + hash = Arrays.hashCode(interfaces); + refs = (WeakReference>[])new WeakReference[interfaces.length]; + for (int i = 0; i < interfaces.length; i++) { + refs[i] = new WeakReference<>(interfaces[i]); + } + } + + @Override + public int hashCode() { + return hash; + } + + @Override + public boolean equals(Object obj) { + return this == obj || + obj != null && + obj.getClass() == KeyX.class && + equals(refs, ((KeyX) obj).refs); + } + + private static boolean equals(WeakReference>[] refs1, + WeakReference>[] refs2) { + if (refs1.length != refs2.length) { + return false; + } + for (int i = 0; i < refs1.length; i++) { + Class intf = refs1[i].get(); + if (intf == null || intf != refs2[i].get()) { + return false; + } + } + return true; + } + } + + /** + * A function that maps an array of interfaces to an optimal key where + * Class objects representing interfaces are weakly referenced. + */ + private static final class KeyFactory + implements BiFunction[], Object> + { + @Override + public Object apply(ClassLoader classLoader, Class[] interfaces) { + switch (interfaces.length) { + case 1: return new Key1(interfaces[0]); // the most frequent + case 2: return new Key2(interfaces[0], interfaces[1]); + case 0: return key0; + default: return new KeyX(interfaces); + } + } + } + + /** + * A factory function that generates, defines and returns the proxy class given + * the ClassLoader and array of interfaces. + */ + private static final class ProxyClassFactory + implements BiFunction[], Class> + { + // prefix for all proxy class names + private static final String proxyClassNamePrefix = "$Proxy"; + + // next number to use for generation of unique proxy class names + private static final AtomicLong nextUniqueNumber = new AtomicLong(); + + @Override + public Class apply(ClassLoader loader, Class[] interfaces) { + + Map, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length); + for (Class intf : interfaces) { + /* + * Verify that the class loader resolves the name of this + * interface to the same Class object. + */ + Class interfaceClass = null; + try { + interfaceClass = Class.forName(intf.getName(), false, loader); + } catch (ClassNotFoundException e) { + } + if (interfaceClass != intf) { + throw new IllegalArgumentException( + intf + " is not visible from class loader"); + } + /* + * Verify that the Class object actually represents an + * interface. + */ + if (!interfaceClass.isInterface()) { + throw new IllegalArgumentException( + interfaceClass.getName() + " is not an interface"); + } + /* + * Verify that this interface is not a duplicate. + */ + if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) { + throw new IllegalArgumentException( + "repeated interface: " + interfaceClass.getName()); + } + } + + String proxyPkg = null; // package to define proxy class in + int accessFlags = Modifier.PUBLIC | Modifier.FINAL; + + /* + * Record the package of a non-public proxy interface so that the + * proxy class will be defined in the same package. Verify that + * all non-public proxy interfaces are in the same package. + */ + for (Class intf : interfaces) { + int flags = intf.getModifiers(); + if (!Modifier.isPublic(flags)) { + accessFlags = Modifier.FINAL; + String name = intf.getName(); + int n = name.lastIndexOf('.'); + String pkg = ((n == -1) ? "" : name.substring(0, n + 1)); + if (proxyPkg == null) { + proxyPkg = pkg; + } else if (!pkg.equals(proxyPkg)) { + throw new IllegalArgumentException( + "non-public interfaces from different packages"); + } + } + } + + if (proxyPkg == null) { + // if no non-public proxy interfaces, use com.sun.proxy package + proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; + } + + /* + * Choose a name for the proxy class to generate. + */ + long num = nextUniqueNumber.getAndIncrement(); + String proxyName = proxyPkg + proxyClassNamePrefix + num; + + Class precompiledProxyClass = getPrecompiledProxy(loader, proxyName, interfaces); + if (precompiledProxyClass != null) { + return precompiledProxyClass; + } + + /* + * Generate the specified proxy class. + */ + byte[] proxyClassFile = ProxyGenerator.generateProxyClass( + proxyName, interfaces, accessFlags); + try { + return defineClass0(loader, proxyName, + proxyClassFile, 0, proxyClassFile.length); + } catch (ClassFormatError e) { + /* + * A ClassFormatError here means that (barring bugs in the + * proxy class generation code) there was some other + * invalid aspect of the arguments supplied to the proxy + * class creation (such as virtual machine limitations + * exceeded). + */ + throw new IllegalArgumentException(e.toString()); + } + } + } + + /** + * Returns an instance of a proxy class for the specified interfaces + * that dispatches method invocations to the specified invocation + * handler. + * + *

{@code Proxy.newProxyInstance} throws + * {@code IllegalArgumentException} for the same reasons that + * {@code Proxy.getProxyClass} does. + * + * @param loader the class loader to define the proxy class + * @param interfaces the list of interfaces for the proxy class + * to implement + * @param h the invocation handler to dispatch method invocations to + * @return a proxy instance with the specified invocation handler of a + * proxy class that is defined by the specified class loader + * and that implements the specified interfaces + * @throws IllegalArgumentException if any of the restrictions on the + * parameters that may be passed to {@code getProxyClass} + * are violated + * @throws SecurityException if a security manager, s, is present + * and any of the following conditions is met: + *

    + *
  • the given {@code loader} is {@code null} and + * the caller's class loader is not {@code null} and the + * invocation of {@link SecurityManager#checkPermission + * s.checkPermission} with + * {@code RuntimePermission("getClassLoader")} permission + * denies access;
  • + *
  • for each proxy interface, {@code intf}, + * the caller's class loader is not the same as or an + * ancestor of the class loader for {@code intf} and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to {@code intf};
  • + *
  • any of the given proxy interfaces is non-public and the + * caller class is not in the same {@linkplain Package runtime package} + * as the non-public interface and the invocation of + * {@link SecurityManager#checkPermission s.checkPermission} with + * {@code ReflectPermission("newProxyInPackage.{package name}")} + * permission denies access.
  • + *
+ * @throws NullPointerException if the {@code interfaces} array + * argument or any of its elements are {@code null}, or + * if the invocation handler, {@code h}, is + * {@code null} + */ + @CallerSensitive + public static Object newProxyInstance(ClassLoader loader, + Class[] interfaces, + InvocationHandler h) + throws IllegalArgumentException + { + Objects.requireNonNull(h); + + final Class[] intfs = interfaces.clone(); + final SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + checkProxyAccess(Reflection.getCallerClass(), loader, intfs); + } + + /* + * Look up or generate the designated proxy class. + */ + Class cl = getProxyClass0(loader, intfs); + + /* + * Invoke its constructor with the designated invocation handler. + */ + try { + if (sm != null) { + checkNewProxyPermission(Reflection.getCallerClass(), cl); + } + + final Constructor cons = cl.getConstructor(constructorParams); + final InvocationHandler ih = h; + if (!Modifier.isPublic(cl.getModifiers())) { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + cons.setAccessible(true); + return null; + } + }); + } + return cons.newInstance(new Object[]{h}); + } catch (IllegalAccessException|InstantiationException e) { + throw new InternalError(e.toString(), e); + } catch (InvocationTargetException e) { + Throwable t = e.getCause(); + if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } else { + throw new InternalError(t.toString(), t); + } + } catch (NoSuchMethodException e) { + throw new InternalError(e.toString(), e); + } + } + + private static void checkNewProxyPermission(Class caller, Class proxyClass) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + if (ReflectUtil.isNonPublicProxyClass(proxyClass)) { + ClassLoader ccl = caller.getClassLoader(); + ClassLoader pcl = proxyClass.getClassLoader(); + + // do permission check if the caller is in a different runtime package + // of the proxy class + int n = proxyClass.getName().lastIndexOf('.'); + String pkg = (n == -1) ? "" : proxyClass.getName().substring(0, n); + + n = caller.getName().lastIndexOf('.'); + String callerPkg = (n == -1) ? "" : caller.getName().substring(0, n); + + if (pcl != ccl || !pkg.equals(callerPkg)) { + sm.checkPermission(new ReflectPermission("newProxyInPackage." + pkg)); + } + } + } + } + + /** + * Returns true if and only if the specified class was dynamically + * generated to be a proxy class using the {@code getProxyClass} + * method or the {@code newProxyInstance} method. + * + *

The reliability of this method is important for the ability + * to use it to make security decisions, so its implementation should + * not just test if the class in question extends {@code Proxy}. + * + * @param cl the class to test + * @return {@code true} if the class is a proxy class and + * {@code false} otherwise + * @throws NullPointerException if {@code cl} is {@code null} + */ + public static boolean isProxyClass(Class cl) { + return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl); + } + + /** + * Returns the invocation handler for the specified proxy instance. + * + * @param proxy the proxy instance to return the invocation handler for + * @return the invocation handler for the proxy instance + * @throws IllegalArgumentException if the argument is not a + * proxy instance + * @throws SecurityException if a security manager, s, is present + * and the caller's class loader is not the same as or an + * ancestor of the class loader for the invocation handler + * and invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the invocation + * handler's class. + */ + @CallerSensitive + public static InvocationHandler getInvocationHandler(Object proxy) + throws IllegalArgumentException + { + /* + * Verify that the object is actually a proxy instance. + */ + if (!isProxyClass(proxy.getClass())) { + throw new IllegalArgumentException("not a proxy instance"); + } + + final Proxy p = (Proxy) proxy; + final InvocationHandler ih = p.h; + if (System.getSecurityManager() != null) { + Class ihClass = ih.getClass(); + Class caller = Reflection.getCallerClass(); + if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(), + ihClass.getClassLoader())) + { + ReflectUtil.checkPackageAccess(ihClass); + } + } + + return ih; + } + + private static native Class defineClass0(ClassLoader loader, String name, + byte[] b, int off, int len); + + private static native Class getPrecompiledProxy(ClassLoader loader, String proxyName, Class[] interfaces); +} diff --git a/openjdk/java/net/DefaultDatagramSocketImplFactory.java b/openjdk/java/net/DefaultDatagramSocketImplFactory.java new file mode 100644 index 0000000..68b6830 --- /dev/null +++ b/openjdk/java/net/DefaultDatagramSocketImplFactory.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2007, 2013, 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 java.net; + +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * This class defines a factory for creating DatagramSocketImpls. It defaults + * to creating plain DatagramSocketImpls, but may create other DatagramSocketImpls + * by setting the impl.prefix system property. + * + * For Windows versions lower than Windows Vista a TwoStacksPlainDatagramSocketImpl + * is always created. This impl supports IPv6 on these platform where available. + * + * On Windows platforms greater than Vista that support a dual layer TCP/IP stack + * a DualStackPlainDatagramSocketImpl is created for DatagramSockets. For MulticastSockets + * a TwoStacksPlainDatagramSocketImpl is always created. This is to overcome the lack + * of behavior defined for multicasting over a dual layer socket by the RFC. + * + * @author Chris Hegarty + */ + +class DefaultDatagramSocketImplFactory +{ + static Class prefixImplClass = null; + + /* the windows version. */ + private static float version; + + /* java.net.preferIPv4Stack */ + private static boolean preferIPv4Stack = false; + + /* If the version supports a dual stack TCP implementation */ + private static boolean useDualStackImpl = false; + + /* sun.net.useExclusiveBind */ + private static String exclBindProp; + + /* True if exclusive binding is on for Windows */ + private static boolean exclusiveBind = true; + + + static { + // Determine Windows Version. + java.security.AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + version = 0; + try { + version = Float.parseFloat(System.getProperties() + .getProperty("os.version")); + preferIPv4Stack = Boolean.parseBoolean( + System.getProperties() + .getProperty( + "java.net.preferIPv4Stack")); + exclBindProp = System.getProperty( + "sun.net.useExclusiveBind"); + } catch (NumberFormatException e ) { + assert false : e; + } + return null; // nothing to return + } + }); + + String ipv6 = ikvm.internal.Util.SafeGetEnvironmentVariable("IKVM_IPV6"); + if (ipv6 != null) { + try { + if ((Integer.parseInt(ipv6) & 4) == 0) { + preferIPv4Stack = true; + } else { + useDualStackImpl = true; + } + } catch (NumberFormatException _) { + } + } else if (!InetAddressImplFactory.isIPv6Supported()) { + preferIPv4Stack = true; + } + + // (version >= 6.0) implies Vista or greater. + if (version >= 6.0 && !preferIPv4Stack) { + useDualStackImpl = true; + } + if (exclBindProp != null) { + // sun.net.useExclusiveBind is true + exclusiveBind = exclBindProp.length() == 0 ? true + : Boolean.parseBoolean(exclBindProp); + } else if (version < 6.0) { + exclusiveBind = false; + } + + // impl.prefix + String prefix = null; + try { + prefix = AccessController.doPrivileged( + new sun.security.action.GetPropertyAction("impl.prefix", null)); + if (prefix != null) + prefixImplClass = Class.forName("java.net."+prefix+"DatagramSocketImpl"); + } catch (Exception e) { + System.err.println("Can't find class: java.net." + + prefix + + "DatagramSocketImpl: check impl.prefix property"); + } + } + + /** + * Creates a new DatagramSocketImpl instance. + * + * @param isMulticast true if this impl is to be used for a MutlicastSocket + * @return a new instance of PlainDatagramSocketImpl. + */ + static DatagramSocketImpl createDatagramSocketImpl(boolean isMulticast) + throws SocketException { + if (prefixImplClass != null) { + try { + return (DatagramSocketImpl) prefixImplClass.newInstance(); + } catch (Exception e) { + throw new SocketException("can't instantiate DatagramSocketImpl"); + } + } else { + if (isMulticast) + exclusiveBind = false; + if (useDualStackImpl && !isMulticast) + return new DualStackPlainDatagramSocketImpl(exclusiveBind); + else + return new TwoStacksPlainDatagramSocketImpl(exclusiveBind); + } + } +} diff --git a/openjdk/java/net/DualStackPlainDatagramSocketImpl.java b/openjdk/java/net/DualStackPlainDatagramSocketImpl.java new file mode 100644 index 0000000..f31b55e --- /dev/null +++ b/openjdk/java/net/DualStackPlainDatagramSocketImpl.java @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2007, 2013, 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 java.net; + +import java.io.IOException; + +/** + * This class defines the plain DatagramSocketImpl that is used on + * Windows platforms greater than or equal to Windows Vista. These + * platforms have a dual layer TCP/IP stack and can handle both IPv4 + * and IPV6 through a single file descriptor. + *

+ * Note: Multicasting on a dual layer TCP/IP stack is always done with + * TwoStacksPlainDatagramSocketImpl. This is to overcome the lack + * of behavior defined for multicasting over a dual layer socket by the RFC. + * + * @author Chris Hegarty + */ + +class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl +{ + + // true if this socket is exclusively bound + private final boolean exclusiveBind; + + /* + * Set to true if SO_REUSEADDR is set after the socket is bound to + * indicate SO_REUSEADDR is being emulated + */ + private boolean reuseAddressEmulated; + + // emulates SO_REUSEADDR when exclusiveBind is true and socket is bound + private boolean isReuseAddress; + + DualStackPlainDatagramSocketImpl(boolean exclBind) { + exclusiveBind = exclBind; + } + + protected void datagramSocketCreate() throws SocketException { + if (fd == null) + throw new SocketException("Socket closed"); + + cli.System.Net.Sockets.Socket newfd = socketCreate(false /* v6Only */); + + fd.setSocket(newfd); + } + + protected synchronized void bind0(int lport, InetAddress laddr) + throws SocketException { + cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD(); + + if (laddr == null) + throw new NullPointerException("argument address"); + + socketBind(nativefd, laddr, lport, exclusiveBind); + if (lport == 0) { + localPort = socketLocalPort(nativefd); + } else { + localPort = lport; + } + } + + protected synchronized int peek(InetAddress address) throws IOException { + cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD(); + + if (address == null) + throw new NullPointerException("Null address in peek()"); + + // Use peekData() + DatagramPacket peekPacket = new DatagramPacket(new byte[1], 1); + int peekPort = peekData(peekPacket); + address = peekPacket.getAddress(); + return peekPort; + } + + protected synchronized int peekData(DatagramPacket p) throws IOException { + cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD(); + + if (p == null) + throw new NullPointerException("packet"); + if (p.getData() == null) + throw new NullPointerException("packet buffer"); + + return socketReceiveOrPeekData(nativefd, p, timeout, connected, true /*peek*/); + } + + protected synchronized void receive0(DatagramPacket p) throws IOException { + cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD(); + + if (p == null) + throw new NullPointerException("packet"); + if (p.getData() == null) + throw new NullPointerException("packet buffer"); + + socketReceiveOrPeekData(nativefd, p, timeout, connected, false /*receive*/); + } + + protected void send(DatagramPacket p) throws IOException { + cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD(); + + if (p == null) + throw new NullPointerException("null packet"); + + if (p.getAddress() == null ||p.getData() ==null) + throw new NullPointerException("null address || null buffer"); + + socketSend(nativefd, p.getData(), p.getOffset(), p.getLength(), + p.getAddress(), p.getPort(), connected); + } + + protected void connect0(InetAddress address, int port) throws SocketException { + cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD(); + + if (address == null) + throw new NullPointerException("address"); + + socketConnect(nativefd, address, port); + } + + protected void disconnect0(int family /*unused*/) { + if (fd == null || !fd.valid()) + return; // disconnect doesn't throw any exceptions + + socketDisconnect(fd.getSocket()); + } + + protected void datagramSocketClose() { + if (fd == null || !fd.valid()) + return; // close doesn't throw any exceptions + + socketClose(fd.getSocket()); + fd.setSocket(null); + } + + @SuppressWarnings("fallthrough") + protected void socketSetOption(int opt, Object val) throws SocketException { + cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD(); + + int optionValue = 0; + + switch(opt) { + case IP_TOS : + case SO_RCVBUF : + case SO_SNDBUF : + optionValue = ((Integer)val).intValue(); + break; + case SO_REUSEADDR : + if (exclusiveBind && localPort != 0) { + // socket already bound, emulate SO_REUSEADDR + reuseAddressEmulated = true; + isReuseAddress = (Boolean)val; + return; + } + //Intentional fallthrough + case SO_BROADCAST : + optionValue = ((Boolean)val).booleanValue() ? 1 : 0; + break; + default: /* shouldn't get here */ + throw new SocketException("Option not supported"); + } + + socketSetIntOption(nativefd, opt, optionValue); + } + + protected Object socketGetOption(int opt) throws SocketException { + cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD(); + + // SO_BINDADDR is not a socket option. + if (opt == SO_BINDADDR) { + return socketLocalAddress(nativefd); + } + if (opt == SO_REUSEADDR && reuseAddressEmulated) + return isReuseAddress; + + int value = socketGetIntOption(nativefd, opt); + Object returnValue = null; + + switch (opt) { + case SO_REUSEADDR : + case SO_BROADCAST : + returnValue = (value == 0) ? Boolean.FALSE : Boolean.TRUE; + break; + case IP_TOS : + case SO_RCVBUF : + case SO_SNDBUF : + returnValue = new Integer(value); + break; + default: /* shouldn't get here */ + throw new SocketException("Option not supported"); + } + + return returnValue; + } + + /* Multicast specific methods. + * Multicasting on a dual layer TCP/IP stack is always done with + * TwoStacksPlainDatagramSocketImpl. This is to overcome the lack + * of behavior defined for multicasting over a dual layer socket by the RFC. + */ + protected void join(InetAddress inetaddr, NetworkInterface netIf) + throws IOException { + throw new IOException("Method not implemented!"); + } + + protected void leave(InetAddress inetaddr, NetworkInterface netIf) + throws IOException { + throw new IOException("Method not implemented!"); + } + + protected void setTimeToLive(int ttl) throws IOException { + throw new IOException("Method not implemented!"); + } + + protected int getTimeToLive() throws IOException { + throw new IOException("Method not implemented!"); + } + + @Deprecated + protected void setTTL(byte ttl) throws IOException { + throw new IOException("Method not implemented!"); + } + + @Deprecated + protected byte getTTL() throws IOException { + throw new IOException("Method not implemented!"); + } + /* END Multicast specific methods */ + + private cli.System.Net.Sockets.Socket checkAndReturnNativeFD() throws SocketException { + if (fd == null || !fd.valid()) + throw new SocketException("Socket closed"); + + return fd.getSocket(); + } + + /* Native methods */ + + private static cli.System.Net.Sockets.Socket socketCreate(boolean v6Only) { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + cli.System.Net.Sockets.Socket ret = DualStackPlainDatagramSocketImpl_c.socketCreate(env, v6Only); + env.ThrowPendingException(); + return ret; + } + + private static void socketBind(cli.System.Net.Sockets.Socket fd, InetAddress localAddress, + int localport, boolean exclBind) throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + DualStackPlainDatagramSocketImpl_c.socketBind(env, fd, localAddress, localport, exclBind); + env.ThrowPendingException(); + } + + private static void socketConnect(cli.System.Net.Sockets.Socket fd, InetAddress address, int port) + throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + DualStackPlainDatagramSocketImpl_c.socketConnect(env, fd, address, port); + env.ThrowPendingException(); + } + + private static void socketDisconnect(cli.System.Net.Sockets.Socket fd) { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + DualStackPlainDatagramSocketImpl_c.socketDisconnect(env, fd); + env.ThrowPendingException(); + } + + private static void socketClose(cli.System.Net.Sockets.Socket fd) { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + DualStackPlainDatagramSocketImpl_c.socketClose(env, fd); + env.ThrowPendingException(); + } + + private static int socketLocalPort(cli.System.Net.Sockets.Socket fd) throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + int ret = DualStackPlainDatagramSocketImpl_c.socketLocalPort(env, fd); + env.ThrowPendingException(); + return ret; + } + + private static Object socketLocalAddress(cli.System.Net.Sockets.Socket fd) throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + Object ret = DualStackPlainDatagramSocketImpl_c.socketLocalAddress(env, fd); + env.ThrowPendingException(); + return ret; + } + + private static int socketReceiveOrPeekData(cli.System.Net.Sockets.Socket fd, DatagramPacket packet, + int timeout, boolean connected, boolean peek) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + int ret = DualStackPlainDatagramSocketImpl_c.socketReceiveOrPeekData(env, fd, packet, timeout, connected, peek); + env.ThrowPendingException(); + return ret; + } + + private static void socketSend(cli.System.Net.Sockets.Socket fd, byte[] data, int offset, int length, + InetAddress address, int port, boolean connected) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + DualStackPlainDatagramSocketImpl_c.socketSend(env, fd, data, offset, length, address, port, connected); + env.ThrowPendingException(); + } + + private static void socketSetIntOption(cli.System.Net.Sockets.Socket fd, int cmd, + int optionValue) throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + DualStackPlainDatagramSocketImpl_c.socketSetIntOption(env, fd, cmd, optionValue); + env.ThrowPendingException(); + } + + private static int socketGetIntOption(cli.System.Net.Sockets.Socket fd, int cmd) throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + int ret = DualStackPlainDatagramSocketImpl_c.socketGetIntOption(env, fd, cmd); + env.ThrowPendingException(); + return ret; + } +} diff --git a/openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java b/openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java new file mode 100644 index 0000000..98e364d --- /dev/null +++ b/openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java @@ -0,0 +1,489 @@ +/* + * Copyright (c) 2007, 2013, 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 java.net; + +import java.io.FileDescriptor; +import static ikvm.internal.JNI.*; +import static ikvm.internal.Winsock.*; +import static java.net.net_util_md.*; + +final class DualStackPlainDatagramSocketImpl_c +{ +static final int TRUE = 1; +static final int FALSE = 0; + +static final int JVM_IO_ERR = -1; +static final int JVM_IO_INTR = -2; + +/* +#include +#include +#include "jni.h" +#include "net_util.h" +#include "java_net_DualStackPlainDatagramSocketImpl.h" + +/* + * This function "purges" all outstanding ICMP port unreachable packets + * outstanding on a socket and returns JNI_TRUE if any ICMP messages + * have been purged. The rational for purging is to emulate normal BSD + * behaviour whereby receiving a "connection reset" status resets the + * socket. + */ +static boolean purgeOutstandingICMP(JNIEnv env, cli.System.Net.Sockets.Socket fd) +{ + boolean got_icmp = false; + byte[] buf = new byte[1]; + fd_set tbl = new fd_set(); + timeval t = new timeval(); + SOCKETADDRESS rmtaddr = null; + + /* + * Peek at the queue to see if there is an ICMP port unreachable. If there + * is then receive it. + */ + FD_ZERO(tbl); + FD_SET(fd, tbl); + while(true) { + if (select(tbl, null, null, t) <= 0) { + break; + } + if (recvfrom(fd, buf, 1, MSG_PEEK, + rmtaddr) != JVM_IO_ERR) { + break; + } + if (WSAGetLastError() != WSAECONNRESET) { + /* some other error - we don't care here */ + break; + } + + recvfrom(fd, buf, 1, 0, rmtaddr); + got_icmp = JNI_TRUE; + } + + return got_icmp; +} + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketCreate + * Signature: (Z)I + */ +static cli.System.Net.Sockets.Socket socketCreate + (JNIEnv env, boolean v6Only /*unused*/) { + cli.System.Net.Sockets.Socket fd; + int rv, opt=0, t=TRUE; + + fd = socket(AF_INET6, SOCK_DGRAM, 0); + if (fd == INVALID_SOCKET) { + NET_ThrowNew(env, WSAGetLastError(), "Socket creation failed"); + return null; + } + + rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, opt); + if (rv == SOCKET_ERROR) { + NET_ThrowNew(env, WSAGetLastError(), "Socket creation failed"); + return null; + } + + //SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE); + NET_SetSockOpt(fd, SOL_SOCKET, SO_BROADCAST, t); + + /* SIO_UDP_CONNRESET fixes a "bug" introduced in Windows 2000, which + * returns connection reset errors on unconnected UDP sockets (as well + * as connected sockets). The solution is to only enable this feature + * when the socket is connected. + */ + t = FALSE; + WSAIoctl(fd ,SIO_UDP_CONNRESET ,false); + + return fd; +} + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketBind + * Signature: (ILjava/net/InetAddress;I)V + */ +static void socketBind + (JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddress iaObj, int port, boolean exclBind) { + SOCKETADDRESS sa; + sa = new SOCKETADDRESS(); + int rv; + + if (NET_InetAddressToSockaddr(env, iaObj, port, sa, + JNI_TRUE) != 0) { + return; + } + rv = NET_WinBind(fd, sa, exclBind); + + if (rv == SOCKET_ERROR) { + if (WSAGetLastError() == WSAEACCES) { + WSASetLastError(WSAEADDRINUSE); + } + NET_ThrowNew(env, WSAGetLastError(), "Cannot bind"); + } +} + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketConnect + * Signature: (ILjava/net/InetAddress;I)V + */ +static void socketConnect + (JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddress iaObj, int port) { + SOCKETADDRESS sa; + sa = new SOCKETADDRESS(); + int rv; + int t = TRUE; + + if (NET_InetAddressToSockaddr(env, iaObj, port, sa, + JNI_TRUE) != 0) { + return; + } + + rv = connect(fd, sa); + if (rv == SOCKET_ERROR) { + NET_ThrowNew(env, WSAGetLastError(), "connect"); + return; + } + + /* see comment in socketCreate */ + WSAIoctl(fd, SIO_UDP_CONNRESET, true); +} + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketDisconnect + * Signature: (I)V + */ +static void socketDisconnect + (JNIEnv env, cli.System.Net.Sockets.Socket fd ) { + SOCKETADDRESS sa; + sa = new SOCKETADDRESS(); + + connect(fd, sa); + + /* see comment in socketCreate */ + WSAIoctl(fd, SIO_UDP_CONNRESET, false); +} + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketClose + * Signature: (I)V + */ +static void socketClose + (JNIEnv env, cli.System.Net.Sockets.Socket fd) { + NET_SocketClose(fd); +} + + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketLocalPort + * Signature: (I)I + */ +static int socketLocalPort + (JNIEnv env, cli.System.Net.Sockets.Socket fd) { + SOCKETADDRESS sa; + sa = new SOCKETADDRESS(); + + if (getsockname(fd, sa) == SOCKET_ERROR) { + NET_ThrowNew(env, WSAGetLastError(), "JVM_GetSockName"); + return -1; + } + return ntohs(GET_PORT(sa)); +} + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketLocalAddress + * Signature: (I)Ljava/lang/Object; + */ +static InetAddress socketLocalAddress + (JNIEnv env , cli.System.Net.Sockets.Socket fd) { + SOCKETADDRESS sa; + sa = new SOCKETADDRESS(); + InetAddress iaObj; + int[] port = { 0 }; + + if (getsockname(fd, sa) == SOCKET_ERROR) { + NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name"); + return null; + } + + iaObj = NET_SockaddrToInetAddress(env, sa, port); + return iaObj; +} + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketReceiveOrPeekData + * Signature: (ILjava/net/DatagramPacket;IZZ)I + */ +static int socketReceiveOrPeekData + (JNIEnv env, cli.System.Net.Sockets.Socket fd, DatagramPacket dpObj, + int timeout, boolean connected, boolean peek) { + SOCKETADDRESS sa; + sa = new SOCKETADDRESS(); + int port, rv, flags=0; + boolean retry; + long prevTime = 0; + + int packetBufferOffset, packetBufferLen; + byte[] packetBuffer; + + /* if we are only peeking. Called from peekData */ + if (peek) { + flags = MSG_PEEK; + } + + packetBuffer = dpObj.buf; + packetBufferOffset = dpObj.offset; + packetBufferLen = dpObj.bufLength; + /* Note: the buffer needn't be greater than 65,536 (0xFFFF) + * the max size of an IP packet. Anything bigger is truncated anyway. + *-/ + if (packetBufferLen > MAX_PACKET_LEN) { + packetBufferLen = MAX_PACKET_LEN; + } + + if (packetBufferLen > MAX_BUFFER_LEN) { + fullPacket = (char *)malloc(packetBufferLen); + if (!fullPacket) { + JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); + return -1; + } + } else { + fullPacket = &(BUF[0]); + } + */ + + do { + retry = false; + + if (timeout != 0) { + if (prevTime == 0) { + prevTime = JVM_CurrentTimeMillis(env, 0); + } + rv = NET_Timeout(fd, timeout); + if (rv <= 0) { + if (rv == 0) { + JNU_ThrowByName(env,JNU_JAVANETPKG+"SocketTimeoutException", + "Receive timed out"); + } else if (rv == JVM_IO_ERR) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Socket closed"); + } else if (rv == JVM_IO_INTR) { + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", + "operation interrupted"); + } + return -1; + } + } + + /* receive the packet */ + rv = recvfrom(fd, packetBuffer, packetBufferOffset, packetBufferLen, flags, + sa); + + if (rv == SOCKET_ERROR && (WSAGetLastError() == WSAECONNRESET)) { + /* An icmp port unreachable - we must receive this as Windows + * does not reset the state of the socket until this has been + * received. + */ + purgeOutstandingICMP(env, fd); + + if (connected) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"PortUnreachableException", + "ICMP Port Unreachable"); + return -1; + } else if (timeout != 0) { + /* Adjust timeout */ + long newTime = JVM_CurrentTimeMillis(env, 0); + timeout -= (int)(newTime - prevTime); + if (timeout <= 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", + "Receive timed out"); + return -1; + } + prevTime = newTime; + } + retry = true; + } + } while (retry); + + port = ntohs (GET_PORT(sa)); + + /* truncate the data if the packet's length is too small */ + if (rv > packetBufferLen) { + rv = packetBufferLen; + } + if (rv < 0) { + if (WSAGetLastError() == WSAEMSGSIZE) { + /* it is because the buffer is too small. It's UDP, it's + * unreliable, it's all good. discard the rest of the + * data.. + */ + rv = packetBufferLen; + } else { + /* failure */ + dpObj.length = 0; + } + } + + if (rv == -1) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); + } else if (rv == -2) { + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", + "operation interrupted"); + } else if (rv < 0) { + NET_ThrowCurrent(env, "Datagram receive failed"); + } else { + InetAddress packetAddress; + /* + * Check if there is an InetAddress already associated with this + * packet. If so, we check if it is the same source address. We + * can't update any existing InetAddress because it is immutable + */ + packetAddress = dpObj.address; + if (packetAddress != NULL) { + if (!NET_SockaddrEqualsInetAddress(sa, + packetAddress)) { + /* force a new InetAddress to be created */ + packetAddress = null; + } + } + if (packetAddress == NULL) { + int[] tmp = { port }; + packetAddress = NET_SockaddrToInetAddress(sa, tmp); + port = tmp[0]; + if (packetAddress != NULL) { + /* stuff the new Inetaddress into the packet */ + dpObj.address = packetAddress; + } + } + + /* populate the packet */ + dpObj.port = port; + dpObj.length = rv; + } + + return port; +} + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketSend + * Signature: (I[BIILjava/net/InetAddress;IZ)V + */ +static void socketSend + (JNIEnv env, cli.System.Net.Sockets.Socket fd, byte[] data, int offset, int length, + InetAddress iaObj, int port, boolean connected) { + SOCKETADDRESS sa; + int rv; + + if (connected) { + sa = null; /* arg to JVM_Sendto () null in this case */ + } else { + sa = new SOCKETADDRESS(); + if (NET_InetAddressToSockaddr(env, iaObj, port, sa, + JNI_TRUE) != 0) { + return; + } + } + + /* + if (length > MAX_BUFFER_LEN) { + /* Note: the buffer needn't be greater than 65,536 (0xFFFF) + * the max size of an IP packet. Anything bigger is truncated anyway. + *-/ + if (length > MAX_PACKET_LEN) { + length = MAX_PACKET_LEN; + } + fullPacket = (char *)malloc(length); + if (!fullPacket) { + JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); + return; + } + } else { + fullPacket = &(BUF[0]); + } + */ + + rv = sendto(fd, data, offset, length, 0, sa); + if (rv == SOCKET_ERROR) { + if (rv == JVM_IO_ERR) { + NET_ThrowNew(env, WSAGetLastError(), "Datagram send failed"); + } else if (rv == JVM_IO_INTR) { + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", + "operation interrupted"); + } + } + +} + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketSetIntOption + * Signature: (III)V + */ +static void socketSetIntOption + (JNIEnv env, cli.System.Net.Sockets.Socket fd , int cmd, int value) { + int[] level = { 0 }, opt = { 0 }; + + if (NET_MapSocketOption(cmd, level, opt) < 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Invalid option"); + return; + } + + if (NET_SetSockOpt(fd, level[0], opt[0], value) < 0) { + NET_ThrowNew(env, WSAGetLastError(), "setsockopt"); + } +} + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketGetIntOption + * Signature: (II)I + */ +static int socketGetIntOption + (JNIEnv env, cli.System.Net.Sockets.Socket fd, int cmd) { + int[] level = { 0 }, opt = { 0 }, result = { 0 }; + + if (NET_MapSocketOption(cmd, level, opt) < 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Invalid option"); + return -1; + } + + if (NET_GetSockOpt(fd, level[0], opt[0], result) < 0) { + NET_ThrowNew(env, WSAGetLastError(), "getsockopt"); + return -1; + } + + return result[0]; +} +} diff --git a/openjdk/java/net/DualStackPlainSocketImpl.java b/openjdk/java/net/DualStackPlainSocketImpl.java new file mode 100644 index 0000000..a55455a --- /dev/null +++ b/openjdk/java/net/DualStackPlainSocketImpl.java @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2007, 2013, 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 java.net; + +import java.io.IOException; +import java.io.FileDescriptor; + +/** + * This class defines the plain SocketImpl that is used on Windows platforms + * greater or equal to Windows Vista. These platforms have a dual + * layer TCP/IP stack and can handle both IPv4 and IPV6 through a + * single file descriptor. + * + * @author Chris Hegarty + */ + +class DualStackPlainSocketImpl extends AbstractPlainSocketImpl +{ + + + // true if this socket is exclusively bound + private final boolean exclusiveBind; + + // emulates SO_REUSEADDR when exclusiveBind is true + private boolean isReuseAddress; + + public DualStackPlainSocketImpl(boolean exclBind) { + exclusiveBind = exclBind; + } + + public DualStackPlainSocketImpl(FileDescriptor fd, boolean exclBind) { + this.fd = fd; + exclusiveBind = exclBind; + } + + void socketCreate(boolean stream) throws IOException { + if (fd == null) + throw new SocketException("Socket closed"); + + cli.System.Net.Sockets.Socket newfd = socket0(stream, false /*v6 Only*/); + + fd.setSocket(newfd); + } + + void socketConnect(InetAddress address, int port, int timeout) + throws IOException { + cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD(); + + if (address == null) + throw new NullPointerException("inet address argument is null."); + + int connectResult; + if (timeout <= 0) { + connectResult = connect0(nativefd, address, port); + } else { + configureBlocking(nativefd, false); + try { + connectResult = connect0(nativefd, address, port); + if (connectResult == WOULDBLOCK) { + waitForConnect(nativefd, timeout); + } + } finally { + configureBlocking(nativefd, true); + } + } + /* + * We need to set the local port field. If bind was called + * previous to the connect (by the client) then localport field + * will already be set. + */ + if (localport == 0) + localport = localPort0(nativefd); + } + + void socketBind(InetAddress address, int port) throws IOException { + cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD(); + + if (address == null) + throw new NullPointerException("inet address argument is null."); + + bind0(nativefd, address, port, exclusiveBind); + if (port == 0) { + localport = localPort0(nativefd); + } else { + localport = port; + } + + this.address = address; + } + + void socketListen(int backlog) throws IOException { + cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD(); + + listen0(nativefd, backlog); + } + + void socketAccept(SocketImpl s) throws IOException { + cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD(); + + if (s == null) + throw new NullPointerException("socket is null"); + + cli.System.Net.Sockets.Socket newfd = null; + InetSocketAddress[] isaa = new InetSocketAddress[1]; + if (timeout <= 0) { + newfd = accept0(nativefd, isaa); + } else { + configureBlocking(nativefd, false); + try { + waitForNewConnection(nativefd, timeout); + newfd = accept0(nativefd, isaa); + if (newfd != null) { + configureBlocking(newfd, true); + } + } finally { + configureBlocking(nativefd, true); + } + } + /* Update (SocketImpl)s' fd */ + s.fd.setSocket(newfd); + /* Update socketImpls remote port, address and localport */ + InetSocketAddress isa = isaa[0]; + s.port = isa.getPort(); + s.address = isa.getAddress(); + s.localport = localport; + } + + int socketAvailable() throws IOException { + cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD(); + return available0(nativefd); + } + + void socketClose0(boolean useDeferredClose/*unused*/) throws IOException { + if (fd == null) + throw new SocketException("Socket closed"); + + if (!fd.valid()) + return; + + cli.System.Net.Sockets.Socket nativefd = fd.getSocket(); + fd.setSocket(null); + close0(nativefd); + } + + void socketShutdown(int howto) throws IOException { + cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD(); + shutdown0(nativefd, howto); + } + + // Intentional fallthrough after SO_REUSEADDR + @SuppressWarnings("fallthrough") + void socketSetOption(int opt, boolean on, Object value) + throws SocketException { + cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD(); + + if (opt == SO_TIMEOUT) { // timeout implemented through select. + return; + } + + int optionValue = 0; + + switch(opt) { + case SO_REUSEADDR : + if (exclusiveBind) { + // SO_REUSEADDR emulated when using exclusive bind + isReuseAddress = on; + return; + } + // intentional fallthrough + case TCP_NODELAY : + case SO_OOBINLINE : + case SO_KEEPALIVE : + optionValue = on ? 1 : 0; + break; + case SO_SNDBUF : + case SO_RCVBUF : + case IP_TOS : + optionValue = ((Integer)value).intValue(); + break; + case SO_LINGER : + if (on) { + optionValue = ((Integer)value).intValue(); + } else { + optionValue = -1; + } + break; + default :/* shouldn't get here */ + throw new SocketException("Option not supported"); + } + + setIntOption(nativefd, opt, optionValue); + } + + int socketGetOption(int opt, Object iaContainerObj) throws SocketException { + cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD(); + + // SO_BINDADDR is not a socket option. + if (opt == SO_BINDADDR) { + localAddress(nativefd, (InetAddressContainer)iaContainerObj); + return 0; // return value doesn't matter. + } + + // SO_REUSEADDR emulated when using exclusive bind + if (opt == SO_REUSEADDR && exclusiveBind) + return isReuseAddress? 1 : -1; + + int value = getIntOption(nativefd, opt); + + switch (opt) { + case TCP_NODELAY : + case SO_OOBINLINE : + case SO_KEEPALIVE : + case SO_REUSEADDR : + return (value == 0) ? -1 : 1; + } + return value; + } + + void socketSendUrgentData(int data) throws IOException { + cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD(); + sendOOB(nativefd, data); + } + + private cli.System.Net.Sockets.Socket checkAndReturnNativeFD() throws SocketException { + if (fd == null || !fd.valid()) + throw new SocketException("Socket closed"); + + return fd.getSocket(); + } + + static final int WOULDBLOCK = -2; // Nothing available (non-blocking) + + /* Native methods */ + + static cli.System.Net.Sockets.Socket socket0(boolean stream, boolean v6Only) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + cli.System.Net.Sockets.Socket ret = DualStackPlainSocketImpl_c.socket0(env, stream, v6Only); + env.ThrowPendingException(); + return ret; + } + + static void bind0(cli.System.Net.Sockets.Socket fd, InetAddress localAddress, int localport, + boolean exclBind) + throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + DualStackPlainSocketImpl_c.bind0(env, fd, localAddress, localport, exclBind); + env.ThrowPendingException(); + } + + static int connect0(cli.System.Net.Sockets.Socket fd, InetAddress remote, int remotePort) + throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + int ret = DualStackPlainSocketImpl_c.connect0(env, fd, remote, remotePort); + env.ThrowPendingException(); + return ret; + } + + static void waitForConnect(cli.System.Net.Sockets.Socket fd, int timeout) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + DualStackPlainSocketImpl_c.waitForConnect(env, fd, timeout); + env.ThrowPendingException(); + } + + static int localPort0(cli.System.Net.Sockets.Socket fd) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + int ret = DualStackPlainSocketImpl_c.localPort0(env, fd); + env.ThrowPendingException(); + return ret; + } + + static void localAddress(cli.System.Net.Sockets.Socket fd, InetAddressContainer in) throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + DualStackPlainSocketImpl_c.localAddress(env, fd, in); + env.ThrowPendingException(); + } + + static void listen0(cli.System.Net.Sockets.Socket fd, int backlog) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + DualStackPlainSocketImpl_c.listen0(env, fd, backlog); + env.ThrowPendingException(); + } + + static cli.System.Net.Sockets.Socket accept0(cli.System.Net.Sockets.Socket fd, InetSocketAddress[] isaa) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + cli.System.Net.Sockets.Socket ret = DualStackPlainSocketImpl_c.accept0(env, fd, isaa); + env.ThrowPendingException(); + return ret; + } + + static void waitForNewConnection(cli.System.Net.Sockets.Socket fd, int timeout) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + DualStackPlainSocketImpl_c.waitForNewConnection(env, fd, timeout); + env.ThrowPendingException(); + } + + static int available0(cli.System.Net.Sockets.Socket fd) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + int ret = DualStackPlainSocketImpl_c.available0(env, fd); + env.ThrowPendingException(); + return ret; + } + + static void close0(cli.System.Net.Sockets.Socket fd) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + DualStackPlainSocketImpl_c.close0(env, fd); + env.ThrowPendingException(); + } + + static void shutdown0(cli.System.Net.Sockets.Socket fd, int howto) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + DualStackPlainSocketImpl_c.shutdown0(env, fd, howto); + env.ThrowPendingException(); + } + + static void setIntOption(cli.System.Net.Sockets.Socket fd, int cmd, int optionValue) throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + DualStackPlainSocketImpl_c.setIntOption(env, fd, cmd, optionValue); + env.ThrowPendingException(); + } + + static int getIntOption(cli.System.Net.Sockets.Socket fd, int cmd) throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + int ret = DualStackPlainSocketImpl_c.getIntOption(env, fd, cmd); + env.ThrowPendingException(); + return ret; + } + + static void sendOOB(cli.System.Net.Sockets.Socket fd, int data) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + DualStackPlainSocketImpl_c.sendOOB(env, fd, data); + env.ThrowPendingException(); + } + + static void configureBlocking(cli.System.Net.Sockets.Socket fd, boolean blocking) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + DualStackPlainSocketImpl_c.configureBlocking(env, fd, blocking); + env.ThrowPendingException(); + } +} diff --git a/openjdk/java/net/DualStackPlainSocketImpl_c.java b/openjdk/java/net/DualStackPlainSocketImpl_c.java new file mode 100644 index 0000000..26a8219 --- /dev/null +++ b/openjdk/java/net/DualStackPlainSocketImpl_c.java @@ -0,0 +1,491 @@ +/* + * Copyright (c) 2007, 2013, 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 java.net; + +import java.io.FileDescriptor; +import static ikvm.internal.JNI.*; +import static ikvm.internal.Winsock.*; +import static java.net.net_util_md.*; + +final class DualStackPlainSocketImpl_c +{ +private static final int JVM_IO_ERR = -1; +private static final int JVM_IO_INTR = -2; + +private static final int SET_BLOCKING = 0; +private static final int SET_NONBLOCKING = 1; +/* +#include +#include +#include "jni.h" +#include "net_util.h" +#include "java_net_DualStackPlainSocketImpl.h" + +#define SET_BLOCKING 0 +#define SET_NONBLOCKING 1 + +static jclass isa_class; /* java.net.InetSocketAddress *-/ +static jmethodID isa_ctorID; /* InetSocketAddress(InetAddress, int) *-/ + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: initIDs + * Signature: ()V + *-/ +JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_initIDs + (JNIEnv *env, jclass clazz) { + + jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress"); + CHECK_NULL(cls); + isa_class = (*env)->NewGlobalRef(env, cls); + isa_ctorID = (*env)->GetMethodID(env, cls, "", + "(Ljava/net/InetAddress;I)V"); + + // implement read timeout with select. + isRcvTimeoutSupported = 0; +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: socket0 + * Signature: (ZZ)I + */ +static cli.System.Net.Sockets.Socket socket0 + (JNIEnv env, boolean stream, boolean v6Only /*unused*/) { + cli.System.Net.Sockets.Socket fd; + int rv, opt=0; + + fd = NET_Socket(AF_INET6, (stream ? SOCK_STREAM : SOCK_DGRAM), 0); + if (fd == INVALID_SOCKET) { + NET_ThrowNew(env, WSAGetLastError(), "create"); + return null; + } + + rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, opt); + if (rv == SOCKET_ERROR) { + NET_ThrowNew(env, WSAGetLastError(), "create"); + } + + + return fd; +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: bind0 + * Signature: (ILjava/net/InetAddress;I)V + */ +static void bind0 + (JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddress iaObj, int port, + boolean exclBind) +{ + SOCKETADDRESS sa; + sa = new SOCKETADDRESS(); + int rv; + + if (NET_InetAddressToSockaddr(env, iaObj, port, sa, + JNI_TRUE) != 0) { + return; + } + + rv = NET_WinBind(fd, sa, exclBind); + + if (rv == SOCKET_ERROR) + NET_ThrowNew(env, WSAGetLastError(), "JVM_Bind"); +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: connect0 + * Signature: (ILjava/net/InetAddress;I)I + */ +static int connect0 + (JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddress iaObj, int port) { + SOCKETADDRESS sa; + sa = new SOCKETADDRESS(); + int rv; + + if (NET_InetAddressToSockaddr(env, iaObj, port, sa, + JNI_TRUE) != 0) { + return -1; + } + + rv = connect(fd, sa); + if (rv == SOCKET_ERROR) { + int err = WSAGetLastError(); + if (err == WSAEWOULDBLOCK) { + return java.net.DualStackPlainSocketImpl.WOULDBLOCK; + } else if (err == WSAEADDRNOTAVAIL) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"ConnectException", + "connect: Address is invalid on local machine, or port is not valid on remote machine"); + } else { + NET_ThrowNew(env, err, "connect"); + } + return -1; // return value not important. + } + return rv; +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: waitForConnect + * Signature: (II)V + */ +static void waitForConnect + (JNIEnv env, cli.System.Net.Sockets.Socket fd, int timeout) { + int rv, retry; + fd_set wr, ex; + wr = new fd_set(); ex = new fd_set(); + timeval t = new timeval(); + + FD_ZERO(wr); + FD_ZERO(ex); + FD_SET(fd, wr); + FD_SET(fd, ex); + t.tv_sec = timeout / 1000; + t.tv_usec = (timeout % 1000) * 1000; + + /* + * Wait for timeout, connection established or + * connection failed. + */ + rv = select(null, wr, ex, t); + + /* + * Timeout before connection is established/failed so + * we throw exception and shutdown input/output to prevent + * socket from being used. + * The socket should be closed immediately by the caller. + */ + if (rv == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", + "connect timed out"); + shutdown( fd, SD_BOTH ); + return; + } + + /* + * Socket is writable or error occurred. On some Windows editions + * the socket will appear writable when the connect fails so we + * check for error rather than writable. + */ + if (!FD_ISSET(fd, ex)) { + return; /* connection established */ + } + + /* + * Connection failed. The logic here is designed to work around + * bug on Windows NT whereby using getsockopt to obtain the + * last error (SO_ERROR) indicates there is no error. The workaround + * on NT is to allow winsock to be scheduled and this is done by + * yielding and retrying. As yielding is problematic in heavy + * load conditions we attempt up to 3 times to get the error reason. + */ + for (retry=0; retry<3; retry++) { + int[] tmp = { 0 }; + NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, + tmp); + rv = tmp[0]; + if (rv != 0) { + break; + } + Sleep(0); + } + + if (rv == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Unable to establish connection"); + } else { + NET_ThrowNew(env, rv, "connect"); + } +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: localPort0 + * Signature: (I)I + */ +static int localPort0 + (JNIEnv env, cli.System.Net.Sockets.Socket fd) { + SOCKETADDRESS sa; + sa = new SOCKETADDRESS(); + + if (getsockname(fd, sa) == SOCKET_ERROR) { + if (WSAGetLastError() == WSAENOTSOCK) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Socket closed"); + } else { + NET_ThrowNew(env, WSAGetLastError(), "getsockname failed"); + } + return -1; + } + return ntohs(GET_PORT(sa)); +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: localAddress + * Signature: (ILjava/net/InetAddressContainer;)V + */ +static void localAddress + (JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddressContainer iaContainerObj) { + int[] port = { 0 }; + SOCKETADDRESS sa; + sa = new SOCKETADDRESS(); + InetAddress iaObj; + + if (getsockname(fd, sa) == SOCKET_ERROR) { + NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name"); + return; + } + iaObj = NET_SockaddrToInetAddress(env, sa, port); + + iaContainerObj.addr = iaObj; +} + + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: listen0 + * Signature: (II)V + */ +static void listen0 + (JNIEnv env, cli.System.Net.Sockets.Socket fd, int backlog) { + if (listen(fd, backlog) == SOCKET_ERROR) { + NET_ThrowNew(env, WSAGetLastError(), "listen failed"); + } +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: accept0 + * Signature: (I[Ljava/net/InetSocketAddress;)I + */ +static cli.System.Net.Sockets.Socket accept0 + (JNIEnv env, cli.System.Net.Sockets.Socket fd, InetSocketAddress[] isaa) { + cli.System.Net.Sockets.Socket newfd; + int[] port = { 0 }; + InetSocketAddress isa; + InetAddress ia; + SOCKETADDRESS sa; + sa = new SOCKETADDRESS(); + + newfd = accept(fd, sa); + + if (newfd == INVALID_SOCKET) { + if (WSAGetLastError() == -2) { + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", + "operation interrupted"); + } else { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "socket closed"); + } + return null; + } + + ia = NET_SockaddrToInetAddress(env, sa, port); + isa = new InetSocketAddress(ia, port[0]); + isaa[0] = isa; + + return newfd; +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: waitForNewConnection + * Signature: (II)V + */ +static void waitForNewConnection + (JNIEnv env, cli.System.Net.Sockets.Socket fd, int timeout) { + int rv; + + rv = NET_Timeout(fd, timeout); + if (rv == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", + "Accept timed out"); + } else if (rv == -1) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); + } else if (rv == -2) { + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", + "operation interrupted"); + } +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: available0 + * Signature: (I)I + */ +static int available0 + (JNIEnv env, cli.System.Net.Sockets.Socket fd) { + int[] available = { -1 }; + + if ((ioctlsocket(fd, FIONREAD, available)) == SOCKET_ERROR) { + NET_ThrowNew(env, WSAGetLastError(), "socket available"); + } + + return available[0]; +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: close0 + * Signature: (I)V + */ +static void close0 + (JNIEnv env, cli.System.Net.Sockets.Socket fd) { + NET_SocketClose(fd); +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: shutdown0 + * Signature: (II)V + */ +static void shutdown0 + (JNIEnv env, cli.System.Net.Sockets.Socket fd, int howto) { + shutdown(fd, howto); +} + + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: setIntOption + * Signature: (III)V + */ +static void setIntOption + (JNIEnv env, cli.System.Net.Sockets.Socket fd, int cmd, int value) { + + int[] level = { 0 }; + int[] opt = { 0 }; + linger linger; + Object optval; + + if (NET_MapSocketOption(cmd, level, opt) < 0) { + JNU_ThrowByName(env, + JNU_JAVANETPKG+"SocketException", + "Invalid option"); + return; + } + + if (opt[0] == java.net.SocketOptions.SO_LINGER) { + linger = new linger(); + if (value >= 0) { + linger.l_onoff = 1; + linger.l_linger = value & 0xFFFF; + } else { + linger.l_onoff = 0; + linger.l_linger = 0; + } + optval = linger; + } else { + optval = value; + } + + if (NET_SetSockOpt(fd, level[0], opt[0], optval) < 0) { + NET_ThrowNew(env, WSAGetLastError(), "setsockopt"); + } +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: getIntOption + * Signature: (II)I + */ +static int getIntOption + (JNIEnv env, cli.System.Net.Sockets.Socket fd, int cmd) { + + int[] level = { 0 }; + int[] opt = { 0 }; + int[] result = { 0 }; + linger linger; + Object optval; + + if (NET_MapSocketOption(cmd, level, opt) < 0) { + JNU_ThrowByName(env, + JNU_JAVANETPKG+"SocketException", + "Unsupported socket option"); + return -1; + } + + if (opt[0] == java.net.SocketOptions.SO_LINGER) { + linger = new linger(); + optval = linger; + } else { + linger = null; + optval = result; + } + + if (NET_GetSockOpt(fd, level[0], opt[0], optval) < 0) { + NET_ThrowNew(env, WSAGetLastError(), "getsockopt"); + return -1; + } + + if (opt[0] == java.net.SocketOptions.SO_LINGER) + return linger.l_onoff != 0 ? linger.l_linger : -1; + else + return result[0]; +} + + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: sendOOB + * Signature: (II)V + */ +static void sendOOB + (JNIEnv env, cli.System.Net.Sockets.Socket fd, int data) { + int n; + + n = send(fd, new byte[] { (byte)data }, 1, MSG_OOB); + if (n == JVM_IO_ERR) { + NET_ThrowNew(env, WSAGetLastError(), "send"); + } else if (n == JVM_IO_INTR) { + JNU_ThrowByName(env, "java.io.InterruptedIOException", null); + } +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: configureBlocking + * Signature: (IZ)V + */ +static void configureBlocking + (JNIEnv env, cli.System.Net.Sockets.Socket fd, boolean blocking) { + int arg; + int result; + + if (blocking == JNI_TRUE) { + arg = SET_BLOCKING; // 0 + } else { + arg = SET_NONBLOCKING; // 1 + } + + result = ioctlsocket(fd, FIONBIO, arg); + if (result == SOCKET_ERROR) { + NET_ThrowNew(env, WSAGetLastError(), "configureBlocking"); + } +} +} diff --git a/openjdk/java/net/PlainSocketImpl.java b/openjdk/java/net/PlainSocketImpl.java new file mode 100644 index 0000000..6a80e63 --- /dev/null +++ b/openjdk/java/net/PlainSocketImpl.java @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2007, 2013, 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 java.net; + +import java.io.*; +import java.security.PrivilegedAction; + +/* + * This class PlainSocketImpl simply delegates to the appropriate real + * SocketImpl. We do this because PlainSocketImpl is already extended + * by SocksSocketImpl. + *

+ * There are two possibilities for the real SocketImpl, + * TwoStacksPlainSocketImpl or DualStackPlainSocketImpl. We use + * DualStackPlainSocketImpl on systems that have a dual stack + * TCP implementation. Otherwise we create an instance of + * TwoStacksPlainSocketImpl and delegate to it. + * + * @author Chris Hegarty + */ + +class PlainSocketImpl extends AbstractPlainSocketImpl +{ + private AbstractPlainSocketImpl impl; + + /* the windows version. */ + private static float version; + + /* java.net.preferIPv4Stack */ + private static boolean preferIPv4Stack = false; + + /* If the version supports a dual stack TCP implementation */ + private static boolean useDualStackImpl = false; + + /* sun.net.useExclusiveBind */ + private static String exclBindProp; + + /* True if exclusive binding is on for Windows */ + private static boolean exclusiveBind = true; + + static { + java.security.AccessController.doPrivileged( new PrivilegedAction() { + public Object run() { + version = 0; + try { + version = Float.parseFloat(System.getProperties().getProperty("os.version")); + preferIPv4Stack = Boolean.parseBoolean( + System.getProperties().getProperty("java.net.preferIPv4Stack")); + exclBindProp = System.getProperty("sun.net.useExclusiveBind"); + } catch (NumberFormatException e ) { + assert false : e; + } + return null; // nothing to return + } }); + + String ipv6 = ikvm.internal.Util.SafeGetEnvironmentVariable("IKVM_IPV6"); + if (ipv6 != null) { + try { + if ((Integer.parseInt(ipv6) & 4) == 0) { + preferIPv4Stack = true; + } else { + useDualStackImpl = true; + } + } catch (NumberFormatException _) { + } + } else if (!InetAddressImplFactory.isIPv6Supported()) { + preferIPv4Stack = true; + } + + // (version >= 6.0) implies Vista or greater. + if (version >= 6.0 && !preferIPv4Stack) { + useDualStackImpl = true; + } + + if (exclBindProp != null) { + // sun.net.useExclusiveBind is true + exclusiveBind = exclBindProp.length() == 0 ? true + : Boolean.parseBoolean(exclBindProp); + } else if (version < 6.0) { + exclusiveBind = false; + } + } + + /** + * Constructs an empty instance. + */ + PlainSocketImpl() { + if (useDualStackImpl) { + impl = new DualStackPlainSocketImpl(exclusiveBind); + } else { + impl = new TwoStacksPlainSocketImpl(exclusiveBind); + } + } + + /** + * Constructs an instance with the given file descriptor. + */ + PlainSocketImpl(FileDescriptor fd) { + if (useDualStackImpl) { + impl = new DualStackPlainSocketImpl(fd, exclusiveBind); + } else { + impl = new TwoStacksPlainSocketImpl(fd, exclusiveBind); + } + } + + // Override methods in SocketImpl that access impl's fields. + + protected FileDescriptor getFileDescriptor() { + return impl.getFileDescriptor(); + } + + protected InetAddress getInetAddress() { + return impl.getInetAddress(); + } + + protected int getPort() { + return impl.getPort(); + } + + protected int getLocalPort() { + return impl.getLocalPort(); + } + + void setSocket(Socket soc) { + impl.setSocket(soc); + } + + Socket getSocket() { + return impl.getSocket(); + } + + void setServerSocket(ServerSocket soc) { + impl.setServerSocket(soc); + } + + ServerSocket getServerSocket() { + return impl.getServerSocket(); + } + + public String toString() { + return impl.toString(); + } + + // Override methods in AbstractPlainSocketImpl that access impl's fields. + + protected synchronized void create(boolean stream) throws IOException { + impl.create(stream); + + // set fd to delegate's fd to be compatible with older releases + this.fd = impl.fd; + } + + protected void connect(String host, int port) + throws UnknownHostException, IOException + { + impl.connect(host, port); + } + + protected void connect(InetAddress address, int port) throws IOException { + impl.connect(address, port); + } + + protected void connect(SocketAddress address, int timeout) throws IOException { + impl.connect(address, timeout); + } + + public void setOption(int opt, Object val) throws SocketException { + impl.setOption(opt, val); + } + + public Object getOption(int opt) throws SocketException { + return impl.getOption(opt); + } + + synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException { + impl.doConnect(address, port, timeout); + } + + protected synchronized void bind(InetAddress address, int lport) + throws IOException + { + impl.bind(address, lport); + } + + protected synchronized void accept(SocketImpl s) throws IOException { + if (s instanceof PlainSocketImpl) { + // pass in the real impl not the wrapper. + SocketImpl delegate = ((PlainSocketImpl)s).impl; + delegate.address = new InetAddress(); + delegate.fd = new FileDescriptor(); + impl.accept(delegate); + // set fd to delegate's fd to be compatible with older releases + s.fd = delegate.fd; + } else { + impl.accept(s); + } + } + + void setFileDescriptor(FileDescriptor fd) { + impl.setFileDescriptor(fd); + } + + void setAddress(InetAddress address) { + impl.setAddress(address); + } + + void setPort(int port) { + impl.setPort(port); + } + + void setLocalPort(int localPort) { + impl.setLocalPort(localPort); + } + + protected synchronized InputStream getInputStream() throws IOException { + return impl.getInputStream(); + } + + void setInputStream(SocketInputStream in) { + impl.setInputStream(in); + } + + protected synchronized OutputStream getOutputStream() throws IOException { + return impl.getOutputStream(); + } + + protected void close() throws IOException { + try { + impl.close(); + } finally { + // set fd to delegate's fd to be compatible with older releases + this.fd = null; + } + } + + void reset() throws IOException { + try { + impl.reset(); + } finally { + // set fd to delegate's fd to be compatible with older releases + this.fd = null; + } + } + + protected void shutdownInput() throws IOException { + impl.shutdownInput(); + } + + protected void shutdownOutput() throws IOException { + impl.shutdownOutput(); + } + + protected void sendUrgentData(int data) throws IOException { + impl.sendUrgentData(data); + } + + FileDescriptor acquireFD() { + return impl.acquireFD(); + } + + void releaseFD() { + impl.releaseFD(); + } + + public boolean isConnectionReset() { + return impl.isConnectionReset(); + } + + public boolean isConnectionResetPending() { + return impl.isConnectionResetPending(); + } + + public void setConnectionReset() { + impl.setConnectionReset(); + } + + public void setConnectionResetPending() { + impl.setConnectionResetPending(); + } + + public boolean isClosedOrPending() { + return impl.isClosedOrPending(); + } + + public int getTimeout() { + return impl.getTimeout(); + } + + // Override methods in AbstractPlainSocketImpl that need to be implemented. + + void socketCreate(boolean isServer) throws IOException { + impl.socketCreate(isServer); + } + + void socketConnect(InetAddress address, int port, int timeout) + throws IOException { + impl.socketConnect(address, port, timeout); + } + + void socketBind(InetAddress address, int port) + throws IOException { + impl.socketBind(address, port); + } + + void socketListen(int count) throws IOException { + impl.socketListen(count); + } + + void socketAccept(SocketImpl s) throws IOException { + impl.socketAccept(s); + } + + int socketAvailable() throws IOException { + return impl.socketAvailable(); + } + + void socketClose0(boolean useDeferredClose) throws IOException { + impl.socketClose0(useDeferredClose); + } + + void socketShutdown(int howto) throws IOException { + impl.socketShutdown(howto); + } + + void socketSetOption(int cmd, boolean on, Object value) + throws SocketException { + impl.socketSetOption(cmd, on, value); + } + + int socketGetOption(int opt, Object iaContainerObj) throws SocketException { + return impl.socketGetOption(opt, iaContainerObj); + } + + void socketSendUrgentData(int data) throws IOException { + impl.socketSendUrgentData(data); + } +} diff --git a/openjdk/java/net/SocketUtil.java b/openjdk/java/net/SocketUtil.java new file mode 100644 index 0000000..d9a3086 --- /dev/null +++ b/openjdk/java/net/SocketUtil.java @@ -0,0 +1,190 @@ +/* + Copyright (C) 2002-2010 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package java.net; + +import cli.System.Net.IPAddress; +import cli.System.Net.IPEndPoint; +import cli.System.Net.Sockets.SocketOptionName; +import cli.System.Net.Sockets.SocketOptionLevel; +import ikvm.lang.CIL; +import java.io.IOException; + +@ikvm.lang.Internal +public final class SocketUtil +{ + private SocketUtil() { } + + // Winsock Error Codes + public static final int WSAEINVAL = 10022; + public static final int WSAEWOULDBLOCK = 10035; + public static final int WSAEMSGSIZE = 10040; + public static final int WSAENOPROTOOPT = 10042; + public static final int WSAEADDRINUSE = 10048; + public static final int WSAENETUNREACH = 10051; + public static final int WSAECONNRESET = 10054; + public static final int WSAESHUTDOWN = 10058; + public static final int WSAETIMEDOUT = 10060; + public static final int WSAECONNREFUSED = 10061; + public static final int WSAEHOSTUNREACH = 10065; + public static final int WSAHOST_NOT_FOUND = 11001; + + public static IOException convertSocketExceptionToIOException(cli.System.Net.Sockets.SocketException x) throws IOException + { + switch (x.get_ErrorCode()) + { + case WSAEADDRINUSE: + return new BindException(x.getMessage()); + case WSAENETUNREACH: + case WSAEHOSTUNREACH: + return new NoRouteToHostException(x.getMessage()); + case WSAETIMEDOUT: + return new SocketTimeoutException(x.getMessage()); + case WSAECONNREFUSED: + return new PortUnreachableException(x.getMessage()); + case WSAHOST_NOT_FOUND: + return new UnknownHostException(x.getMessage()); + default: + return new SocketException(x.getMessage() + "\nError Code: " + x.get_ErrorCode()); + } + } + + public static IPAddress getAddressFromInetAddress(InetAddress addr) + { + return getAddressFromInetAddress(addr, false); + } + + public static IPAddress getAddressFromInetAddress(InetAddress addr, boolean v4mapped) + { + byte[] b = addr.getAddress(); + if (b.length == 16) + { + // FXBUG in .NET 1.1 you can only construct IPv6 addresses (not IPv4) with this constructor + // (according to the documentation this was fixed in .NET 2.0) + return new IPAddress(b); + } + else if (v4mapped) + { + if (b[0] == 0 && b[1] == 0 && b[2] == 0 && b[3] == 0) + { + return IPAddress.IPv6Any; + } + byte[] b16 = new byte[16]; + b16[10] = -1; + b16[11] = -1; + b16[12] = b[0]; + b16[13] = b[1]; + b16[14] = b[2]; + b16[15] = b[3]; + return new IPAddress(b16); + } + else + { + return new IPAddress((((b[3] & 0xff) << 24) + ((b[2] & 0xff) << 16) + ((b[1] & 0xff) << 8) + (b[0] & 0xff)) & 0xffffffffL); + } + } + + public static InetAddress getInetAddressFromIPEndPoint(IPEndPoint endpoint) + { + try + { + return InetAddress.getByAddress(endpoint.get_Address().GetAddressBytes()); + } + catch (UnknownHostException x) + { + // this exception only happens if the address byte array is of invalid length, which cannot happen unless + // the .NET socket returns a bogus address + throw (InternalError)new InternalError().initCause(x); + } + } + + static void setCommonSocketOption(cli.System.Net.Sockets.Socket netSocket, int cmd, boolean on, Object value) throws SocketException + { + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + switch (cmd) + { + case SocketOptions.SO_REUSEADDR: + netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReuseAddress), on ? 1 : 0); + break; + case SocketOptions.SO_SNDBUF: + netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.SendBuffer), ((Integer)value).intValue()); + break; + case SocketOptions.SO_RCVBUF: + netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReceiveBuffer), ((Integer)value).intValue()); + break; + case SocketOptions.IP_TOS: + netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.TypeOfService), ((Integer)value).intValue()); + break; + case SocketOptions.SO_BINDADDR: // read-only + default: + throw new SocketException("Invalid socket option: " + cmd); + } + } + catch (cli.System.Net.Sockets.SocketException x) + { + throw new SocketException(x.getMessage()); + } + catch (cli.System.ObjectDisposedException x1) + { + throw new SocketException("Socket is closed"); + } + } + + static int getCommonSocketOption(cli.System.Net.Sockets.Socket netSocket, int opt, Object iaContainerObj) throws SocketException + { + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + switch (opt) + { + case SocketOptions.SO_REUSEADDR: + return CIL.unbox_int(netSocket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReuseAddress))) == 0 ? -1 : 1; + case SocketOptions.SO_SNDBUF: + return CIL.unbox_int(netSocket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.SendBuffer))); + case SocketOptions.SO_RCVBUF: + return CIL.unbox_int(netSocket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReceiveBuffer))); + case SocketOptions.IP_TOS: + // TODO handle IPv6 here + return CIL.unbox_int(netSocket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.TypeOfService))); + case SocketOptions.SO_BINDADDR: + ((InetAddressContainer)iaContainerObj).addr = getInetAddressFromIPEndPoint((IPEndPoint)netSocket.get_LocalEndPoint()); + return 0; + default: + throw new SocketException("Invalid socket option: " + opt); + } + } + catch (cli.System.Net.Sockets.SocketException x) + { + throw new SocketException(x.getMessage()); + } + catch (cli.System.ObjectDisposedException x1) + { + throw new SocketException("Socket is closed"); + } + } +} diff --git a/openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java b/openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java new file mode 100644 index 0000000..d5467e5 --- /dev/null +++ b/openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2007, 2013, 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 java.net; + +import java.io.IOException; +import java.io.FileDescriptor; +import sun.net.ResourceManager; + +/** + * This class defines the plain DatagramSocketImpl that is used for all + * Windows versions lower than Vista. It adds support for IPv6 on + * these platforms where available. + * + * For backward compatibility windows platforms that do not have IPv6 + * support also use this implementation, and fd1 gets set to null + * during socket creation. + * + * @author Chris Hegarty + */ + +class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl +{ + /* Used for IPv6 on Windows only */ + FileDescriptor fd1; + + /* + * Needed for ipv6 on windows because we need to know + * if the socket was bound to ::0 or 0.0.0.0, when a caller + * asks for it. In this case, both sockets are used, but we + * don't know whether the caller requested ::0 or 0.0.0.0 + * and need to remember it here. + */ + private InetAddress anyLocalBoundAddr=null; + + cli.System.Net.Sockets.Socket fduse=null; /* saved between peek() and receive() calls */ + + /* saved between successive calls to receive, if data is detected + * on both sockets at same time. To ensure that one socket is not + * starved, they rotate using this field + */ + cli.System.Net.Sockets.Socket lastfd=null; + + // true if this socket is exclusively bound + private final boolean exclusiveBind; + + /* + * Set to true if SO_REUSEADDR is set after the socket is bound to + * indicate SO_REUSEADDR is being emulated + */ + private boolean reuseAddressEmulated; + + // emulates SO_REUSEADDR when exclusiveBind is true and socket is bound + private boolean isReuseAddress; + + TwoStacksPlainDatagramSocketImpl(boolean exclBind) { + exclusiveBind = exclBind; + } + + protected synchronized void create() throws SocketException { + fd1 = new FileDescriptor(); + try { + super.create(); + } catch (SocketException e) { + fd1 = null; + throw e; + } + } + + protected synchronized void bind(int lport, InetAddress laddr) + throws SocketException { + super.bind(lport, laddr); + if (laddr.isAnyLocalAddress()) { + anyLocalBoundAddr = laddr; + } + } + + @Override + protected synchronized void bind0(int lport, InetAddress laddr) + throws SocketException + { + bind0(lport, laddr, exclusiveBind); + + } + + protected synchronized void receive(DatagramPacket p) + throws IOException { + try { + receive0(p); + } finally { + fduse = null; + } + } + + public Object getOption(int optID) throws SocketException { + if (isClosed()) { + throw new SocketException("Socket Closed"); + } + + if (optID == SO_BINDADDR) { + if ((fd != null && fd1 != null) && !connected) { + return anyLocalBoundAddr; + } + int family = connectedAddress == null ? -1 : connectedAddress.holder().getFamily(); + return socketLocalAddress(family); + } else if (optID == SO_REUSEADDR && reuseAddressEmulated) { + return isReuseAddress; + } else { + return super.getOption(optID); + } + } + + protected void socketSetOption(int opt, Object val) + throws SocketException + { + if (opt == SO_REUSEADDR && exclusiveBind && localPort != 0) { + // socket already bound, emulate + reuseAddressEmulated = true; + isReuseAddress = (Boolean)val; + } else { + socketNativeSetOption(opt, val); + } + + } + + protected boolean isClosed() { + return (fd == null && fd1 == null) ? true : false; + } + + protected void close() { + if (fd != null || fd1 != null) { + datagramSocketClose(); + ResourceManager.afterUdpClose(); + fd = null; + fd1 = null; + } + } + + /* Native methods */ + + protected synchronized void bind0(int lport, InetAddress laddr, + boolean exclBind) throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainDatagramSocketImpl_c.bind0(env, this, lport, laddr, exclBind); + env.ThrowPendingException(); + } + + protected void send(DatagramPacket packet) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainDatagramSocketImpl_c.send(env, this, packet); + env.ThrowPendingException(); + } + + protected synchronized int peek(InetAddress addressObj) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + int ret = TwoStacksPlainDatagramSocketImpl_c.peek(env, this, addressObj); + env.ThrowPendingException(); + return ret; + } + + protected synchronized int peekData(DatagramPacket p) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + int ret = TwoStacksPlainDatagramSocketImpl_c.peekData(env, this, p); + env.ThrowPendingException(); + return ret; + } + + protected synchronized void receive0(DatagramPacket packet) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainDatagramSocketImpl_c.receive0(env, this, packet); + env.ThrowPendingException(); + } + + protected void setTimeToLive(int ttl) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainDatagramSocketImpl_c.setTimeToLive(env, this, ttl); + env.ThrowPendingException(); + } + + protected int getTimeToLive() throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + int ret = TwoStacksPlainDatagramSocketImpl_c.getTimeToLive(env, this); + env.ThrowPendingException(); + return ret; + } + + protected void setTTL(byte ttl) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainDatagramSocketImpl_c.setTTL(env, this, ttl); + env.ThrowPendingException(); + } + + protected byte getTTL() throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + byte ret = TwoStacksPlainDatagramSocketImpl_c.getTTL(env, this); + env.ThrowPendingException(); + return ret; + } + + protected void join(InetAddress inetaddr, NetworkInterface netIf) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainDatagramSocketImpl_c.join(env, this, inetaddr, netIf); + env.ThrowPendingException(); + } + + protected void leave(InetAddress inetaddr, NetworkInterface netIf) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainDatagramSocketImpl_c.leave(env, this, inetaddr, netIf); + env.ThrowPendingException(); + } + + protected void datagramSocketCreate() throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainDatagramSocketImpl_c.datagramSocketCreate(env, this); + env.ThrowPendingException(); + } + + protected void datagramSocketClose() { + TwoStacksPlainDatagramSocketImpl_c.datagramSocketClose(this); + } + + protected void socketNativeSetOption(int opt, Object val) throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainDatagramSocketImpl_c.socketNativeSetOption(env, this, opt, val); + env.ThrowPendingException(); + } + + protected Object socketGetOption(int opt) throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + Object ret = TwoStacksPlainDatagramSocketImpl_c.socketGetOption(env, this, opt); + env.ThrowPendingException(); + return ret; + } + + protected void connect0(InetAddress address, int port) throws SocketException { + if (ikvm.internal.Util.MONO) { + // MONOBUG Mono doesn't allow Socket.Connect(IPAddress.Any, 0) to disconnect a datagram socket, + // so we throw a SocketException, this will cause DatagramSocket to emulate connectedness + throw new SocketException("connected datagram sockets not supported on Mono"); + } + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainDatagramSocketImpl_c.connect0(env, this, address, port); + env.ThrowPendingException(); + } + + protected Object socketLocalAddress(int family) throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + Object ret = TwoStacksPlainDatagramSocketImpl_c.socketLocalAddress(env, this, family); + env.ThrowPendingException(); + return ret; + } + + protected void disconnect0(int family) { + TwoStacksPlainDatagramSocketImpl_c.disconnect0(this, family); + } +} diff --git a/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java b/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java new file mode 100644 index 0000000..1b44cce --- /dev/null +++ b/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java @@ -0,0 +1,2466 @@ +/* + * Copyright (c) 1997, 2013, 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 java.net; + +import java.io.FileDescriptor; +import static ikvm.internal.JNI.*; +import static ikvm.internal.Winsock.*; +import static java.net.net_util_md.*; +import static java.net.InetAddress.IPv4; +import static java.net.InetAddress.IPv6; + +final class TwoStacksPlainDatagramSocketImpl_c +{ +static final int ni_class = 0; +static final int JVM_IO_ERR = -1; +static final int JVM_IO_INTR = -2; + +static final int java_net_SocketOptions_SO_BINDADDR = SocketOptions.SO_BINDADDR; +static final int java_net_SocketOptions_SO_SNDBUF = SocketOptions.SO_SNDBUF; +static final int java_net_SocketOptions_SO_RCVBUF = SocketOptions.SO_RCVBUF; +static final int java_net_SocketOptions_IP_TOS = SocketOptions.IP_TOS; +static final int java_net_SocketOptions_SO_REUSEADDR = SocketOptions.SO_REUSEADDR; +static final int java_net_SocketOptions_SO_BROADCAST = SocketOptions.SO_BROADCAST; +static final int java_net_SocketOptions_IP_MULTICAST_LOOP = SocketOptions.IP_MULTICAST_LOOP; +static final int java_net_SocketOptions_IP_MULTICAST_IF = SocketOptions.IP_MULTICAST_IF; +static final int java_net_SocketOptions_IP_MULTICAST_IF2 = SocketOptions.IP_MULTICAST_IF2; + +/* + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef IPTOS_TOS_MASK +#define IPTOS_TOS_MASK 0x1e +#endif +#ifndef IPTOS_PREC_MASK +#define IPTOS_PREC_MASK 0xe0 +#endif + +#include "java_net_TwoStacksPlainDatagramSocketImpl.h" +#include "java_net_SocketOptions.h" +#include "java_net_NetworkInterface.h" + +#include "NetworkInterface.h" +#include "jvm.h" +#include "jni_util.h" +#include "net_util.h" + +#define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000) +#define IN_MULTICAST(i) IN_CLASSD(i) + +*/ + +static boolean IN_MULTICAST(int ipv4address) { + return ((ipv4address >> 24) & 0xf0) == 0xe0; +} + +/************************************************************************ + * TwoStacksPlainDatagramSocketImpl + */ + +/* +static jfieldID IO_fd_fdID; +static jfieldID pdsi_trafficClassID; +jfieldID pdsi_fdID; +jfieldID pdsi_fd1ID; +jfieldID pdsi_fduseID; +jfieldID pdsi_lastfdID; +jfieldID pdsi_timeoutID; + +jfieldID pdsi_localPortID; +jfieldID pdsi_connected; + +static jclass ia4_clazz; +static jmethodID ia4_ctor; + +static CRITICAL_SECTION sizeCheckLock; +*/ + +/* Windows OS version is XP or better */ +static final boolean xp_or_later = true; +/* Windows OS version is Windows 2000 or better */ +//static int w2k_or_later = 0; + +/* + * Notes about UDP/IPV6 on Windows (XP and 2003 server): + * + * fd always points to the IPv4 fd, and fd1 points to the IPv6 fd. + * Both fds are used when we bind to a wild-card address. When a specific + * address is used, only one of them is used. + */ + +/* + * Returns a java.lang.Integer based on 'i' + */ +/* +jobject createInteger(JNIEnv *env, int i) { + static jclass i_class; + static jmethodID i_ctrID; + static jfieldID i_valueID; + + if (i_class == NULL) { + jclass c = (*env)->FindClass(env, "java/lang/Integer"); + CHECK_NULL_RETURN(c, NULL); + i_ctrID = (*env)->GetMethodID(env, c, "", "(I)V"); + CHECK_NULL_RETURN(i_ctrID, NULL); + i_class = (*env)->NewGlobalRef(env, c); + CHECK_NULL_RETURN(i_class, NULL); + } + + return ( (*env)->NewObject(env, i_class, i_ctrID, i) ); +} +*/ + +/* + * Returns a java.lang.Boolean based on 'b' + */ +/* +jobject createBoolean(JNIEnv *env, int b) { + static jclass b_class; + static jmethodID b_ctrID; + static jfieldID b_valueID; + + if (b_class == NULL) { + jclass c = (*env)->FindClass(env, "java/lang/Boolean"); + CHECK_NULL_RETURN(c, NULL); + b_ctrID = (*env)->GetMethodID(env, c, "", "(Z)V"); + CHECK_NULL_RETURN(b_ctrID, NULL); + b_class = (*env)->NewGlobalRef(env, c); + CHECK_NULL_RETURN(b_class, NULL); + } + + return( (*env)->NewObject(env, b_class, b_ctrID, (jboolean)(b!=0)) ); +} +*/ + + +static cli.System.Net.Sockets.Socket getFD(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this) { + FileDescriptor fdObj = _this.fd; + + if (fdObj == NULL) { + return null; + } + return fdObj.getSocket(); +} + +static cli.System.Net.Sockets.Socket getFD1(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this) { + FileDescriptor fdObj = _this.fd1; + + if (fdObj == NULL) { + return null; + } + return fdObj.getSocket(); +} + +/* + * This function returns JNI_TRUE if the datagram size exceeds the underlying + * provider's ability to send to the target address. The following OS + * oddities have been observed :- + * + * 1. On Windows 95/98 if we try to send a datagram > 12k to an application + * on the same machine then the send will fail silently. + * + * 2. On Windows ME if we try to send a datagram > supported by underlying + * provider then send will not return an error. + * + * 3. On Windows NT/2000 if we exceeds the maximum size then send will fail + * with WSAEADDRNOTAVAIL. + * + * 4. On Windows 95/98 if we exceed the maximum size when sending to + * another machine then WSAEINVAL is returned. + * + */ +/* +jboolean exceedSizeLimit(JNIEnv *env, jint fd, jint addr, jint size) +{ +#define DEFAULT_MSG_SIZE 65527 + static jboolean initDone; + static jboolean is95or98; + static int maxmsg; + + typedef struct _netaddr { /* Windows 95/98 only *-/ + unsigned long addr; + struct _netaddr *next; + } netaddr; + static netaddr *addrList; + netaddr *curr; + + /* + * First time we are called we must determine which OS this is and also + * get the maximum size supported by the underlying provider. + * + * In addition on 95/98 we must enumerate our IP addresses. + *-/ + if (!initDone) { + EnterCriticalSection(&sizeCheckLock); + + if (initDone) { + /* another thread got there first *-/ + LeaveCriticalSection(&sizeCheckLock); + + } else { + OSVERSIONINFO ver; + int len; + + /* + * Step 1: Determine which OS this is. + *-/ + ver.dwOSVersionInfoSize = sizeof(ver); + GetVersionEx(&ver); + + is95or98 = JNI_FALSE; + if (ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && + ver.dwMajorVersion == 4 && + (ver.dwMinorVersion == 0 || ver.dwMinorVersion == 10)) { + + is95or98 = JNI_TRUE; + } + + /* + * Step 2: Determine the maximum datagram supported by the + * underlying provider. On Windows 95 if winsock hasn't been + * upgraded (ie: unsupported configuration) then we assume + * the default 64k limit. + *-/ + len = sizeof(maxmsg); + if (NET_GetSockOpt(fd, SOL_SOCKET, SO_MAX_MSG_SIZE, (char *)&maxmsg, &len) < 0) { + maxmsg = DEFAULT_MSG_SIZE; + } + + /* + * Step 3: On Windows 95/98 then enumerate the IP addresses on + * this machine. This is neccesary because we need to check if the + * datagram is being sent to an application on the same machine. + *-/ + if (is95or98) { + char hostname[255]; + struct hostent *hp; + + if (gethostname(hostname, sizeof(hostname)) == -1) { + LeaveCriticalSection(&sizeCheckLock); + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Unable to obtain hostname"); + return JNI_TRUE; + } + hp = (struct hostent *)gethostbyname(hostname); + if (hp != NULL) { + struct in_addr **addrp = (struct in_addr **) hp->h_addr_list; + + while (*addrp != (struct in_addr *) 0) { + curr = (netaddr *)malloc(sizeof(netaddr)); + if (curr == NULL) { + while (addrList != NULL) { + curr = addrList->next; + free(addrList); + addrList = curr; + } + LeaveCriticalSection(&sizeCheckLock); + JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); + return JNI_TRUE; + } + curr->addr = htonl((*addrp)->S_un.S_addr); + curr->next = addrList; + addrList = curr; + addrp++; + } + } + } + + /* + * Step 4: initialization is done so set flag and unlock cs + *-/ + initDone = JNI_TRUE; + LeaveCriticalSection(&sizeCheckLock); + } + } + + /* + * Now examine the size of the datagram :- + * + * (a) If exceeds size of service provider return 'false' to indicate that + * we exceed the limit. + * (b) If not 95/98 then return 'true' to indicate that the size is okay. + * (c) On 95/98 if the size is <12k we are okay. + * (d) On 95/98 if size > 12k then check if the destination is the current + * machine. + *-/ + if (size > maxmsg) { /* step (a) *-/ + return JNI_TRUE; + } + if (!is95or98) { /* step (b) *-/ + return JNI_FALSE; + } + if (size <= 12280) { /* step (c) *-/ + return JNI_FALSE; + } + + /* step (d) *-/ + + if ((addr & 0x7f000000) == 0x7f000000) { + return JNI_TRUE; + } + curr = addrList; + while (curr != NULL) { + if (curr->addr == addr) { + return JNI_TRUE; + } + curr = curr->next; + } + return JNI_FALSE; +} +*/ + +/* + * Return JNI_TRUE if this Windows edition supports ICMP Port Unreachable + */ +static boolean supportPortUnreachable() { + // we don't support anything pre-Win2K anyway + return true; +} + +/* + * This function "purges" all outstanding ICMP port unreachable packets + * outstanding on a socket and returns JNI_TRUE if any ICMP messages + * have been purged. The rational for purging is to emulate normal BSD + * behaviour whereby receiving a "connection reset" status resets the + * socket. + */ +static boolean purgeOutstandingICMP(cli.System.Net.Sockets.Socket fd) +{ + boolean got_icmp = false; + byte[] buf = new byte[1]; + fd_set tbl = new fd_set(); + timeval t = new timeval(); + SOCKETADDRESS rmtaddr = null; + + /* + * A no-op if this OS doesn't support it. + */ + if (!supportPortUnreachable()) { + return JNI_FALSE; + } + + /* + * Peek at the queue to see if there is an ICMP port unreachable. If there + * is then receive it. + */ + FD_ZERO(tbl); + FD_SET(fd, tbl); + while(true) { + if (select(tbl, null, null, t) <= 0) { + break; + } + if (recvfrom(fd, buf, 1, MSG_PEEK, + rmtaddr) != JVM_IO_ERR) { + break; + } + if (WSAGetLastError() != WSAECONNRESET) { + /* some other error - we don't care here */ + break; + } + + recvfrom(fd, buf, 1, 0, rmtaddr); + got_icmp = JNI_TRUE; + } + + return got_icmp; +} + + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: init + * Signature: ()V + */ +/* +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) { + + OSVERSIONINFO ver; + int version; + ver.dwOSVersionInfoSize = sizeof(ver); + GetVersionEx(&ver); + + version = ver.dwMajorVersion * 10 + ver.dwMinorVersion; + xp_or_later = (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (version >= 51); + w2k_or_later = (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (version >= 50); + + /* get fieldIDs *-/ + pdsi_fdID = (*env)->GetFieldID(env, cls, "fd", "Ljava/io/FileDescriptor;"); + CHECK_NULL(pdsi_fdID); + pdsi_fd1ID = (*env)->GetFieldID(env, cls, "fd1", "Ljava/io/FileDescriptor;"); + CHECK_NULL(pdsi_fd1ID); + pdsi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I"); + CHECK_NULL(pdsi_timeoutID); + pdsi_fduseID = (*env)->GetFieldID(env, cls, "fduse", "I"); + CHECK_NULL(pdsi_fduseID); + pdsi_lastfdID = (*env)->GetFieldID(env, cls, "lastfd", "I"); + CHECK_NULL(pdsi_lastfdID); + pdsi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I"); + CHECK_NULL(pdsi_trafficClassID); + pdsi_localPortID = (*env)->GetFieldID(env, cls, "localPort", "I"); + CHECK_NULL(pdsi_localPortID); + pdsi_connected = (*env)->GetFieldID(env, cls, "connected", "Z"); + CHECK_NULL(pdsi_connected); + + cls = (*env)->FindClass(env, "java/io/FileDescriptor"); + CHECK_NULL(cls); + IO_fd_fdID = NET_GetFileDescriptorID(env); + CHECK_NULL(IO_fd_fdID); + + ia4_clazz = (*env)->FindClass(env, "java/net/Inet4Address"); + CHECK_NULL(ia4_clazz); + ia4_clazz = (*env)->NewGlobalRef(env, ia4_clazz); + CHECK_NULL(ia4_clazz); + ia4_ctor = (*env)->GetMethodID(env, ia4_clazz, "", "()V"); + CHECK_NULL(ia4_ctor); + + + InitializeCriticalSection(&sizeCheckLock); +} +*/ + +static void bind0(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, + int port, InetAddress addressObj, + boolean exclBind) { + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + int family; + boolean ipv6_supported = ipv6_available(); + + SOCKETADDRESS lcladdr; + lcladdr = new SOCKETADDRESS(); + + family = getInetAddress_family(env, addressObj); + if (family == IPv6 && !ipv6_supported) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Protocol family not supported"); + return; + } + + if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); + return; + } else { + fd = fdObj.getSocket(); + if (ipv6_supported) { + fd1 = fd1Obj.getSocket(); + } + } + if (IS_NULL(addressObj)) { + JNU_ThrowNullPointerException(env, "argument address"); + return; + } + + if (NET_InetAddressToSockaddr(env, addressObj, port, lcladdr, JNI_FALSE) != 0) { + return; + } + + if (ipv6_supported) { + ipv6bind v6bind = new ipv6bind(); + v6bind.addr = lcladdr; + v6bind.ipv4_fd = fd; + v6bind.ipv6_fd = fd1; + if (NET_BindV6(v6bind, exclBind) != -1) { + /* check if the fds have changed */ + if (v6bind.ipv4_fd != fd) { + fd = v6bind.ipv4_fd; + if (fd == null) { + /* socket is closed. */ + _this.fd = null; + } else { + /* socket was re-created */ + fdObj.setSocket(fd); + } + } + if (v6bind.ipv6_fd != fd1) { + fd1 = v6bind.ipv6_fd; + if (fd1 == null) { + /* socket is closed. */ + _this.fd1 = null; + } else { + /* socket was re-created */ + fd1Obj.setSocket(fd1); + } + } + } else { + /* NET_BindV6() closes both sockets upon a failure */ + _this.fd = null; + _this.fd1 = null; + NET_ThrowCurrent (env, "Cannot bind"); + return; + } + } else { + if (NET_WinBind(fd, lcladdr, exclBind) == -1) { + if (WSAGetLastError() == WSAEACCES) { + WSASetLastError(WSAEADDRINUSE); + } + NET_ThrowCurrent(env, "Cannot bind"); + return; + } + } + + if (port == 0) { + if (fd == null) { + /* must be an IPV6 only socket. */ + fd = fd1; + } + if (getsockname(fd, lcladdr) == -1) { + NET_ThrowCurrent(env, "JVM_GetSockName"); + return; + } + port = ntohs(GET_PORT (lcladdr)); + } + _this.localPort = port; +} + + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: connect0 + * Signature: (Ljava/net/InetAddress;I)V + */ + +static void connect0(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, InetAddress address, int port) { + /* The object's field */ + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + /* The fdObj'fd */ + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + cli.System.Net.Sockets.Socket fdc; + /* The packetAddress address, family and port */ + int addr, family; + SOCKETADDRESS rmtaddr; + rmtaddr = new SOCKETADDRESS(); + boolean ipv6_supported = ipv6_available(); + + if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Socket closed"); + return; + } + if (!IS_NULL(fdObj)) { + fd = fdObj.getSocket(); + } + if (!IS_NULL(fd1Obj)) { + fd1 = fd1Obj.getSocket(); + } + + if (IS_NULL(address)) { + JNU_ThrowNullPointerException(env, "address"); + return; + } + + addr = getInetAddress_addr(env, address); + + family = getInetAddress_family(env, address); + if (family == IPv6 && !ipv6_supported) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Protocol family not supported"); + return; + } + + fdc = family == IPv4? fd: fd1; + + if (xp_or_later) { + /* SIO_UDP_CONNRESET fixes a bug introduced in Windows 2000, which + * returns connection reset errors on connected UDP sockets (as well + * as connected sockets). The solution is to only enable this feature + * when the socket is connected + */ + WSAIoctl(fdc, SIO_UDP_CONNRESET, true); + } + + if (NET_InetAddressToSockaddr(env, address, port, rmtaddr, JNI_FALSE) != 0) { + return; + } + + if (connect(fdc, rmtaddr) == -1) { + NET_ThrowCurrent(env, "connect"); + return; + } +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: disconnect0 + * Signature: ()V + */ + +static void disconnect0(TwoStacksPlainDatagramSocketImpl _this, int family) { + /* The object's field */ + FileDescriptor fdObj; + /* The fdObj'fd */ + cli.System.Net.Sockets.Socket fd; + SOCKETADDRESS addr; + addr = new SOCKETADDRESS(); + + if (family == IPv4) { + fdObj = _this.fd; + } else { + fdObj = _this.fd1; + } + + if (IS_NULL(fdObj)) { + /* disconnect doesn't throw any exceptions */ + return; + } + fd = fdObj.getSocket(); + + connect(fd, addr); + + /* + * use SIO_UDP_CONNRESET + * to disable ICMP port unreachable handling here. + */ + if (xp_or_later) { + WSAIoctl(fd,SIO_UDP_CONNRESET,false); + } +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: send + * Signature: (Ljava/net/DatagramPacket;)V + */ +static void send(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, DatagramPacket packet) { + FileDescriptor fdObj; + cli.System.Net.Sockets.Socket fd; + + InetAddress iaObj; + int address; + int family; + + int packetBufferOffset, packetBufferLen, packetPort; + byte[] packetBuffer; + boolean connected; + + SOCKETADDRESS rmtaddr; + rmtaddr = new SOCKETADDRESS(); + + if (IS_NULL(packet)) { + JNU_ThrowNullPointerException(env, "null packet"); + return; + } + + iaObj = packet.address; + + packetPort = packet.port; + packetBufferOffset = packet.offset; + packetBuffer = packet.buf; + connected = _this.connected; + + if (IS_NULL(iaObj) || IS_NULL(packetBuffer)) { + JNU_ThrowNullPointerException(env, "null address || null buffer"); + return; + } + + family = getInetAddress_family(env, iaObj); + if (family == IPv4) { + fdObj = _this.fd; + } else { + if (!ipv6_available()) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Protocol not allowed"); + return; + } + fdObj = _this.fd1; + } + + if (IS_NULL(fdObj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Socket closed"); + return; + } + fd = fdObj.getSocket(); + + packetBufferLen = packet.length; + /* Note: the buffer needn't be greater than 65,536 (0xFFFF)... + * the maximum size of an IP packet. Anything bigger is truncated anyway. + */ + if (packetBufferLen > MAX_PACKET_LEN) { + packetBufferLen = MAX_PACKET_LEN; + } + + if (connected) { + rmtaddr = null; + } else { + if (NET_InetAddressToSockaddr(env, iaObj, packetPort, rmtaddr, JNI_FALSE) != 0) { + return; + } + } + + /* + if (packetBufferLen > MAX_BUFFER_LEN) { + + /* + * On 95/98 if we try to send a datagram >12k to an application + * on the same machine then this will fail silently. Thus we + * catch this situation here so that we can throw an exception + * when this arises. + * On ME if we try to send a datagram with a size greater than + * that supported by the service provider then no error is + * returned. + *-/ + if (!w2k_or_later) { /* avoid this check on Win 2K or better. Does not work with IPv6. + * Check is not necessary on these OSes *-/ + if (connected) { + address = getInetAddress_addr(env, iaObj); + } else { + address = ntohl(rmtaddr.him4.sin_addr.s_addr); + } + + if (exceedSizeLimit(env, fd, address, packetBufferLen)) { + if (!((*env)->ExceptionOccurred(env))) { + NET_ThrowNew(env, WSAEMSGSIZE, "Datagram send failed"); + } + return; + } + } + + /* When JNI-ifying the JDK's IO routines, we turned + * reads and writes of byte arrays of size greater + * than 2048 bytes into several operations of size 2048. + * This saves a malloc()/memcpy()/free() for big + * buffers. This is OK for file IO and TCP, but that + * strategy violates the semantics of a datagram protocol. + * (one big send) != (several smaller sends). So here + * we *must* alloc the buffer. Note it needn't be bigger + * than 65,536 (0xFFFF) the max size of an IP packet. + * anything bigger is truncated anyway. + *-/ + fullPacket = (char *)malloc(packetBufferLen); + if (!fullPacket) { + JNU_ThrowOutOfMemoryError(env, "Send buf native heap allocation failed"); + return; + } + } else { + fullPacket = &(BUF[0]); + } + */ + + switch (sendto(fd, packetBuffer, packetBufferOffset, packetBufferLen, 0, rmtaddr)) { + case JVM_IO_ERR: + NET_ThrowCurrent(env, "Datagram send failed"); + break; + + case JVM_IO_INTR: + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", + "operation interrupted"); + } +} + +/* + * check which socket was last serviced when there was data on both sockets. + * Only call this if sure that there is data on both sockets. + */ +private static cli.System.Net.Sockets.Socket checkLastFD (TwoStacksPlainDatagramSocketImpl _this, cli.System.Net.Sockets.Socket fd, cli.System.Net.Sockets.Socket fd1) { + cli.System.Net.Sockets.Socket nextfd, lastfd = _this.lastfd; + if (lastfd == null) { + /* arbitrary. Choose fd */ + _this.lastfd = fd; + return fd; + } else { + if (lastfd == fd) { + nextfd = fd1; + } else { + nextfd = fd; + } + _this.lastfd = nextfd; + return nextfd; + } +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: peek + * Signature: (Ljava/net/InetAddress;)I + */ +static int peek(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, InetAddress addressObj) { + FileDescriptor fdObj = _this.fd; + int timeout = _this.timeout; + cli.System.Net.Sockets.Socket fd; + + /* The address and family fields of addressObj */ + int address, family; + + int n; + SOCKETADDRESS remote_addr = new SOCKETADDRESS(); + byte[] buf = new byte[1]; + boolean retry; + long prevTime = 0; + + if (IS_NULL(fdObj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); + return -1; + } else { + fd = fdObj.getSocket(); + if (fd == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "socket closed"); + return -1; + } + } + if (IS_NULL(addressObj)) { + JNU_ThrowNullPointerException(env, "Null address in peek()"); + return -1; + } else { + address = getInetAddress_addr(env, addressObj); + /* We only handle IPv4 for now. Will support IPv6 once its in the os */ + family = AF_INET; + } + + do { + retry = FALSE; + + /* + * If a timeout has been specified then we select on the socket + * waiting for a read event or a timeout. + */ + if (timeout != 0) { + int ret; + prevTime = JVM_CurrentTimeMillis(env, 0); + ret = NET_Timeout (fd, timeout); + if (ret == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", + "Peek timed out"); + return ret; + } else if (ret == JVM_IO_ERR) { + NET_ThrowCurrent(env, "timeout in datagram socket peek"); + return ret; + } else if (ret == JVM_IO_INTR) { + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", + "operation interrupted"); + return ret; + } + } + + /* now try the peek */ + n = recvfrom(fd, buf, 1, MSG_PEEK, + remote_addr); + + if (n == JVM_IO_ERR) { + if (WSAGetLastError() == WSAECONNRESET) { + boolean connected; + + /* + * An icmp port unreachable - we must receive this as Windows + * does not reset the state of the socket until this has been + * received. + */ + purgeOutstandingICMP(fd); + + connected = _this.connected; + if (connected) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"PortUnreachableException", + "ICMP Port Unreachable"); + return 0; + } + + /* + * If a timeout was specified then we need to adjust it because + * we may have used up some of the timeout befor the icmp port + * unreachable arrived. + */ + if (timeout != 0) { + long newTime = JVM_CurrentTimeMillis(env, 0); + timeout -= (newTime - prevTime); + if (timeout <= 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", + "Receive timed out"); + return 0; + } + prevTime = newTime; + } + + /* Need to retry the recv */ + retry = TRUE; + } + } + } while (retry); + + if (n == JVM_IO_ERR && WSAGetLastError() != WSAEMSGSIZE) { + NET_ThrowCurrent(env, "Datagram peek failed"); + return 0; + } + if (n == JVM_IO_INTR) { + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", null); + return 0; + } + addressObj.holder().address = ntohl(remote_addr.sin_addr.s_addr); + addressObj.holder().family = IPv4; + + /* return port */ + return ntohs(remote_addr.sin_port); +} + +static int peekData(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, DatagramPacket packet) { + + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + int timeout = _this.timeout; + + byte[] packetBuffer; + int packetBufferOffset, packetBufferLen; + + cli.System.Net.Sockets.Socket fd = null, fd1 = null, fduse = null; + int nsockets=0, errorCode; + int port; + byte[] data; + + boolean checkBoth = false; + int datalen; + int n; + SOCKETADDRESS remote_addr; + remote_addr = new SOCKETADDRESS(); + boolean retry; + long prevTime = 0; + + if (!IS_NULL(fdObj)) { + fd = fdObj.getSocket(); + if (fd == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "socket closed"); + return -1; + } + nsockets = 1; + } + + if (!IS_NULL(fd1Obj)) { + fd1 = fd1Obj.getSocket(); + if (fd1 == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "socket closed"); + return -1; + } + nsockets ++; + } + + switch (nsockets) { + case 0: + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "socket closed"); + return -1; + case 1: + if (!IS_NULL(fdObj)) { + fduse = fd; + } else { + fduse = fd1; + } + break; + case 2: + checkBoth = TRUE; + break; + } + + if (IS_NULL(packet)) { + JNU_ThrowNullPointerException(env, "packet"); + return -1; + } + + packetBuffer = packet.buf; + + if (IS_NULL(packetBuffer)) { + JNU_ThrowNullPointerException(env, "packet buffer"); + return -1; + } + + packetBufferOffset = packet.offset; + packetBufferLen = packet.bufLength; + + /* + if (packetBufferLen > MAX_BUFFER_LEN) { + + /* When JNI-ifying the JDK's IO routines, we turned + * read's and write's of byte arrays of size greater + * than 2048 bytes into several operations of size 2048. + * This saves a malloc()/memcpy()/free() for big + * buffers. This is OK for file IO and TCP, but that + * strategy violates the semantics of a datagram protocol. + * (one big send) != (several smaller sends). So here + * we *must* alloc the buffer. Note it needn't be bigger + * than 65,536 (0xFFFF) the max size of an IP packet. + * anything bigger is truncated anyway. + *-/ + fullPacket = (char *)malloc(packetBufferLen); + if (!fullPacket) { + JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); + return -1; + } + } else { + fullPacket = &(BUF[0]); + } + */ + + do { + int ret; + retry = FALSE; + + /* + * If a timeout has been specified then we select on the socket + * waiting for a read event or a timeout. + */ + if (checkBoth) { + int t = timeout == 0 ? -1: timeout; + prevTime = JVM_CurrentTimeMillis(env, 0); + cli.System.Net.Sockets.Socket[] tmp = new cli.System.Net.Sockets.Socket[] { fduse }; + ret = NET_Timeout2 (fd, fd1, t, tmp); + fduse = tmp[0]; + /* all subsequent calls to recv() or select() will use the same fd + * for this call to peek() */ + if (ret <= 0) { + if (ret == 0) { + JNU_ThrowByName(env,JNU_JAVANETPKG+"SocketTimeoutException", + "Peek timed out"); + } else if (ret == JVM_IO_ERR) { + NET_ThrowCurrent(env, "timeout in datagram socket peek"); + } else if (ret == JVM_IO_INTR) { + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", + "operation interrupted"); + } + return -1; + } + if (ret == 2) { + fduse = checkLastFD (_this, fd, fd1); + } + checkBoth = FALSE; + } else if (timeout != 0) { + if (prevTime == 0) { + prevTime = JVM_CurrentTimeMillis(env, 0); + } + ret = NET_Timeout (fduse, timeout); + if (ret <= 0) { + if (ret == 0) { + JNU_ThrowByName(env,JNU_JAVANETPKG+"SocketTimeoutException", + "Receive timed out"); + } else if (ret == JVM_IO_ERR) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Socket closed"); + } else if (ret == JVM_IO_INTR) { + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", + "operation interrupted"); + } + return -1; + } + } + + /* receive the packet */ + n = recvfrom(fduse, packetBuffer, packetBufferOffset, packetBufferLen, MSG_PEEK, remote_addr); + port = ntohs (GET_PORT(remote_addr)); + if (n == JVM_IO_ERR) { + if (WSAGetLastError() == WSAECONNRESET) { + boolean connected; + + /* + * An icmp port unreachable - we must receive this as Windows + * does not reset the state of the socket until this has been + * received. + */ + purgeOutstandingICMP(fduse); + + connected = _this.connected; + if (connected) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"PortUnreachableException", + "ICMP Port Unreachable"); + + return -1; + } + + /* + * If a timeout was specified then we need to adjust it because + * we may have used up some of the timeout befor the icmp port + * unreachable arrived. + */ + if (timeout != 0) { + long newTime = JVM_CurrentTimeMillis(env, 0); + timeout -= (newTime - prevTime); + if (timeout <= 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", + "Receive timed out"); + return -1; + } + prevTime = newTime; + } + retry = TRUE; + } + } + } while (retry); + + if (n < 0) { + errorCode = WSAGetLastError(); + /* check to see if it's because the buffer was too small */ + if (errorCode == WSAEMSGSIZE) { + /* it is because the buffer is too small. It's UDP, it's + * unreliable, it's all good. discard the rest of the + * data.. + */ + n = packetBufferLen; + } else { + /* failure */ + packet.length = 0; + } + } + if (n == -1) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); + } else if (n == -2) { + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", + "operation interrupted"); + } else if (n < 0) { + NET_ThrowCurrent(env, "Datagram receive failed"); + } else { + InetAddress packetAddress; + + /* + * Check if there is an InetAddress already associated with this + * packet. If so we check if it is the same source address. We + * can't update any existing InetAddress because it is immutable + */ + packetAddress = packet.address; + if (packetAddress != NULL) { + if (!NET_SockaddrEqualsInetAddress(remote_addr, packetAddress)) { + /* force a new InetAddress to be created */ + packetAddress = null; + } + } + if (packetAddress == NULL) { + int[] tmp = { port }; + packetAddress = NET_SockaddrToInetAddress(remote_addr, tmp); + port = tmp[0]; + /* stuff the new Inetaddress in the packet */ + packet.address = packetAddress; + } + + /* populate the packet */ + packet.port = port; + packet.length = n; + } + + /* make sure receive() picks up the right fd */ + _this.fduse = fduse; + + return port; +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: receive + * Signature: (Ljava/net/DatagramPacket;)V + */ +static void receive0(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, DatagramPacket packet) { + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + int timeout = _this.timeout; + byte[] packetBuffer; + int packetBufferOffset, packetBufferLen; + boolean ipv6_supported = ipv6_available(); + + /* as a result of the changes for ipv6, peek() or peekData() + * must be called prior to receive() so that fduse can be set. + */ + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + cli.System.Net.Sockets.Socket fduse = null; + int errorCode; + + int n, nsockets=0; + SOCKETADDRESS remote_addr; + remote_addr = new SOCKETADDRESS(); + boolean retry; + long prevTime = 0, selectTime=0; + boolean connected; + + if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Socket closed"); + return; + } + + if (!IS_NULL(fdObj)) { + fd = fdObj.getSocket(); + nsockets ++; + } + if (!IS_NULL(fd1Obj)) { + fd1 = fd1Obj.getSocket(); + nsockets ++; + } + + if (nsockets == 2) { /* need to choose one of them */ + /* was fduse set in peek? */ + fduse = _this.fduse; + if (fduse == null) { + /* not set in peek(), must select on both sockets */ + int ret, t = (timeout == 0) ? -1: timeout; + cli.System.Net.Sockets.Socket[] tmp = new cli.System.Net.Sockets.Socket[] { fduse }; + ret = NET_Timeout2 (fd, fd1, t, tmp); + fduse = tmp[0]; + if (ret == 2) { + fduse = checkLastFD (_this, fd, fd1); + } else if (ret <= 0) { + if (ret == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", + "Receive timed out"); + } else if (ret == JVM_IO_ERR) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Socket closed"); + } else if (ret == JVM_IO_INTR) { + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", + "operation interrupted"); + } + return; + } + } + } else if (!ipv6_supported) { + fduse = fd; + } else if (IS_NULL(fdObj)) { + /* ipv6 supported: and this socket bound to an IPV6 only address */ + fduse = fd1; + } else { + /* ipv6 supported: and this socket bound to an IPV4 only address */ + fduse = fd; + } + + if (IS_NULL(packet)) { + JNU_ThrowNullPointerException(env, "packet"); + return; + } + + packetBuffer = packet.buf; + + if (IS_NULL(packetBuffer)) { + JNU_ThrowNullPointerException(env, "packet buffer"); + return; + } + + packetBufferOffset = packet.offset; + packetBufferLen = packet.bufLength; + + /* + if (packetBufferLen > MAX_BUFFER_LEN) { + + /* When JNI-ifying the JDK's IO routines, we turned + * read's and write's of byte arrays of size greater + * than 2048 bytes into several operations of size 2048. + * This saves a malloc()/memcpy()/free() for big + * buffers. This is OK for file IO and TCP, but that + * strategy violates the semantics of a datagram protocol. + * (one big send) != (several smaller sends). So here + * we *must* alloc the buffer. Note it needn't be bigger + * than 65,536 (0xFFFF) the max size of an IP packet. + * anything bigger is truncated anyway. + *-/ + fullPacket = (char *)malloc(packetBufferLen); + if (!fullPacket) { + JNU_ThrowOutOfMemoryError(env, "Receive buf native heap allocation failed"); + return; + } + } else { + fullPacket = &(BUF[0]); + } + */ + + + + /* + * If this Windows edition supports ICMP port unreachable and if we + * are not connected then we need to know if a timeout has been specified + * and if so we need to pick up the current time. These are required in + * order to implement the semantics of timeout, viz :- + * timeout set to t1 but ICMP port unreachable arrives in t2 where + * t2 < t1. In this case we must discard the ICMP packets and then + * wait for the next packet up to a maximum of t1 minus t2. + */ + connected = _this.connected; + if (supportPortUnreachable() && !connected && timeout != 0 &&!ipv6_supported) { + prevTime = JVM_CurrentTimeMillis(env, 0); + } + + if (timeout != 0 && nsockets == 1) { + int ret; + ret = NET_Timeout(fduse, timeout); + if (ret <= 0) { + if (ret == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", + "Receive timed out"); + } else if (ret == JVM_IO_ERR) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Socket closed"); + } else if (ret == JVM_IO_INTR) { + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", + "operation interrupted"); + } + return; + } + } + + /* + * Loop only if we discarding ICMP port unreachable packets + */ + do { + retry = FALSE; + + /* receive the packet */ + n = recvfrom(fduse, packetBuffer, packetBufferOffset, packetBufferLen, 0, remote_addr); + + if (n == JVM_IO_ERR) { + if (WSAGetLastError() == WSAECONNRESET) { + /* + * An icmp port unreachable has been received - consume any other + * outstanding packets. + */ + purgeOutstandingICMP(fduse); + + /* + * If connected throw a PortUnreachableException + */ + + if (connected) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"PortUnreachableException", + "ICMP Port Unreachable"); + return; + } + + /* + * If a timeout was specified then we need to adjust it because + * we may have used up some of the timeout before the icmp port + * unreachable arrived. + */ + if (timeout != 0) { + int ret; + long newTime = JVM_CurrentTimeMillis(env, 0); + timeout -= (newTime - prevTime); + prevTime = newTime; + + if (timeout <= 0) { + ret = 0; + } else { + ret = NET_Timeout(fduse, timeout); + } + + if (ret <= 0) { + if (ret == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", + "Receive timed out"); + } else if (ret == JVM_IO_ERR) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Socket closed"); + } else if (ret == JVM_IO_INTR) { + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", + "operation interrupted"); + } + return; + } + } + + /* + * An ICMP port unreachable was received but we are + * not connected so ignore it. + */ + retry = TRUE; + } + } + } while (retry); + + if (n < 0) { + errorCode = WSAGetLastError(); + /* check to see if it's because the buffer was too small */ + if (errorCode == WSAEMSGSIZE) { + /* it is because the buffer is too small. It's UDP, it's + * unreliable, it's all good. discard the rest of the + * data.. + */ + n = packetBufferLen; + } else { + /* failure */ + packet.length = 0; + } + } + if (n == -1) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); + } else if (n == -2) { + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", + "operation interrupted"); + } else if (n < 0) { + NET_ThrowCurrent(env, "Datagram receive failed"); + } else { + int port; + InetAddress packetAddress; + + /* + * Check if there is an InetAddress already associated with this + * packet. If so we check if it is the same source address. We + * can't update any existing InetAddress because it is immutable + */ + packetAddress = packet.address; + + if (packetAddress != NULL) { + if (!NET_SockaddrEqualsInetAddress(remote_addr, packetAddress)) { + /* force a new InetAddress to be created */ + packetAddress = null; + } + } + if (packetAddress == NULL) { + int[] tmp = { 0 }; + packetAddress = NET_SockaddrToInetAddress(remote_addr, tmp); + port = tmp[0]; + /* stuff the new Inetaddress in the packet */ + packet.address = packetAddress; + } else { + /* only get the new port number */ + port = NET_GetPortFromSockaddr(remote_addr); + } + /* populate the packet */ + packet.port = port; + packet.length = n; + } +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: datagramSocketCreate + * Signature: ()V + */ +static void datagramSocketCreate(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this) { + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + boolean ipv6_supported = ipv6_available(); + + if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); + return; + } else { + fd = socket (AF_INET, SOCK_DGRAM, 0); + } + if (fd == INVALID_SOCKET) { + NET_ThrowCurrent(env, "Socket creation failed"); + return; + } + fdObj.setSocket(fd); + NET_SetSockOpt(fd, SOL_SOCKET, SO_BROADCAST, true); + + if (ipv6_supported) { + /* SIO_UDP_CONNRESET fixes a bug introduced in Windows 2000, which + * returns connection reset errors un connected UDP sockets (as well + * as connected sockets. The solution is to only enable this feature + * when the socket is connected + */ + WSAIoctl(fd,SIO_UDP_CONNRESET,false); + fd1 = socket (AF_INET6, SOCK_DGRAM, 0); + if (fd1 == INVALID_SOCKET) { + NET_ThrowCurrent(env, "Socket creation failed"); + return; + } + NET_SetSockOpt(fd1, SOL_SOCKET, SO_BROADCAST, true); + WSAIoctl(fd1,SIO_UDP_CONNRESET,false); + fd1Obj.setSocket(fd1); + } else { + /* drop the second fd */ + _this.fd1 = null; + } +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: datagramSocketClose + * Signature: ()V + */ +static void datagramSocketClose(TwoStacksPlainDatagramSocketImpl _this) { + /* + * REMIND: PUT A LOCK AROUND THIS CODE + */ + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + boolean ipv6_supported = ipv6_available(); + cli.System.Net.Sockets.Socket fd = null, fd1 = null; + + if (IS_NULL(fdObj) && (!ipv6_supported || IS_NULL(fd1Obj))) { + return; + } + + if (!IS_NULL(fdObj)) { + fd = fdObj.getSocket(); + if (fd != null) { + fdObj.setSocket(null); + NET_SocketClose(fd); + } + } + + if (ipv6_supported && fd1Obj != NULL) { + fd1 = fd1Obj.getSocket(); + if (fd1 == null) { + return; + } + fd1Obj.setSocket(null); + NET_SocketClose(fd1); + } +} + +/* + * check the addresses attached to the NetworkInterface object + * and return the first one (of the requested family Ipv4 or Ipv6) + * in *iaddr + */ + +private static int getInetAddrFromIf (JNIEnv env, int family, NetworkInterface nif, InetAddress[] iaddr) +{ + InetAddress[] addrArray; + int len; + InetAddress addr; + int i; + + addrArray = getNetworkInterfaceAddresses(nif); + len = addrArray.length; + + /* + * Check that there is at least one address bound to this + * interface. + */ + if (len < 1) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "bad argument for IP_MULTICAST_IF2: No IP addresses bound to interface"); + return -1; + } + for (i=0; i() { + public InetAddress[] run() { + java.util.ArrayList list = new java.util.ArrayList(); + for (java.util.Enumeration e = nif.getInetAddresses(); e.hasMoreElements(); ) { + list.add(e.nextElement()); + } + return list.toArray(new InetAddress[list.size()]); + } + }); +} + +static int isAdapterIpv6Enabled(JNIEnv env, int index) { + return java.security.AccessController.doPrivileged(new java.security.PrivilegedAction() { + public Integer run() { + try { + for (java.util.Enumeration e = NetworkInterface.getByIndex(index).getInetAddresses(); e.hasMoreElements(); ) { + if (e.nextElement() instanceof Inet6Address) { + return 1; + } + } + } catch (SocketException x) { + } + return 0; + } + }).intValue(); +} + +private static NetworkInterface Java_java_net_NetworkInterface_getByIndex(JNIEnv env, int ni_class, int index) +{ + try { + return NetworkInterface.getByIndex(index); + } catch (Exception x) { + env.Throw(x); + return null; + } +} + +private static NetworkInterface Java_java_net_NetworkInterface_getByInetAddress0(JNIEnv env, int ni_class, Object address) +{ + try { + return NetworkInterface.getByInetAddress((InetAddress)address); + } catch (Exception x) { + env.Throw(x); + return null; + } +} + +/* + * Sets the multicast interface. + * + * SocketOptions.IP_MULTICAST_IF (argument is an InetAddress) :- + * IPv4: set outgoing multicast interface using + * IPPROTO_IP/IP_MULTICAST_IF + * + * IPv6: Get the interface to which the + * InetAddress is bound + * and do same as SockOptions.IF_MULTICAST_IF2 + * + * SockOptions.IF_MULTICAST_IF2 (argument is a NetworkInterface ) :- + * For each stack: + * IPv4: Obtain IP address bound to network interface + * (NetworkInterface.addres[0]) + * set outgoing multicast interface using + * IPPROTO_IP/IP_MULTICAST_IF + * + * IPv6: Obtain NetworkInterface.index + * Set outgoing multicast interface using + * IPPROTO_IPV6/IPV6_MULTICAST_IF + * + */ +private static void setMulticastInterface(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, cli.System.Net.Sockets.Socket fd, cli.System.Net.Sockets.Socket fd1, + int opt, Object value) +{ + boolean ipv6_supported = ipv6_available(); + + if (opt == java_net_SocketOptions_IP_MULTICAST_IF) { + /* + * value is an InetAddress. + * On IPv4 system use IP_MULTICAST_IF socket option + * On IPv6 system get the NetworkInterface that this IP + * address is bound to and use the IPV6_MULTICAST_IF + * option instead of IP_MULTICAST_IF + */ + if (ipv6_supported) { + value = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, value); + if (value == NULL) { + if (env.ExceptionOccurred() == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "bad argument for IP_MULTICAST_IF" + +": address not bound to any interface"); + } + return; + } + opt = java_net_SocketOptions_IP_MULTICAST_IF2; + } else { + in_addr in = new in_addr(); + + in.s_addr = htonl(getInetAddress_addr(env, (InetAddress)value)); + + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, + in) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", + "Error setting socket option"); + } + return; + } + } + + if (opt == java_net_SocketOptions_IP_MULTICAST_IF2) { + /* + * value is a NetworkInterface. + * On IPv6 system get the index of the interface and use the + * IPV6_MULTICAST_IF socket option + * On IPv4 system extract addr[0] and use the IP_MULTICAST_IF + * option. For IPv6 both must be done. + */ + if (ipv6_supported) { + in_addr in = new in_addr(); + int index; + + index = ((NetworkInterface)value).getIndex(); + + if ( isAdapterIpv6Enabled(env, index) != 0 ) { + if (setsockopt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF, + index) < 0) { + if (WSAGetLastError() == WSAEINVAL && index > 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "IPV6_MULTICAST_IF failed (interface has IPv4 " + +"address only?)"); + } else { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", + "Error setting socket option"); + } + return; + } + } + + /* If there are any IPv4 addresses on this interface then + * repeat the operation on the IPv4 fd */ + + if (getInet4AddrFromIf (env, (NetworkInterface)value, in) < 0) { + return; + } + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, + in) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", + "Error setting socket option"); + } + return; + } else { + in_addr in = new in_addr(); + + if (getInet4AddrFromIf (env, (NetworkInterface)value, in) < 0) { + if (env.ExceptionOccurred() != null) { + return; + } + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "no InetAddress instances of requested type"); + return; + } + + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, + in) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", + "Error setting socket option"); + } + return; + } + } +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: socketNativeSetOption + * Signature: (ILjava/lang/Object;)V + */ +static void socketNativeSetOption(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, int opt, Object value) { + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + int[] levelv4 = new int[1]; + int[] levelv6 = new int[1]; + int[] optnamev4 = new int[1]; + int[] optnamev6 = new int[1]; + Object optval; + boolean ipv6_supported = ipv6_available(); + + fd = getFD(env, _this); + + if (ipv6_supported) { + fd1 = getFD1(env, _this); + } + if (fd == null && fd1 == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); + return; + } + + if ((opt == java_net_SocketOptions_IP_MULTICAST_IF) || + (opt == java_net_SocketOptions_IP_MULTICAST_IF2)) { + + setMulticastInterface(env, _this, fd, fd1, opt, value); + return; + } + + /* + * Map the Java level socket option to the platform specific + * level(s) and option name(s). + */ + if (fd1 != null) { + if (NET_MapSocketOptionV6(opt, levelv6, optnamev6) != 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Invalid option"); + return; + } + } + if (fd != null) { + if (NET_MapSocketOption(opt, levelv4, optnamev4) != 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Invalid option"); + return; + } + } + + switch (opt) { + case java_net_SocketOptions_SO_SNDBUF : + case java_net_SocketOptions_SO_RCVBUF : + case java_net_SocketOptions_IP_TOS : + optval = ((Integer)value).intValue(); + break; + + case java_net_SocketOptions_SO_REUSEADDR: + case java_net_SocketOptions_SO_BROADCAST: + case java_net_SocketOptions_IP_MULTICAST_LOOP: + { + boolean on = ((Boolean)value).booleanValue(); + optval = on; + /* + * setLoopbackMode (true) disables IP_MULTICAST_LOOP rather + * than enabling it. + */ + if (opt == java_net_SocketOptions_IP_MULTICAST_LOOP) { + optval = !on; + } + } + break; + + default : + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Socket option not supported by PlainDatagramSocketImp"); + return; + } + + if (fd1 != null) { + if (NET_SetSockOpt(fd1, levelv6[0], optnamev6[0], optval) < 0) { + NET_ThrowCurrent(env, "setsockopt IPv6"); + return; + } + } + if (fd != null) { + if (NET_SetSockOpt(fd, levelv4[0], optnamev4[0], optval) < 0) { + NET_ThrowCurrent(env, "setsockopt"); + return; + } + } +} + +/* + * + * called by getMulticastInterface to retrieve a NetworkInterface + * configured for IPv4. + * The ipv4Mode parameter, is a closet boolean, which allows for a NULL return, + * or forces the creation of a NetworkInterface object with null data. + * It relates to its calling context in getMulticastInterface. + * ipv4Mode == 1, the context is IPV4 processing only. + * ipv4Mode == 0, the context is IPV6 processing + * + *-/ +static jobject getIPv4NetworkInterface (JNIEnv *env, jobject this, int fd, jint opt, int ipv4Mode) { + static jclass inet4_class; + static jmethodID inet4_ctrID; + + static jclass ni_class; static jmethodID ni_ctrID; + static jfieldID ni_indexID; + static jfieldID ni_addrsID; + + jobjectArray addrArray; + jobject addr; + jobject ni; + + struct in_addr in; + struct in_addr *inP = ∈ + int len = sizeof(struct in_addr); + if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, + (char *)inP, &len) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", + "Error getting socket option"); + return NULL; + } + + /* + * Construct and populate an Inet4Address + *-/ + if (inet4_class == NULL) { + jclass c = (*env)->FindClass(env, "java/net/Inet4Address"); + CHECK_NULL_RETURN(c, NULL); + inet4_ctrID = (*env)->GetMethodID(env, c, "", "()V"); + CHECK_NULL_RETURN(inet4_ctrID, NULL); + inet4_class = (*env)->NewGlobalRef(env, c); + CHECK_NULL_RETURN(inet4_class, NULL); + } + addr = (*env)->NewObject(env, inet4_class, inet4_ctrID, 0); + CHECK_NULL_RETURN(addr, NULL); + + setInetAddress_addr(env, addr, ntohl(in.s_addr)); + + /* + * For IP_MULTICAST_IF return InetAddress + *-/ + if (opt == java_net_SocketOptions_IP_MULTICAST_IF) { + return addr; + } + + /* + * For IP_MULTICAST_IF2 we get the NetworkInterface for + * this address and return it + *-/ + if (ni_class == NULL) { + jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); + CHECK_NULL_RETURN(c, NULL); + ni_ctrID = (*env)->GetMethodID(env, c, "", "()V"); + CHECK_NULL_RETURN(ni_ctrID, NULL); + ni_indexID = (*env)->GetFieldID(env, c, "index", "I"); + CHECK_NULL_RETURN(ni_indexID, NULL); + ni_addrsID = (*env)->GetFieldID(env, c, "addrs", + "[Ljava/net/InetAddress;"); + CHECK_NULL_RETURN(ni_addrsID, NULL); + ni_class = (*env)->NewGlobalRef(env, c); + CHECK_NULL_RETURN(ni_class, NULL); + } + ni = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, addr); + if (ni) { + return ni; + } + if (ipv4Mode) { + ni = (*env)->NewObject(env, ni_class, ni_ctrID, 0); + CHECK_NULL_RETURN(ni, NULL); + + (*env)->SetIntField(env, ni, ni_indexID, -1); + addrArray = (*env)->NewObjectArray(env, 1, inet4_class, NULL); + CHECK_NULL_RETURN(addrArray, NULL); + (*env)->SetObjectArrayElement(env, addrArray, 0, addr); + (*env)->SetObjectField(env, ni, ni_addrsID, addrArray); + } else { + ni = NULL; + } + return ni; +} + +/* + * Return the multicast interface: + * + * SocketOptions.IP_MULTICAST_IF + * IPv4: Query IPPROTO_IP/IP_MULTICAST_IF + * Create InetAddress + * IP_MULTICAST_IF returns struct ip_mreqn on 2.2 + * kernel but struct in_addr on 2.4 kernel + * IPv6: Query IPPROTO_IPV6 / IPV6_MULTICAST_IF or + * obtain from impl is Linux 2.2 kernel + * If index == 0 return InetAddress representing + * anyLocalAddress. + * If index > 0 query NetworkInterface by index + * and returns addrs[0] + * + * SocketOptions.IP_MULTICAST_IF2 + * IPv4: Query IPPROTO_IP/IP_MULTICAST_IF + * Query NetworkInterface by IP address and + * return the NetworkInterface that the address + * is bound too. + * IPv6: Query IPPROTO_IPV6 / IPV6_MULTICAST_IF + * (except Linux .2 kernel) + * Query NetworkInterface by index and + * return NetworkInterface. + */ +private static Object getMulticastInterface(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, cli.System.Net.Sockets.Socket fd, cli.System.Net.Sockets.Socket fd1, int opt) { + boolean isIPV4 = !ipv6_available() || fd1 == null; + + /* + * IPv4 implementation + */ + if (isIPV4) { + Inet4Address addr; + + in_addr in = new in_addr(); + + if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, + in) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", + "Error getting socket option"); + return NULL; + } + + /* + * Construct and populate an Inet4Address + */ + addr = new Inet4Address(); + addr.holder().address = ntohl(in.s_addr); + + /* + * For IP_MULTICAST_IF return InetAddress + */ + if (opt == java_net_SocketOptions_IP_MULTICAST_IF) { + return addr; + } + + NetworkInterface ni; + ni = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, addr); + if (ni != null) { + return ni; + } + + /* + * The address doesn't appear to be bound at any known + * NetworkInterface. Therefore we construct a NetworkInterface + * with this address. + */ + return new NetworkInterface(null, -1, new InetAddress[] { addr }); + } + + + /* + * IPv6 implementation + */ + if ((opt == java_net_SocketOptions_IP_MULTICAST_IF) || + (opt == java_net_SocketOptions_IP_MULTICAST_IF2)) { + + int index; + + InetAddress[] addrArray; + InetAddress addr; + NetworkInterface ni; + + { + int[] tmp = { 0 }; + if (getsockopt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF, + tmp) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", + "Error getting socket option"); + return NULL; + } + index = tmp[0]; + } + + /* + * If multicast to a specific interface then return the + * interface (for IF2) or the any address on that interface + * (for IF). + */ + if (index > 0) { + ni = Java_java_net_NetworkInterface_getByIndex(env, ni_class, + index); + if (ni == NULL) { + String errmsg = "IPV6_MULTICAST_IF returned index to unrecognized interface: " + index; + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", errmsg); + return NULL; + } + + /* + * For IP_MULTICAST_IF2 return the NetworkInterface + */ + if (opt == java_net_SocketOptions_IP_MULTICAST_IF2) { + return ni; + } + + /* + * For IP_MULTICAST_IF return addrs[0] + */ + addrArray = getNetworkInterfaceAddresses(ni); + if (addrArray.length < 1) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "IPV6_MULTICAST_IF returned interface without IP bindings"); + return NULL; + } + + addr = addrArray[0]; + return addr; + } + + /* + * Multicast to any address - return anyLocalAddress + * or a NetworkInterface with addrs[0] set to anyLocalAddress + */ + + addr = InetAddress.anyLocalAddress(); + if (opt == java_net_SocketOptions_IP_MULTICAST_IF) { + return addr; + } + + return new NetworkInterface(null, -1, new InetAddress[] { addr }); + } + return NULL; +} +/* + * Returns relevant info as a jint. + * + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: socketGetOption + * Signature: (I)Ljava/lang/Object; + */ +static Object socketGetOption(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, int opt) { + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + int[] level = new int[1]; + int[] optname = new int[1]; + int[] optval = new int[1]; + boolean ipv6_supported = ipv6_available(); + + fd = getFD(env, _this); + if (ipv6_supported) { + fd1 = getFD1(env, _this); + } + + if (fd == null && fd1 == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Socket closed"); + return NULL; + } + + /* + * Handle IP_MULTICAST_IF separately + */ + if (opt == java_net_SocketOptions_IP_MULTICAST_IF || + opt == java_net_SocketOptions_IP_MULTICAST_IF2) { + return getMulticastInterface(env, _this, fd, fd1, opt); + } + + /* + * Map the Java level socket option to the platform specific + * level and option name. + */ + if (NET_MapSocketOption(opt, level, optname) != 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Invalid option"); + return NULL; + } + + if (fd == null) { + if (NET_MapSocketOptionV6(opt, level, optname) != 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Invalid option"); + return NULL; + } + fd = fd1; /* must be IPv6 only */ + } + + if (NET_GetSockOpt(fd, level[0], optname[0], optval) < 0) { + String errmsg = "error getting socket option: " + WSAGetLastError(); + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", errmsg); + return NULL; + } + + switch (opt) { + case java_net_SocketOptions_SO_BROADCAST: + case java_net_SocketOptions_SO_REUSEADDR: + return optval[0] != 0; + + case java_net_SocketOptions_IP_MULTICAST_LOOP: + /* getLoopbackMode() returns true if IP_MULTICAST_LOOP is disabled */ + return optval[0] == 0; + + case java_net_SocketOptions_SO_SNDBUF: + case java_net_SocketOptions_SO_RCVBUF: + case java_net_SocketOptions_IP_TOS: + return optval[0]; + + default : + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Socket option not supported by TwoStacksPlainDatagramSocketImpl"); + return NULL; + + } +} + +/* + * Returns local address of the socket. + * + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: socketLocalAddress + * Signature: (I)Ljava/lang/Object; + */ +static Object socketLocalAddress(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, + int family) { + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + SOCKETADDRESS him; + him = new SOCKETADDRESS(); + Object iaObj; + boolean ipv6_supported = ipv6_available(); + + fd = getFD(env, _this); + if (ipv6_supported) { + fd1 = getFD1(env, _this); + } + + if (fd == null && fd1 == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Socket closed"); + return NULL; + } + + /* find out local IP address */ + + /* family==-1 when socket is not connected */ + if ((family == IPv6) || (family == -1 && fd == null)) { + fd = fd1; /* must be IPv6 only */ + } + + if (fd == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Socket closed"); + return NULL; + } + + if (getsockname(fd, him) == -1) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", + "Error getting socket name"); + return NULL; + } + iaObj = NET_SockaddrToInetAddress(him, new int[1]); + + return iaObj; +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: setTimeToLive + * Signature: (I)V + */ +static void setTimeToLive(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, int ttl) { + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + + if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Socket closed"); + return; + } else { + if (!IS_NULL(fdObj)) { + fd = fdObj.getSocket(); + } + if (!IS_NULL(fd1Obj)) { + fd1 = fd1Obj.getSocket(); + } + } + + /* setsockopt to be correct ttl */ + if (fd != null) { + if (NET_SetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_TTL, ttl) < 0) { + NET_ThrowCurrent(env, "set IP_MULTICAST_TTL failed"); + } + } + + if (fd1 != null) { + if (NET_SetSockOpt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, ttl) <0) { + NET_ThrowCurrent(env, "set IPV6_MULTICAST_HOPS failed"); + } + } +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: setTTL + * Signature: (B)V + */ +static void setTTL(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, byte ttl) { + setTimeToLive(env, _this, ttl & 0xFF); +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: getTimeToLive + * Signature: ()I + */ +static int getTimeToLive(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this) { + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + int[] ttl = new int[1]; + + if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Socket closed"); + return -1; + } else { + if (!IS_NULL(fdObj)) { + fd = fdObj.getSocket(); + } + if (!IS_NULL(fd1Obj)) { + fd1 = fd1Obj.getSocket(); + } + } + + /* getsockopt of ttl */ + if (fd != null) { + if (NET_GetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_TTL, ttl) < 0) { + NET_ThrowCurrent(env, "get IP_MULTICAST_TTL failed"); + return -1; + } + return ttl[0]; + } + if (fd1 != null) { + if (NET_GetSockOpt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, ttl) < 0) { + NET_ThrowCurrent(env, "get IP_MULTICAST_TTL failed"); + return -1; + } + return ttl[0]; + } + return -1; +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: getTTL + * Signature: ()B + */ +static byte getTTL(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this) { + int result = getTimeToLive(env, _this); + + return (byte)result; +} + +/* join/leave the named group on the named interface, or if no interface specified + * then the interface set with setInterfac(), or the default interface otherwise */ + +private static void mcast_join_leave(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, InetAddress iaObj, NetworkInterface niObj, boolean join) +{ + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + + SOCKETADDRESS name; + name = new SOCKETADDRESS(); + ip_mreq mname = new ip_mreq(); + ipv6_mreq mname6 = new ipv6_mreq(); + + in_addr in = new in_addr(); + int ifindex; + + int family; + boolean ipv6_supported = ipv6_available(); + int cmd ; + + if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Socket closed"); + return; + } + if (!IS_NULL(fdObj)) { + fd = fdObj.getSocket(); + } + if (ipv6_supported && !IS_NULL(fd1Obj)) { + fd1 = fd1Obj.getSocket(); + } + + if (IS_NULL(iaObj)) { + JNU_ThrowNullPointerException(env, "address"); + return; + } + + if (NET_InetAddressToSockaddr(env, iaObj, 0, name, JNI_FALSE) != 0) { + return; + } + + /* Set the multicast group address in the ip_mreq field + * eventually this check should be done by the security manager + */ + family = name.him.sa_family; + + if (family == AF_INET) { + int address = name.him4.sin_addr.s_addr; + if (!IN_MULTICAST(ntohl(address))) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "not in multicast"); + return; + } + mname.imr_multiaddr.s_addr = address; + if (fd == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Can't join an IPv4 group on an IPv6 only socket"); + return; + } + if (IS_NULL(niObj)) { + if (NET_GetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_IF, in) < 0) { + NET_ThrowCurrent(env, "get IP_MULTICAST_IF failed"); + return; + } + mname.imr_interface.s_addr = in.s_addr; + } else { + if (getInet4AddrFromIf (env, niObj, mname.imr_interface) != 0) { + NET_ThrowCurrent(env, "no Inet4Address associated with interface"); + return; + } + } + + cmd = join ? IP_ADD_MEMBERSHIP: IP_DROP_MEMBERSHIP; + + /* Join the multicast group */ + if (NET_SetSockOpt(fd, IPPROTO_IP, cmd, mname) < 0) { + if (WSAGetLastError() == WSAENOBUFS) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "IP_ADD_MEMBERSHIP failed (out of hardware filters?)"); + } else { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException","error setting options"); + } + } + } else /* AF_INET6 */ { + if (ipv6_supported) { + in6_addr address; + address = in6_addr.FromSockAddr(name); + if (!IN6_IS_ADDR_MULTICAST(address)) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "not in6 multicast"); + return; + } + mname6.ipv6mr_multiaddr = address; + } else { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "IPv6 not supported"); + return; + } + if (fd1 == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Can't join an IPv6 group on a IPv4 socket"); + return; + } + if (IS_NULL(niObj)) { + int[] tmp = { 0 }; + if (NET_GetSockOpt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF, tmp) < 0) { + NET_ThrowCurrent(env, "get IPV6_MULTICAST_IF failed"); + return; + } + ifindex = tmp[0]; + } else { + ifindex = getIndexFromIf (env, niObj); + if (ifindex == -1) { + NET_ThrowCurrent(env, "get ifindex failed"); + return; + } + } + mname6.ipv6mr_interface = ifindex; + cmd = join ? IPV6_ADD_MEMBERSHIP: IPV6_DROP_MEMBERSHIP; + + /* Join the multicast group */ + if (NET_SetSockOpt(fd1, IPPROTO_IPV6, cmd, mname6) < 0) { + if (WSAGetLastError() == WSAENOBUFS) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "IP_ADD_MEMBERSHIP failed (out of hardware filters?)"); + } else { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException","error setting options"); + } + } + } + + return; +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: join + * Signature: (Ljava/net/InetAddress;)V + */ +static void join(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, InetAddress inetaddr, NetworkInterface netIf) { + mcast_join_leave(env, _this, inetaddr, netIf, true); +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: leave + * Signature: (Ljava/net/InetAddress;)V + */ +static void leave(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, InetAddress inetaddr, NetworkInterface netIf) { + mcast_join_leave(env, _this, inetaddr, netIf, false); +} + +} diff --git a/openjdk/java/net/TwoStacksPlainSocketImpl.java b/openjdk/java/net/TwoStacksPlainSocketImpl.java new file mode 100644 index 0000000..5aee074 --- /dev/null +++ b/openjdk/java/net/TwoStacksPlainSocketImpl.java @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2007, 2013, 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 java.net; + +import java.io.IOException; +import java.io.FileDescriptor; +import sun.net.ResourceManager; + +/* + * This class defines the plain SocketImpl that is used for all + * Windows version lower than Vista. It adds support for IPv6 on + * these platforms where available. + * + * For backward compatibility Windows platforms that do not have IPv6 + * support also use this implementation, and fd1 gets set to null + * during socket creation. + * + * @author Chris Hegarty + */ + +class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl +{ + /* second fd, used for ipv6 on windows only. + * fd1 is used for listeners and for client sockets at initialization + * until the socket is connected. Up to this point fd always refers + * to the ipv4 socket and fd1 to the ipv6 socket. After the socket + * becomes connected, fd always refers to the connected socket + * (either v4 or v6) and fd1 is closed. + * + * For ServerSockets, fd always refers to the v4 listener and + * fd1 the v6 listener. + */ + FileDescriptor fd1; + + /* + * Needed for ipv6 on windows because we need to know + * if the socket is bound to ::0 or 0.0.0.0, when a caller + * asks for it. Otherwise we don't know which socket to ask. + */ + private InetAddress anyLocalBoundAddr = null; + + /* to prevent starvation when listening on two sockets, this is + * is used to hold the id of the last socket we accepted on. + */ + cli.System.Net.Sockets.Socket lastfd = null; + + // true if this socket is exclusively bound + private final boolean exclusiveBind; + + // emulates SO_REUSEADDR when exclusiveBind is true + private boolean isReuseAddress; + + + public TwoStacksPlainSocketImpl(boolean exclBind) { + exclusiveBind = exclBind; + } + + public TwoStacksPlainSocketImpl(FileDescriptor fd, boolean exclBind) { + this.fd = fd; + exclusiveBind = exclBind; + } + + /** + * Creates a socket with a boolean that specifies whether this + * is a stream socket (true) or an unconnected UDP socket (false). + */ + protected synchronized void create(boolean stream) throws IOException { + fd1 = new FileDescriptor(); + try { + super.create(stream); + } catch (IOException e) { + fd1 = null; + throw e; + } + } + + /** + * Binds the socket to the specified address of the specified local port. + * @param address the address + * @param port the port + */ + protected synchronized void bind(InetAddress address, int lport) + throws IOException + { + super.bind(address, lport); + if (address.isAnyLocalAddress()) { + anyLocalBoundAddr = address; + } + } + + public Object getOption(int opt) throws SocketException { + if (isClosedOrPending()) { + throw new SocketException("Socket Closed"); + } + if (opt == SO_BINDADDR) { + if (fd != null && fd1 != null ) { + /* must be unbound or else bound to anyLocal */ + return anyLocalBoundAddr; + } + InetAddressContainer in = new InetAddressContainer(); + socketGetOption(opt, in); + return in.addr; + } else if (opt == SO_REUSEADDR && exclusiveBind) { + // SO_REUSEADDR emulated when using exclusive bind + return isReuseAddress; + } else + return super.getOption(opt); + } + + @Override + void socketBind(InetAddress address, int port) throws IOException { + socketBind(address, port, exclusiveBind); + } + + @Override + void socketSetOption(int opt, boolean on, Object value) + throws SocketException + { + // SO_REUSEADDR emulated when using exclusive bind + if (opt == SO_REUSEADDR && exclusiveBind) + isReuseAddress = on; + else + socketNativeSetOption(opt, on, value); + } + + /** + * Closes the socket. + */ + @Override + protected void close() throws IOException { + synchronized(fdLock) { + if (fd != null || fd1 != null) { + if (!stream) { + ResourceManager.afterUdpClose(); + } + if (fdUseCount == 0) { + if (closePending) { + return; + } + closePending = true; + socketClose(); + fd = null; + fd1 = null; + return; + } else { + /* + * If a thread has acquired the fd and a close + * isn't pending then use a deferred close. + * Also decrement fdUseCount to signal the last + * thread that releases the fd to close it. + */ + if (!closePending) { + closePending = true; + fdUseCount--; + socketClose(); + } + } + } + } + } + + @Override + void reset() throws IOException { + if (fd != null || fd1 != null) { + socketClose(); + } + fd = null; + fd1 = null; + super.reset(); + } + + /* + * Return true if already closed or close is pending + */ + @Override + public boolean isClosedOrPending() { + /* + * Lock on fdLock to ensure that we wait if a + * close is in progress. + */ + synchronized (fdLock) { + if (closePending || (fd == null && fd1 == null)) { + return true; + } else { + return false; + } + } + } + + /* Native methods */ + + void socketCreate(boolean stream) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainSocketImpl_c.socketCreate(env, this, stream); + env.ThrowPendingException(); + } + + void socketConnect(InetAddress address, int port, int timeout) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainSocketImpl_c.socketConnect(env, this, address, port, timeout); + env.ThrowPendingException(); + } + + void socketBind(InetAddress address, int localport, boolean exclBind) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainSocketImpl_c.socketBind(env, this, address, localport, exclBind); + env.ThrowPendingException(); + } + + void socketListen(int count) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainSocketImpl_c.socketListen(env, this, count); + env.ThrowPendingException(); + } + + void socketAccept(SocketImpl socket) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainSocketImpl_c.socketAccept(env, this, socket); + env.ThrowPendingException(); + } + + int socketAvailable() throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + int ret = TwoStacksPlainSocketImpl_c.socketAvailable(env, this); + env.ThrowPendingException(); + return ret; + } + + void socketClose0(boolean useDeferredClose) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainSocketImpl_c.socketClose0(env, this, useDeferredClose); + env.ThrowPendingException(); + } + + void socketShutdown(int howto) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainSocketImpl_c.socketShutdown(env, this, howto); + env.ThrowPendingException(); + } + + void socketNativeSetOption(int cmd, boolean on, Object value) throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainSocketImpl_c.socketNativeSetOption(env, this, cmd, on, value); + env.ThrowPendingException(); + } + + int socketGetOption(int opt, Object iaContainerObj) throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + int ret = TwoStacksPlainSocketImpl_c.socketGetOption(env, this, opt, iaContainerObj); + env.ThrowPendingException(); + return ret; + } + + int socketGetOption1(int opt, Object iaContainerObj, FileDescriptor fd) throws SocketException { + throw new UnsatisfiedLinkError(); + } + + void socketSendUrgentData(int data) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainSocketImpl_c.socketSendUrgentData(env, this, data); + env.ThrowPendingException(); + } +} diff --git a/openjdk/java/net/TwoStacksPlainSocketImpl_c.java b/openjdk/java/net/TwoStacksPlainSocketImpl_c.java new file mode 100644 index 0000000..d51845e --- /dev/null +++ b/openjdk/java/net/TwoStacksPlainSocketImpl_c.java @@ -0,0 +1,1083 @@ +/* + * Copyright (c) 1997, 2013, 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 java.net; + +import java.io.FileDescriptor; +import static ikvm.internal.JNI.*; +import static ikvm.internal.Winsock.*; +import static java.net.net_util_md.*; +import static java.net.InetAddress.IPv4; +import static java.net.InetAddress.IPv6; + +final class TwoStacksPlainSocketImpl_c +{ +static final int JVM_IO_ERR = -1; +static final int JVM_IO_INTR = -2; + +static final int java_net_SocketOptions_SO_TIMEOUT = SocketOptions.SO_TIMEOUT; +static final int java_net_SocketOptions_SO_BINDADDR = SocketOptions.SO_BINDADDR; +static final int java_net_SocketOptions_SO_SNDBUF = SocketOptions.SO_SNDBUF; +static final int java_net_SocketOptions_SO_RCVBUF = SocketOptions.SO_RCVBUF; +static final int java_net_SocketOptions_IP_TOS = SocketOptions.IP_TOS; +static final int java_net_SocketOptions_SO_REUSEADDR = SocketOptions.SO_REUSEADDR; +static final int java_net_SocketOptions_TCP_NODELAY = SocketOptions.TCP_NODELAY; +static final int java_net_SocketOptions_SO_OOBINLINE = SocketOptions.SO_OOBINLINE; +static final int java_net_SocketOptions_SO_KEEPALIVE = SocketOptions.SO_KEEPALIVE; +static final int java_net_SocketOptions_SO_LINGER = SocketOptions.SO_LINGER; + +/* +#include +#include +#include +#include +#include +#include +#include + +#include "java_net_SocketOptions.h" +#include "java_net_TwoStacksPlainSocketImpl.h" +#include "java_net_InetAddress.h" +#include "java_io_FileDescriptor.h" +#include "java_lang_Integer.h" + +#include "jvm.h" +#include "net_util.h" +#include "jni_util.h" +*/ + +/************************************************************************ + * TwoStacksPlainSocketImpl + */ + +/* +static jfieldID IO_fd_fdID; + +jfieldID psi_fdID; +jfieldID psi_fd1ID; +jfieldID psi_addressID; +jfieldID psi_portID; +jfieldID psi_localportID; +jfieldID psi_timeoutID; +jfieldID psi_trafficClassID; +jfieldID psi_serverSocketID; +jfieldID psi_lastfdID; +*/ + +/* + * the level of the TCP protocol for setsockopt and getsockopt + * we only want to look this up once, from the static initializer + * of TwoStacksPlainSocketImpl + */ +static int tcp_level = -1; + +static cli.System.Net.Sockets.Socket getFD(JNIEnv env, TwoStacksPlainSocketImpl _this) { + FileDescriptor fdObj = _this.fd; + + if (fdObj == NULL) { + return null; + } + return fdObj.getSocket(); +} + +static cli.System.Net.Sockets.Socket getFD1(JNIEnv env, TwoStacksPlainSocketImpl _this) { + FileDescriptor fdObj = _this.fd1; + + if (fdObj == NULL) { + return null; + } + return fdObj.getSocket(); +} + + +/* + * The initProto function is called whenever TwoStacksPlainSocketImpl is + * loaded, to cache fieldIds for efficiency. This is called everytime + * the Java class is loaded. + * + * Class: java_net_TwoStacksPlainSocketImpl + * Method: initProto + + * Signature: ()V + */ +/* +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainSocketImpl_initProto(JNIEnv *env, jclass cls) { + + struct protoent *proto = getprotobyname("TCP"); + tcp_level = (proto == 0 ? IPPROTO_TCP: proto->p_proto); + + psi_fdID = (*env)->GetFieldID(env, cls , "fd", "Ljava/io/FileDescriptor;"); + CHECK_NULL(psi_fdID); + psi_fd1ID =(*env)->GetFieldID(env, cls , "fd1", "Ljava/io/FileDescriptor;"); + CHECK_NULL(psi_fd1ID); + psi_addressID = (*env)->GetFieldID(env, cls, "address", + "Ljava/net/InetAddress;"); + CHECK_NULL(psi_addressID); + psi_portID = (*env)->GetFieldID(env, cls, "port", "I"); + CHECK_NULL(psi_portID); + psi_lastfdID = (*env)->GetFieldID(env, cls, "lastfd", "I"); + CHECK_NULL(psi_portID); + psi_localportID = (*env)->GetFieldID(env, cls, "localport", "I"); + CHECK_NULL(psi_localportID); + psi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I"); + CHECK_NULL(psi_timeoutID); + psi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I"); + CHECK_NULL(psi_trafficClassID); + psi_serverSocketID = (*env)->GetFieldID(env, cls, "serverSocket", + "Ljava/net/ServerSocket;"); + CHECK_NULL(psi_serverSocketID); + IO_fd_fdID = NET_GetFileDescriptorID(env); + CHECK_NULL(IO_fd_fdID); +} +*/ + +/* + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketCreate + * Signature: (Z)V + */ +static void socketCreate(JNIEnv env, TwoStacksPlainSocketImpl _this, boolean stream) { + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + + if (IS_NULL(fdObj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "null fd object"); + return; + } + fd = socket(AF_INET, (stream ? SOCK_STREAM: SOCK_DGRAM), 0); + if (fd == INVALID_SOCKET) { + NET_ThrowCurrent(env, "create"); + return; + } else { + /* Set socket attribute so it is not passed to any child process */ + //SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE); + fdObj.setSocket(fd); + } + if (ipv6_available()) { + + if (IS_NULL(fd1Obj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "null fd1 object"); + fdObj.setSocket(null); + NET_SocketClose(fd); + return; + } + fd1 = socket(AF_INET6, (stream ? SOCK_STREAM: SOCK_DGRAM), 0); + if (fd1 == INVALID_SOCKET) { + NET_ThrowCurrent(env, "create"); + fdObj.setSocket(null); + NET_SocketClose(fd); + return; + } else { + fd1Obj.setSocket(fd1); + } + } else { + _this.fd1 = null; + } +} + +/* + * inetAddress is the address object passed to the socket connect + * call. + * + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketConnect + * Signature: (Ljava/net/InetAddress;I)V + */ +static void socketConnect(JNIEnv env, TwoStacksPlainSocketImpl _this, InetAddress iaObj, int port, int timeout) +{ + int localport = _this.localport; + + /* family and localport are int fields of iaObj */ + int family; + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + boolean ipv6_supported = ipv6_available(); + + /* fd initially points to the IPv4 socket and fd1 to the IPv6 socket + * If we want to connect to IPv6 then we swap the two sockets/objects + * This way, fd is always the connected socket, and fd1 always gets closed. + */ + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + + SOCKETADDRESS him; + him = new SOCKETADDRESS(); + + /* The result of the connection */ + int connect_res; + + if (!IS_NULL(fdObj)) { + fd = fdObj.getSocket(); + } + + if (ipv6_supported && !IS_NULL(fd1Obj)) { + fd1 = fd1Obj.getSocket(); + } + + if (IS_NULL(iaObj)) { + JNU_ThrowNullPointerException(env, "inet address argument is null."); + return; + } + + if (NET_InetAddressToSockaddr(env, iaObj, port, him, JNI_FALSE) != 0) { + return; + } + + family = him.him.sa_family; + if (family == AF_INET6) { + if (!ipv6_supported) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Protocol family not supported"); + return; + } else { + if (fd1 == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Destination unreachable"); + return; + } + /* close the v4 socket, and set fd to be the v6 socket */ + _this.fd = fd1Obj; + _this.fd1 = null; + NET_SocketClose(fd); + fd = fd1; fdObj = fd1Obj; + } + } else { + if (fd1 != null) { + fd1Obj.setSocket(null); + NET_SocketClose(fd1); + } + if (fd == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Destination unreachable"); + return; + } + } + _this.fd1 = null; + + if (timeout <= 0) { + connect_res = connect(fd, him); + if (connect_res == SOCKET_ERROR) { + connect_res = WSAGetLastError(); + } + } else { + int optval; + + /* make socket non-blocking */ + optval = 1; + ioctlsocket( fd, FIONBIO, optval ); + + /* initiate the connect */ + connect_res = connect(fd, him); + if (connect_res == SOCKET_ERROR) { + if (WSAGetLastError() != WSAEWOULDBLOCK) { + connect_res = WSAGetLastError(); + } else { + fd_set wr, ex; + wr = new fd_set(); ex = new fd_set(); + timeval t = new timeval(); + + FD_ZERO(wr); + FD_ZERO(ex); + FD_SET(fd, wr); + FD_SET(fd, ex); + t.tv_sec = timeout / 1000; + t.tv_usec = (timeout % 1000) * 1000; + + /* + * Wait for timout, connection established or + * connection failed. + */ + connect_res = select(null, wr, ex, t); + + /* + * Timeout before connection is established/failed so + * we throw exception and shutdown input/output to prevent + * socket from being used. + * The socket should be closed immediately by the caller. + */ + if (connect_res == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", + "connect timed out"); + shutdown( fd, SD_BOTH ); + + /* make socket blocking again - just in case */ + optval = 0; + ioctlsocket( fd, FIONBIO, optval ); + return; + } + + /* + * We must now determine if the connection has been established + * or if it has failed. The logic here is designed to work around + * bug on Windows NT whereby using getsockopt to obtain the + * last error (SO_ERROR) indicates there is no error. The workaround + * on NT is to allow winsock to be scheduled and this is done by + * yielding and retrying. As yielding is problematic in heavy + * load conditions we attempt up to 3 times to get the error reason. + */ + if (!FD_ISSET(fd, ex)) { + connect_res = 0; + } else { + int retry; + for (retry=0; retry<3; retry++) { + int[] tmp = { 0 }; + NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, + tmp); + connect_res = tmp[0]; + if (connect_res != 0) { + break; + } + Sleep(0); + } + + if (connect_res == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Unable to establish connection"); + return; + } + } + } + } + + /* make socket blocking again */ + optval = 0; + ioctlsocket(fd, FIONBIO, optval); + } + + if (connect_res != 0) { + if (connect_res == WSAEADDRNOTAVAIL) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"ConnectException", + "connect: Address is invalid on local machine, or port is not valid on remote machine"); + } else { + NET_ThrowNew(env, connect_res, "connect"); + } + return; + } + + fdObj.setSocket(fd); + + /* set the remote peer address and port */ + _this.address = iaObj; + _this.port = port; + + /* + * we need to initialize the local port field if bind was called + * previously to the connect (by the client) then localport field + * will already be initialized + */ + if (localport == 0) { + /* Now that we're a connected socket, let's extract the port number + * that the system chose for us and store it in the Socket object. + */ + if (getsockname(fd, him) == -1) { + + if (WSAGetLastError() == WSAENOTSOCK) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Socket closed"); + } else { + NET_ThrowCurrent(env, "getsockname failed"); + } + return; + } + port = ntohs (GET_PORT(him)); + _this.localport = port; + } +} + +/* + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketBind + * Signature: (Ljava/net/InetAddress;I)V + */ +static void socketBind(JNIEnv env, TwoStacksPlainSocketImpl _this, + InetAddress iaObj, int localport, + boolean exclBind) { + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + boolean ipv6_supported = ipv6_available(); + + /* family is an int field of iaObj */ + int family; + int rv; + + SOCKETADDRESS him; + him = new SOCKETADDRESS(); + + family = getInetAddress_family(env, iaObj); + + if (family == IPv6 && !ipv6_supported) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Protocol family not supported"); + return; + } + + if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Socket closed"); + return; + } else { + fd = fdObj.getSocket(); + if (ipv6_supported) { + fd1 = fd1Obj.getSocket(); + } + } + if (IS_NULL(iaObj)) { + JNU_ThrowNullPointerException(env, "inet address argument"); + return; + } + + if (NET_InetAddressToSockaddr(env, iaObj, localport, + him, JNI_FALSE) != 0) { + return; + } + if (ipv6_supported) { + ipv6bind v6bind = new ipv6bind(); + v6bind.addr = him; + v6bind.ipv4_fd = fd; + v6bind.ipv6_fd = fd1; + rv = NET_BindV6(v6bind, exclBind); + if (rv != -1) { + /* check if the fds have changed */ + if (v6bind.ipv4_fd != fd) { + fd = v6bind.ipv4_fd; + if (fd == null) { + /* socket is closed. */ + _this.fd = null; + } else { + /* socket was re-created */ + fdObj.setSocket(fd); + } + } + if (v6bind.ipv6_fd != fd1) { + fd1 = v6bind.ipv6_fd; + if (fd1 == null) { + /* socket is closed. */ + _this.fd1 = null; + } else { + /* socket was re-created */ + fd1Obj.setSocket(fd1); + } + } else { + /* NET_BindV6() closes both sockets upon a failure */ + _this.fd = null; + _this.fd1 = null; + } + } + } else { + rv = NET_WinBind(fd, him, exclBind); + } + + if (rv == -1) { + NET_ThrowCurrent(env, "JVM_Bind"); + return; + } + + /* set the address */ + _this.address = iaObj; + + /* intialize the local port */ + if (localport == 0) { + /* Now that we're a bound socket, let's extract the port number + * that the system chose for us and store it in the Socket object. + */ + int port; + fd = him.him.sa_family == AF_INET? fd: fd1; + + if (getsockname(fd, him) == -1) { + NET_ThrowCurrent(env, "getsockname in plain socketBind"); + return; + } + port = ntohs (GET_PORT (him)); + + _this.localport = port; + } else { + _this.localport = localport; + } +} + +/* + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketListen + * Signature: (I)V + */ +static void socketListen (JNIEnv env, TwoStacksPlainSocketImpl _this, int count) +{ + /* this FileDescriptor fd field */ + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + InetAddress address; + /* fdObj's int fd field */ + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + SOCKETADDRESS addr = new SOCKETADDRESS(); + + if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "socket closed"); + return; + } + + if (!IS_NULL(fdObj)) { + fd = fdObj.getSocket(); + } + /* Listen on V4 if address type is v4 or if v6 and address is ::0. + * Listen on V6 if address type is v6 or if v4 and address is 0.0.0.0. + * In cases, where we listen on one space only, we close the other socket. + */ + address = _this.address; + if (IS_NULL(address)) { + JNU_ThrowNullPointerException(env, "socket address"); + return; + } + if (NET_InetAddressToSockaddr(env, address, 0, addr, + JNI_FALSE) != 0) { + return; + } + + if (addr.him.sa_family == AF_INET || IN6ADDR_ISANY(addr.him6)) { + /* listen on v4 */ + if (listen(fd, count) == -1) { + NET_ThrowCurrent(env, "listen failed"); + } + } else { + NET_SocketClose (fd); + _this.fd = null; + } + if (ipv6_available() && !IS_NULL(fd1Obj)) { + fd1 = fd1Obj.getSocket(); + if (addr.him.sa_family == AF_INET6 || addr.him4.sin_addr.s_addr == INADDR_ANY) { + /* listen on v6 */ + if (listen(fd1, count) == -1) { + NET_ThrowCurrent(env, "listen failed"); + } + } else { + NET_SocketClose (fd1); + _this.fd1 = null; + } + } +} + +/* + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketAccept + * Signature: (Ljava/net/SocketImpl;)V + */ +static void socketAccept(JNIEnv env, TwoStacksPlainSocketImpl _this, SocketImpl socket) +{ + /* fields on this */ + int port; + int timeout = _this.timeout; + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + + /* the FileDescriptor field on socket */ + FileDescriptor socketFdObj; + + /* the InetAddress field on socket */ + InetAddress socketAddressObj; + + /* the fd int field on fdObj */ + cli.System.Net.Sockets.Socket fd=null, fd1=null; + + SOCKETADDRESS him; + him = new SOCKETADDRESS(); + + if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Socket closed"); + return; + } + if (!IS_NULL(fdObj)) { + fd = fdObj.getSocket(); + } + if (!IS_NULL(fd1Obj)) { + fd1 = fd1Obj.getSocket(); + } + if (IS_NULL(socket)) { + JNU_ThrowNullPointerException(env, "socket is null"); + return; + } else { + socketFdObj = socket.fd; + socketAddressObj = socket.address; + } + if ((IS_NULL(socketAddressObj)) || (IS_NULL(socketFdObj))) { + JNU_ThrowNullPointerException(env, "socket address or fd obj"); + return; + } + if (fd != null && fd1 != null) { + fd_set rfds = new fd_set(); + timeval t = new timeval(); + cli.System.Net.Sockets.Socket lastfd, fd2; + FD_ZERO(rfds); + FD_SET(fd,rfds); + FD_SET(fd1,rfds); + if (timeout != 0) { + t.tv_sec = timeout/1000; + t.tv_usec = (timeout%1000)*1000; + } else { + t = null; + } + int res = select (rfds, null, null, t); + if (res == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", + "Accept timed out"); + return; + } else if (res == 1) { + fd2 = FD_ISSET(fd, rfds)? fd: fd1; + } else if (res == 2) { + /* avoid starvation */ + lastfd = _this.lastfd; + if (lastfd != null) { + fd2 = lastfd==fd? fd1: fd; + } else { + fd2 = fd; + } + _this.lastfd = fd2; + } else { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "select failed"); + return; + } + fd = fd2; + } else { + int ret; + if (fd1 != null) { + fd = fd1; + } + if (timeout != 0) { + ret = NET_Timeout(fd, timeout); + if (ret == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", + "Accept timed out"); + return; + } else if (ret == -1) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); + /* REMIND: SOCKET CLOSED PROBLEM */ + /* NET_ThrowCurrent(env, "Accept failed"); */ + return; + } else if (ret == -2) { + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", + "operation interrupted"); + return; + } + } + } + fd = accept(fd, him); + if (fd == null) { + /* REMIND: SOCKET CLOSED PROBLEM */ + if (false) { + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", + "operation interrupted"); + } else { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "socket closed"); + } + return; + } + socketFdObj.setSocket(fd); + + if (him.him.sa_family == AF_INET) { + + /* + * fill up the remote peer port and address in the new socket structure + */ + socketAddressObj = new Inet4Address(null, ntohl(him.him4.sin_addr.s_addr)); + socket.address = socketAddressObj; + } else { + /* AF_INET6 -> Inet6Address */ + + // [IKVM] We need to convert scope_id 0 to -1 here, because for sin6_scope_id 0 means unspecified, whereas Java uses -1 + int scopeId = him.him6.sin6_scope_id; + socketAddressObj = new Inet6Address(null, him.him6.sin6_addr, scopeId == 0 ? -1 : scopeId); + } + /* fields common to AF_INET and AF_INET6 */ + + port = ntohs (GET_PORT (him)); + socket.port = port; + port = _this.localport; + socket.localport = port; + socket.address = socketAddressObj; +} + +/* + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketAvailable + * Signature: ()I + */ +static int socketAvailable(JNIEnv env, TwoStacksPlainSocketImpl _this) { + + int[] available = { -1 }; + int res; + FileDescriptor fdObj = _this.fd; + cli.System.Net.Sockets.Socket fd; + + if (IS_NULL(fdObj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); + return -1; + } else { + fd = fdObj.getSocket(); + } + res = ioctlsocket(fd, FIONREAD, available); + /* if result isn't 0, it means an error */ + if (res != 0) { + NET_ThrowNew(env, res, "socket available"); + } + return available[0]; +} + +/* + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketClose + * Signature: ()V + */ +static void socketClose0(JNIEnv env, TwoStacksPlainSocketImpl _this, boolean useDeferredClose) { + + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + + if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "socket already closed"); + return; + } + if (!IS_NULL(fdObj)) { + fd = fdObj.getSocket(); + } + if (!IS_NULL(fd1Obj)) { + fd1 = fd1Obj.getSocket(); + } + if (fd != null) { + fdObj.setSocket(null); + NET_SocketClose(fd); + } + if (fd1 != null) { + fd1Obj.setSocket(null); + NET_SocketClose(fd1); + } +} + +/* + * Socket options for plainsocketImpl + * + * + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketNativeSetOption + * Signature: (IZLjava/lang/Object;)V + */ +static void socketNativeSetOption(JNIEnv env, TwoStacksPlainSocketImpl _this, int cmd, boolean on, Object value) { + cli.System.Net.Sockets.Socket fd, fd1; + int[] level = new int[1]; + int[] optname = new int[1]; + Object optval; + + /* + * Get SOCKET and check that it hasn't been closed + */ + fd = getFD(env, _this); + fd1 = getFD1(env, _this); + if (fd == null && fd1 == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); + return; + } + + /* + * SO_TIMEOUT is the socket option used to specify the timeout + * for ServerSocket.accept and Socket.getInputStream().read. + * It does not typically map to a native level socket option. + * For Windows we special-case this and use the SOL_SOCKET/SO_RCVTIMEO + * socket option to specify a receive timeout on the socket. This + * receive timeout is applicable to Socket only and the socket + * option should not be set on ServerSocket. + */ + if (cmd == java_net_SocketOptions_SO_TIMEOUT) { + + /* + * Don't enable the socket option on ServerSocket as it's + * meaningless (we don't receive on a ServerSocket). + */ + Object ssObj = _this.serverSocket; + if (ssObj != NULL) { + return; + } + + /* + * SO_RCVTIMEO is only supported on Microsoft's implementation + * of Windows Sockets so if WSAENOPROTOOPT returned then + * reset flag and timeout will be implemented using + * select() -- see SocketInputStream.socketRead. + */ + if (isRcvTimeoutSupported) { + int timeout = ((Integer)value).intValue(); + + /* + * Disable SO_RCVTIMEO if timeout is <= 5 second. + */ + if (timeout <= 5000) { + timeout = 0; + } + + if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, timeout) < 0) { + if (WSAGetLastError() == WSAENOPROTOOPT) { + isRcvTimeoutSupported = JNI_FALSE; + } else { + NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO"); + } + } + if (fd1 != null) { + if (setsockopt(fd1, SOL_SOCKET, SO_RCVTIMEO, timeout) < 0) { + NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO"); + } + } + } + return; + } + + /* + * Map the Java level socket option to the platform specific + * level + */ + if (NET_MapSocketOption(cmd, level, optname) != 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Invalid option"); + return; + } + + switch (cmd) { + + case java_net_SocketOptions_TCP_NODELAY : + case java_net_SocketOptions_SO_OOBINLINE : + case java_net_SocketOptions_SO_KEEPALIVE : + case java_net_SocketOptions_SO_REUSEADDR : + optval = on; + break; + + case java_net_SocketOptions_SO_SNDBUF : + case java_net_SocketOptions_SO_RCVBUF : + case java_net_SocketOptions_IP_TOS : + optval = ((Integer)value).intValue(); + break; + + case java_net_SocketOptions_SO_LINGER : + { + linger ling = new linger(); + if (on) { + ling.l_onoff = 1; + ling.l_linger = ((Integer)value).intValue(); + } else { + ling.l_onoff = 0; + ling.l_linger = 0; + } + optval = ling; + } + break; + + default: /* shouldn't get here */ + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Option not supported by TwoStacksPlainSocketImpl"); + return; + } + + if (fd != null) { + if (NET_SetSockOpt(fd, level[0], optname[0], optval) < 0) { + NET_ThrowCurrent(env, "setsockopt"); + } + } + + if (fd1 != null) { + if (NET_SetSockOpt(fd1, level[0], optname[0], optval) < 0) { + NET_ThrowCurrent(env, "setsockopt"); + } + } +} + + +/* + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketGetOption + * Signature: (I)I + */ +static int socketGetOption(JNIEnv env, TwoStacksPlainSocketImpl _this, int opt, Object iaContainerObj) { + + cli.System.Net.Sockets.Socket fd, fd1; + int[] level = new int[1]; + int[] optname = new int[1]; + Object optval; + + /* + * Get SOCKET and check it hasn't been closed + */ + fd = getFD(env, _this); + fd1 = getFD1(env, _this); + + if (fd == null && fd1 == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); + return -1; + } + if (fd == null) { + fd = fd1; + } + + /* For IPv6, we assume both sockets have the same setting always */ + + /* + * SO_BINDADDR isn't a socket option + */ + if (opt == java_net_SocketOptions_SO_BINDADDR) { + SOCKETADDRESS him; + him = new SOCKETADDRESS(); + int[] port = { 0 }; + InetAddress iaObj; + + if (fd == null) { + /* must be an IPV6 only socket. Case where both sockets are != -1 + * is handled in java + */ + fd = getFD1 (env, _this); + } + + if (getsockname(fd, him) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", + "Error getting socket name"); + return -1; + } + iaObj = NET_SockaddrToInetAddress(him, port); + ((InetAddressContainer)iaContainerObj).addr = iaObj; + return 0; /* notice change from before */ + } + + /* + * Map the Java level socket option to the platform specific + * level and option name. + */ + if (NET_MapSocketOption(opt, level, optname) != 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Invalid option"); + return -1; + } + + /* + * Args are int except for SO_LINGER + */ + if (opt == java_net_SocketOptions_SO_LINGER) { + optval = new linger(); + } else { + optval = new int[1]; + } + + if (NET_GetSockOpt(fd, level[0], optname[0], optval) < 0) { + NET_ThrowCurrent(env, "getsockopt"); + return -1; + } + + switch (opt) { + case java_net_SocketOptions_SO_LINGER: + return (((linger)optval).l_onoff != 0 ? ((linger)optval).l_linger: -1); + + case java_net_SocketOptions_SO_SNDBUF: + case java_net_SocketOptions_SO_RCVBUF: + case java_net_SocketOptions_IP_TOS: + return ((int[])optval)[0]; + + case java_net_SocketOptions_TCP_NODELAY : + case java_net_SocketOptions_SO_OOBINLINE : + case java_net_SocketOptions_SO_KEEPALIVE : + case java_net_SocketOptions_SO_REUSEADDR : + return (((int[])optval)[0] == 0) ? -1 : 1; + + default: /* shouldn't get here */ + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "Option not supported by TwoStacksPlainSocketImpl"); + return -1; + } +} + +/* + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketShutdown + * Signature: (I)V + */ +static void socketShutdown(JNIEnv env, TwoStacksPlainSocketImpl _this, int howto) +{ + + FileDescriptor fdObj = _this.fd; + cli.System.Net.Sockets.Socket fd; + + /* + * WARNING: THIS NEEDS LOCKING. ALSO: SHOULD WE CHECK for fd being + * -1 already? + */ + if (IS_NULL(fdObj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", + "socket already closed"); + return; + } else { + fd = fdObj.getSocket(); + } + shutdown(fd, howto); +} + +/* + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketSendUrgentData + * Signature: (B)V + */ +static void socketSendUrgentData(JNIEnv env, TwoStacksPlainSocketImpl _this, int data) { + /* The fd field */ + FileDescriptor fdObj = _this.fd; + int n; + cli.System.Net.Sockets.Socket fd; + + if (IS_NULL(fdObj)) { + JNU_ThrowByName(env, "java/net/SocketException", "Socket closed"); + return; + } else { + fd = fdObj.getSocket(); + /* Bug 4086704 - If the Socket associated with this file descriptor + * was closed (sysCloseFD), the the file descriptor is set to -1. + */ + if (fd == null) { + JNU_ThrowByName(env, "java/net/SocketException", "Socket closed"); + return; + } + + } + n = send(fd, new byte[] { (byte)data }, 1, MSG_OOB); + if (n == JVM_IO_ERR) { + NET_ThrowCurrent(env, "send"); + return; + } + if (n == JVM_IO_INTR) { + JNU_ThrowByName(env, "java/io/InterruptedIOException", null); + return; + } +} +} diff --git a/openjdk/java/net/net_util_md.java b/openjdk/java/net/net_util_md.java new file mode 100644 index 0000000..03fe929 --- /dev/null +++ b/openjdk/java/net/net_util_md.java @@ -0,0 +1,889 @@ +/* + * Copyright (c) 1997, 2013, 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 java.net; + +import java.io.FileDescriptor; +import cli.System.Net.IPAddress; +import cli.System.Net.IPEndPoint; +import static ikvm.internal.JNI.*; +import static ikvm.internal.Winsock.*; + +final class net_util_md +{ + private net_util_md() { } + + static final int INADDR_ANY = 0; + + static final int IPTOS_TOS_MASK = 0x1e; + static final int IPTOS_PREC_MASK = 0xe0; + + static boolean isRcvTimeoutSupported = true; + + /* + * Table of Windows Sockets errors, the specific exception we + * throw for the error, and the error text. + * + * Note that this table excludes OS dependent errors. + * + * Latest list of Windows Sockets errors can be found at :- + * http://msdn.microsoft.com/library/psdk/winsock/errors_3wc2.htm + */ + private static class WinsockError + { + final int errCode; + final int exc; + final String errString; + + WinsockError(int errCode, int exc, String errString) + { + this.errCode = errCode; + this.exc = exc; + this.errString = errString; + } + } + + private static final int Exception_BindException = 1; + private static final int Exception_ConnectException = 2; + private static final int Exception_NoRouteToHostException = 3; + + private static final WinsockError[] winsock_errors = { + new WinsockError(WSAEACCES, 0, "Permission denied"), + new WinsockError(WSAEADDRINUSE, Exception_BindException, "Address already in use"), + new WinsockError(WSAEADDRNOTAVAIL, Exception_BindException, "Cannot assign requested address"), + new WinsockError(WSAEAFNOSUPPORT, 0, "Address family not supported by protocol family"), + new WinsockError(WSAEALREADY, 0, "Operation already in progress"), + new WinsockError(WSAECONNABORTED, 0, "Software caused connection abort"), + new WinsockError(WSAECONNREFUSED, Exception_ConnectException, "Connection refused"), + new WinsockError(WSAECONNRESET, 0, "Connection reset by peer"), + new WinsockError(WSAEDESTADDRREQ, 0, "Destination address required"), + new WinsockError(WSAEFAULT, 0, "Bad address"), + new WinsockError(WSAEHOSTDOWN, 0, "Host is down"), + new WinsockError(WSAEHOSTUNREACH, Exception_NoRouteToHostException, "No route to host"), + new WinsockError(WSAEINPROGRESS, 0, "Operation now in progress"), + new WinsockError(WSAEINTR, 0, "Interrupted function call"), + new WinsockError(WSAEINVAL, 0, "Invalid argument"), + new WinsockError(WSAEISCONN, 0, "Socket is already connected"), + new WinsockError(WSAEMFILE, 0, "Too many open files"), + new WinsockError(WSAEMSGSIZE, 0, "The message is larger than the maximum supported by the underlying transport"), + new WinsockError(WSAENETDOWN, 0, "Network is down"), + new WinsockError(WSAENETRESET, 0, "Network dropped connection on reset"), + new WinsockError(WSAENETUNREACH, 0, "Network is unreachable"), + new WinsockError(WSAENOBUFS, 0, "No buffer space available (maximum connections reached?)"), + new WinsockError(WSAENOPROTOOPT, 0, "Bad protocol option"), + new WinsockError(WSAENOTCONN, 0, "Socket is not connected"), + new WinsockError(WSAENOTSOCK, 0, "Socket operation on nonsocket"), + new WinsockError(WSAEOPNOTSUPP, 0, "Operation not supported"), + new WinsockError(WSAEPFNOSUPPORT, 0, "Protocol family not supported"), + new WinsockError(WSAEPROCLIM, 0, "Too many processes"), + new WinsockError(WSAEPROTONOSUPPORT, 0, "Protocol not supported"), + new WinsockError(WSAEPROTOTYPE, 0, "Protocol wrong type for socket"), + new WinsockError(WSAESHUTDOWN, 0, "Cannot send after socket shutdown"), + new WinsockError(WSAESOCKTNOSUPPORT, 0, "Socket type not supported"), + new WinsockError(WSAETIMEDOUT, Exception_ConnectException, "Connection timed out"), + new WinsockError(WSATYPE_NOT_FOUND, 0, "Class type not found"), + new WinsockError(WSAEWOULDBLOCK, 0, "Resource temporarily unavailable"), + new WinsockError(WSAHOST_NOT_FOUND, 0, "Host not found"), + new WinsockError(WSA_NOT_ENOUGH_MEMORY, 0, "Insufficient memory available"), + new WinsockError(WSANOTINITIALISED, 0, "Successful WSAStartup not yet performed"), + new WinsockError(WSANO_DATA, 0, "Valid name, no data record of requested type"), + new WinsockError(WSANO_RECOVERY, 0, "This is a nonrecoverable error"), + new WinsockError(WSASYSNOTREADY, 0, "Network subsystem is unavailable"), + new WinsockError(WSATRY_AGAIN, 0, "Nonauthoritative host not found"), + new WinsockError(WSAVERNOTSUPPORTED, 0, "Winsock.dll version out of range"), + new WinsockError(WSAEDISCON, 0, "Graceful shutdown in progress"), + new WinsockError(WSA_OPERATION_ABORTED, 0, "Overlapped operation aborted") + }; + + /* + * Since winsock doesn't have the equivalent of strerror(errno) + * use table to lookup error text for the error. + */ + static SocketException NET_ThrowNew(int errorNum, String msg) + { + int i; + int table_size = winsock_errors.length; + int excP = 0; + String fullMsg; + + if (msg == null) { + msg = "no further information"; + } + + /* + * Check table for known winsock errors + */ + i=0; + while (i < table_size) { + if (errorNum == winsock_errors[i].errCode) { + break; + } + i++; + } + + /* + * If found get pick the specific exception and error + * message corresponding to this error. + */ + if (i < table_size) { + excP = winsock_errors[i].exc; + fullMsg = winsock_errors[i].errString + ": " + msg; + } else { + fullMsg = "Unrecognized Windows Sockets error: " + errorNum + ": " + msg; + } + + /* + * Throw SocketException if no specific exception for this + * error. + */ + switch (excP) { + case Exception_BindException: + return new BindException(fullMsg); + case Exception_ConnectException: + return new ConnectException(fullMsg); + case Exception_NoRouteToHostException: + return new NoRouteToHostException(fullMsg); + default: + return new SocketException(fullMsg); + } + } + + static void NET_ThrowNew(JNIEnv env, int errorNum, String msg) + { + env.Throw(NET_ThrowNew(errorNum, msg)); + } + + static SocketException NET_ThrowCurrent(String msg) + { + return NET_ThrowNew(WSAGetLastError(), msg); + } + + static void NET_ThrowCurrent(JNIEnv env, String msg) + { + env.Throw(NET_ThrowCurrent(msg)); + } + + /* + * Return the default TOS value + */ + static int NET_GetDefaultTOS() { + // we always use the "default" default... + return 0; + } + + /* + * Map the Java level socket option to the platform specific + * level and option name. + */ + + private static final class sockopts { + int cmd; + int level; + int optname; + + sockopts(int cmd, int level, int optname) { + this.cmd = cmd; + this.level = level; + this.optname = optname; + } + } + + private static final sockopts opts[] = { + new sockopts(SocketOptions.TCP_NODELAY, IPPROTO_TCP, TCP_NODELAY ), + new sockopts(SocketOptions.SO_OOBINLINE, SOL_SOCKET, SO_OOBINLINE ), + new sockopts(SocketOptions.SO_LINGER, SOL_SOCKET, SO_LINGER ), + new sockopts(SocketOptions.SO_SNDBUF, SOL_SOCKET, SO_SNDBUF ), + new sockopts(SocketOptions.SO_RCVBUF, SOL_SOCKET, SO_RCVBUF ), + new sockopts(SocketOptions.SO_KEEPALIVE, SOL_SOCKET, SO_KEEPALIVE ), + new sockopts(SocketOptions.SO_REUSEADDR, SOL_SOCKET, SO_REUSEADDR ), + new sockopts(SocketOptions.SO_BROADCAST, SOL_SOCKET, SO_BROADCAST ), + new sockopts(SocketOptions.IP_MULTICAST_IF, IPPROTO_IP, IP_MULTICAST_IF ), + new sockopts(SocketOptions.IP_MULTICAST_LOOP, IPPROTO_IP, IP_MULTICAST_LOOP ), + new sockopts(SocketOptions.IP_TOS, IPPROTO_IP, IP_TOS ), + + }; + + /* call NET_MapSocketOptionV6 for the IPv6 fd only + * and NET_MapSocketOption for the IPv4 fd + */ + static int NET_MapSocketOptionV6(int cmd, int[] level, int[] optname) { + + switch (cmd) { + case SocketOptions.IP_MULTICAST_IF: + case SocketOptions.IP_MULTICAST_IF2: + level[0] = IPPROTO_IPV6; + optname[0] = IPV6_MULTICAST_IF; + return 0; + + case SocketOptions.IP_MULTICAST_LOOP: + level[0] = IPPROTO_IPV6; + optname[0] = IPV6_MULTICAST_LOOP; + return 0; + } + return NET_MapSocketOption (cmd, level, optname); + } + + static int NET_MapSocketOption(int cmd, int[] level, int[] optname) { + /* + * Map the Java level option to the native level + */ + for (int i=0; i 0 ? scope : -1); + } + port[0] = ntohs(him.him6.sin_port); + } else { + iaObj = new Inet4Address(null, ntohl(him.him4.sin_addr.s_addr)); + port[0] = ntohs(him.him4.sin_port); + } + return iaObj; + } + + static void NET_ThrowByNameWithLastError(JNIEnv env, String exceptionClass, String message) { + JNU_ThrowByName(env, exceptionClass, "errno: " + WSAGetLastError() + ", error: " + message + "\n"); + } + + static boolean IN_MULTICAST(int ipv4address) { + return ((ipv4address >> 24) & 0xf0) == 0xe0; + } + + static boolean IN6_IS_ADDR_MULTICAST(in6_addr address) { + return (address.s6_bytes()[0] & 0xff) == 0xff; + } + + static final class SOCKETADDRESS implements IIPEndPointWrapper { + final SOCKETADDRESS him = this; + final SOCKETADDRESS him4 = this; + final SOCKETADDRESS him6 = this; + final SOCKETADDRESS sin_addr = this; + int sa_family; + int sin_port; + int s_addr; + byte[] sin6_addr; + int sin6_scope_id; + + public void set(IPEndPoint ep) { + if (ep == null) { + sa_family = 0; + sin_port = 0; + s_addr = 0; + sin6_addr = null; + sin6_scope_id = 0; + } else { + sa_family = ep.get_AddressFamily().Value; + sin_port = htons(ep.get_Port()); + if (sa_family == AF_INET) { + s_addr = (int)ep.get_Address().get_Address(); + sin6_addr = null; + sin6_scope_id = 0; + } else { + s_addr = 0; + IPAddress addr = ep.get_Address(); + sin6_addr = addr.GetAddressBytes(); + sin6_scope_id = (int)addr.get_ScopeId(); + } + } + } + + public IPEndPoint get() { + if (sa_family == AF_INET) { + return new IPEndPoint(new IPAddress(s_addr & 0xFFFFFFFFL), ntohs(sin_port)); + } else if (sa_family == AF_INET6) { + IPAddress addr; + if (sin6_addr == null) { + addr = IPAddress.IPv6Any; + } else { + addr = new IPAddress(sin6_addr, sin6_scope_id & 0xFFFFFFFFL); + } + return new IPEndPoint(addr, ntohs(sin_port)); + } else { + return null; + } + } + } + + static int GET_PORT(SOCKETADDRESS sockaddr) { + return sockaddr.sin_port; + } + + static void Sleep(int ms) { + cli.System.Threading.Thread.Sleep(ms); + } + + static cli.System.Net.Sockets.Socket NET_Socket (int domain, int type, int protocol) { + cli.System.Net.Sockets.Socket sock; + sock = socket (domain, type, protocol); + if (sock != INVALID_SOCKET) { + //SetHandleInformation((HANDLE)(uintptr_t)sock, HANDLE_FLAG_INHERIT, FALSE); + } + return sock; + } + + static int getInetAddress_addr(JNIEnv env, InetAddress iaObj) { + return iaObj.holder().address; + } + + static int getInetAddress_family(JNIEnv env, InetAddress iaObj) { + return iaObj.holder().family; + } +} diff --git a/openjdk/java/nio/Bits.java b/openjdk/java/nio/Bits.java new file mode 100644 index 0000000..cea374f --- /dev/null +++ b/openjdk/java/nio/Bits.java @@ -0,0 +1,850 @@ +/* + * Copyright (c) 2000, 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 java.nio; + +import java.security.AccessController; +import sun.misc.Unsafe; +import sun.misc.VM; + +/** + * Access to bits, native and otherwise. + */ + +class Bits { // package-private + + private Bits() { } + + + // -- Swapping -- + + static short swap(short x) { + return Short.reverseBytes(x); + } + + static char swap(char x) { + return Character.reverseBytes(x); + } + + static int swap(int x) { + return Integer.reverseBytes(x); + } + + static long swap(long x) { + return Long.reverseBytes(x); + } + + + // -- get/put char -- + + static private char makeChar(byte b1, byte b0) { + return (char)((b1 << 8) | (b0 & 0xff)); + } + + static char getCharL(ByteBuffer bb, int bi) { + return makeChar(bb._get(bi + 1), + bb._get(bi )); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static char getCharL(long a) { + return makeChar(_get(a + 1), + _get(a )); + } + + static char getCharB(ByteBuffer bb, int bi) { + return makeChar(bb._get(bi ), + bb._get(bi + 1)); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static char getCharB(long a) { + return makeChar(_get(a ), + _get(a + 1)); + } + + static char getChar(ByteBuffer bb, int bi, boolean bigEndian) { + return bigEndian ? getCharB(bb, bi) : getCharL(bb, bi); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static char getChar(long a, boolean bigEndian) { + return bigEndian ? getCharB(a) : getCharL(a); + } + + private static byte char1(char x) { return (byte)(x >> 8); } + private static byte char0(char x) { return (byte)(x ); } + + static void putCharL(ByteBuffer bb, int bi, char x) { + bb._put(bi , char0(x)); + bb._put(bi + 1, char1(x)); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void putCharL(long a, char x) { + _put(a , char0(x)); + _put(a + 1, char1(x)); + } + + static void putCharB(ByteBuffer bb, int bi, char x) { + bb._put(bi , char1(x)); + bb._put(bi + 1, char0(x)); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void putCharB(long a, char x) { + _put(a , char1(x)); + _put(a + 1, char0(x)); + } + + static void putChar(ByteBuffer bb, int bi, char x, boolean bigEndian) { + if (bigEndian) + putCharB(bb, bi, x); + else + putCharL(bb, bi, x); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void putChar(long a, char x, boolean bigEndian) { + if (bigEndian) + putCharB(a, x); + else + putCharL(a, x); + } + + + // -- get/put short -- + + static private short makeShort(byte b1, byte b0) { + return (short)((b1 << 8) | (b0 & 0xff)); + } + + static short getShortL(ByteBuffer bb, int bi) { + return makeShort(bb._get(bi + 1), + bb._get(bi )); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static short getShortL(long a) { + return makeShort(_get(a + 1), + _get(a )); + } + + static short getShortB(ByteBuffer bb, int bi) { + return makeShort(bb._get(bi ), + bb._get(bi + 1)); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static short getShortB(long a) { + return makeShort(_get(a ), + _get(a + 1)); + } + + static short getShort(ByteBuffer bb, int bi, boolean bigEndian) { + return bigEndian ? getShortB(bb, bi) : getShortL(bb, bi); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static short getShort(long a, boolean bigEndian) { + return bigEndian ? getShortB(a) : getShortL(a); + } + + private static byte short1(short x) { return (byte)(x >> 8); } + private static byte short0(short x) { return (byte)(x ); } + + static void putShortL(ByteBuffer bb, int bi, short x) { + bb._put(bi , short0(x)); + bb._put(bi + 1, short1(x)); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void putShortL(long a, short x) { + _put(a , short0(x)); + _put(a + 1, short1(x)); + } + + static void putShortB(ByteBuffer bb, int bi, short x) { + bb._put(bi , short1(x)); + bb._put(bi + 1, short0(x)); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void putShortB(long a, short x) { + _put(a , short1(x)); + _put(a + 1, short0(x)); + } + + static void putShort(ByteBuffer bb, int bi, short x, boolean bigEndian) { + if (bigEndian) + putShortB(bb, bi, x); + else + putShortL(bb, bi, x); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void putShort(long a, short x, boolean bigEndian) { + if (bigEndian) + putShortB(a, x); + else + putShortL(a, x); + } + + + // -- get/put int -- + + static private int makeInt(byte b3, byte b2, byte b1, byte b0) { + return (((b3 ) << 24) | + ((b2 & 0xff) << 16) | + ((b1 & 0xff) << 8) | + ((b0 & 0xff) )); + } + + static int getIntL(ByteBuffer bb, int bi) { + return makeInt(bb._get(bi + 3), + bb._get(bi + 2), + bb._get(bi + 1), + bb._get(bi )); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static int getIntL(long a) { + return makeInt(_get(a + 3), + _get(a + 2), + _get(a + 1), + _get(a )); + } + + static int getIntB(ByteBuffer bb, int bi) { + return makeInt(bb._get(bi ), + bb._get(bi + 1), + bb._get(bi + 2), + bb._get(bi + 3)); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static int getIntB(long a) { + return makeInt(_get(a ), + _get(a + 1), + _get(a + 2), + _get(a + 3)); + } + + static int getInt(ByteBuffer bb, int bi, boolean bigEndian) { + return bigEndian ? getIntB(bb, bi) : getIntL(bb, bi) ; + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static int getInt(long a, boolean bigEndian) { + return bigEndian ? getIntB(a) : getIntL(a) ; + } + + private static byte int3(int x) { return (byte)(x >> 24); } + private static byte int2(int x) { return (byte)(x >> 16); } + private static byte int1(int x) { return (byte)(x >> 8); } + private static byte int0(int x) { return (byte)(x ); } + + static void putIntL(ByteBuffer bb, int bi, int x) { + bb._put(bi + 3, int3(x)); + bb._put(bi + 2, int2(x)); + bb._put(bi + 1, int1(x)); + bb._put(bi , int0(x)); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void putIntL(long a, int x) { + _put(a + 3, int3(x)); + _put(a + 2, int2(x)); + _put(a + 1, int1(x)); + _put(a , int0(x)); + } + + static void putIntB(ByteBuffer bb, int bi, int x) { + bb._put(bi , int3(x)); + bb._put(bi + 1, int2(x)); + bb._put(bi + 2, int1(x)); + bb._put(bi + 3, int0(x)); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void putIntB(long a, int x) { + _put(a , int3(x)); + _put(a + 1, int2(x)); + _put(a + 2, int1(x)); + _put(a + 3, int0(x)); + } + + static void putInt(ByteBuffer bb, int bi, int x, boolean bigEndian) { + if (bigEndian) + putIntB(bb, bi, x); + else + putIntL(bb, bi, x); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void putInt(long a, int x, boolean bigEndian) { + if (bigEndian) + putIntB(a, x); + else + putIntL(a, x); + } + + + // -- get/put long -- + + static private long makeLong(byte b7, byte b6, byte b5, byte b4, + byte b3, byte b2, byte b1, byte b0) + { + return ((((long)b7 ) << 56) | + (((long)b6 & 0xff) << 48) | + (((long)b5 & 0xff) << 40) | + (((long)b4 & 0xff) << 32) | + (((long)b3 & 0xff) << 24) | + (((long)b2 & 0xff) << 16) | + (((long)b1 & 0xff) << 8) | + (((long)b0 & 0xff) )); + } + + static long getLongL(ByteBuffer bb, int bi) { + return makeLong(bb._get(bi + 7), + bb._get(bi + 6), + bb._get(bi + 5), + bb._get(bi + 4), + bb._get(bi + 3), + bb._get(bi + 2), + bb._get(bi + 1), + bb._get(bi )); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static long getLongL(long a) { + return makeLong(_get(a + 7), + _get(a + 6), + _get(a + 5), + _get(a + 4), + _get(a + 3), + _get(a + 2), + _get(a + 1), + _get(a )); + } + + static long getLongB(ByteBuffer bb, int bi) { + return makeLong(bb._get(bi ), + bb._get(bi + 1), + bb._get(bi + 2), + bb._get(bi + 3), + bb._get(bi + 4), + bb._get(bi + 5), + bb._get(bi + 6), + bb._get(bi + 7)); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static long getLongB(long a) { + return makeLong(_get(a ), + _get(a + 1), + _get(a + 2), + _get(a + 3), + _get(a + 4), + _get(a + 5), + _get(a + 6), + _get(a + 7)); + } + + static long getLong(ByteBuffer bb, int bi, boolean bigEndian) { + return bigEndian ? getLongB(bb, bi) : getLongL(bb, bi); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static long getLong(long a, boolean bigEndian) { + return bigEndian ? getLongB(a) : getLongL(a); + } + + private static byte long7(long x) { return (byte)(x >> 56); } + private static byte long6(long x) { return (byte)(x >> 48); } + private static byte long5(long x) { return (byte)(x >> 40); } + private static byte long4(long x) { return (byte)(x >> 32); } + private static byte long3(long x) { return (byte)(x >> 24); } + private static byte long2(long x) { return (byte)(x >> 16); } + private static byte long1(long x) { return (byte)(x >> 8); } + private static byte long0(long x) { return (byte)(x ); } + + static void putLongL(ByteBuffer bb, int bi, long x) { + bb._put(bi + 7, long7(x)); + bb._put(bi + 6, long6(x)); + bb._put(bi + 5, long5(x)); + bb._put(bi + 4, long4(x)); + bb._put(bi + 3, long3(x)); + bb._put(bi + 2, long2(x)); + bb._put(bi + 1, long1(x)); + bb._put(bi , long0(x)); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void putLongL(long a, long x) { + _put(a + 7, long7(x)); + _put(a + 6, long6(x)); + _put(a + 5, long5(x)); + _put(a + 4, long4(x)); + _put(a + 3, long3(x)); + _put(a + 2, long2(x)); + _put(a + 1, long1(x)); + _put(a , long0(x)); + } + + static void putLongB(ByteBuffer bb, int bi, long x) { + bb._put(bi , long7(x)); + bb._put(bi + 1, long6(x)); + bb._put(bi + 2, long5(x)); + bb._put(bi + 3, long4(x)); + bb._put(bi + 4, long3(x)); + bb._put(bi + 5, long2(x)); + bb._put(bi + 6, long1(x)); + bb._put(bi + 7, long0(x)); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void putLongB(long a, long x) { + _put(a , long7(x)); + _put(a + 1, long6(x)); + _put(a + 2, long5(x)); + _put(a + 3, long4(x)); + _put(a + 4, long3(x)); + _put(a + 5, long2(x)); + _put(a + 6, long1(x)); + _put(a + 7, long0(x)); + } + + static void putLong(ByteBuffer bb, int bi, long x, boolean bigEndian) { + if (bigEndian) + putLongB(bb, bi, x); + else + putLongL(bb, bi, x); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void putLong(long a, long x, boolean bigEndian) { + if (bigEndian) + putLongB(a, x); + else + putLongL(a, x); + } + + + // -- get/put float -- + + static float getFloatL(ByteBuffer bb, int bi) { + return Float.intBitsToFloat(getIntL(bb, bi)); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static float getFloatL(long a) { + return Float.intBitsToFloat(getIntL(a)); + } + + static float getFloatB(ByteBuffer bb, int bi) { + return Float.intBitsToFloat(getIntB(bb, bi)); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static float getFloatB(long a) { + return Float.intBitsToFloat(getIntB(a)); + } + + static float getFloat(ByteBuffer bb, int bi, boolean bigEndian) { + return bigEndian ? getFloatB(bb, bi) : getFloatL(bb, bi); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static float getFloat(long a, boolean bigEndian) { + return bigEndian ? getFloatB(a) : getFloatL(a); + } + + static void putFloatL(ByteBuffer bb, int bi, float x) { + putIntL(bb, bi, Float.floatToRawIntBits(x)); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void putFloatL(long a, float x) { + putIntL(a, Float.floatToRawIntBits(x)); + } + + static void putFloatB(ByteBuffer bb, int bi, float x) { + putIntB(bb, bi, Float.floatToRawIntBits(x)); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void putFloatB(long a, float x) { + putIntB(a, Float.floatToRawIntBits(x)); + } + + static void putFloat(ByteBuffer bb, int bi, float x, boolean bigEndian) { + if (bigEndian) + putFloatB(bb, bi, x); + else + putFloatL(bb, bi, x); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void putFloat(long a, float x, boolean bigEndian) { + if (bigEndian) + putFloatB(a, x); + else + putFloatL(a, x); + } + + + // -- get/put double -- + + static double getDoubleL(ByteBuffer bb, int bi) { + return Double.longBitsToDouble(getLongL(bb, bi)); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static double getDoubleL(long a) { + return Double.longBitsToDouble(getLongL(a)); + } + + static double getDoubleB(ByteBuffer bb, int bi) { + return Double.longBitsToDouble(getLongB(bb, bi)); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static double getDoubleB(long a) { + return Double.longBitsToDouble(getLongB(a)); + } + + static double getDouble(ByteBuffer bb, int bi, boolean bigEndian) { + return bigEndian ? getDoubleB(bb, bi) : getDoubleL(bb, bi); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static double getDouble(long a, boolean bigEndian) { + return bigEndian ? getDoubleB(a) : getDoubleL(a); + } + + static void putDoubleL(ByteBuffer bb, int bi, double x) { + putLongL(bb, bi, Double.doubleToRawLongBits(x)); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void putDoubleL(long a, double x) { + putLongL(a, Double.doubleToRawLongBits(x)); + } + + static void putDoubleB(ByteBuffer bb, int bi, double x) { + putLongB(bb, bi, Double.doubleToRawLongBits(x)); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void putDoubleB(long a, double x) { + putLongB(a, Double.doubleToRawLongBits(x)); + } + + static void putDouble(ByteBuffer bb, int bi, double x, boolean bigEndian) { + if (bigEndian) + putDoubleB(bb, bi, x); + else + putDoubleL(bb, bi, x); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void putDouble(long a, double x, boolean bigEndian) { + if (bigEndian) + putDoubleB(a, x); + else + putDoubleL(a, x); + } + + + // -- Unsafe access -- + + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + @cli.System.Security.SecurityCriticalAttribute.Annotation + private static byte _get(long a) { + return unsafe.getByte(a); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + private static void _put(long a, byte b) { + unsafe.putByte(a, b); + } + + static Unsafe unsafe() { + return unsafe; + } + + + // -- Processor and memory-system properties -- + + private static final ByteOrder byteOrder; + + static ByteOrder byteOrder() { + if (byteOrder == null) + throw new Error("Unknown byte order"); + return byteOrder; + } + + static { + if (cli.System.BitConverter.IsLittleEndian) { + byteOrder = ByteOrder.LITTLE_ENDIAN; + } else { + byteOrder = ByteOrder.BIG_ENDIAN; + } + } + + + private static int pageSize = -1; + + static int pageSize() { + if (pageSize == -1) + pageSize = unsafe().pageSize(); + return pageSize; + } + + static int pageCount(long size) { + return (int)(size + (long)pageSize() - 1L) / pageSize(); + } + + private static boolean unaligned; + private static boolean unalignedKnown = false; + + static boolean unaligned() { + if (unalignedKnown) + return unaligned; + String arch = AccessController.doPrivileged( + new sun.security.action.GetPropertyAction("os.arch")); + unaligned = arch.equals("i386") || arch.equals("x86") + || arch.equals("amd64") || arch.equals("x86_64"); + unalignedKnown = true; + return unaligned; + } + + + // -- Direct memory management -- + + // A user-settable upper limit on the maximum amount of allocatable + // direct buffer memory. This value may be changed during VM + // initialization if it is launched with "-XX:MaxDirectMemorySize=". + private static volatile long maxMemory = VM.maxDirectMemory(); + private static volatile long reservedMemory; + private static volatile long totalCapacity; + private static volatile long count; + private static boolean memoryLimitSet = false; + + // These methods should be called whenever direct memory is allocated or + // freed. They allow the user to control the amount of direct memory + // which a process may access. All sizes are specified in bytes. + static void reserveMemory(long size, int cap) { + synchronized (Bits.class) { + if (!memoryLimitSet && VM.isBooted()) { + maxMemory = VM.maxDirectMemory(); + memoryLimitSet = true; + } + // -XX:MaxDirectMemorySize limits the total capacity rather than the + // actual memory usage, which will differ when buffers are page + // aligned. + if (cap <= maxMemory - totalCapacity) { + reservedMemory += size; + totalCapacity += cap; + count++; + return; + } + } + + System.gc(); + try { + Thread.sleep(100); + } catch (InterruptedException x) { + // Restore interrupt status + Thread.currentThread().interrupt(); + } + synchronized (Bits.class) { + if (totalCapacity + cap > maxMemory) + throw new OutOfMemoryError("Direct buffer memory"); + reservedMemory += size; + totalCapacity += cap; + count++; + } + + } + + static synchronized void unreserveMemory(long size, int cap) { + if (reservedMemory > 0) { + reservedMemory -= size; + totalCapacity -= cap; + count--; + assert (reservedMemory > -1); + } + } + + // -- Monitoring of direct buffer usage -- + + static { + // setup access to this package in SharedSecrets + sun.misc.SharedSecrets.setJavaNioAccess( + new sun.misc.JavaNioAccess() { + @Override + public sun.misc.JavaNioAccess.BufferPool getDirectBufferPool() { + return new sun.misc.JavaNioAccess.BufferPool() { + @Override + public String getName() { + return "direct"; + } + @Override + public long getCount() { + return Bits.count; + } + @Override + public long getTotalCapacity() { + return Bits.totalCapacity; + } + @Override + public long getMemoryUsed() { + return Bits.reservedMemory; + } + }; + } + @Override + public ByteBuffer newDirectByteBuffer(long addr, int cap, Object ob) { + return new DirectByteBuffer(addr, cap, ob); + } + @Override + public void truncate(Buffer buf) { + buf.truncate(); + } + }); + } + + // -- Bulk get/put acceleration -- + + // These numbers represent the point at which we have empirically + // determined that the average cost of a JNI call exceeds the expense + // of an element by element copy. These numbers may change over time. + static final int JNI_COPY_TO_ARRAY_THRESHOLD = 6; + static final int JNI_COPY_FROM_ARRAY_THRESHOLD = 6; + + // This number limits the number of bytes to copy per call to Unsafe's + // copyMemory method. A limit is imposed to allow for safepoint polling + // during a large copy + static final long UNSAFE_COPY_THRESHOLD = 1024L * 1024L; + + // These methods do no bounds checking. Verification that the copy will not + // result in memory corruption should be done prior to invocation. + // All positions and lengths are specified in bytes. + + /** + * Copy from given source array to destination address. + * + * @param src + * source array + * @param srcBaseOffset + * offset of first element of storage in source array + * @param srcPos + * offset within source array of the first element to read + * @param dstAddr + * destination address + * @param length + * number of bytes to copy + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void copyFromArray(Object src, long srcBaseOffset, long srcPos, + long dstAddr, long length) + { + long offset = srcBaseOffset + srcPos; + while (length > 0) { + long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length; + unsafe.copyMemory(src, offset, null, dstAddr, size); + length -= size; + offset += size; + dstAddr += size; + } + } + + /** + * Copy from source address into given destination array. + * + * @param srcAddr + * source address + * @param dst + * destination array + * @param dstBaseOffset + * offset of first element of storage in destination array + * @param dstPos + * offset within destination array of the first element to write + * @param length + * number of bytes to copy + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void copyToArray(long srcAddr, Object dst, long dstBaseOffset, long dstPos, + long length) + { + long offset = dstBaseOffset + dstPos; + while (length > 0) { + long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length; + unsafe.copyMemory(null, srcAddr, dst, offset, size); + length -= size; + srcAddr += size; + offset += size; + } + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void copyFromCharArray(Object src, long srcPos, long dstAddr, + long length) + { + copyFromShortArray(src, srcPos, dstAddr, length); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static void copyToCharArray(long srcAddr, Object dst, long dstPos, + long length) + { + copyToShortArray(srcAddr, dst, dstPos, length); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static native void copyFromShortArray(Object src, long srcPos, long dstAddr, + long length); + @cli.System.Security.SecurityCriticalAttribute.Annotation + static native void copyToShortArray(long srcAddr, Object dst, long dstPos, + long length); + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static native void copyFromIntArray(Object src, long srcPos, long dstAddr, + long length); + @cli.System.Security.SecurityCriticalAttribute.Annotation + static native void copyToIntArray(long srcAddr, Object dst, long dstPos, + long length); + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static native void copyFromLongArray(Object src, long srcPos, long dstAddr, + long length); + @cli.System.Security.SecurityCriticalAttribute.Annotation + static native void copyToLongArray(long srcAddr, Object dst, long dstPos, + long length); + +} diff --git a/openjdk/java/security/AccessController.java b/openjdk/java/security/AccessController.java new file mode 100644 index 0000000..f87fe25 --- /dev/null +++ b/openjdk/java/security/AccessController.java @@ -0,0 +1,960 @@ +/* + * Copyright (c) 1997, 2013, 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 java.security; + +import ikvm.internal.CallerID; +import sun.security.util.Debug; +import sun.reflect.CallerSensitive; +import sun.reflect.Reflection; + +/** + *

The AccessController class is used for access control operations + * and decisions. + * + *

More specifically, the AccessController class is used for + * three purposes: + * + *

    + *
  • to decide whether an access to a critical system + * resource is to be allowed or denied, based on the security policy + * currently in effect, + *
  • to mark code as being "privileged", thus affecting subsequent + * access determinations, and + *
  • to obtain a "snapshot" of the current calling context so + * access-control decisions from a different context can be made with + * respect to the saved context.
+ * + *

The {@link #checkPermission(Permission) checkPermission} method + * determines whether the access request indicated by a specified + * permission should be granted or denied. A sample call appears + * below. In this example, {@code checkPermission} will determine + * whether or not to grant "read" access to the file named "testFile" in + * the "/temp" directory. + * + *

+ *
+ * FilePermission perm = new FilePermission("/temp/testFile", "read");
+ * AccessController.checkPermission(perm);
+ *
+ * 
+ * + *

If a requested access is allowed, + * {@code checkPermission} returns quietly. If denied, an + * AccessControlException is + * thrown. AccessControlException can also be thrown if the requested + * permission is of an incorrect type or contains an invalid value. + * Such information is given whenever possible. + * + * Suppose the current thread traversed m callers, in the order of caller 1 + * to caller 2 to caller m. Then caller m invoked the + * {@code checkPermission} method. + * The {@code checkPermission} method determines whether access + * is granted or denied based on the following algorithm: + * + *

 {@code
+ * for (int i = m; i > 0; i--) {
+ *
+ *     if (caller i's domain does not have the permission)
+ *         throw AccessControlException
+ *
+ *     else if (caller i is marked as privileged) {
+ *         if (a context was specified in the call to doPrivileged)
+ *             context.checkPermission(permission)
+ *         if (limited permissions were specified in the call to doPrivileged) {
+ *             for (each limited permission) {
+ *                 if (the limited permission implies the requested permission)
+ *                     return;
+ *             }
+ *         } else
+ *             return;
+ *     }
+ * }
+ *
+ * // Next, check the context inherited when the thread was created.
+ * // Whenever a new thread is created, the AccessControlContext at
+ * // that time is stored and associated with the new thread, as the
+ * // "inherited" context.
+ *
+ * inheritedContext.checkPermission(permission);
+ * }
+ * + *

A caller can be marked as being "privileged" + * (see {@link #doPrivileged(PrivilegedAction) doPrivileged} and below). + * When making access control decisions, the {@code checkPermission} + * method stops checking if it reaches a caller that + * was marked as "privileged" via a {@code doPrivileged} + * call without a context argument (see below for information about a + * context argument). If that caller's domain has the + * specified permission and at least one limiting permission argument (if any) + * implies the requested permission, no further checking is done and + * {@code checkPermission} + * returns quietly, indicating that the requested access is allowed. + * If that domain does not have the specified permission, an exception + * is thrown, as usual. If the caller's domain had the specified permission + * but it was not implied by any limiting permission arguments given in the call + * to {@code doPrivileged} then the permission checking continues + * until there are no more callers or another {@code doPrivileged} + * call matches the requested permission and returns normally. + * + *

The normal use of the "privileged" feature is as follows. If you + * don't need to return a value from within the "privileged" block, do + * the following: + * + *

 {@code
+ * somemethod() {
+ *     ...normal code here...
+ *     AccessController.doPrivileged(new PrivilegedAction() {
+ *         public Void run() {
+ *             // privileged code goes here, for example:
+ *             System.loadLibrary("awt");
+ *             return null; // nothing to return
+ *         }
+ *     });
+ *     ...normal code here...
+ * }}
+ * + *

+ * PrivilegedAction is an interface with a single method, named + * {@code run}. + * The above example shows creation of an implementation + * of that interface; a concrete implementation of the + * {@code run} method is supplied. + * When the call to {@code doPrivileged} is made, an + * instance of the PrivilegedAction implementation is passed + * to it. The {@code doPrivileged} method calls the + * {@code run} method from the PrivilegedAction + * implementation after enabling privileges, and returns the + * {@code run} method's return value as the + * {@code doPrivileged} return value (which is + * ignored in this example). + * + *

If you need to return a value, you can do something like the following: + * + *

 {@code
+ * somemethod() {
+ *     ...normal code here...
+ *     String user = AccessController.doPrivileged(
+ *         new PrivilegedAction() {
+ *         public String run() {
+ *             return System.getProperty("user.name");
+ *             }
+ *         });
+ *     ...normal code here...
+ * }}
+ * + *

If the action performed in your {@code run} method could + * throw a "checked" exception (those listed in the {@code throws} clause + * of a method), then you need to use the + * {@code PrivilegedExceptionAction} interface instead of the + * {@code PrivilegedAction} interface: + * + *

 {@code
+ * somemethod() throws FileNotFoundException {
+ *     ...normal code here...
+ *     try {
+ *         FileInputStream fis = AccessController.doPrivileged(
+ *         new PrivilegedExceptionAction() {
+ *             public FileInputStream run() throws FileNotFoundException {
+ *                 return new FileInputStream("someFile");
+ *             }
+ *         });
+ *     } catch (PrivilegedActionException e) {
+ *         // e.getException() should be an instance of FileNotFoundException,
+ *         // as only "checked" exceptions will be "wrapped" in a
+ *         // PrivilegedActionException.
+ *         throw (FileNotFoundException) e.getException();
+ *     }
+ *     ...normal code here...
+ *  }}
+ * + *

Be *very* careful in your use of the "privileged" construct, and + * always remember to make the privileged code section as small as possible. + * You can pass {@code Permission} arguments to further limit the + * scope of the "privilege" (see below). + * + * + *

Note that {@code checkPermission} always performs security checks + * within the context of the currently executing thread. + * Sometimes a security check that should be made within a given context + * will actually need to be done from within a + * different context (for example, from within a worker thread). + * The {@link #getContext() getContext} method and + * AccessControlContext class are provided + * for this situation. The {@code getContext} method takes a "snapshot" + * of the current calling context, and places + * it in an AccessControlContext object, which it returns. A sample call is + * the following: + * + *

+ *
+ * AccessControlContext acc = AccessController.getContext()
+ *
+ * 
+ * + *

+ * AccessControlContext itself has a {@code checkPermission} method + * that makes access decisions based on the context it encapsulates, + * rather than that of the current execution thread. + * Code within a different context can thus call that method on the + * previously-saved AccessControlContext object. A sample call is the + * following: + * + *

+ *
+ * acc.checkPermission(permission)
+ *
+ * 
+ * + *

There are also times where you don't know a priori which permissions + * to check the context against. In these cases you can use the + * doPrivileged method that takes a context. You can also limit the scope + * of the privileged code by passing additional {@code Permission} + * parameters. + * + *

 {@code
+ * somemethod() {
+ *     AccessController.doPrivileged(new PrivilegedAction() {
+ *         public Object run() {
+ *             // Code goes here. Any permission checks within this
+ *             // run method will require that the intersection of the
+ *             // caller's protection domain and the snapshot's
+ *             // context have the desired permission. If a requested
+ *             // permission is not implied by the limiting FilePermission
+ *             // argument then checking of the thread continues beyond the
+ *             // caller of doPrivileged.
+ *         }
+ *     }, acc, new FilePermission("/temp/*", read));
+ *     ...normal code here...
+ * }}
+ * 

Passing a limiting {@code Permission} argument of an instance of + * {@code AllPermission} is equivalent to calling the equivalent + * {@code doPrivileged} method without limiting {@code Permission} + * arguments. Passing a zero length array of {@code Permission} disables + * the code privileges so that checking always continues beyond the caller of + * that {@code doPrivileged} method. + * + * @see AccessControlContext + * + * @author Li Gong + * @author Roland Schemers + */ + +public final class AccessController { + + @cli.System.ThreadStaticAttribute.Annotation + private static PrivilegedElement privileged_stack_top; + + @ikvm.lang.Internal + public static final class LazyContext { + LazyContext parent; + CallerID callerID; + AccessControlContext context; + final cli.System.Diagnostics.StackTrace stackTrace = new cli.System.Diagnostics.StackTrace(1); + } + + @ikvm.lang.Internal + public static Object getLazyContext(Object parent) { + if (!(parent instanceof LazyContext)) { + // we don't have an optimized path if the current thread already has an AccessControlContext + // instead of a LazyContext, because this is not worth it + return getContext(); + } + LazyContext lc = new LazyContext(); + lc.parent = (LazyContext)parent; + if (privileged_stack_top != null) { + lc.callerID = privileged_stack_top.callerID; + lc.context = privileged_stack_top.context; + } + return lc; + } + + private static final class PrivilegedElement { + CallerID callerID; + AccessControlContext context; + } + + private static Object doPrivileged(Object action, AccessControlContext context, CallerID callerID) { + PrivilegedElement savedPrivilegedElement = privileged_stack_top; + try { + PrivilegedElement pi = new PrivilegedElement(); + pi.callerID = callerID; + pi.context = context; + privileged_stack_top = pi; + try { + if (action instanceof PrivilegedAction) { + return ((PrivilegedAction)action).run(); + } else { + return ((PrivilegedExceptionAction)action).run(); + } + } catch (Exception x) { + if (!(x instanceof RuntimeException)) { + sun.misc.Unsafe.getUnsafe().throwException(new PrivilegedActionException(x)); + } + throw (RuntimeException)x; + } + } finally { + privileged_stack_top = savedPrivilegedElement; + } + } + + /** + * Don't allow anyone to instantiate an AccessController + */ + private AccessController() { } + + /** + * Performs the specified {@code PrivilegedAction} with privileges + * enabled. The action is performed with all of the permissions + * possessed by the caller's protection domain. + * + *

If the action's {@code run} method throws an (unchecked) + * exception, it will propagate through this method. + * + *

Note that any DomainCombiner associated with the current + * AccessControlContext will be ignored while the action is performed. + * + * @param the type of the value returned by the PrivilegedAction's + * {@code run} method. + * + * @param action the action to be performed. + * + * @return the value returned by the action's {@code run} method. + * + * @exception NullPointerException if the action is {@code null} + * + * @see #doPrivileged(PrivilegedAction,AccessControlContext) + * @see #doPrivileged(PrivilegedExceptionAction) + * @see #doPrivilegedWithCombiner(PrivilegedAction) + * @see java.security.DomainCombiner + */ + + @CallerSensitive + public static T doPrivileged(PrivilegedAction action) { + return (T)doPrivileged(action, null, CallerID.getCallerID()); + } + + /** + * Performs the specified {@code PrivilegedAction} with privileges + * enabled. The action is performed with all of the permissions + * possessed by the caller's protection domain. + * + *

If the action's {@code run} method throws an (unchecked) + * exception, it will propagate through this method. + * + *

This method preserves the current AccessControlContext's + * DomainCombiner (which may be null) while the action is performed. + * + * @param the type of the value returned by the PrivilegedAction's + * {@code run} method. + * + * @param action the action to be performed. + * + * @return the value returned by the action's {@code run} method. + * + * @exception NullPointerException if the action is {@code null} + * + * @see #doPrivileged(PrivilegedAction) + * @see java.security.DomainCombiner + * + * @since 1.6 + */ + @CallerSensitive + public static T doPrivilegedWithCombiner(PrivilegedAction action) { + AccessControlContext acc = getStackAccessControlContext(); + if (acc == null) { + return AccessController.doPrivileged(action); + } + DomainCombiner dc = acc.getAssignedCombiner(); + return AccessController.doPrivileged(action, + preserveCombiner(dc, Reflection.getCallerClass())); + } + + + /** + * Performs the specified {@code PrivilegedAction} with privileges + * enabled and restricted by the specified {@code AccessControlContext}. + * The action is performed with the intersection of the permissions + * possessed by the caller's protection domain, and those possessed + * by the domains represented by the specified {@code AccessControlContext}. + *

+ * If the action's {@code run} method throws an (unchecked) exception, + * it will propagate through this method. + *

+ * If a security manager is installed and the specified + * {@code AccessControlContext} was not created by system code and the + * caller's {@code ProtectionDomain} has not been granted the + * {@literal "createAccessControlContext"} + * {@link java.security.SecurityPermission}, then the action is performed + * with no permissions. + * + * @param the type of the value returned by the PrivilegedAction's + * {@code run} method. + * @param action the action to be performed. + * @param context an access control context + * representing the restriction to be applied to the + * caller's domain's privileges before performing + * the specified action. If the context is + * {@code null}, then no additional restriction is applied. + * + * @return the value returned by the action's {@code run} method. + * + * @exception NullPointerException if the action is {@code null} + * + * @see #doPrivileged(PrivilegedAction) + * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) + */ + @CallerSensitive + public static T doPrivileged(PrivilegedAction action, + AccessControlContext context) { + return (T)doPrivileged(action, context, CallerID.getCallerID()); + } + + + /** + * Performs the specified {@code PrivilegedAction} with privileges + * enabled and restricted by the specified + * {@code AccessControlContext} and with a privilege scope limited + * by specified {@code Permission} arguments. + * + * The action is performed with the intersection of the permissions + * possessed by the caller's protection domain, and those possessed + * by the domains represented by the specified + * {@code AccessControlContext}. + *

+ * If the action's {@code run} method throws an (unchecked) exception, + * it will propagate through this method. + *

+ * If a security manager is installed and the specified + * {@code AccessControlContext} was not created by system code and the + * caller's {@code ProtectionDomain} has not been granted the + * {@literal "createAccessControlContext"} + * {@link java.security.SecurityPermission}, then the action is performed + * with no permissions. + * + * @param the type of the value returned by the PrivilegedAction's + * {@code run} method. + * @param action the action to be performed. + * @param context an access control context + * representing the restriction to be applied to the + * caller's domain's privileges before performing + * the specified action. If the context is + * {@code null}, + * then no additional restriction is applied. + * @param perms the {@code Permission} arguments which limit the + * scope of the caller's privileges. The number of arguments + * is variable. + * + * @return the value returned by the action's {@code run} method. + * + * @throws NullPointerException if action or perms or any element of + * perms is {@code null} + * + * @see #doPrivileged(PrivilegedAction) + * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) + * + * @since 1.8 + */ + @CallerSensitive + public static T doPrivileged(PrivilegedAction action, + AccessControlContext context, Permission... perms) { + + AccessControlContext parent = getContext(); + if (perms == null) { + throw new NullPointerException("null permissions parameter"); + } + Class caller = Reflection.getCallerClass(); + return AccessController.doPrivileged(action, createWrapper(null, + caller, parent, context, perms)); + } + + + /** + * Performs the specified {@code PrivilegedAction} with privileges + * enabled and restricted by the specified + * {@code AccessControlContext} and with a privilege scope limited + * by specified {@code Permission} arguments. + * + * The action is performed with the intersection of the permissions + * possessed by the caller's protection domain, and those possessed + * by the domains represented by the specified + * {@code AccessControlContext}. + *

+ * If the action's {@code run} method throws an (unchecked) exception, + * it will propagate through this method. + * + *

This method preserves the current AccessControlContext's + * DomainCombiner (which may be null) while the action is performed. + *

+ * If a security manager is installed and the specified + * {@code AccessControlContext} was not created by system code and the + * caller's {@code ProtectionDomain} has not been granted the + * {@literal "createAccessControlContext"} + * {@link java.security.SecurityPermission}, then the action is performed + * with no permissions. + * + * @param the type of the value returned by the PrivilegedAction's + * {@code run} method. + * @param action the action to be performed. + * @param context an access control context + * representing the restriction to be applied to the + * caller's domain's privileges before performing + * the specified action. If the context is + * {@code null}, + * then no additional restriction is applied. + * @param perms the {@code Permission} arguments which limit the + * scope of the caller's privileges. The number of arguments + * is variable. + * + * @return the value returned by the action's {@code run} method. + * + * @throws NullPointerException if action or perms or any element of + * perms is {@code null} + * + * @see #doPrivileged(PrivilegedAction) + * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) + * @see java.security.DomainCombiner + * + * @since 1.8 + */ + @CallerSensitive + public static T doPrivilegedWithCombiner(PrivilegedAction action, + AccessControlContext context, Permission... perms) { + + AccessControlContext parent = getContext(); + DomainCombiner dc = parent.getCombiner(); + if (dc == null && context != null) { + dc = context.getCombiner(); + } + if (perms == null) { + throw new NullPointerException("null permissions parameter"); + } + Class caller = Reflection.getCallerClass(); + return AccessController.doPrivileged(action, createWrapper(dc, caller, + parent, context, perms)); + } + + /** + * Performs the specified {@code PrivilegedExceptionAction} with + * privileges enabled. The action is performed with all of the + * permissions possessed by the caller's protection domain. + * + *

If the action's {@code run} method throws an unchecked + * exception, it will propagate through this method. + * + *

Note that any DomainCombiner associated with the current + * AccessControlContext will be ignored while the action is performed. + * + * @param the type of the value returned by the + * PrivilegedExceptionAction's {@code run} method. + * + * @param action the action to be performed + * + * @return the value returned by the action's {@code run} method + * + * @exception PrivilegedActionException if the specified action's + * {@code run} method threw a checked exception + * @exception NullPointerException if the action is {@code null} + * + * @see #doPrivileged(PrivilegedAction) + * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) + * @see #doPrivilegedWithCombiner(PrivilegedExceptionAction) + * @see java.security.DomainCombiner + */ + @CallerSensitive + public static T + doPrivileged(PrivilegedExceptionAction action) + throws PrivilegedActionException { + return (T)doPrivileged(action, null, CallerID.getCallerID()); + } + + + /** + * Performs the specified {@code PrivilegedExceptionAction} with + * privileges enabled. The action is performed with all of the + * permissions possessed by the caller's protection domain. + * + *

If the action's {@code run} method throws an unchecked + * exception, it will propagate through this method. + * + *

This method preserves the current AccessControlContext's + * DomainCombiner (which may be null) while the action is performed. + * + * @param the type of the value returned by the + * PrivilegedExceptionAction's {@code run} method. + * + * @param action the action to be performed. + * + * @return the value returned by the action's {@code run} method + * + * @exception PrivilegedActionException if the specified action's + * {@code run} method threw a checked exception + * @exception NullPointerException if the action is {@code null} + * + * @see #doPrivileged(PrivilegedAction) + * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) + * @see java.security.DomainCombiner + * + * @since 1.6 + */ + @CallerSensitive + public static T doPrivilegedWithCombiner(PrivilegedExceptionAction action) + throws PrivilegedActionException + { + AccessControlContext acc = getStackAccessControlContext(); + if (acc == null) { + return AccessController.doPrivileged(action); + } + DomainCombiner dc = acc.getAssignedCombiner(); + return AccessController.doPrivileged(action, + preserveCombiner(dc, Reflection.getCallerClass())); + } + + /** + * preserve the combiner across the doPrivileged call + */ + private static AccessControlContext preserveCombiner(DomainCombiner combiner, + Class caller) + { + return createWrapper(combiner, caller, null, null, null); + } + + /** + * Create a wrapper to contain the limited privilege scope data. + */ + private static AccessControlContext + createWrapper(DomainCombiner combiner, Class caller, + AccessControlContext parent, AccessControlContext context, + Permission[] perms) + { + ProtectionDomain callerPD = getCallerPD(caller); + // check if caller is authorized to create context + if (context != null && !context.isAuthorized() && + System.getSecurityManager() != null && + !callerPD.impliesCreateAccessControlContext()) + { + ProtectionDomain nullPD = new ProtectionDomain(null, null); + return new AccessControlContext(new ProtectionDomain[] { nullPD }); + } else { + return new AccessControlContext(callerPD, combiner, parent, + context, perms); + } + } + + private static ProtectionDomain getCallerPD(final Class caller) { + ProtectionDomain callerPd = doPrivileged + (new PrivilegedAction() { + public ProtectionDomain run() { + return caller.getProtectionDomain(); + } + }); + + return callerPd; + } + + /** + * Performs the specified {@code PrivilegedExceptionAction} with + * privileges enabled and restricted by the specified + * {@code AccessControlContext}. The action is performed with the + * intersection of the permissions possessed by the caller's + * protection domain, and those possessed by the domains represented by the + * specified {@code AccessControlContext}. + *

+ * If the action's {@code run} method throws an unchecked + * exception, it will propagate through this method. + *

+ * If a security manager is installed and the specified + * {@code AccessControlContext} was not created by system code and the + * caller's {@code ProtectionDomain} has not been granted the + * {@literal "createAccessControlContext"} + * {@link java.security.SecurityPermission}, then the action is performed + * with no permissions. + * + * @param the type of the value returned by the + * PrivilegedExceptionAction's {@code run} method. + * @param action the action to be performed + * @param context an access control context + * representing the restriction to be applied to the + * caller's domain's privileges before performing + * the specified action. If the context is + * {@code null}, then no additional restriction is applied. + * + * @return the value returned by the action's {@code run} method + * + * @exception PrivilegedActionException if the specified action's + * {@code run} method threw a checked exception + * @exception NullPointerException if the action is {@code null} + * + * @see #doPrivileged(PrivilegedAction) + * @see #doPrivileged(PrivilegedAction,AccessControlContext) + */ + @CallerSensitive + public static T + doPrivileged(PrivilegedExceptionAction action, + AccessControlContext context) + throws PrivilegedActionException { + return (T)doPrivileged(action, context, CallerID.getCallerID()); + } + + /** + * Performs the specified {@code PrivilegedExceptionAction} with + * privileges enabled and restricted by the specified + * {@code AccessControlContext} and with a privilege scope limited by + * specified {@code Permission} arguments. + * + * The action is performed with the intersection of the permissions + * possessed by the caller's protection domain, and those possessed + * by the domains represented by the specified + * {@code AccessControlContext}. + *

+ * If the action's {@code run} method throws an (unchecked) exception, + * it will propagate through this method. + *

+ * If a security manager is installed and the specified + * {@code AccessControlContext} was not created by system code and the + * caller's {@code ProtectionDomain} has not been granted the + * {@literal "createAccessControlContext"} + * {@link java.security.SecurityPermission}, then the action is performed + * with no permissions. + * + * @param the type of the value returned by the + * PrivilegedExceptionAction's {@code run} method. + * @param action the action to be performed. + * @param context an access control context + * representing the restriction to be applied to the + * caller's domain's privileges before performing + * the specified action. If the context is + * {@code null}, + * then no additional restriction is applied. + * @param perms the {@code Permission} arguments which limit the + * scope of the caller's privileges. The number of arguments + * is variable. + * + * @return the value returned by the action's {@code run} method. + * + * @throws PrivilegedActionException if the specified action's + * {@code run} method threw a checked exception + * @throws NullPointerException if action or perms or any element of + * perms is {@code null} + * + * @see #doPrivileged(PrivilegedAction) + * @see #doPrivileged(PrivilegedAction,AccessControlContext) + * + * @since 1.8 + */ + @CallerSensitive + public static T doPrivileged(PrivilegedExceptionAction action, + AccessControlContext context, Permission... perms) + throws PrivilegedActionException + { + AccessControlContext parent = getContext(); + if (perms == null) { + throw new NullPointerException("null permissions parameter"); + } + Class caller = Reflection.getCallerClass(); + return AccessController.doPrivileged(action, createWrapper(null, caller, parent, context, perms)); + } + + + /** + * Performs the specified {@code PrivilegedExceptionAction} with + * privileges enabled and restricted by the specified + * {@code AccessControlContext} and with a privilege scope limited by + * specified {@code Permission} arguments. + * + * The action is performed with the intersection of the permissions + * possessed by the caller's protection domain, and those possessed + * by the domains represented by the specified + * {@code AccessControlContext}. + *

+ * If the action's {@code run} method throws an (unchecked) exception, + * it will propagate through this method. + * + *

This method preserves the current AccessControlContext's + * DomainCombiner (which may be null) while the action is performed. + *

+ * If a security manager is installed and the specified + * {@code AccessControlContext} was not created by system code and the + * caller's {@code ProtectionDomain} has not been granted the + * {@literal "createAccessControlContext"} + * {@link java.security.SecurityPermission}, then the action is performed + * with no permissions. + * + * @param the type of the value returned by the + * PrivilegedExceptionAction's {@code run} method. + * @param action the action to be performed. + * @param context an access control context + * representing the restriction to be applied to the + * caller's domain's privileges before performing + * the specified action. If the context is + * {@code null}, + * then no additional restriction is applied. + * @param perms the {@code Permission} arguments which limit the + * scope of the caller's privileges. The number of arguments + * is variable. + * + * @return the value returned by the action's {@code run} method. + * + * @throws PrivilegedActionException if the specified action's + * {@code run} method threw a checked exception + * @throws NullPointerException if action or perms or any element of + * perms is {@code null} + * + * @see #doPrivileged(PrivilegedAction) + * @see #doPrivileged(PrivilegedAction,AccessControlContext) + * @see java.security.DomainCombiner + * + * @since 1.8 + */ + @CallerSensitive + public static T doPrivilegedWithCombiner(PrivilegedExceptionAction action, + AccessControlContext context, + Permission... perms) + throws PrivilegedActionException + { + AccessControlContext parent = getContext(); + DomainCombiner dc = parent.getCombiner(); + if (dc == null && context != null) { + dc = context.getCombiner(); + } + if (perms == null) { + throw new NullPointerException("null permissions parameter"); + } + Class caller = Reflection.getCallerClass(); + return AccessController.doPrivileged(action, createWrapper(dc, caller, + parent, context, perms)); + } + + /** + * Returns the AccessControl context. i.e., it gets + * the protection domains of all the callers on the stack, + * starting at the first class with a non-null + * ProtectionDomain. + * + * @return the access control context based on the current stack or + * null if there was only privileged system code. + */ + + private static AccessControlContext getStackAccessControlContext() { + AccessControlContext context = null; + CallerID callerID = null; + PrivilegedElement pi = privileged_stack_top; + if (pi != null) { + context = pi.context; + callerID = pi.callerID; + } + return getStackAccessControlContext(context, callerID); + } + + private static native AccessControlContext getStackAccessControlContext(AccessControlContext context, CallerID callerID); + + /** + * Returns the "inherited" AccessControl context. This is the context + * that existed when the thread was created. Package private so + * AccessControlContext can use it. + */ + + static native AccessControlContext getInheritedAccessControlContext(); + + /** + * This method takes a "snapshot" of the current calling context, which + * includes the current Thread's inherited AccessControlContext and any + * limited privilege scope, and places it in an AccessControlContext object. + * This context may then be checked at a later point, possibly in another thread. + * + * @see AccessControlContext + * + * @return the AccessControlContext based on the current context. + */ + + public static AccessControlContext getContext() + { + AccessControlContext acc = getStackAccessControlContext(); + if (acc == null) { + // all we had was privileged system code. We don't want + // to return null though, so we construct a real ACC. + return new AccessControlContext(null, true); + } else { + return acc.optimize(); + } + } + + /** + * Determines whether the access request indicated by the + * specified permission should be allowed or denied, based on + * the current AccessControlContext and security policy. + * This method quietly returns if the access request + * is permitted, or throws an AccessControlException otherwise. The + * getPermission method of the AccessControlException returns the + * {@code perm} Permission object instance. + * + * @param perm the requested permission. + * + * @exception AccessControlException if the specified permission + * is not permitted, based on the current security policy. + * @exception NullPointerException if the specified permission + * is {@code null} and is checked based on the + * security policy currently in effect. + */ + + public static void checkPermission(Permission perm) + throws AccessControlException + { + //System.err.println("checkPermission "+perm); + //Thread.currentThread().dumpStack(); + + if (perm == null) { + throw new NullPointerException("permission can't be null"); + } + + AccessControlContext stack = getStackAccessControlContext(); + // if context is null, we had privileged system code on the stack. + if (stack == null) { + Debug debug = AccessControlContext.getDebug(); + boolean dumpDebug = false; + if (debug != null) { + dumpDebug = !Debug.isOn("codebase="); + dumpDebug &= !Debug.isOn("permission=") || + Debug.isOn("permission=" + perm.getClass().getCanonicalName()); + } + + if (dumpDebug && Debug.isOn("stack")) { + Thread.dumpStack(); + } + + if (dumpDebug && Debug.isOn("domain")) { + debug.println("domain (context is null)"); + } + + if (dumpDebug) { + debug.println("access allowed "+perm); + } + return; + } + + AccessControlContext acc = stack.optimize(); + acc.checkPermission(perm); + } +} diff --git a/openjdk/java/security/ProtectionDomain.java b/openjdk/java/security/ProtectionDomain.java new file mode 100644 index 0000000..7e05249 --- /dev/null +++ b/openjdk/java/security/ProtectionDomain.java @@ -0,0 +1,532 @@ +/* + * Copyright (c) 1997, 2013, 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 java.security; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; +import sun.misc.JavaSecurityProtectionDomainAccess; +import static sun.misc.JavaSecurityProtectionDomainAccess.ProtectionDomainCache; +import sun.security.util.Debug; +import sun.security.util.SecurityConstants; +import sun.misc.JavaSecurityAccess; +import sun.misc.SharedSecrets; + +/** + * + *

+ * This ProtectionDomain class encapsulates the characteristics of a domain, + * which encloses a set of classes whose instances are granted a set + * of permissions when being executed on behalf of a given set of Principals. + *

+ * A static set of permissions can be bound to a ProtectionDomain when it is + * constructed; such permissions are granted to the domain regardless of the + * Policy in force. However, to support dynamic security policies, a + * ProtectionDomain can also be constructed such that it is dynamically + * mapped to a set of permissions by the current Policy whenever a permission + * is checked. + *

+ * + * @author Li Gong + * @author Roland Schemers + * @author Gary Ellison + */ + +public class ProtectionDomain { + + static { + // Set up JavaSecurityAccess in SharedSecrets + SharedSecrets.setJavaSecurityAccess( + new JavaSecurityAccess() { + public T doIntersectionPrivilege( + PrivilegedAction action, + final AccessControlContext stack, + final AccessControlContext context) + { + if (action == null) { + throw new NullPointerException(); + } + return AccessController.doPrivileged( + action, + new AccessControlContext( + stack.getContext(), context).optimize() + ); + } + + public T doIntersectionPrivilege( + PrivilegedAction action, + AccessControlContext context) + { + return doIntersectionPrivilege(action, + AccessController.getContext(), context); + } + } + ); + } + + /* CodeSource */ + private CodeSource codesource ; + + /* [IKVM] If this is a protection from an Assembly class loader, we lazily construct the codesource, classloader and permissions */ + private cli.System.Reflection.Assembly assembly; + + /* ClassLoader the protection domain was consed from */ + private ClassLoader classloader; + + /* Principals running-as within this protection domain */ + private Principal[] principals; + + /* the rights this protection domain is granted */ + private PermissionCollection permissions; + + /* if the permissions object has AllPermission */ + private boolean hasAllPerm = false; + + /* the PermissionCollection is static (pre 1.4 constructor) + or dynamic (via a policy refresh) */ + private boolean staticPermissions; + + /* + * An object used as a key when the ProtectionDomain is stored in a Map. + */ + final Key key = new Key(); + + /* [IKVM] constructor for use by the runtime (AssemblyClassLoader) */ + ProtectionDomain(cli.System.Reflection.Assembly assembly) { + this.assembly = assembly; + this.hasAllPerm = true; + this.staticPermissions = true; + this.principals = new Principal[0]; + } + + /* [IKVM] */ + private void lazyInitClassLoader() { + if (classloader == null && assembly != null) { + classloader = ikvm.runtime.AssemblyClassLoader.getAssemblyClassLoader(assembly); + } + } + + /* [IKVM] */ + private void lazyInitPermissions() { + if (permissions == null && hasAllPerm) { + Permissions p = new Permissions(); + p.add(new AllPermission()); + p.setReadOnly(); + // we lock on principals since that is a private object + synchronized (principals) { + if (permissions == null) { + permissions = p; + } + } + } + } + + /* [IKVM] */ + private void lazyInitCodeSource() { + if (codesource == null && assembly != null) { + java.net.URL url; + try { + if (false) throw new cli.System.NotSupportedException(); + url = new java.net.URL(assembly.get_EscapedCodeBase()); + } catch (java.net.MalformedURLException _) { + url = null; + } catch (cli.System.NotSupportedException _) { + // dynamic assemblies don't have a codebase + url = null; + } + CodeSource cs = new CodeSource(url, (java.security.cert.Certificate[])null); + // we lock on principals since that is a private object + synchronized (principals) { + if (codesource == null) { + codesource = cs; + } + } + } + } + + /** + * Creates a new ProtectionDomain with the given CodeSource and + * Permissions. If the permissions object is not null, then + * {@code setReadOnly())} will be called on the passed in + * Permissions object. The only permissions granted to this domain + * are the ones specified; the current Policy will not be consulted. + * + * @param codesource the codesource associated with this domain + * @param permissions the permissions granted to this domain + */ + public ProtectionDomain(CodeSource codesource, + PermissionCollection permissions) { + this.codesource = codesource; + if (permissions != null) { + this.permissions = permissions; + this.permissions.setReadOnly(); + if (permissions instanceof Permissions && + ((Permissions)permissions).allPermission != null) { + hasAllPerm = true; + } + } + this.classloader = null; + this.principals = new Principal[0]; + staticPermissions = true; + } + + /** + * Creates a new ProtectionDomain qualified by the given CodeSource, + * Permissions, ClassLoader and array of Principals. If the + * permissions object is not null, then {@code setReadOnly()} + * will be called on the passed in Permissions object. + * The permissions granted to this domain are dynamic; they include + * both the static permissions passed to this constructor, and any + * permissions granted to this domain by the current Policy at the + * time a permission is checked. + *

+ * This constructor is typically used by + * {@link SecureClassLoader ClassLoaders} + * and {@link DomainCombiner DomainCombiners} which delegate to + * {@code Policy} to actively associate the permissions granted to + * this domain. This constructor affords the + * Policy provider the opportunity to augment the supplied + * PermissionCollection to reflect policy changes. + *

+ * + * @param codesource the CodeSource associated with this domain + * @param permissions the permissions granted to this domain + * @param classloader the ClassLoader associated with this domain + * @param principals the array of Principals associated with this + * domain. The contents of the array are copied to protect against + * subsequent modification. + * @see Policy#refresh + * @see Policy#getPermissions(ProtectionDomain) + * @since 1.4 + */ + public ProtectionDomain(CodeSource codesource, + PermissionCollection permissions, + ClassLoader classloader, + Principal[] principals) { + this.codesource = codesource; + if (permissions != null) { + this.permissions = permissions; + this.permissions.setReadOnly(); + if (permissions instanceof Permissions && + ((Permissions)permissions).allPermission != null) { + hasAllPerm = true; + } + } + this.classloader = classloader; + this.principals = (principals != null ? principals.clone(): + new Principal[0]); + staticPermissions = false; + } + + /** + * Returns the CodeSource of this domain. + * @return the CodeSource of this domain which may be null. + * @since 1.2 + */ + public final CodeSource getCodeSource() { + lazyInitCodeSource(); + return this.codesource; + } + + + /** + * Returns the ClassLoader of this domain. + * @return the ClassLoader of this domain which may be null. + * + * @since 1.4 + */ + public final ClassLoader getClassLoader() { + lazyInitClassLoader(); + return this.classloader; + } + + + /** + * Returns an array of principals for this domain. + * @return a non-null array of principals for this domain. + * Returns a new array each time this method is called. + * + * @since 1.4 + */ + public final Principal[] getPrincipals() { + return this.principals.clone(); + } + + /** + * Returns the static permissions granted to this domain. + * + * @return the static set of permissions for this domain which may be null. + * @see Policy#refresh + * @see Policy#getPermissions(ProtectionDomain) + */ + public final PermissionCollection getPermissions() { + lazyInitPermissions(); + return permissions; + } + + /** + * Check and see if this ProtectionDomain implies the permissions + * expressed in the Permission object. + *

+ * The set of permissions evaluated is a function of whether the + * ProtectionDomain was constructed with a static set of permissions + * or it was bound to a dynamically mapped set of permissions. + *

+ * If the ProtectionDomain was constructed to a + * {@link #ProtectionDomain(CodeSource, PermissionCollection) + * statically bound} PermissionCollection then the permission will + * only be checked against the PermissionCollection supplied at + * construction. + *

+ * However, if the ProtectionDomain was constructed with + * the constructor variant which supports + * {@link #ProtectionDomain(CodeSource, PermissionCollection, + * ClassLoader, java.security.Principal[]) dynamically binding} + * permissions, then the permission will be checked against the + * combination of the PermissionCollection supplied at construction and + * the current Policy binding. + *

+ * + * @param permission the Permission object to check. + * + * @return true if "permission" is implicit to this ProtectionDomain. + */ + public boolean implies(Permission permission) { + + if (hasAllPerm) { + // internal permission collection already has AllPermission - + // no need to go to policy + return true; + } + + if (!staticPermissions && + Policy.getPolicyNoCheck().implies(this, permission)) + return true; + if (permissions != null) + return permissions.implies(permission); + + return false; + } + + // called by the VM -- do not remove + boolean impliesCreateAccessControlContext() { + return implies(SecurityConstants.CREATE_ACC_PERMISSION); + } + + /** + * Convert a ProtectionDomain to a String. + */ + @Override public String toString() { + lazyInitCodeSource(); + lazyInitClassLoader(); + String pals = ""; + if (principals != null && principals.length > 0) { + StringBuilder palBuf = new StringBuilder("(principals "); + + for (int i = 0; i < principals.length; i++) { + palBuf.append(principals[i].getClass().getName() + + " \"" + principals[i].getName() + + "\""); + if (i < principals.length-1) + palBuf.append(",\n"); + else + palBuf.append(")\n"); + } + pals = palBuf.toString(); + } + + // Check if policy is set; we don't want to load + // the policy prematurely here + PermissionCollection pc = Policy.isSet() && seeAllp() ? + mergePermissions(): + getPermissions(); + + return "ProtectionDomain "+ + " "+codesource+"\n"+ + " "+classloader+"\n"+ + " "+pals+"\n"+ + " "+pc+"\n"; + } + + /** + * Return true (merge policy permissions) in the following cases: + * + * . SecurityManager is null + * + * . SecurityManager is not null, + * debug is not null, + * SecurityManager impelmentation is in bootclasspath, + * Policy implementation is in bootclasspath + * (the bootclasspath restrictions avoid recursion) + * + * . SecurityManager is not null, + * debug is null, + * caller has Policy.getPolicy permission + */ + private static boolean seeAllp() { + SecurityManager sm = System.getSecurityManager(); + + if (sm == null) { + return true; + } else { + Debug debug = Debug.getInstance("domain"); + if (debug != null) { + if (sm.getClass().getClassLoader() == null && + Policy.getPolicyNoCheck().getClass().getClassLoader() + == null) { + return true; + } + } else { + try { + sm.checkPermission(SecurityConstants.GET_POLICY_PERMISSION); + return true; + } catch (SecurityException se) { + // fall thru and return false + } + } + } + + return false; + } + + private PermissionCollection mergePermissions() { + lazyInitPermissions(); + if (staticPermissions) + return permissions; + + PermissionCollection perms = + java.security.AccessController.doPrivileged + (new java.security.PrivilegedAction() { + public PermissionCollection run() { + Policy p = Policy.getPolicyNoCheck(); + return p.getPermissions(ProtectionDomain.this); + } + }); + + Permissions mergedPerms = new Permissions(); + int swag = 32; + int vcap = 8; + Enumeration e; + List pdVector = new ArrayList<>(vcap); + List plVector = new ArrayList<>(swag); + + // + // Build a vector of domain permissions for subsequent merge + if (permissions != null) { + synchronized (permissions) { + e = permissions.elements(); + while (e.hasMoreElements()) { + pdVector.add(e.nextElement()); + } + } + } + + // + // Build a vector of Policy permissions for subsequent merge + if (perms != null) { + synchronized (perms) { + e = perms.elements(); + while (e.hasMoreElements()) { + plVector.add(e.nextElement()); + vcap++; + } + } + } + + if (perms != null && permissions != null) { + // + // Weed out the duplicates from the policy. Unless a refresh + // has occurred since the pd was consed this should result in + // an empty vector. + synchronized (permissions) { + e = permissions.elements(); // domain vs policy + while (e.hasMoreElements()) { + Permission pdp = e.nextElement(); + Class pdpClass = pdp.getClass(); + String pdpActions = pdp.getActions(); + String pdpName = pdp.getName(); + for (int i = 0; i < plVector.size(); i++) { + Permission pp = plVector.get(i); + if (pdpClass.isInstance(pp)) { + // The equals() method on some permissions + // have some side effects so this manual + // comparison is sufficient. + if (pdpName.equals(pp.getName()) && + pdpActions.equals(pp.getActions())) { + plVector.remove(i); + break; + } + } + } + } + } + } + + if (perms !=null) { + // the order of adding to merged perms and permissions + // needs to preserve the bugfix 4301064 + + for (int i = plVector.size()-1; i >= 0; i--) { + mergedPerms.add(plVector.get(i)); + } + } + if (permissions != null) { + for (int i = pdVector.size()-1; i >= 0; i--) { + mergedPerms.add(pdVector.get(i)); + } + } + + return mergedPerms; + } + + /** + * Used for storing ProtectionDomains as keys in a Map. + */ + final class Key {} + + static { + SharedSecrets.setJavaSecurityProtectionDomainAccess( + new JavaSecurityProtectionDomainAccess() { + public ProtectionDomainCache getProtectionDomainCache() { + return new ProtectionDomainCache() { + private final Map map = + Collections.synchronizedMap + (new WeakHashMap()); + public void put(ProtectionDomain pd, + PermissionCollection pc) { + map.put((pd == null ? null : pd.key), pc); + } + public PermissionCollection get(ProtectionDomain pd) { + return pd == null ? map.get(null) : map.get(pd.key); + } + }; + } + }); + } +} diff --git a/openjdk/java/util/concurrent/locks/AbstractQueuedSynchronizer.java b/openjdk/java/util/concurrent/locks/AbstractQueuedSynchronizer.java new file mode 100644 index 0000000..f2e5a5c --- /dev/null +++ b/openjdk/java/util/concurrent/locks/AbstractQueuedSynchronizer.java @@ -0,0 +1,2285 @@ +/* + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +package java.util.concurrent.locks; +import java.util.concurrent.TimeUnit; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; + +/** + * Provides a framework for implementing blocking locks and related + * synchronizers (semaphores, events, etc) that rely on + * first-in-first-out (FIFO) wait queues. This class is designed to + * be a useful basis for most kinds of synchronizers that rely on a + * single atomic {@code int} value to represent state. Subclasses + * must define the protected methods that change this state, and which + * define what that state means in terms of this object being acquired + * or released. Given these, the other methods in this class carry + * out all queuing and blocking mechanics. Subclasses can maintain + * other state fields, but only the atomically updated {@code int} + * value manipulated using methods {@link #getState}, {@link + * #setState} and {@link #compareAndSetState} is tracked with respect + * to synchronization. + * + *

Subclasses should be defined as non-public internal helper + * classes that are used to implement the synchronization properties + * of their enclosing class. Class + * {@code AbstractQueuedSynchronizer} does not implement any + * synchronization interface. Instead it defines methods such as + * {@link #acquireInterruptibly} that can be invoked as + * appropriate by concrete locks and related synchronizers to + * implement their public methods. + * + *

This class supports either or both a default exclusive + * mode and a shared mode. When acquired in exclusive mode, + * attempted acquires by other threads cannot succeed. Shared mode + * acquires by multiple threads may (but need not) succeed. This class + * does not "understand" these differences except in the + * mechanical sense that when a shared mode acquire succeeds, the next + * waiting thread (if one exists) must also determine whether it can + * acquire as well. Threads waiting in the different modes share the + * same FIFO queue. Usually, implementation subclasses support only + * one of these modes, but both can come into play for example in a + * {@link ReadWriteLock}. Subclasses that support only exclusive or + * only shared modes need not define the methods supporting the unused mode. + * + *

This class defines a nested {@link ConditionObject} class that + * can be used as a {@link Condition} implementation by subclasses + * supporting exclusive mode for which method {@link + * #isHeldExclusively} reports whether synchronization is exclusively + * held with respect to the current thread, method {@link #release} + * invoked with the current {@link #getState} value fully releases + * this object, and {@link #acquire}, given this saved state value, + * eventually restores this object to its previous acquired state. No + * {@code AbstractQueuedSynchronizer} method otherwise creates such a + * condition, so if this constraint cannot be met, do not use it. The + * behavior of {@link ConditionObject} depends of course on the + * semantics of its synchronizer implementation. + * + *

This class provides inspection, instrumentation, and monitoring + * methods for the internal queue, as well as similar methods for + * condition objects. These can be exported as desired into classes + * using an {@code AbstractQueuedSynchronizer} for their + * synchronization mechanics. + * + *

Serialization of this class stores only the underlying atomic + * integer maintaining state, so deserialized objects have empty + * thread queues. Typical subclasses requiring serializability will + * define a {@code readObject} method that restores this to a known + * initial state upon deserialization. + * + *

Usage

+ * + *

To use this class as the basis of a synchronizer, redefine the + * following methods, as applicable, by inspecting and/or modifying + * the synchronization state using {@link #getState}, {@link + * #setState} and/or {@link #compareAndSetState}: + * + *

    + *
  • {@link #tryAcquire} + *
  • {@link #tryRelease} + *
  • {@link #tryAcquireShared} + *
  • {@link #tryReleaseShared} + *
  • {@link #isHeldExclusively} + *
+ * + * Each of these methods by default throws {@link + * UnsupportedOperationException}. Implementations of these methods + * must be internally thread-safe, and should in general be short and + * not block. Defining these methods is the only supported + * means of using this class. All other methods are declared + * {@code final} because they cannot be independently varied. + * + *

You may also find the inherited methods from {@link + * AbstractOwnableSynchronizer} useful to keep track of the thread + * owning an exclusive synchronizer. You are encouraged to use them + * -- this enables monitoring and diagnostic tools to assist users in + * determining which threads hold locks. + * + *

Even though this class is based on an internal FIFO queue, it + * does not automatically enforce FIFO acquisition policies. The core + * of exclusive synchronization takes the form: + * + *

+ * Acquire:
+ *     while (!tryAcquire(arg)) {
+ *        enqueue thread if it is not already queued;
+ *        possibly block current thread;
+ *     }
+ *
+ * Release:
+ *     if (tryRelease(arg))
+ *        unblock the first queued thread;
+ * 
+ * + * (Shared mode is similar but may involve cascading signals.) + * + *

Because checks in acquire are invoked before + * enqueuing, a newly acquiring thread may barge ahead of + * others that are blocked and queued. However, you can, if desired, + * define {@code tryAcquire} and/or {@code tryAcquireShared} to + * disable barging by internally invoking one or more of the inspection + * methods, thereby providing a fair FIFO acquisition order. + * In particular, most fair synchronizers can define {@code tryAcquire} + * to return {@code false} if {@link #hasQueuedPredecessors} (a method + * specifically designed to be used by fair synchronizers) returns + * {@code true}. Other variations are possible. + * + *

Throughput and scalability are generally highest for the + * default barging (also known as greedy, + * renouncement, and convoy-avoidance) strategy. + * While this is not guaranteed to be fair or starvation-free, earlier + * queued threads are allowed to recontend before later queued + * threads, and each recontention has an unbiased chance to succeed + * against incoming threads. Also, while acquires do not + * "spin" in the usual sense, they may perform multiple + * invocations of {@code tryAcquire} interspersed with other + * computations before blocking. This gives most of the benefits of + * spins when exclusive synchronization is only briefly held, without + * most of the liabilities when it isn't. If so desired, you can + * augment this by preceding calls to acquire methods with + * "fast-path" checks, possibly prechecking {@link #hasContended} + * and/or {@link #hasQueuedThreads} to only do so if the synchronizer + * is likely not to be contended. + * + *

This class provides an efficient and scalable basis for + * synchronization in part by specializing its range of use to + * synchronizers that can rely on {@code int} state, acquire, and + * release parameters, and an internal FIFO wait queue. When this does + * not suffice, you can build synchronizers from a lower level using + * {@link java.util.concurrent.atomic atomic} classes, your own custom + * {@link java.util.Queue} classes, and {@link LockSupport} blocking + * support. + * + *

Usage Examples

+ * + *

Here is a non-reentrant mutual exclusion lock class that uses + * the value zero to represent the unlocked state, and one to + * represent the locked state. While a non-reentrant lock + * does not strictly require recording of the current owner + * thread, this class does so anyway to make usage easier to monitor. + * It also supports conditions and exposes + * one of the instrumentation methods: + * + *

 {@code
+ * class Mutex implements Lock, java.io.Serializable {
+ *
+ *   // Our internal helper class
+ *   private static class Sync extends AbstractQueuedSynchronizer {
+ *     // Reports whether in locked state
+ *     protected boolean isHeldExclusively() {
+ *       return getState() == 1;
+ *     }
+ *
+ *     // Acquires the lock if state is zero
+ *     public boolean tryAcquire(int acquires) {
+ *       assert acquires == 1; // Otherwise unused
+ *       if (compareAndSetState(0, 1)) {
+ *         setExclusiveOwnerThread(Thread.currentThread());
+ *         return true;
+ *       }
+ *       return false;
+ *     }
+ *
+ *     // Releases the lock by setting state to zero
+ *     protected boolean tryRelease(int releases) {
+ *       assert releases == 1; // Otherwise unused
+ *       if (getState() == 0) throw new IllegalMonitorStateException();
+ *       setExclusiveOwnerThread(null);
+ *       setState(0);
+ *       return true;
+ *     }
+ *
+ *     // Provides a Condition
+ *     Condition newCondition() { return new ConditionObject(); }
+ *
+ *     // Deserializes properly
+ *     private void readObject(ObjectInputStream s)
+ *         throws IOException, ClassNotFoundException {
+ *       s.defaultReadObject();
+ *       setState(0); // reset to unlocked state
+ *     }
+ *   }
+ *
+ *   // The sync object does all the hard work. We just forward to it.
+ *   private final Sync sync = new Sync();
+ *
+ *   public void lock()                { sync.acquire(1); }
+ *   public boolean tryLock()          { return sync.tryAcquire(1); }
+ *   public void unlock()              { sync.release(1); }
+ *   public Condition newCondition()   { return sync.newCondition(); }
+ *   public boolean isLocked()         { return sync.isHeldExclusively(); }
+ *   public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
+ *   public void lockInterruptibly() throws InterruptedException {
+ *     sync.acquireInterruptibly(1);
+ *   }
+ *   public boolean tryLock(long timeout, TimeUnit unit)
+ *       throws InterruptedException {
+ *     return sync.tryAcquireNanos(1, unit.toNanos(timeout));
+ *   }
+ * }}
+ * + *

Here is a latch class that is like a + * {@link java.util.concurrent.CountDownLatch CountDownLatch} + * except that it only requires a single {@code signal} to + * fire. Because a latch is non-exclusive, it uses the {@code shared} + * acquire and release methods. + * + *

 {@code
+ * class BooleanLatch {
+ *
+ *   private static class Sync extends AbstractQueuedSynchronizer {
+ *     boolean isSignalled() { return getState() != 0; }
+ *
+ *     protected int tryAcquireShared(int ignore) {
+ *       return isSignalled() ? 1 : -1;
+ *     }
+ *
+ *     protected boolean tryReleaseShared(int ignore) {
+ *       setState(1);
+ *       return true;
+ *     }
+ *   }
+ *
+ *   private final Sync sync = new Sync();
+ *   public boolean isSignalled() { return sync.isSignalled(); }
+ *   public void signal()         { sync.releaseShared(1); }
+ *   public void await() throws InterruptedException {
+ *     sync.acquireSharedInterruptibly(1);
+ *   }
+ * }}
+ * + * @since 1.5 + * @author Doug Lea + */ +public abstract class AbstractQueuedSynchronizer + extends AbstractOwnableSynchronizer + implements java.io.Serializable { + + private static final long serialVersionUID = 7373984972572414691L; + + /** + * Creates a new {@code AbstractQueuedSynchronizer} instance + * with initial synchronization state of zero. + */ + protected AbstractQueuedSynchronizer() { } + + /** + * Wait queue node class. + * + *

The wait queue is a variant of a "CLH" (Craig, Landin, and + * Hagersten) lock queue. CLH locks are normally used for + * spinlocks. We instead use them for blocking synchronizers, but + * use the same basic tactic of holding some of the control + * information about a thread in the predecessor of its node. A + * "status" field in each node keeps track of whether a thread + * should block. A node is signalled when its predecessor + * releases. Each node of the queue otherwise serves as a + * specific-notification-style monitor holding a single waiting + * thread. The status field does NOT control whether threads are + * granted locks etc though. A thread may try to acquire if it is + * first in the queue. But being first does not guarantee success; + * it only gives the right to contend. So the currently released + * contender thread may need to rewait. + * + *

To enqueue into a CLH lock, you atomically splice it in as new + * tail. To dequeue, you just set the head field. + *

+     *      +------+  prev +-----+       +-----+
+     * head |      | <---- |     | <---- |     |  tail
+     *      +------+       +-----+       +-----+
+     * 
+ * + *

Insertion into a CLH queue requires only a single atomic + * operation on "tail", so there is a simple atomic point of + * demarcation from unqueued to queued. Similarly, dequeuing + * involves only updating the "head". However, it takes a bit + * more work for nodes to determine who their successors are, + * in part to deal with possible cancellation due to timeouts + * and interrupts. + * + *

The "prev" links (not used in original CLH locks), are mainly + * needed to handle cancellation. If a node is cancelled, its + * successor is (normally) relinked to a non-cancelled + * predecessor. For explanation of similar mechanics in the case + * of spin locks, see the papers by Scott and Scherer at + * http://www.cs.rochester.edu/u/scott/synchronization/ + * + *

We also use "next" links to implement blocking mechanics. + * The thread id for each node is kept in its own node, so a + * predecessor signals the next node to wake up by traversing + * next link to determine which thread it is. Determination of + * successor must avoid races with newly queued nodes to set + * the "next" fields of their predecessors. This is solved + * when necessary by checking backwards from the atomically + * updated "tail" when a node's successor appears to be null. + * (Or, said differently, the next-links are an optimization + * so that we don't usually need a backward scan.) + * + *

Cancellation introduces some conservatism to the basic + * algorithms. Since we must poll for cancellation of other + * nodes, we can miss noticing whether a cancelled node is + * ahead or behind us. This is dealt with by always unparking + * successors upon cancellation, allowing them to stabilize on + * a new predecessor, unless we can identify an uncancelled + * predecessor who will carry this responsibility. + * + *

CLH queues need a dummy header node to get started. But + * we don't create them on construction, because it would be wasted + * effort if there is never contention. Instead, the node + * is constructed and head and tail pointers are set upon first + * contention. + * + *

Threads waiting on Conditions use the same nodes, but + * use an additional link. Conditions only need to link nodes + * in simple (non-concurrent) linked queues because they are + * only accessed when exclusively held. Upon await, a node is + * inserted into a condition queue. Upon signal, the node is + * transferred to the main queue. A special value of status + * field is used to mark which queue a node is on. + * + *

Thanks go to Dave Dice, Mark Moir, Victor Luchangco, Bill + * Scherer and Michael Scott, along with members of JSR-166 + * expert group, for helpful ideas, discussions, and critiques + * on the design of this class. + */ + static final class Node { + static final AtomicReferenceFieldUpdater nextUpdater = AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "next"); + /** Marker to indicate a node is waiting in shared mode */ + static final Node SHARED = new Node(); + /** Marker to indicate a node is waiting in exclusive mode */ + static final Node EXCLUSIVE = null; + + /** waitStatus value to indicate thread has cancelled */ + static final int CANCELLED = 1; + /** waitStatus value to indicate successor's thread needs unparking */ + static final int SIGNAL = -1; + /** waitStatus value to indicate thread is waiting on condition */ + static final int CONDITION = -2; + /** + * waitStatus value to indicate the next acquireShared should + * unconditionally propagate + */ + static final int PROPAGATE = -3; + + /** + * Status field, taking on only the values: + * SIGNAL: The successor of this node is (or will soon be) + * blocked (via park), so the current node must + * unpark its successor when it releases or + * cancels. To avoid races, acquire methods must + * first indicate they need a signal, + * then retry the atomic acquire, and then, + * on failure, block. + * CANCELLED: This node is cancelled due to timeout or interrupt. + * Nodes never leave this state. In particular, + * a thread with cancelled node never again blocks. + * CONDITION: This node is currently on a condition queue. + * It will not be used as a sync queue node + * until transferred, at which time the status + * will be set to 0. (Use of this value here has + * nothing to do with the other uses of the + * field, but simplifies mechanics.) + * PROPAGATE: A releaseShared should be propagated to other + * nodes. This is set (for head node only) in + * doReleaseShared to ensure propagation + * continues, even if other operations have + * since intervened. + * 0: None of the above + * + * The values are arranged numerically to simplify use. + * Non-negative values mean that a node doesn't need to + * signal. So, most code doesn't need to check for particular + * values, just for sign. + * + * The field is initialized to 0 for normal sync nodes, and + * CONDITION for condition nodes. It is modified using CAS + * (or when possible, unconditional volatile writes). + */ + volatile int waitStatus; + + /** + * Link to predecessor node that current node/thread relies on + * for checking waitStatus. Assigned during enqueuing, and nulled + * out (for sake of GC) only upon dequeuing. Also, upon + * cancellation of a predecessor, we short-circuit while + * finding a non-cancelled one, which will always exist + * because the head node is never cancelled: A node becomes + * head only as a result of successful acquire. A + * cancelled thread never succeeds in acquiring, and a thread only + * cancels itself, not any other node. + */ + volatile Node prev; + + /** + * Link to the successor node that the current node/thread + * unparks upon release. Assigned during enqueuing, adjusted + * when bypassing cancelled predecessors, and nulled out (for + * sake of GC) when dequeued. The enq operation does not + * assign next field of a predecessor until after attachment, + * so seeing a null next field does not necessarily mean that + * node is at end of queue. However, if a next field appears + * to be null, we can scan prev's from the tail to + * double-check. The next field of cancelled nodes is set to + * point to the node itself instead of null, to make life + * easier for isOnSyncQueue. + */ + volatile Node next; + + /** + * The thread that enqueued this node. Initialized on + * construction and nulled out after use. + */ + volatile Thread thread; + + /** + * Link to next node waiting on condition, or the special + * value SHARED. Because condition queues are accessed only + * when holding in exclusive mode, we just need a simple + * linked queue to hold nodes while they are waiting on + * conditions. They are then transferred to the queue to + * re-acquire. And because conditions can only be exclusive, + * we save a field by using special value to indicate shared + * mode. + */ + Node nextWaiter; + + /** + * Returns true if node is waiting in shared mode. + */ + final boolean isShared() { + return nextWaiter == SHARED; + } + + /** + * Returns previous node, or throws NullPointerException if null. + * Use when predecessor cannot be null. The null check could + * be elided, but is present to help the VM. + * + * @return the predecessor of this node + */ + final Node predecessor() throws NullPointerException { + Node p = prev; + if (p == null) + throw new NullPointerException(); + else + return p; + } + + Node() { // Used to establish initial head or SHARED marker + } + + Node(Thread thread, Node mode) { // Used by addWaiter + this.nextWaiter = mode; + this.thread = thread; + } + + Node(Thread thread, int waitStatus) { // Used by Condition + this.waitStatus = waitStatus; + this.thread = thread; + } + } + + /** + * Head of the wait queue, lazily initialized. Except for + * initialization, it is modified only via method setHead. Note: + * If head exists, its waitStatus is guaranteed not to be + * CANCELLED. + */ + private transient volatile Node head; + + /** + * Tail of the wait queue, lazily initialized. Modified only via + * method enq to add new wait node. + */ + private transient volatile Node tail; + + /** + * The synchronization state. + */ + private volatile int state; + + /** + * Returns the current value of synchronization state. + * This operation has memory semantics of a {@code volatile} read. + * @return current state value + */ + protected final int getState() { + return state; + } + + /** + * Sets the value of synchronization state. + * This operation has memory semantics of a {@code volatile} read. + * @param newState the new state value + */ + protected final void setState(int newState) { + state = newState; + } + + /** + * Atomically sets synchronization state to the given updated + * value if the current state value equals the expected value. + * This operation has memory semantics of a {@code volatile} read + * and write. + * + * @param expect the expected value + * @param update the new value + * @return {@code true} if successful. False return indicates that the actual + * value was not equal to the expected value. + */ + protected final native boolean compareAndSetState(int expect, int update); // implemented in map.xml + + // Queuing utilities + + /** + * The number of nanoseconds for which it is faster to spin + * rather than to use timed park. A rough estimate suffices + * to improve responsiveness with very short timeouts. + */ + static final long spinForTimeoutThreshold = 1000L; + + /** + * Inserts node into queue, initializing if necessary. See picture above. + * @param node the node to insert + * @return node's predecessor + */ + private Node enq(final Node node) { + for (;;) { + Node t = tail; + if (t == null) { // Must initialize + if (compareAndSetHead(new Node())) + tail = head; + } else { + node.prev = t; + if (compareAndSetTail(t, node)) { + t.next = node; + return t; + } + } + } + } + + /** + * Creates and enqueues node for current thread and given mode. + * + * @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared + * @return the new node + */ + private Node addWaiter(Node mode) { + Node node = new Node(Thread.currentThread(), mode); + // Try the fast path of enq; backup to full enq on failure + Node pred = tail; + if (pred != null) { + node.prev = pred; + if (compareAndSetTail(pred, node)) { + pred.next = node; + return node; + } + } + enq(node); + return node; + } + + /** + * Sets head of queue to be node, thus dequeuing. Called only by + * acquire methods. Also nulls out unused fields for sake of GC + * and to suppress unnecessary signals and traversals. + * + * @param node the node + */ + private void setHead(Node node) { + head = node; + node.thread = null; + node.prev = null; + } + + /** + * Wakes up node's successor, if one exists. + * + * @param node the node + */ + private void unparkSuccessor(Node node) { + /* + * If status is negative (i.e., possibly needing signal) try + * to clear in anticipation of signalling. It is OK if this + * fails or if status is changed by waiting thread. + */ + int ws = node.waitStatus; + if (ws < 0) + compareAndSetWaitStatus(node, ws, 0); + + /* + * Thread to unpark is held in successor, which is normally + * just the next node. But if cancelled or apparently null, + * traverse backwards from tail to find the actual + * non-cancelled successor. + */ + Node s = node.next; + if (s == null || s.waitStatus > 0) { + s = null; + for (Node t = tail; t != null && t != node; t = t.prev) + if (t.waitStatus <= 0) + s = t; + } + if (s != null) + LockSupport.unpark(s.thread); + } + + /** + * Release action for shared mode -- signals successor and ensure + * propagation. (Note: For exclusive mode, release just amounts + * to calling unparkSuccessor of head if it needs signal.) + */ + private void doReleaseShared() { + /* + * Ensure that a release propagates, even if there are other + * in-progress acquires/releases. This proceeds in the usual + * way of trying to unparkSuccessor of head if it needs + * signal. But if it does not, status is set to PROPAGATE to + * ensure that upon release, propagation continues. + * Additionally, we must loop in case a new node is added + * while we are doing this. Also, unlike other uses of + * unparkSuccessor, we need to know if CAS to reset status + * fails, if so rechecking. + */ + for (;;) { + Node h = head; + if (h != null && h != tail) { + int ws = h.waitStatus; + if (ws == Node.SIGNAL) { + if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) + continue; // loop to recheck cases + unparkSuccessor(h); + } + else if (ws == 0 && + !compareAndSetWaitStatus(h, 0, Node.PROPAGATE)) + continue; // loop on failed CAS + } + if (h == head) // loop if head changed + break; + } + } + + /** + * Sets head of queue, and checks if successor may be waiting + * in shared mode, if so propagating if either propagate > 0 or + * PROPAGATE status was set. + * + * @param node the node + * @param propagate the return value from a tryAcquireShared + */ + private void setHeadAndPropagate(Node node, int propagate) { + Node h = head; // Record old head for check below + setHead(node); + /* + * Try to signal next queued node if: + * Propagation was indicated by caller, + * or was recorded (as h.waitStatus either before + * or after setHead) by a previous operation + * (note: this uses sign-check of waitStatus because + * PROPAGATE status may transition to SIGNAL.) + * and + * The next node is waiting in shared mode, + * or we don't know, because it appears null + * + * The conservatism in both of these checks may cause + * unnecessary wake-ups, but only when there are multiple + * racing acquires/releases, so most need signals now or soon + * anyway. + */ + if (propagate > 0 || h == null || h.waitStatus < 0 || + (h = head) == null || h.waitStatus < 0) { + Node s = node.next; + if (s == null || s.isShared()) + doReleaseShared(); + } + } + + // Utilities for various versions of acquire + + /** + * Cancels an ongoing attempt to acquire. + * + * @param node the node + */ + private void cancelAcquire(Node node) { + // Ignore if node doesn't exist + if (node == null) + return; + + node.thread = null; + + // Skip cancelled predecessors + Node pred = node.prev; + while (pred.waitStatus > 0) + node.prev = pred = pred.prev; + + // predNext is the apparent node to unsplice. CASes below will + // fail if not, in which case, we lost race vs another cancel + // or signal, so no further action is necessary. + Node predNext = pred.next; + + // Can use unconditional write instead of CAS here. + // After this atomic step, other Nodes can skip past us. + // Before, we are free of interference from other threads. + node.waitStatus = Node.CANCELLED; + + // If we are the tail, remove ourselves. + if (node == tail && compareAndSetTail(node, pred)) { + compareAndSetNext(pred, predNext, null); + } else { + // If successor needs signal, try to set pred's next-link + // so it will get one. Otherwise wake it up to propagate. + int ws; + if (pred != head && + ((ws = pred.waitStatus) == Node.SIGNAL || + (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) && + pred.thread != null) { + Node next = node.next; + if (next != null && next.waitStatus <= 0) + compareAndSetNext(pred, predNext, next); + } else { + unparkSuccessor(node); + } + + node.next = node; // help GC + } + } + + /** + * Checks and updates status for a node that failed to acquire. + * Returns true if thread should block. This is the main signal + * control in all acquire loops. Requires that pred == node.prev. + * + * @param pred node's predecessor holding status + * @param node the node + * @return {@code true} if thread should block + */ + private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) { + int ws = pred.waitStatus; + if (ws == Node.SIGNAL) + /* + * This node has already set status asking a release + * to signal it, so it can safely park. + */ + return true; + if (ws > 0) { + /* + * Predecessor was cancelled. Skip over predecessors and + * indicate retry. + */ + do { + node.prev = pred = pred.prev; + } while (pred.waitStatus > 0); + pred.next = node; + } else { + /* + * waitStatus must be 0 or PROPAGATE. Indicate that we + * need a signal, but don't park yet. Caller will need to + * retry to make sure it cannot acquire before parking. + */ + compareAndSetWaitStatus(pred, ws, Node.SIGNAL); + } + return false; + } + + /** + * Convenience method to interrupt current thread. + */ + static void selfInterrupt() { + Thread.currentThread().interrupt(); + } + + /** + * Convenience method to park and then check if interrupted + * + * @return {@code true} if interrupted + */ + private final boolean parkAndCheckInterrupt() { + LockSupport.park(this); + return Thread.interrupted(); + } + + /* + * Various flavors of acquire, varying in exclusive/shared and + * control modes. Each is mostly the same, but annoyingly + * different. Only a little bit of factoring is possible due to + * interactions of exception mechanics (including ensuring that we + * cancel if tryAcquire throws exception) and other control, at + * least not without hurting performance too much. + */ + + /** + * Acquires in exclusive uninterruptible mode for thread already in + * queue. Used by condition wait methods as well as acquire. + * + * @param node the node + * @param arg the acquire argument + * @return {@code true} if interrupted while waiting + */ + final boolean acquireQueued(final Node node, int arg) { + boolean failed = true; + try { + boolean interrupted = false; + for (;;) { + final Node p = node.predecessor(); + if (p == head && tryAcquire(arg)) { + setHead(node); + p.next = null; // help GC + failed = false; + return interrupted; + } + if (shouldParkAfterFailedAcquire(p, node) && + parkAndCheckInterrupt()) + interrupted = true; + } + } finally { + if (failed) + cancelAcquire(node); + } + } + + /** + * Acquires in exclusive interruptible mode. + * @param arg the acquire argument + */ + private void doAcquireInterruptibly(int arg) + throws InterruptedException { + final Node node = addWaiter(Node.EXCLUSIVE); + boolean failed = true; + try { + for (;;) { + final Node p = node.predecessor(); + if (p == head && tryAcquire(arg)) { + setHead(node); + p.next = null; // help GC + failed = false; + return; + } + if (shouldParkAfterFailedAcquire(p, node) && + parkAndCheckInterrupt()) + throw new InterruptedException(); + } + } finally { + if (failed) + cancelAcquire(node); + } + } + + /** + * Acquires in exclusive timed mode. + * + * @param arg the acquire argument + * @param nanosTimeout max wait time + * @return {@code true} if acquired + */ + private boolean doAcquireNanos(int arg, long nanosTimeout) + throws InterruptedException { + if (nanosTimeout <= 0L) + return false; + final long deadline = System.nanoTime() + nanosTimeout; + final Node node = addWaiter(Node.EXCLUSIVE); + boolean failed = true; + try { + for (;;) { + final Node p = node.predecessor(); + if (p == head && tryAcquire(arg)) { + setHead(node); + p.next = null; // help GC + failed = false; + return true; + } + nanosTimeout = deadline - System.nanoTime(); + if (nanosTimeout <= 0L) + return false; + if (shouldParkAfterFailedAcquire(p, node) && + nanosTimeout > spinForTimeoutThreshold) + LockSupport.parkNanos(this, nanosTimeout); + if (Thread.interrupted()) + throw new InterruptedException(); + } + } finally { + if (failed) + cancelAcquire(node); + } + } + + /** + * Acquires in shared uninterruptible mode. + * @param arg the acquire argument + */ + private void doAcquireShared(int arg) { + final Node node = addWaiter(Node.SHARED); + boolean failed = true; + try { + boolean interrupted = false; + for (;;) { + final Node p = node.predecessor(); + if (p == head) { + int r = tryAcquireShared(arg); + if (r >= 0) { + setHeadAndPropagate(node, r); + p.next = null; // help GC + if (interrupted) + selfInterrupt(); + failed = false; + return; + } + } + if (shouldParkAfterFailedAcquire(p, node) && + parkAndCheckInterrupt()) + interrupted = true; + } + } finally { + if (failed) + cancelAcquire(node); + } + } + + /** + * Acquires in shared interruptible mode. + * @param arg the acquire argument + */ + private void doAcquireSharedInterruptibly(int arg) + throws InterruptedException { + final Node node = addWaiter(Node.SHARED); + boolean failed = true; + try { + for (;;) { + final Node p = node.predecessor(); + if (p == head) { + int r = tryAcquireShared(arg); + if (r >= 0) { + setHeadAndPropagate(node, r); + p.next = null; // help GC + failed = false; + return; + } + } + if (shouldParkAfterFailedAcquire(p, node) && + parkAndCheckInterrupt()) + throw new InterruptedException(); + } + } finally { + if (failed) + cancelAcquire(node); + } + } + + /** + * Acquires in shared timed mode. + * + * @param arg the acquire argument + * @param nanosTimeout max wait time + * @return {@code true} if acquired + */ + private boolean doAcquireSharedNanos(int arg, long nanosTimeout) + throws InterruptedException { + if (nanosTimeout <= 0L) + return false; + final long deadline = System.nanoTime() + nanosTimeout; + final Node node = addWaiter(Node.SHARED); + boolean failed = true; + try { + for (;;) { + final Node p = node.predecessor(); + if (p == head) { + int r = tryAcquireShared(arg); + if (r >= 0) { + setHeadAndPropagate(node, r); + p.next = null; // help GC + failed = false; + return true; + } + } + nanosTimeout = deadline - System.nanoTime(); + if (nanosTimeout <= 0L) + return false; + if (shouldParkAfterFailedAcquire(p, node) && + nanosTimeout > spinForTimeoutThreshold) + LockSupport.parkNanos(this, nanosTimeout); + if (Thread.interrupted()) + throw new InterruptedException(); + } + } finally { + if (failed) + cancelAcquire(node); + } + } + + // Main exported methods + + /** + * Attempts to acquire in exclusive mode. This method should query + * if the state of the object permits it to be acquired in the + * exclusive mode, and if so to acquire it. + * + *

This method is always invoked by the thread performing + * acquire. If this method reports failure, the acquire method + * may queue the thread, if it is not already queued, until it is + * signalled by a release from some other thread. This can be used + * to implement method {@link Lock#tryLock()}. + * + *

The default + * implementation throws {@link UnsupportedOperationException}. + * + * @param arg the acquire argument. This value is always the one + * passed to an acquire method, or is the value saved on entry + * to a condition wait. The value is otherwise uninterpreted + * and can represent anything you like. + * @return {@code true} if successful. Upon success, this object has + * been acquired. + * @throws IllegalMonitorStateException if acquiring would place this + * synchronizer in an illegal state. This exception must be + * thrown in a consistent fashion for synchronization to work + * correctly. + * @throws UnsupportedOperationException if exclusive mode is not supported + */ + protected boolean tryAcquire(int arg) { + throw new UnsupportedOperationException(); + } + + /** + * Attempts to set the state to reflect a release in exclusive + * mode. + * + *

This method is always invoked by the thread performing release. + * + *

The default implementation throws + * {@link UnsupportedOperationException}. + * + * @param arg the release argument. This value is always the one + * passed to a release method, or the current state value upon + * entry to a condition wait. The value is otherwise + * uninterpreted and can represent anything you like. + * @return {@code true} if this object is now in a fully released + * state, so that any waiting threads may attempt to acquire; + * and {@code false} otherwise. + * @throws IllegalMonitorStateException if releasing would place this + * synchronizer in an illegal state. This exception must be + * thrown in a consistent fashion for synchronization to work + * correctly. + * @throws UnsupportedOperationException if exclusive mode is not supported + */ + protected boolean tryRelease(int arg) { + throw new UnsupportedOperationException(); + } + + /** + * Attempts to acquire in shared mode. This method should query if + * the state of the object permits it to be acquired in the shared + * mode, and if so to acquire it. + * + *

This method is always invoked by the thread performing + * acquire. If this method reports failure, the acquire method + * may queue the thread, if it is not already queued, until it is + * signalled by a release from some other thread. + * + *

The default implementation throws {@link + * UnsupportedOperationException}. + * + * @param arg the acquire argument. This value is always the one + * passed to an acquire method, or is the value saved on entry + * to a condition wait. The value is otherwise uninterpreted + * and can represent anything you like. + * @return a negative value on failure; zero if acquisition in shared + * mode succeeded but no subsequent shared-mode acquire can + * succeed; and a positive value if acquisition in shared + * mode succeeded and subsequent shared-mode acquires might + * also succeed, in which case a subsequent waiting thread + * must check availability. (Support for three different + * return values enables this method to be used in contexts + * where acquires only sometimes act exclusively.) Upon + * success, this object has been acquired. + * @throws IllegalMonitorStateException if acquiring would place this + * synchronizer in an illegal state. This exception must be + * thrown in a consistent fashion for synchronization to work + * correctly. + * @throws UnsupportedOperationException if shared mode is not supported + */ + protected int tryAcquireShared(int arg) { + throw new UnsupportedOperationException(); + } + + /** + * Attempts to set the state to reflect a release in shared mode. + * + *

This method is always invoked by the thread performing release. + * + *

The default implementation throws + * {@link UnsupportedOperationException}. + * + * @param arg the release argument. This value is always the one + * passed to a release method, or the current state value upon + * entry to a condition wait. The value is otherwise + * uninterpreted and can represent anything you like. + * @return {@code true} if this release of shared mode may permit a + * waiting acquire (shared or exclusive) to succeed; and + * {@code false} otherwise + * @throws IllegalMonitorStateException if releasing would place this + * synchronizer in an illegal state. This exception must be + * thrown in a consistent fashion for synchronization to work + * correctly. + * @throws UnsupportedOperationException if shared mode is not supported + */ + protected boolean tryReleaseShared(int arg) { + throw new UnsupportedOperationException(); + } + + /** + * Returns {@code true} if synchronization is held exclusively with + * respect to the current (calling) thread. This method is invoked + * upon each call to a non-waiting {@link ConditionObject} method. + * (Waiting methods instead invoke {@link #release}.) + * + *

The default implementation throws {@link + * UnsupportedOperationException}. This method is invoked + * internally only within {@link ConditionObject} methods, so need + * not be defined if conditions are not used. + * + * @return {@code true} if synchronization is held exclusively; + * {@code false} otherwise + * @throws UnsupportedOperationException if conditions are not supported + */ + protected boolean isHeldExclusively() { + throw new UnsupportedOperationException(); + } + + /** + * Acquires in exclusive mode, ignoring interrupts. Implemented + * by invoking at least once {@link #tryAcquire}, + * returning on success. Otherwise the thread is queued, possibly + * repeatedly blocking and unblocking, invoking {@link + * #tryAcquire} until success. This method can be used + * to implement method {@link Lock#lock}. + * + * @param arg the acquire argument. This value is conveyed to + * {@link #tryAcquire} but is otherwise uninterpreted and + * can represent anything you like. + */ + public final void acquire(int arg) { + if (!tryAcquire(arg) && + acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) + selfInterrupt(); + } + + /** + * Acquires in exclusive mode, aborting if interrupted. + * Implemented by first checking interrupt status, then invoking + * at least once {@link #tryAcquire}, returning on + * success. Otherwise the thread is queued, possibly repeatedly + * blocking and unblocking, invoking {@link #tryAcquire} + * until success or the thread is interrupted. This method can be + * used to implement method {@link Lock#lockInterruptibly}. + * + * @param arg the acquire argument. This value is conveyed to + * {@link #tryAcquire} but is otherwise uninterpreted and + * can represent anything you like. + * @throws InterruptedException if the current thread is interrupted + */ + public final void acquireInterruptibly(int arg) + throws InterruptedException { + if (Thread.interrupted()) + throw new InterruptedException(); + if (!tryAcquire(arg)) + doAcquireInterruptibly(arg); + } + + /** + * Attempts to acquire in exclusive mode, aborting if interrupted, + * and failing if the given timeout elapses. Implemented by first + * checking interrupt status, then invoking at least once {@link + * #tryAcquire}, returning on success. Otherwise, the thread is + * queued, possibly repeatedly blocking and unblocking, invoking + * {@link #tryAcquire} until success or the thread is interrupted + * or the timeout elapses. This method can be used to implement + * method {@link Lock#tryLock(long, TimeUnit)}. + * + * @param arg the acquire argument. This value is conveyed to + * {@link #tryAcquire} but is otherwise uninterpreted and + * can represent anything you like. + * @param nanosTimeout the maximum number of nanoseconds to wait + * @return {@code true} if acquired; {@code false} if timed out + * @throws InterruptedException if the current thread is interrupted + */ + public final boolean tryAcquireNanos(int arg, long nanosTimeout) + throws InterruptedException { + if (Thread.interrupted()) + throw new InterruptedException(); + return tryAcquire(arg) || + doAcquireNanos(arg, nanosTimeout); + } + + /** + * Releases in exclusive mode. Implemented by unblocking one or + * more threads if {@link #tryRelease} returns true. + * This method can be used to implement method {@link Lock#unlock}. + * + * @param arg the release argument. This value is conveyed to + * {@link #tryRelease} but is otherwise uninterpreted and + * can represent anything you like. + * @return the value returned from {@link #tryRelease} + */ + public final boolean release(int arg) { + if (tryRelease(arg)) { + Node h = head; + if (h != null && h.waitStatus != 0) + unparkSuccessor(h); + return true; + } + return false; + } + + /** + * Acquires in shared mode, ignoring interrupts. Implemented by + * first invoking at least once {@link #tryAcquireShared}, + * returning on success. Otherwise the thread is queued, possibly + * repeatedly blocking and unblocking, invoking {@link + * #tryAcquireShared} until success. + * + * @param arg the acquire argument. This value is conveyed to + * {@link #tryAcquireShared} but is otherwise uninterpreted + * and can represent anything you like. + */ + public final void acquireShared(int arg) { + if (tryAcquireShared(arg) < 0) + doAcquireShared(arg); + } + + /** + * Acquires in shared mode, aborting if interrupted. Implemented + * by first checking interrupt status, then invoking at least once + * {@link #tryAcquireShared}, returning on success. Otherwise the + * thread is queued, possibly repeatedly blocking and unblocking, + * invoking {@link #tryAcquireShared} until success or the thread + * is interrupted. + * @param arg the acquire argument. + * This value is conveyed to {@link #tryAcquireShared} but is + * otherwise uninterpreted and can represent anything + * you like. + * @throws InterruptedException if the current thread is interrupted + */ + public final void acquireSharedInterruptibly(int arg) + throws InterruptedException { + if (Thread.interrupted()) + throw new InterruptedException(); + if (tryAcquireShared(arg) < 0) + doAcquireSharedInterruptibly(arg); + } + + /** + * Attempts to acquire in shared mode, aborting if interrupted, and + * failing if the given timeout elapses. Implemented by first + * checking interrupt status, then invoking at least once {@link + * #tryAcquireShared}, returning on success. Otherwise, the + * thread is queued, possibly repeatedly blocking and unblocking, + * invoking {@link #tryAcquireShared} until success or the thread + * is interrupted or the timeout elapses. + * + * @param arg the acquire argument. This value is conveyed to + * {@link #tryAcquireShared} but is otherwise uninterpreted + * and can represent anything you like. + * @param nanosTimeout the maximum number of nanoseconds to wait + * @return {@code true} if acquired; {@code false} if timed out + * @throws InterruptedException if the current thread is interrupted + */ + public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout) + throws InterruptedException { + if (Thread.interrupted()) + throw new InterruptedException(); + return tryAcquireShared(arg) >= 0 || + doAcquireSharedNanos(arg, nanosTimeout); + } + + /** + * Releases in shared mode. Implemented by unblocking one or more + * threads if {@link #tryReleaseShared} returns true. + * + * @param arg the release argument. This value is conveyed to + * {@link #tryReleaseShared} but is otherwise uninterpreted + * and can represent anything you like. + * @return the value returned from {@link #tryReleaseShared} + */ + public final boolean releaseShared(int arg) { + if (tryReleaseShared(arg)) { + doReleaseShared(); + return true; + } + return false; + } + + // Queue inspection methods + + /** + * Queries whether any threads are waiting to acquire. Note that + * because cancellations due to interrupts and timeouts may occur + * at any time, a {@code true} return does not guarantee that any + * other thread will ever acquire. + * + *

In this implementation, this operation returns in + * constant time. + * + * @return {@code true} if there may be other threads waiting to acquire + */ + public final boolean hasQueuedThreads() { + return head != tail; + } + + /** + * Queries whether any threads have ever contended to acquire this + * synchronizer; that is if an acquire method has ever blocked. + * + *

In this implementation, this operation returns in + * constant time. + * + * @return {@code true} if there has ever been contention + */ + public final boolean hasContended() { + return head != null; + } + + /** + * Returns the first (longest-waiting) thread in the queue, or + * {@code null} if no threads are currently queued. + * + *

In this implementation, this operation normally returns in + * constant time, but may iterate upon contention if other threads are + * concurrently modifying the queue. + * + * @return the first (longest-waiting) thread in the queue, or + * {@code null} if no threads are currently queued + */ + public final Thread getFirstQueuedThread() { + // handle only fast path, else relay + return (head == tail) ? null : fullGetFirstQueuedThread(); + } + + /** + * Version of getFirstQueuedThread called when fastpath fails + */ + private Thread fullGetFirstQueuedThread() { + /* + * The first node is normally head.next. Try to get its + * thread field, ensuring consistent reads: If thread + * field is nulled out or s.prev is no longer head, then + * some other thread(s) concurrently performed setHead in + * between some of our reads. We try this twice before + * resorting to traversal. + */ + Node h, s; + Thread st; + if (((h = head) != null && (s = h.next) != null && + s.prev == head && (st = s.thread) != null) || + ((h = head) != null && (s = h.next) != null && + s.prev == head && (st = s.thread) != null)) + return st; + + /* + * Head's next field might not have been set yet, or may have + * been unset after setHead. So we must check to see if tail + * is actually first node. If not, we continue on, safely + * traversing from tail back to head to find first, + * guaranteeing termination. + */ + + Node t = tail; + Thread firstThread = null; + while (t != null && t != head) { + Thread tt = t.thread; + if (tt != null) + firstThread = tt; + t = t.prev; + } + return firstThread; + } + + /** + * Returns true if the given thread is currently queued. + * + *

This implementation traverses the queue to determine + * presence of the given thread. + * + * @param thread the thread + * @return {@code true} if the given thread is on the queue + * @throws NullPointerException if the thread is null + */ + public final boolean isQueued(Thread thread) { + if (thread == null) + throw new NullPointerException(); + for (Node p = tail; p != null; p = p.prev) + if (p.thread == thread) + return true; + return false; + } + + /** + * Returns {@code true} if the apparent first queued thread, if one + * exists, is waiting in exclusive mode. If this method returns + * {@code true}, and the current thread is attempting to acquire in + * shared mode (that is, this method is invoked from {@link + * #tryAcquireShared}) then it is guaranteed that the current thread + * is not the first queued thread. Used only as a heuristic in + * ReentrantReadWriteLock. + */ + final boolean apparentlyFirstQueuedIsExclusive() { + Node h, s; + return (h = head) != null && + (s = h.next) != null && + !s.isShared() && + s.thread != null; + } + + /** + * Queries whether any threads have been waiting to acquire longer + * than the current thread. + * + *

An invocation of this method is equivalent to (but may be + * more efficient than): + *

 {@code
+     * getFirstQueuedThread() != Thread.currentThread() &&
+     * hasQueuedThreads()}
+ * + *

Note that because cancellations due to interrupts and + * timeouts may occur at any time, a {@code true} return does not + * guarantee that some other thread will acquire before the current + * thread. Likewise, it is possible for another thread to win a + * race to enqueue after this method has returned {@code false}, + * due to the queue being empty. + * + *

This method is designed to be used by a fair synchronizer to + * avoid barging. + * Such a synchronizer's {@link #tryAcquire} method should return + * {@code false}, and its {@link #tryAcquireShared} method should + * return a negative value, if this method returns {@code true} + * (unless this is a reentrant acquire). For example, the {@code + * tryAcquire} method for a fair, reentrant, exclusive mode + * synchronizer might look like this: + * + *

 {@code
+     * protected boolean tryAcquire(int arg) {
+     *   if (isHeldExclusively()) {
+     *     // A reentrant acquire; increment hold count
+     *     return true;
+     *   } else if (hasQueuedPredecessors()) {
+     *     return false;
+     *   } else {
+     *     // try to acquire normally
+     *   }
+     * }}
+ * + * @return {@code true} if there is a queued thread preceding the + * current thread, and {@code false} if the current thread + * is at the head of the queue or the queue is empty + * @since 1.7 + */ + public final boolean hasQueuedPredecessors() { + // The correctness of this depends on head being initialized + // before tail and on head.next being accurate if the current + // thread is first in queue. + Node t = tail; // Read fields in reverse initialization order + Node h = head; + Node s; + return h != t && + ((s = h.next) == null || s.thread != Thread.currentThread()); + } + + + // Instrumentation and monitoring methods + + /** + * Returns an estimate of the number of threads waiting to + * acquire. The value is only an estimate because the number of + * threads may change dynamically while this method traverses + * internal data structures. This method is designed for use in + * monitoring system state, not for synchronization + * control. + * + * @return the estimated number of threads waiting to acquire + */ + public final int getQueueLength() { + int n = 0; + for (Node p = tail; p != null; p = p.prev) { + if (p.thread != null) + ++n; + } + return n; + } + + /** + * Returns a collection containing threads that may be waiting to + * acquire. Because the actual set of threads may change + * dynamically while constructing this result, the returned + * collection is only a best-effort estimate. The elements of the + * returned collection are in no particular order. This method is + * designed to facilitate construction of subclasses that provide + * more extensive monitoring facilities. + * + * @return the collection of threads + */ + public final Collection getQueuedThreads() { + ArrayList list = new ArrayList(); + for (Node p = tail; p != null; p = p.prev) { + Thread t = p.thread; + if (t != null) + list.add(t); + } + return list; + } + + /** + * Returns a collection containing threads that may be waiting to + * acquire in exclusive mode. This has the same properties + * as {@link #getQueuedThreads} except that it only returns + * those threads waiting due to an exclusive acquire. + * + * @return the collection of threads + */ + public final Collection getExclusiveQueuedThreads() { + ArrayList list = new ArrayList(); + for (Node p = tail; p != null; p = p.prev) { + if (!p.isShared()) { + Thread t = p.thread; + if (t != null) + list.add(t); + } + } + return list; + } + + /** + * Returns a collection containing threads that may be waiting to + * acquire in shared mode. This has the same properties + * as {@link #getQueuedThreads} except that it only returns + * those threads waiting due to a shared acquire. + * + * @return the collection of threads + */ + public final Collection getSharedQueuedThreads() { + ArrayList list = new ArrayList(); + for (Node p = tail; p != null; p = p.prev) { + if (p.isShared()) { + Thread t = p.thread; + if (t != null) + list.add(t); + } + } + return list; + } + + /** + * Returns a string identifying this synchronizer, as well as its state. + * The state, in brackets, includes the String {@code "State ="} + * followed by the current value of {@link #getState}, and either + * {@code "nonempty"} or {@code "empty"} depending on whether the + * queue is empty. + * + * @return a string identifying this synchronizer, as well as its state + */ + public String toString() { + int s = getState(); + String q = hasQueuedThreads() ? "non" : ""; + return super.toString() + + "[State = " + s + ", " + q + "empty queue]"; + } + + + // Internal support methods for Conditions + + /** + * Returns true if a node, always one that was initially placed on + * a condition queue, is now waiting to reacquire on sync queue. + * @param node the node + * @return true if is reacquiring + */ + final boolean isOnSyncQueue(Node node) { + if (node.waitStatus == Node.CONDITION || node.prev == null) + return false; + if (node.next != null) // If has successor, it must be on queue + return true; + /* + * node.prev can be non-null, but not yet on queue because + * the CAS to place it on queue can fail. So we have to + * traverse from tail to make sure it actually made it. It + * will always be near the tail in calls to this method, and + * unless the CAS failed (which is unlikely), it will be + * there, so we hardly ever traverse much. + */ + return findNodeFromTail(node); + } + + /** + * Returns true if node is on sync queue by searching backwards from tail. + * Called only when needed by isOnSyncQueue. + * @return true if present + */ + private boolean findNodeFromTail(Node node) { + Node t = tail; + for (;;) { + if (t == node) + return true; + if (t == null) + return false; + t = t.prev; + } + } + + /** + * Transfers a node from a condition queue onto sync queue. + * Returns true if successful. + * @param node the node + * @return true if successfully transferred (else the node was + * cancelled before signal) + */ + final boolean transferForSignal(Node node) { + /* + * If cannot change waitStatus, the node has been cancelled. + */ + if (!compareAndSetWaitStatus(node, Node.CONDITION, 0)) + return false; + + /* + * Splice onto queue and try to set waitStatus of predecessor to + * indicate that thread is (probably) waiting. If cancelled or + * attempt to set waitStatus fails, wake up to resync (in which + * case the waitStatus can be transiently and harmlessly wrong). + */ + Node p = enq(node); + int ws = p.waitStatus; + if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL)) + LockSupport.unpark(node.thread); + return true; + } + + /** + * Transfers node, if necessary, to sync queue after a cancelled wait. + * Returns true if thread was cancelled before being signalled. + * + * @param node the node + * @return true if cancelled before the node was signalled + */ + final boolean transferAfterCancelledWait(Node node) { + if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) { + enq(node); + return true; + } + /* + * If we lost out to a signal(), then we can't proceed + * until it finishes its enq(). Cancelling during an + * incomplete transfer is both rare and transient, so just + * spin. + */ + while (!isOnSyncQueue(node)) + Thread.yield(); + return false; + } + + /** + * Invokes release with current state value; returns saved state. + * Cancels node and throws exception on failure. + * @param node the condition node for this wait + * @return previous sync state + */ + final int fullyRelease(Node node) { + boolean failed = true; + try { + int savedState = getState(); + if (release(savedState)) { + failed = false; + return savedState; + } else { + throw new IllegalMonitorStateException(); + } + } finally { + if (failed) + node.waitStatus = Node.CANCELLED; + } + } + + // Instrumentation methods for conditions + + /** + * Queries whether the given ConditionObject + * uses this synchronizer as its lock. + * + * @param condition the condition + * @return {@code true} if owned + * @throws NullPointerException if the condition is null + */ + public final boolean owns(ConditionObject condition) { + return condition.isOwnedBy(this); + } + + /** + * Queries whether any threads are waiting on the given condition + * associated with this synchronizer. Note that because timeouts + * and interrupts may occur at any time, a {@code true} return + * does not guarantee that a future {@code signal} will awaken + * any threads. This method is designed primarily for use in + * monitoring of the system state. + * + * @param condition the condition + * @return {@code true} if there are any waiting threads + * @throws IllegalMonitorStateException if exclusive synchronization + * is not held + * @throws IllegalArgumentException if the given condition is + * not associated with this synchronizer + * @throws NullPointerException if the condition is null + */ + public final boolean hasWaiters(ConditionObject condition) { + if (!owns(condition)) + throw new IllegalArgumentException("Not owner"); + return condition.hasWaiters(); + } + + /** + * Returns an estimate of the number of threads waiting on the + * given condition associated with this synchronizer. Note that + * because timeouts and interrupts may occur at any time, the + * estimate serves only as an upper bound on the actual number of + * waiters. This method is designed for use in monitoring of the + * system state, not for synchronization control. + * + * @param condition the condition + * @return the estimated number of waiting threads + * @throws IllegalMonitorStateException if exclusive synchronization + * is not held + * @throws IllegalArgumentException if the given condition is + * not associated with this synchronizer + * @throws NullPointerException if the condition is null + */ + public final int getWaitQueueLength(ConditionObject condition) { + if (!owns(condition)) + throw new IllegalArgumentException("Not owner"); + return condition.getWaitQueueLength(); + } + + /** + * Returns a collection containing those threads that may be + * waiting on the given condition associated with this + * synchronizer. Because the actual set of threads may change + * dynamically while constructing this result, the returned + * collection is only a best-effort estimate. The elements of the + * returned collection are in no particular order. + * + * @param condition the condition + * @return the collection of threads + * @throws IllegalMonitorStateException if exclusive synchronization + * is not held + * @throws IllegalArgumentException if the given condition is + * not associated with this synchronizer + * @throws NullPointerException if the condition is null + */ + public final Collection getWaitingThreads(ConditionObject condition) { + if (!owns(condition)) + throw new IllegalArgumentException("Not owner"); + return condition.getWaitingThreads(); + } + + /** + * Condition implementation for a {@link + * AbstractQueuedSynchronizer} serving as the basis of a {@link + * Lock} implementation. + * + *

Method documentation for this class describes mechanics, + * not behavioral specifications from the point of view of Lock + * and Condition users. Exported versions of this class will in + * general need to be accompanied by documentation describing + * condition semantics that rely on those of the associated + * {@code AbstractQueuedSynchronizer}. + * + *

This class is Serializable, but all fields are transient, + * so deserialized conditions have no waiters. + */ + public class ConditionObject implements Condition, java.io.Serializable { + private static final long serialVersionUID = 1173984872572414699L; + /** First node of condition queue. */ + private transient Node firstWaiter; + /** Last node of condition queue. */ + private transient Node lastWaiter; + + /** + * Creates a new {@code ConditionObject} instance. + */ + public ConditionObject() { } + + // Internal methods + + /** + * Adds a new waiter to wait queue. + * @return its new wait node + */ + private Node addConditionWaiter() { + Node t = lastWaiter; + // If lastWaiter is cancelled, clean out. + if (t != null && t.waitStatus != Node.CONDITION) { + unlinkCancelledWaiters(); + t = lastWaiter; + } + Node node = new Node(Thread.currentThread(), Node.CONDITION); + if (t == null) + firstWaiter = node; + else + t.nextWaiter = node; + lastWaiter = node; + return node; + } + + /** + * Removes and transfers nodes until hit non-cancelled one or + * null. Split out from signal in part to encourage compilers + * to inline the case of no waiters. + * @param first (non-null) the first node on condition queue + */ + private void doSignal(Node first) { + do { + if ( (firstWaiter = first.nextWaiter) == null) + lastWaiter = null; + first.nextWaiter = null; + } while (!transferForSignal(first) && + (first = firstWaiter) != null); + } + + /** + * Removes and transfers all nodes. + * @param first (non-null) the first node on condition queue + */ + private void doSignalAll(Node first) { + lastWaiter = firstWaiter = null; + do { + Node next = first.nextWaiter; + first.nextWaiter = null; + transferForSignal(first); + first = next; + } while (first != null); + } + + /** + * Unlinks cancelled waiter nodes from condition queue. + * Called only while holding lock. This is called when + * cancellation occurred during condition wait, and upon + * insertion of a new waiter when lastWaiter is seen to have + * been cancelled. This method is needed to avoid garbage + * retention in the absence of signals. So even though it may + * require a full traversal, it comes into play only when + * timeouts or cancellations occur in the absence of + * signals. It traverses all nodes rather than stopping at a + * particular target to unlink all pointers to garbage nodes + * without requiring many re-traversals during cancellation + * storms. + */ + private void unlinkCancelledWaiters() { + Node t = firstWaiter; + Node trail = null; + while (t != null) { + Node next = t.nextWaiter; + if (t.waitStatus != Node.CONDITION) { + t.nextWaiter = null; + if (trail == null) + firstWaiter = next; + else + trail.nextWaiter = next; + if (next == null) + lastWaiter = trail; + } + else + trail = t; + t = next; + } + } + + // public methods + + /** + * Moves the longest-waiting thread, if one exists, from the + * wait queue for this condition to the wait queue for the + * owning lock. + * + * @throws IllegalMonitorStateException if {@link #isHeldExclusively} + * returns {@code false} + */ + public final void signal() { + if (!isHeldExclusively()) + throw new IllegalMonitorStateException(); + Node first = firstWaiter; + if (first != null) + doSignal(first); + } + + /** + * Moves all threads from the wait queue for this condition to + * the wait queue for the owning lock. + * + * @throws IllegalMonitorStateException if {@link #isHeldExclusively} + * returns {@code false} + */ + public final void signalAll() { + if (!isHeldExclusively()) + throw new IllegalMonitorStateException(); + Node first = firstWaiter; + if (first != null) + doSignalAll(first); + } + + /** + * Implements uninterruptible condition wait. + *

    + *
  1. Save lock state returned by {@link #getState}. + *
  2. Invoke {@link #release} with saved state as argument, + * throwing IllegalMonitorStateException if it fails. + *
  3. Block until signalled. + *
  4. Reacquire by invoking specialized version of + * {@link #acquire} with saved state as argument. + *
+ */ + public final void awaitUninterruptibly() { + Node node = addConditionWaiter(); + int savedState = fullyRelease(node); + boolean interrupted = false; + while (!isOnSyncQueue(node)) { + LockSupport.park(this); + if (Thread.interrupted()) + interrupted = true; + } + if (acquireQueued(node, savedState) || interrupted) + selfInterrupt(); + } + + /* + * For interruptible waits, we need to track whether to throw + * InterruptedException, if interrupted while blocked on + * condition, versus reinterrupt current thread, if + * interrupted while blocked waiting to re-acquire. + */ + + /** Mode meaning to reinterrupt on exit from wait */ + private static final int REINTERRUPT = 1; + /** Mode meaning to throw InterruptedException on exit from wait */ + private static final int THROW_IE = -1; + + /** + * Checks for interrupt, returning THROW_IE if interrupted + * before signalled, REINTERRUPT if after signalled, or + * 0 if not interrupted. + */ + private int checkInterruptWhileWaiting(Node node) { + return Thread.interrupted() ? + (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) : + 0; + } + + /** + * Throws InterruptedException, reinterrupts current thread, or + * does nothing, depending on mode. + */ + private void reportInterruptAfterWait(int interruptMode) + throws InterruptedException { + if (interruptMode == THROW_IE) + throw new InterruptedException(); + else if (interruptMode == REINTERRUPT) + selfInterrupt(); + } + + /** + * Implements interruptible condition wait. + *
    + *
  1. If current thread is interrupted, throw InterruptedException. + *
  2. Save lock state returned by {@link #getState}. + *
  3. Invoke {@link #release} with saved state as argument, + * throwing IllegalMonitorStateException if it fails. + *
  4. Block until signalled or interrupted. + *
  5. Reacquire by invoking specialized version of + * {@link #acquire} with saved state as argument. + *
  6. If interrupted while blocked in step 4, throw InterruptedException. + *
+ */ + public final void await() throws InterruptedException { + if (Thread.interrupted()) + throw new InterruptedException(); + Node node = addConditionWaiter(); + int savedState = fullyRelease(node); + int interruptMode = 0; + while (!isOnSyncQueue(node)) { + LockSupport.park(this); + if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) + break; + } + if (acquireQueued(node, savedState) && interruptMode != THROW_IE) + interruptMode = REINTERRUPT; + if (node.nextWaiter != null) // clean up if cancelled + unlinkCancelledWaiters(); + if (interruptMode != 0) + reportInterruptAfterWait(interruptMode); + } + + /** + * Implements timed condition wait. + *
    + *
  1. If current thread is interrupted, throw InterruptedException. + *
  2. Save lock state returned by {@link #getState}. + *
  3. Invoke {@link #release} with saved state as argument, + * throwing IllegalMonitorStateException if it fails. + *
  4. Block until signalled, interrupted, or timed out. + *
  5. Reacquire by invoking specialized version of + * {@link #acquire} with saved state as argument. + *
  6. If interrupted while blocked in step 4, throw InterruptedException. + *
+ */ + public final long awaitNanos(long nanosTimeout) + throws InterruptedException { + if (Thread.interrupted()) + throw new InterruptedException(); + Node node = addConditionWaiter(); + int savedState = fullyRelease(node); + final long deadline = System.nanoTime() + nanosTimeout; + int interruptMode = 0; + while (!isOnSyncQueue(node)) { + if (nanosTimeout <= 0L) { + transferAfterCancelledWait(node); + break; + } + if (nanosTimeout >= spinForTimeoutThreshold) + LockSupport.parkNanos(this, nanosTimeout); + if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) + break; + nanosTimeout = deadline - System.nanoTime(); + } + if (acquireQueued(node, savedState) && interruptMode != THROW_IE) + interruptMode = REINTERRUPT; + if (node.nextWaiter != null) + unlinkCancelledWaiters(); + if (interruptMode != 0) + reportInterruptAfterWait(interruptMode); + return deadline - System.nanoTime(); + } + + /** + * Implements absolute timed condition wait. + *
    + *
  1. If current thread is interrupted, throw InterruptedException. + *
  2. Save lock state returned by {@link #getState}. + *
  3. Invoke {@link #release} with saved state as argument, + * throwing IllegalMonitorStateException if it fails. + *
  4. Block until signalled, interrupted, or timed out. + *
  5. Reacquire by invoking specialized version of + * {@link #acquire} with saved state as argument. + *
  6. If interrupted while blocked in step 4, throw InterruptedException. + *
  7. If timed out while blocked in step 4, return false, else true. + *
+ */ + public final boolean awaitUntil(Date deadline) + throws InterruptedException { + long abstime = deadline.getTime(); + if (Thread.interrupted()) + throw new InterruptedException(); + Node node = addConditionWaiter(); + int savedState = fullyRelease(node); + boolean timedout = false; + int interruptMode = 0; + while (!isOnSyncQueue(node)) { + if (System.currentTimeMillis() > abstime) { + timedout = transferAfterCancelledWait(node); + break; + } + LockSupport.parkUntil(this, abstime); + if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) + break; + } + if (acquireQueued(node, savedState) && interruptMode != THROW_IE) + interruptMode = REINTERRUPT; + if (node.nextWaiter != null) + unlinkCancelledWaiters(); + if (interruptMode != 0) + reportInterruptAfterWait(interruptMode); + return !timedout; + } + + /** + * Implements timed condition wait. + *
    + *
  1. If current thread is interrupted, throw InterruptedException. + *
  2. Save lock state returned by {@link #getState}. + *
  3. Invoke {@link #release} with saved state as argument, + * throwing IllegalMonitorStateException if it fails. + *
  4. Block until signalled, interrupted, or timed out. + *
  5. Reacquire by invoking specialized version of + * {@link #acquire} with saved state as argument. + *
  6. If interrupted while blocked in step 4, throw InterruptedException. + *
  7. If timed out while blocked in step 4, return false, else true. + *
+ */ + public final boolean await(long time, TimeUnit unit) + throws InterruptedException { + long nanosTimeout = unit.toNanos(time); + if (Thread.interrupted()) + throw new InterruptedException(); + Node node = addConditionWaiter(); + int savedState = fullyRelease(node); + final long deadline = System.nanoTime() + nanosTimeout; + boolean timedout = false; + int interruptMode = 0; + while (!isOnSyncQueue(node)) { + if (nanosTimeout <= 0L) { + timedout = transferAfterCancelledWait(node); + break; + } + if (nanosTimeout >= spinForTimeoutThreshold) + LockSupport.parkNanos(this, nanosTimeout); + if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) + break; + nanosTimeout = deadline - System.nanoTime(); + } + if (acquireQueued(node, savedState) && interruptMode != THROW_IE) + interruptMode = REINTERRUPT; + if (node.nextWaiter != null) + unlinkCancelledWaiters(); + if (interruptMode != 0) + reportInterruptAfterWait(interruptMode); + return !timedout; + } + + // support for instrumentation + + /** + * Returns true if this condition was created by the given + * synchronization object. + * + * @return {@code true} if owned + */ + final boolean isOwnedBy(AbstractQueuedSynchronizer sync) { + return sync == AbstractQueuedSynchronizer.this; + } + + /** + * Queries whether any threads are waiting on this condition. + * Implements {@link AbstractQueuedSynchronizer#hasWaiters(ConditionObject)}. + * + * @return {@code true} if there are any waiting threads + * @throws IllegalMonitorStateException if {@link #isHeldExclusively} + * returns {@code false} + */ + protected final boolean hasWaiters() { + if (!isHeldExclusively()) + throw new IllegalMonitorStateException(); + for (Node w = firstWaiter; w != null; w = w.nextWaiter) { + if (w.waitStatus == Node.CONDITION) + return true; + } + return false; + } + + /** + * Returns an estimate of the number of threads waiting on + * this condition. + * Implements {@link AbstractQueuedSynchronizer#getWaitQueueLength(ConditionObject)}. + * + * @return the estimated number of waiting threads + * @throws IllegalMonitorStateException if {@link #isHeldExclusively} + * returns {@code false} + */ + protected final int getWaitQueueLength() { + if (!isHeldExclusively()) + throw new IllegalMonitorStateException(); + int n = 0; + for (Node w = firstWaiter; w != null; w = w.nextWaiter) { + if (w.waitStatus == Node.CONDITION) + ++n; + } + return n; + } + + /** + * Returns a collection containing those threads that may be + * waiting on this Condition. + * Implements {@link AbstractQueuedSynchronizer#getWaitingThreads(ConditionObject)}. + * + * @return the collection of threads + * @throws IllegalMonitorStateException if {@link #isHeldExclusively} + * returns {@code false} + */ + protected final Collection getWaitingThreads() { + if (!isHeldExclusively()) + throw new IllegalMonitorStateException(); + ArrayList list = new ArrayList(); + for (Node w = firstWaiter; w != null; w = w.nextWaiter) { + if (w.waitStatus == Node.CONDITION) { + Thread t = w.thread; + if (t != null) + list.add(t); + } + } + return list; + } + } + + /** + * IKVM specific. We use AtomicReferenceFieldUpdater instead of Unsafe primitives. + */ + private static final AtomicReferenceFieldUpdater headUpdater = + AtomicReferenceFieldUpdater.newUpdater(AbstractQueuedSynchronizer.class, Node.class, "head"); + private static final AtomicReferenceFieldUpdater tailUpdater = + AtomicReferenceFieldUpdater.newUpdater(AbstractQueuedSynchronizer.class, Node.class, "tail"); + + /** + * CAS head field. Used only by enq. + */ + private final boolean compareAndSetHead(Node update) { + return headUpdater.compareAndSet(this, null, update); + } + + /** + * CAS tail field. Used only by enq. + */ + private final boolean compareAndSetTail(Node expect, Node update) { + return tailUpdater.compareAndSet(this, expect, update); + } + + /** + * CAS waitStatus field of a node. + */ + private static final native boolean compareAndSetWaitStatus(Node node, + int expect, + int update); // implemented in map.xml + /** + * CAS next field of a node. + */ + private static final boolean compareAndSetNext(Node node, + Node expect, + Node update) { + return Node.nextUpdater.compareAndSet(node, expect, update); + } +} diff --git a/openjdk/java/util/concurrent/locks/LockSupport.java b/openjdk/java/util/concurrent/locks/LockSupport.java new file mode 100644 index 0000000..45a3811 --- /dev/null +++ b/openjdk/java/util/concurrent/locks/LockSupport.java @@ -0,0 +1,456 @@ +/* + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +package java.util.concurrent.locks; + +/** + * Basic thread blocking primitives for creating locks and other + * synchronization classes. + * + *

This class associates, with each thread that uses it, a permit + * (in the sense of the {@link java.util.concurrent.Semaphore + * Semaphore} class). A call to {@code park} will return immediately + * if the permit is available, consuming it in the process; otherwise + * it may block. A call to {@code unpark} makes the permit + * available, if it was not already available. (Unlike with Semaphores + * though, permits do not accumulate. There is at most one.) + * + *

Methods {@code park} and {@code unpark} provide efficient + * means of blocking and unblocking threads that do not encounter the + * problems that cause the deprecated methods {@code Thread.suspend} + * and {@code Thread.resume} to be unusable for such purposes: Races + * between one thread invoking {@code park} and another thread trying + * to {@code unpark} it will preserve liveness, due to the + * permit. Additionally, {@code park} will return if the caller's + * thread was interrupted, and timeout versions are supported. The + * {@code park} method may also return at any other time, for "no + * reason", so in general must be invoked within a loop that rechecks + * conditions upon return. In this sense {@code park} serves as an + * optimization of a "busy wait" that does not waste as much time + * spinning, but must be paired with an {@code unpark} to be + * effective. + * + *

The three forms of {@code park} each also support a + * {@code blocker} object parameter. This object is recorded while + * the thread is blocked to permit monitoring and diagnostic tools to + * identify the reasons that threads are blocked. (Such tools may + * access blockers using method {@link #getBlocker(Thread)}.) + * The use of these forms rather than the original forms without this + * parameter is strongly encouraged. The normal argument to supply as + * a {@code blocker} within a lock implementation is {@code this}. + * + *

These methods are designed to be used as tools for creating + * higher-level synchronization utilities, and are not in themselves + * useful for most concurrency control applications. The {@code park} + * method is designed for use only in constructions of the form: + * + *

 {@code
+ * while (!canProceed()) { ... LockSupport.park(this); }}
+ * + * where neither {@code canProceed} nor any other actions prior to the + * call to {@code park} entail locking or blocking. Because only one + * permit is associated with each thread, any intermediary uses of + * {@code park} could interfere with its intended effects. + * + *

Sample Usage. Here is a sketch of a first-in-first-out + * non-reentrant lock class: + *

 {@code
+ * class FIFOMutex {
+ *   private final AtomicBoolean locked = new AtomicBoolean(false);
+ *   private final Queue waiters
+ *     = new ConcurrentLinkedQueue();
+ *
+ *   public void lock() {
+ *     boolean wasInterrupted = false;
+ *     Thread current = Thread.currentThread();
+ *     waiters.add(current);
+ *
+ *     // Block while not first in queue or cannot acquire lock
+ *     while (waiters.peek() != current ||
+ *            !locked.compareAndSet(false, true)) {
+ *       LockSupport.park(this);
+ *       if (Thread.interrupted()) // ignore interrupts while waiting
+ *         wasInterrupted = true;
+ *     }
+ *
+ *     waiters.remove();
+ *     if (wasInterrupted)          // reassert interrupt status on exit
+ *       current.interrupt();
+ *   }
+ *
+ *   public void unlock() {
+ *     locked.set(false);
+ *     LockSupport.unpark(waiters.peek());
+ *   }
+ * }}
+ */ +public class LockSupport { + private LockSupport() {} // Cannot be instantiated. + + private static void setBlocker(Thread t, Object arg) { + t.parkBlocker = arg; + } + + private static final int PARK_STATE_RUNNING = 0; + private static final int PARK_STATE_PERMIT = 1; + private static final int PARK_STATE_PARKED = 2; + + // these native methods are all implemented in map.xml + private static native int cmpxchgParkState(Thread t, int newValue, int comparand); + private static native Object getParkLock(Thread t); + private static native void setParkLock(Thread t, Object obj); + + /** + * Makes available the permit for the given thread, if it + * was not already available. If the thread was blocked on + * {@code park} then it will unblock. Otherwise, its next call + * to {@code park} is guaranteed not to block. This operation + * is not guaranteed to have any effect at all if the given + * thread has not been started. + * + * @param thread the thread to unpark, or {@code null}, in which case + * this operation has no effect + */ + public static void unpark(Thread thread) { + if (thread != null) + { + if (cmpxchgParkState(thread, PARK_STATE_PERMIT, PARK_STATE_RUNNING) == PARK_STATE_PARKED) + { + if (cmpxchgParkState(thread, PARK_STATE_RUNNING, PARK_STATE_PARKED) == PARK_STATE_PARKED) + { + // thread is currently blocking, so we have to release it + Object lock = getParkLock(thread); + synchronized (lock) + { + lock.notify(); + } + } + } + } + } + + private static void parkImpl(Thread currentThread, boolean deadline, long nanos) + { + if (cmpxchgParkState(currentThread, PARK_STATE_RUNNING, PARK_STATE_PERMIT) == PARK_STATE_PERMIT) + { + // we consumed a permit + return; + } + + Object lock = getParkLock(currentThread); + if (lock == null) + { + // we lazily allocate the lock object + lock = new Object(); + setParkLock(currentThread, lock); + } + synchronized (lock) + { + if (cmpxchgParkState(currentThread, PARK_STATE_PARKED, PARK_STATE_RUNNING) == PARK_STATE_PERMIT) + { + // entering the parked state failed because we got a permit after the previous permit test + // release the permit and return + cmpxchgParkState(currentThread, PARK_STATE_RUNNING, PARK_STATE_PERMIT); + return; + } + if (deadline) + { + nanos -= System.currentTimeMillis() * 1000000; + } + if (nanos >= 0) + { + try + { + lock.wait(nanos / 1000000, (int)(nanos % 1000000)); + } + catch (InterruptedException _) + { + currentThread.interrupt(); + } + } + cmpxchgParkState(currentThread, PARK_STATE_RUNNING, PARK_STATE_PARKED); + } + } + + /** + * Disables the current thread for thread scheduling purposes unless the + * permit is available. + * + *

If the permit is available then it is consumed and the call returns + * immediately; otherwise + * the current thread becomes disabled for thread scheduling + * purposes and lies dormant until one of three things happens: + * + *

    + *
  • Some other thread invokes {@link #unpark unpark} with the + * current thread as the target; or + * + *
  • Some other thread {@linkplain Thread#interrupt interrupts} + * the current thread; or + * + *
  • The call spuriously (that is, for no reason) returns. + *
+ * + *

This method does not report which of these caused the + * method to return. Callers should re-check the conditions which caused + * the thread to park in the first place. Callers may also determine, + * for example, the interrupt status of the thread upon return. + * + * @param blocker the synchronization object responsible for this + * thread parking + * @since 1.6 + */ + public static void park(Object blocker) { + Thread t = Thread.currentThread(); + setBlocker(t, blocker); + parkImpl(t, false, 0L); + setBlocker(t, null); + } + + /** + * Disables the current thread for thread scheduling purposes, for up to + * the specified waiting time, unless the permit is available. + * + *

If the permit is available then it is consumed and the call + * returns immediately; otherwise the current thread becomes disabled + * for thread scheduling purposes and lies dormant until one of four + * things happens: + * + *

    + *
  • Some other thread invokes {@link #unpark unpark} with the + * current thread as the target; or + * + *
  • Some other thread {@linkplain Thread#interrupt interrupts} + * the current thread; or + * + *
  • The specified waiting time elapses; or + * + *
  • The call spuriously (that is, for no reason) returns. + *
+ * + *

This method does not report which of these caused the + * method to return. Callers should re-check the conditions which caused + * the thread to park in the first place. Callers may also determine, + * for example, the interrupt status of the thread, or the elapsed time + * upon return. + * + * @param blocker the synchronization object responsible for this + * thread parking + * @param nanos the maximum number of nanoseconds to wait + * @since 1.6 + */ + public static void parkNanos(Object blocker, long nanos) { + if (nanos > 0) { + Thread t = Thread.currentThread(); + setBlocker(t, blocker); + parkImpl(t, false, nanos); + setBlocker(t, null); + } + } + + /** + * Disables the current thread for thread scheduling purposes, until + * the specified deadline, unless the permit is available. + * + *

If the permit is available then it is consumed and the call + * returns immediately; otherwise the current thread becomes disabled + * for thread scheduling purposes and lies dormant until one of four + * things happens: + * + *

    + *
  • Some other thread invokes {@link #unpark unpark} with the + * current thread as the target; or + * + *
  • Some other thread {@linkplain Thread#interrupt interrupts} the + * current thread; or + * + *
  • The specified deadline passes; or + * + *
  • The call spuriously (that is, for no reason) returns. + *
+ * + *

This method does not report which of these caused the + * method to return. Callers should re-check the conditions which caused + * the thread to park in the first place. Callers may also determine, + * for example, the interrupt status of the thread, or the current time + * upon return. + * + * @param blocker the synchronization object responsible for this + * thread parking + * @param deadline the absolute time, in milliseconds from the Epoch, + * to wait until + * @since 1.6 + */ + public static void parkUntil(Object blocker, long deadline) { + Thread t = Thread.currentThread(); + setBlocker(t, blocker); + parkImpl(t, true, deadline * 1000000); + setBlocker(t, null); + } + + /** + * Returns the blocker object supplied to the most recent + * invocation of a park method that has not yet unblocked, or null + * if not blocked. The value returned is just a momentary + * snapshot -- the thread may have since unblocked or blocked on a + * different blocker object. + * + * @param t the thread + * @return the blocker + * @throws NullPointerException if argument is null + * @since 1.6 + */ + public static Object getBlocker(Thread t) { + if (t == null) + throw new NullPointerException(); + return t.parkBlocker; + } + + /** + * Disables the current thread for thread scheduling purposes unless the + * permit is available. + * + *

If the permit is available then it is consumed and the call + * returns immediately; otherwise the current thread becomes disabled + * for thread scheduling purposes and lies dormant until one of three + * things happens: + * + *

    + * + *
  • Some other thread invokes {@link #unpark unpark} with the + * current thread as the target; or + * + *
  • Some other thread {@linkplain Thread#interrupt interrupts} + * the current thread; or + * + *
  • The call spuriously (that is, for no reason) returns. + *
+ * + *

This method does not report which of these caused the + * method to return. Callers should re-check the conditions which caused + * the thread to park in the first place. Callers may also determine, + * for example, the interrupt status of the thread upon return. + */ + public static void park() { + parkImpl(Thread.currentThread(), false, 0L); + } + + /** + * Disables the current thread for thread scheduling purposes, for up to + * the specified waiting time, unless the permit is available. + * + *

If the permit is available then it is consumed and the call + * returns immediately; otherwise the current thread becomes disabled + * for thread scheduling purposes and lies dormant until one of four + * things happens: + * + *

    + *
  • Some other thread invokes {@link #unpark unpark} with the + * current thread as the target; or + * + *
  • Some other thread {@linkplain Thread#interrupt interrupts} + * the current thread; or + * + *
  • The specified waiting time elapses; or + * + *
  • The call spuriously (that is, for no reason) returns. + *
+ * + *

This method does not report which of these caused the + * method to return. Callers should re-check the conditions which caused + * the thread to park in the first place. Callers may also determine, + * for example, the interrupt status of the thread, or the elapsed time + * upon return. + * + * @param nanos the maximum number of nanoseconds to wait + */ + public static void parkNanos(long nanos) { + if (nanos > 0) + parkImpl(Thread.currentThread(), false, nanos); + } + + /** + * Disables the current thread for thread scheduling purposes, until + * the specified deadline, unless the permit is available. + * + *

If the permit is available then it is consumed and the call + * returns immediately; otherwise the current thread becomes disabled + * for thread scheduling purposes and lies dormant until one of four + * things happens: + * + *

    + *
  • Some other thread invokes {@link #unpark unpark} with the + * current thread as the target; or + * + *
  • Some other thread {@linkplain Thread#interrupt interrupts} + * the current thread; or + * + *
  • The specified deadline passes; or + * + *
  • The call spuriously (that is, for no reason) returns. + *
+ * + *

This method does not report which of these caused the + * method to return. Callers should re-check the conditions which caused + * the thread to park in the first place. Callers may also determine, + * for example, the interrupt status of the thread, or the current time + * upon return. + * + * @param deadline the absolute time, in milliseconds from the Epoch, + * to wait until + */ + public static void parkUntil(long deadline) { + parkImpl(Thread.currentThread(), true, deadline * 1000000); + } + + /** + * Returns the pseudo-randomly initialized or updated secondary seed. + * Copied from ThreadLocalRandom due to package access restrictions. + */ + static final int nextSecondarySeed() { + int r; + Thread t = Thread.currentThread(); + if ((r = t.threadLocalRandomSecondarySeed) != 0) { + r ^= r << 13; // xorshift + r ^= r >>> 17; + r ^= r << 5; + } + else if ((r = java.util.concurrent.ThreadLocalRandom.current().nextInt()) == 0) + r = 1; // avoid zero + t.threadLocalRandomSecondarySeed = r; + return r; + } + +} diff --git a/openjdk/java/util/zip/Adler32.java b/openjdk/java/util/zip/Adler32.java new file mode 100644 index 0000000..7e399b4 --- /dev/null +++ b/openjdk/java/util/zip/Adler32.java @@ -0,0 +1,212 @@ +/* Adler32.java - Computes Adler32 data checksum of a data stream + Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.util.zip; + +/* + * Written using on-line Java Platform 1.2 API Specification, as well + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). + * The actual Adler32 algorithm is taken from RFC 1950. + * Status: Believed complete and correct. + */ + +/** + * Computes Adler32 checksum for a stream of data. An Adler32 + * checksum is not as reliable as a CRC32 checksum, but a lot faster to + * compute. + *

+ * The specification for Adler32 may be found in RFC 1950. + * (ZLIB Compressed Data Format Specification version 3.3) + *

+ *

+ * From that document: + *

+ * "ADLER32 (Adler-32 checksum) + * This contains a checksum value of the uncompressed data + * (excluding any dictionary data) computed according to Adler-32 + * algorithm. This algorithm is a 32-bit extension and improvement + * of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 + * standard. + *

+ * Adler-32 is composed of two sums accumulated per byte: s1 is + * the sum of all bytes, s2 is the sum of all s1 values. Both sums + * are done modulo 65521. s1 is initialized to 1, s2 to zero. The + * Adler-32 checksum is stored as s2*65536 + s1 in most- + * significant-byte first (network) order." + *

+ * "8.2. The Adler-32 algorithm + *

+ * The Adler-32 algorithm is much faster than the CRC32 algorithm yet + * still provides an extremely low probability of undetected errors. + *

+ * The modulo on unsigned long accumulators can be delayed for 5552 + * bytes, so the modulo operation time is negligible. If the bytes + * are a, b, c, the second sum is 3a + 2b + c + 3, and so is position + * and order sensitive, unlike the first sum, which is just a + * checksum. That 65521 is prime is important to avoid a possible + * large class of two-byte errors that leave the check unchanged. + * (The Fletcher checksum uses 255, which is not prime and which also + * makes the Fletcher check insensitive to single byte changes 0 <-> + * 255.) + *

+ * The sum s1 is initialized to 1 instead of zero to make the length + * of the sequence part of s2, so that the length does not have to be + * checked separately. (Any sequence of zeroes has a Fletcher + * checksum of zero.)" + * + * @author John Leuner, Per Bothner + * @since JDK 1.1 + * + * @see InflaterInputStream + * @see DeflaterOutputStream + */ +public class Adler32 implements Checksum +{ + + /** largest prime smaller than 65536 */ + private static final int BASE = 65521; + + private int adler; //we do all in int. + + //Note that java doesn't have unsigned integers, + //so we have to be careful with what arithmetic + //we do. We return the checksum as a long to + //avoid sign confusion. + + /** + * Creates a new instance of the Adler32 class. + * The checksum starts off with a value of 1. + */ + public Adler32 () + { + reset(); + } + + /** + * Resets the Adler32 checksum to the initial value. + */ + public void reset () + { + adler = 1; //Initialize to 1 + } + + /** + * Updates the checksum with the byte b. + * + * @param bval the data value to add. The high byte of the int is ignored. + */ + public void update (int bval) + { + //We could make a length 1 byte array and call update again, but I + //would rather not have that overhead + int s1 = adler & 0xffff; + int s2 = adler >>> 16; + + s1 = (s1 + (bval & 0xFF)) % BASE; + s2 = (s1 + s2) % BASE; + + adler = (s2 << 16) + s1; + } + + /** + * Updates the checksum with the bytes taken from the array. + * + * @param buffer an array of bytes + */ + public void update (byte[] buffer) + { + update(buffer, 0, buffer.length); + } + + /** + * Updates the checksum with the bytes taken from the array. + * + * @param buf an array of bytes + * @param off the start of the data used for this update + * @param len the number of bytes to use for this update + */ + public void update (byte[] buf, int off, int len) + { + //(By Per Bothner) + int s1 = adler & 0xffff; + int s2 = adler >>> 16; + + while (len > 0) + { + // We can defer the modulo operation: + // s1 maximally grows from 65521 to 65521 + 255 * 3800 + // s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31 + int n = 3800; + if (n > len) + n = len; + len -= n; + while (--n >= 0) + { + s1 = s1 + (buf[off++] & 0xFF); + s2 = s2 + s1; + } + s1 %= BASE; + s2 %= BASE; + } + + /*Old implementation, borrowed from somewhere: + int n; + + while (len-- > 0) { + + s1 = (s1 + (bs[offset++] & 0xff)) % BASE; + s2 = (s2 + s1) % BASE; + }*/ + + adler = (s2 << 16) | s1; + } + + public void update(java.nio.ByteBuffer buffer) + { + byte[] buf = new byte[buffer.remaining()]; + buffer.get(buf); + update(buf, 0, buf.length); + } + + /** + * Returns the Adler32 data checksum computed so far. + */ + public long getValue() + { + return (long) adler & 0xffffffffL; + } +} diff --git a/openjdk/java/util/zip/CRC32.java b/openjdk/java/util/zip/CRC32.java new file mode 100644 index 0000000..235f0d8 --- /dev/null +++ b/openjdk/java/util/zip/CRC32.java @@ -0,0 +1,139 @@ +/* CRC32.java - Computes CRC32 data checksum of a data stream + Copyright (C) 1999. 2000, 2001 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.util.zip; + +/* + * Written using on-line Java Platform 1.2 API Specification, as well + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). + * The actual CRC32 algorithm is taken from RFC 1952. + * Status: Believed complete and correct. + */ + +/** + * Computes CRC32 data checksum of a data stream. + * The actual CRC32 algorithm is described in RFC 1952 + * (GZIP file format specification version 4.3). + * Can be used to get the CRC32 over a stream if used with checked input/output + * streams. + * + * @see InflaterInputStream + * @see DeflaterOutputStream + * + * @author Per Bothner + * @date April 1, 1999. + */ +public class CRC32 implements Checksum +{ + /** The crc data checksum so far. */ + private int crc = 0; + + /** The fast CRC table. Computed once when the CRC32 class is loaded. */ + private static int[] crc_table = make_crc_table(); + + /** Make the table for a fast CRC. */ + private static int[] make_crc_table () + { + int[] crc_table = new int[256]; + for (int n = 0; n < 256; n++) + { + int c = n; + for (int k = 8; --k >= 0; ) + { + if ((c & 1) != 0) + c = 0xedb88320 ^ (c >>> 1); + else + c = c >>> 1; + } + crc_table[n] = c; + } + return crc_table; + } + + /** + * Returns the CRC32 data checksum computed so far. + */ + public long getValue () + { + return (long) crc & 0xffffffffL; + } + + /** + * Resets the CRC32 data checksum as if no update was ever called. + */ + public void reset () { crc = 0; } + + /** + * Updates the checksum with the int bval. + * + * @param bval (the byte is taken as the lower 8 bits of bval) + */ + + public void update (int bval) + { + int c = ~crc; + c = crc_table[(c ^ bval) & 0xff] ^ (c >>> 8); + crc = ~c; + } + + /** + * Adds the byte array to the data checksum. + * + * @param buf the buffer which contains the data + * @param off the offset in the buffer where the data starts + * @param len the length of the data + */ + public void update (byte[] buf, int off, int len) + { + int c = ~crc; + while (--len >= 0) + c = crc_table[(c ^ buf[off++]) & 0xff] ^ (c >>> 8); + crc = ~c; + } + + /** + * Adds the complete byte array to the data checksum. + */ + public void update (byte[] buf) { update(buf, 0, buf.length); } + + public void update(java.nio.ByteBuffer buffer) + { + byte[] buf = new byte[buffer.remaining()]; + buffer.get(buf); + update(buf, 0, buf.length); + } +} diff --git a/openjdk/java/util/zip/ClassStubZipEntry.java b/openjdk/java/util/zip/ClassStubZipEntry.java new file mode 100644 index 0000000..6a2a6df --- /dev/null +++ b/openjdk/java/util/zip/ClassStubZipEntry.java @@ -0,0 +1,98 @@ +/* + Copyright (C) 2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package java.util.zip; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.IOException; +import java.util.LinkedHashMap; + +final class ClassStubZipEntry extends ZipEntry +{ + private final String zipFilePath; + + ClassStubZipEntry(String zipFilePath, String name) + { + super(name); + this.zipFilePath = zipFilePath; + } + + private File getFile() + { + return new File(new File(zipFilePath).getParentFile().getParentFile(), "classes" + File.separator + name); + } + + public long getSize() + { + if (size == -1) + { + size = getFile().length(); + } + return size; + } + + public long getCompressedSize() + { + if (csize == -1) + { + csize = getSize(); + } + return csize; + } + + public long getCrc() + { + if (crc == -1) + { + crc = computeCrc(); + } + return crc; + } + + private long computeCrc() + { + try (InputStream in = getInputStream()) + { + CRC32 crc = new CRC32(); + int b; + while ((b = in.read()) != -1) + { + crc.update(b); + } + return crc.getValue(); + } + catch (IOException _) + { + return 0; + } + } + + final InputStream getInputStream() throws IOException + { + return new FileInputStream(getFile()); + } + + static native void expandIkvmClasses(ZipFile zipFile, LinkedHashMap entries); +} diff --git a/openjdk/java/util/zip/Deflater.java b/openjdk/java/util/zip/Deflater.java new file mode 100644 index 0000000..3c2a48e --- /dev/null +++ b/openjdk/java/util/zip/Deflater.java @@ -0,0 +1,569 @@ +/* Deflater.java - Compress a data stream + Copyright (C) 1999, 2000, 2001, 2004, 2005, 2011 + Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.util.zip; + +/** + * This is the Deflater class. The deflater class compresses input + * with the deflate algorithm described in RFC 1951. It has several + * compression levels and three different strategies described below. + * + * This class is not thread safe. This is inherent in the API, due + * to the split of deflate and setInput. + * + * @author Jochen Hoenicke + * @author Tom Tromey + */ +public class Deflater +{ + /** + * The best and slowest compression level. This tries to find very + * long and distant string repetitions. + */ + public static final int BEST_COMPRESSION = 9; + /** + * The worst but fastest compression level. + */ + public static final int BEST_SPEED = 1; + /** + * The default compression level. + */ + public static final int DEFAULT_COMPRESSION = -1; + /** + * This level won't compress at all but output uncompressed blocks. + */ + public static final int NO_COMPRESSION = 0; + + /** + * Flush operation. + */ + public static final int NO_FLUSH = 0; + public static final int SYNC_FLUSH = 2; + public static final int FULL_FLUSH = 3; + + /** + * The default strategy. + */ + public static final int DEFAULT_STRATEGY = 0; + /** + * This strategy will only allow longer string repetitions. It is + * useful for random data with a small character set. + */ + public static final int FILTERED = 1; + + /** + * This strategy will not look for string repetitions at all. It + * only encodes with Huffman trees (which means, that more common + * characters get a smaller encoding. + */ + public static final int HUFFMAN_ONLY = 2; + + /** + * The compression method. This is the only method supported so far. + * There is no need to use this constant at all. + */ + public static final int DEFLATED = 8; + + /* + * The Deflater can do the following state transitions: + * + * (1) -> INIT_STATE ----> INIT_FINISHING_STATE ---. + * / | (2) (5) | + * / v (5) | + * (3)| SETDICT_STATE ---> SETDICT_FINISHING_STATE |(3) + * \ | (3) | ,-------' + * | | | (3) / + * v v (5) v v + * (1) -> BUSY_STATE ----> FINISHING_STATE + * | (6) + * v + * FINISHED_STATE + * \_____________________________________/ + * | (7) + * v + * CLOSED_STATE + * + * (1) If we should produce a header we start in INIT_STATE, otherwise + * we start in BUSY_STATE. + * (2) A dictionary may be set only when we are in INIT_STATE, then + * we change the state as indicated. + * (3) Whether a dictionary is set or not, on the first call of deflate + * we change to BUSY_STATE. + * (4) -- intentionally left blank -- :) + * (5) FINISHING_STATE is entered, when flush() is called to indicate that + * there is no more INPUT. There are also states indicating, that + * the header wasn't written yet. + * (6) FINISHED_STATE is entered, when everything has been flushed to the + * internal pending output buffer. + * (7) At any time (7) + * + */ + + private static final int IS_SETDICT = 0x01; + private static final int IS_FINISHING = 0x08; + + private static final int INIT_STATE = 0x00; + private static final int SETDICT_STATE = 0x01; + private static final int INIT_FINISHING_STATE = 0x08; + private static final int SETDICT_FINISHING_STATE = 0x09; + private static final int BUSY_STATE = 0x10; + private static final int FINISHING_STATE = 0x18; + private static final int FINISHED_STATE = 0x1e; + private static final int CLOSED_STATE = 0x7f; + + /** Compression level. */ + private int level; + + /** should we include a header. */ + private boolean noHeader; + + /** The current state. */ + private int state; + + /** The flush level the previous deflate call used. */ + private int lastFlush; + + /** The total bytes of output written. */ + private long totalOut; + + /** The pending output. */ + private DeflaterPending pending; + + /** The deflater engine. */ + private DeflaterEngine engine; + + /** + * Creates a new deflater with default compression level. + */ + public Deflater() + { + this(DEFAULT_COMPRESSION, false); + } + + /** + * Creates a new deflater with given compression level. + * @param lvl the compression level, a value between NO_COMPRESSION + * and BEST_COMPRESSION, or DEFAULT_COMPRESSION. + * @exception IllegalArgumentException if lvl is out of range. + */ + public Deflater(int lvl) + { + this(lvl, false); + } + + /** + * Creates a new deflater with given compression level. + * @param lvl the compression level, a value between NO_COMPRESSION + * and BEST_COMPRESSION. + * @param nowrap true, iff we should suppress the deflate header at the + * beginning and the adler checksum at the end of the output. This is + * useful for the GZIP format. + * @exception IllegalArgumentException if lvl is out of range. + */ + public Deflater(int lvl, boolean nowrap) + { + if (lvl == DEFAULT_COMPRESSION) + lvl = 6; + else if (lvl < NO_COMPRESSION || lvl > BEST_COMPRESSION) + throw new IllegalArgumentException(); + + pending = new DeflaterPending(); + engine = new DeflaterEngine(pending); + this.noHeader = nowrap; + setStrategy(DEFAULT_STRATEGY); + setLevel(lvl); + reset(); + } + + /** + * Resets the deflater. The deflater acts afterwards as if it was + * just created with the same compression level and strategy as it + * had before. + */ + public void reset() + { + state = (noHeader ? BUSY_STATE : INIT_STATE); + totalOut = 0; + pending.reset(); + engine.reset(); + } + + /** + * Frees all objects allocated by the compressor. There's no + * reason to call this, since you can just rely on garbage + * collection. Exists only for compatibility against Sun's JDK, + * where the compressor allocates native memory. + * If you call any method (even reset) afterwards the behaviour is + * undefined. + */ + public void end() + { + engine = null; + pending = null; + state = CLOSED_STATE; + } + + /** + * Gets the current adler checksum of the data that was processed so + * far. + */ + public int getAdler() + { + return engine.getAdler(); + } + + /** + * Gets the number of input bytes processed so far. + */ + public int getTotalIn() + { + return (int) engine.getTotalIn(); + } + + /** + * Gets the number of input bytes processed so far. + * @since 1.5 + */ + public long getBytesRead() + { + return engine.getTotalIn(); + } + + /** + * Gets the number of output bytes so far. + */ + public int getTotalOut() + { + return (int) totalOut; + } + + /** + * Gets the number of output bytes so far. + * @since 1.5 + */ + public long getBytesWritten() + { + return totalOut; + } + + /** + * Finalizes this object. + */ + protected void finalize() + { + /* Exists solely for compatibility. We don't have any native state. */ + } + + /** + * Finishes the deflater with the current input block. It is an error + * to give more input after this method was called. This method must + * be called to force all bytes to be flushed. + */ + public void finish() { + state |= IS_FINISHING; + } + + /** + * Returns true iff the stream was finished and no more output bytes + * are available. + */ + public boolean finished() + { + return state == FINISHED_STATE && pending.isFlushed(); + } + + /** + * Returns true, if the input buffer is empty. + * You should then call setInput().
+ * + * NOTE: This method can also return true when the stream + * was finished. + */ + public boolean needsInput() + { + return engine.needsInput(); + } + + /** + * Sets the data which should be compressed next. This should be only + * called when needsInput indicates that more input is needed. + * If you call setInput when needsInput() returns false, the + * previous input that is still pending will be thrown away. + * The given byte array should not be changed, before needsInput() returns + * true again. + * This call is equivalent to setInput(input, 0, input.length). + * @param input the buffer containing the input data. + * @exception IllegalStateException if the buffer was finished() or ended(). + */ + public void setInput(byte[] input) + { + setInput(input, 0, input.length); + } + + /** + * Sets the data which should be compressed next. This should be + * only called when needsInput indicates that more input is needed. + * The given byte array should not be changed, before needsInput() returns + * true again. + * @param input the buffer containing the input data. + * @param off the start of the data. + * @param len the length of the data. + * @exception IllegalStateException if the buffer was finished() or ended() + * or if previous input is still pending. + */ + public void setInput(byte[] input, int off, int len) + { + if (input == null) + throw new NullPointerException(); + if (off < 0 || len < 0 || off > input.length - len) + throw new ArrayIndexOutOfBoundsException(); + engine.setInput(input, off, len); + } + + /** + * Sets the compression level. There is no guarantee of the exact + * position of the change, but if you call this when needsInput is + * true the change of compression level will occur somewhere near + * before the end of the so far given input. + * @param lvl the new compression level. + */ + public void setLevel(int lvl) + { + if (lvl == DEFAULT_COMPRESSION) + lvl = 6; + else if (lvl < NO_COMPRESSION || lvl > BEST_COMPRESSION) + throw new IllegalArgumentException(); + + + if (level != lvl) + { + level = lvl; + engine.setLevel(lvl); + } + } + + /** + * Sets the compression strategy. Strategy is one of + * DEFAULT_STRATEGY, HUFFMAN_ONLY and FILTERED. For the exact + * position where the strategy is changed, the same as for + * setLevel() applies. + * @param stgy the new compression strategy. + */ + public void setStrategy(int stgy) + { + if (stgy != DEFAULT_STRATEGY && stgy != FILTERED + && stgy != HUFFMAN_ONLY) + throw new IllegalArgumentException(); + engine.setStrategy(stgy); + } + + /** + * Deflates the current input block to the given array. It returns + * the number of bytes compressed, or 0 if either + * needsInput() or finished() returns true or length is zero. + * @param output the buffer where to write the compressed data. + */ + public int deflate(byte[] output) + { + return deflate(output, 0, output.length, NO_FLUSH); + } + + /** + * Deflates the current input block to the given array. It returns + * the number of bytes compressed, or 0 if either + * needsInput() or finished() returns true or length is zero. + * @param output the buffer where to write the compressed data. + * @param offset the offset into the output array. + * @param length the maximum number of bytes that may be written. + * @exception IllegalStateException if end() was called. + * @exception IndexOutOfBoundsException if offset and/or length + * don't match the array length. + */ + public int deflate(byte[] output, int offset, int length) + { + return deflate(output, offset, length, NO_FLUSH); + } + + /** + * Deflates the current input block to the given array. It returns + * the number of bytes compressed, or 0 if either + * needsInput() or finished() returns true or length is zero. + * @param output the buffer where to write the compressed data. + * @param offset the offset into the output array. + * @param length the maximum number of bytes that may be written. + * @param flush the compression flush mode + * @exception IllegalStateException if end() was called. + * @exception IndexOutOfBoundsException if offset and/or length + * don't match the array length. + */ + public int deflate(byte[] output, int offset, int length, int flush) + { + if (output.length - offset < length || offset < 0 || length < 0) + throw new ArrayIndexOutOfBoundsException(); + + if (flush < NO_FLUSH || flush > FULL_FLUSH) + throw new IllegalArgumentException(); + + int origLength = length; + + if (state == CLOSED_STATE) + throw new IllegalStateException("Deflater closed"); + + if (state < BUSY_STATE) + { + /* output header */ + int header = (DEFLATED + + ((DeflaterConstants.MAX_WBITS - 8) << 4)) << 8; + int level_flags = (level - 1) >> 1; + if (level_flags < 0 || level_flags > 3) + level_flags = 3; + header |= level_flags << 6; + if ((state & IS_SETDICT) != 0) + /* Dictionary was set */ + header |= DeflaterConstants.PRESET_DICT; + header += 31 - (header % 31); + + pending.writeShortMSB(header); + if ((state & IS_SETDICT) != 0) + { + int chksum = engine.getAdler(); + engine.resetAdler(); + pending.writeShortMSB(chksum >> 16); + pending.writeShortMSB(chksum & 0xffff); + } + + state = BUSY_STATE | (state & IS_FINISHING); + } + + int oldFlush = lastFlush; + lastFlush = flush; + + if (engine.needsInput() && flush <= oldFlush && (state & IS_FINISHING) == 0) + { + int count = pending.flush(output, offset, length); + totalOut += count; + return count; + } + + boolean done = state == FINISHED_STATE; + + for (;;) + { + int count = pending.flush(output, offset, length); + offset += count; + totalOut += count; + length -= count; + if (length == 0 || done) + return origLength - length; + + if (!engine.deflate((state & IS_FINISHING) != 0 || flush != NO_FLUSH, + (state & IS_FINISHING) != 0)) + { + done = true; + if (state == FINISHING_STATE) + { + pending.alignToByte(); + /* We have completed the stream */ + if (!noHeader) + { + int adler = engine.getAdler(); + pending.writeShortMSB(adler >> 16); + pending.writeShortMSB(adler & 0xffff); + } + state = FINISHED_STATE; + } + else if (flush != NO_FLUSH) + { + if (level != NO_COMPRESSION) + { + /* We have to supply some lookahead. 8 bit lookahead + * are needed by the zlib inflater, and we must fill + * the next byte, so that all bits are flushed. + */ + int neededbits = 8 + ((-pending.getBitCount()) & 7); + while (neededbits > 0) + { + /* write a static tree block consisting solely of + * an EOF: + */ + pending.writeBits(2, 10); + neededbits -= 10; + } + } + if (flush == FULL_FLUSH) + engine.clearHash(); + } + } + } + } + + /** + * Sets the dictionary which should be used in the deflate process. + * This call is equivalent to setDictionary(dict, 0, + * dict.length). + * @param dict the dictionary. + * @exception IllegalStateException if setInput () or deflate () + * were already called or another dictionary was already set. + */ + public void setDictionary(byte[] dict) + { + setDictionary(dict, 0, dict.length); + } + + /** + * Sets the dictionary which should be used in the deflate process. + * The dictionary should be a byte array containing strings that are + * likely to occur in the data which should be compressed. The + * dictionary is not stored in the compressed output, only a + * checksum. To decompress the output you need to supply the same + * dictionary again. + * @param dict the dictionary. + * @param offset an offset into the dictionary. + * @param length the length of the dictionary. + * @exception IllegalStateException if setInput () or deflate () were + * already called or another dictionary was already set. + */ + public void setDictionary(byte[] dict, int offset, int length) + { + if (state != INIT_STATE) + throw new IllegalStateException(); + + state = SETDICT_STATE; + engine.setDictionary(dict, offset, length); + } +} diff --git a/openjdk/java/util/zip/DeflaterConstants.java b/openjdk/java/util/zip/DeflaterConstants.java new file mode 100644 index 0000000..bfef863 --- /dev/null +++ b/openjdk/java/util/zip/DeflaterConstants.java @@ -0,0 +1,78 @@ +/* java.util.zip.DeflaterConstants + Copyright (C) 2001 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.util.zip; + +interface DeflaterConstants +{ + boolean DEBUGGING = false; + + int STORED_BLOCK = 0; + int STATIC_TREES = 1; + int DYN_TREES = 2; + int PRESET_DICT = 0x20; + + int DEFAULT_MEM_LEVEL = 8; + + int MAX_MATCH = 258; + int MIN_MATCH = 3; + + int MAX_WBITS = 15; + int WSIZE = 1 << MAX_WBITS; + int WMASK = WSIZE - 1; + + int HASH_BITS = DEFAULT_MEM_LEVEL + 7; + int HASH_SIZE = 1 << HASH_BITS; + int HASH_MASK = HASH_SIZE - 1; + int HASH_SHIFT = (HASH_BITS + MIN_MATCH - 1) / MIN_MATCH; + + int MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1; + int MAX_DIST = WSIZE - MIN_LOOKAHEAD; + + int PENDING_BUF_SIZE = 1 << (DEFAULT_MEM_LEVEL + 8); + int MAX_BLOCK_SIZE = Math.min(65535, PENDING_BUF_SIZE-5); + + int DEFLATE_STORED = 0; + int DEFLATE_FAST = 1; + int DEFLATE_SLOW = 2; + + int GOOD_LENGTH[] = { 0,4, 4, 4, 4, 8, 8, 8, 32, 32 }; + int MAX_LAZY[] = { 0,4, 5, 6, 4,16, 16, 32, 128, 258 }; + int NICE_LENGTH[] = { 0,8,16,32,16,32,128,128, 258, 258 }; + int MAX_CHAIN[] = { 0,4, 8,32,16,32,128,256,1024,4096 }; + int COMPR_FUNC[] = { 0,1, 1, 1, 1, 2, 2, 2, 2, 2 }; +} diff --git a/openjdk/java/util/zip/DeflaterEngine.java b/openjdk/java/util/zip/DeflaterEngine.java new file mode 100644 index 0000000..474e491 --- /dev/null +++ b/openjdk/java/util/zip/DeflaterEngine.java @@ -0,0 +1,692 @@ +/* DeflaterEngine.java -- + Copyright (C) 2001, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.util.zip; + +final class DeflaterEngine implements DeflaterConstants +{ + private static final int TOO_FAR = 4096; + + private int ins_h; + + /** + * Hashtable, hashing three characters to an index for window, so + * that window[index]..window[index+2] have this hash code. + * Note that the array should really be unsigned short, so you need + * to and the values with 0xffff. + */ + private short[] head; + + /** + * prev[index & WMASK] points to the previous index that has the + * same hash code as the string starting at index. This way + * entries with the same hash code are in a linked list. + * Note that the array should really be unsigned short, so you need + * to and the values with 0xffff. + */ + private short[] prev; + + private int matchStart, matchLen; + private boolean prevAvailable; + private int blockStart; + + /** + * strstart points to the current character in window. + */ + private int strstart; + + /** + * lookahead is the number of characters starting at strstart in + * window that are valid. + * So window[strstart] until window[strstart+lookahead-1] are valid + * characters. + */ + private int lookahead; + + /** + * This array contains the part of the uncompressed stream that + * is of relevance. The current character is indexed by strstart. + */ + private byte[] window; + + private int strategy, max_chain, max_lazy, niceLength, goodLength; + + /** The current compression function. */ + private int comprFunc; + + /** The input data for compression. */ + private byte[] inputBuf; + + /** The total bytes of input read. */ + private long totalIn; + + /** The offset into inputBuf, where input data starts. */ + private int inputOff; + + /** The end offset of the input data. */ + private int inputEnd; + + private DeflaterPending pending; + private DeflaterHuffman huffman; + + /** The adler checksum */ + private Adler32 adler; + + /* DEFLATE ALGORITHM: + * + * The uncompressed stream is inserted into the window array. When + * the window array is full the first half is thrown away and the + * second half is copied to the beginning. + * + * The head array is a hash table. Three characters build a hash value + * and they the value points to the corresponding index in window of + * the last string with this hash. The prev array implements a + * linked list of matches with the same hash: prev[index & WMASK] points + * to the previous index with the same hash. + * + * + */ + + + DeflaterEngine(DeflaterPending pending) { + this.pending = pending; + huffman = new DeflaterHuffman(pending); + adler = new Adler32(); + + window = new byte[2*WSIZE]; + head = new short[HASH_SIZE]; + prev = new short[WSIZE]; + + /* We start at index 1, to avoid a implementation deficiency, that + * we cannot build a repeat pattern at index 0. + */ + blockStart = strstart = 1; + } + + public void reset() + { + huffman.reset(); + adler.reset(); + clearHash(); + totalIn = 0; + } + + final void clearHash() + { + blockStart = strstart = 1; + lookahead = 0; + prevAvailable = false; + matchLen = MIN_MATCH - 1; + for (int i = 0; i < HASH_SIZE; i++) + head[i] = 0; + for (int i = 0; i < WSIZE; i++) + prev[i] = 0; + } + + public final void resetAdler() + { + adler.reset(); + } + + public final int getAdler() + { + int chksum = (int) adler.getValue(); + return chksum; + } + + public final long getTotalIn() + { + return totalIn; + } + + public final void setStrategy(int strat) + { + strategy = strat; + } + + public void setLevel(int lvl) + { + goodLength = DeflaterConstants.GOOD_LENGTH[lvl]; + max_lazy = DeflaterConstants.MAX_LAZY[lvl]; + niceLength = DeflaterConstants.NICE_LENGTH[lvl]; + max_chain = DeflaterConstants.MAX_CHAIN[lvl]; + + if (DeflaterConstants.COMPR_FUNC[lvl] != comprFunc) + { + if (DeflaterConstants.DEBUGGING) + System.err.println("Change from "+comprFunc +" to " + + DeflaterConstants.COMPR_FUNC[lvl]); + switch (comprFunc) + { + case DEFLATE_STORED: + if (strstart > blockStart) + { + huffman.flushStoredBlock(window, blockStart, + strstart - blockStart, false); + blockStart = strstart; + } + updateHash(); + break; + case DEFLATE_FAST: + if (strstart > blockStart) + { + huffman.flushBlock(window, blockStart, strstart - blockStart, + false); + blockStart = strstart; + } + break; + case DEFLATE_SLOW: + if (prevAvailable) + huffman.tallyLit(window[strstart-1] & 0xff); + if (strstart > blockStart) + { + huffman.flushBlock(window, blockStart, strstart - blockStart, + false); + blockStart = strstart; + } + prevAvailable = false; + matchLen = MIN_MATCH - 1; + break; + } + comprFunc = COMPR_FUNC[lvl]; + } + } + + private void updateHash() { + if (DEBUGGING) + System.err.println("updateHash: "+strstart); + ins_h = (window[strstart] << HASH_SHIFT) ^ window[strstart + 1]; + } + + /** + * Inserts the current string in the head hash and returns the previous + * value for this hash. + */ + private int insertString() { + short match; + int hash = ((ins_h << HASH_SHIFT) ^ window[strstart + (MIN_MATCH -1)]) + & HASH_MASK; + + if (DEBUGGING) + { + if (hash != (((window[strstart] << (2*HASH_SHIFT)) + ^ (window[strstart + 1] << HASH_SHIFT) + ^ (window[strstart + 2])) & HASH_MASK)) + throw new InternalError("hash inconsistent: "+hash+"/" + +window[strstart]+"," + +window[strstart+1]+"," + +window[strstart+2]+","+HASH_SHIFT); + } + + prev[strstart & WMASK] = match = head[hash]; + head[hash] = (short) strstart; + ins_h = hash; + return match & 0xffff; + } + + private void slideWindow() + { + System.arraycopy(window, WSIZE, window, 0, WSIZE); + matchStart -= WSIZE; + strstart -= WSIZE; + blockStart -= WSIZE; + + /* Slide the hash table (could be avoided with 32 bit values + * at the expense of memory usage). + */ + for (int i = 0; i < HASH_SIZE; i++) + { + int m = head[i] & 0xffff; + head[i] = m >= WSIZE ? (short) (m - WSIZE) : 0; + } + + /* Slide the prev table. + */ + for (int i = 0; i < WSIZE; i++) + { + int m = prev[i] & 0xffff; + prev[i] = m >= WSIZE ? (short) (m - WSIZE) : 0; + } + } + + /** + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * OUT assertions: strstart + lookahead <= 2*WSIZE + * lookahead >= MIN_LOOKAHEAD or inputOff == inputEnd + */ + private void fillWindow() + { + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (strstart >= WSIZE + MAX_DIST) + slideWindow(); + + /* If there is not enough lookahead, but still some input left, + * read in the input + */ + while (lookahead < DeflaterConstants.MIN_LOOKAHEAD && inputOff < inputEnd) + { + int more = 2*WSIZE - lookahead - strstart; + + if (more > inputEnd - inputOff) + more = inputEnd - inputOff; + + System.arraycopy(inputBuf, inputOff, + window, strstart + lookahead, more); + adler.update(inputBuf, inputOff, more); + inputOff += more; + totalIn += more; + lookahead += more; + } + + if (lookahead >= MIN_MATCH) + updateHash(); + } + + /** + * Find the best (longest) string in the window matching the + * string starting at strstart. + * + * Preconditions: + * strstart + MAX_MATCH <= window.length. + * + * + * @param curMatch + */ + private boolean findLongestMatch(int curMatch) { + int chainLength = this.max_chain; + int niceLength = this.niceLength; + short[] prev = this.prev; + int scan = this.strstart; + int match; + int best_end = this.strstart + matchLen; + int best_len = Math.max(matchLen, MIN_MATCH - 1); + + int limit = Math.max(strstart - MAX_DIST, 0); + + int strend = scan + MAX_MATCH - 1; + byte scan_end1 = window[best_end - 1]; + byte scan_end = window[best_end]; + + /* Do not waste too much time if we already have a good match: */ + if (best_len >= this.goodLength) + chainLength >>= 2; + + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if (niceLength > lookahead) + niceLength = lookahead; + + if (DeflaterConstants.DEBUGGING + && strstart > 2*WSIZE - MIN_LOOKAHEAD) + throw new InternalError("need lookahead"); + + do { + if (DeflaterConstants.DEBUGGING && curMatch >= strstart) + throw new InternalError("future match"); + if (window[curMatch + best_len] != scan_end + || window[curMatch + best_len - 1] != scan_end1 + || window[curMatch] != window[scan] + || window[curMatch+1] != window[scan + 1]) + continue; + + match = curMatch + 2; + scan += 2; + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + while (window[++scan] == window[++match] + && window[++scan] == window[++match] + && window[++scan] == window[++match] + && window[++scan] == window[++match] + && window[++scan] == window[++match] + && window[++scan] == window[++match] + && window[++scan] == window[++match] + && window[++scan] == window[++match] + && scan < strend) + ; + + if (scan > best_end) { +// if (DeflaterConstants.DEBUGGING && ins_h == 0) +// System.err.println("Found match: "+curMatch+"-"+(scan-strstart)); + matchStart = curMatch; + best_end = scan; + best_len = scan - strstart; + if (best_len >= niceLength) + break; + + scan_end1 = window[best_end-1]; + scan_end = window[best_end]; + } + scan = strstart; + } while ((curMatch = (prev[curMatch & WMASK] & 0xffff)) > limit + && --chainLength != 0); + + matchLen = Math.min(best_len, lookahead); + return matchLen >= MIN_MATCH; + } + + void setDictionary(byte[] buffer, int offset, int length) { + if (DeflaterConstants.DEBUGGING && strstart != 1) + throw new IllegalStateException("strstart not 1"); + adler.update(buffer, offset, length); + if (length < MIN_MATCH) + return; + if (length > MAX_DIST) { + offset += length - MAX_DIST; + length = MAX_DIST; + } + + System.arraycopy(buffer, offset, window, strstart, length); + + updateHash(); + length--; + while (--length > 0) + { + insertString(); + strstart++; + } + strstart += 2; + blockStart = strstart; + } + + private boolean deflateStored(boolean flush, boolean finish) + { + if (!flush && lookahead == 0) + return false; + + strstart += lookahead; + lookahead = 0; + + int storedLen = strstart - blockStart; + + if ((storedLen >= DeflaterConstants.MAX_BLOCK_SIZE) + /* Block is full */ + || (blockStart < WSIZE && storedLen >= MAX_DIST) + /* Block may move out of window */ + || flush) + { + boolean lastBlock = finish; + if (storedLen > DeflaterConstants.MAX_BLOCK_SIZE) + { + storedLen = DeflaterConstants.MAX_BLOCK_SIZE; + lastBlock = false; + } + + if (DeflaterConstants.DEBUGGING) + System.err.println("storedBlock["+storedLen+","+lastBlock+"]"); + + huffman.flushStoredBlock(window, blockStart, storedLen, lastBlock); + blockStart += storedLen; + return !lastBlock; + } + return true; + } + + private boolean deflateFast(boolean flush, boolean finish) + { + if (lookahead < MIN_LOOKAHEAD && !flush) + return false; + + while (lookahead >= MIN_LOOKAHEAD || flush) + { + if (lookahead == 0) + { + /* We are flushing everything */ + huffman.flushBlock(window, blockStart, strstart - blockStart, + finish); + blockStart = strstart; + return false; + } + + if (strstart > 2 * WSIZE - MIN_LOOKAHEAD) + { + /* slide window, as findLongestMatch need this. + * This should only happen when flushing and the window + * is almost full. + */ + slideWindow(); + } + + int hashHead; + if (lookahead >= MIN_MATCH + && (hashHead = insertString()) != 0 + && strategy != Deflater.HUFFMAN_ONLY + && strstart - hashHead <= MAX_DIST + && findLongestMatch(hashHead)) + { + /* longestMatch sets matchStart and matchLen */ + if (DeflaterConstants.DEBUGGING) + { + for (int i = 0 ; i < matchLen; i++) + { + if (window[strstart+i] != window[matchStart + i]) + throw new InternalError(); + } + } + boolean full = huffman.tallyDist(strstart - matchStart, matchLen); + + lookahead -= matchLen; + if (matchLen <= max_lazy && lookahead >= MIN_MATCH) + { + while (--matchLen > 0) + { + strstart++; + insertString(); + } + strstart++; + } + else + { + strstart += matchLen; + if (lookahead >= MIN_MATCH - 1) + updateHash(); + } + matchLen = MIN_MATCH - 1; + if (!full) + continue; + } + else + { + /* No match found */ + huffman.tallyLit(window[strstart] & 0xff); + strstart++; + lookahead--; + } + + if (huffman.isFull()) + { + boolean lastBlock = finish && lookahead == 0; + huffman.flushBlock(window, blockStart, strstart - blockStart, + lastBlock); + blockStart = strstart; + return !lastBlock; + } + } + return true; + } + + private boolean deflateSlow(boolean flush, boolean finish) + { + if (lookahead < MIN_LOOKAHEAD && !flush) + return false; + + while (lookahead >= MIN_LOOKAHEAD || flush) + { + if (lookahead == 0) + { + if (prevAvailable) + huffman.tallyLit(window[strstart-1] & 0xff); + prevAvailable = false; + + /* We are flushing everything */ + if (DeflaterConstants.DEBUGGING && !flush) + throw new InternalError("Not flushing, but no lookahead"); + huffman.flushBlock(window, blockStart, strstart - blockStart, + finish); + blockStart = strstart; + return false; + } + + if (strstart >= 2 * WSIZE - MIN_LOOKAHEAD) + { + /* slide window, as findLongestMatch need this. + * This should only happen when flushing and the window + * is almost full. + */ + slideWindow(); + } + + int prevMatch = matchStart; + int prevLen = matchLen; + if (lookahead >= MIN_MATCH) + { + int hashHead = insertString(); + if (strategy != Deflater.HUFFMAN_ONLY + && hashHead != 0 && strstart - hashHead <= MAX_DIST + && findLongestMatch(hashHead)) + { + /* longestMatch sets matchStart and matchLen */ + + /* Discard match if too small and too far away */ + if (matchLen <= 5 + && (strategy == Deflater.FILTERED + || (matchLen == MIN_MATCH + && strstart - matchStart > TOO_FAR))) { + matchLen = MIN_MATCH - 1; + } + } + } + + /* previous match was better */ + if (prevLen >= MIN_MATCH && matchLen <= prevLen) + { + if (DeflaterConstants.DEBUGGING) + { + for (int i = 0 ; i < matchLen; i++) + { + if (window[strstart-1+i] != window[prevMatch + i]) + throw new InternalError(); + } + } + huffman.tallyDist(strstart - 1 - prevMatch, prevLen); + prevLen -= 2; + do + { + strstart++; + lookahead--; + if (lookahead >= MIN_MATCH) + insertString(); + } + while (--prevLen > 0); + strstart ++; + lookahead--; + prevAvailable = false; + matchLen = MIN_MATCH - 1; + } + else + { + if (prevAvailable) + huffman.tallyLit(window[strstart-1] & 0xff); + prevAvailable = true; + strstart++; + lookahead--; + } + + if (huffman.isFull()) + { + int len = strstart - blockStart; + if (prevAvailable) + len--; + boolean lastBlock = (finish && lookahead == 0 && !prevAvailable); + huffman.flushBlock(window, blockStart, len, lastBlock); + blockStart += len; + return !lastBlock; + } + } + return true; + } + + public boolean deflate(boolean flush, boolean finish) + { + boolean progress; + do + { + fillWindow(); + boolean canFlush = flush && inputOff == inputEnd; + if (DeflaterConstants.DEBUGGING) + System.err.println("window: ["+blockStart+","+strstart+"," + +lookahead+"], "+comprFunc+","+canFlush); + switch (comprFunc) + { + case DEFLATE_STORED: + progress = deflateStored(canFlush, finish); + break; + case DEFLATE_FAST: + progress = deflateFast(canFlush, finish); + break; + case DEFLATE_SLOW: + progress = deflateSlow(canFlush, finish); + break; + default: + throw new InternalError(); + } + } + while (pending.isFlushed() /* repeat while we have no pending output */ + && progress); /* and progress was made */ + + return progress; + } + + void setInput(byte[] buf, int off, int len) + { + // caller has already checked parameters + inputBuf = buf; + inputOff = off; + inputEnd = off + len; + } + + public final boolean needsInput() + { + return inputEnd == inputOff; + } +} diff --git a/openjdk/java/util/zip/DeflaterHuffman.java b/openjdk/java/util/zip/DeflaterHuffman.java new file mode 100644 index 0000000..3d10cdd --- /dev/null +++ b/openjdk/java/util/zip/DeflaterHuffman.java @@ -0,0 +1,776 @@ +/* DeflaterHuffman.java -- + Copyright (C) 2001, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.util.zip; + +/** + * This is the DeflaterHuffman class. + * + * This class is not thread safe. This is inherent in the API, due + * to the split of deflate and setInput. + * + * @author Jochen Hoenicke + * @date Jan 6, 2000 + */ +class DeflaterHuffman +{ + private static final int BUFSIZE = 1 << (DeflaterConstants.DEFAULT_MEM_LEVEL + 6); + private static final int LITERAL_NUM = 286; + private static final int DIST_NUM = 30; + private static final int BITLEN_NUM = 19; + private static final int REP_3_6 = 16; + private static final int REP_3_10 = 17; + private static final int REP_11_138 = 18; + private static final int EOF_SYMBOL = 256; + private static final int[] BL_ORDER = + { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + + private static final String bit4Reverse = + "\000\010\004\014\002\012\006\016\001\011\005\015\003\013\007\017"; + + class Tree { + short[] freqs; + short[] codes; + byte[] length; + int[] bl_counts; + int minNumCodes, numCodes; + int maxLength; + + Tree(int elems, int minCodes, int maxLength) { + this.minNumCodes = minCodes; + this.maxLength = maxLength; + freqs = new short[elems]; + bl_counts = new int[maxLength]; + } + + void reset() { + for (int i = 0; i < freqs.length; i++) + freqs[i] = 0; + codes = null; + length = null; + } + + final void writeSymbol(int code) + { + if (DeflaterConstants.DEBUGGING) + { + freqs[code]--; +// System.err.print("writeSymbol("+freqs.length+","+code+"): "); + } + pending.writeBits(codes[code] & 0xffff, length[code]); + } + + final void checkEmpty() + { + boolean empty = true; + for (int i = 0; i < freqs.length; i++) + if (freqs[i] != 0) + { + System.err.println("freqs["+i+"] == "+freqs[i]); + empty = false; + } + if (!empty) + throw new InternalError(); + System.err.println("checkEmpty suceeded!"); + } + + void setStaticCodes(short[] stCodes, byte[] stLength) + { + codes = stCodes; + length = stLength; + } + + public void buildCodes() { + int[] nextCode = new int[maxLength]; + int code = 0; + codes = new short[freqs.length]; + + if (DeflaterConstants.DEBUGGING) + System.err.println("buildCodes: "+freqs.length); + for (int bits = 0; bits < maxLength; bits++) + { + nextCode[bits] = code; + code += bl_counts[bits] << (15 - bits); + if (DeflaterConstants.DEBUGGING) + System.err.println("bits: "+(bits+1)+" count: "+bl_counts[bits] + +" nextCode: "+Integer.toHexString(code)); + } + if (DeflaterConstants.DEBUGGING && code != 65536) + throw new RuntimeException("Inconsistent bl_counts!"); + + for (int i=0; i < numCodes; i++) + { + int bits = length[i]; + if (bits > 0) + { + if (DeflaterConstants.DEBUGGING) + System.err.println("codes["+i+"] = rev(" + +Integer.toHexString(nextCode[bits-1])+")," + +bits); + codes[i] = bitReverse(nextCode[bits-1]); + nextCode[bits-1] += 1 << (16 - bits); + } + } + } + + private void buildLength(int childs[]) + { + this.length = new byte [freqs.length]; + int numNodes = childs.length / 2; + int numLeafs = (numNodes + 1) / 2; + int overflow = 0; + + for (int i = 0; i < maxLength; i++) + bl_counts[i] = 0; + + /* First calculate optimal bit lengths */ + int lengths[] = new int[numNodes]; + lengths[numNodes-1] = 0; + for (int i = numNodes - 1; i >= 0; i--) + { + if (childs[2*i+1] != -1) + { + int bitLength = lengths[i] + 1; + if (bitLength > maxLength) + { + bitLength = maxLength; + overflow++; + } + lengths[childs[2*i]] = lengths[childs[2*i+1]] = bitLength; + } + else + { + /* A leaf node */ + int bitLength = lengths[i]; + bl_counts[bitLength - 1]++; + this.length[childs[2*i]] = (byte) lengths[i]; + } + } + + if (DeflaterConstants.DEBUGGING) + { + System.err.println("Tree "+freqs.length+" lengths:"); + for (int i=0; i < numLeafs; i++) + System.err.println("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]] + + " len: "+length[childs[2*i]]); + } + + if (overflow == 0) + return; + + int incrBitLen = maxLength - 1; + do + { + /* Find the first bit length which could increase: */ + while (bl_counts[--incrBitLen] == 0) + ; + + /* Move this node one down and remove a corresponding + * amount of overflow nodes. + */ + do + { + bl_counts[incrBitLen]--; + bl_counts[++incrBitLen]++; + overflow -= 1 << (maxLength - 1 - incrBitLen); + } + while (overflow > 0 && incrBitLen < maxLength - 1); + } + while (overflow > 0); + + /* We may have overshot above. Move some nodes from maxLength to + * maxLength-1 in that case. + */ + bl_counts[maxLength-1] += overflow; + bl_counts[maxLength-2] -= overflow; + + /* Now recompute all bit lengths, scanning in increasing + * frequency. It is simpler to reconstruct all lengths instead of + * fixing only the wrong ones. This idea is taken from 'ar' + * written by Haruhiko Okumura. + * + * The nodes were inserted with decreasing frequency into the childs + * array. + */ + int nodePtr = 2 * numLeafs; + for (int bits = maxLength; bits != 0; bits--) + { + int n = bl_counts[bits-1]; + while (n > 0) + { + int childPtr = 2*childs[nodePtr++]; + if (childs[childPtr + 1] == -1) + { + /* We found another leaf */ + length[childs[childPtr]] = (byte) bits; + n--; + } + } + } + if (DeflaterConstants.DEBUGGING) + { + System.err.println("*** After overflow elimination. ***"); + for (int i=0; i < numLeafs; i++) + System.err.println("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]] + + " len: "+length[childs[2*i]]); + } + } + + void buildTree() + { + int numSymbols = freqs.length; + + /* heap is a priority queue, sorted by frequency, least frequent + * nodes first. The heap is a binary tree, with the property, that + * the parent node is smaller than both child nodes. This assures + * that the smallest node is the first parent. + * + * The binary tree is encoded in an array: 0 is root node and + * the nodes 2*n+1, 2*n+2 are the child nodes of node n. + */ + int[] heap = new int[numSymbols]; + int heapLen = 0; + int maxCode = 0; + for (int n = 0; n < numSymbols; n++) + { + int freq = freqs[n]; + if (freq != 0) + { + /* Insert n into heap */ + int pos = heapLen++; + int ppos; + while (pos > 0 && + freqs[heap[ppos = (pos - 1) / 2]] > freq) { + heap[pos] = heap[ppos]; + pos = ppos; + } + heap[pos] = n; + maxCode = n; + } + } + + /* We could encode a single literal with 0 bits but then we + * don't see the literals. Therefore we force at least two + * literals to avoid this case. We don't care about order in + * this case, both literals get a 1 bit code. + */ + while (heapLen < 2) + { + int node = maxCode < 2 ? ++maxCode : 0; + heap[heapLen++] = node; + } + + numCodes = Math.max(maxCode + 1, minNumCodes); + + int numLeafs = heapLen; + int[] childs = new int[4*heapLen - 2]; + int[] values = new int[2*heapLen - 1]; + int numNodes = numLeafs; + for (int i = 0; i < heapLen; i++) + { + int node = heap[i]; + childs[2*i] = node; + childs[2*i+1] = -1; + values[i] = freqs[node] << 8; + heap[i] = i; + } + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + do + { + int first = heap[0]; + int last = heap[--heapLen]; + + /* Propagate the hole to the leafs of the heap */ + int ppos = 0; + int path = 1; + while (path < heapLen) + { + if (path + 1 < heapLen + && values[heap[path]] > values[heap[path+1]]) + path++; + + heap[ppos] = heap[path]; + ppos = path; + path = path * 2 + 1; + } + + /* Now propagate the last element down along path. Normally + * it shouldn't go too deep. + */ + int lastVal = values[last]; + while ((path = ppos) > 0 + && values[heap[ppos = (path - 1)/2]] > lastVal) + heap[path] = heap[ppos]; + heap[path] = last; + + + int second = heap[0]; + + /* Create a new node father of first and second */ + last = numNodes++; + childs[2*last] = first; + childs[2*last+1] = second; + int mindepth = Math.min(values[first] & 0xff, values[second] & 0xff); + values[last] = lastVal = values[first] + values[second] - mindepth + 1; + + /* Again, propagate the hole to the leafs */ + ppos = 0; + path = 1; + while (path < heapLen) + { + if (path + 1 < heapLen + && values[heap[path]] > values[heap[path+1]]) + path++; + + heap[ppos] = heap[path]; + ppos = path; + path = ppos * 2 + 1; + } + + /* Now propagate the new element down along path */ + while ((path = ppos) > 0 + && values[heap[ppos = (path - 1)/2]] > lastVal) + heap[path] = heap[ppos]; + heap[path] = last; + } + while (heapLen > 1); + + if (heap[0] != childs.length / 2 - 1) + throw new RuntimeException("Weird!"); + + buildLength(childs); + } + + int getEncodedLength() + { + int len = 0; + for (int i = 0; i < freqs.length; i++) + len += freqs[i] * length[i]; + return len; + } + + void calcBLFreq(Tree blTree) { + int max_count; /* max repeat count */ + int min_count; /* min repeat count */ + int count; /* repeat count of the current code */ + int curlen = -1; /* length of current code */ + + int i = 0; + while (i < numCodes) + { + count = 1; + int nextlen = length[i]; + if (nextlen == 0) + { + max_count = 138; + min_count = 3; + } + else + { + max_count = 6; + min_count = 3; + if (curlen != nextlen) + { + blTree.freqs[nextlen]++; + count = 0; + } + } + curlen = nextlen; + i++; + + while (i < numCodes && curlen == length[i]) + { + i++; + if (++count >= max_count) + break; + } + + if (count < min_count) + blTree.freqs[curlen] += count; + else if (curlen != 0) + blTree.freqs[REP_3_6]++; + else if (count <= 10) + blTree.freqs[REP_3_10]++; + else + blTree.freqs[REP_11_138]++; + } + } + + void writeTree(Tree blTree) + { + int max_count; /* max repeat count */ + int min_count; /* min repeat count */ + int count; /* repeat count of the current code */ + int curlen = -1; /* length of current code */ + + int i = 0; + while (i < numCodes) + { + count = 1; + int nextlen = length[i]; + if (nextlen == 0) + { + max_count = 138; + min_count = 3; + } + else + { + max_count = 6; + min_count = 3; + if (curlen != nextlen) + { + blTree.writeSymbol(nextlen); + count = 0; + } + } + curlen = nextlen; + i++; + + while (i < numCodes && curlen == length[i]) + { + i++; + if (++count >= max_count) + break; + } + + if (count < min_count) + { + while (count-- > 0) + blTree.writeSymbol(curlen); + } + else if (curlen != 0) + { + blTree.writeSymbol(REP_3_6); + pending.writeBits(count - 3, 2); + } + else if (count <= 10) + { + blTree.writeSymbol(REP_3_10); + pending.writeBits(count - 3, 3); + } + else + { + blTree.writeSymbol(REP_11_138); + pending.writeBits(count - 11, 7); + } + } + } + } + + + + DeflaterPending pending; + private Tree literalTree, distTree, blTree; + + private short d_buf[]; + private byte l_buf[]; + private int last_lit; + private int extra_bits; + + private static short staticLCodes[]; + private static byte staticLLength[]; + private static short staticDCodes[]; + private static byte staticDLength[]; + + /** + * Reverse the bits of a 16 bit value. + */ + static short bitReverse(int value) { + return (short) (bit4Reverse.charAt(value & 0xf) << 12 + | bit4Reverse.charAt((value >> 4) & 0xf) << 8 + | bit4Reverse.charAt((value >> 8) & 0xf) << 4 + | bit4Reverse.charAt(value >> 12)); + } + + static { + /* See RFC 1951 3.2.6 */ + /* Literal codes */ + staticLCodes = new short[LITERAL_NUM]; + staticLLength = new byte[LITERAL_NUM]; + int i = 0; + while (i < 144) { + staticLCodes[i] = bitReverse((0x030 + i) << 8); + staticLLength[i++] = 8; + } + while (i < 256) { + staticLCodes[i] = bitReverse((0x190 - 144 + i) << 7); + staticLLength[i++] = 9; + } + while (i < 280) { + staticLCodes[i] = bitReverse((0x000 - 256 + i) << 9); + staticLLength[i++] = 7; + } + while (i < LITERAL_NUM) { + staticLCodes[i] = bitReverse((0x0c0 - 280 + i) << 8); + staticLLength[i++] = 8; + } + + /* Distant codes */ + staticDCodes = new short[DIST_NUM]; + staticDLength = new byte[DIST_NUM]; + for (i = 0; i < DIST_NUM; i++) { + staticDCodes[i] = bitReverse(i << 11); + staticDLength[i] = 5; + } + } + + public DeflaterHuffman(DeflaterPending pending) + { + this.pending = pending; + + literalTree = new Tree(LITERAL_NUM, 257, 15); + distTree = new Tree(DIST_NUM, 1, 15); + blTree = new Tree(BITLEN_NUM, 4, 7); + + d_buf = new short[BUFSIZE]; + l_buf = new byte [BUFSIZE]; + } + + public final void reset() { + last_lit = 0; + extra_bits = 0; + literalTree.reset(); + distTree.reset(); + blTree.reset(); + } + + private int l_code(int len) { + if (len == 255) + return 285; + + int code = 257; + while (len >= 8) + { + code += 4; + len >>= 1; + } + return code + len; + } + + private int d_code(int distance) { + int code = 0; + while (distance >= 4) + { + code += 2; + distance >>= 1; + } + return code + distance; + } + + public void sendAllTrees(int blTreeCodes) { + blTree.buildCodes(); + literalTree.buildCodes(); + distTree.buildCodes(); + pending.writeBits(literalTree.numCodes - 257, 5); + pending.writeBits(distTree.numCodes - 1, 5); + pending.writeBits(blTreeCodes - 4, 4); + for (int rank = 0; rank < blTreeCodes; rank++) + pending.writeBits(blTree.length[BL_ORDER[rank]], 3); + literalTree.writeTree(blTree); + distTree.writeTree(blTree); + if (DeflaterConstants.DEBUGGING) + blTree.checkEmpty(); + } + + public void compressBlock() { + for (int i = 0; i < last_lit; i++) + { + int litlen = l_buf[i] & 0xff; + int dist = d_buf[i]; + if (dist-- != 0) + { + if (DeflaterConstants.DEBUGGING) + System.err.print("["+(dist+1)+","+(litlen+3)+"]: "); + + int lc = l_code(litlen); + literalTree.writeSymbol(lc); + + int bits = (lc - 261) / 4; + if (bits > 0 && bits <= 5) + pending.writeBits(litlen & ((1 << bits) - 1), bits); + + int dc = d_code(dist); + distTree.writeSymbol(dc); + + bits = dc / 2 - 1; + if (bits > 0) + pending.writeBits(dist & ((1 << bits) - 1), bits); + } + else + { + if (DeflaterConstants.DEBUGGING) + { + if (litlen > 32 && litlen < 127) + System.err.print("("+(char)litlen+"): "); + else + System.err.print("{"+litlen+"}: "); + } + literalTree.writeSymbol(litlen); + } + } + if (DeflaterConstants.DEBUGGING) + System.err.print("EOF: "); + literalTree.writeSymbol(EOF_SYMBOL); + if (DeflaterConstants.DEBUGGING) + { + literalTree.checkEmpty(); + distTree.checkEmpty(); + } + } + + public void flushStoredBlock(byte[] stored, + int stored_offset, int stored_len, + boolean lastBlock) { + if (DeflaterConstants.DEBUGGING) + System.err.println("Flushing stored block "+ stored_len); + pending.writeBits((DeflaterConstants.STORED_BLOCK << 1) + + (lastBlock ? 1 : 0), 3); + pending.alignToByte(); + pending.writeShort(stored_len); + pending.writeShort(~stored_len); + pending.writeBlock(stored, stored_offset, stored_len); + reset(); + } + + public void flushBlock(byte[] stored, int stored_offset, int stored_len, + boolean lastBlock) { + literalTree.freqs[EOF_SYMBOL]++; + + /* Build trees */ + literalTree.buildTree(); + distTree.buildTree(); + + /* Calculate bitlen frequency */ + literalTree.calcBLFreq(blTree); + distTree.calcBLFreq(blTree); + + /* Build bitlen tree */ + blTree.buildTree(); + + int blTreeCodes = 4; + for (int i = 18; i > blTreeCodes; i--) + { + if (blTree.length[BL_ORDER[i]] > 0) + blTreeCodes = i+1; + } + int opt_len = 14 + blTreeCodes * 3 + blTree.getEncodedLength() + + literalTree.getEncodedLength() + distTree.getEncodedLength() + + extra_bits; + + int static_len = extra_bits; + for (int i = 0; i < LITERAL_NUM; i++) + static_len += literalTree.freqs[i] * staticLLength[i]; + for (int i = 0; i < DIST_NUM; i++) + static_len += distTree.freqs[i] * staticDLength[i]; + if (opt_len >= static_len) + { + /* Force static trees */ + opt_len = static_len; + } + + if (stored_offset >= 0 && stored_len+4 < opt_len >> 3) + { + /* Store Block */ + if (DeflaterConstants.DEBUGGING) + System.err.println("Storing, since " + stored_len + " < " + opt_len + + " <= " + static_len); + flushStoredBlock(stored, stored_offset, stored_len, lastBlock); + } + else if (opt_len == static_len) + { + /* Encode with static tree */ + pending.writeBits((DeflaterConstants.STATIC_TREES << 1) + + (lastBlock ? 1 : 0), 3); + literalTree.setStaticCodes(staticLCodes, staticLLength); + distTree.setStaticCodes(staticDCodes, staticDLength); + compressBlock(); + reset(); + } + else + { + /* Encode with dynamic tree */ + pending.writeBits((DeflaterConstants.DYN_TREES << 1) + + (lastBlock ? 1 : 0), 3); + sendAllTrees(blTreeCodes); + compressBlock(); + reset(); + } + } + + public final boolean isFull() + { + return last_lit == BUFSIZE; + } + + public final boolean tallyLit(int lit) + { + if (DeflaterConstants.DEBUGGING) + { + if (lit > 32 && lit < 127) + System.err.println("("+(char)lit+")"); + else + System.err.println("{"+lit+"}"); + } + d_buf[last_lit] = 0; + l_buf[last_lit++] = (byte) lit; + literalTree.freqs[lit]++; + return last_lit == BUFSIZE; + } + + public final boolean tallyDist(int dist, int len) + { + if (DeflaterConstants.DEBUGGING) + System.err.println("["+dist+","+len+"]"); + + d_buf[last_lit] = (short) dist; + l_buf[last_lit++] = (byte) (len - 3); + + int lc = l_code(len-3); + literalTree.freqs[lc]++; + if (lc >= 265 && lc < 285) + extra_bits += (lc - 261) / 4; + + int dc = d_code(dist-1); + distTree.freqs[dc]++; + if (dc >= 4) + extra_bits += dc / 2 - 1; + return last_lit == BUFSIZE; + } +} diff --git a/openjdk/java/util/zip/DeflaterPending.java b/openjdk/java/util/zip/DeflaterPending.java new file mode 100644 index 0000000..f38212c --- /dev/null +++ b/openjdk/java/util/zip/DeflaterPending.java @@ -0,0 +1,54 @@ +/* java.util.zip.DeflaterPending + Copyright (C) 2001 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.util.zip; + +/** + * This class stores the pending output of the Deflater. + * + * @author Jochen Hoenicke + * @date Jan 5, 2000 + */ + +class DeflaterPending extends PendingBuffer +{ + public DeflaterPending() + { + super(DeflaterConstants.PENDING_BUF_SIZE); + } +} + diff --git a/openjdk/java/util/zip/Inflater.java b/openjdk/java/util/zip/Inflater.java new file mode 100644 index 0000000..a5912bd --- /dev/null +++ b/openjdk/java/util/zip/Inflater.java @@ -0,0 +1,727 @@ +/* Inflater.java - Decompress a data stream + Copyright (C) 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.util.zip; + +/* Written using on-line Java Platform 1.2 API Specification + * and JCL book. + * Believed complete and correct. + */ + +/** + * Inflater is used to decompress data that has been compressed according + * to the "deflate" standard described in rfc1950. + * + * The usage is as following. First you have to set some input with + * setInput(), then inflate() it. If inflate doesn't + * inflate any bytes there may be three reasons: + *

    + *
  • needsInput() returns true because the input buffer is empty. + * You have to provide more input with setInput(). + * NOTE: needsInput() also returns true when, the stream is finished. + *
  • + *
  • needsDictionary() returns true, you have to provide a preset + * dictionary with setDictionary().
  • + *
  • finished() returns true, the inflater has finished.
  • + *
+ * Once the first output byte is produced, a dictionary will not be + * needed at a later stage. + * + * @author John Leuner, Jochen Hoenicke + * @author Tom Tromey + * @date May 17, 1999 + * @since JDK 1.1 + */ +public class Inflater +{ + /* Copy lengths for literal codes 257..285 */ + private static final int CPLENS[] = + { + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258 + }; + + /* Extra bits for literal codes 257..285 */ + private static final int CPLEXT[] = + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 + }; + + /* Copy offsets for distance codes 0..29 */ + private static final int CPDIST[] = { + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577 + }; + + /* Extra bits for distance codes */ + private static final int CPDEXT[] = { + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13 + }; + + /* This are the state in which the inflater can be. */ + private static final int DECODE_HEADER = 0; + private static final int DECODE_DICT = 1; + private static final int DECODE_BLOCKS = 2; + private static final int DECODE_STORED_LEN1 = 3; + private static final int DECODE_STORED_LEN2 = 4; + private static final int DECODE_STORED = 5; + private static final int DECODE_DYN_HEADER = 6; + private static final int DECODE_HUFFMAN = 7; + private static final int DECODE_HUFFMAN_LENBITS = 8; + private static final int DECODE_HUFFMAN_DIST = 9; + private static final int DECODE_HUFFMAN_DISTBITS = 10; + private static final int DECODE_CHKSUM = 11; + private static final int FINISHED = 12; + + /** This variable contains the current state. */ + private int mode; + + /** + * The adler checksum of the dictionary or of the decompressed + * stream, as it is written in the header resp. footer of the + * compressed stream.
+ * + * Only valid if mode is DECODE_DICT or DECODE_CHKSUM. + */ + private int readAdler; + /** + * The number of bits needed to complete the current state. This + * is valid, if mode is DECODE_DICT, DECODE_CHKSUM, + * DECODE_HUFFMAN_LENBITS or DECODE_HUFFMAN_DISTBITS. + */ + private int neededBits; + private int repLength, repDist; + private int uncomprLen; + /** + * True, if the last block flag was set in the last block of the + * inflated stream. This means that the stream ends after the + * current block. + */ + private boolean isLastBlock; + + /** + * The total number of inflated bytes. + */ + private long totalOut; + /** + * The total number of bytes set with setInput(). This is not the + * value returned by getTotalIn(), since this also includes the + * unprocessed input. + */ + private long totalIn; + /** + * This variable stores the nowrap flag that was given to the constructor. + * True means, that the inflated stream doesn't contain a header nor the + * checksum in the footer. + */ + private boolean nowrap; + + private StreamManipulator input; + private OutputWindow outputWindow; + private InflaterDynHeader dynHeader; + private InflaterHuffmanTree litlenTree, distTree; + private Adler32 adler; + + /** + * Creates a new inflater. + */ + public Inflater () + { + this (false); + } + + /** + * Creates a new inflater. + * @param nowrap true if no header and checksum field appears in the + * stream. This is used for GZIPed input. For compatibility with + * Sun JDK you should provide one byte of input more than needed in + * this case. + */ + public Inflater (boolean nowrap) + { + this.nowrap = nowrap; + this.adler = new Adler32(); + input = new StreamManipulator(); + outputWindow = new OutputWindow(); + mode = nowrap ? DECODE_BLOCKS : DECODE_HEADER; + } + + /** + * Finalizes this object. + */ + protected void finalize () + { + /* Exists only for compatibility */ + } + + /** + * Frees all objects allocated by the inflater. There's no reason + * to call this, since you can just rely on garbage collection (even + * for the Sun implementation). Exists only for compatibility + * with Sun's JDK, where the compressor allocates native memory. + * If you call any method (even reset) afterwards the behaviour is + * undefined. + */ + public void end () + { + outputWindow = null; + input = null; + dynHeader = null; + litlenTree = null; + distTree = null; + adler = null; + } + + /** + * Returns true, if the inflater has finished. This means, that no + * input is needed and no output can be produced. + */ + public boolean finished() + { + return mode == FINISHED + && (outputWindow == null || outputWindow.getAvailable() == 0); + } + + /** + * Gets the adler checksum. This is either the checksum of all + * uncompressed bytes returned by inflate(), or if needsDictionary() + * returns true (and thus no output was yet produced) this is the + * adler checksum of the expected dictionary. + * @returns the adler checksum. + */ + public int getAdler() + { + return needsDictionary() ? readAdler : (int) adler.getValue(); + } + + /** + * Gets the number of unprocessed input. Useful, if the end of the + * stream is reached and you want to further process the bytes after + * the deflate stream. + * @return the number of bytes of the input which were not processed. + */ + public int getRemaining() + { + return input.getAvailableBytes(); + } + + /** + * Gets the total number of processed compressed input bytes. + * @return the total number of bytes of processed input bytes. + */ + public int getTotalIn() + { + return (int) (totalIn - getRemaining()); + } + + /** + * Gets the total number of processed compressed input bytes. + * @return the total number of bytes of processed input bytes. + * @since 1.5 + */ + public long getBytesRead() + { + return totalIn - getRemaining(); + } + + /** + * Gets the total number of output bytes returned by inflate(). + * @return the total number of output bytes. + */ + public int getTotalOut() + { + return (int) totalOut; + } + + /** + * Gets the total number of output bytes returned by inflate(). + * @return the total number of output bytes. + * @since 1.5 + */ + public long getBytesWritten() + { + return totalOut; + } + + /** + * Inflates the compressed stream to the output buffer. If this + * returns 0, you should check, whether needsDictionary(), + * needsInput() or finished() returns true, to determine why no + * further output is produced. + * @param buf the output buffer. + * @return the number of bytes written to the buffer, 0 if no further + * output can be produced. + * @exception DataFormatException if deflated stream is invalid. + * @exception IllegalArgumentException if buf has length 0. + */ + public int inflate (byte[] buf) throws DataFormatException + { + return inflate (buf, 0, buf.length); + } + + /** + * Inflates the compressed stream to the output buffer. If this + * returns 0, you should check, whether needsDictionary(), + * needsInput() or finished() returns true, to determine why no + * further output is produced. + * @param buf the output buffer. + * @param off the offset into buffer where the output should start. + * @param len the maximum length of the output. + * @return the number of bytes written to the buffer, 0 if no further + * output can be produced. + * @exception DataFormatException if deflated stream is invalid. + * @exception IndexOutOfBoundsException if the off and/or len are wrong. + */ + public int inflate (byte[] buf, int off, int len) throws DataFormatException + { + /* Check for correct buff, off, len triple */ + if (0 > off || off > off + len || off + len > buf.length) + throw new ArrayIndexOutOfBoundsException(); + int count = 0; + for (;;) + { + if (outputWindow.getAvailable() == 0) + { + if (!decode()) + break; + } + else if (len > 0) + { + int more = outputWindow.copyOutput(buf, off, len); + adler.update(buf, off, more); + off += more; + count += more; + totalOut += more; + len -= more; + } + else + break; + } + return count; + } + + /** + * Returns true, if a preset dictionary is needed to inflate the input. + */ + public boolean needsDictionary () + { + return mode == DECODE_DICT && neededBits == 0; + } + + /** + * Returns true, if the input buffer is empty. + * You should then call setInput().
+ * + * NOTE: This method also returns true when the stream is finished. + */ + public boolean needsInput () + { + return input == null || input.needsInput (); + } + + /** + * Resets the inflater so that a new stream can be decompressed. All + * pending input and output will be discarded. + */ + public void reset () + { + mode = nowrap ? DECODE_BLOCKS : DECODE_HEADER; + totalIn = totalOut = 0; + input.reset(); + outputWindow.reset(); + dynHeader = null; + litlenTree = null; + distTree = null; + isLastBlock = false; + adler.reset(); + } + + /** + * Sets the preset dictionary. This should only be called, if + * needsDictionary() returns true and it should set the same + * dictionary, that was used for deflating. The getAdler() + * function returns the checksum of the dictionary needed. + * @param buffer the dictionary. + * @exception IllegalStateException if no dictionary is needed. + * @exception IllegalArgumentException if the dictionary checksum is + * wrong. + */ + public void setDictionary (byte[] buffer) + { + setDictionary(buffer, 0, buffer.length); + } + + /** + * Sets the preset dictionary. This should only be called, if + * needsDictionary() returns true and it should set the same + * dictionary, that was used for deflating. The getAdler() + * function returns the checksum of the dictionary needed. + * @param buffer the dictionary. + * @param off the offset into buffer where the dictionary starts. + * @param len the length of the dictionary. + * @exception IllegalStateException if no dictionary is needed. + * @exception IllegalArgumentException if the dictionary checksum is + * wrong. + * @exception IndexOutOfBoundsException if the off and/or len are wrong. + */ + public void setDictionary (byte[] buffer, int off, int len) + { + if (!needsDictionary()) + throw new IllegalStateException(); + + adler.update(buffer, off, len); + if ((int) adler.getValue() != readAdler) + throw new IllegalArgumentException("Wrong adler checksum"); + adler.reset(); + outputWindow.copyDict(buffer, off, len); + mode = DECODE_BLOCKS; + } + + /** + * Sets the input. This should only be called, if needsInput() + * returns true. + * @param buf the input. + * @exception IllegalStateException if no input is needed. + */ + public void setInput (byte[] buf) + { + setInput (buf, 0, buf.length); + } + + /** + * Sets the input. This should only be called, if needsInput() + * returns true. + * @param buf the input. + * @param off the offset into buffer where the input starts. + * @param len the length of the input. + * @exception IllegalStateException if no input is needed. + * @exception IndexOutOfBoundsException if the off and/or len are wrong. + */ + public void setInput (byte[] buf, int off, int len) + { + input.setInput (buf, off, len); + totalIn += len; + } + + /** + * Decodes the deflate header. + * @return false if more input is needed. + * @exception DataFormatException if header is invalid. + */ + private boolean decodeHeader () throws DataFormatException + { + int header = input.peekBits(16); + if (header < 0) + return false; + input.dropBits(16); + + /* The header is written in "wrong" byte order */ + header = ((header << 8) | (header >> 8)) & 0xffff; + if (header % 31 != 0) + throw new DataFormatException("Header checksum illegal"); + + if ((header & 0x0f00) != (Deflater.DEFLATED << 8)) + throw new DataFormatException("Compression Method unknown"); + + /* Maximum size of the backwards window in bits. + * We currently ignore this, but we could use it to make the + * inflater window more space efficient. On the other hand the + * full window (15 bits) is needed most times, anyway. + int max_wbits = ((header & 0x7000) >> 12) + 8; + */ + + if ((header & 0x0020) == 0) // Dictionary flag? + { + mode = DECODE_BLOCKS; + } + else + { + mode = DECODE_DICT; + neededBits = 32; + } + return true; + } + + /** + * Decodes the dictionary checksum after the deflate header. + * @return false if more input is needed. + */ + private boolean decodeDict () + { + while (neededBits > 0) + { + int dictByte = input.peekBits(8); + if (dictByte < 0) + return false; + input.dropBits(8); + readAdler = (readAdler << 8) | dictByte; + neededBits -= 8; + } + return false; + } + + /** + * Decodes the huffman encoded symbols in the input stream. + * @return false if more input is needed, true if output window is + * full or the current block ends. + * @exception DataFormatException if deflated stream is invalid. + */ + private boolean decodeHuffman () throws DataFormatException + { + int free = outputWindow.getFreeSpace(); + while (free >= 258) + { + int symbol; + switch (mode) + { + case DECODE_HUFFMAN: + /* This is the inner loop so it is optimized a bit */ + while (((symbol = litlenTree.getSymbol(input)) & ~0xff) == 0) + { + outputWindow.write(symbol); + if (--free < 258) + return true; + } + if (symbol < 257) + { + if (symbol < 0) + return false; + else + { + /* symbol == 256: end of block */ + distTree = null; + litlenTree = null; + mode = DECODE_BLOCKS; + return true; + } + } + + try + { + repLength = CPLENS[symbol - 257]; + neededBits = CPLEXT[symbol - 257]; + } + catch (ArrayIndexOutOfBoundsException ex) + { + throw new DataFormatException("Illegal rep length code"); + } + /* fall through */ + case DECODE_HUFFMAN_LENBITS: + if (neededBits > 0) + { + mode = DECODE_HUFFMAN_LENBITS; + int i = input.peekBits(neededBits); + if (i < 0) + return false; + input.dropBits(neededBits); + repLength += i; + } + mode = DECODE_HUFFMAN_DIST; + /* fall through */ + case DECODE_HUFFMAN_DIST: + symbol = distTree.getSymbol(input); + if (symbol < 0) + return false; + try + { + repDist = CPDIST[symbol]; + neededBits = CPDEXT[symbol]; + } + catch (ArrayIndexOutOfBoundsException ex) + { + throw new DataFormatException("Illegal rep dist code"); + } + /* fall through */ + case DECODE_HUFFMAN_DISTBITS: + if (neededBits > 0) + { + mode = DECODE_HUFFMAN_DISTBITS; + int i = input.peekBits(neededBits); + if (i < 0) + return false; + input.dropBits(neededBits); + repDist += i; + } + outputWindow.repeat(repLength, repDist); + free -= repLength; + mode = DECODE_HUFFMAN; + break; + default: + throw new IllegalStateException(); + } + } + return true; + } + + /** + * Decodes the adler checksum after the deflate stream. + * @return false if more input is needed. + * @exception DataFormatException if checksum doesn't match. + */ + private boolean decodeChksum () throws DataFormatException + { + while (neededBits > 0) + { + int chkByte = input.peekBits(8); + if (chkByte < 0) + return false; + input.dropBits(8); + readAdler = (readAdler << 8) | chkByte; + neededBits -= 8; + } + if ((int) adler.getValue() != readAdler) + throw new DataFormatException("Adler chksum doesn't match: " + +Integer.toHexString((int)adler.getValue()) + +" vs. "+Integer.toHexString(readAdler)); + mode = FINISHED; + return false; + } + + /** + * Decodes the deflated stream. + * @return false if more input is needed, or if finished. + * @exception DataFormatException if deflated stream is invalid. + */ + private boolean decode () throws DataFormatException + { + switch (mode) + { + case DECODE_HEADER: + return decodeHeader(); + case DECODE_DICT: + return decodeDict(); + case DECODE_CHKSUM: + return decodeChksum(); + + case DECODE_BLOCKS: + if (isLastBlock) + { + if (nowrap) + { + mode = FINISHED; + return false; + } + else + { + input.skipToByteBoundary(); + neededBits = 32; + mode = DECODE_CHKSUM; + return true; + } + } + + int type = input.peekBits(3); + if (type < 0) + return false; + input.dropBits(3); + + if ((type & 1) != 0) + isLastBlock = true; + switch (type >> 1) + { + case DeflaterConstants.STORED_BLOCK: + input.skipToByteBoundary(); + mode = DECODE_STORED_LEN1; + break; + case DeflaterConstants.STATIC_TREES: + litlenTree = InflaterHuffmanTree.defLitLenTree; + distTree = InflaterHuffmanTree.defDistTree; + mode = DECODE_HUFFMAN; + break; + case DeflaterConstants.DYN_TREES: + dynHeader = new InflaterDynHeader(); + mode = DECODE_DYN_HEADER; + break; + default: + throw new DataFormatException("Unknown block type "+type); + } + return true; + + case DECODE_STORED_LEN1: + { + if ((uncomprLen = input.peekBits(16)) < 0) + return false; + input.dropBits(16); + mode = DECODE_STORED_LEN2; + } + /* fall through */ + case DECODE_STORED_LEN2: + { + int nlen = input.peekBits(16); + if (nlen < 0) + return false; + input.dropBits(16); + if (nlen != (uncomprLen ^ 0xffff)) + throw new DataFormatException("broken uncompressed block"); + mode = DECODE_STORED; + } + /* fall through */ + case DECODE_STORED: + { + int more = outputWindow.copyStored(input, uncomprLen); + uncomprLen -= more; + if (uncomprLen == 0) + { + mode = DECODE_BLOCKS; + return true; + } + return !input.needsInput(); + } + + case DECODE_DYN_HEADER: + if (!dynHeader.decode(input)) + return false; + litlenTree = dynHeader.buildLitLenTree(); + distTree = dynHeader.buildDistTree(); + mode = DECODE_HUFFMAN; + /* fall through */ + case DECODE_HUFFMAN: + case DECODE_HUFFMAN_LENBITS: + case DECODE_HUFFMAN_DIST: + case DECODE_HUFFMAN_DISTBITS: + return decodeHuffman(); + case FINISHED: + return false; + default: + throw new IllegalStateException(); + } + } +} diff --git a/openjdk/java/util/zip/InflaterDynHeader.java b/openjdk/java/util/zip/InflaterDynHeader.java new file mode 100644 index 0000000..ad931e4 --- /dev/null +++ b/openjdk/java/util/zip/InflaterDynHeader.java @@ -0,0 +1,203 @@ +/* java.util.zip.InflaterDynHeader + Copyright (C) 2001 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.util.zip; + +class InflaterDynHeader +{ + private static final int LNUM = 0; + private static final int DNUM = 1; + private static final int BLNUM = 2; + private static final int BLLENS = 3; + private static final int LENS = 4; + private static final int REPS = 5; + + private static final int repMin[] = { 3, 3, 11 }; + private static final int repBits[] = { 2, 3, 7 }; + + + private byte[] blLens; + private byte[] litdistLens; + + private InflaterHuffmanTree blTree; + + private int mode; + private int lnum, dnum, blnum, num; + private int repSymbol; + private byte lastLen; + private int ptr; + + private static final int[] BL_ORDER = + { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + + public InflaterDynHeader() + { + } + + public boolean decode(StreamManipulator input) throws DataFormatException + { + decode_loop: + for (;;) + { + switch (mode) + { + case LNUM: + lnum = input.peekBits(5); + if (lnum < 0) + return false; + lnum += 257; + input.dropBits(5); +// System.err.println("LNUM: "+lnum); + mode = DNUM; + /* fall through */ + case DNUM: + dnum = input.peekBits(5); + if (dnum < 0) + return false; + dnum++; + input.dropBits(5); +// System.err.println("DNUM: "+dnum); + num = lnum+dnum; + litdistLens = new byte[num]; + mode = BLNUM; + /* fall through */ + case BLNUM: + blnum = input.peekBits(4); + if (blnum < 0) + return false; + blnum += 4; + input.dropBits(4); + blLens = new byte[19]; + ptr = 0; +// System.err.println("BLNUM: "+blnum); + mode = BLLENS; + /* fall through */ + case BLLENS: + while (ptr < blnum) + { + int len = input.peekBits(3); + if (len < 0) + return false; + input.dropBits(3); +// System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len); + blLens[BL_ORDER[ptr]] = (byte) len; + ptr++; + } + blTree = new InflaterHuffmanTree(blLens); + blLens = null; + ptr = 0; + mode = LENS; + /* fall through */ + case LENS: + { + int symbol; + while (((symbol = blTree.getSymbol(input)) & ~15) == 0) + { + /* Normal case: symbol in [0..15] */ + +// System.err.println("litdistLens["+ptr+"]: "+symbol); + litdistLens[ptr++] = lastLen = (byte) symbol; + + if (ptr == num) + { + /* Finished */ + return true; + } + } + + /* need more input ? */ + if (symbol < 0) + return false; + + /* otherwise repeat code */ + if (symbol >= 17) + { + /* repeat zero */ +// System.err.println("repeating zero"); + lastLen = 0; + } + else + { + if (ptr == 0) + throw new DataFormatException(); + } + repSymbol = symbol-16; + mode = REPS; + } + /* fall through */ + + case REPS: + { + int bits = repBits[repSymbol]; + int count = input.peekBits(bits); + if (count < 0) + return false; + input.dropBits(bits); + count += repMin[repSymbol]; +// System.err.println("litdistLens repeated: "+count); + + if (ptr + count > num) + throw new DataFormatException(); + while (count-- > 0) + litdistLens[ptr++] = lastLen; + + if (ptr == num) + { + /* Finished */ + return true; + } + } + mode = LENS; + continue decode_loop; + } + } + } + + public InflaterHuffmanTree buildLitLenTree() throws DataFormatException + { + byte[] litlenLens = new byte[lnum]; + System.arraycopy(litdistLens, 0, litlenLens, 0, lnum); + return new InflaterHuffmanTree(litlenLens); + } + + public InflaterHuffmanTree buildDistTree() throws DataFormatException + { + byte[] distLens = new byte[dnum]; + System.arraycopy(litdistLens, lnum, distLens, 0, dnum); + return new InflaterHuffmanTree(distLens); + } +} diff --git a/openjdk/java/util/zip/InflaterHuffmanTree.java b/openjdk/java/util/zip/InflaterHuffmanTree.java new file mode 100644 index 0000000..1a152d2 --- /dev/null +++ b/openjdk/java/util/zip/InflaterHuffmanTree.java @@ -0,0 +1,220 @@ +/* InflaterHuffmanTree.java -- + Copyright (C) 2001, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.util.zip; + +class InflaterHuffmanTree +{ + private static final int MAX_BITLEN = 15; + + private short[] tree; + + static InflaterHuffmanTree defLitLenTree, defDistTree; + + static + { + try + { + byte[] codeLengths = new byte[288]; + int i = 0; + while (i < 144) + codeLengths[i++] = 8; + while (i < 256) + codeLengths[i++] = 9; + while (i < 280) + codeLengths[i++] = 7; + while (i < 288) + codeLengths[i++] = 8; + defLitLenTree = new InflaterHuffmanTree(codeLengths); + + codeLengths = new byte[32]; + i = 0; + while (i < 32) + codeLengths[i++] = 5; + defDistTree = new InflaterHuffmanTree(codeLengths); + } + catch (DataFormatException ex) + { + throw new InternalError + ("InflaterHuffmanTree: static tree length illegal"); + } + } + + /** + * Constructs a Huffman tree from the array of code lengths. + * + * @param codeLengths the array of code lengths + */ + InflaterHuffmanTree(byte[] codeLengths) throws DataFormatException + { + buildTree(codeLengths); + } + + private void buildTree(byte[] codeLengths) throws DataFormatException + { + int[] blCount = new int[MAX_BITLEN+1]; + int[] nextCode = new int[MAX_BITLEN+1]; + for (int i = 0; i < codeLengths.length; i++) + { + int bits = codeLengths[i]; + if (bits > 0) + blCount[bits]++; + } + + int max = 0; + int code = 0; + int treeSize = 512; + for (int bits = 1; bits <= MAX_BITLEN; bits++) + { + nextCode[bits] = code; + if (blCount[bits] > 0) + max = bits; + code += blCount[bits] << (16 - bits); + if (bits >= 10) + { + /* We need an extra table for bit lengths >= 10. */ + int start = nextCode[bits] & 0x1ff80; + int end = code & 0x1ff80; + treeSize += (end - start) >> (16 - bits); + } + } + if (code != 65536 && max > 1) + throw new DataFormatException("incomplete dynamic bit lengths tree"); + + /* Now create and fill the extra tables from longest to shortest + * bit len. This way the sub trees will be aligned. + */ + tree = new short[treeSize]; + int treePtr = 512; + for (int bits = MAX_BITLEN; bits >= 10; bits--) + { + int end = code & 0x1ff80; + code -= blCount[bits] << (16 - bits); + int start = code & 0x1ff80; + for (int i = start; i < end; i += 1 << 7) + { + tree[DeflaterHuffman.bitReverse(i)] + = (short) ((-treePtr << 4) | bits); + treePtr += 1 << (bits-9); + } + } + + for (int i = 0; i < codeLengths.length; i++) + { + int bits = codeLengths[i]; + if (bits == 0) + continue; + code = nextCode[bits]; + int revcode = DeflaterHuffman.bitReverse(code); + if (bits <= 9) + { + do + { + tree[revcode] = (short) ((i << 4) | bits); + revcode += 1 << bits; + } + while (revcode < 512); + } + else + { + int subTree = tree[revcode & 511]; + int treeLen = 1 << (subTree & 15); + subTree = -(subTree >> 4); + do + { + tree[subTree | (revcode >> 9)] = (short) ((i << 4) | bits); + revcode += 1 << bits; + } + while (revcode < treeLen); + } + nextCode[bits] = code + (1 << (16 - bits)); + } + } + + /** + * Reads the next symbol from input. The symbol is encoded using the + * huffman tree. + * @param input the input source. + * @return the next symbol, or -1 if not enough input is available. + */ + int getSymbol(StreamManipulator input) throws DataFormatException + { + int lookahead, symbol; + if ((lookahead = input.peekBits(9)) >= 0) + { + if ((symbol = tree[lookahead]) >= 0) + { + input.dropBits(symbol & 15); + return symbol >> 4; + } + int subtree = -(symbol >> 4); + int bitlen = symbol & 15; + if ((lookahead = input.peekBits(bitlen)) >= 0) + { + symbol = tree[subtree | (lookahead >> 9)]; + input.dropBits(symbol & 15); + return symbol >> 4; + } + else + { + int bits = input.getAvailableBits(); + lookahead = input.peekBits(bits); + symbol = tree[subtree | (lookahead >> 9)]; + if ((symbol & 15) <= bits) + { + input.dropBits(symbol & 15); + return symbol >> 4; + } + else + return -1; + } + } + else + { + int bits = input.getAvailableBits(); + lookahead = input.peekBits(bits); + symbol = tree[lookahead]; + if (symbol >= 0 && (symbol & 15) <= bits) + { + input.dropBits(symbol & 15); + return symbol >> 4; + } + else + return -1; + } + } +} diff --git a/openjdk/java/util/zip/OutputWindow.java b/openjdk/java/util/zip/OutputWindow.java new file mode 100644 index 0000000..f432605 --- /dev/null +++ b/openjdk/java/util/zip/OutputWindow.java @@ -0,0 +1,178 @@ +/* OutputWindow.java -- + Copyright (C) 2001, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.util.zip; + +/** + * Contains the output from the Inflation process. + * + * We need to have a window so that we can refer backwards into the output stream + * to repeat stuff. + * + * @author John Leuner + * @since 1.1 + */ +class OutputWindow +{ + private static final int WINDOW_SIZE = 1 << 15; + private static final int WINDOW_MASK = WINDOW_SIZE - 1; + + private byte[] window = new byte[WINDOW_SIZE]; //The window is 2^15 bytes + private int window_end = 0; + private int window_filled = 0; + + public void write(int abyte) + { + if (window_filled++ == WINDOW_SIZE) + throw new IllegalStateException("Window full"); + window[window_end++] = (byte) abyte; + window_end &= WINDOW_MASK; + } + + private void slowRepeat(int rep_start, int len, int dist) + { + while (len-- > 0) + { + window[window_end++] = window[rep_start++]; + window_end &= WINDOW_MASK; + rep_start &= WINDOW_MASK; + } + } + + public void repeat(int len, int dist) + { + if ((window_filled += len) > WINDOW_SIZE) + throw new IllegalStateException("Window full"); + + int rep_start = (window_end - dist) & WINDOW_MASK; + int border = WINDOW_SIZE - len; + if (rep_start <= border && window_end < border) + { + if (len <= dist) + { + System.arraycopy(window, rep_start, window, window_end, len); + window_end += len; + } + else + { + /* We have to copy manually, since the repeat pattern overlaps. + */ + while (len-- > 0) + window[window_end++] = window[rep_start++]; + } + } + else + slowRepeat(rep_start, len, dist); + } + + public int copyStored(StreamManipulator input, int len) + { + len = Math.min(Math.min(len, WINDOW_SIZE - window_filled), + input.getAvailableBytes()); + int copied; + + int tailLen = WINDOW_SIZE - window_end; + if (len > tailLen) + { + copied = input.copyBytes(window, window_end, tailLen); + if (copied == tailLen) + copied += input.copyBytes(window, 0, len - tailLen); + } + else + copied = input.copyBytes(window, window_end, len); + + window_end = (window_end + copied) & WINDOW_MASK; + window_filled += copied; + return copied; + } + + public void copyDict(byte[] dict, int offset, int len) + { + if (window_filled > 0) + throw new IllegalStateException(); + + if (len > WINDOW_SIZE) + { + offset += len - WINDOW_SIZE; + len = WINDOW_SIZE; + } + System.arraycopy(dict, offset, window, 0, len); + window_end = len & WINDOW_MASK; + } + + public int getFreeSpace() + { + return WINDOW_SIZE - window_filled; + } + + public int getAvailable() + { + return window_filled; + } + + public int copyOutput(byte[] output, int offset, int len) + { + int copy_end = window_end; + if (len > window_filled) + len = window_filled; + else + copy_end = (window_end - window_filled + len) & WINDOW_MASK; + + int copied = len; + int tailLen = len - copy_end; + + if (tailLen > 0) + { + System.arraycopy(window, WINDOW_SIZE - tailLen, + output, offset, tailLen); + offset += tailLen; + len = copy_end; + } + System.arraycopy(window, copy_end - len, output, offset, len); + window_filled -= copied; + if (window_filled < 0) + throw new IllegalStateException(); + return copied; + } + + public void reset() { + window_filled = window_end = 0; + } +} + + + diff --git a/openjdk/java/util/zip/PendingBuffer.java b/openjdk/java/util/zip/PendingBuffer.java new file mode 100644 index 0000000..4c7e216 --- /dev/null +++ b/openjdk/java/util/zip/PendingBuffer.java @@ -0,0 +1,200 @@ +/* java.util.zip.PendingBuffer + Copyright (C) 2001 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.util.zip; + +/** + * This class is general purpose class for writing data to a buffer. + * + * It allows you to write bits as well as bytes + * + * Based on DeflaterPending.java + * + * @author Jochen Hoenicke + * @date Jan 5, 2000 + */ + +class PendingBuffer +{ + protected byte[] buf; + int start; + int end; + + int bits; + int bitCount; + + public PendingBuffer() + { + this( 4096 ); + } + + public PendingBuffer(int bufsize) + { + buf = new byte[bufsize]; + } + + public final void reset() { + start = end = bitCount = 0; + } + + public final void writeByte(int b) + { + if (DeflaterConstants.DEBUGGING && start != 0) + throw new IllegalStateException(); + buf[end++] = (byte) b; + } + + public final void writeShort(int s) + { + if (DeflaterConstants.DEBUGGING && start != 0) + throw new IllegalStateException(); + buf[end++] = (byte) s; + buf[end++] = (byte) (s >> 8); + } + + public final void writeInt(int s) + { + if (DeflaterConstants.DEBUGGING && start != 0) + throw new IllegalStateException(); + buf[end++] = (byte) s; + buf[end++] = (byte) (s >> 8); + buf[end++] = (byte) (s >> 16); + buf[end++] = (byte) (s >> 24); + } + + public final void writeBlock(byte[] block, int offset, int len) + { + if (DeflaterConstants.DEBUGGING && start != 0) + throw new IllegalStateException(); + System.arraycopy(block, offset, buf, end, len); + end += len; + } + + public final int getBitCount() { + return bitCount; + } + + public final void alignToByte() { + if (DeflaterConstants.DEBUGGING && start != 0) + throw new IllegalStateException(); + if (bitCount > 0) + { + buf[end++] = (byte) bits; + if (bitCount > 8) + buf[end++] = (byte) (bits >>> 8); + } + bits = 0; + bitCount = 0; + } + + public final void writeBits(int b, int count) + { + if (DeflaterConstants.DEBUGGING && start != 0) + throw new IllegalStateException(); + if (DeflaterConstants.DEBUGGING) + System.err.println("writeBits("+Integer.toHexString(b)+","+count+")"); + bits |= b << bitCount; + bitCount += count; + if (bitCount >= 16) { + buf[end++] = (byte) bits; + buf[end++] = (byte) (bits >>> 8); + bits >>>= 16; + bitCount -= 16; + } + } + + public final void writeShortMSB(int s) { + if (DeflaterConstants.DEBUGGING && start != 0) + throw new IllegalStateException(); + buf[end++] = (byte) (s >> 8); + buf[end++] = (byte) s; + } + + public final boolean isFlushed() { + return end == 0; + } + + /** + * Flushes the pending buffer into the given output array. If the + * output array is to small, only a partial flush is done. + * + * @param output the output array; + * @param offset the offset into output array; + * @param length the maximum number of bytes to store; + * @exception IndexOutOfBoundsException if offset or length are + * invalid. + */ + public final int flush(byte[] output, int offset, int length) { + if (bitCount >= 8) + { + buf[end++] = (byte) bits; + bits >>>= 8; + bitCount -= 8; + } + if (length > end - start) + { + length = end - start; + System.arraycopy(buf, start, output, offset, length); + start = 0; + end = 0; + } + else + { + System.arraycopy(buf, start, output, offset, length); + start += length; + } + return length; + } + + /** + * Flushes the pending buffer and returns that data in a new array + * + * @return the output stream + */ + + public final byte[] toByteArray() + { + byte[] ret = new byte[ end - start ]; + System.arraycopy(buf, start, ret, 0, ret.length); + start = 0; + end = 0; + return ret; + } + + +} + diff --git a/openjdk/java/util/zip/StreamManipulator.java b/openjdk/java/util/zip/StreamManipulator.java new file mode 100644 index 0000000..16585de --- /dev/null +++ b/openjdk/java/util/zip/StreamManipulator.java @@ -0,0 +1,216 @@ +/* java.util.zip.StreamManipulator + Copyright (C) 2001 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.util.zip; + +/** + * This class allows us to retrieve a specified amount of bits from + * the input buffer, as well as copy big byte blocks. + * + * It uses an int buffer to store up to 31 bits for direct + * manipulation. This guarantees that we can get at least 16 bits, + * but we only need at most 15, so this is all safe. + * + * There are some optimizations in this class, for example, you must + * never peek more then 8 bits more than needed, and you must first + * peek bits before you may drop them. This is not a general purpose + * class but optimized for the behaviour of the Inflater. + * + * @author John Leuner, Jochen Hoenicke + */ + +class StreamManipulator +{ + private byte[] window; + private int window_start = 0; + private int window_end = 0; + + private int buffer = 0; + private int bits_in_buffer = 0; + + /** + * Get the next n bits but don't increase input pointer. n must be + * less or equal 16 and if you if this call succeeds, you must drop + * at least n-8 bits in the next call. + * + * @return the value of the bits, or -1 if not enough bits available. */ + public final int peekBits(int n) + { + if (bits_in_buffer < n) + { + if (window_start == window_end) + return -1; + buffer |= (window[window_start++] & 0xff + | (window[window_start++] & 0xff) << 8) << bits_in_buffer; + bits_in_buffer += 16; + } + return buffer & ((1 << n) - 1); + } + + /* Drops the next n bits from the input. You should have called peekBits + * with a bigger or equal n before, to make sure that enough bits are in + * the bit buffer. + */ + public final void dropBits(int n) + { + buffer >>>= n; + bits_in_buffer -= n; + } + + /** + * Gets the next n bits and increases input pointer. This is equivalent + * to peekBits followed by dropBits, except for correct error handling. + * @return the value of the bits, or -1 if not enough bits available. + */ + public final int getBits(int n) + { + int bits = peekBits(n); + if (bits >= 0) + dropBits(n); + return bits; + } + /** + * Gets the number of bits available in the bit buffer. This must be + * only called when a previous peekBits() returned -1. + * @return the number of bits available. + */ + public final int getAvailableBits() + { + return bits_in_buffer; + } + + /** + * Gets the number of bytes available. + * @return the number of bytes available. + */ + public final int getAvailableBytes() + { + return window_end - window_start + (bits_in_buffer >> 3); + } + + /** + * Skips to the next byte boundary. + */ + public void skipToByteBoundary() + { + buffer >>= (bits_in_buffer & 7); + bits_in_buffer &= ~7; + } + + public final boolean needsInput() { + return window_start == window_end; + } + + + /* Copies length bytes from input buffer to output buffer starting + * at output[offset]. You have to make sure, that the buffer is + * byte aligned. If not enough bytes are available, copies fewer + * bytes. + * @param length the length to copy, 0 is allowed. + * @return the number of bytes copied, 0 if no byte is available. + */ + public int copyBytes(byte[] output, int offset, int length) + { + if (length < 0) + throw new IllegalArgumentException("length negative"); + if ((bits_in_buffer & 7) != 0) + /* bits_in_buffer may only be 0 or 8 */ + throw new IllegalStateException("Bit buffer is not aligned!"); + + int count = 0; + while (bits_in_buffer > 0 && length > 0) + { + output[offset++] = (byte) buffer; + buffer >>>= 8; + bits_in_buffer -= 8; + length--; + count++; + } + if (length == 0) + return count; + + int avail = window_end - window_start; + if (length > avail) + length = avail; + System.arraycopy(window, window_start, output, offset, length); + window_start += length; + + if (((window_start - window_end) & 1) != 0) + { + /* We always want an even number of bytes in input, see peekBits */ + buffer = (window[window_start++] & 0xff); + bits_in_buffer = 8; + } + return count + length; + } + + public StreamManipulator() + { + } + + public void reset() + { + window_start = window_end = buffer = bits_in_buffer = 0; + } + + public void setInput(byte[] buf, int off, int len) + { + if (window_start < window_end) + throw new IllegalStateException + ("Old input was not completely processed"); + + int end = off + len; + + /* We want to throw an ArrayIndexOutOfBoundsException early. The + * check is very tricky: it also handles integer wrap around. + */ + if (0 > off || off > end || end > buf.length) + throw new ArrayIndexOutOfBoundsException(); + + if ((len & 1) != 0) + { + /* We always want an even number of bytes in input, see peekBits */ + buffer |= (buf[off++] & 0xff) << bits_in_buffer; + bits_in_buffer += 8; + } + + window = buf; + window_start = off; + window_end = end; + } +} + diff --git a/openjdk/java/util/zip/ZipEntry.java b/openjdk/java/util/zip/ZipEntry.java new file mode 100644 index 0000000..5676097 --- /dev/null +++ b/openjdk/java/util/zip/ZipEntry.java @@ -0,0 +1,577 @@ +/* + * Copyright (c) 1995, 2013, 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 java.util.zip; + +import static java.util.zip.ZipUtils.*; +import java.nio.file.attribute.FileTime; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import static java.util.zip.ZipConstants64.*; + +/** + * This class is used to represent a ZIP file entry. + * + * @author David Connelly + */ +public +class ZipEntry implements ZipConstants, Cloneable { + + String name; // entry name + long time = -1; // last modification time + FileTime mtime; // last modification time, from extra field data + FileTime atime; // last access time, from extra field data + FileTime ctime; // creation time, from extra field data + long crc = -1; // crc-32 of entry data + long size = -1; // uncompressed size of entry data + long csize = -1; // compressed size of entry data + int method = -1; // compression method + int flag = 0; // general purpose flag + byte[] extra; // optional extra field data for entry + String comment; // optional comment string for entry + long offset; // [IKVM] used by ZipFile + volatile long dostime = -1; // [IKVM] undecoded DOS time (to avoid bootstrap issue, because java.util.Date needs to read from VFS zip file) + + /** + * Compression method for uncompressed entries. + */ + public static final int STORED = 0; + + /** + * Compression method for compressed (deflated) entries. + */ + public static final int DEFLATED = 8; + + /** + * Creates a new zip entry with the specified name. + * + * @param name + * The entry name + * + * @throws NullPointerException if the entry name is null + * @throws IllegalArgumentException if the entry name is longer than + * 0xFFFF bytes + */ + public ZipEntry(String name) { + Objects.requireNonNull(name, "name"); + if (name.length() > 0xFFFF) { + throw new IllegalArgumentException("entry name too long"); + } + this.name = name; + } + + /** + * Creates a new zip entry with fields taken from the specified + * zip entry. + * + * @param e + * A zip Entry object + * + * @throws NullPointerException if the entry object is null + */ + public ZipEntry(ZipEntry e) { + Objects.requireNonNull(e, "entry"); + name = e.name; + time = e.time; + mtime = e.mtime; + atime = e.atime; + ctime = e.ctime; + crc = e.crc; + size = e.size; + csize = e.csize; + method = e.method; + flag = e.flag; + extra = e.extra; + comment = e.comment; + dostime = e.dostime; + } + + /** + * Creates a new un-initialized zip entry + */ + ZipEntry() {} + + /** + * Returns the name of the entry. + * @return the name of the entry + */ + public String getName() { + return name; + } + + /** + * Sets the last modification time of the entry. + * + *

If the entry is output to a ZIP file or ZIP file formatted + * output stream the last modification time set by this method will + * be stored into the {@code date and time fields} of the zip file + * entry and encoded in standard {@code MS-DOS date and time format}. + * The {@link java.util.TimeZone#getDefault() default TimeZone} is + * used to convert the epoch time to the MS-DOS data and time. + * + * @param time + * The last modification time of the entry in milliseconds + * since the epoch + * + * @see #getTime() + * @see #getLastModifiedTime() + */ + public void setTime(long time) { + this.time = time; + this.dostime = -1; + this.mtime = null; + } + + /** + * Returns the last modification time of the entry. + * + *

If the entry is read from a ZIP file or ZIP file formatted + * input stream, this is the last modification time from the {@code + * date and time fields} of the zip file entry. The + * {@link java.util.TimeZone#getDefault() default TimeZone} is used + * to convert the standard MS-DOS formatted date and time to the + * epoch time. + * + * @return The last modification time of the entry in milliseconds + * since the epoch, or -1 if not specified + * + * @see #setTime(long) + * @see #setLastModifiedTime(FileTime) + */ + public long getTime() { + return getTimeImpl(); + } + + // [IKVM] we store the DOS time to avoid a bootstrap issue + private long getTimeImpl() { + long tmp = dostime; + if (tmp != -1) { + return ZipUtils.dosToJavaTime(tmp); + } + return time; + } + + /** + * Sets the last modification time of the entry. + * + *

When output to a ZIP file or ZIP file formatted output stream + * the last modification time set by this method will be stored into + * zip file entry's {@code date and time fields} in {@code standard + * MS-DOS date and time format}), and the extended timestamp fields + * in {@code optional extra data} in UTC time. + * + * @param time + * The last modification time of the entry + * @return This zip entry + * + * @throws NullPointerException if the {@code time} is null + * + * @see #getLastModifiedTime() + * @since 1.8 + */ + public ZipEntry setLastModifiedTime(FileTime time) { + Objects.requireNonNull(name, "time"); + this.mtime = time; + this.time = time.to(TimeUnit.MILLISECONDS); + this.dostime = -1; + return this; + } + + /** + * Returns the last modification time of the entry. + * + *

If the entry is read from a ZIP file or ZIP file formatted + * input stream, this is the last modification time from the zip + * file entry's {@code optional extra data} if the extended timestamp + * fields are present. Otherwise the last modification time is read + * from the entry's {@code date and time fields}, the {@link + * java.util.TimeZone#getDefault() default TimeZone} is used to convert + * the standard MS-DOS formatted date and time to the epoch time. + * + * @return The last modification time of the entry, null if not specified + * + * @see #setLastModifiedTime(FileTime) + * @since 1.8 + */ + public FileTime getLastModifiedTime() { + if (mtime != null) + return mtime; + long time = getTimeImpl(); + if (time == -1) + return null; + return FileTime.from(time, TimeUnit.MILLISECONDS); + } + + /** + * Sets the last access time of the entry. + * + *

If set, the last access time will be stored into the extended + * timestamp fields of entry's {@code optional extra data}, when output + * to a ZIP file or ZIP file formatted stream. + * + * @param time + * The last access time of the entry + * @return This zip entry + * + * @throws NullPointerException if the {@code time} is null + * + * @see #getLastAccessTime() + * @since 1.8 + */ + public ZipEntry setLastAccessTime(FileTime time) { + Objects.requireNonNull(name, "time"); + this.atime = time; + return this; + } + + /** + * Returns the last access time of the entry. + * + *

The last access time is from the extended timestamp fields + * of entry's {@code optional extra data} when read from a ZIP file + * or ZIP file formatted stream. + * + * @return The last access time of the entry, null if not specified + + * @see #setLastAccessTime(FileTime) + * @since 1.8 + */ + public FileTime getLastAccessTime() { + return atime; + } + + /** + * Sets the creation time of the entry. + * + *

If set, the creation time will be stored into the extended + * timestamp fields of entry's {@code optional extra data}, when + * output to a ZIP file or ZIP file formatted stream. + * + * @param time + * The creation time of the entry + * @return This zip entry + * + * @throws NullPointerException if the {@code time} is null + * + * @see #getCreationTime() + * @since 1.8 + */ + public ZipEntry setCreationTime(FileTime time) { + Objects.requireNonNull(name, "time"); + this.ctime = time; + return this; + } + + /** + * Returns the creation time of the entry. + * + *

The creation time is from the extended timestamp fields of + * entry's {@code optional extra data} when read from a ZIP file + * or ZIP file formatted stream. + * + * @return the creation time of the entry, null if not specified + * @see #setCreationTime(FileTime) + * @since 1.8 + */ + public FileTime getCreationTime() { + return ctime; + } + + /** + * Sets the uncompressed size of the entry data. + * + * @param size the uncompressed size in bytes + * + * @throws IllegalArgumentException if the specified size is less + * than 0, is greater than 0xFFFFFFFF when + * ZIP64 format is not supported, + * or is less than 0 when ZIP64 is supported + * @see #getSize() + */ + public void setSize(long size) { + if (size < 0) { + throw new IllegalArgumentException("invalid entry size"); + } + this.size = size; + } + + /** + * Returns the uncompressed size of the entry data. + * + * @return the uncompressed size of the entry data, or -1 if not known + * @see #setSize(long) + */ + public long getSize() { + return size; + } + + /** + * Returns the size of the compressed entry data. + * + *

In the case of a stored entry, the compressed size will be the same + * as the uncompressed size of the entry. + * + * @return the size of the compressed entry data, or -1 if not known + * @see #setCompressedSize(long) + */ + public long getCompressedSize() { + return csize; + } + + /** + * Sets the size of the compressed entry data. + * + * @param csize the compressed size to set to + * + * @see #getCompressedSize() + */ + public void setCompressedSize(long csize) { + this.csize = csize; + } + + /** + * Sets the CRC-32 checksum of the uncompressed entry data. + * + * @param crc the CRC-32 value + * + * @throws IllegalArgumentException if the specified CRC-32 value is + * less than 0 or greater than 0xFFFFFFFF + * @see #getCrc() + */ + public void setCrc(long crc) { + if (crc < 0 || crc > 0xFFFFFFFFL) { + throw new IllegalArgumentException("invalid entry crc-32"); + } + this.crc = crc; + } + + /** + * Returns the CRC-32 checksum of the uncompressed entry data. + * + * @return the CRC-32 checksum of the uncompressed entry data, or -1 if + * not known + * + * @see #setCrc(long) + */ + public long getCrc() { + return crc; + } + + /** + * Sets the compression method for the entry. + * + * @param method the compression method, either STORED or DEFLATED + * + * @throws IllegalArgumentException if the specified compression + * method is invalid + * @see #getMethod() + */ + public void setMethod(int method) { + if (method != STORED && method != DEFLATED) { + throw new IllegalArgumentException("invalid compression method"); + } + this.method = method; + } + + /** + * Returns the compression method of the entry. + * + * @return the compression method of the entry, or -1 if not specified + * @see #setMethod(int) + */ + public int getMethod() { + return method; + } + + /** + * Sets the optional extra field data for the entry. + * + *

Invoking this method may change this entry's last modification + * time, last access time and creation time, if the {@code extra} field + * data includes the extensible timestamp fields, such as {@code NTFS tag + * 0x0001} or {@code Info-ZIP Extended Timestamp}, as specified in + * Info-ZIP + * Application Note 970311. + * + * @param extra + * The extra field data bytes + * + * @throws IllegalArgumentException if the length of the specified + * extra field data is greater than 0xFFFF bytes + * + * @see #getExtra() + */ + public void setExtra(byte[] extra) { + setExtra0(extra, false); + } + + /** + * Sets the optional extra field data for the entry. + * + * @param extra + * the extra field data bytes + * @param doZIP64 + * if true, set size and csize from ZIP64 fields if present + */ + void setExtra0(byte[] extra, boolean doZIP64) { + if (extra != null) { + if (extra.length > 0xFFFF) { + throw new IllegalArgumentException("invalid extra field length"); + } + // extra fields are in "HeaderID(2)DataSize(2)Data... format + int off = 0; + int len = extra.length; + while (off + 4 < len) { + int tag = get16(extra, off); + int sz = get16(extra, off + 2); + off += 4; + if (off + sz > len) // invalid data + break; + switch (tag) { + case EXTID_ZIP64: + if (doZIP64) { + // LOC extra zip64 entry MUST include BOTH original + // and compressed file size fields. + // If invalid zip64 extra fields, simply skip. Even + // it's rare, it's possible the entry size happens to + // be the magic value and it "accidently" has some + // bytes in extra match the id. + if (sz >= 16) { + size = get64(extra, off); + csize = get64(extra, off + 8); + } + } + break; + case EXTID_NTFS: + int pos = off + 4; // reserved 4 bytes + if (get16(extra, pos) != 0x0001 || get16(extra, pos + 2) != 24) + break; + mtime = winTimeToFileTime(get64(extra, pos + 4)); + atime = winTimeToFileTime(get64(extra, pos + 12)); + ctime = winTimeToFileTime(get64(extra, pos + 20)); + break; + case EXTID_EXTT: + int flag = Byte.toUnsignedInt(extra[off]); + int sz0 = 1; + // The CEN-header extra field contains the modification + // time only, or no timestamp at all. 'sz' is used to + // flag its presence or absence. But if mtime is present + // in LOC it must be present in CEN as well. + if ((flag & 0x1) != 0 && (sz0 + 4) <= sz) { + mtime = unixTimeToFileTime(get32(extra, off + sz0)); + sz0 += 4; + } + if ((flag & 0x2) != 0 && (sz0 + 4) <= sz) { + atime = unixTimeToFileTime(get32(extra, off + sz0)); + sz0 += 4; + } + if ((flag & 0x4) != 0 && (sz0 + 4) <= sz) { + ctime = unixTimeToFileTime(get32(extra, off + sz0)); + sz0 += 4; + } + break; + default: + } + off += sz; + } + } + this.extra = extra; + } + + /** + * Returns the extra field data for the entry. + * + * @return the extra field data for the entry, or null if none + * + * @see #setExtra(byte[]) + */ + public byte[] getExtra() { + return extra; + } + + /** + * Sets the optional comment string for the entry. + * + *

ZIP entry comments have maximum length of 0xffff. If the length of the + * specified comment string is greater than 0xFFFF bytes after encoding, only + * the first 0xFFFF bytes are output to the ZIP file entry. + * + * @param comment the comment string + * + * @see #getComment() + */ + public void setComment(String comment) { + this.comment = comment; + } + + /** + * Returns the comment string for the entry. + * + * @return the comment string for the entry, or null if none + * + * @see #setComment(String) + */ + public String getComment() { + return comment; + } + + /** + * Returns true if this is a directory entry. A directory entry is + * defined to be one whose name ends with a '/'. + * @return true if this is a directory entry + */ + public boolean isDirectory() { + return name.endsWith("/"); + } + + /** + * Returns a string representation of the ZIP entry. + */ + public String toString() { + return getName(); + } + + /** + * Returns the hash code value for this entry. + */ + public int hashCode() { + return name.hashCode(); + } + + /** + * Returns a copy of this entry. + */ + public Object clone() { + try { + ZipEntry e = (ZipEntry)super.clone(); + e.extra = (extra == null) ? null : extra.clone(); + return e; + } catch (CloneNotSupportedException e) { + // This should never happen, since we are Cloneable + throw new InternalError(e); + } + } +} diff --git a/openjdk/java/util/zip/ZipFile.java b/openjdk/java/util/zip/ZipFile.java new file mode 100644 index 0000000..6aa5c44 --- /dev/null +++ b/openjdk/java/util/zip/ZipFile.java @@ -0,0 +1,908 @@ +/* ZipFile.java -- + Copyright (C) 2001, 2014 + Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.util.zip; + +import java.io.Closeable; +import java.io.EOFException; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.RandomAccessFile; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.stream.Stream; +import static java.util.zip.ZipConstants64.*; + +/** + * This class represents a Zip archive. You can ask for the contained + * entries, or get an input stream for a file entry. The entry is + * automatically decompressed. + * + * This class is thread safe: You can open input streams for arbitrary + * entries in different threads. + * + * @author Jochen Hoenicke + * @author Artur Biesiadowski + */ +public class ZipFile implements ZipConstants, Closeable +{ + + /** + * Mode flag to open a zip file for reading. + */ + public static final int OPEN_READ = 0x1; + + /** + * Mode flag to delete a zip file after reading. + */ + public static final int OPEN_DELETE = 0x4; + + /** + * This field isn't defined in the JDK's ZipConstants, but should be. + */ + static final int ENDNRD = 4; + + // Name of this zip file. + private final String name; + + // Encoding to use for name and comment strings + private final Charset charset; + + // File from which zip entries are read. + private final RandomAccessFile raf; + + // The entries of this zip file when initialized and not yet closed. + private LinkedHashMap entries; + + private boolean closed = false; + final boolean hasLocHeader; + + /** + * Opens a Zip file with the given name for reading. + * @exception IOException if a i/o error occured. + * @exception ZipException if the file doesn't contain a valid zip + * archive. + */ + public ZipFile(String name) throws ZipException, IOException + { + this(new File(name), OPEN_READ); + } + + /** + * Opens a Zip file reading the given File. + * @exception IOException if a i/o error occured. + * @exception ZipException if the file doesn't contain a valid zip + * archive. + */ + public ZipFile(File file) throws ZipException, IOException + { + this(file, OPEN_READ); + } + + /** + * Opens a Zip file reading the given File. + * @exception IOException if a i/o error occured. + * @exception ZipException if the file doesn't contain a valid zip + * archive. + */ + public ZipFile(File file, Charset charset) throws IOException + { + this(file, OPEN_READ, charset); + } + + /** + * Opens a Zip file reading the given File. + * @exception IOException if a i/o error occured. + * @exception ZipException if the file doesn't contain a valid zip + * archive. + */ + public ZipFile(String name, Charset charset) throws IOException + { + this(new File(name), OPEN_READ, charset); + } + + /** + * Opens a Zip file reading the given File in the given mode. + * + * If the OPEN_DELETE mode is specified, the zip file will be deleted at + * some time moment after it is opened. It will be deleted before the zip + * file is closed or the Virtual Machine exits. + * + * The contents of the zip file will be accessible until it is closed. + * + * @since JDK1.3 + * @param mode Must be one of OPEN_READ or OPEN_READ | OPEN_DELETE + * + * @exception IOException if a i/o error occured. + * @exception ZipException if the file doesn't contain a valid zip + * archive. + */ + public ZipFile(File file, int mode) throws IOException + { + this(file, mode, StandardCharsets.UTF_8); + } + + /** + * Opens a Zip file reading the given File in the given mode. + * + * If the OPEN_DELETE mode is specified, the zip file will be deleted at + * some time moment after it is opened. It will be deleted before the zip + * file is closed or the Virtual Machine exits. + * + * The contents of the zip file will be accessible until it is closed. + * + * @since JDK1.7 + * @param mode Must be one of OPEN_READ or OPEN_READ | OPEN_DELETE + * @param charset Character encoding to use for names and comments + * + * @exception IOException if a i/o error occured. + * @exception ZipException if the file doesn't contain a valid zip + * archive. + */ + public ZipFile(File file, int mode, Charset charset) throws IOException + { + if (mode != OPEN_READ && mode != (OPEN_READ | OPEN_DELETE)) + throw new IllegalArgumentException("Illegal mode: 0x" + Integer.toHexString(mode)); + if (charset == null) + throw new NullPointerException("charset is null"); + if ((mode & OPEN_DELETE) != 0) + file.deleteOnExit(); + this.raf = new RandomAccessFile(file, "r"); + this.name = file.getPath(); + this.charset = charset; + this.hasLocHeader = raf.length() >= 4 && raf.readInt() == (int)((LOCSIG << 24) | ((LOCSIG & 0xFF00) << 8) | ((LOCSIG & 0xFF0000) >> 8) | (LOCSIG >> 24)); + + boolean valid = false; + + try + { + readEntries(); + ClassStubZipEntry.expandIkvmClasses(this, entries); + valid = true; + } + catch (EOFException _) + { + throw new ZipException("invalid CEN header (bad header size)"); + } + finally + { + if (!valid) + { + try + { + raf.close(); + } + catch (IOException _) + { + } + } + } + } + + /** + * Checks if file is closed and throws an exception. + */ + private void checkClosed() + { + if (closed) + throw new IllegalStateException("zip file closed"); + } + + /** + * Read the central directory of a zip file and fill the entries + * array. This is called exactly once when first needed. It is called + * while holding the lock on raf. + * + * @exception IOException if a i/o error occured. + * @exception ZipException if the central directory is malformed + */ + private void readEntries() throws IOException + { + PartialInputStream inp = new PartialInputStream(4096); + long pos = inp.seekEndOfCentralDirectory(); + inp.skip(6); + int count = inp.readLeUnsignedShort(); + long centralSize = inp.readLeUnsignedInt(); + long centralOffset = inp.readLeUnsignedInt(); + + if (centralSize == ZIP64_MAGICVAL + || centralOffset == ZIP64_MAGICVAL + || count == ZIP64_MAGICCOUNT) + { + inp.seek(pos - ZIP64_LOCHDR); + if (inp.readLeInt() == ZIP64_LOCSIG) + { + inp.skip(4); + long zip64end = inp.readLeLong(); + inp.seek(zip64end); + if (inp.readLeInt() == ZIP64_ENDSIG) + { + inp.skip(ZIP64_ENDSIZ - 4); + centralSize = inp.readLeLong(); + centralOffset = inp.readLeLong(); + pos = zip64end; + } + } + } + + if (centralSize > pos) + throw new ZipException("invalid END header (bad central directory size)"); + + if (centralOffset > pos - centralSize) + throw new ZipException("invalid END header (bad central directory offset)"); + + entries = new LinkedHashMap (count+count/2); + inp.seek(pos - centralSize); + + while (inp.position() <= pos - CENHDR) + { + if (inp.readLeInt() != CENSIG) + throw new ZipException("invalid CEN header (bad signature)"); + + inp.skip(4); + int flags = inp.readLeUnsignedShort(); + if ((flags & 1) != 0) + throw new ZipException("invalid CEN header (encrypted entry)"); + int method = inp.readLeUnsignedShort(); + if (method != ZipEntry.STORED && method != ZipEntry.DEFLATED) + throw new ZipException("invalid CEN header (bad compression method)"); + ZipEntry entry = new ZipEntry(); + entry.flag = flags; + entry.method = method; + entry.dostime = inp.readLeUnsignedInt(); + entry.crc = inp.readLeUnsignedInt(); + entry.csize = inp.readLeUnsignedInt(); + entry.size = inp.readLeUnsignedInt(); + int nameLen = inp.readLeUnsignedShort(); + int extraLen = inp.readLeUnsignedShort(); + int commentLen = inp.readLeUnsignedShort(); + inp.skip(8); + entry.offset = inp.readLeUnsignedInt(); + entry.name = inp.readString(nameLen, (flags & EFS) != 0); + + if (extraLen > 0) + { + byte[] extra = new byte[extraLen]; + inp.readFully(extra); + entry.setExtra0(extra, false); + readZip64ExtraField(entry, extra); + } + if (commentLen > 0) + { + entry.comment = inp.readString(commentLen, (flags & EFS) != 0); + } + entries.put(entry.name, entry); + } + + if (inp.position() != pos) + throw new ZipException("invalid CEN header (bad header size)"); + } + + private static void readZip64ExtraField(ZipEntry entry, byte[] extra) + { + if (entry.csize == ZIP64_MAGICVAL || entry.size == ZIP64_MAGICVAL + || entry.offset == ZIP64_MAGICVAL) + { + for (int pos = 0; pos < extra.length - 4; ) + { + int headerID = decodeLeUnsignedShort(extra, pos); + int dataSize = decodeLeUnsignedShort(extra, pos + 2); + pos += 4; + if (headerID == ZIP64_EXTID) + { + if (entry.size == ZIP64_MAGICVAL) + { + entry.size = decodeLeLong(extra, pos); + pos += 8; + } + if (entry.csize == ZIP64_MAGICVAL) + { + entry.csize = decodeLeLong(extra, pos); + pos += 8; + } + if (entry.offset == ZIP64_MAGICVAL) + { + entry.offset = decodeLeLong(extra, pos); + pos += 8; + } + break; + } + pos += dataSize; + } + } + } + + private static int decodeLeUnsignedShort(byte[] b, int off) + { + return (b[off] & 0xFF) | ((b[off + 1] & 0xFF) << 8); + } + + private static long decodeLeLong(byte[] b, int off) + { + return 0 + | ((b[off + 0] & 0xFFL) << 0) + | ((b[off + 1] & 0xFFL) << 8) + | ((b[off + 2] & 0xFFL) << 16) + | ((b[off + 3] & 0xFFL) << 24) + | ((b[off + 4] & 0xFFL) << 32) + | ((b[off + 5] & 0xFFL) << 40) + | ((b[off + 6] & 0xFFL) << 48) + | ((b[off + 7] & 0xFFL) << 56); + } + + /** + * Closes the ZipFile. This also closes all input streams given by + * this class. After this is called, no further method should be + * called. + * + * @exception IOException if a i/o error occured. + */ + public void close() throws IOException + { + RandomAccessFile raf = this.raf; + if (raf == null) + return; + + synchronized (raf) + { + closed = true; + entries = null; + raf.close(); + } + } + + /** + * Calls the close() method when this ZipFile has not yet + * been explicitly closed. + */ + protected void finalize() throws IOException + { + if (!closed && raf != null) close(); + } + + /** + * Returns an enumeration of all Zip entries in this Zip file. + * + * @exception IllegalStateException when the ZipFile has already been closed + */ + public Enumeration entries() + { + checkClosed(); + return new ZipEntryEnumeration(entries.values().iterator()); + } + + public Stream stream() + { + checkClosed(); + return entries.values().stream(); + } + + /** + * Searches for a zip entry in this archive with the given name. + * + * @param name the name. May contain directory components separated by + * slashes ('/'). + * @return the zip entry, or null if no entry with that name exists. + * + * @exception IllegalStateException when the ZipFile has already been closed + */ + public ZipEntry getEntry(String name) + { + checkClosed(); + ZipEntry entry = entries.get(name); + // If we didn't find it, maybe it's a directory. + if (entry == null && !name.endsWith("/")) + entry = entries.get(name + '/'); + return entry != null ? (ZipEntry)entry.clone() : null; + } + + /** + * Creates an input stream reading the given zip entry as + * uncompressed data. Normally zip entry should be an entry + * returned by getEntry() or entries(). + * + * This implementation returns null if the requested entry does not + * exist. This decision is not obviously correct, however, it does + * appear to mirror Sun's implementation, and it is consistant with + * their javadoc. On the other hand, the old JCL book, 2nd Edition, + * claims that this should return a "non-null ZIP entry". We have + * chosen for now ignore the old book, as modern versions of Ant (an + * important application) depend on this behaviour. See discussion + * in this thread: + * http://gcc.gnu.org/ml/java-patches/2004-q2/msg00602.html + * + * @param entry the entry to create an InputStream for. + * @return the input stream, or null if the requested entry does not exist. + * + * @exception IllegalStateException when the ZipFile has already been closed + * @exception IOException if a i/o error occured. + * @exception ZipException if the Zip archive is malformed. + */ + public InputStream getInputStream(ZipEntry entry) throws IOException + { + checkClosed(); + + final ZipEntry zipEntry = entries.get(entry.getName()); + if (zipEntry == null) + return null; + + if (zipEntry instanceof ClassStubZipEntry) + return ((ClassStubZipEntry)zipEntry).getInputStream(); + + PartialInputStream inp = new PartialInputStream(1024) { + void lazyInitialSeek() throws IOException { + seek(zipEntry.offset); + + if (readLeInt() != LOCSIG) + throw new ZipException("invalid LOC header (bad signature)"); + + skip(22); + + int nameLen = readLeUnsignedShort(); + int extraLen = readLeUnsignedShort(); + skip(nameLen + extraLen); + + setLength(zipEntry.getCompressedSize()); + } + }; + + switch (zipEntry.getMethod()) + { + case ZipOutputStream.STORED: + return inp; + case ZipOutputStream.DEFLATED: + inp.addDummyByte(); + final Inflater inf = new Inflater(true); + final int sz = (int) zipEntry.getSize(); + return new InflaterInputStream(inp, inf) + { + private boolean closed; + public void close() throws IOException + { + closed = true; + super.close(); + } + public int available() throws IOException + { + if (closed) + return 0; + if (sz == -1) + return super.available(); + if (super.available() != 0) + return sz - inf.getTotalOut(); + return 0; + } + }; + default: + throw new ZipException("invalid compression method"); + } + } + + /** + * Returns the (path) name of this zip file. + */ + public String getName() + { + return name; + } + + /** + * Returns the number of entries in this zip file. + * + * @exception IllegalStateException when the ZipFile has already been closed + */ + public int size() + { + checkClosed(); + return entries.size(); + } + + /** + * Returns the zip file comment. + * + * @exception IllegalStateException when the ZipFile has already been closed + */ + public synchronized String getComment() + { + checkClosed(); + try + { + PartialInputStream inp = new PartialInputStream(4096); + long pos = inp.seekEndOfCentralDirectory(); + inp.skip(16); + int commentLength = inp.readLeUnsignedShort(); + if (commentLength == 0) + return null; + return inp.readString(commentLength, false); + } + catch (IOException _) + { + return null; + } + } + + private static class ZipEntryEnumeration implements Enumeration + { + private final Iterator elements; + + public ZipEntryEnumeration(Iterator elements) + { + this.elements = elements; + } + + public boolean hasMoreElements() + { + return elements.hasNext(); + } + + public ZipEntry nextElement() + { + /* We return a clone, just to be safe that the user doesn't + * change the entry. + */ + return (ZipEntry) (elements.next().clone()); + } + } + + private class PartialInputStream extends InputStream + { + private final byte[] buffer; + private long bufferOffset; + private int pos; + private long end; + private boolean lazy; + // We may need to supply an extra dummy byte to our reader. + // See Inflater. We use a count here to simplify the logic + // elsewhere in this class. Note that we ignore the dummy + // byte in methods where we know it is not needed. + private int dummyByteCount; + + public PartialInputStream(int bufferSize) + throws IOException + { + buffer = new byte[bufferSize]; + bufferOffset = -buffer.length; + pos = buffer.length; + end = raf.length(); + lazy = true; + } + + // Seek to the "end of central directory record" and position + // the stream after the ENDSIG and return the file offset + // where the record starts. + long seekEndOfCentralDirectory() throws IOException + { + /* Search for the End Of Central Directory. When a zip comment is + * present the directory may start earlier. + * Note that a comment has a maximum length of 64K, so that is the + * maximum we search backwards. + */ + long length = raf.length(); + if (length == 0) + throw new ZipException("zip file is empty"); + long pos = length - ENDHDR; + long top = Math.max(0, pos - 65536); + do + { + if (pos < top) + throw new ZipException("error in opening zip file"); + seek(pos--); + } + while (readLeInt() != ENDSIG); + return pos + 1; + } + + void lazyInitialSeek() throws IOException + { + } + + void setLength(long length) + { + end = bufferOffset + pos + length; + } + + private void fillBuffer() throws IOException + { + if (closed) + throw new ZipException("ZipFile closed"); + + synchronized (raf) + { + long len = end - bufferOffset; + if (len == 0 && dummyByteCount > 0) + { + buffer[0] = 0; + dummyByteCount = 0; + } + else + { + raf.seek(bufferOffset); + raf.readFully(buffer, 0, (int) Math.min(buffer.length, len)); + } + } + } + + public int available() throws IOException + { + if (lazy) + { + lazy = false; + lazyInitialSeek(); + } + long amount = end - (bufferOffset + pos); + if (amount > Integer.MAX_VALUE) + return Integer.MAX_VALUE; + return (int) amount; + } + + public int read() throws IOException + { + if (bufferOffset + pos >= end + dummyByteCount) + return -1; + if (pos == buffer.length) + { + if (lazy) + { + lazy = false; + lazyInitialSeek(); + return read(); + } + bufferOffset += buffer.length; + pos = 0; + fillBuffer(); + } + + return buffer[pos++] & 0xFF; + } + + public int read(byte[] b, int off, int len) throws IOException + { + if (lazy) + { + lazy = false; + lazyInitialSeek(); + } + + if (len > end + dummyByteCount - (bufferOffset + pos)) + { + len = (int) (end + dummyByteCount - (bufferOffset + pos)); + if (len == 0) + return -1; + } + + int totalBytesRead = Math.min(buffer.length - pos, len); + System.arraycopy(buffer, pos, b, off, totalBytesRead); + pos += totalBytesRead; + off += totalBytesRead; + len -= totalBytesRead; + + while (len > 0) + { + bufferOffset += buffer.length; + pos = 0; + fillBuffer(); + int remain = Math.min(buffer.length, len); + System.arraycopy(buffer, pos, b, off, remain); + pos += remain; + off += remain; + len -= remain; + totalBytesRead += remain; + } + + return totalBytesRead; + } + + public long skip(long amount) throws IOException + { + if (lazy) + { + lazy = false; + lazyInitialSeek(); + } + if (amount < 0) + return 0; + if (amount > end - (bufferOffset + pos)) + amount = end - (bufferOffset + pos); + seek(bufferOffset + pos + amount); + return amount; + } + + void seek(long newpos) throws IOException + { + long offset = newpos - bufferOffset; + if (offset >= 0 && offset <= buffer.length) + { + pos = (int) offset; + } + else + { + bufferOffset = newpos; + pos = 0; + fillBuffer(); + } + } + + long position() + { + return bufferOffset + pos; + } + + void readFully(byte[] buf) throws IOException + { + if (read(buf, 0, buf.length) != buf.length) + throw new EOFException(); + } + + void readFully(byte[] buf, int off, int len) throws IOException + { + if (read(buf, off, len) != len) + throw new EOFException(); + } + + int readLeUnsignedShort() throws IOException + { + int result; + if(pos + 1 < buffer.length) + { + result = ((buffer[pos + 0] & 0xff) | (buffer[pos + 1] & 0xff) << 8); + pos += 2; + } + else + { + int b0 = read(); + int b1 = read(); + if (b1 == -1) + throw new EOFException(); + result = (b0 & 0xff) | (b1 & 0xff) << 8; + } + return result; + } + + int readLeInt() throws IOException + { + int result; + if(pos + 3 < buffer.length) + { + result = (((buffer[pos + 0] & 0xff) | (buffer[pos + 1] & 0xff) << 8) + | ((buffer[pos + 2] & 0xff) + | (buffer[pos + 3] & 0xff) << 8) << 16); + pos += 4; + } + else + { + int b0 = read(); + int b1 = read(); + int b2 = read(); + int b3 = read(); + if (b3 == -1) + throw new EOFException(); + result = (((b0 & 0xff) | (b1 & 0xff) << 8) | ((b2 & 0xff) + | (b3 & 0xff) << 8) << 16); + } + return result; + } + + final long readLeUnsignedInt() throws IOException + { + return readLeInt() & 0xffffffffL; + } + + final long readLeLong() throws IOException + { + return readLeUnsignedInt() | (readLeUnsignedInt() << 32); + } + + /** + * Decode chars from byte buffer using charset encoding. This + * operation is performance-critical since a jar file contains a + * large number of strings for the name of each file in the + * archive. This routine therefore avoids using the expensive + * utf8Decoder when decoding is straightforward. + * + * @param buffer the buffer that contains the encoded character + * data + * @param pos the index in buffer of the first byte of the encoded + * data + * @param length the length of the encoded data in number of + * bytes. + * + * @return a String that contains the decoded characters. + */ + private String decodeChars(byte[] buffer, int pos, int length, boolean utf8) + throws IOException + { + if (!utf8 && charset != StandardCharsets.UTF_8) + return new String(buffer, pos, length, charset); + + for (int i = pos; i < pos + length; i++) + { + if (buffer[i] <= 0) + return new String(buffer, pos, length, "UTF-8"); + } + return new String(buffer, 0, pos, length); + } + + String readString(int length, boolean utf8) throws IOException + { + if (length > end - (bufferOffset + pos)) + throw new EOFException(); + + String result = null; + try + { + if (buffer.length - pos >= length) + { + result = decodeChars(buffer, pos, length, utf8); + pos += length; + } + else + { + byte[] b = new byte[length]; + readFully(b); + result = decodeChars(b, 0, length, utf8); + } + } + catch (UnsupportedEncodingException uee) + { + throw new AssertionError(uee); + } + return result; + } + + public void addDummyByte() + { + dummyByteCount = 1; + } + } + + static { + sun.misc.SharedSecrets.setJavaUtilZipFileAccess( + new sun.misc.JavaUtilZipFileAccess() { + public boolean startsWithLocHeader(ZipFile zip) { + return zip.hasLocHeader; + } + } + ); + } +} diff --git a/openjdk/map.xml b/openjdk/map.xml new file mode 100644 index 0000000..2ce91ed --- /dev/null +++ b/openjdk/map.xml @@ -0,0 +1,3153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ()Ljava/lang/Class<+Ljava/lang/Object;>; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + Ljava/lang/Object;Ljava/io/Serializable;Ljava/lang/Comparable<Ljava/lang/String;>;Ljava/lang/CharSequence; + + + java.lang.String$CaseInsensitiveComparator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (Ljava/lang/CharSequence;Ljava/lang/Iterable<+Ljava/lang/CharSequence;>;)Ljava/lang/String; + + + + + + Ljava/util/Comparator<Ljava/lang/String;>; + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Never + + + + + + + + + + + + + + + + + Never + + + + + + + + + + + Never + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Demand + true + + + + + Never + + + + + + + + + + + + + + + Demand + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <T:Ljava/lang/Object;>Ljava/lang/Object; + + + + (TT;)I + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Never + + + + + + + + + + + + + + + + + + + + + + + + + + + + Never + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NoInlining + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NoInlining + + + invoke + ([Ljava.lang.Object;)Ljava.lang.Object; + + + Public,Final,Native,VarArgs + + + + + + + + + + + NoInlining + + + invokeExact + ([Ljava.lang.Object;)Ljava.lang.Object; + + + Public,Final,Native,VarArgs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/openjdk/openjdk.build b/openjdk/openjdk.build new file mode 100644 index 0000000..3d7e189 --- /dev/null +++ b/openjdk/openjdk.build @@ -0,0 +1,465 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openjdk/resources/META-INF/services/java.sql.Driver b/openjdk/resources/META-INF/services/java.sql.Driver new file mode 100644 index 0000000..73d549a --- /dev/null +++ b/openjdk/resources/META-INF/services/java.sql.Driver @@ -0,0 +1 @@ +sun.jdbc.odbc.JdbcOdbcDriver diff --git a/openjdk/resources/META-INF/services/sun.java2d.pipe.RenderingEngine b/openjdk/resources/META-INF/services/sun.java2d.pipe.RenderingEngine new file mode 100644 index 0000000..607ff59 --- /dev/null +++ b/openjdk/resources/META-INF/services/sun.java2d.pipe.RenderingEngine @@ -0,0 +1,2 @@ +# Pisces Rendering Engine module +sun.java2d.pisces.PiscesRenderingEngine diff --git a/openjdk/resources/nashorn/version.properties b/openjdk/resources/nashorn/version.properties new file mode 100644 index 0000000..3d3ca44 --- /dev/null +++ b/openjdk/resources/nashorn/version.properties @@ -0,0 +1,2 @@ +full=1.8.0_45-b14 +release=1.8.0 diff --git a/openjdk/resources/nashorn/version.properties.in b/openjdk/resources/nashorn/version.properties.in new file mode 100644 index 0000000..b573f3c --- /dev/null +++ b/openjdk/resources/nashorn/version.properties.in @@ -0,0 +1,2 @@ +full=@FULL_VERSION@ +release=@IMPLEMENTATION_VERSION@ diff --git a/openjdk/response.txt b/openjdk/response.txt new file mode 100644 index 0000000..9bc69a0 --- /dev/null +++ b/openjdk/response.txt @@ -0,0 +1,1622 @@ +# +# Copyright (C) 2002-2015 Jeroen Frijters +# +# This software is provided 'as-is', without any express or implied +# warranty. In no event will the authors be held liable for any damages +# arising from the use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software +# in a product, an acknowledgment in the product documentation would be +# appreciated but is not required. +# 2. Altered source versions must be plainly marked as such, and must not be +# misrepresented as being the original software. +# 3. This notice may not be removed or altered from any source distribution. +# +# Jeroen Frijters +# jeroen@frijters.net +# + +-assemblyattributes:commonAttributes.class +{ + -out:IKVM.OpenJDK.Core.dll + -baseaddress:0x56000000 + -remap:map.xml + -assemblyattributes:coreAttributes.class + -exclude:exclude.lst + -resource:META-INF/MANIFEST.MF=MANIFEST.MF + -resource:java/lang/uniName.dat=@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/classes/java/lang/uniName.dat + -resource:sun/net/idn/uidna.spp=@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/classes/sun/net/idn/uidna.spp + -resource:sun/reflect/misc/Trampoline.class=@OPENJDK@/jdk/src/share/classes/sun/reflect/misc/Trampoline.class + -resource:java/lang/invoke/MethodHandleImpl$BindCaller$T.class=@OPENJDK@/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl$BindCaller$T.class + -recurse:resources.zip/sun/util/resources/* + ikvm/internal/*.class + java/io/*.class + java/lang/*.class + java/lang/invoke/*.class + java/lang/ref/*.class + java/lang/reflect/*.class + java/net/*.class + java/nio/*.class + java/security/*.class + java/util/concurrent/locks/*.class + gnu/java/util/*.class + sun/misc/*.class + sun/net/sdp/*.class + sun/net/www/protocol/file/*.class + sun/net/www/protocol/ikvmres/*.class + sun/net/www/protocol/jar/*.class + sun/nio/ch/*.class + sun/nio/cs/*.class + sun/nio/fs/*.class + sun/reflect/*.class + sun/reflect/annotation/*.class + ../classpath/gnu/java/net/protocol/ikvmres/*.class + ../classpath/ikvm/extensions/*.class + ../classpath/ikvm/internal/*.class + ../classpath/ikvm/io/*.class + ../classpath/ikvm/lang/*.class + ../classpath/ikvm/runtime/*.class + ../classpath/java/util/concurrent/atomic/*.class + ../classpath/sun/misc/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/lang/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/channels/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/java/nio/charset/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/locale/provider/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/logging/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/ServerSideException.class + @OPENJDK@/jdk/src/share/classes/com/sun/nio/file/*.class + @OPENJDK@/jdk/src/share/classes/java/beans/ChangeListenerMap.class + @OPENJDK@/jdk/src/share/classes/java/beans/IndexedPropertyChangeEvent.class + @OPENJDK@/jdk/src/share/classes/java/beans/PropertyChangeEvent.class + @OPENJDK@/jdk/src/share/classes/java/beans/PropertyChangeListener.class + @OPENJDK@/jdk/src/share/classes/java/beans/PropertyChangeListenerProxy.class + @OPENJDK@/jdk/src/share/classes/java/beans/PropertyChangeSupport*.class + @OPENJDK@/jdk/src/share/classes/java/io/*.class + @OPENJDK@/jdk/src/share/classes/java/lang/*.class + @OPENJDK@/jdk/src/share/classes/java/lang/annotation/*.class + @OPENJDK@/jdk/src/share/classes/java/lang/invoke/*.class + @OPENJDK@/jdk/src/share/classes/java/lang/ref/*.class + @OPENJDK@/jdk/src/share/classes/java/lang/reflect/*.class + @OPENJDK@/jdk/src/share/classes/java/math/*.class + @OPENJDK@/jdk/src/share/classes/java/net/*.class + @OPENJDK@/jdk/src/share/classes/java/nio/*.class + @OPENJDK@/jdk/src/share/classes/java/nio/channels/*.class + @OPENJDK@/jdk/src/share/classes/java/nio/channels/spi/*.class + @OPENJDK@/jdk/src/share/classes/java/nio/charset/*.class + @OPENJDK@/jdk/src/share/classes/java/nio/charset/spi/*.class + @OPENJDK@/jdk/src/share/classes/java/nio/file/*.class + @OPENJDK@/jdk/src/share/classes/java/nio/file/attribute/*.class + @OPENJDK@/jdk/src/share/classes/java/nio/file/spi/*.class + @OPENJDK@/jdk/src/share/classes/java/security/*.class + @OPENJDK@/jdk/src/share/classes/java/security/cert/*.class + @OPENJDK@/jdk/src/share/classes/java/sql/Timestamp.class + @OPENJDK@/jdk/src/share/classes/java/time/*.class + @OPENJDK@/jdk/src/share/classes/java/time/chrono/*.class + @OPENJDK@/jdk/src/share/classes/java/time/format/*.class + @OPENJDK@/jdk/src/share/classes/java/time/temporal/*.class + @OPENJDK@/jdk/src/share/classes/java/time/zone/*.class + @OPENJDK@/jdk/src/share/classes/java/util/*.class + @OPENJDK@/jdk/src/share/classes/java/util/concurrent/*.class + @OPENJDK@/jdk/src/share/classes/java/util/concurrent/atomic/*.class + @OPENJDK@/jdk/src/share/classes/java/util/concurrent/locks/*.class + @OPENJDK@/jdk/src/share/classes/java/util/function/*.class + @OPENJDK@/jdk/src/share/classes/java/util/jar/Attributes*.class + @OPENJDK@/jdk/src/share/classes/java/util/jar/Manifest*.class + @OPENJDK@/jdk/src/share/classes/java/util/regex/*.class + @OPENJDK@/jdk/src/share/classes/java/util/stream/*.class + @OPENJDK@/jdk/src/share/classes/javax/net/*.class + @OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/*.class + @OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/*.class + @OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/signature/*.class + @OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/*.class + @OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/*.class + @OPENJDK@/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/*.class + @OPENJDK@/jdk/src/share/classes/jdk/internal/org/xml/sax/*.class + @OPENJDK@/jdk/src/share/classes/jdk/internal/org/xml/sax/helpers/*.class + @OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/*.class + @OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/impl/*.class + @OPENJDK@/jdk/src/share/classes/jdk/net/*.class + @OPENJDK@/jdk/src/share/classes/sun/invoke/*.class + @OPENJDK@/jdk/src/share/classes/sun/invoke/anon/*.class + @OPENJDK@/jdk/src/share/classes/sun/invoke/empty/*.class + @OPENJDK@/jdk/src/share/classes/sun/invoke/util/*.class + @OPENJDK@/jdk/src/share/classes/sun/misc/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/ftp/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/ftp/impl/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/idn/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/smtp/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/spi/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/spi/nameservice/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/util/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/www/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/www/content/text/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/www/http/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/ftp/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/logging/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/spnego/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/jar/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/mailto/*.class + @OPENJDK@/jdk/src/share/classes/sun/nio/*.class + @OPENJDK@/jdk/src/share/classes/sun/nio/ch/*.class + @OPENJDK@/jdk/src/share/classes/sun/nio/cs/*.class + @OPENJDK@/jdk/src/share/classes/sun/nio/fs/*.class + @OPENJDK@/jdk/src/share/classes/sun/reflect/*.class + @OPENJDK@/jdk/src/share/classes/sun/reflect/annotation/*.class + @OPENJDK@/jdk/src/share/classes/sun/reflect/generics/factory/*.class + @OPENJDK@/jdk/src/share/classes/sun/reflect/generics/parser/*.class + @OPENJDK@/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/*.class + @OPENJDK@/jdk/src/share/classes/sun/reflect/generics/repository/*.class + @OPENJDK@/jdk/src/share/classes/sun/reflect/generics/scope/*.class + @OPENJDK@/jdk/src/share/classes/sun/reflect/generics/tree/*.class + @OPENJDK@/jdk/src/share/classes/sun/reflect/generics/visitor/*.class + @OPENJDK@/jdk/src/share/classes/sun/reflect/misc/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/action/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/jca/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/provider/ByteArrayAccess.class + @OPENJDK@/jdk/src/share/classes/sun/security/provider/DigestBase.class + @OPENJDK@/jdk/src/share/classes/sun/security/provider/SHA.class + @OPENJDK@/jdk/src/share/classes/sun/security/provider/Sun.class + @OPENJDK@/jdk/src/share/classes/sun/security/provider/SunEntries$1.class + @OPENJDK@/jdk/src/share/classes/sun/security/provider/SunEntries.class + @OPENJDK@/jdk/src/share/classes/sun/security/util/Debug.class + @OPENJDK@/jdk/src/share/classes/sun/security/util/PermissionFactory.class + @OPENJDK@/jdk/src/share/classes/sun/security/util/PropertyExpander$ExpandException.class + @OPENJDK@/jdk/src/share/classes/sun/security/util/PropertyExpander.class + @OPENJDK@/jdk/src/share/classes/sun/security/util/SecurityConstants*.class + @OPENJDK@/jdk/src/share/classes/sun/util/*.class + @OPENJDK@/jdk/src/share/classes/sun/util/cldr/*.class + @OPENJDK@/jdk/src/share/classes/sun/util/locale/*.class + @OPENJDK@/jdk/src/share/classes/sun/util/locale/provider/*.class + @OPENJDK@/jdk/src/share/classes/sun/util/logging/*.class + @OPENJDK@/jdk/src/share/classes/sun/util/spi/*.class + @OPENJDK@/jdk/src/solaris/classes/java/io/*.class + @OPENJDK@/jdk/src/solaris/classes/sun/net/www/protocol/http/ntlm/*.class + @OPENJDK@/jdk/src/windows/classes/java/io/*.class + @OPENJDK@/jdk/src/windows/classes/java/lang/*.class + @OPENJDK@/jdk/src/windows/classes/java/net/DefaultInterface.class + @OPENJDK@/jdk/src/windows/classes/sun/net/*.class + @OPENJDK@/jdk/src/windows/classes/sun/nio/ch/*.class + @OPENJDK@/jdk/src/windows/classes/sun/nio/fs/*.class + @OPENJDK@/jdk/src/windows/classes/sun/security/provider/NativePRNG.class + @OPENJDK@/jdk/src/windows/classes/sun/util/locale/provider/*.class + @OPENJDK@/langtools/src/share/classes/jdk/Exported.class +} +{ + -out:IKVM.OpenJDK.Corba.dll + -baseaddress:0x57320000 + -recurse:resources.zip/com/sun/corba/* + -recurse:resources.zip/com/sun/jndi/cosnaming/jndiprovider.properties + -resource:com/sun/corba/se/impl/logging/LogStrings.properties=@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/classes/com/sun/corba/se/impl/logging/LogStrings.properties + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/InitialNameServicePackage/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/LocatorPackage/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/com/sun/corba/se/spi/activation/RepositoryPackage/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CORBA/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextExtPackage/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/CosNaming/NamingContextPackage/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/Dynamic/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynAnyFactoryPackage/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/DynamicAny/DynAnyPackage/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/CodecFactoryPackage/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/IOP/CodecPackage/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/Messaging/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableInterceptor/ORBInitInfoPackage/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/CurrentPackage/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAManagerPackage/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/corba/gensrc/org/omg/PortableServer/POAPackage/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/impsrc/com/sun/corba/se/impl/logging/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/activation/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/copyobject/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/corba/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/dynamicany/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/encoding/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/interceptors/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/io/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/ior/iiop/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/javax/rmi/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/legacy/connection/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/monitoring/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/cosnaming/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/namingutil/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/naming/pcosnaming/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/oa/toa/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orb/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/closure/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/concurrent/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/fsm/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/graph/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/orbutil/threadpool/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/protocol/giopmsgheaders/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/resolver/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/transport/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/impl/util/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/internal/corba/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/internal/CosNaming/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/internal/iiop/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/internal/Interceptors/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/internal/POA/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/org/omg/CORBA/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/broker/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/encoding/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/protocol/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/pept/transport/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/copyobject/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/encoding/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/extension/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/ior/iiop/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/legacy/connection/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/legacy/interceptor/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/logging/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/monitoring/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/oa/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orb/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/closure/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/fsm/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/proxy/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/orbutil/threadpool/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/presentation/rmi/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/protocol/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/resolver/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/servicecontext/*.class + @OPENJDK@/corba/src/share/classes/com/sun/corba/se/spi/transport/*.class + @OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/*.class + @OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/portable/*.class + @OPENJDK@/corba/src/share/classes/com/sun/org/omg/CORBA/ValueDefPackage/*.class + @OPENJDK@/corba/src/share/classes/com/sun/org/omg/SendingContext/*.class + @OPENJDK@/corba/src/share/classes/com/sun/org/omg/SendingContext/CodeBasePackage/*.class + @OPENJDK@/corba/src/share/classes/javax/activity/*.class + @OPENJDK@/corba/src/share/classes/javax/rmi/*.class + @OPENJDK@/corba/src/share/classes/javax/rmi/CORBA/*.class + @OPENJDK@/corba/src/share/classes/javax/transaction/*.class + @OPENJDK@/corba/src/share/classes/javax/transaction/xa/*.class + @OPENJDK@/corba/src/share/classes/org/omg/CORBA/*.class + @OPENJDK@/corba/src/share/classes/org/omg/CORBA/DynAnyPackage/*.class + @OPENJDK@/corba/src/share/classes/org/omg/CORBA/ORBPackage/*.class + @OPENJDK@/corba/src/share/classes/org/omg/CORBA/portable/*.class + @OPENJDK@/corba/src/share/classes/org/omg/CORBA/TypeCodePackage/*.class + @OPENJDK@/corba/src/share/classes/org/omg/CORBA_2_3/*.class + @OPENJDK@/corba/src/share/classes/org/omg/CORBA_2_3/portable/*.class + @OPENJDK@/corba/src/share/classes/org/omg/CosNaming/*.class + @OPENJDK@/corba/src/share/classes/org/omg/PortableServer/*.class + @OPENJDK@/corba/src/share/classes/org/omg/PortableServer/portable/*.class + @OPENJDK@/corba/src/share/classes/org/omg/PortableServer/ServantLocatorPackage/*.class + @OPENJDK@/corba/src/share/classes/org/omg/SendingContext/*.class + @OPENJDK@/corba/src/share/classes/org/omg/stub/java/rmi/*.class + @OPENJDK@/corba/src/share/classes/sun/corba/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jndi/cosnaming/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/corba/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jndi/url/corbaname/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jndi/url/iiop/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jndi/url/iiopname/*.class +} +{ + -out:IKVM.OpenJDK.XML.API.dll + -baseaddress:0x57950000 + -resource:META-INF/services/sun.util.spi.XmlPropertiesProvider=@OPENJDK@/jdk/src/share/classes/sun/util/xml/META-INF/services/sun.util.spi.XmlPropertiesProvider + @OPENJDK@/jaxp/src/javax/xml/*.class + @OPENJDK@/jaxp/src/javax/xml/datatype/*.class + @OPENJDK@/jaxp/src/javax/xml/namespace/*.class + @OPENJDK@/jaxp/src/javax/xml/parsers/*.class + @OPENJDK@/jaxp/src/javax/xml/stream/*.class + @OPENJDK@/jaxp/src/javax/xml/stream/events/*.class + @OPENJDK@/jaxp/src/javax/xml/stream/util/*.class + @OPENJDK@/jaxp/src/javax/xml/transform/*.class + @OPENJDK@/jaxp/src/javax/xml/transform/dom/*.class + @OPENJDK@/jaxp/src/javax/xml/transform/sax/*.class + @OPENJDK@/jaxp/src/javax/xml/transform/stax/*.class + @OPENJDK@/jaxp/src/javax/xml/transform/stream/*.class + @OPENJDK@/jaxp/src/javax/xml/validation/*.class + @OPENJDK@/jaxp/src/javax/xml/xpath/*.class + @OPENJDK@/jaxp/src/org/w3c/dom/*.class + @OPENJDK@/jaxp/src/org/w3c/dom/bootstrap/*.class + @OPENJDK@/jaxp/src/org/w3c/dom/css/*.class + @OPENJDK@/jaxp/src/org/w3c/dom/events/*.class + @OPENJDK@/jaxp/src/org/w3c/dom/html/*.class + @OPENJDK@/jaxp/src/org/w3c/dom/ls/*.class + @OPENJDK@/jaxp/src/org/w3c/dom/ranges/*.class + @OPENJDK@/jaxp/src/org/w3c/dom/stylesheets/*.class + @OPENJDK@/jaxp/src/org/w3c/dom/traversal/*.class + @OPENJDK@/jaxp/src/org/w3c/dom/views/*.class + @OPENJDK@/jaxp/src/org/w3c/dom/xpath/*.class + @OPENJDK@/jaxp/src/org/xml/sax/*.class + @OPENJDK@/jaxp/src/org/xml/sax/ext/*.class + @OPENJDK@/jaxp/src/org/xml/sax/helpers/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/java/browser/dom/*.class + @OPENJDK@/jdk/src/share/classes/sun/util/xml/*.class +} +{ + -out:IKVM.OpenJDK.XML.XPath.dll + -baseaddress:0x57A10000 + -recurse:resources.zip/com/sun/org/apache/xalan/internal/res/* + @OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/extensions/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/res/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/dom2dtm/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/sax2dtm/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/AttList.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/DOMHelper.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/DOM2Helper.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/TreeWalker.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/axes/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/compiler/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/domapi/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/functions/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/jaxp/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/objects/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/operations/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/patterns/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xpath/internal/res/*.class +} +{ + -out:IKVM.OpenJDK.XML.Parse.dll + -baseaddress:0x57D70000 + -recurse:resources.zip/com/sun/org/apache/xerces/* + -recurse:resources.zip/com/sun/org/apache/xml/internal/* + -recurse:resources.zip/com/sun/xml/internal/stream/* + @OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/SecuritySupport.class + @OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/SecuritySupport$*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/utils/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/dom/events/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dtd/models/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/dtd/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/util/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/io/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/validation/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xpath/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xpath/regex/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/identity/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/models/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/opti/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/util/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/parsers/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/util/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/utils/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xinclude/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/grammars/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xni/parser/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xerces/internal/xs/datatypes/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/res/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/helpers/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/readers/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/resolver/tools/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serialize/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xml/internal/utils/res/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/staxex/*.class + @OPENJDK@/jaxp/src/com/sun/xml/internal/stream/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/sax/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/stax/*.class + @OPENJDK@/jaxp/src/com/sun/xml/internal/stream/dtd/*.class + @OPENJDK@/jaxp/src/com/sun/xml/internal/stream/dtd/nonvalidating/*.class + @OPENJDK@/jaxp/src/com/sun/xml/internal/stream/events/*.class + @OPENJDK@/jaxp/src/com/sun/xml/internal/stream/util/*.class + @OPENJDK@/jaxp/src/com/sun/xml/internal/stream/writers/*.class +} +{ + -out:IKVM.OpenJDK.XML.Transform.dll + -baseaddress:0x58550000 + @OPENJDK@/jaxp/src/com/sun/java_cup/internal/runtime/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/generic/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/regexp/internal/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/lib/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/templates/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xslt/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/cmdline/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/cmdline/getopt/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/output/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/*.class + @OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/util/*.class +} +{ + -out:IKVM.OpenJDK.XML.Bind.dll + -baseaddress:0x589A0000 + -recurse:resources.zip/javax/xml/bind/* + -recurse:resources.zip/com/sun/xml/internal/bind/* + -recurse:resources.zip/com/sun/xml/internal/fastinfoset/* + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/annotation/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/api/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/api/impl/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/marshaller/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/unmarshaller/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/bytecode/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/annotation/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/core/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/nav/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/runtime/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/episode/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/schemagen/xmlschema/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/algorithm/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/alphabet/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/dom/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/org/apache/xerces/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/sax/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/events/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/factory/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/tools/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/vocab/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/sax/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/sax/helpers/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/fastinfoset/stax/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/annotation/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2/output/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/annotation/adapters/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/attachment/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/helpers/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/bind/util/*.class +} +{ + -out:IKVM.OpenJDK.XML.WebServices.dll + -baseaddress:0x58DC0000 + -recurse:resources.zip/com/sun/xml/internal/messaging/* + -recurse:resources.zip/com/sun/xml/internal/ws/* + @OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/databinding/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/message/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/impl/encoding/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/impl/internalspi/encoding/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal/webservices/jaxws_databinding/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/localization/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/amx/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/arc/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/probe/provider/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/probe/provider/annotations/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/annotations/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/impl/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/gmbal/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/client/p2p/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/dynamic/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/impl/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/name/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_1/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ver1_2/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/util/transform/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/model/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/policy/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/addressing/v200408/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/addressing/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/client/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/config/management/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/config/management/policy/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/databinding/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/fastinfoset/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/ha/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/handler/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/saaj/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/stream/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/soap/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/model/wsdl/editable/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/helper/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/policy/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/policy/subject/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/streaming/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/wsdl/parser/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/wsdl/writer/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/dev/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/assembler/jaxws/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/binding/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/dispatch/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/commons/xmlutil/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/config/management/policy/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/config/metro/dev/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/config/metro/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/db/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/db/glassfish/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/dump/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/fastinfoset/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/policy/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/soap/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/soap/streaming/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/xml/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/fault/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/handler/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/jaxb/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/saaj/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/source/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/message/stream/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/soap/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/model/wsdl/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/jaxws/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/jaxws/spi/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/privateutil/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/attach/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/wspolicy/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/spi/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/subject/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/protocol/soap/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/protocol/xml/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/resources/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/runtime/config/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/provider/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/server/sei/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/streaming/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/client/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/server/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/exception/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/pipe/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/parser/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/http/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/soap/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/soap12/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/wsdl/writer/document/xsd/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/soap/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/handler/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/handler/soap/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/http/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/soap/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/spi/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/spi/http/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/javax/xml/ws/wsaddressing/*.class +} +{ + -out:IKVM.OpenJDK.XML.Crypto.dll + -baseaddress:0x595D0000 + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/helper/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/encryption/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/exceptions/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/keyvalues/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/signature/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/signature/reference/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/params/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/*.class + @OPENJDK@/jdk/src/share/classes/javax/xml/crypto/*.class + @OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dom/*.class + @OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/*.class + @OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/dom/*.class + @OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/keyinfo/*.class + @OPENJDK@/jdk/src/share/classes/javax/xml/crypto/dsig/spec/*.class + @OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/*.class + @OPENJDK@/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/*.class +} +{ + -out:IKVM.OpenJDK.SwingAWT.dll + -baseaddress:0x59750000 + -remap:swingawt.xml + -resource:META-INF/services/sun.java2d.pipe.RenderingEngine=resources/META-INF/services/sun.java2d.pipe.RenderingEngine + -resource:META-INF/services/sun.java2d.cmm.CMMServiceProvider=@OPENJDK@/jdk/src/share/classes/sun/java2d/cmm/lcms/META-INF/services/sun.java2d.cmm.CMMServiceProvider + -recurse:resources.zip/com/sun/java/swing/* + -recurse:resources.zip/com/sun/swing/internal/plaf/* + -recurse:resources.zip/javax/swing/* + -r:System.Drawing.dll + -r:IKVM.AWT.WinForms.dll + ikvm/awt/*.class + java/awt/*.class + java/awt/color/*.class + java/awt/image/*.class + gnu/java/awt/*.class + gnu/java/awt/color/*.class + sun/awt/*.class + sun/awt/image/*.class + sun/awt/shell/*.class + sun/font/*.class + sun/java2d/*.class + sun/java2d/cmm/lcms/*.class + sun/java2d/pipe/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/accessibility/internal/resources/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/motif/resources/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/java/swing/plaf/windows/resources/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/basic/resources/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/metal/resources/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/swing/internal/plaf/synth/resources/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/javax/swing/plaf/nimbus/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/awt/resources/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/awt/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/java/swing/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/motif/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/nimbus/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/java/swing/plaf/windows/*.class + @OPENJDK@/jdk/src/share/classes/java/applet/*.class + @OPENJDK@/jdk/src/share/classes/java/awt/*.class + @OPENJDK@/jdk/src/share/classes/java/awt/color/*.class + @OPENJDK@/jdk/src/share/classes/java/awt/datatransfer/*.class + @OPENJDK@/jdk/src/share/classes/java/awt/dnd/*.class + @OPENJDK@/jdk/src/share/classes/java/awt/dnd/peer/*.class + @OPENJDK@/jdk/src/share/classes/java/awt/event/*.class + @OPENJDK@/jdk/src/share/classes/java/awt/font/*.class + @OPENJDK@/jdk/src/share/classes/java/awt/geom/*.class + @OPENJDK@/jdk/src/share/classes/java/awt/im/*.class + @OPENJDK@/jdk/src/share/classes/java/awt/im/spi/*.class + @OPENJDK@/jdk/src/share/classes/java/awt/image/*.class + @OPENJDK@/jdk/src/share/classes/java/awt/image/renderable/*.class + @OPENJDK@/jdk/src/share/classes/java/awt/peer/*.class + @OPENJDK@/jdk/src/share/classes/java/awt/print/*.class + @OPENJDK@/jdk/src/share/classes/javax/accessibility/*.class + @OPENJDK@/jdk/src/share/classes/javax/swing/*.class + @OPENJDK@/jdk/src/share/classes/javax/swing/border/*.class + @OPENJDK@/jdk/src/share/classes/javax/swing/colorchooser/*.class + @OPENJDK@/jdk/src/share/classes/javax/swing/event/*.class + @OPENJDK@/jdk/src/share/classes/javax/swing/filechooser/*.class + @OPENJDK@/jdk/src/share/classes/javax/swing/plaf/*.class + @OPENJDK@/jdk/src/share/classes/javax/swing/plaf/basic/*.class + @OPENJDK@/jdk/src/share/classes/javax/swing/plaf/metal/*.class + @OPENJDK@/jdk/src/share/classes/javax/swing/plaf/multi/*.class + @OPENJDK@/jdk/src/share/classes/javax/swing/plaf/nimbus/*.class + @OPENJDK@/jdk/src/share/classes/javax/swing/plaf/synth/*.class + @OPENJDK@/jdk/src/share/classes/javax/swing/table/*.class + @OPENJDK@/jdk/src/share/classes/javax/swing/text/*.class + @OPENJDK@/jdk/src/share/classes/javax/swing/text/html/*.class + @OPENJDK@/jdk/src/share/classes/javax/swing/text/html/parser/*.class + @OPENJDK@/jdk/src/share/classes/javax/swing/text/rtf/*.class + @OPENJDK@/jdk/src/share/classes/javax/swing/tree/*.class + @OPENJDK@/jdk/src/share/classes/javax/swing/undo/*.class + @OPENJDK@/jdk/src/share/classes/sun/applet/*.class + @OPENJDK@/jdk/src/share/classes/sun/awt/*.class + @OPENJDK@/jdk/src/share/classes/sun/awt/datatransfer/*.class + @OPENJDK@/jdk/src/share/classes/sun/awt/dnd/*.class + @OPENJDK@/jdk/src/share/classes/sun/awt/event/*.class + @OPENJDK@/jdk/src/share/classes/sun/awt/geom/*.class + @OPENJDK@/jdk/src/share/classes/sun/awt/im/*.class + @OPENJDK@/jdk/src/share/classes/sun/awt/image/*.class + @OPENJDK@/jdk/src/share/classes/sun/awt/shell/*.class + @OPENJDK@/jdk/src/share/classes/sun/awt/util/*.class + @OPENJDK@/jdk/src/share/classes/sun/font/*.class + @OPENJDK@/jdk/src/share/classes/sun/java2d/*.class + @OPENJDK@/jdk/src/share/classes/sun/java2d/cmm/*.class + @OPENJDK@/jdk/src/share/classes/sun/java2d/cmm/lcms/*.class + @OPENJDK@/jdk/src/share/classes/sun/java2d/pipe/*.class + @OPENJDK@/jdk/src/share/classes/sun/java2d/pipe/hw/*.class + @OPENJDK@/jdk/src/share/classes/sun/java2d/pisces/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/www/content/image/*.class + @OPENJDK@/jdk/src/share/classes/sun/swing/*.class + @OPENJDK@/jdk/src/share/classes/sun/swing/icon/*.class + @OPENJDK@/jdk/src/share/classes/sun/swing/plaf/*.class + @OPENJDK@/jdk/src/share/classes/sun/swing/plaf/synth/*.class + @OPENJDK@/jdk/src/share/classes/sun/swing/plaf/windows/*.class + @OPENJDK@/jdk/src/share/classes/sun/swing/table/*.class + @OPENJDK@/jdk/src/share/classes/sun/swing/text/*.class + @OPENJDK@/jdk/src/share/classes/sun/swing/text/html/*.class + @OPENJDK@/jdk/src/solaris/classes/sun/awt/windows/*.class + @OPENJDK@/jdk/src/windows/classes/sun/awt/*.class +} +{ + -out:IKVM.OpenJDK.Charsets.dll + -baseaddress:0x5A980000 + -resource:sun/nio/cs/ext/sjis0213.dat=@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/sjis0213.dat + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/*.class + @OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/*.class +} +{ + -out:IKVM.OpenJDK.Util.dll + -baseaddress:0x5AE90000 + -recurse:resources.zip/com/sun/java/util/jar/pack/intrinsic.properties + -recurse:resources.zip/sun/launcher/resources/* + -resource:META-INF/services/java.nio.file.spi.FileSystemProvider=@OPENJDK@/jdk/src/share/demo/nio/zipfs/src/META-INF/services/java.nio.file.spi.FileSystemProvider + com/sun/java/util/jar/pack/*.class + java/util/zip/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/logging/resources/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/en/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/java/browser/net/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/java/util/jar/pack/*.class + @OPENJDK@/jdk/src/share/classes/java/util/jar/*.class + @OPENJDK@/jdk/src/share/classes/java/util/logging/*.class + @OPENJDK@/jdk/src/share/classes/java/util/prefs/*.class + @OPENJDK@/jdk/src/share/classes/java/util/spi/*.class + @OPENJDK@/jdk/src/share/classes/java/util/zip/*.class + @OPENJDK@/jdk/src/share/classes/sun/launcher/*.class + @OPENJDK@/jdk/src/share/classes/sun/util/calendar/*.class + @OPENJDK@/jdk/src/share/classes/sun/util/resources/*.class + @OPENJDK@/jdk/src/share/classes/sun/util/resources/en/*.class + @OPENJDK@/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/*.class + @OPENJDK@/jdk/src/solaris/classes/java/util/prefs/*.class + @OPENJDK@/jdk/src/windows/classes/java/util/prefs/*.class +} +{ + -out:IKVM.OpenJDK.Text.dll + -baseaddress:0x5B160000 + -recurse:resources.zip/sun/text/resources/* + @OPENJDK@/jdk/src/share/classes/java/text/*.class + @OPENJDK@/jdk/src/share/classes/java/text/spi/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/bidi/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/normalizer/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/en/*.class +} +{ + -out:IKVM.OpenJDK.Security.dll + -baseaddress:0x5B310000 + -remap:security.xml + sun/security/jgss/wrapper/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/security/util/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/crypto/provider/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/internal/ssl/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/net/ssl/internal/www/protocol/https/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/security/auth/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/security/auth/callback/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/security/auth/login/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/security/auth/module/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/security/cert/internal/x509/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/security/jgss/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/security/ntlm/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/digest/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/gsskerb/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/ntlm/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/security/sasl/util/*.class + @OPENJDK@/jdk/src/share/classes/java/security/acl/*.class + @OPENJDK@/jdk/src/share/classes/java/security/interfaces/*.class + @OPENJDK@/jdk/src/share/classes/java/security/spec/*.class + @OPENJDK@/jdk/src/share/classes/javax/crypto/*.class + @OPENJDK@/jdk/src/share/classes/javax/crypto/interfaces/*.class + @OPENJDK@/jdk/src/share/classes/javax/crypto/spec/*.class + @OPENJDK@/jdk/src/share/classes/javax/net/ssl/*.class + @OPENJDK@/jdk/src/share/classes/javax/security/auth/*.class + @OPENJDK@/jdk/src/share/classes/javax/security/auth/callback/*.class + @OPENJDK@/jdk/src/share/classes/javax/security/auth/kerberos/*.class + @OPENJDK@/jdk/src/share/classes/javax/security/auth/login/*.class + @OPENJDK@/jdk/src/share/classes/javax/security/auth/spi/*.class + @OPENJDK@/jdk/src/share/classes/javax/security/auth/x500/*.class + @OPENJDK@/jdk/src/share/classes/javax/security/cert/*.class + @OPENJDK@/jdk/src/share/classes/javax/security/sasl/*.class + @OPENJDK@/jdk/src/share/classes/org/ietf/jgss/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/http/ntlm/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/https/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/acl/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/internal/interfaces/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/internal/spec/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/jgss/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/jgss/krb5/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/jgss/spi/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/jgss/spnego/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/krb5/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/ccache/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/crypto/dk/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/ktab/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/rcache/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/krb5/internal/util/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/pkcs/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/pkcs10/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/pkcs12/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/provider/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/ldap/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/provider/certpath/ssl/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/rsa/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/ssl/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/ssl/krb5/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/timestamp/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/tools/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/tools/keytool/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/util/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/validator/*.class + @OPENJDK@/jdk/src/share/classes/sun/security/x509/*.class + @OPENJDK@/jdk/src/windows/classes/sun/security/krb5/internal/tools/*.class + @OPENJDK@/jdk/src/windows/classes/sun/security/provider/*.class +} +{ + -out:IKVM.OpenJDK.Management.dll + -baseaddress:0x5BB50000 + java/lang/management/*.class + sun/management/*.class + rmistubs/org/omg/stub/javax/management/remote/rmi/*.class + rmistubs/javax/management/remote/rmi/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/management/resources/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jmx/defaults/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jmx/interceptor/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jmx/mbeanserver/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/internal/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/protocol/iiop/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/protocol/rmi/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/security/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/util/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/management/*.class + @OPENJDK@/jdk/src/share/classes/java/lang/management/*.class + @OPENJDK@/jdk/src/share/classes/javax/management/*.class + @OPENJDK@/jdk/src/share/classes/javax/management/loading/*.class + @OPENJDK@/jdk/src/share/classes/javax/management/modelmbean/*.class + @OPENJDK@/jdk/src/share/classes/javax/management/monitor/*.class + @OPENJDK@/jdk/src/share/classes/javax/management/openmbean/*.class + @OPENJDK@/jdk/src/share/classes/javax/management/relation/*.class + @OPENJDK@/jdk/src/share/classes/javax/management/remote/*.class + @OPENJDK@/jdk/src/share/classes/javax/management/remote/rmi/*.class + @OPENJDK@/jdk/src/share/classes/javax/management/timer/*.class + @OPENJDK@/jdk/src/share/classes/sun/management/*.class + @OPENJDK@/jdk/src/share/classes/sun/management/counter/*.class + @OPENJDK@/jdk/src/share/classes/sun/management/counter/perf/*.class + @OPENJDK@/jdk/src/share/classes/sun/management/jdp/*.class + @OPENJDK@/jdk/src/share/classes/sun/management/jmxremote/*.class + @OPENJDK@/jdk/src/windows/classes/sun/management/*.class +} +{ + -out:IKVM.OpenJDK.Misc.dll + -baseaddress:0x5BEE0000 + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/misc/resources/*.class + @OPENJDK@/corba/src/share/classes/javax/activity/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/javax/annotation/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/javax/jws/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/javax/jws/soap/*.class + @OPENJDK@/corba/src/share/classes/javax/transaction/*.class + @OPENJDK@/corba/src/share/classes/javax/transaction/xa/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/net/httpserver/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/net/httpserver/spi/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/pept/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/pept/encoding/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/pept/ept/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/pept/presentation/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/pept/protocol/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/pept/transport/*.class + @OPENJDK@/jdk/src/share/classes/java/lang/instrument/*.class + @OPENJDK@/jdk/src/share/classes/javax/script/*.class + @OPENJDK@/jdk/src/share/classes/javax/smartcardio/*.class + @OPENJDK@/jdk/src/share/classes/sun/misc/resources/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/httpserver/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/www/protocol/netdoc/*.class + @OPENJDK@/langtools/src/share/classes/javax/annotation/processing/*.class + @OPENJDK@/langtools/src/share/classes/javax/lang/model/*.class + @OPENJDK@/langtools/src/share/classes/javax/lang/model/element/*.class + @OPENJDK@/langtools/src/share/classes/javax/lang/model/type/*.class + @OPENJDK@/langtools/src/share/classes/javax/lang/model/util/*.class + @OPENJDK@/langtools/src/share/classes/javax/tools/*.class +} +{ + -out:IKVM.OpenJDK.Naming.dll + -baseaddress:0x5BFA0000 + -recurse:resources.zip/com/sun/jndi/ldap/jndiprovider.properties + -resource:META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor=@OPENJDK@/jdk/src/share/classes/sun/net/spi/nameservice/dns/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor + sun/net/dns/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jndi/dns/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/ext/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/pool/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jndi/ldap/sasl/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/dir/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jndi/toolkit/url/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jndi/url/dns/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jndi/url/ldap/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jndi/url/ldaps/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/naming/internal/*.class + @OPENJDK@/jdk/src/share/classes/javax/naming/*.class + @OPENJDK@/jdk/src/share/classes/javax/naming/directory/*.class + @OPENJDK@/jdk/src/share/classes/javax/naming/event/*.class + @OPENJDK@/jdk/src/share/classes/javax/naming/ldap/*.class + @OPENJDK@/jdk/src/share/classes/javax/naming/spi/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/dns/*.class + @OPENJDK@/jdk/src/share/classes/sun/net/spi/nameservice/dns/*.class +} +{ + -out:IKVM.OpenJDK.Jdbc.dll + -baseaddress:0x5C120000 + -resource:META-INF/services/java.sql.Driver=resources/META-INF/services/java.sql.Driver + -recurse:resources.zip/com/sun/rowset/* + -recurse:resources.zip/javax/sql/* + -r:System.Data.dll + sun/jdbc/odbc/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/rowset/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/rowset/internal/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/rowset/providers/*.class + @OPENJDK@/jdk/src/share/classes/java/sql/*.class + @OPENJDK@/jdk/src/share/classes/javax/sql/*.class + @OPENJDK@/jdk/src/share/classes/javax/sql/rowset/*.class + @OPENJDK@/jdk/src/share/classes/javax/sql/rowset/serial/*.class + @OPENJDK@/jdk/src/share/classes/javax/sql/rowset/spi/*.class +} +{ + -out:IKVM.OpenJDK.Remoting.dll + -baseaddress:0x5C2A0000 + -recurse:resources.zip/sun/rmi/* + rmistubs/com/sun/jndi/rmi/registry/*.class + rmistubs/java/rmi/activation/*.class + rmistubs/sun/rmi/registry/*.class + rmistubs/sun/rmi/server/*.class + rmistubs/sun/rmi/transport/*.class + @OPENJDK@/jdk/src/share/classes/java/rmi/*.class + @OPENJDK@/jdk/src/share/classes/java/rmi/activation/*.class + @OPENJDK@/jdk/src/share/classes/java/rmi/dgc/*.class + @OPENJDK@/jdk/src/share/classes/java/rmi/registry/*.class + @OPENJDK@/jdk/src/share/classes/java/rmi/server/*.class + @OPENJDK@/jdk/src/share/classes/javax/rmi/ssl/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jndi/rmi/registry/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jndi/url/rmi/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/rmi/rmid/*.class + @OPENJDK@/jdk/src/share/classes/sun/rmi/log/*.class + @OPENJDK@/jdk/src/share/classes/sun/rmi/registry/*.class + @OPENJDK@/jdk/src/share/classes/sun/rmi/runtime/*.class + @OPENJDK@/jdk/src/share/classes/sun/rmi/server/*.class + @OPENJDK@/jdk/src/share/classes/sun/rmi/transport/*.class + @OPENJDK@/jdk/src/share/classes/sun/rmi/transport/proxy/*.class + @OPENJDK@/jdk/src/share/classes/sun/rmi/transport/tcp/*.class +} +{ + -out:IKVM.OpenJDK.Beans.dll + -baseaddress:0x5C3F0000 + -resource:META-INF/mailcap.default=@OPENJDK@/jaxws/src/share/jaf_classes/META-INF/mailcap.default + -resource:META-INF/mimetypes.default=@OPENJDK@/jaxws/src/share/jaf_classes/META-INF/mimetypes.default + @OPENJDK@/jaxws/src/share/jaf_classes/com/sun/activation/registries/*.class + @OPENJDK@/jaxws/src/share/jaf_classes/javax/activation/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/beans/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/beans/decoder/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/beans/editors/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/beans/finder/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/beans/infos/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/beans/util/*.class + @OPENJDK@/jdk/src/share/classes/java/beans/*.class + @OPENJDK@/jdk/src/share/classes/java/beans/beancontext/*.class +} +{ + -out:IKVM.OpenJDK.Media.dll + -baseaddress:0x5C4E0000 + -resource:META-INF/services/javax.print.PrintServiceLookup=@OPENJDK@/jdk/src/windows/classes/sun/print/services/javax.print.PrintServiceLookup + -resource:META-INF/services/javax.print.StreamPrintServiceFactory=@OPENJDK@/jdk/src/windows/classes/sun/print/services/javax.print.StreamPrintServiceFactory + -resource:META-INF/services/javax.sound.midi.spi.MidiDeviceProvider=@OPENJDK@/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiDeviceProvider + -resource:META-INF/services/javax.sound.midi.spi.MidiFileReader=@OPENJDK@/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiFileReader + -resource:META-INF/services/javax.sound.midi.spi.MidiFileWriter=@OPENJDK@/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiFileWriter + -resource:META-INF/services/javax.sound.midi.spi.SoundbankReader=@OPENJDK@/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.SoundbankReader + -resource:META-INF/services/javax.sound.sampled.spi.AudioFileReader=@OPENJDK@/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.AudioFileReader + -resource:META-INF/services/javax.sound.sampled.spi.AudioFileWriter=@OPENJDK@/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.AudioFileWriter + -resource:META-INF/services/javax.sound.sampled.spi.FormatConversionProvider=@OPENJDK@/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.FormatConversionProvider + -resource:META-INF/services/javax.sound.sampled.spi.MixerProvider=@OPENJDK@/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.MixerProvider + -recurse:resources.zip/com/sun/imageio/plugins/common/iio-plugin.properties + -r:System.Drawing.dll + com/sun/imageio/plugins/jpeg/*.class + icedtea/rt/com/sun/media/sound/*.class + sun/print/*.class + sun/awt/windows/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/print/resources/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/bmp/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/common/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/gif/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/png/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/imageio/spi/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/imageio/stream/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/media/sound/*.class + @OPENJDK@/jdk/src/share/classes/javax/imageio/*.class + @OPENJDK@/jdk/src/share/classes/javax/imageio/event/*.class + @OPENJDK@/jdk/src/share/classes/javax/imageio/metadata/*.class + @OPENJDK@/jdk/src/share/classes/javax/imageio/plugins/bmp/*.class + @OPENJDK@/jdk/src/share/classes/javax/imageio/plugins/jpeg/*.class + @OPENJDK@/jdk/src/share/classes/javax/imageio/spi/*.class + @OPENJDK@/jdk/src/share/classes/javax/imageio/stream/*.class + @OPENJDK@/jdk/src/share/classes/javax/print/*.class + @OPENJDK@/jdk/src/share/classes/javax/print/attribute/*.class + @OPENJDK@/jdk/src/share/classes/javax/print/attribute/standard/*.class + @OPENJDK@/jdk/src/share/classes/javax/print/event/*.class + @OPENJDK@/jdk/src/share/classes/javax/sound/midi/*.class + @OPENJDK@/jdk/src/share/classes/javax/sound/midi/spi/*.class + @OPENJDK@/jdk/src/share/classes/javax/sound/sampled/*.class + @OPENJDK@/jdk/src/share/classes/javax/sound/sampled/spi/*.class + @OPENJDK@/jdk/src/share/classes/sun/print/*.class + @OPENJDK@/jdk/src/windows/classes/sun/print/*.class +} +{ + -out:IKVM.OpenJDK.Nashorn.dll + -baseaddress:0x5C750000 + -resource:META-INF/services/javax.script.ScriptEngineFactory=@OPENJDK@/nashorn/src/META-INF/services/javax.script.ScriptEngineFactory + -resource:jdk/nashorn/internal/runtime/resources/version.properties=resources/nashorn/version.properties + -recurse:@OPENJDK@/nashorn/src/*.js + -recurse:@OPENJDK@/nashorn/src/*.properties + @OPENJDK@/nashorn/src/jdk/internal/dynalink/*.class + @OPENJDK@/nashorn/src/jdk/internal/dynalink/beans/*.class + @OPENJDK@/nashorn/src/jdk/internal/dynalink/linker/*.class + @OPENJDK@/nashorn/src/jdk/internal/dynalink/support/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/api/scripting/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/annotations/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/debug/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/visitor/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/lookup/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/annotations/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/parser/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/events/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/logging/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/options/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/internal/scripts/*.class + @OPENJDK@/nashorn/src/jdk/nashorn/tools/*.class +} +{ + -out:IKVM.OpenJDK.Localedata.dll + -baseaddress:0x5CCC0000 + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/be/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/bg/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ca/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cs/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/da/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/de/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/el/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/es/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/et/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/fi/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/fr/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ga/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/hi/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/hr/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/hu/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/in/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/is/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/it/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/iw/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ja/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ko/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/lt/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/lv/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/mk/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ms/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/mt/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/nl/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/no/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/pl/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/pt/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ro/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ru/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sk/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sl/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sq/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sr/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/sv/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/th/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/tr/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/uk/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/vi/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/zh/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/ar/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/be/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/bg/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/ca/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/cs/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/da/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/de/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/el/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/es/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/et/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/fi/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/fr/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/ga/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/hi/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/hr/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/hu/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/in/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/is/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/it/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/iw/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/ja/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/ko/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/lt/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/lv/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/mk/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/ms/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/mt/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/nl/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/no/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/pl/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/pt/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/ro/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/ru/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/sk/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/sl/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/sq/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/sr/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/sv/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/th/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/tr/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/uk/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/vi/*.class + @OPENJDK@/jdk/src/share/classes/sun/text/resources/zh/*.class + @OPENJDK@/jdk/src/share/classes/sun/util/resources/de/*.class + @OPENJDK@/jdk/src/share/classes/sun/util/resources/es/*.class + @OPENJDK@/jdk/src/share/classes/sun/util/resources/fr/*.class + @OPENJDK@/jdk/src/share/classes/sun/util/resources/hi/*.class + @OPENJDK@/jdk/src/share/classes/sun/util/resources/it/*.class + @OPENJDK@/jdk/src/share/classes/sun/util/resources/ja/*.class + @OPENJDK@/jdk/src/share/classes/sun/util/resources/ko/*.class + @OPENJDK@/jdk/src/share/classes/sun/util/resources/pt/*.class + @OPENJDK@/jdk/src/share/classes/sun/util/resources/sv/*.class + @OPENJDK@/jdk/src/share/classes/sun/util/resources/zh/*.class +} +{ + -out:IKVM.OpenJDK.Cldrdata.dll + -baseaddress:0x5D1A0000 + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/aa/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/af/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/agq/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ak/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/am/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ar/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/as/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/asa/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/az/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/bas/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/be/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/bem/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/bez/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/bg/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/bm/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/bn/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/bo/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/br/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/brx/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/bs/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/byn/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ca/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/cgg/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/chr/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/cs/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/cy/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/da/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/dav/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/de/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/dje/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/dua/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/dyo/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/dz/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ebu/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ee/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/el/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/en/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/eo/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/es/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/et/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/eu/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ewo/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/fa/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ff/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/fi/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/fil/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/fo/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/fr/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/fur/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ga/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/gd/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/gl/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/gsw/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/gu/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/guz/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/gv/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ha/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/haw/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/he/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/hi/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/hr/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/hu/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/hy/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ia/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/id/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ig/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ii/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/is/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/it/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ja/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/jmc/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ka/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/kab/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/kam/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/kde/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/kea/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/khq/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ki/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/kk/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/kl/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/kln/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/km/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/kn/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ko/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/kok/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ksb/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ksf/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ksh/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/kw/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/lag/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/lg/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ln/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/lo/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/lt/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/lu/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/luo/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/luy/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/lv/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/mas/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/mer/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/mfe/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/mg/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/mgh/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/mk/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ml/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/mr/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ms/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/mt/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/mua/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/my/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/naq/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/nb/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/nd/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ne/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/nl/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/nmg/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/nn/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/nr/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/nso/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/nus/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/nyn/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/om/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/or/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/pa/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/pl/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ps/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/pt/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/rm/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/rn/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ro/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/rof/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ru/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/rw/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/rwk/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/saq/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sbp/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/se/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/seh/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ses/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sg/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/shi/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/si/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sk/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sl/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sn/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/so/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sq/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sr/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ss/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ssy/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/st/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sv/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/sw/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/swc/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ta/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/te/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/teo/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/th/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ti/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/tig/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/tn/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/to/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/tr/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ts/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/twq/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/tzm/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/uk/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ur/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/uz/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/vai/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/ve/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/vi/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/vun/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/wae/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/wal/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/xh/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/xog/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/yav/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/yo/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/zh/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/zu/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/cldr/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/aa/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/af/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/agq/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ak/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/am/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ar/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/as/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/asa/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/az/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bas/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/be/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bem/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bez/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bg/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bm/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bn/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bo/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/br/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/brx/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/bs/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/byn/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ca/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/cgg/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/chr/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/cs/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/cy/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/da/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/dav/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/de/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/dje/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/dua/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/dyo/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/dz/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ebu/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ee/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/el/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/en/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/eo/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/es/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/et/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/eu/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ewo/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fa/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ff/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fi/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fil/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fo/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fr/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/fur/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ga/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/gd/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/gl/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/gsw/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/gu/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/guz/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/gv/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ha/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/haw/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/he/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/hi/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/hr/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/hu/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/hy/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/id/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ig/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ii/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/is/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/it/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ja/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/jmc/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ka/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kab/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kam/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kde/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kea/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/khq/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ki/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kk/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kl/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kln/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/km/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kn/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ko/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kok/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ksb/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ksf/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ksh/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/kw/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lag/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lg/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ln/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lo/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lt/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lu/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/luo/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/luy/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/lv/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mas/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mer/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mfe/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mg/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mgh/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mk/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ml/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mr/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ms/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mt/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/mua/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/my/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/naq/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nb/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nd/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ne/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nl/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nmg/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nn/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nr/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nso/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nus/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/nyn/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/om/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/or/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pa/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pl/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ps/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/pt/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/rm/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/rn/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ro/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/rof/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ru/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/rw/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/rwk/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sah/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/saq/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sbp/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/se/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/seh/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ses/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sg/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/shi/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/si/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sk/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sl/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sn/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/so/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sq/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sr/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ss/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ssy/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/st/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sv/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/sw/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/swc/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ta/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/te/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/teo/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/tg/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/th/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ti/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/tig/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/tn/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/to/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/tr/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ts/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/twq/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/tzm/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/uk/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ur/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/uz/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/vai/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/ve/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/vi/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/vun/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/wae/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/wal/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/xh/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/xog/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/yav/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/yo/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zh/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/cldr/zu/*.class +} diff --git a/openjdk/security.xml b/openjdk/security.xml new file mode 100644 index 0000000..7807a73 --- /dev/null +++ b/openjdk/security.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openjdk/sun/awt/DebugSettings.java b/openjdk/sun/awt/DebugSettings.java new file mode 100644 index 0000000..43c3f28 --- /dev/null +++ b/openjdk/sun/awt/DebugSettings.java @@ -0,0 +1,30 @@ +/* + Copyright (C) 2015 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package sun.awt; + +final class DebugSettings +{ + static void init() { } +} diff --git a/openjdk/sun/awt/EmbeddedFrame.java b/openjdk/sun/awt/EmbeddedFrame.java new file mode 100644 index 0000000..1cbdf94 --- /dev/null +++ b/openjdk/sun/awt/EmbeddedFrame.java @@ -0,0 +1,544 @@ +/* + * Copyright (c) 1996, 2013, 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.awt; + +import java.awt.*; +import java.awt.event.*; +import java.awt.image.*; +import java.awt.peer.*; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeEvent; +import java.util.Set; +import java.awt.AWTKeyStroke; +import java.applet.Applet; + +/** + * A generic container used for embedding Java components, usually applets. + * An EmbeddedFrame has two related uses: + * + * . Within a Java-based application, an EmbeddedFrame serves as a sort of + * firewall, preventing the contained components or applets from using + * getParent() to find parent components, such as menubars. + * + * . Within a C-based application, an EmbeddedFrame contains a window handle + * which was created by the application, which serves as the top-level + * Java window. EmbeddedFrames created for this purpose are passed-in a + * handle of an existing window created by the application. The window + * handle should be of the appropriate native type for a specific + * platform, as stored in the pData field of the ComponentPeer. + * + * @author Thomas Ball + */ +public abstract class EmbeddedFrame extends Frame + implements KeyEventDispatcher, PropertyChangeListener { + + private boolean isCursorAllowed = true; + private boolean supportsXEmbed = false; + private KeyboardFocusManager appletKFM; + // JDK 1.1 compatibility + private static final long serialVersionUID = 2967042741780317130L; + + /* + * The constants define focus traversal directions. + * Use them in {@code traverseIn}, {@code traverseOut} methods. + */ + protected static final boolean FORWARD = true; + protected static final boolean BACKWARD = false; + + public boolean supportsXEmbed() { + return supportsXEmbed && SunToolkit.needsXEmbed(); + } + + protected EmbeddedFrame(boolean supportsXEmbed) { + this((long)0, supportsXEmbed); + } + + + protected EmbeddedFrame() { + this((long)0); + } + + /** + * @deprecated This constructor will be removed in 1.5 + */ + @Deprecated + protected EmbeddedFrame(int handle) { + this((long)handle); + } + + protected EmbeddedFrame(long handle) { + this(handle, false); + } + + protected EmbeddedFrame(long handle, boolean supportsXEmbed) { + this.supportsXEmbed = supportsXEmbed; + registerListeners(); + } + + /** + * Block introspection of a parent window by this child. + */ + public Container getParent() { + return null; + } + + /** + * Needed to track which KeyboardFocusManager is current. We want to avoid memory + * leaks, so when KFM stops being current, we remove ourselves as listeners. + */ + public void propertyChange(PropertyChangeEvent evt) { + // We don't handle any other properties. Skip it. + if (!evt.getPropertyName().equals("managingFocus")) { + return; + } + + // We only do it if it stops being current. Technically, we should + // never get an event about KFM starting being current. + if (evt.getNewValue() == Boolean.TRUE) { + return; + } + + // should be the same as appletKFM + removeTraversingOutListeners((KeyboardFocusManager)evt.getSource()); + + appletKFM = KeyboardFocusManager.getCurrentKeyboardFocusManager(); + if (isVisible()) { + addTraversingOutListeners(appletKFM); + } + } + + /** + * Register us as KeyEventDispatcher and property "managingFocus" listeners. + */ + private void addTraversingOutListeners(KeyboardFocusManager kfm) { + kfm.addKeyEventDispatcher(this); + kfm.addPropertyChangeListener("managingFocus", this); + } + + /** + * Deregister us as KeyEventDispatcher and property "managingFocus" listeners. + */ + private void removeTraversingOutListeners(KeyboardFocusManager kfm) { + kfm.removeKeyEventDispatcher(this); + kfm.removePropertyChangeListener("managingFocus", this); + } + + /** + * Because there may be many AppContexts, and we can't be sure where this + * EmbeddedFrame is first created or shown, we can't automatically determine + * the correct KeyboardFocusManager to attach to as KeyEventDispatcher. + * Those who want to use the functionality of traversing out of the EmbeddedFrame + * must call this method on the Applet's AppContext. After that, all the changes + * can be handled automatically, including possible replacement of + * KeyboardFocusManager. + */ + public void registerListeners() { + if (appletKFM != null) { + removeTraversingOutListeners(appletKFM); + } + appletKFM = KeyboardFocusManager.getCurrentKeyboardFocusManager(); + if (isVisible()) { + addTraversingOutListeners(appletKFM); + } + } + + /** + * Needed to avoid memory leak: we register this EmbeddedFrame as a listener with + * KeyboardFocusManager of applet's AppContext. We don't want the KFM to keep + * reference to our EmbeddedFrame forever if the Frame is no longer in use, so we + * add listeners in show() and remove them in hide(). + */ + @SuppressWarnings("deprecation") + public void show() { + if (appletKFM != null) { + addTraversingOutListeners(appletKFM); + } + super.show(); + } + + /** + * Needed to avoid memory leak: we register this EmbeddedFrame as a listener with + * KeyboardFocusManager of applet's AppContext. We don't want the KFM to keep + * reference to our EmbeddedFrame forever if the Frame is no longer in use, so we + * add listeners in show() and remove them in hide(). + */ + @SuppressWarnings("deprecation") + public void hide() { + if (appletKFM != null) { + removeTraversingOutListeners(appletKFM); + } + super.hide(); + } + + /** + * Need this method to detect when the focus may have chance to leave the + * focus cycle root which is EmbeddedFrame. Mostly, the code here is copied + * from DefaultKeyboardFocusManager.processKeyEvent with some minor + * modifications. + */ + public boolean dispatchKeyEvent(KeyEvent e) { + + Container currentRoot = AWTAccessor.getKeyboardFocusManagerAccessor() + .getCurrentFocusCycleRoot(); + + // if we are not in EmbeddedFrame's cycle, we should not try to leave. + if (this != currentRoot) { + return false; + } + + // KEY_TYPED events cannot be focus traversal keys + if (e.getID() == KeyEvent.KEY_TYPED) { + return false; + } + + if (!getFocusTraversalKeysEnabled() || e.isConsumed()) { + return false; + } + + AWTKeyStroke stroke = AWTKeyStroke.getAWTKeyStrokeForEvent(e); + Set toTest; + Component currentFocused = e.getComponent(); + + Component last = getFocusTraversalPolicy().getLastComponent(this); + toTest = getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); + if (toTest.contains(stroke) && (currentFocused == last || last == null)) { + if (traverseOut(FORWARD)) { + e.consume(); + return true; + } + } + + Component first = getFocusTraversalPolicy().getFirstComponent(this); + toTest = getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); + if (toTest.contains(stroke) && (currentFocused == first || first == null)) { + if (traverseOut(BACKWARD)) { + e.consume(); + return true; + } + } + return false; + } + + /** + * This method is called from dispatchKeyEvent in the following two cases: + * 1. The focus is on the first Component of this EmbeddedFrame and we are + * about to transfer the focus backward. + * 2. The focus in on the last Component of this EmbeddedFrame and we are + * about to transfer the focus forward. + * This is needed to give the opportuity for keyboard focus to leave the + * EmbeddedFrame. Override this method, initiate focus transfer in it and + * return true if you want the focus to leave EmbeddedFrame's cycle. + * The direction parameter specifies which of the two mentioned cases is + * happening. Use FORWARD and BACKWARD constants defined in EmbeddedFrame + * to avoid confusing boolean values. + * + * @param direction FORWARD or BACKWARD + * @return true, if EmbeddedFrame wants the focus to leave it, + * false otherwise. + */ + protected boolean traverseOut(boolean direction) { + return false; + } + + /** + * Block modifying any frame attributes, since they aren't applicable + * for EmbeddedFrames. + */ + public void setTitle(String title) {} + public void setIconImage(Image image) {} + public void setIconImages(java.util.List icons) {} + public void setMenuBar(MenuBar mb) {} + public void setResizable(boolean resizable) {} + public void remove(MenuComponent m) {} + + public boolean isResizable() { + return true; + } + + @SuppressWarnings("deprecation") + public void addNotify() { + synchronized (getTreeLock()) { + if (getPeer() == null) { + setPeer(new NullEmbeddedFramePeer()); + } + super.addNotify(); + } + } + + // These three functions consitute RFE 4100710. Do not remove. + @SuppressWarnings("deprecation") + public void setCursorAllowed(boolean isCursorAllowed) { + this.isCursorAllowed = isCursorAllowed; + getPeer().updateCursorImmediately(); + } + public boolean isCursorAllowed() { + return isCursorAllowed; + } + public Cursor getCursor() { + return (isCursorAllowed) + ? super.getCursor() + : Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); + } + + @SuppressWarnings("deprecation") + protected void setPeer(final ComponentPeer p){ + AWTAccessor.getComponentAccessor().setPeer(EmbeddedFrame.this, p); + }; + + /** + * Synthesize native message to activate or deactivate EmbeddedFrame window + * depending on the value of parameter b. + * Peers should override this method if they are to implement + * this functionality. + * @param doActivate if true, activates the window; + * otherwise, deactivates the window + */ + public void synthesizeWindowActivation(boolean doActivate) {} + + /** + * Moves this embedded frame to a new location. The top-left corner of + * the new location is specified by the x and y + * parameters relative to the native parent component. + *

+ * setLocation() and setBounds() for EmbeddedFrame really don't move it + * within the native parent. These methods always put embedded frame to + * (0, 0) for backward compatibility. To allow moving embedded frame + * setLocationPrivate() and setBoundsPrivate() were introduced, and they + * work just the same way as setLocation() and setBounds() for usual, + * non-embedded components. + *

+ *

+ * Using usual get/setLocation() and get/setBounds() together with new + * get/setLocationPrivate() and get/setBoundsPrivate() is not recommended. + * For example, calling getBoundsPrivate() after setLocation() works fine, + * but getBounds() after setBoundsPrivate() may return unpredictable value. + *

+ * @param x the new x-coordinate relative to the parent component + * @param y the new y-coordinate relative to the parent component + * @see java.awt.Component#setLocation + * @see #getLocationPrivate + * @see #setBoundsPrivate + * @see #getBoundsPrivate + * @since 1.5 + */ + protected void setLocationPrivate(int x, int y) { + Dimension size = getSize(); + setBoundsPrivate(x, y, size.width, size.height); + } + + /** + * Gets the location of this embedded frame as a point specifying the + * top-left corner relative to parent component. + *

+ * setLocation() and setBounds() for EmbeddedFrame really don't move it + * within the native parent. These methods always put embedded frame to + * (0, 0) for backward compatibility. To allow getting location and size + * of embedded frame getLocationPrivate() and getBoundsPrivate() were + * introduced, and they work just the same way as getLocation() and getBounds() + * for ususal, non-embedded components. + *

+ *

+ * Using usual get/setLocation() and get/setBounds() together with new + * get/setLocationPrivate() and get/setBoundsPrivate() is not recommended. + * For example, calling getBoundsPrivate() after setLocation() works fine, + * but getBounds() after setBoundsPrivate() may return unpredictable value. + *

+ * @return a point indicating this embedded frame's top-left corner + * @see java.awt.Component#getLocation + * @see #setLocationPrivate + * @see #setBoundsPrivate + * @see #getBoundsPrivate + * @since 1.6 + */ + protected Point getLocationPrivate() { + Rectangle bounds = getBoundsPrivate(); + return new Point(bounds.x, bounds.y); + } + + /** + * Moves and resizes this embedded frame. The new location of the top-left + * corner is specified by x and y parameters + * relative to the native parent component. The new size is specified by + * width and height. + *

+ * setLocation() and setBounds() for EmbeddedFrame really don't move it + * within the native parent. These methods always put embedded frame to + * (0, 0) for backward compatibility. To allow moving embedded frames + * setLocationPrivate() and setBoundsPrivate() were introduced, and they + * work just the same way as setLocation() and setBounds() for usual, + * non-embedded components. + *

+ *

+ * Using usual get/setLocation() and get/setBounds() together with new + * get/setLocationPrivate() and get/setBoundsPrivate() is not recommended. + * For example, calling getBoundsPrivate() after setLocation() works fine, + * but getBounds() after setBoundsPrivate() may return unpredictable value. + *

+ * @param x the new x-coordinate relative to the parent component + * @param y the new y-coordinate relative to the parent component + * @param width the new width of this embedded frame + * @param height the new height of this embedded frame + * @see java.awt.Component#setBounds + * @see #setLocationPrivate + * @see #getLocationPrivate + * @see #getBoundsPrivate + * @since 1.5 + */ + @SuppressWarnings("deprecation") + protected void setBoundsPrivate(int x, int y, int width, int height) { + final FramePeer peer = (FramePeer)getPeer(); + if (peer != null) { + peer.setBoundsPrivate(x, y, width, height); + } + } + + /** + * Gets the bounds of this embedded frame as a rectangle specifying the + * width, height and location relative to the native parent component. + *

+ * setLocation() and setBounds() for EmbeddedFrame really don't move it + * within the native parent. These methods always put embedded frame to + * (0, 0) for backward compatibility. To allow getting location and size + * of embedded frames getLocationPrivate() and getBoundsPrivate() were + * introduced, and they work just the same way as getLocation() and getBounds() + * for ususal, non-embedded components. + *

+ *

+ * Using usual get/setLocation() and get/setBounds() together with new + * get/setLocationPrivate() and get/setBoundsPrivate() is not recommended. + * For example, calling getBoundsPrivate() after setLocation() works fine, + * but getBounds() after setBoundsPrivate() may return unpredictable value. + *

+ * @return a rectangle indicating this embedded frame's bounds + * @see java.awt.Component#getBounds + * @see #setLocationPrivate + * @see #getLocationPrivate + * @see #setBoundsPrivate + * @since 1.6 + */ + @SuppressWarnings("deprecation") + protected Rectangle getBoundsPrivate() { + final FramePeer peer = (FramePeer)getPeer(); + if (peer != null) { + return peer.getBoundsPrivate(); + } + else { + return getBounds(); + } + } + + public void toFront() {} + public void toBack() {} + + public abstract void registerAccelerator(AWTKeyStroke stroke); + public abstract void unregisterAccelerator(AWTKeyStroke stroke); + + /** + * Checks if the component is in an EmbeddedFrame. If so, + * returns the applet found in the hierarchy or null if + * not found. + * @return the parent applet or {@ null} + * @since 1.6 + */ + public static Applet getAppletIfAncestorOf(Component comp) { + Container parent = comp.getParent(); + Applet applet = null; + while (parent != null && !(parent instanceof EmbeddedFrame)) { + if (parent instanceof Applet) { + applet = (Applet)parent; + } + parent = parent.getParent(); + } + return parent == null ? null : applet; + } + + /** + * This method should be overriden in subclasses. It is + * called when window this frame is within should be blocked + * by some modal dialog. + */ + public void notifyModalBlocked(Dialog blocker, boolean blocked) { + } + + private static class NullEmbeddedFramePeer + extends NullComponentPeer implements FramePeer { + public void setTitle(String title) {} + public void setIconImage(Image im) {} + public void updateIconImages() {} + public void setMenuBar(MenuBar mb) {} + public void setResizable(boolean resizeable) {} + public void setState(int state) {} + public int getState() { return Frame.NORMAL; } + public void setMaximizedBounds(Rectangle b) {} + public void toFront() {} + public void toBack() {} + public void updateFocusableWindowState() {} + public void updateAlwaysOnTop() {} + public void updateAlwaysOnTopState() {} + public Component getGlobalHeavyweightFocusOwner() { return null; } + public void setBoundsPrivate(int x, int y, int width, int height) { + setBounds(x, y, width, height, SET_BOUNDS); + } + public Rectangle getBoundsPrivate() { + return getBounds(); + } + public void setModalBlocked(Dialog blocker, boolean blocked) {} + + /** + * @see java.awt.peer.ContainerPeer#restack + */ + public void restack() { + throw new UnsupportedOperationException(); + } + + /** + * @see java.awt.peer.ContainerPeer#isRestackSupported + */ + public boolean isRestackSupported() { + return false; + } + public boolean requestWindowFocus() { + return false; + } + public void updateMinimumSize() { + } + + public void setOpacity(float opacity) { + } + + public void setOpaque(boolean isOpaque) { + } + + public void updateWindow() { + } + + public void repositionSecurityWarning() { + } + + public void emulateActivation(boolean activate) { + } + } +} // class EmbeddedFrame diff --git a/openjdk/sun/awt/IkvmDataTransferer.java b/openjdk/sun/awt/IkvmDataTransferer.java new file mode 100644 index 0000000..5dad27f --- /dev/null +++ b/openjdk/sun/awt/IkvmDataTransferer.java @@ -0,0 +1,566 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ + +package sun.awt; + +import java.awt.Image; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.FlavorTable; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.SortedMap; + +import sun.awt.datatransfer.DataTransferer; +import cli.System.Runtime.InteropServices.DllImportAttribute; + +public abstract class IkvmDataTransferer extends DataTransferer { + public static final int CF_TEXT = 1; + public static final int CF_METAFILEPICT = 3; + public static final int CF_DIB = 8; + public static final int CF_ENHMETAFILE = 14; + public static final int CF_HDROP = 15; + public static final int CF_LOCALE = 16; + + public static final long CF_HTML = RegisterClipboardFormat("HTML Format"); + public static final long CFSTR_INETURL = RegisterClipboardFormat("UniformResourceLocator"); + public static final long CF_PNG = RegisterClipboardFormat("PNG"); + public static final long CF_JFIF = RegisterClipboardFormat("JFIF"); + + private static final String[] predefinedClipboardNames = { + "", + "TEXT", + "BITMAP", + "METAFILEPICT", + "SYLK", + "DIF", + "TIFF", + "OEM TEXT", + "DIB", + "PALETTE", + "PENDATA", + "RIFF", + "WAVE", + "UNICODE TEXT", + "ENHMETAFILE", + "HDROP", + "LOCALE", + "DIBV5" + }; + + private static final Map predefinedClipboardNameMap; + + static { + Map tempMap = new HashMap(predefinedClipboardNames.length, 1.0f); + for (int i = 1; i < predefinedClipboardNames.length; i++) { + tempMap.put(predefinedClipboardNames[i], Long.valueOf(i)); + } + predefinedClipboardNameMap = Collections.synchronizedMap(tempMap); + } + + private static final Long L_CF_LOCALE = (Long) predefinedClipboardNameMap.get(predefinedClipboardNames[CF_LOCALE]); + + @DllImportAttribute.Annotation(value = "user32.dll", EntryPoint = "RegisterClipboardFormat") + private native static int _RegisterClipboardFormat(String format); + + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + private static int RegisterClipboardFormat(String format) + { + return _RegisterClipboardFormat(format); + } + + public SortedMap getFormatsForFlavors(DataFlavor[] flavors, FlavorTable map) { + SortedMap retval = super.getFormatsForFlavors(flavors, map); + + // The Win32 native code does not support exporting LOCALE data, nor + // should it. + retval.remove(L_CF_LOCALE); + + return retval; + } + + public String getDefaultUnicodeEncoding() { + return "utf-16le"; + } + + public byte[] translateTransferable(Transferable contents, + DataFlavor flavor, + long format) throws IOException + { + byte[] bytes = super.translateTransferable(contents, flavor, format); + + if (format == CF_HTML) { + bytes = HTMLCodec.convertToHTMLFormat(bytes); + } + return bytes; + } + + protected byte[] imageToPlatformBytes(Image image, long format) + throws IOException { + String mimeType = null; + if (format == CF_PNG) { + mimeType = "image/png"; + } else if (format == CF_JFIF) { + mimeType = "image/jpeg"; + } + if (mimeType != null) { + return imageToStandardBytes(image, mimeType); + } + throw new Error("Not implemented"); + } + + protected abstract byte[] imageToStandardBytes(Image image, String mimeType) + throws IOException; + + protected Image platformImageBytesOrStreamToImage(InputStream str, + byte[] bytes, long format) { + throw new Error("Not implemented"); + } + + protected String[] dragQueryFile(byte[] bytes) { + throw new Error("Not implemented"); + } + + protected String getNativeForFormat(long format) { + return (format < predefinedClipboardNames.length && format>=0) + ? predefinedClipboardNames[(int)format] + : getClipboardFormatName(format); + } + + protected Long getFormatForNativeAsLong(String str) { + Long format = (Long)predefinedClipboardNameMap.get(str); + if (format == null) { + format = Long.valueOf(RegisterClipboardFormat(str)); + } + return format; } + + protected abstract String getClipboardFormatName(long format); + + public boolean isImageFormat(long format) { + return format == CF_DIB || format == CF_ENHMETAFILE || + format == CF_METAFILEPICT || format == CF_PNG || + format == CF_JFIF; + } + + public boolean isLocaleDependentTextFormat(long format) { + return format == CF_TEXT || format == CFSTR_INETURL; + } + + public boolean isFileFormat(long format) { + return format == CF_HDROP; + } + +} + +enum EHTMLReadMode { + HTML_READ_ALL, + HTML_READ_FRAGMENT, + HTML_READ_SELECTION +} + +/** + * on decode: This stream takes an InputStream which provides data in CF_HTML format, + * strips off the description and context to extract the original HTML data. + * + * on encode: static convertToHTMLFormat is responsible for HTML clipboard header creation + */ +class HTMLCodec extends InputStream { + //static section + public static final String ENCODING = "UTF-8"; + + public static final String VERSION = "Version:"; + public static final String START_HTML = "StartHTML:"; + public static final String END_HTML = "EndHTML:"; + public static final String START_FRAGMENT = "StartFragment:"; + public static final String END_FRAGMENT = "EndFragment:"; + public static final String START_SELECTION = "StartSelection:"; //optional + public static final String END_SELECTION = "EndSelection:"; //optional + + public static final String START_FRAGMENT_CMT = ""; + public static final String END_FRAGMENT_CMT = ""; + public static final String SOURCE_URL = "SourceURL:"; + public static final String DEF_SOURCE_URL = "about:blank"; + + public static final String EOLN = "\r\n"; + + private static final String VERSION_NUM = "1.0"; + private static final int PADDED_WIDTH = 10; + + private static String toPaddedString(int n, int width) { + String string = "" + n; + int len = string.length(); + if (n >= 0 && len < width) { + char[] array = new char[width - len]; + Arrays.fill(array, '0'); + StringBuffer buffer = new StringBuffer(width); + buffer.append(array); + buffer.append(string); + string = buffer.toString(); + } + return string; + } + + /** + * convertToHTMLFormat adds the MS HTML clipboard header to byte array that + * contains the parameters pairs. + * + * The consequence of parameters is fixed, but some or all of them could be + * omitted. One parameter per one text line. + * It looks like that: + * + * Version:1.0\r\n -- current supported version + * StartHTML:000000192\r\n -- shift in array to the first byte after the header + * EndHTML:000000757\r\n -- shift in array of last byte for HTML syntax analysis + * StartFragment:000000396\r\n -- shift in array jast after + * EndFragment:000000694\r\n -- shift in array before start + * StartSelection:000000398\r\n -- shift in array of the first char in copied selection + * EndSelection:000000692\r\n -- shift in array of the last char in copied selection + * SourceURL:http://sun.com/\r\n -- base URL for related referenses + * .............................. + * ^ ^ ^ ^^ ^ + * \ StartHTML | \-StartSelection | \EndFragment EndHTML/ + * \-StartFragment \EndSelection + * + *Combinations with tags sequence + *...... + * or + *......... + * are vailid too. + */ + public static byte[] convertToHTMLFormat(byte[] bytes) { + // Calculate section offsets + String htmlPrefix = ""; + String htmlSuffix = ""; + { + //we have extend the fragment to full HTML document correctly + //to avoid HTML and BODY tags doubling + String stContext = new String(bytes); + String stUpContext = stContext.toUpperCase(); + if( -1 == stUpContext.indexOf(""; + htmlSuffix = "" + htmlSuffix; + }; + }; + htmlPrefix = htmlPrefix + START_FRAGMENT_CMT; + htmlSuffix = END_FRAGMENT_CMT + htmlSuffix; + } + + String stBaseUrl = DEF_SOURCE_URL; + int nStartHTML = + VERSION.length() + VERSION_NUM.length() + EOLN.length() + + START_HTML.length() + PADDED_WIDTH + EOLN.length() + + END_HTML.length() + PADDED_WIDTH + EOLN.length() + + START_FRAGMENT.length() + PADDED_WIDTH + EOLN.length() + + END_FRAGMENT.length() + PADDED_WIDTH + EOLN.length() + + SOURCE_URL.length() + stBaseUrl.length() + EOLN.length() + ; + int nStartFragment = nStartHTML + htmlPrefix.length(); + int nEndFragment = nStartFragment + bytes.length - 1; + int nEndHTML = nEndFragment + htmlSuffix.length(); + + StringBuilder header = new StringBuilder( + nStartFragment + + START_FRAGMENT_CMT.length() + ); + //header + header.append(VERSION); + header.append(VERSION_NUM); + header.append(EOLN); + + header.append(START_HTML); + header.append(toPaddedString(nStartHTML, PADDED_WIDTH)); + header.append(EOLN); + + header.append(END_HTML); + header.append(toPaddedString(nEndHTML, PADDED_WIDTH)); + header.append(EOLN); + + header.append(START_FRAGMENT); + header.append(toPaddedString(nStartFragment, PADDED_WIDTH)); + header.append(EOLN); + + header.append(END_FRAGMENT); + header.append(toPaddedString(nEndFragment, PADDED_WIDTH)); + header.append(EOLN); + + header.append(SOURCE_URL); + header.append(stBaseUrl); + header.append(EOLN); + + //HTML + header.append(htmlPrefix); + + byte[] headerBytes = null, trailerBytes = null; + + try { + headerBytes = new String(header).getBytes(ENCODING); + trailerBytes = htmlSuffix.getBytes(ENCODING); + } catch (UnsupportedEncodingException cannotHappen) { + } + + byte[] retval = new byte[headerBytes.length + bytes.length + + trailerBytes.length]; + + System.arraycopy(headerBytes, 0, retval, 0, headerBytes.length); + System.arraycopy(bytes, 0, retval, headerBytes.length, + bytes.length - 1); + System.arraycopy(trailerBytes, 0, retval, + headerBytes.length + bytes.length - 1, + trailerBytes.length); + retval[retval.length-1] = 0; + + return retval; + } + + //////////////////////////////////// + //decoder instance data and methods: + + private final BufferedInputStream bufferedStream; + private boolean descriptionParsed = false; + private boolean closed = false; + + // InputStreamReader uses an 8K buffer. The size is not customizable. + public static final int BYTE_BUFFER_LEN = 8192; + + // CharToByteUTF8.getMaxBytesPerChar returns 3, so we should not buffer + // more chars than 3 times the number of bytes we can buffer. + public static final int CHAR_BUFFER_LEN = BYTE_BUFFER_LEN / 3; + + private static final String FAILURE_MSG = + "Unable to parse HTML description: "; + private static final String INVALID_MSG = + " invalid"; + + //HTML header mapping: + private long iHTMLStart,// StartHTML -- shift in array to the first byte after the header + iHTMLEnd, // EndHTML -- shift in array of last byte for HTML syntax analysis + iFragStart,// StartFragment -- shift in array jast after + iFragEnd, // EndFragment -- shift in array before start + iSelStart, // StartSelection -- shift in array of the first char in copied selection + iSelEnd; // EndSelection -- shift in array of the last char in copied selection + private String stBaseURL; // SourceURL -- base URL for related referenses + private String stVersion; // Version -- current supported version + + //Stream reader markers: + private long iStartOffset, + iEndOffset, + iReadCount; + + private EHTMLReadMode readMode; + + public HTMLCodec( + InputStream _bytestream, + EHTMLReadMode _readMode) throws IOException + { + bufferedStream = new BufferedInputStream(_bytestream, BYTE_BUFFER_LEN); + readMode = _readMode; + } + + public synchronized String getBaseURL() throws IOException + { + if( !descriptionParsed ) { + parseDescription(); + } + return stBaseURL; + } + public synchronized String getVersion() throws IOException + { + if( !descriptionParsed ) { + parseDescription(); + } + return stVersion; + } + + /** + * parseDescription parsing HTML clipboard header as it described in + * comment to convertToHTMLFormat + */ + private void parseDescription() throws IOException + { + stBaseURL = null; + stVersion = null; + + // initialization of array offset pointers + // to the same "uninitialized" state. + iHTMLEnd = + iHTMLStart = + iFragEnd = + iFragStart = + iSelEnd = + iSelStart = -1; + + bufferedStream.mark(BYTE_BUFFER_LEN); + String astEntries[] = new String[] { + //common + VERSION, + START_HTML, + END_HTML, + START_FRAGMENT, + END_FRAGMENT, + //ver 1.0 + START_SELECTION, + END_SELECTION, + SOURCE_URL + }; + BufferedReader bufferedReader = new BufferedReader( + new InputStreamReader( + bufferedStream, + ENCODING + ), + CHAR_BUFFER_LEN + ); + long iHeadSize = 0; + long iCRSize = EOLN.length(); + int iEntCount = astEntries.length; + boolean bContinue = true; + + for( int iEntry = 0; iEntry < iEntCount; ++iEntry ){ + String stLine = bufferedReader.readLine(); + if( null==stLine ) { + break; + } + //some header entries are optional, but the order is fixed. + for( ; iEntry < iEntCount; ++iEntry ){ + if( !stLine.startsWith(astEntries[iEntry]) ) { + continue; + } + iHeadSize += stLine.length() + iCRSize; + String stValue = stLine.substring(astEntries[iEntry].length()).trim(); + if( null!=stValue ) { + try{ + switch( iEntry ){ + case 0: + stVersion = stValue; + break; + case 1: + iHTMLStart = Integer.parseInt(stValue); + break; + case 2: + iHTMLEnd = Integer.parseInt(stValue); + break; + case 3: + iFragStart = Integer.parseInt(stValue); + break; + case 4: + iFragEnd = Integer.parseInt(stValue); + break; + case 5: + iSelStart = Integer.parseInt(stValue); + break; + case 6: + iSelEnd = Integer.parseInt(stValue); + break; + case 7: + stBaseURL = stValue; + break; + }; + } catch ( NumberFormatException e ) { + throw new IOException(FAILURE_MSG + astEntries[iEntry]+ " value " + e + INVALID_MSG); + } + } + break; + } + } + //some entries could absent in HTML header, + //so we have find they by another way. + if( -1 == iHTMLStart ) + iHTMLStart = iHeadSize; + if( -1 == iFragStart ) + iFragStart = iHTMLStart; + if( -1 == iFragEnd ) + iFragEnd = iHTMLEnd; + if( -1 == iSelStart ) + iSelStart = iFragStart; + if( -1 == iSelEnd ) + iSelEnd = iFragEnd; + + //one of possible modes + switch( readMode ){ + case HTML_READ_ALL: + iStartOffset = iHTMLStart; + iEndOffset = iHTMLEnd; + break; + case HTML_READ_FRAGMENT: + iStartOffset = iFragStart; + iEndOffset = iFragEnd; + break; + case HTML_READ_SELECTION: + default: + iStartOffset = iSelStart; + iEndOffset = iSelEnd; + break; + } + + bufferedStream.reset(); + if( -1 == iStartOffset ){ + throw new IOException(FAILURE_MSG + "invalid HTML format."); + } + iReadCount = bufferedStream.skip(iStartOffset); + if( iStartOffset != iReadCount ){ + throw new IOException(FAILURE_MSG + "Byte stream ends in description."); + } + descriptionParsed = true; + } + + public synchronized int read() throws IOException { + if( closed ){ + throw new IOException("Stream closed"); + } + + if( !descriptionParsed ){ + parseDescription(); + } + if( -1 != iEndOffset && iReadCount >= iEndOffset ) { + return -1; + } + + int retval = bufferedStream.read(); + if( retval == -1 ) { + return -1; + } + ++iReadCount; + return retval; + } + + public synchronized void close() throws IOException { + if( !closed ){ + closed = true; + bufferedStream.close(); + } + } +} diff --git a/openjdk/sun/awt/Win32FontManager.java b/openjdk/sun/awt/Win32FontManager.java new file mode 100644 index 0000000..20dbe48 --- /dev/null +++ b/openjdk/sun/awt/Win32FontManager.java @@ -0,0 +1,30 @@ +/* + Copyright (C) 2011 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.awt; + +import sun.font.SunFontManager; + +public class Win32FontManager extends SunFontManager { + +} diff --git a/openjdk/sun/awt/X11FontManager.java b/openjdk/sun/awt/X11FontManager.java new file mode 100644 index 0000000..1f1ab31 --- /dev/null +++ b/openjdk/sun/awt/X11FontManager.java @@ -0,0 +1,30 @@ +/* + Copyright (C) 2011 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.awt; + +import sun.font.SunFontManager; + +public class X11FontManager extends SunFontManager { + +} diff --git a/openjdk/sun/awt/image/ByteInterleavedRaster.java b/openjdk/sun/awt/image/ByteInterleavedRaster.java new file mode 100644 index 0000000..b7b6298 --- /dev/null +++ b/openjdk/sun/awt/image/ByteInterleavedRaster.java @@ -0,0 +1,1331 @@ +/* + * Copyright (c) 1998, 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.awt.image; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.awt.image.RasterFormatException; +import java.awt.image.SampleModel; +import java.awt.image.ComponentSampleModel; +import java.awt.image.PixelInterleavedSampleModel; +import java.awt.image.SinglePixelPackedSampleModel; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.Rectangle; +import java.awt.Point; + +/** + * This class defines a Raster with pixels consisting of one or more + * 8-bit data elements stored in close proximity to each other in a + * single byte array. + *

+ * The bit precision per data element is that of the data type (that + * is, the bit precision for this Raster is 8). There is only one + * pixel stride and one scanline stride for all bands. This type of + * Raster can be used with a ComponentColorModel if there are multiple + * bands, or an IndexColorModel if there is only one band. + * + */ +public class ByteInterleavedRaster extends ByteComponentRaster { + + /** True if the data offsets range from 0 to (pixelStride - 1) in order. */ + boolean inOrder; + + /** + * The DataBuffer offset, minus sampleModelTranslateX*pixelStride, + * minus sampleModelTranslateY*scanlineStride, used to calculate + * pixel offsets. + */ + int dbOffset; + int dbOffsetPacked; + + /** True if a SinglePixelPackedSampleModel is being used. */ + boolean packed = false; + + /** If packed == true, the SampleModel's bit masks. */ + int[] bitMasks; + + /** If packed == true, the SampleModel's bit offsets. */ + int[] bitOffsets; + + /** A cached copy of minX + width for use in bounds checks. */ + private int maxX; + + /** A cached copy of minY + height for use in bounds checks. */ + private int maxY; + + /** + * Constructs a ByteInterleavedRaster with the given SampleModel. + * The Raster's upper left corner is origin and it is the same + * size as the SampleModel. A DataBuffer large enough to describe the + * Raster is automatically created. SampleModel must be of type + * SinglePixelPackedSampleModel or InterleavedSampleModel. + * @param sampleModel The SampleModel that specifies the layout. + * @param origin The Point that specified the origin. + */ + public ByteInterleavedRaster(SampleModel sampleModel, Point origin) { + this(sampleModel, + sampleModel.createDataBuffer(), + new Rectangle(origin.x, + origin.y, + sampleModel.getWidth(), + sampleModel.getHeight()), + origin, + null); + } + + /** + * Constructs a ByteInterleavedRaster with the given SampleModel + * and DataBuffer. The Raster's upper left corner is origin and + * it is the same size as the SampleModel. The DataBuffer is not + * initialized and must be a DataBufferByte compatible with SampleModel. + * SampleModel must be of type SinglePixelPackedSampleModel + * or InterleavedSampleModel. + * @param sampleModel The SampleModel that specifies the layout. + * @param dataBuffer The DataBufferShort that contains the image data. + * @param origin The Point that specifies the origin. + */ + public ByteInterleavedRaster(SampleModel sampleModel, + DataBuffer dataBuffer, + Point origin) { + this(sampleModel, + dataBuffer, + new Rectangle(origin.x, + origin.y, + sampleModel.getWidth(), + sampleModel.getHeight()), + origin, + null); + } + + /*** Analyzes a ComponentSampleModel to determine if it can function + * as a PixelInterleavedSampleModel. In order to do so, it must use + * only bank 0 of its DataBuffer, and the data offsets must span a range + * of less than pixelStride. + * + *

These properties are trivially true for a 1-banded SampleModel. + */ + private boolean isInterleaved(ComponentSampleModel sm) { + // Analyze ComponentSampleModel to determine if it has the + // properties of a PixelInterleavedSampleModel + + int numBands = sampleModel.getNumBands(); + if (numBands == 1) { + return true; + } + + // Determine banks used + int[] bankIndices = sm.getBankIndices(); + for (int i = 0; i < numBands; i++) { + if (bankIndices[i] != 0) { + return false; + } + } + + // Determine range of band offsets + int[] bandOffsets = sm.getBandOffsets(); + int minOffset = bandOffsets[0]; + int maxOffset = minOffset; + for (int i = 1; i < numBands; i++) { + int offset = bandOffsets[i]; + if (offset < minOffset) { + minOffset = offset; + } + if (offset > maxOffset) { + maxOffset = offset; + } + } + if (maxOffset - minOffset >= sm.getPixelStride()) { + return false; + } + + return true; + } + + /** + * Constructs a ByteInterleavedRaster with the given SampleModel, + * DataBuffer, and parent. DataBuffer must be a DataBufferByte and + * SampleModel must be of type SinglePixelPackedSampleModel + * or InterleavedSampleModel. + * When translated into the base Raster's + * coordinate system, aRegion must be contained by the base Raster. + * Origin is the coordinate in the new Raster's coordinate system of + * the origin of the base Raster. (The base Raster is the Raster's + * ancestor which has no parent.) + * + * Note that this constructor should generally be called by other + * constructors or create methods, it should not be used directly. + * @param sampleModel The SampleModel that specifies the layout. + * @param dataBuffer The DataBufferShort that contains the image data. + * @param aRegion The Rectangle that specifies the image area. + * @param origin The Point that specifies the origin. + * @param parent The parent (if any) of this raster. + */ + public ByteInterleavedRaster(SampleModel sampleModel, + DataBuffer dataBuffer, + Rectangle aRegion, + Point origin, + ByteInterleavedRaster parent) { + super(sampleModel, dataBuffer, aRegion, origin, parent); + this.maxX = minX + width; + this.maxY = minY + height; + + if (!(dataBuffer instanceof DataBufferByte)) { + throw new RasterFormatException("ByteInterleavedRasters must have " + + "byte DataBuffers"); + } + + DataBufferByte dbb = (DataBufferByte)dataBuffer; + this.data = stealData(dbb, 0); + + int xOffset = aRegion.x - origin.x; + int yOffset = aRegion.y - origin.y; + if (sampleModel instanceof PixelInterleavedSampleModel || + (sampleModel instanceof ComponentSampleModel && + isInterleaved((ComponentSampleModel)sampleModel))) { + ComponentSampleModel csm = (ComponentSampleModel)sampleModel; + this.scanlineStride = csm.getScanlineStride(); + this.pixelStride = csm.getPixelStride(); + this.dataOffsets = csm.getBandOffsets(); + for (int i = 0; i < getNumDataElements(); i++) { + dataOffsets[i] += xOffset*pixelStride+yOffset*scanlineStride; + } + } else if (sampleModel instanceof SinglePixelPackedSampleModel) { + SinglePixelPackedSampleModel sppsm = + (SinglePixelPackedSampleModel)sampleModel; + this.packed = true; + this.bitMasks = sppsm.getBitMasks(); + this.bitOffsets = sppsm.getBitOffsets(); + this.scanlineStride = sppsm.getScanlineStride(); + this.pixelStride = 1; + this.dataOffsets = new int[1]; + this.dataOffsets[0] = dbb.getOffset(); + dataOffsets[0] += xOffset*pixelStride+yOffset*scanlineStride; + } else { + throw new RasterFormatException("ByteInterleavedRasters must " + + "have PixelInterleavedSampleModel, SinglePixelPackedSampleModel"+ + " or interleaved ComponentSampleModel. Sample model is " + + sampleModel); + } + this.bandOffset = this.dataOffsets[0]; + + this.dbOffsetPacked = dataBuffer.getOffset() - + sampleModelTranslateY*scanlineStride - + sampleModelTranslateX*pixelStride; + this.dbOffset = dbOffsetPacked - + (xOffset*pixelStride+yOffset*scanlineStride); + + // Set inOrder to true if the data elements are in order and + // have no gaps between them + this.inOrder = false; + if (numDataElements == pixelStride) { + inOrder = true; + for (int i = 1; i < numDataElements; i++) { + if (dataOffsets[i] - dataOffsets[0] != i) { + inOrder = false; + break; + } + } + } + + verify(); + } + + /** + * Returns a copy of the data offsets array. For each band the data offset + * is the index into the band's data array, of the first sample of the + * band. + */ + public int[] getDataOffsets() { + return (int[]) dataOffsets.clone(); + } + + /** + * Returns the data offset for the specified band. The data offset + * is the index into the data array + * in which the first sample of the first scanline is stored. + * @param band The band whose offset is returned. + */ + public int getDataOffset(int band) { + return dataOffsets[band]; + } + + /** + * Returns the scanline stride -- the number of data array elements between + * a given sample and the sample in the same column of the next row in the + * same band. + */ + public int getScanlineStride() { + return scanlineStride; + } + + /** + * Returns pixel stride -- the number of data array elements between two + * samples for the same band on the same scanline. + */ + public int getPixelStride() { + return pixelStride; + } + + /** + * Returns a reference to the data array. + */ + public byte[] getDataStorage() { + return data; + } + + /** + * Returns the data elements for all bands at the specified + * location. + * An ArrayIndexOutOfBounds exception will be thrown at runtime + * if the pixel coordinate is out of bounds. + * A ClassCastException will be thrown if the input object is non null + * and references anything other than an array of transferType. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param outData An object reference to an array of type defined by + * getTransferType() and length getNumDataElements(). + * If null an array of appropriate type and size will be + * allocated. + * @return An object reference to an array of type defined by + * getTransferType() with the request pixel data. + */ + public Object getDataElements(int x, int y, Object obj) { + if ((x < this.minX) || (y < this.minY) || + (x >= this.maxX) || (y >= this.maxY)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + byte outData[]; + if (obj == null) { + outData = new byte[numDataElements]; + } else { + outData = (byte[])obj; + } + int off = (y-minY)*scanlineStride + + (x-minX)*pixelStride; + + for (int band = 0; band < numDataElements; band++) { + outData[band] = data[dataOffsets[band] + off]; + } + + return outData; + } + + /** + * Returns an array of data elements from the specified rectangular + * region. + * An ArrayIndexOutOfBounds exception will be thrown at runtime + * if the pixel coordinates are out of bounds. + * A ClassCastException will be thrown if the input object is non null + * and references anything other than an array of transferType. + *

+     *       byte[] bandData = (byte[])raster.getDataElements(x, y, w, h, null);
+     *       int numDataElements = raster.getNumDataElements();
+     *       byte[] pixel = new byte[numDataElements];
+     *       // To find a data element at location (x2, y2)
+     *       System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
+     *                        pixel, 0, numDataElements);
+     * 
+ * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param width Width of the pixel rectangle. + * @param height Height of the pixel rectangle. + * @param outData An object reference to an array of type defined by + * getTransferType() and length w*h*getNumDataElements(). + * If null an array of appropriate type and size will be + * allocated. + * @return An object reference to an array of type defined by + * getTransferType() with the request pixel data. + */ + public Object getDataElements(int x, int y, int w, int h, Object obj) { + return getByteData(x, y, w, h, (byte[])obj); + } + + /** + * Returns a byte array of data elements from the specified rectangular + * region for the specified band. + * An ArrayIndexOutOfBounds exception will be thrown at runtime + * if the pixel coordinates are out of bounds. + *
+     *       byte[] bandData = raster.getByteData(x, y, w, h, null);
+     *       // To find the data element at location (x2, y2)
+     *       byte bandElement = bandData[((y2-y)*w + (x2-x))];
+     * 
+ * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param width Width of the pixel rectangle. + * @param height Height of the pixel rectangle. + * @param band The band to return. + * @param outData If non-null, data elements for all bands + * at the specified location are returned in this array. + * @return Data array with data elements for all bands. + */ + public byte[] getByteData(int x, int y, int w, int h, + int band, byte[] outData) { + // Bounds check for 'band' will be performed automatically + if ((x < this.minX) || (y < this.minY) || + (x + w > this.maxX) || (y + h > this.maxY)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + if (outData == null) { + outData = new byte[w*h]; + } + int yoff = (y-minY)*scanlineStride + + (x-minX)*pixelStride + dataOffsets[band]; + int xoff; + int off = 0; + int xstart; + int ystart; + + if (pixelStride == 1) { + if (scanlineStride == w) { + System.arraycopy(data, yoff, outData, 0, w*h); + } else { + for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { + System.arraycopy(data, yoff, outData, off, w); + off += w; + } + } + } else { + for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { + xoff = yoff; + for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { + outData[off++] = data[xoff]; + } + } + } + + return outData; + } + + /** + * Returns a byte array of data elements from the specified rectangular + * region. + * An ArrayIndexOutOfBounds exception will be thrown at runtime + * if the pixel coordinates are out of bounds. + *
+     *       byte[] bandData = raster.getByteData(x, y, w, h, null);
+     *       int numDataElements = raster.getnumDataElements();
+     *       byte[] pixel = new byte[numDataElements];
+     *       // To find a data element at location (x2, y2)
+     *       System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
+     *                        pixel, 0, numDataElements);
+     * 
+ * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param width Width of the pixel rectangle. + * @param height Height of the pixel rectangle. + * @param outData If non-null, data elements for all bands + * at the specified location are returned in this array. + * @return Data array with data elements for all bands. + */ + public byte[] getByteData(int x, int y, int w, int h, byte[] outData) { + if ((x < this.minX) || (y < this.minY) || + (x + w > this.maxX) || (y + h > this.maxY)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + if (outData == null) { + outData = new byte[numDataElements*w*h]; + } + int yoff = (y-minY)*scanlineStride + + (x-minX)*pixelStride; + int xoff; + int off = 0; + int xstart; + int ystart; + + if (inOrder) { + yoff += dataOffsets[0]; + int rowBytes = w*pixelStride; + if (scanlineStride == rowBytes) { + System.arraycopy(data, yoff, outData, off, rowBytes*h); + } else { + for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { + System.arraycopy(data, yoff, outData, off, rowBytes); + off += rowBytes; + } + } + } else if (numDataElements == 1) { + yoff += dataOffsets[0]; + for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { + xoff = yoff; + for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { + outData[off++] = data[xoff]; + } + } + } else if (numDataElements == 2) { + yoff += dataOffsets[0]; + int d1 = dataOffsets[1] - dataOffsets[0]; + for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { + xoff = yoff; + for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { + outData[off++] = data[xoff]; + outData[off++] = data[xoff + d1]; + } + } + } else if (numDataElements == 3) { + yoff += dataOffsets[0]; + int d1 = dataOffsets[1] - dataOffsets[0]; + int d2 = dataOffsets[2] - dataOffsets[0]; + for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { + xoff = yoff; + for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { + outData[off++] = data[xoff]; + outData[off++] = data[xoff + d1]; + outData[off++] = data[xoff + d2]; + } + } + } else if (numDataElements == 4) { + yoff += dataOffsets[0]; + int d1 = dataOffsets[1] - dataOffsets[0]; + int d2 = dataOffsets[2] - dataOffsets[0]; + int d3 = dataOffsets[3] - dataOffsets[0]; + for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { + xoff = yoff; + for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { + outData[off++] = data[xoff]; + outData[off++] = data[xoff + d1]; + outData[off++] = data[xoff + d2]; + outData[off++] = data[xoff + d3]; + } + } + } else { + for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { + xoff = yoff; + for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { + for (int c = 0; c < numDataElements; c++) { + outData[off++] = data[dataOffsets[c] + xoff]; + } + } + } + } + + return outData; + } + + /** + * Stores the data elements for all bands at the specified location. + * An ArrayIndexOutOfBounds exception will be thrown at runtime + * if the pixel coordinate is out of bounds. + * A ClassCastException will be thrown if the input object is non null + * and references anything other than an array of transferType. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param inData An object reference to an array of type defined by + * getTransferType() and length getNumDataElements() + * containing the pixel data to place at x,y. + */ + public void setDataElements(int x, int y, Object obj) { + if ((x < this.minX) || (y < this.minY) || + (x >= this.maxX) || (y >= this.maxY)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + byte inData[] = (byte[])obj; + int off = (y-minY)*scanlineStride + + (x-minX)*pixelStride; + + dataBuffer.markBitmapDirty(); + for (int i = 0; i < numDataElements; i++) { + data[dataOffsets[i] + off] = inData[i]; + } + + markDirty(); + } + + /** + * Stores the Raster data at the specified location. + * An ArrayIndexOutOfBounds exception will be thrown at runtime + * if the pixel coordinates are out of bounds. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param inRaster Raster of data to place at x,y location. + */ + public void setDataElements(int x, int y, Raster inRaster) { + int srcOffX = inRaster.getMinX(); + int srcOffY = inRaster.getMinY(); + int dstOffX = x + srcOffX; + int dstOffY = y + srcOffY; + int width = inRaster.getWidth(); + int height = inRaster.getHeight(); + if ((dstOffX < this.minX) || (dstOffY < this.minY) || + (dstOffX + width > this.maxX) || (dstOffY + height > this.maxY)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + + setDataElements(dstOffX, dstOffY, srcOffX, srcOffY, + width, height, inRaster); + } + + /** + * Stores the Raster data at the specified location. + * @param dstX The absolute X coordinate of the destination pixel + * that will receive a copy of the upper-left pixel of the + * inRaster + * @param dstY The absolute Y coordinate of the destination pixel + * that will receive a copy of the upper-left pixel of the + * inRaster + * @param srcX The absolute X coordinate of the upper-left source + * pixel that will be copied into this Raster + * @param srcY The absolute Y coordinate of the upper-left source + * pixel that will be copied into this Raster + * @param width The number of pixels to store horizontally + * @param height The number of pixels to store vertically + * @param inRaster Raster of data to place at x,y location. + */ + private void setDataElements(int dstX, int dstY, + int srcX, int srcY, + int width, int height, + Raster inRaster) { + // Assume bounds checking has been performed previously + if (width <= 0 || height <= 0) { + return; + } + + // Write inRaster (minX, minY) to (dstX, dstY) + + int srcOffX = inRaster.getMinX(); + int srcOffY = inRaster.getMinY(); + Object tdata = null; + + if (inRaster instanceof ByteInterleavedRaster) { + ByteInterleavedRaster bct = (ByteInterleavedRaster) inRaster; + byte[] bdata = bct.getDataStorage(); + // copy whole scanlines + if (inOrder && bct.inOrder && pixelStride == bct.pixelStride) { + int toff = bct.getDataOffset(0); + int tss = bct.getScanlineStride(); + int tps = bct.getPixelStride(); + + int srcOffset = toff + + (srcY - srcOffY) * tss + + (srcX - srcOffX) * tps; + int dstOffset = dataOffsets[0] + + (dstY - minY) * scanlineStride + + (dstX - minX) * pixelStride; + + dataBuffer.markBitmapDirty(); + int nbytes = width*pixelStride; + for (int tmpY=0; tmpY < height; tmpY++) { + System.arraycopy(bdata, srcOffset, + data, dstOffset, nbytes); + srcOffset += tss; + dstOffset += scanlineStride; + } + markDirty(); + return; + } + } + + for (int startY=0; startY < height; startY++) { + // Grab one scanline at a time + tdata = inRaster.getDataElements(srcOffX, srcOffY+startY, + width, 1, tdata); + setDataElements(dstX, dstY + startY, width, 1, tdata); + } + } + + /** + * Stores an array of data elements into the specified rectangular + * region. + * An ArrayIndexOutOfBounds exception will be thrown at runtime + * if the pixel coordinates are out of bounds. + * A ClassCastException will be thrown if the input object is non null + * and references anything other than an array of transferType. + * The data elements in the + * data array are assumed to be packed. That is, a data element + * for the nth band at location (x2, y2) would be found at: + *
+     *      inData[((y2-y)*w + (x2-x))*numDataElements + n]
+     * 
+ * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. + * @param inData An object reference to an array of type defined by + * getTransferType() and length w*h*getNumDataElements() + * containing the pixel data to place between x,y and + * x+h, y+h. + */ + public void setDataElements(int x, int y, int w, int h, Object obj) { + putByteData(x, y, w, h, (byte[])obj); + } + + /** + * Stores a byte array of data elements into the specified rectangular + * region for the specified band. + * An ArrayIndexOutOfBounds exception will be thrown at runtime + * if the pixel coordinates are out of bounds. + * The data elements in the + * data array are assumed to be packed. That is, a data element + * at location (x2, y2) would be found at: + *
+     *      inData[((y2-y)*w + (x2-x)) + n]
+     * 
+ * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. + * @param band The band to set. + * @param inData The data elements to be stored. + */ + public void putByteData(int x, int y, int w, int h, + int band, byte[] inData) { + // Bounds check for 'band' will be performed automatically + if ((x < this.minX) || (y < this.minY) || + (x + w > this.maxX) || (y + h > this.maxY)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int yoff = (y-minY)*scanlineStride + + (x-minX)*pixelStride + dataOffsets[band]; + int xoff; + int off = 0; + int xstart; + int ystart; + + dataBuffer.markBitmapDirty(); + if (pixelStride == 1) { + if (scanlineStride == w) { + System.arraycopy(inData, 0, data, yoff, w*h); + } + else { + for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { + System.arraycopy(inData, off, data, yoff, w); + off += w; + } + } + } + else { + for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { + xoff = yoff; + for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { + data[xoff] = inData[off++]; + } + } + } + + markDirty(); + } + + /** + * Stores a byte array of data elements into the specified rectangular + * region. + * An ArrayIndexOutOfBounds exception will be thrown at runtime + * if the pixel coordinates are out of bounds. + * The data elements in the + * data array are assumed to be packed. That is, a data element + * for the nth band at location (x2, y2) would be found at: + *
+     *      inData[((y2-y)*w + (x2-x))*numDataElements + n]
+     * 
+ * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. + * @param inData The data elements to be stored. + */ + public void putByteData(int x, int y, int w, int h, byte[] inData) { + if ((x < this.minX) || (y < this.minY) || + (x + w > this.maxX) || (y + h > this.maxY)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int yoff = (y-minY)*scanlineStride + + (x-minX)*pixelStride; + + int xoff; + int off = 0; + int xstart; + int ystart; + + dataBuffer.markBitmapDirty(); + if (inOrder) { + yoff += dataOffsets[0]; + int rowBytes = w*pixelStride; + if (rowBytes == scanlineStride) { + System.arraycopy(inData, 0, data, yoff, rowBytes*h); + } else { + for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { + System.arraycopy(inData, off, data, yoff, rowBytes); + off += rowBytes; + } + } + } else if (numDataElements == 1) { + yoff += dataOffsets[0]; + for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { + xoff = yoff; + for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { + data[xoff] = inData[off++]; + } + } + } else if (numDataElements == 2) { + yoff += dataOffsets[0]; + int d1 = dataOffsets[1] - dataOffsets[0]; + for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { + xoff = yoff; + for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { + data[xoff] = inData[off++]; + data[xoff + d1] = inData[off++]; + } + } + } else if (numDataElements == 3) { + yoff += dataOffsets[0]; + int d1 = dataOffsets[1] - dataOffsets[0]; + int d2 = dataOffsets[2] - dataOffsets[0]; + for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { + xoff = yoff; + for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { + data[xoff] = inData[off++]; + data[xoff + d1] = inData[off++]; + data[xoff + d2] = inData[off++]; + } + } + } else if (numDataElements == 4) { + yoff += dataOffsets[0]; + int d1 = dataOffsets[1] - dataOffsets[0]; + int d2 = dataOffsets[2] - dataOffsets[0]; + int d3 = dataOffsets[3] - dataOffsets[0]; + for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { + xoff = yoff; + for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { + data[xoff] = inData[off++]; + data[xoff + d1] = inData[off++]; + data[xoff + d2] = inData[off++]; + data[xoff + d3] = inData[off++]; + } + } + } else { + for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { + xoff = yoff; + for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { + for (int c = 0; c < numDataElements; c++) { + data[dataOffsets[c] + xoff] = inData[off++]; + } + } + } + } + + markDirty(); + } + + public int getSample(int x, int y, int b) { + if ((x < this.minX) || (y < this.minY) || + (x >= this.maxX) || (y >= this.maxY)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + if (packed) { + int offset = y*scanlineStride + x + dbOffsetPacked; + byte sample = data[offset]; + return (sample & bitMasks[b]) >>> bitOffsets[b]; + } else { + int offset = y*scanlineStride + x*pixelStride + dbOffset; + return data[offset + dataOffsets[b]] & 0xff; + } + } + + public void setSample(int x, int y, int b, int s) { + if ((x < this.minX) || (y < this.minY) || + (x >= this.maxX) || (y >= this.maxY)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + dataBuffer.markBitmapDirty(); + if (packed) { + int offset = y*scanlineStride + x + dbOffsetPacked; + int bitMask = bitMasks[b]; + + byte value = data[offset]; + value &= ~bitMask; + value |= (s << bitOffsets[b]) & bitMask; + data[offset] = value; + } else { + int offset = y*scanlineStride + x*pixelStride + dbOffset; + data[offset + dataOffsets[b]] = (byte)s; + } + + markDirty(); + } + + public int[] getSamples(int x, int y, int w, int h, int b, + int[] iArray) { + if ((x < this.minX) || (y < this.minY) || + (x + w > this.maxX) || (y + h > this.maxY)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int samples[]; + if (iArray != null) { + samples = iArray; + } else { + samples = new int [w*h]; + } + + int lineOffset = y*scanlineStride + x*pixelStride; + int dstOffset = 0; + + if (packed) { + lineOffset += dbOffsetPacked; + int bitMask = bitMasks[b]; + int bitOffset = bitOffsets[b]; + + for (int j = 0; j < h; j++) { + int sampleOffset = lineOffset; + for (int i = 0; i < w; i++) { + int value = data[sampleOffset++]; + samples[dstOffset++] = ((value & bitMask) >>> bitOffset); + } + lineOffset += scanlineStride; + } + } else { + lineOffset += dbOffset + dataOffsets[b]; + for (int j = 0; j < h; j++) { + int sampleOffset = lineOffset; + for (int i = 0; i < w; i++) { + samples[dstOffset++] = data[sampleOffset] & 0xff; + sampleOffset += pixelStride; + } + lineOffset += scanlineStride; + } + } + + return samples; + } + + public void setSamples(int x, int y, int w, int h, int b, int iArray[]) { + if ((x < this.minX) || (y < this.minY) || + (x + w > this.maxX) || (y + h > this.maxY)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int lineOffset = y*scanlineStride + x*pixelStride; + int srcOffset = 0; + + dataBuffer.markBitmapDirty(); + if (packed) { + lineOffset += dbOffsetPacked; + int bitMask = bitMasks[b]; + + for (int j = 0; j < h; j++) { + int sampleOffset = lineOffset; + for (int i = 0; i < w; i++) { + byte value = data[sampleOffset]; + value &= ~bitMask; + int sample = iArray[srcOffset++]; + value |= (sample << bitOffsets[b]) & bitMask; + data[sampleOffset++] = value; + } + lineOffset += scanlineStride; + } + } else { + lineOffset += dbOffset + dataOffsets[b]; + for (int i = 0; i < h; i++) { + int sampleOffset = lineOffset; + for (int j = 0; j < w; j++) { + data[sampleOffset] = (byte)iArray[srcOffset++]; + sampleOffset += pixelStride; + } + lineOffset += scanlineStride; + } + } + + markDirty(); + } + + public int[] getPixels(int x, int y, int w, int h, int[] iArray) { + if ((x < this.minX) || (y < this.minY) || + (x + w > this.maxX) || (y + h > this.maxY)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int pixels[]; + if (iArray != null) { + pixels = iArray; + } else { + pixels = new int[w*h*numBands]; + } + + int lineOffset = y*scanlineStride + x*pixelStride; + int dstOffset = 0; + + if (packed) { + lineOffset += dbOffsetPacked; + for (int j = 0; j < h; j++) { + for (int i = 0; i < w; i++) { + int value = data[lineOffset + i]; + for (int k = 0; k < numBands; k++) { + pixels[dstOffset++] = + (value & bitMasks[k]) >>> bitOffsets[k]; + } + } + lineOffset += scanlineStride; + } + } else { + lineOffset += dbOffset; + int d0 = dataOffsets[0]; + + if (numBands == 1) { + for (int j = 0; j < h; j++) { + int pixelOffset = lineOffset + d0; + for (int i = 0; i < w; i++) { + pixels[dstOffset++] = data[pixelOffset] & 0xff; + pixelOffset += pixelStride; + } + lineOffset += scanlineStride; + } + } else if (numBands == 2) { + int d1 = dataOffsets[1] - d0; + for (int j = 0; j < h; j++) { + int pixelOffset = lineOffset + d0; + for (int i = 0; i < w; i++) { + pixels[dstOffset++] = data[pixelOffset] & 0xff; + pixels[dstOffset++] = data[pixelOffset + d1] & 0xff; + pixelOffset += pixelStride; + } + lineOffset += scanlineStride; + } + } else if (numBands == 3) { + int d1 = dataOffsets[1] - d0; + int d2 = dataOffsets[2] - d0; + for (int j = 0; j < h; j++) { + int pixelOffset = lineOffset + d0; + for (int i = 0; i < w; i++) { + pixels[dstOffset++] = data[pixelOffset] & 0xff; + pixels[dstOffset++] = data[pixelOffset + d1] & 0xff; + pixels[dstOffset++] = data[pixelOffset + d2] & 0xff; + pixelOffset += pixelStride; + } + lineOffset += scanlineStride; + } + } else if (numBands == 4) { + int d1 = dataOffsets[1] - d0; + int d2 = dataOffsets[2] - d0; + int d3 = dataOffsets[3] - d0; + for (int j = 0; j < h; j++) { + int pixelOffset = lineOffset + d0; + for (int i = 0; i < w; i++) { + pixels[dstOffset++] = data[pixelOffset] & 0xff; + pixels[dstOffset++] = data[pixelOffset + d1] & 0xff; + pixels[dstOffset++] = data[pixelOffset + d2] & 0xff; + pixels[dstOffset++] = data[pixelOffset + d3] & 0xff; + pixelOffset += pixelStride; + } + lineOffset += scanlineStride; + } + } else { + for (int j = 0; j < h; j++) { + int pixelOffset = lineOffset; + for (int i = 0; i < w; i++) { + for (int k = 0; k < numBands; k++) { + pixels[dstOffset++] = + data[pixelOffset + dataOffsets[k]] & 0xff; + } + pixelOffset += pixelStride; + } + lineOffset += scanlineStride; + } + } + } + + return pixels; + } + + public void setPixels(int x, int y, int w, int h, int[] iArray) { + if ((x < this.minX) || (y < this.minY) || + (x + w > this.maxX) || (y + h > this.maxY)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int lineOffset = y*scanlineStride + x*pixelStride; + int srcOffset = 0; + + dataBuffer.markBitmapDirty(); + if (packed) { + lineOffset += dbOffsetPacked; + for (int j = 0; j < h; j++) { + for (int i = 0; i < w; i++) { + int value = 0; + for (int k = 0; k < numBands; k++) { + int srcValue = iArray[srcOffset++]; + value |= ((srcValue << bitOffsets[k]) + & bitMasks[k]); + } + data[lineOffset + i] = (byte)value; + } + lineOffset += scanlineStride; + } + } else { + lineOffset += dbOffset; + int d0 = dataOffsets[0]; + + if (numBands == 1) { + for (int j = 0; j < h; j++) { + int pixelOffset = lineOffset + d0; + for (int i = 0; i < w; i++) { + data[pixelOffset] = (byte)iArray[srcOffset++]; + pixelOffset += pixelStride; + } + lineOffset += scanlineStride; + } + } else if (numBands == 2) { + int d1 = dataOffsets[1] - d0; + for (int j = 0; j < h; j++) { + int pixelOffset = lineOffset + d0; + for (int i = 0; i < w; i++) { + data[pixelOffset] = (byte)iArray[srcOffset++]; + data[pixelOffset + d1] = (byte)iArray[srcOffset++]; + pixelOffset += pixelStride; + } + lineOffset += scanlineStride; + } + } else if (numBands == 3) { + int d1 = dataOffsets[1] - d0; + int d2 = dataOffsets[2] - d0; + for (int j = 0; j < h; j++) { + int pixelOffset = lineOffset + d0; + for (int i = 0; i < w; i++) { + data[pixelOffset] = (byte)iArray[srcOffset++]; + data[pixelOffset + d1] = (byte)iArray[srcOffset++]; + data[pixelOffset + d2] = (byte)iArray[srcOffset++]; + pixelOffset += pixelStride; + } + lineOffset += scanlineStride; + } + } else if (numBands == 4) { + int d1 = dataOffsets[1] - d0; + int d2 = dataOffsets[2] - d0; + int d3 = dataOffsets[3] - d0; + for (int j = 0; j < h; j++) { + int pixelOffset = lineOffset + d0; + for (int i = 0; i < w; i++) { + data[pixelOffset] = (byte)iArray[srcOffset++]; + data[pixelOffset + d1] = (byte)iArray[srcOffset++]; + data[pixelOffset + d2] = (byte)iArray[srcOffset++]; + data[pixelOffset + d3] = (byte)iArray[srcOffset++]; + pixelOffset += pixelStride; + } + lineOffset += scanlineStride; + } + } else { + for (int j = 0; j < h; j++) { + int pixelOffset = lineOffset; + for (int i = 0; i < w; i++) { + for (int k = 0; k < numBands; k++) { + data[pixelOffset + dataOffsets[k]] = + (byte)iArray[srcOffset++]; + } + pixelOffset += pixelStride; + } + lineOffset += scanlineStride; + } + } + } + + markDirty(); + } + + public void setRect(int dx, int dy, Raster srcRaster) { + if (!(srcRaster instanceof ByteInterleavedRaster)) { + super.setRect(dx, dy, srcRaster); + return; + } + + int width = srcRaster.getWidth(); + int height = srcRaster.getHeight(); + int srcOffX = srcRaster.getMinX(); + int srcOffY = srcRaster.getMinY(); + int dstOffX = dx+srcOffX; + int dstOffY = dy+srcOffY; + + // Clip to this raster + if (dstOffX < this.minX) { + int skipX = minX - dstOffX; + width -= skipX; + srcOffX += skipX; + dstOffX = this.minX; + } + if (dstOffY < this.minY) { + int skipY = this.minY - dstOffY; + height -= skipY; + srcOffY += skipY; + dstOffY = this.minY; + } + if (dstOffX+width > this.maxX) { + width = this.maxX - dstOffX; + } + if (dstOffY+height > this.maxY) { + height = this.maxY - dstOffY; + } + + setDataElements(dstOffX, dstOffY, + srcOffX, srcOffY, + width, height, srcRaster); + } + + + /** + * Creates a subraster given a region of the raster. The x and y + * coordinates specify the horizontal and vertical offsets + * from the upper-left corner of this raster to the upper-left corner + * of the subraster. A subset of the bands of the parent Raster may + * be specified. If this is null, then all the bands are present in the + * subRaster. A translation to the subRaster may also be specified. + * Note that the subraster will reference the same + * DataBuffer as the parent raster, but using different offsets. + * @param x X offset. + * @param y Y offset. + * @param width Width (in pixels) of the subraster. + * @param height Height (in pixels) of the subraster. + * @param x0 Translated X origin of the subraster. + * @param y0 Translated Y origin of the subraster. + * @param bandList Array of band indices. + * @exception RasterFormatException + * if the specified bounding box is outside of the parent raster. + */ + public Raster createChild(int x, int y, + int width, int height, + int x0, int y0, int[] bandList) { + WritableRaster newRaster = createWritableChild(x, y, + width, height, + x0, y0, + bandList); + return (Raster) newRaster; + } + + /** + * Creates a Writable subRaster given a region of the Raster. The x and y + * coordinates specify the horizontal and vertical offsets + * from the upper-left corner of this Raster to the upper-left corner + * of the subRaster. A subset of the bands of the parent Raster may + * be specified. If this is null, then all the bands are present in the + * subRaster. A translation to the subRaster may also be specified. + * Note that the subRaster will reference the same + * DataBuffer as the parent Raster, but using different offsets. + * @param x X offset. + * @param y Y offset. + * @param width Width (in pixels) of the subraster. + * @param height Height (in pixels) of the subraster. + * @param x0 Translated X origin of the subraster. + * @param y0 Translated Y origin of the subraster. + * @param bandList Array of band indices. + * @exception RasterFormatException + * if the specified bounding box is outside of the parent Raster. + */ + public WritableRaster createWritableChild(int x, int y, + int width, int height, + int x0, int y0, + int[] bandList) { + if (x < this.minX) { + throw new RasterFormatException("x lies outside the raster"); + } + if (y < this.minY) { + throw new RasterFormatException("y lies outside the raster"); + } + if ((x+width < x) || (x+width > this.minX + this.width)) { + throw new RasterFormatException("(x + width) is outside of Raster"); + } + if ((y+height < y) || (y+height > this.minY + this.height)) { + throw new RasterFormatException("(y + height) is outside of Raster"); + } + + SampleModel sm; + + if (bandList != null) + sm = sampleModel.createSubsetSampleModel(bandList); + else + sm = sampleModel; + + int deltaX = x0 - x; + int deltaY = y0 - y; + + return new ByteInterleavedRaster(sm, + dataBuffer, + new Rectangle(x0, y0, width, height), + new Point(sampleModelTranslateX+deltaX, + sampleModelTranslateY+deltaY), + this); + } + + /** + * Creates a Raster with the same layout but using a different + * width and height, and with new zeroed data arrays. + */ + public WritableRaster createCompatibleWritableRaster(int w, int h) { + if (w <= 0 || h <=0) { + throw new RasterFormatException("negative "+ + ((w <= 0) ? "width" : "height")); + } + + SampleModel sm = sampleModel.createCompatibleSampleModel(w, h); + + return new ByteInterleavedRaster(sm, new Point(0,0)); + + } + + /** + * Creates a Raster with the same layout and the same + * width and height, and with new zeroed data arrays. If + * the Raster is a subRaster, this will call + * createCompatibleRaster(width, height). + */ + public WritableRaster createCompatibleWritableRaster() { + return createCompatibleWritableRaster(width,height); + } + + public String toString() { + return new String ("ByteInterleavedRaster: width = "+width+" height = " + + height + +" #numDataElements "+numDataElements + // +" xOff = "+xOffset+" yOff = "+yOffset + +" dataOff[0] = "+dataOffsets[0]); + } + +// /** +// * For debugging... prints a region of a one-band ByteInterleavedRaster +// */ +// public void print(int x, int y, int w, int h) { +// // REMIND: Only works for 1 band! +// System.out.println(this); +// int offset = dataOffsets[0] + y*scanlineStride + x*pixelStride; +// int off; +// for (int yoff=0; yoff < h; yoff++, offset += scanlineStride) { +// off = offset; +// System.out.print("Line "+(y+yoff)+": "); +// for (int xoff = 0; xoff < w; xoff++, off+= pixelStride) { +// String s = Integer.toHexString(data[off]); +// if (s.length() == 8) { +// s = s.substring(6,8); +// } +// System.out.print(s+" "); +// } +// System.out.println(""); +// } +// } +} diff --git a/openjdk/sun/awt/image/GifImageDecoder.java b/openjdk/sun/awt/image/GifImageDecoder.java new file mode 100644 index 0000000..80f79e1 --- /dev/null +++ b/openjdk/sun/awt/image/GifImageDecoder.java @@ -0,0 +1,38 @@ +/* + Copyright (C) 2010 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.awt.image; + +import java.io.InputStream; + +/** + * Replace the same class from Sun with native parts. + * @author Volker Berlin + */ +public class GifImageDecoder extends IkvmImageDecoder{ + + GifImageDecoder(InputStreamImageSource src, InputStream is){ + super(src, is); + } + +} diff --git a/openjdk/sun/awt/image/IkvmImageDecoder.java b/openjdk/sun/awt/image/IkvmImageDecoder.java new file mode 100644 index 0000000..17be22b --- /dev/null +++ b/openjdk/sun/awt/image/IkvmImageDecoder.java @@ -0,0 +1,150 @@ +/* + Copyright (C) 2010 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.awt.image; + +import java.awt.image.*; +import java.io.IOException; +import java.io.InputStream; + +import cli.System.Drawing.Bitmap; +import cli.System.Drawing.Imaging.ImageLockMode; +import cli.System.Drawing.Imaging.PixelFormat; +import cli.System.IO.SeekOrigin; +import cli.System.IO.Stream; +import cli.System.NotSupportedException; +import ikvm.runtime.Util; + +abstract class IkvmImageDecoder extends ImageDecoder { + + IkvmImageDecoder(InputStreamImageSource src, InputStream is){ + super(src, is); + } + + @Override + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + public void produceImage() throws IOException, ImageFormatException{ + Stream stream = new Stream(){ + + @Override + public void Flush(){ + Util.throwException(new NotSupportedException()); + } + + @Override + public int Read(byte[] bytes, int off, int len){ + try{ + int count = input.read(bytes, off, len); + if( count < 0 ){ + return 0; + } + return count; + }catch(IOException ex){ + throw new RuntimeException(ex); + } + } + + @Override + public long Seek(long arg0, SeekOrigin arg1){ + Util.throwException(new NotSupportedException()); + return 0; + } + + @Override + public void SetLength(long arg0){ + Util.throwException(new NotSupportedException()); + } + + @Override + public void Write(byte[] arg0, int arg1, int arg2){ + Util.throwException(new NotSupportedException()); + } + + @Override + public boolean get_CanRead(){ + return true; + } + + @Override + public boolean get_CanSeek(){ + return false; + } + + @Override + public boolean get_CanWrite(){ + return true; + } + + @Override + public long get_Length(){ + try{ + return input.available(); + }catch(IOException ex){ + throw new RuntimeException(ex); + } + } + + @Override + public long get_Position(){ + Util.throwException(new NotSupportedException()); + return 0; + } + + @Override + public void set_Position(long arg0){ + Util.throwException(new NotSupportedException()); + } + + }; + try{ + Bitmap bitmap = new Bitmap(stream); + int width = bitmap.get_Width(); + int height = bitmap.get_Height(); + int size = width * height; + int[] pixelData = new int[size]; + + cli.System.Drawing.Rectangle rect = new cli.System.Drawing.Rectangle(0, 0, width, height); + cli.System.Drawing.Imaging.BitmapData data = bitmap.LockBits(rect, ImageLockMode.wrap(ImageLockMode.ReadOnly), PixelFormat.wrap(PixelFormat.Format32bppArgb)); + cli.System.IntPtr pixelPtr = data.get_Scan0(); + cli.System.Runtime.InteropServices.Marshal.Copy(pixelPtr, pixelData, 0, size); + bitmap.UnlockBits(data); + + //source. + + setDimensions(width, height); + ColorModel cm = ColorModel.getRGBdefault(); + setColorModel(cm); + //setHints(flags); + headerComplete(); + + setPixels(0,0,width,height, cm, pixelData,0,width); + imageComplete(ImageConsumer.STATICIMAGEDONE, true); + }catch(Throwable th){ + th.printStackTrace(); + imageComplete(ImageConsumer.IMAGEERROR|ImageConsumer.STATICIMAGEDONE, true); + throw new IOException(th); + } finally { + try { close(); } catch(Throwable e){e.printStackTrace();} + } + } +} diff --git a/openjdk/sun/awt/image/ImageRepresentation.java b/openjdk/sun/awt/image/ImageRepresentation.java new file mode 100644 index 0000000..962d46e --- /dev/null +++ b/openjdk/sun/awt/image/ImageRepresentation.java @@ -0,0 +1,421 @@ +/* + Copyright (C) 2009 Jeroen Frijters + Copyright (C) 2010 Volker Berlin (i-net software) + Copyright (C) 2011 Karsten Heinrich (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package sun.awt.image; + +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.ImageConsumer; +import java.awt.image.ImageObserver; +import java.util.Hashtable; + +import cli.System.Drawing.Bitmap; +import cli.System.Drawing.Imaging.BitmapData; +import cli.System.Drawing.Imaging.ImageLockMode; +import cli.System.Drawing.Imaging.PixelFormat; + +public class ImageRepresentation extends ImageWatched implements ImageConsumer{ + + private static final int DEFAULT_PIXEL_FORMAT = PixelFormat.Format32bppArgb; + InputStreamImageSource src; + ToolkitImage image; + + private int width = -1; + private int height = -1; + + private int availinfo; + + private BufferedImage bimage; + private cli.System.Drawing.Bitmap bitmap; + private int pixelFormat = DEFAULT_PIXEL_FORMAT; + + ImageRepresentation(ToolkitImage im){ + image = im; + + if (image.getSource() instanceof InputStreamImageSource) { + src = (InputStreamImageSource) image.getSource(); + } + } + + /* REMIND: Only used for Frame.setIcon - should use ImageWatcher instead */ + public synchronized void reconstruct(int flags) { + if (src != null) { + src.checkSecurity(null, false); + } + int missinginfo = flags & ~availinfo; + if ((availinfo & ImageObserver.ERROR) == 0 && missinginfo != 0) { + numWaiters++; + try { + startProduction(); + missinginfo = flags & ~availinfo; + while ((availinfo & ImageObserver.ERROR) == 0 && + missinginfo != 0) + { + try { + wait(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return; + } + missinginfo = flags & ~availinfo; + } + } finally { + decrementWaiters(); + } + } + } + + @Override + public void setDimensions(int w, int h){ + if (src != null) { + src.checkSecurity(null, false); + } + + image.setDimensions(w, h); +// bitmap = new cli.System.Drawing.Bitmap(w, h); + + newInfo(image, (ImageObserver.WIDTH | ImageObserver.HEIGHT), + 0, 0, w, h); + + if (w <= 0 || h <= 0) { + imageComplete(ImageConsumer.IMAGEERROR); + return; + } + + width = w; + height = h; + + availinfo |= ImageObserver.WIDTH | ImageObserver.HEIGHT; + } + + private Bitmap getBitmapRef(){ + if( bitmap == null ){ + bitmap = new Bitmap(width, height, PixelFormat.wrap(pixelFormat) ); + } + return bitmap; + } + + public int getWidth(){ + return width; + } + + public int getHeight(){ + return height; + } + + public BufferedImage getBufferedImage(){ + return bimage; + } + + @Override + public void setProperties(Hashtable props){ + // ignore it + + } + + @Override + public synchronized void setColorModel(ColorModel model){ + int newPixelFormat = getPixelFormatForColorModel(model); + if( model.getPixelSize() <= 8 ){ + newPixelFormat = DEFAULT_PIXEL_FORMAT; + } + if( newPixelFormat != pixelFormat && bitmap != null ){ + // force reconstruct of the bitmap due to a color model change + bitmap.Dispose(); + bitmap = null; + } + pixelFormat = newPixelFormat; + } + + @Override + public void setHints(int hintflags){ + // ignore it + } + + @Override + public void setPixels(int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize){ + int[] pixeli = new int[pixels.length]; + for (int i = 0; i < pixels.length; i++) + { + pixeli[i] = model.getRGB(pixels[i] & 0xff); + } + setPixels(x, y, w, h, model, pixeli, off, scansize); + } + + @Override + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + public void setPixels(int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize){ + // FIXME this method will fail for scan lines + if( x < 0) { + w -= x; + x = 0; + } + if (y < 0) { + h -= y; + y = 0; + } + if (w <= 0 || h <= 0) { + // nothing to set + return; + } + if ( off < 0 ) { + throw new java.lang.ArrayIndexOutOfBoundsException( "Data offset out of bounds." ); + } + long length = w * h; + if (length > pixels.length - off) + { + throw new java.lang.ArrayIndexOutOfBoundsException("Data offset out of bounds."); + } + synchronized (this) + { + int pixelFormat = getPixelFormatForColorModel( model ); + int bpp = model.getPixelSize(); + if( bpp == 32 ){ // 32 can be copies 1:1 using an int array + copyInt(x, y, w, h, pixels, off, pixelFormat); + }else if( bpp <= 8 ){ + // transform all pixels using the color model (for indexed color models) + int[] newData = new int[pixels.length]; + for( int i=0; i < newData.length; i++ ){ + newData[i] = model.getRGB(pixels[i]); + } + copyInt(x, y, w, h, pixels, off, DEFAULT_PIXEL_FORMAT); + }else { + // byte per scanline, must be a multitude of 4 + // see http://stackoverflow.com/questions/2185944/why-must-stride-in-the-system-drawing-bitmap-constructor-be-a-multiple-of-4 + int bytesPerLine = (bpp * w) / 8; + int scanLine = ((bytesPerLine + 3) / 4) * 4; + int offset = scanLine - bytesPerLine; + byte[] newData = new byte[h * scanLine]; + int position = 0; + int pixel; + for( int i=0; i> 8) & 0xFF); break; + case 24: newData[position] = (byte)(pixel & 0xFF); + newData[position + 1] = (byte)((pixel >> 8) & 0xFF); + newData[position + 2] = (byte)((pixel >> 16) & 0xFF); break; + } + position += bpp / 8; + if( position % scanLine == bytesPerLine ){ + position += offset; + } + } + copyByte(x, y, w, h, newData, off, pixelFormat, bpp); + } + } + + availinfo |= ImageObserver.SOMEBITS; + + // Can't do this here since we might need to transform/clip + // the region + if (((availinfo & ImageObserver.FRAMEBITS) == 0)) { + newInfo(image, ImageObserver.SOMEBITS, x, y, w, h); + } + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + private void copyInt(int x, int y, int w, int h, int[] pixels, int off, int pixelFormat ) { + BitmapData data = getBitmapRef().LockBits(new cli.System.Drawing.Rectangle(x, y, w, h), ImageLockMode.wrap(ImageLockMode.WriteOnly), PixelFormat.wrap(pixelFormat)); + cli.System.Runtime.InteropServices.Marshal.Copy(pixels, off, data.get_Scan0(), data.get_Width() * data.get_Height()); + getBitmapRef().UnlockBits(data); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + private void copyByte(int x, int y, int w, int h, byte[] pixels, int off, int pixelFormat, int bpp) { + BitmapData data = getBitmapRef().LockBits(new cli.System.Drawing.Rectangle(x, y, w, h), ImageLockMode.wrap(ImageLockMode.WriteOnly), PixelFormat.wrap(pixelFormat)); + cli.System.Runtime.InteropServices.Marshal.Copy(pixels, off, data.get_Scan0(), pixels.length); + getBitmapRef().UnlockBits(data); + } + + + private int getPixelFormatForColorModel( ColorModel cm ){ + if( cm == null ){ + return DEFAULT_PIXEL_FORMAT; // TODO is PixelFormat.Canonical better here? + } + int bpp = cm.getPixelSize(); + int[] sizes = cm.getComponentSize(); + switch( bpp ){ + case 1: return PixelFormat.Undefined; // Indexed is invalid and there is no 1bpp + case 4: return PixelFormat.Format4bppIndexed; + case 8: return PixelFormat.Format8bppIndexed; + case 16: + if( sizes.length <= 1) { + return PixelFormat.Format16bppGrayScale; + } + if( sizes.length == 3 ){ + if( sizes[0] == 5 && sizes[2] == 5 ){ + return sizes[1] == 5 ? PixelFormat.Format16bppRgb555 : PixelFormat.Format16bppRgb565; + } + } + if( sizes.length == 4 && cm.hasAlpha() ){ + return PixelFormat.Format16bppArgb1555; + } + break; + case 24: + return PixelFormat.Format24bppRgb; + case 32: + if(!cm.hasAlpha()){ + return PixelFormat.Format32bppRgb; + } else { + return cm.isAlphaPremultiplied() ? PixelFormat.Format32bppPArgb : PixelFormat.Format32bppArgb; + } + case 48: + return PixelFormat.Format48bppRgb; + case 64: + return cm.isAlphaPremultiplied() ? PixelFormat.Format64bppPArgb : PixelFormat.Format64bppArgb; + } + return PixelFormat.Undefined; + } + + private boolean consuming = false; + + public void imageComplete(int status) { + if (src != null) { + src.checkSecurity(null, false); + } + boolean done; + int info; + switch (status) { + default: + case ImageConsumer.IMAGEABORTED: + done = true; + info = ImageObserver.ABORT; + break; + case ImageConsumer.IMAGEERROR: + image.addInfo(ImageObserver.ERROR); + done = true; + info = ImageObserver.ERROR; + dispose(); + break; + case ImageConsumer.STATICIMAGEDONE: + done = true; + info = ImageObserver.ALLBITS; + break; + case ImageConsumer.SINGLEFRAMEDONE: + done = false; + info = ImageObserver.FRAMEBITS; + break; + } + synchronized (this) { + if (done) { + image.getSource().removeConsumer(this); + consuming = false; + } + if (bimage == null ) { + bimage = new BufferedImage(getBitmapRef()); + } + availinfo |= info; + notifyAll(); + } + + newInfo(image, info, 0, 0, width, height); + + image.infoDone(status); + } + + /*synchronized*/ void startProduction() { + if (!consuming) { + consuming = true; + image.getSource().startProduction(this); + } + } + + private int numWaiters; + + private synchronized void checkConsumption() { + if (isWatcherListEmpty() && numWaiters == 0 && + ((availinfo & ImageObserver.ALLBITS) == 0)) + { + dispose(); + } + } + + @Override + public synchronized void notifyWatcherListEmpty() { + checkConsumption(); + } + + private synchronized void decrementWaiters() { + --numWaiters; + checkConsumption(); + } + + public boolean prepare(ImageObserver iw) { + if (src != null) { + src.checkSecurity(null, false); + } + if ((availinfo & ImageObserver.ERROR) != 0) { + if (iw != null) { + iw.imageUpdate(image, ImageObserver.ERROR|ImageObserver.ABORT, + -1, -1, -1, -1); + } + return false; + } + boolean done = ((availinfo & ImageObserver.ALLBITS) != 0); + if (!done) { + addWatcher(iw); + startProduction(); + // Some producers deliver image data synchronously + done = ((availinfo & ImageObserver.ALLBITS) != 0); + } + return done; + } + + public int check(ImageObserver iw) { + + if (src != null) { + src.checkSecurity(null, false); + } + if ((availinfo & (ImageObserver.ERROR | ImageObserver.ALLBITS)) == 0) { + addWatcher(iw); + } + + return availinfo; + } + + synchronized void abort() { + image.getSource().removeConsumer(this); + consuming = false; + bimage = null; + bitmap = null; + + newInfo(image, ImageObserver.ABORT, -1, -1, -1, -1); + availinfo &= ~(ImageObserver.SOMEBITS + | ImageObserver.FRAMEBITS + | ImageObserver.ALLBITS + | ImageObserver.ERROR); + } + + synchronized void dispose() { + image.getSource().removeConsumer(this); + consuming = false; + availinfo &= ~(ImageObserver.SOMEBITS + | ImageObserver.FRAMEBITS + | ImageObserver.ALLBITS); + } +} diff --git a/openjdk/sun/awt/image/ImagingLib.java b/openjdk/sun/awt/image/ImagingLib.java new file mode 100644 index 0000000..104c3c4 --- /dev/null +++ b/openjdk/sun/awt/image/ImagingLib.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1997, 2007, 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.awt.image; + +import java.awt.geom.AffineTransform; +import java.awt.image.AffineTransformOp; +import java.awt.image.BufferedImage; +import java.awt.image.BufferedImageOp; +import java.awt.image.ByteLookupTable; +import java.awt.image.ConvolveOp; +import java.awt.image.Kernel; +import java.awt.image.LookupOp; +import java.awt.image.LookupTable; +import java.awt.image.RasterOp; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * This class provides a hook to access platform-specific + * imaging code. + * + * If the implementing class cannot handle the op, tile format or + * image format, the method will return null; + * If there is an error when processing the + * data, the implementing class may either return null + * (in which case our java code will be executed) or may throw + * an exception. + */ +public class ImagingLib { + + public static WritableRaster filter(RasterOp op, Raster src, + WritableRaster dst) { + return null; + } + + + public static BufferedImage filter(BufferedImageOp op, BufferedImage src, + BufferedImage dst) + { + return null; + } +} diff --git a/openjdk/sun/awt/image/IntegerInterleavedRaster.java b/openjdk/sun/awt/image/IntegerInterleavedRaster.java new file mode 100644 index 0000000..7a940a3 --- /dev/null +++ b/openjdk/sun/awt/image/IntegerInterleavedRaster.java @@ -0,0 +1,573 @@ +/* + * Copyright (c) 1998, 2013, 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.awt.image; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.awt.image.RasterFormatException; +import java.awt.image.SampleModel; +import java.awt.image.SinglePixelPackedSampleModel; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferInt; +import java.awt.Rectangle; +import java.awt.Point; + +/** + * This class defines a Raster with pixels consisting of one or more 32-bit + * data elements stored in close proximity to each other in a integer array. + * The bit precision per data element is that + * of the data type (that is, the bit precision for this raster is 32). + * There is only one pixel stride and one scanline stride for all + * bands. For a given pixel, all samples fit in N data elements and these + * N data elements hold samples for only one pixel. This type of Raster + * can be used with a PackedColorModel. + *

+ * For example, if there is only one data element per pixel, a + * SinglePixelPackedSampleModel can be used to represent multiple + * bands with a PackedColorModel (including a DirectColorModel) for + * color interpretation. + * + */ +public class IntegerInterleavedRaster extends IntegerComponentRaster { + + /** A cached copy of minX + width for use in bounds checks. */ + private int maxX; + + /** A cached copy of minY + height for use in bounds checks. */ + private int maxY; + + /** + * Constructs a IntegerInterleavedRaster with the given SampleModel. + * The Raster's upper left corner is origin and it is the same + * size as the SampleModel. A DataBuffer large enough to describe the + * Raster is automatically created. SampleModel must be of type + * SinglePixelPackedSampleModel. + * @param sampleModel The SampleModel that specifies the layout. + * @param origin The Point that specified the origin. + */ + public IntegerInterleavedRaster(SampleModel sampleModel, + Point origin) { + this(sampleModel, + sampleModel.createDataBuffer(), + new Rectangle(origin.x, + origin.y, + sampleModel.getWidth(), + sampleModel.getHeight()), + origin, + null); + } + + /** + * Constructs a IntegerInterleavedRaster with the given SampleModel + * and DataBuffer. The Raster's upper left corner is origin and + * it is the same sizes the SampleModel. The DataBuffer is not + * initialized and must be a DataBufferInt compatible with SampleModel. + * SampleModel must be of type SinglePixelPackedSampleModel. + * @param sampleModel The SampleModel that specifies the layout. + * @param dataBuffer The DataBufferInt that contains the image data. + * @param origin The Point that specifies the origin. + */ + public IntegerInterleavedRaster(SampleModel sampleModel, + DataBuffer dataBuffer, + Point origin) { + this(sampleModel, + dataBuffer, + new Rectangle(origin.x, + origin.y, + sampleModel.getWidth(), + sampleModel.getHeight()), + origin, + null); + } + + /** + * Constructs a IntegerInterleavedRaster with the given SampleModel, + * DataBuffer, and parent. DataBuffer must be a DataBufferInt and + * SampleModel must be of type SinglePixelPackedSampleModel. + * When translated into the base Raster's + * coordinate system, aRegion must be contained by the base Raster. + * Origin is the coodinate in the new Raster's coordinate system of + * the origin of the base Raster. (The base Raster is the Raster's + * ancestor which has no parent.) + * + * Note that this constructor should generally be called by other + * constructors or create methods, it should not be used directly. + * @param sampleModel The SampleModel that specifies the layout. + * @param dataBuffer The DataBufferInt that contains the image data. + * @param aRegion The Rectangle that specifies the image area. + * @param origin The Point that specifies the origin. + * @param parent The parent (if any) of this raster. + */ + public IntegerInterleavedRaster(SampleModel sampleModel, + DataBuffer dataBuffer, + Rectangle aRegion, + Point origin, + IntegerInterleavedRaster parent){ + super(sampleModel,dataBuffer,aRegion,origin,parent); + this.maxX = minX + width; + this.maxY = minY + height; + if (!(dataBuffer instanceof DataBufferInt)) { + throw new RasterFormatException("IntegerInterleavedRasters must have" + + "integer DataBuffers"); + } + DataBufferInt dbi = (DataBufferInt)dataBuffer; + this.data = stealData(dbi, 0); + + if (sampleModel instanceof SinglePixelPackedSampleModel) { + SinglePixelPackedSampleModel sppsm = + (SinglePixelPackedSampleModel)sampleModel; + this.scanlineStride = sppsm.getScanlineStride(); + this.pixelStride = 1; + this.dataOffsets = new int[1]; + this.dataOffsets[0] = dbi.getOffset(); + this.bandOffset = this.dataOffsets[0]; + int xOffset = aRegion.x - origin.x; + int yOffset = aRegion.y - origin.y; + dataOffsets[0] += xOffset+yOffset*scanlineStride; + this.numDataElems = sppsm.getNumDataElements(); + } else { + throw new RasterFormatException("IntegerInterleavedRasters must have"+ + " SinglePixelPackedSampleModel"); + } + verify(); + } + + + /** + * Returns a copy of the data offsets array. For each band the data offset + * is the index into the band's data array, of the first sample of the + * band. + */ + public int[] getDataOffsets() { + return (int[]) dataOffsets.clone(); + } + + /** + * Returns data offset for the specified band. The data offset + * is the index into the data array in which the first sample + * of the first scanline is stored. + */ + public int getDataOffset(int band) { + return dataOffsets[band]; + } + + + /** + * Returns the scanline stride -- the number of data array elements between + * a given sample and the sample in the same column of the next row. + */ + public int getScanlineStride() { + return scanlineStride; + } + + /** + * Returns pixel stride -- the number of data array elements between two + * samples for the same band on the same scanline. + */ + public int getPixelStride() { + return pixelStride; + } + + /** + * Returns a reference to the data array. + */ + public int[] getDataStorage() { + return data; + } + + /** + * Returns the data elements for all bands at the specified + * location. + * An ArrayIndexOutOfBounds exception will be thrown at runtime + * if the pixel coordinate is out of bounds. + * A ClassCastException will be thrown if the input object is non null + * and references anything other than an array of transferType. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param outData An object reference to an array of type defined by + * getTransferType() and length getNumDataElements(). + * If null an array of appropriate type and size will be + * allocated. + * @return An object reference to an array of type defined by + * getTransferType() with the request pixel data. + */ + public Object getDataElements(int x, int y, Object obj) { + if ((x < this.minX) || (y < this.minY) || + (x >= this.maxX) || (y >= this.maxY)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int outData[]; + if (obj == null) { + outData = new int[1]; + } else { + outData = (int[])obj; + } + int off = (y-minY)*scanlineStride + (x-minX) + dataOffsets[0]; + outData[0] = data[off]; + + return outData; + } + + + /** + * Returns an array of data elements from the specified rectangular + * region. + * An ArrayIndexOutOfBounds exception will be thrown at runtime + * if the pixel coordinates are out of bounds. + * A ClassCastException will be thrown if the input object is non null + * and references anything other than an array of transferType. +

+     *       int[] bandData = (int[])raster.getDataElements(x, y, w, h, null);
+     *       int numDataElements = raster.getNumDataElements();
+     *       int[] pixel = new int[numDataElements];
+     *       // To find a data element at location (x2, y2)
+     *       System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
+     *                        pixel, 0, numDataElements);
+     * 
+ * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param width Width of the pixel rectangle. + * @param height Height of the pixel rectangle. + * @param outData An object reference to an array of type defined by + * getTransferType() and length w*h*getNumDataElements(). + * If null an array of appropriate type and size will be + * allocated. + * @return An object reference to an array of type defined by + * getTransferType() with the request pixel data. + */ + public Object getDataElements(int x, int y, int w, int h, Object obj) { + if ((x < this.minX) || (y < this.minY) || + (x + w > this.maxX) || (y + h > this.maxY)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int outData[]; + if (obj instanceof int[]) { + outData = (int[])obj; + } else { + outData = new int[w*h]; + } + int yoff = (y-minY)*scanlineStride + (x-minX) + dataOffsets[0]; + int off = 0; + + for (int ystart = 0; ystart < h; ystart++) { + System.arraycopy(data, yoff, outData, off, w); + off += w; + yoff += scanlineStride; + } + + return outData; + } + + + /** + * Stores the data elements for all bands at the specified location. + * An ArrayIndexOutOfBounds exception will be thrown at runtime + * if the pixel coordinate is out of bounds. + * A ClassCastException will be thrown if the input object is non null + * and references anything other than an array of transferType. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param inData An object reference to an array of type defined by + * getTransferType() and length getNumDataElements() + * containing the pixel data to place at x,y. + */ + public void setDataElements(int x, int y, Object obj) { + if ((x < this.minX) || (y < this.minY) || + (x >= this.maxX) || (y >= this.maxY)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int inData[] = (int[])obj; + + int off = (y-minY)*scanlineStride + (x-minX) + dataOffsets[0]; + + dataBuffer.markBitmapDirty(); + data[off] = inData[0]; + + markDirty(); + } + + + /** + * Stores the Raster data at the specified location. + * The transferType of the inputRaster must match this raster. + * An ArrayIndexOutOfBoundsException will be thrown at runtime + * if the pixel coordinates are out of bounds. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param inRaster Raster of data to place at x,y location. + */ + public void setDataElements(int x, int y, Raster inRaster) { + int dstOffX = x + inRaster.getMinX(); + int dstOffY = y + inRaster.getMinY(); + int width = inRaster.getWidth(); + int height = inRaster.getHeight(); + if ((dstOffX < this.minX) || (dstOffY < this.minY) || + (dstOffX + width > this.maxX) || (dstOffY + height > this.maxY)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + + setDataElements(dstOffX, dstOffY, width, height, inRaster); + } + + /** + * Stores the Raster data at the specified location. + * @param dstX The absolute X coordinate of the destination pixel + * that will receive a copy of the upper-left pixel of the + * inRaster + * @param dstY The absolute Y coordinate of the destination pixel + * that will receive a copy of the upper-left pixel of the + * inRaster + * @param width The number of pixels to store horizontally + * @param height The number of pixels to store vertically + * @param inRaster Raster of data to place at x,y location. + */ + private void setDataElements(int dstX, int dstY, + int width, int height, + Raster inRaster) { + // Assume bounds checking has been performed previously + if (width <= 0 || height <= 0) { + return; + } + + // Write inRaster (minX, minY) to (dstX, dstY) + + int srcOffX = inRaster.getMinX(); + int srcOffY = inRaster.getMinY(); + int tdata[] = null; + + if (inRaster instanceof IntegerInterleavedRaster) { + IntegerInterleavedRaster ict = (IntegerInterleavedRaster) inRaster; + + // Extract the raster parameters + tdata = ict.getDataStorage(); + int tss = ict.getScanlineStride(); + int toff = ict.getDataOffset(0); + + int srcOffset = toff; + int dstOffset = dataOffsets[0]+(dstY-minY)*scanlineStride+ + (dstX-minX); + + + dataBuffer.markBitmapDirty(); + // Fastest case. We can copy scanlines + // Loop through all of the scanlines and copy the data + for (int startY=0; startY < height; startY++) { + System.arraycopy(tdata, srcOffset, data, dstOffset, width); + srcOffset += tss; + dstOffset += scanlineStride; + } + markDirty(); + return; + } + + Object odata = null; + for (int startY=0; startY < height; startY++) { + // Grab one scanline at a time + odata = inRaster.getDataElements(srcOffX, srcOffY+startY, + width, 1, odata); + setDataElements(dstX, dstY+startY, width, 1, odata); + } + } + + /** + * Stores an array of data elements into the specified rectangular + * region. + * An ArrayIndexOutOfBounds exception will be thrown at runtime + * if the pixel coordinates are out of bounds. + * A ClassCastException will be thrown if the input object is non null + * and references anything other than an array of transferType. + * The data elements in the + * data array are assumed to be packed. That is, a data element + * for the nth band at location (x2, y2) would be found at: + *
+     *      inData[((y2-y)*w + (x2-x))*numDataElements + n]
+     * 
+ * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. + * @param inData An object reference to an array of type defined by + * getTransferType() and length w*h*getNumDataElements() + * containing the pixel data to place between x,y and + * x+h, y+h. + */ + public void setDataElements(int x, int y, int w, int h, Object obj) { + if ((x < this.minX) || (y < this.minY) || + (x + w > this.maxX) || (y + h > this.maxY)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int inData[] = (int[])obj; + int yoff = (y-minY)*scanlineStride + (x-minX) + dataOffsets[0]; + int off = 0; + + dataBuffer.markBitmapDirty(); + for (int ystart = 0; ystart < h; ystart++) { + System.arraycopy(inData, off, data, yoff, w); + off += w; + yoff += scanlineStride; + } + + markDirty(); + } + + /** + * Creates a subraster given a region of the raster. The x and y + * coordinates specify the horizontal and vertical offsets + * from the upper-left corner of this raster to the upper-left corner + * of the subraster. A subset of the bands of the parent Raster may + * be specified. If this is null, then all the bands are present in the + * subRaster. A translation to the subRaster may also be specified. + * Note that the subraster will reference the same + * DataBuffer as the parent raster, but using different offsets. + * @param x X offset. + * @param y Y offset. + * @param width Width (in pixels) of the subraster. + * @param height Height (in pixels) of the subraster. + * @param x0 Translated X origin of the subraster. + * @param y0 Translated Y origin of the subraster. + * @param bandList Array of band indices. + * @exception RasterFormatException + * if the specified bounding box is outside of the parent raster. + */ + public WritableRaster createWritableChild (int x, int y, + int width, int height, + int x0, int y0, + int bandList[]) { + if (x < this.minX) { + throw new RasterFormatException("x lies outside raster"); + } + if (y < this.minY) { + throw new RasterFormatException("y lies outside raster"); + } + if ((x+width < x) || (x+width > this.minX + this.width)) { + throw new RasterFormatException("(x + width) is outside raster"); + } + if ((y+height < y) || (y+height > this.minY + this.height)) { + throw new RasterFormatException("(y + height) is outside raster"); + } + + SampleModel sm; + + if (bandList != null) + sm = sampleModel.createSubsetSampleModel(bandList); + else + sm = sampleModel; + + int deltaX = x0 - x; + int deltaY = y0 - y; + + return new IntegerInterleavedRaster(sm, + dataBuffer, + new Rectangle(x0,y0,width,height), + new Point(sampleModelTranslateX+deltaX, + sampleModelTranslateY+deltaY), + this); + } + + + /** + * Creates a subraster given a region of the raster. The x and y + * coordinates specify the horizontal and vertical offsets + * from the upper-left corner of this raster to the upper-left corner + * of the subraster. A subset of the bands of the parent raster may + * be specified. If this is null, then all the bands are present in the + * subRaster. Note that the subraster will reference the same + * DataBuffer as the parent raster, but using different offsets. + * @param x X offset. + * @param y Y offset. + * @param width Width (in pixels) of the subraster. + * @param height Height (in pixels) of the subraster. + * @param x0 Translated X origin of the subRaster. + * @param y0 Translated Y origin of the subRaster. + * @param bandList Array of band indices. + * @exception RasterFormatException + * if the specified bounding box is outside of the parent raster. + */ + public Raster createChild (int x, int y, + int width, int height, + int x0, int y0, + int bandList[]) { + return createWritableChild(x, y, width, height, x0, y0, bandList); + } + + + /** + * Creates a raster with the same band layout but using a different + * width and height, and with new zeroed data arrays. + */ + public WritableRaster createCompatibleWritableRaster(int w, int h) { + if (w <= 0 || h <=0) { + throw new RasterFormatException("negative "+ + ((w <= 0) ? "width" : "height")); + } + + SampleModel sm = sampleModel.createCompatibleSampleModel(w,h); + + return new IntegerInterleavedRaster(sm, new Point(0,0)); + } + + /** + * Creates a raster with the same data layout and the same + * width and height, and with new zeroed data arrays. If + * the raster is a subraster, this will call + * createCompatibleRaster(width, height). + */ + public WritableRaster createCompatibleWritableRaster() { + return createCompatibleWritableRaster(width,height); + } + + public String toString() { + return new String ("IntegerInterleavedRaster: width = "+width + +" height = " + height + +" #Bands = " + numBands + +" xOff = "+sampleModelTranslateX + +" yOff = "+sampleModelTranslateY + +" dataOffset[0] "+dataOffsets[0]); + } + +// /** +// * For debugging... prints a region of a one-band IntegerInterleavedRaster +// */ +// public void print(int x, int y, int w, int h) { +// // REMIND: Only works for 1 band! +// System.out.println(this); +// int offset = dataOffsets[0] + y*scanlineStride + x*pixelStride; +// int off; +// for (int yoff=0; yoff < h; yoff++, offset += scanlineStride) { +// off = offset; +// System.out.print("Line "+(sampleModelTranslateY+y+yoff)+": "); +// for (int xoff = 0; xoff < w; xoff++, off+= pixelStride) { +// System.out.print(Integer.toHexString(data[off])+" "); +// } +// System.out.println(""); +// } +// } + +} diff --git a/openjdk/sun/awt/image/JPEGImageDecoder.java b/openjdk/sun/awt/image/JPEGImageDecoder.java new file mode 100644 index 0000000..8a40681 --- /dev/null +++ b/openjdk/sun/awt/image/JPEGImageDecoder.java @@ -0,0 +1,38 @@ +/* + Copyright (C) 2010 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.awt.image; + +import java.io.InputStream; + +/** + * Replace the same class from Sun with native parts. + * @author Volker Berlin + */ +public class JPEGImageDecoder extends IkvmImageDecoder{ + + JPEGImageDecoder(InputStreamImageSource src, InputStream is){ + super(src, is); + } + +} diff --git a/openjdk/sun/awt/image/SunWritableRaster.java b/openjdk/sun/awt/image/SunWritableRaster.java new file mode 100644 index 0000000..40e55ab --- /dev/null +++ b/openjdk/sun/awt/image/SunWritableRaster.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2001, 2008, 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.awt.image; + +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Image; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferUShort; +import java.awt.image.DataBufferInt; +import java.awt.image.SampleModel; +import java.awt.image.WritableRaster; + +import sun.java2d.StateTrackable.State; +import sun.java2d.SurfaceData; +import sun.java2d.StateTrackableDelegate; + +/** + * This class exists as a middle layer between WritableRaster and its + * implementation specific subclasses (ByteComponentRaster, ShortBandedRaster, + * etc). + * It provides utilities to steal the data arrays from the standard DataBuffer + * types and also steals the StateTrackableDelegate from the associated + * DataBuffer so that it can be updated when the data is changed. + */ +public class SunWritableRaster extends WritableRaster { + private static DataStealer stealer; + + public static interface DataStealer { + public byte[] getData(DataBufferByte dbb, int bank); + public short[] getData(DataBufferUShort dbus, int bank); + public int[] getData(DataBufferInt dbi, int bank); + public StateTrackableDelegate getTrackable(DataBuffer db); + public void setTrackable(DataBuffer db, StateTrackableDelegate trackable); + } + + public static void setDataStealer(DataStealer ds) { + if (stealer != null) { + throw new InternalError("Attempt to set DataStealer twice"); + } + stealer = ds; + } + + public static byte[] stealData(DataBufferByte dbb, int bank) { + return stealer.getData(dbb, bank); + } + + public static short[] stealData(DataBufferUShort dbus, int bank) { + return stealer.getData(dbus, bank); + } + + public static int[] stealData(DataBufferInt dbi, int bank) { + return stealer.getData(dbi, bank); + } + + public static StateTrackableDelegate stealTrackable(DataBuffer db) { + return stealer.getTrackable(db); + } + + public static void setTrackable(DataBuffer db, StateTrackableDelegate trackable) { + stealer.setTrackable(db, trackable); + } + + public static void makeTrackable(DataBuffer db) { + stealer.setTrackable(db, StateTrackableDelegate.createInstance(State.STABLE)); + } + + public static void markDirty(DataBuffer db) { + stealer.getTrackable(db).markDirty(); + } + + public static void markDirty(WritableRaster wr) { + if (wr instanceof SunWritableRaster) { + ((SunWritableRaster) wr).markDirty(); + } else { + markDirty(wr.getDataBuffer()); + } + } + + public static void markDirty(Image img) { +// SurfaceData.getPrimarySurfaceData(img).markDirty(); + } + + private StateTrackableDelegate theTrackable; + + public SunWritableRaster(SampleModel sampleModel, Point origin) { + super(sampleModel, origin); + theTrackable = stealTrackable(dataBuffer); + } + + public SunWritableRaster(SampleModel sampleModel, + DataBuffer dataBuffer, + Point origin) + { + super(sampleModel, dataBuffer, origin); + theTrackable = stealTrackable(dataBuffer); + } + + public SunWritableRaster(SampleModel sampleModel, + DataBuffer dataBuffer, + Rectangle aRegion, + Point sampleModelTranslate, + WritableRaster parent) + { + super(sampleModel, dataBuffer, aRegion, sampleModelTranslate, parent); + theTrackable = stealTrackable(dataBuffer); + } + + /** + * Mark the TrackableDelegate of the associated DataBuffer dirty. + */ + public final void markDirty() { + theTrackable.markDirty(); + } +} diff --git a/openjdk/sun/awt/image/ToolkitImage.java b/openjdk/sun/awt/image/ToolkitImage.java new file mode 100644 index 0000000..8f882f3 --- /dev/null +++ b/openjdk/sun/awt/image/ToolkitImage.java @@ -0,0 +1,325 @@ +/* + * Copyright (c) 1995, 2004, 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.awt.image; + +import java.util.Hashtable; +import java.util.Enumeration; + +import java.awt.Component; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.ImageProducer; +import java.awt.image.ImageConsumer; +import java.awt.image.ImageObserver; +import sun.awt.image.ImageRepresentation; + +public class ToolkitImage extends Image { + + /** + * The object which is used to reconstruct the original image data + * as needed. + */ + ImageProducer source; + + InputStreamImageSource src; + + ImageRepresentation imagerep; + + + protected ToolkitImage() { + } + + /** + * Construct an image from an ImageProducer object. + */ + public ToolkitImage(ImageProducer is) { + source = is; + if (is instanceof InputStreamImageSource) { + src = (InputStreamImageSource) is; + } + } + + public ImageProducer getSource() { + if (src != null) { + src.checkSecurity(null, false); + } + return source; + } + + private int width = -1; + private int height = -1; + private Hashtable properties; + + private int availinfo; + + /** + * Return the width of the original image source. + * If the width isn't known, then the image is reconstructed. + */ + public int getWidth() { + if (src != null) { + src.checkSecurity(null, false); + } + if ((availinfo & ImageObserver.WIDTH) == 0) { + reconstruct(ImageObserver.WIDTH); + } + return width; + } + + /** + * Return the width of the original image source. + * If the width isn't known, then the ImageObserver object will be + * notified when the data is available. + */ + public synchronized int getWidth(ImageObserver iw) { + if (src != null) { + src.checkSecurity(null, false); + } + if ((availinfo & ImageObserver.WIDTH) == 0) { + addWatcher(iw, true); + if ((availinfo & ImageObserver.WIDTH) == 0) { + return -1; + } + } + return width; + } + + /** + * Return the height of the original image source. + * If the height isn't known, then the image is reconstructed. + */ + public int getHeight() { + if (src != null) { + src.checkSecurity(null, false); + } + if ((availinfo & ImageObserver.HEIGHT) == 0) { + reconstruct(ImageObserver.HEIGHT); + } + return height; + } + + /** + * Return the height of the original image source. + * If the height isn't known, then the ImageObserver object will be + * notified when the data is available. + */ + public synchronized int getHeight(ImageObserver iw) { + if (src != null) { + src.checkSecurity(null, false); + } + if ((availinfo & ImageObserver.HEIGHT) == 0) { + addWatcher(iw, true); + if ((availinfo & ImageObserver.HEIGHT) == 0) { + return -1; + } + } + return height; + } + + /** + * Return a property of the image by name. Individual property names + * are defined by the various image formats. If a property is not + * defined for a particular image, then this method will return the + * UndefinedProperty object. If the properties for this image are + * not yet known, then this method will return null and the ImageObserver + * object will be notified later. The property name "comment" should + * be used to store an optional comment which can be presented to + * the user as a description of the image, its source, or its author. + */ + public Object getProperty(String name, ImageObserver observer) { + if (name == null) { + throw new NullPointerException("null property name is not allowed"); + } + + if (src != null) { + src.checkSecurity(null, false); + } + if (properties == null) { + addWatcher(observer, true); + if (properties == null) { + return null; + } + } + Object o = properties.get(name); + if (o == null) { + o = Image.UndefinedProperty; + } + return o; + } + + public boolean hasError() { + if (src != null) { + src.checkSecurity(null, false); + } + return (availinfo & ImageObserver.ERROR) != 0; + } + + public int check(ImageObserver iw) { + if (src != null) { + src.checkSecurity(null, false); + } + if ((availinfo & ImageObserver.ERROR) == 0 && + ((~availinfo) & (ImageObserver.WIDTH | + ImageObserver.HEIGHT | + ImageObserver.PROPERTIES)) != 0) { + addWatcher(iw, false); + } + return availinfo; + } + + public void preload(ImageObserver iw) { + if (src != null) { + src.checkSecurity(null, false); + } + if ((availinfo & ImageObserver.ALLBITS) == 0) { + addWatcher(iw, true); + } + } + + private synchronized void addWatcher(ImageObserver iw, boolean load) { + if ((availinfo & ImageObserver.ERROR) != 0) { + if (iw != null) { + iw.imageUpdate(this, ImageObserver.ERROR|ImageObserver.ABORT, + -1, -1, -1, -1); + } + return; + } + ImageRepresentation ir = getImageRep(); + ir.addWatcher(iw); + if (load) { + ir.startProduction(); + } + } + + private synchronized void reconstruct(int flags) { + if ((flags & ~availinfo) != 0) { + if ((availinfo & ImageObserver.ERROR) != 0) { + return; + } + ImageRepresentation ir = getImageRep(); + ir.startProduction(); + while ((flags & ~availinfo) != 0) { + try { + wait(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return; + } + if ((availinfo & ImageObserver.ERROR) != 0) { + return; + } + } + } + } + + synchronized void addInfo(int newinfo) { + availinfo |= newinfo; + notifyAll(); + } + + void setDimensions(int w, int h) { + width = w; + height = h; + addInfo(ImageObserver.WIDTH | ImageObserver.HEIGHT); + } + + void setProperties(Hashtable props) { + if (props == null) { + props = new Hashtable(); + } + properties = props; + addInfo(ImageObserver.PROPERTIES); + } + + synchronized void infoDone(int status) { + if (status == ImageConsumer.IMAGEERROR || + ((~availinfo) & (ImageObserver.WIDTH | + ImageObserver.HEIGHT)) != 0) { + addInfo(ImageObserver.ERROR); + } else if ((availinfo & ImageObserver.PROPERTIES) == 0) { + setProperties(null); + } + } + + public void flush() { + if (src != null) { + src.checkSecurity(null, false); + } + + ImageRepresentation ir; + synchronized (this) { + availinfo &= ~ImageObserver.ERROR; + ir = imagerep; + imagerep = null; + } + if (ir != null) { + ir.abort(); + } + if (src != null) { + src.flush(); + } + } + + protected ImageRepresentation makeImageRep() { + return new ImageRepresentation(this); + } + + public synchronized ImageRepresentation getImageRep() { + if (src != null) { + src.checkSecurity(null, false); + } + if (imagerep == null) { + imagerep = makeImageRep(); + } + return imagerep; + } + + public Graphics getGraphics() { + throw new UnsupportedOperationException("getGraphics() not valid for images " + + "created with createImage(producer)"); + } + +// /* this method is needed by printing code */ +// public ColorModel getColorModel() { +// ImageRepresentation imageRep = getImageRep(); +// return imageRep.getColorModel(); +// } +// + /* this method is needed by printing code */ + public BufferedImage getBufferedImage() { + ImageRepresentation imageRep = getImageRep(); + return imageRep.getBufferedImage(); + } +// +// public void setAccelerationPriority(float priority) { +// super.setAccelerationPriority(priority); +// ImageRepresentation imageRep = getImageRep(); +// imageRep.setAccelerationPriority(accelerationPriority); +// } +} diff --git a/openjdk/sun/awt/shell/Win32ShellFolder2.java b/openjdk/sun/awt/shell/Win32ShellFolder2.java new file mode 100644 index 0000000..c7d6ea8 --- /dev/null +++ b/openjdk/sun/awt/shell/Win32ShellFolder2.java @@ -0,0 +1,1160 @@ +/* + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (C) 2009 Volker Berlin (i-net software) + * Copyright (C) 2010 Karsten Heinrich (i-net software) + * 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.awt.shell; + +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.*; +import javax.swing.SwingConstants; + +import cli.System.IntPtr; +import cli.System.Drawing.Bitmap; + +// NOTE: This class basically a conversion of the OpenJDK Wen32ShellFolder2, but uses +// .NET pointers and objects instead of representing pointers as long + +/** + * Win32 Shell Folders + *

+ *
+ * There are two fundamental types of shell folders : file system folders + * and non-file system folders. File system folders are relatively easy + * to deal with. Non-file system folders are items such as My Computer, + * Network Neighborhood, and the desktop. Some of these non-file system + * folders have special values and properties. + *

+ *
+ * Win32 keeps two basic data structures for shell folders. The first + * of these is called an ITEMIDLIST. Usually a pointer, called an + * LPITEMIDLIST, or more frequently just "PIDL". This structure holds + * a series of identifiers and can be either relative to the desktop + * (an absolute PIDL), or relative to the shell folder that contains them. + * Some Win32 functions can take absolute or relative PIDL values, and + * others can only accept relative values. + *
+ * The second data structure is an IShellFolder COM interface. Using + * this interface, one can enumerate the relative PIDLs in a shell + * folder, get attributes, etc. + *
+ * All Win32ShellFolder2 objects which are folder types (even non-file + * system folders) contain an IShellFolder object. Files are named in + * directories via relative PIDLs. + * + * @author Michael Martak + * @author Leif Samuelsson + * @author Kenneth Russell + * @author Volker Berlin + * @author Karsten Heinrich + * @since 1.4 */ + +final class Win32ShellFolder2 extends ShellFolder { + + // Win32 Shell Folder Constants + public static final int DESKTOP = 0x0000; + public static final int INTERNET = 0x0001; + public static final int PROGRAMS = 0x0002; + public static final int CONTROLS = 0x0003; + public static final int PRINTERS = 0x0004; + public static final int PERSONAL = 0x0005; + public static final int FAVORITES = 0x0006; + public static final int STARTUP = 0x0007; + public static final int RECENT = 0x0008; + public static final int SENDTO = 0x0009; + public static final int BITBUCKET = 0x000a; + public static final int STARTMENU = 0x000b; + public static final int DESKTOPDIRECTORY = 0x0010; + public static final int DRIVES = 0x0011; + public static final int NETWORK = 0x0012; + public static final int NETHOOD = 0x0013; + public static final int FONTS = 0x0014; + public static final int TEMPLATES = 0x0015; + public static final int COMMON_STARTMENU = 0x0016; + public static final int COMMON_PROGRAMS = 0X0017; + public static final int COMMON_STARTUP = 0x0018; + public static final int COMMON_DESKTOPDIRECTORY = 0x0019; + public static final int APPDATA = 0x001a; + public static final int PRINTHOOD = 0x001b; + public static final int ALTSTARTUP = 0x001d; + public static final int COMMON_ALTSTARTUP = 0x001e; + public static final int COMMON_FAVORITES = 0x001f; + public static final int INTERNET_CACHE = 0x0020; + public static final int COOKIES = 0x0021; + public static final int HISTORY = 0x0022; + + // Win32 shell folder attributes + public static final int ATTRIB_CANCOPY = 0x00000001; + public static final int ATTRIB_CANMOVE = 0x00000002; + public static final int ATTRIB_CANLINK = 0x00000004; + public static final int ATTRIB_CANRENAME = 0x00000010; + public static final int ATTRIB_CANDELETE = 0x00000020; + public static final int ATTRIB_HASPROPSHEET = 0x00000040; + public static final int ATTRIB_DROPTARGET = 0x00000100; + public static final int ATTRIB_LINK = 0x00010000; + public static final int ATTRIB_SHARE = 0x00020000; + public static final int ATTRIB_READONLY = 0x00040000; + public static final int ATTRIB_GHOSTED = 0x00080000; + public static final int ATTRIB_HIDDEN = 0x00080000; + public static final int ATTRIB_FILESYSANCESTOR = 0x10000000; + public static final int ATTRIB_FOLDER = 0x20000000; + public static final int ATTRIB_FILESYSTEM = 0x40000000; + public static final int ATTRIB_HASSUBFOLDER = 0x80000000; + public static final int ATTRIB_VALIDATE = 0x01000000; + public static final int ATTRIB_REMOVABLE = 0x02000000; + public static final int ATTRIB_COMPRESSED = 0x04000000; + public static final int ATTRIB_BROWSABLE = 0x08000000; + public static final int ATTRIB_NONENUMERATED = 0x00100000; + public static final int ATTRIB_NEWCONTENT = 0x00200000; + + // IShellFolder::GetDisplayNameOf constants + public static final int SHGDN_NORMAL = 0; + public static final int SHGDN_INFOLDER = 1; + public static final int SHGDN_INCLUDE_NONFILESYS= 0x2000; + public static final int SHGDN_FORADDRESSBAR = 0x4000; + public static final int SHGDN_FORPARSING = 0x8000; + + // Values for system call LoadIcon() + public enum SystemIcon { + IDI_APPLICATION(32512), + IDI_HAND(32513), + IDI_ERROR(32513), + IDI_QUESTION(32514), + IDI_EXCLAMATION(32515), + IDI_WARNING(32515), + IDI_ASTERISK(32516), + IDI_INFORMATION(32516), + IDI_WINLOGO(32517); + + private final int iconID; + + SystemIcon(int iconID) { + this.iconID = iconID; + } + + public int getIconID() { + return iconID; + } + } + + static class FolderDisposer implements sun.java2d.DisposerRecord { + /* + * This is cached as a concession to getFolderType(), which needs + * an absolute PIDL. + */ + cli.System.IntPtr absolutePIDL; + /* + * We keep track of shell folders through the IShellFolder + * interface of their parents plus their relative PIDL. + */ + cli.System.Object pIShellFolder; + cli.System.IntPtr relativePIDL; + + boolean disposed; + + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + public void dispose() { + if (disposed) + return; + if ( relativePIDL != null && !cli.System.IntPtr.Zero.Equals( relativePIDL ) ) { + releasePIDL(relativePIDL); + } + if ( absolutePIDL != null && !cli.System.IntPtr.Zero.Equals( absolutePIDL ) ) { + releasePIDL(absolutePIDL); + } + if ( pIShellFolder != null ) { + releaseIShellFolder(pIShellFolder); + } + disposed = true; + } + } + + FolderDisposer disposer = new FolderDisposer(); + + private void setIShellFolder( cli.System.Object iShellFolder ) { + disposer.pIShellFolder = iShellFolder; + } + + private void setRelativePIDL(cli.System.IntPtr relativePIDL) { + disposer.relativePIDL = relativePIDL; + } + + /* + * The following are for caching various shell folder properties. + */ + private cli.System.Object pIShellIcon = null; + private String folderType = null; + private String displayName = null; + private Image smallIcon = null; + private Image largeIcon = null; + private Boolean isDir = null; + + /* + * The following is to identify the My Documents folder as being special + */ + private boolean isPersonal; + + /** + * Create a system special shell folder, such as the + * desktop or Network Neighborhood. + */ + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + Win32ShellFolder2(final int csidl) throws IOException, InterruptedException { + // Desktop is parent of DRIVES and NETWORK, not necessarily + // other special shell folders. + super ( null, (getFileSystemPath(csidl) == null) ? ("ShellFolder: 0x" + Integer.toHexString(csidl)) : getFileSystemPath(csidl)); + if (csidl == DESKTOP) { + // compared to the Java implementation we require two steps here since + // we don't have a callback from the native methods in to this instance + setIShellFolder( initDesktopFolder() ); + setRelativePIDL( initDesktopPIDL() ); + } else { + cli.System.Object desktopFolder = getDesktop().getIShellFolder(); + cli.System.IntPtr pidl = initSpecialPIDL( desktopFolder, csidl ); + setRelativePIDL( pidl ); + setIShellFolder( initSpecialFolder(desktopFolder, pidl) ); + // At this point, the native method initSpecial() has set our relativePIDL + // relative to the Desktop, which may not be our immediate parent. We need + // to traverse this ID list and break it into a chain of shell folders from + // the top, with each one having an immediate parent and a relativePIDL + // relative to that parent. + bindToDesktop(); + } + + sun.java2d.Disposer.addRecord(this , disposer); + } + + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + protected void bindToDesktop() { + cli.System.IntPtr pIDL = disposer.relativePIDL; + parent = getDesktop(); + while ( pIDL != null && !cli.System.IntPtr.Zero.Equals( pIDL ) ) { + // Get a child pidl relative to 'parent' + cli.System.IntPtr childPIDL = copyFirstPIDLEntry(pIDL); + if (childPIDL != null && !cli.System.IntPtr.Zero.Equals( childPIDL ) ) { + // Get a handle to the the rest of the ID list + // i,e, parent's grandchilren and down + pIDL = getNextPIDLEntry(pIDL); + if ( pIDL != null && !cli.System.IntPtr.Zero.Equals( pIDL ) ) { + // Now we know that parent isn't immediate to 'this' because it + // has a continued ID list. Create a shell folder for this child + // pidl and make it the new 'parent'. + parent = new Win32ShellFolder2( (Win32ShellFolder2) parent, childPIDL ); + } else { + // No grandchildren means we have arrived at the parent of 'this', + // and childPIDL is directly relative to parent. + disposer.relativePIDL = childPIDL; + } + } else { + break; + } + } + } + + /** + * Create a system shell folder + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + Win32ShellFolder2(Win32ShellFolder2 parent, cli.System.Object pIShellFolder, cli.System.IntPtr relativePIDL, String path) { + super(parent, (path != null) ? path : "ShellFolder: "); + this.disposer.pIShellFolder = pIShellFolder; + this.disposer.relativePIDL = relativePIDL; + sun.java2d.Disposer.addRecord(this, disposer); + } + + /** + * Creates a shell folder with a parent and relative PIDL + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + Win32ShellFolder2(Win32ShellFolder2 parent, cli.System.IntPtr relativePIDL) { + super (parent, getFileSystemPath(parent.getIShellFolder(), relativePIDL)); + this .disposer.relativePIDL = relativePIDL; + getAbsolutePath(); + sun.java2d.Disposer.addRecord(this , disposer); + } + + // Initializes the desktop shell folder + /** + * Returns the pIDL of the Desktop folder (pIDL root) + * @return the pIDL of the Desktop folder (pIDL root) + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + private static native cli.System.IntPtr initDesktopPIDL(); + /** + * Returns the IShellFolder pointer of the Desktop folder (pIDL root) + * @return the IShellFolder pointer of the Desktop folder (pIDL root) + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + private static native cli.System.Object initDesktopFolder(); + + // Initializes a special, non-file system shell folder + // from one of the above constants + /** + * initializes a special folder + * @param desktopIShellFolder the IShellFolder reference of the desktop folder + * @param csidl the CSIDL of the requested special folder + * @return the pIDL of the special folder relative to the desktop root + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + private static native cli.System.IntPtr initSpecialPIDL(cli.System.Object desktopIShellFolder, int csidl); + /** + * initializes a special folder + * @param desktopIShellFolder the IShellFolder reference of the desktop folder + * @param pidl the pIDL of the requested folder relative to the desktopIShellFolder + * @return the IShellFolder reference for the requested folder + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + private static native cli.System.Object initSpecialFolder(cli.System.Object desktopIShellFolder, cli.System.IntPtr pidl); + + /** Marks this folder as being the My Documents (Personal) folder */ + public void setIsPersonal() { + isPersonal = true; + } + + /** + * This method is implemented to make sure that no instances + * of ShellFolder are ever serialized. If isFileSystem() returns + * true, then the object is representable with an instance of + * java.io.File instead. If not, then the object depends + * on native PIDL state and should not be serialized. + * + * @returns a java.io.File replacement object. If the folder + * is a not a normal directory, then returns the first non-removable + * drive (normally "C:\"). + */ + protected Object writeReplace() + throws java.io.ObjectStreamException { + if (isFileSystem()) { + return new File(getPath()); + } else { + Win32ShellFolder2 drives = Win32ShellFolderManager2.getDrives(); + if (drives != null) { + File[] driveRoots = drives.listFiles(); + if (driveRoots != null) { + for (int i = 0; i < driveRoots.length; i++) { + if (driveRoots[i] instanceof Win32ShellFolder2) { + Win32ShellFolder2 sf = (Win32ShellFolder2) driveRoots[i]; + if (sf.isFileSystem() && !sf.hasAttribute(ATTRIB_REMOVABLE)) { + return new File(sf.getPath()); + } + } + } + } + } + // Ouch, we have no hard drives. Return something "valid" anyway. + return new File("C:\\"); + } + } + + /** + * Finalizer to clean up any COM objects or PIDLs used by this object. + */ + protected void dispose() { + disposer.dispose(); + } + + // Given a (possibly multi-level) relative PIDL (with respect to + // the desktop, at least in all of the usage cases in this code), + // return a pointer to the next entry. Does not mutate the PIDL in + // any way. Returns 0 if the null terminator is reached. + // Needs to be accessible to Win32ShellFolderManager2 + @cli.System.Security.SecurityCriticalAttribute.Annotation + static native cli.System.IntPtr getNextPIDLEntry(cli.System.IntPtr pIDL); + + // Given a (possibly multi-level) relative PIDL (with respect to + // the desktop, at least in all of the usage cases in this code), + // copy the first entry into a newly-allocated PIDL. Returns 0 if + // the PIDL is at the end of the list. + // Needs to be accessible to Win32ShellFolderManager2 + @cli.System.Security.SecurityCriticalAttribute.Annotation + static native cli.System.IntPtr copyFirstPIDLEntry(cli.System.IntPtr pIDL); + + // Given a parent's absolute PIDL and our relative PIDL, build an absolute PIDL + /** + * Combines a parent pIDL with a descendant pIDL. It doesn't matter whether the parent pIDL + * is relative or absolute since this is only a concatenation of the IDLs + * @param ppIDL the parent pIDL + * @param pIDL the pIDL relative to the ppIDL + * @return a pIDL for the item referenced by the original pIDL but relative to the parent of ppIDL + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + private static native cli.System.IntPtr combinePIDLs(cli.System.IntPtr ppIDL, cli.System.IntPtr pIDL); + + // Release a PIDL object + // Needs to be accessible to Win32ShellFolderManager2 + @cli.System.Security.SecurityCriticalAttribute.Annotation + static native void releasePIDL(cli.System.IntPtr pIDL); + + // Release an IShellFolder object + @cli.System.Security.SecurityCriticalAttribute.Annotation + static native void releaseIShellFolder( cli.System.Object iShellFolder ); + + /** + * Accessor for IShellFolder + */ + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + public cli.System.Object getIShellFolder() { + if (disposer.pIShellFolder == null ) { + assert (isDirectory()); + assert (parent != null); + cli.System.Object parentIShellFolder = getParentIShellFolder(); + if (parentIShellFolder == null) { + throw new InternalError( "Parent IShellFolder was null for " + getAbsolutePath() ); + } + // We are a directory with a parent and a relative PIDL. + // We want to bind to the parent so we get an IShellFolder instance associated with us. + disposer.pIShellFolder = bindToObject(parentIShellFolder, disposer.relativePIDL); + if (disposer.pIShellFolder == null ) { + throw new InternalError("Unable to bind " + getAbsolutePath() + " to parent"); + } + } + return disposer.pIShellFolder; + } + + /** + * Get the parent ShellFolder's IShellFolder interface + */ + public cli.System.Object getParentIShellFolder() { + Win32ShellFolder2 parent = (Win32ShellFolder2) getParentFile(); + cli.System.Object parentFolder; + if (parent == null) { + // Parent should only be null if this is the desktop, whose + // relativePIDL is relative to its own IShellFolder. + parentFolder = getIShellFolder(); + } else { + parentFolder = parent.getIShellFolder(); + } + return parentFolder; + } + + /** + * Accessor for relative PIDL + */ + public cli.System.IntPtr getRelativePIDL() { + if (disposer.relativePIDL == null) { + throw new InternalError( "Should always have a relative PIDL" ); + } + return disposer.relativePIDL; + } + + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + private cli.System.IntPtr getAbsolutePIDL() { + if (parent == null) { + // This is the desktop + return getRelativePIDL(); + } else { + if (disposer.absolutePIDL == null || disposer.absolutePIDL.Equals( IntPtr.Zero )) { + disposer.absolutePIDL = combinePIDLs( ((Win32ShellFolder2) parent).getAbsolutePIDL(), getRelativePIDL()); + } + + return disposer.absolutePIDL; + } + } + + /** + * Helper function to return the desktop + */ + public Win32ShellFolder2 getDesktop() { + return Win32ShellFolderManager2.getDesktop(); + } + + /** + * Helper function to return the desktop IShellFolder interface + */ + public cli.System.Object getDesktopIShellFolder() { + return getDesktop().getIShellFolder(); + } + + private static boolean pathsEqual(String path1, String path2) { + // Same effective implementation as Win32FileSystem + return path1.equalsIgnoreCase(path2); + } + + /** + * Check to see if two ShellFolder objects are the same + */ + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + public boolean equals(Object o) { + if (o == null || !(o instanceof Win32ShellFolder2)) { + // Short-circuit circuitous delegation path + if (!(o instanceof File)) { + return super.equals(o); + } + return pathsEqual(getPath(), ((File) o).getPath()); + } + Win32ShellFolder2 rhs = (Win32ShellFolder2) o; + if ((parent == null && rhs.parent != null) || + (parent != null && rhs.parent == null)) { + return false; + } + + if (isFileSystem() && rhs.isFileSystem()) { + // Only folders with identical parents can be equal + return (pathsEqual(getPath(), rhs.getPath()) && + (parent == rhs.parent || parent.equals(rhs.parent))); + } + + if (parent == rhs.parent || parent.equals(rhs.parent)) { + try { + return pidlsEqual(getParentIShellFolder(), disposer.relativePIDL, rhs.disposer.relativePIDL); + } catch (InterruptedException e) { + return false; + } + } + + return false; + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static boolean pidlsEqual(final cli.System.Object pIShellFolder, final cli.System.IntPtr pidl1, final cli.System.IntPtr pidl2) + throws InterruptedException { + return invoke(new Callable() { + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + public Boolean call() { + return compareIDs(pIShellFolder, pidl1, pidl2) == 0; + } + }, RuntimeException.class); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static native int compareIDs(cli.System.Object pParentIShellFolder, cli.System.IntPtr pidl1, cli.System.IntPtr pidl2); + + private volatile Boolean cachedIsFileSystem; + + /** + * @return Whether this is a file system shell folder + */ + public boolean isFileSystem() { + if (cachedIsFileSystem == null) { + cachedIsFileSystem = hasAttribute(ATTRIB_FILESYSTEM); + } + + return cachedIsFileSystem; + } + + /** + * Return whether the given attribute flag is set for this object + */ + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + public boolean hasAttribute(int attribute) { + // Caching at this point doesn't seem to be cost efficient + return (getAttributes0(getParentIShellFolder(), getRelativePIDL(), attribute) & attribute) != 0; + } + + /** + * Returns the queried attributes specified in attrsMask. + * + * Could plausibly be used for attribute caching but have to be + * very careful not to touch network drives and file system roots + * with a full attrsMask + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + static native int getAttributes0(cli.System.Object pParentIShellFolder, cli.System.IntPtr pIDL, int attrsMask); + + // Return the path to the underlying file system object + @cli.System.Security.SecurityCriticalAttribute.Annotation + private static String getFileSystemPath(cli.System.Object parentIShellFolder, cli.System.IntPtr relativePIDL) { + int linkedFolder = ATTRIB_LINK | ATTRIB_FOLDER; + if (parentIShellFolder == Win32ShellFolderManager2.getNetwork().getIShellFolder() && + getAttributes0(parentIShellFolder, relativePIDL, linkedFolder) == linkedFolder) { + + cli.System.Object desktopIShellFolder = Win32ShellFolderManager2.getDesktop().getIShellFolder(); + String path = getDisplayNameOf(parentIShellFolder, relativePIDL, SHGDN_FORPARSING ); + String s = getFileSystemPath(desktopIShellFolder, getLinkLocation( path, false)); + if (s != null && s.startsWith("\\\\")) { + return s; + } + } + return getDisplayNameOf(parentIShellFolder, relativePIDL, SHGDN_NORMAL | SHGDN_FORPARSING); + } + + // Needs to be accessible to Win32ShellFolderManager2 + static String getFileSystemPath(final int csidl) throws IOException, InterruptedException { + String path = invoke(new Callable() { + public String call() throws IOException { + return getFileSystemPath0(csidl); + } + }, IOException.class); + if (path != null) { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkRead(path); + } + } + return path; + } + + // NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details + private static native String getFileSystemPath0(int csidl) throws IOException; + + // Return whether the path is a network root. + // Path is assumed to be non-null + private static boolean isNetworkRoot(String path) { + return (path.equals("\\\\") || path.equals("\\") || path.equals("//") || path.equals("/")); + } + + /** + * @return The parent shell folder of this shell folder, null if + * there is no parent + */ + public File getParentFile() { + return parent; + } + + public boolean isDirectory() { + if (isDir == null) { + // Folders with SFGAO_BROWSABLE have "shell extension" handlers and are + // not traversable in JFileChooser. + if (hasAttribute(ATTRIB_FOLDER) && !hasAttribute(ATTRIB_BROWSABLE)) { + isDir = Boolean.TRUE; + } else if (isLink()) { + ShellFolder linkLocation = getLinkLocation(false); + isDir = Boolean.valueOf(linkLocation != null && linkLocation.isDirectory()); + } else { + isDir = Boolean.FALSE; + } + } + return isDir.booleanValue(); + } + + /* + * Functions for enumerating an IShellFolder's children + */ + // Returns an IEnumIDList interface for an IShellFolder. The value + // returned must be released using releaseEnumObjects(). + /** + * Returns an IEnumIDList interface for an IShellFolder. The value + * returned must be released using releaseEnumObjects(). + * @param pIShellFolder the IShellFolder instance of the parent shell folder + * @param includeHiddenFiles if true, hidden files will be included in the enumeration + * @return an instance of IEnumIDList + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + cli.System.Object getEnumObjects(cli.System.Object pIShellFolder, boolean includeHiddenFiles) { + boolean isDesktop = (disposer.pIShellFolder == getDesktopIShellFolder()); + return getEnumObjects(disposer.pIShellFolder, isDesktop, includeHiddenFiles); + } + + /** + * Returns an IEnumIDList interface for an IShellFolder. The value + * returned must be released using releaseEnumObjects(). + * @param pIShellFolder the IShellFolder instance of the parent shell folder + * @param isDesktop must be set to true, if the pIShellFolder is the desktop shell folder + * @param includeHiddenFiles if true, hidden files will be included in the enumeration + * @return an instance of IEnumIDList + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + private static native cli.System.Object getEnumObjects(cli.System.Object pIShellFolder, boolean isDesktop, boolean includeHiddenFiles); + + /** + * Returns the next sequential child as a relative PIDL + * from an IEnumIDList interface. The value returned must + * be released using releasePIDL(). + * @param pEnumObjects the IEnumIDList instance to get the next child from + * @return the next child or {@link IntPtr#Zero} if the end of the enumeration is reached + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + static native cli.System.IntPtr getNextChild(cli.System.Object pEnumObjects); + + /** + * Releases the IEnumIDList interface + * @param pEnumObjects an IEnumIDList instance + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + static native void releaseEnumObjects(cli.System.Object pEnumObjects); + + /** + * Returns the IShellFolder of a child from a parent IShellFolder and a relative pIDL. The pIDL + * may as well be any other descendant of the shell folder - at least this is, what the windows API + * documentation says. + * The value returned must be released using releaseIShellFolder(). + * @param parentIShellFolder an IShellFolder instance as root for the pIDL + * @param pIDL a pIDL relative to the parent shell folder + * @return a NEW instance of an IShellFolder for the path given by the pIDL, may be null if the path is invalid + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + private static native cli.System.Object bindToObject(cli.System.Object parentIShellFolder, cli.System.IntPtr pIDL); + + /** + * @return An array of shell folders that are children of this shell folder + * object. The array will be empty if the folder is empty. Returns + * null if this shellfolder does not denote a directory. + */ + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + public File[] listFiles(final boolean includeHiddenFiles) { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkRead(getPath()); + } + + try { + return invoke(new Callable() { + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + public File[] call() throws InterruptedException { + if (!isDirectory()) { + return null; + } + // Links to directories are not directories and cannot be parents. + // This does not apply to folders in My Network Places (NetHood) + // because they are both links and real directories! + if (isLink() && !hasAttribute(ATTRIB_FOLDER)) { + return new File[0]; + } + + Win32ShellFolder2 desktop = Win32ShellFolderManager2.getDesktop(); + Win32ShellFolder2 personal = Win32ShellFolderManager2.getPersonal(); + + // If we are a directory, we have a parent and (at least) a + // relative PIDL. We must first ensure we are bound to the + // parent so we have an IShellFolder to query. + cli.System.Object pIShellFolder = getIShellFolder(); + // Now we can enumerate the objects in this folder. + ArrayList list = new ArrayList(); + cli.System.Object pEnumObjects = getEnumObjects(pIShellFolder, includeHiddenFiles); + if (pEnumObjects != null) { + cli.System.IntPtr childPIDL = null; + int testedAttrs = ATTRIB_FILESYSTEM | ATTRIB_FILESYSANCESTOR; + do { + if (Thread.currentThread().isInterrupted()) { + return new File[0]; + } + childPIDL = getNextChild(pEnumObjects); + boolean releasePIDL = true; + if ( childPIDL != null && !cli.System.IntPtr.Zero.Equals( childPIDL ) && (getAttributes0(pIShellFolder, childPIDL, testedAttrs) & testedAttrs) != 0) { + Win32ShellFolder2 childFolder = null; + if (this .equals(desktop) && personal != null + && pidlsEqual(pIShellFolder, childPIDL, personal.disposer.relativePIDL) ) { + childFolder = personal; + } else { + childFolder = new Win32ShellFolder2(Win32ShellFolder2.this , childPIDL); + releasePIDL = false; + } + list.add(childFolder); + } + if (releasePIDL) { + releasePIDL(childPIDL); + } + } while (childPIDL != null && !childPIDL.Equals( cli.System.IntPtr.Zero )); + releaseEnumObjects(pEnumObjects); + } + return Thread.currentThread().isInterrupted() + ? new File[0] + : list.toArray(new ShellFolder[list.size()]); + } + }, InterruptedException.class); + } catch (InterruptedException e) { + return new File[0]; + } + } + + + /** + * Look for (possibly special) child folder by it's path. Note: this will not work an an ancestor(not child) + * of the current folder. + * @return The child shell folder, or null if not found. + */ + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + Win32ShellFolder2 getChildByPath(String filePath) { + cli.System.Object pIShellFolder = getIShellFolder(); + cli.System.Object pEnumObjects = getEnumObjects(pIShellFolder, true); + Win32ShellFolder2 child = null; + cli.System.IntPtr childPIDL = null; + + childPIDL = getNextChild(pEnumObjects); + while ( childPIDL != null && !cli.System.IntPtr.Zero.Equals( childPIDL ) ) { + if (getAttributes0(pIShellFolder, childPIDL, ATTRIB_FILESYSTEM) != 0) { + String path = getFileSystemPath(pIShellFolder, childPIDL); + if (path != null && path.equalsIgnoreCase(filePath)) { + cli.System.Object childIShellFolder = bindToObject( pIShellFolder, childPIDL); + child = new Win32ShellFolder2(this, childIShellFolder, childPIDL, path); + break; + } + } + releasePIDL(childPIDL); + childPIDL = getNextChild(pEnumObjects); + } + releaseEnumObjects(pEnumObjects); + return child; + } + + private volatile Boolean cachedIsLink; + + /** + * @return Whether this shell folder is a link + */ + public boolean isLink() { + if (cachedIsLink == null) { + cachedIsLink = hasAttribute(ATTRIB_LINK); + } + + return cachedIsLink; + } + + /** + * @return Whether this shell folder is marked as hidden + */ + public boolean isHidden() { + return hasAttribute(ATTRIB_HIDDEN); + } + + // Return the link location of a shell folder + /** + * Resolves the link location of an item to an ABSOLUTE pIDL + * @param parentIShellFolder the pointer to the parent IShellFolder of the item + * @param relativePIDL a single-level pIDL to the item + * @param resolve + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + static native cli.System.IntPtr getLinkLocation( String path, boolean resolve); + + /** + * @return The shell folder linked to by this shell folder, or null + * if this shell folder is not a link or is a broken or invalid link + */ + public ShellFolder getLinkLocation() { + return getLinkLocation(true); + } + + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + private ShellFolder getLinkLocation(final boolean resolve) { + return invoke(new Callable() { + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + public ShellFolder call() { + if (!isLink()) { + return null; + } + + ShellFolder location = null; + cli.System.IntPtr linkLocationPIDL = getLinkLocation( getAbsolutePath(), resolve); + if (linkLocationPIDL != null && !cli.System.IntPtr.Zero.Equals( linkLocationPIDL ) ) { + try { + location = + Win32ShellFolderManager2.createShellFolderFromRelativePIDL(getDesktop(), + linkLocationPIDL); + } catch (InterruptedException e) { + // Return null + } catch (InternalError e) { + // Could be a link to a non-bindable object, such as a network connection + // TODO: getIShellFolder() should throw FileNotFoundException instead + } + } + return location; + } + }); + } + + /** + * Parse a display name into a PIDL relative to the current IShellFolder. + * @param name the name or relative path + * @return a pIDL for the path, may be {@link IntPtr#Zero} if not found + * @throws FileNotFoundException + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + cli.System.IntPtr parseDisplayName(String name) throws FileNotFoundException { + try { + return parseDisplayName0(getIShellFolder(), name); + } catch (IOException e) { + throw new FileNotFoundException("Could not find file " + name); + } + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + private static native cli.System.IntPtr parseDisplayName0(cli.System.Object pIShellFolder, String name) throws IOException; + + /** + * Returns the display name of an item in a folder + * @param parentIShellFolder the pointer to the IShellFolder interface of the parent folder + * @param relativePIDL single-level pIDL to the requested item within the parent folder + * @param attrs formatting attributes for the display name, refer to SHGDN in MSDN + * @return + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + private static native String getDisplayNameOf( cli.System.Object parentIShellFolder, cli.System.IntPtr relativePIDL, int attrs); + + /** + * @return The name used to display this shell folder + */ + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + public String getDisplayName() { + if (displayName == null) { + displayName = getDisplayNameOf(getParentIShellFolder(), getRelativePIDL(), SHGDN_NORMAL); + } + return displayName; + } + + // Return the folder type of a shell folder + @cli.System.Security.SecurityCriticalAttribute.Annotation + private static native String getFolderType(cli.System.IntPtr pIDL); + + /** + * @return The type of shell folder as a string + */ + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + public String getFolderType() { + if (folderType == null) { + folderType = getFolderType(getAbsolutePIDL()); + } + return folderType; + } + + // Return the executable type of a file system shell folder + private static native String getExecutableType(String path); + + /** + * @return The executable type as a string + */ + public String getExecutableType() { + if (!isFileSystem()) { + return null; + } + return getExecutableType(getAbsolutePath()); + } + + // Icons + + private static Map smallSystemImages = new HashMap(); + private static Map largeSystemImages = new HashMap(); + private static Map smallLinkedSystemImages = new HashMap(); + private static Map largeLinkedSystemImages = new HashMap(); + + /** + * Returns the icon index in the system image list + * @param parentIShellIcon the the pointer to the IShellIcon instance of the parent folder + * @param relativePIDL the relative pIDL to the requested item + * @return the system image list index for the icon of the item or zero, if there is no entry + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + private static native int getIconIndex(cli.System.Object parentIShellFolder, cli.System.IntPtr relativePIDL); + + // Return the icon of a file system shell folder in the form of an HICON + @cli.System.Security.SecurityCriticalAttribute.Annotation + private static native cli.System.IntPtr getIcon(String absolutePath, boolean getLargeIcon); + + @cli.System.Security.SecurityCriticalAttribute.Annotation + private static native cli.System.IntPtr extractIcon(cli.System.Object parentIShellFolder, cli.System.IntPtr relativePIDL, + boolean getLargeIcon); + + /** + * Returns the {@link Bitmap} for a HICON. + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + private static native Bitmap getIconBits(cli.System.IntPtr hIcon, int size); + + /** + * Disposes a icon handle + * @param hIcon the handle to be disposed + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + private static native void disposeIcon(cli.System.IntPtr hIcon); + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static native Bitmap getStandardViewButton0(int iconIndex); + + /** + * Creates a Java icon for a HICON pointer + * @param hIcon the handle for the icon + * @param getLargeIcon true for a large icon, false for a small icon + * @return the created image or null, if the handle is invalid + */ + @cli.System.Security.SecurityCriticalAttribute.Annotation + private static Image makeIcon(cli.System.IntPtr hIcon, boolean getLargeIcon) { + if (hIcon != null ) { + // Get the bits. This has the side effect of setting the imageHash value for this object. + Bitmap bitmap = getIconBits(hIcon, getLargeIcon ? 32 : 16 ); + if (bitmap == null) { + return null; + } + return new BufferedImage(bitmap); + } + return null; + } + + + /** + * @return The icon image used to display this shell folder + */ + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + public Image getIcon(boolean getLargeIcon) { + Image icon = getLargeIcon ? largeIcon : smallIcon; + if (icon == null) { + cli.System.IntPtr relativePIDL = getRelativePIDL(); + + if (isFileSystem() && parent != null) { + // These are cached per type (using the index in the system image list) + int index = getIconIndex( ((Win32ShellFolder2)parent).getIShellFolder(), relativePIDL); + if (index > 0) { + Map imageCache; + if (isLink()) { + imageCache = getLargeIcon ? largeLinkedSystemImages : smallLinkedSystemImages; + } else { + imageCache = getLargeIcon ? largeSystemImages : smallSystemImages; + } + icon = (Image) imageCache.get(Integer.valueOf(index)); + if (icon == null) { + cli.System.IntPtr hIcon = getIcon(getAbsolutePath(), getLargeIcon); + icon = makeIcon(hIcon, getLargeIcon); + disposeIcon(hIcon); + if (icon != null) { + imageCache.put(Integer.valueOf(index), icon); + } + } + } + } + + if (icon == null) { + // These are only cached per object + cli.System.IntPtr hIcon = extractIcon(getParentIShellFolder(), getRelativePIDL(), getLargeIcon); + icon = makeIcon(hIcon, getLargeIcon); + disposeIcon(hIcon); + } + + if (getLargeIcon) { + largeIcon = icon; + } else { + smallIcon = icon; + } + } + if (icon == null) { + icon = super .getIcon(getLargeIcon); + } + return icon; + } + + /** + * Gets an icon from the Windows system icon list as an Image + */ + static Image getShell32Icon(int iconID, boolean getLargeIcon) { + Bitmap bitmap = getShell32IconResourceAsBitmap(iconID, getLargeIcon); + if (bitmap == null) { + return null; + } + return new BufferedImage(bitmap); + } + + private static native Bitmap getShell32IconResourceAsBitmap(int iconID, boolean getLargeIcon); + + /** + * Returns the canonical form of this abstract pathname. Equivalent to + * new Win32ShellFolder2(getParentFile(), this.{@link java.io.File#getCanonicalPath}()). + * + * @see java.io.File#getCanonicalFile + */ + public File getCanonicalFile() throws IOException { + return this; + } + + /* + * Indicates whether this is a special folder (includes My Documents) + */ + public boolean isSpecial() { + return isPersonal || !isFileSystem() || (this == getDesktop()); + } + + /** + * Compares this object with the specified object for order. + * + * @see sun.awt.shell.ShellFolder#compareTo(File) + */ + public int compareTo(File file2) { + if (!(file2 instanceof Win32ShellFolder2)) { + if (isFileSystem() && !isSpecial()) { + return super.compareTo(file2); + } else { + return -1; // Non-file shellfolders sort before files + } + } + return Win32ShellFolderManager2.compareShellFolders(this, (Win32ShellFolder2) file2); + } + + // native constants from commctrl.h + private static final int LVCFMT_LEFT = 0; + private static final int LVCFMT_RIGHT = 1; + private static final int LVCFMT_CENTER = 2; + + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + public ShellFolderColumnInfo[] getFolderColumns() { + Object o = doGetColumnInfo(getIShellFolder()); + ShellFolderColumnInfo[] columns = (ShellFolderColumnInfo[]) o; + + if (columns != null) { + List notNullColumns = new ArrayList(); + for (int i = 0; i < columns.length; i++) { + ShellFolderColumnInfo column = columns[i]; + if (column != null) { + column.setAlignment(column.getAlignment() == LVCFMT_RIGHT ? SwingConstants.RIGHT + : column.getAlignment() == LVCFMT_CENTER ? SwingConstants.CENTER + : SwingConstants.LEADING); + + column.setComparator(new ColumnComparator(i)); + + notNullColumns.add(column); + } + } + columns = new ShellFolderColumnInfo[notNullColumns.size()]; + notNullColumns.toArray(columns); + } + return columns; + } + + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + public Object getFolderColumnValue(int column) { + return doGetColumnValue(getParentIShellFolder(), getRelativePIDL(), column); + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + private static native cli.System.Object /*ShellFolderColumnInfo[]*/ doGetColumnInfo( cli.System.Object iShellFolder2 ); + + @cli.System.Security.SecurityCriticalAttribute.Annotation + private static native Object doGetColumnValue(cli.System.Object parentIShellFolder2, cli.System.IntPtr childPIDL, int columnIdx); + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static native int compareIDsByColumn(cli.System.Object pParentIShellFolder, cli.System.IntPtr pidl1, cli.System.IntPtr pidl2, int columnIdx); + + private class ColumnComparator implements Comparator { + private final int columnIdx; + + public ColumnComparator(int columnIdx) { + this.columnIdx = columnIdx; + } + + // compares 2 objects within this folder by the specified column + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + public int compare(Object o, Object o1) { + if (o instanceof Win32ShellFolder2 && o1 instanceof Win32ShellFolder2) { + // delegates comparison to native method + return compareIDsByColumn(getIShellFolder(), + ((Win32ShellFolder2) o).getRelativePIDL(), + ((Win32ShellFolder2) o1).getRelativePIDL(), + columnIdx); + } + return 0; + } + } +} \ No newline at end of file diff --git a/openjdk/sun/awt/shell/Win32ShellFolderManager2.java b/openjdk/sun/awt/shell/Win32ShellFolderManager2.java new file mode 100644 index 0000000..09bbe97 --- /dev/null +++ b/openjdk/sun/awt/shell/Win32ShellFolderManager2.java @@ -0,0 +1,514 @@ +/* + * Copyright (c) 2003, 2014, 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.awt.shell; + +import java.awt.*; +import java.awt.image.BufferedImage; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.*; +import java.util.List; +import java.util.concurrent.*; +import java.util.stream.Stream; + +import cli.System.IntPtr; +import cli.System.Drawing.Bitmap; +import cli.System.Drawing.SystemIcons; + +import static sun.awt.shell.Win32ShellFolder2.*; +import sun.awt.OSInfo; +import sun.misc.ThreadGroupUtils; + +// NOTE: This class supersedes Win32ShellFolderManager, which was removed +// from distribution after version 1.4.2. + +/** + * @author Michael Martak + * @author Leif Samuelsson + * @author Kenneth Russell + * @since 1.4 + */ + +public class Win32ShellFolderManager2 extends ShellFolderManager { + + + public ShellFolder createShellFolder(File file) throws FileNotFoundException { + try { + return createShellFolder(getDesktop(), file); + } catch (InterruptedException e) { + throw new FileNotFoundException("Execution was interrupted"); + } + } + + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + static Win32ShellFolder2 createShellFolder(Win32ShellFolder2 parent, File file) + throws FileNotFoundException, InterruptedException { + cli.System.IntPtr pIDL = null; + try { + pIDL = parent.parseDisplayName(file.getCanonicalPath()); + } catch (IOException ex) { + pIDL = null; + } + if (pIDL == null || cli.System.IntPtr.Zero.Equals(pIDL) ) { + // Shouldn't happen but watch for it anyway + throw new FileNotFoundException("File " + file.getAbsolutePath() + " not found"); + } + + try { + return createShellFolderFromRelativePIDL(parent, pIDL); + } finally { + Win32ShellFolder2.releasePIDL(pIDL); + } + } + + @cli.System.Security.SecurityCriticalAttribute.Annotation + static Win32ShellFolder2 createShellFolderFromRelativePIDL(Win32ShellFolder2 parent, cli.System.IntPtr pIDL) + throws InterruptedException { + // Walk down this relative pIDL, creating new nodes for each of the entries + while (pIDL != null && !cli.System.IntPtr.Zero.Equals( pIDL ) ) { + cli.System.IntPtr curPIDL = Win32ShellFolder2.copyFirstPIDLEntry(pIDL); + if (curPIDL != null && !cli.System.IntPtr.Zero.Equals( curPIDL )) { + parent = new Win32ShellFolder2(parent, curPIDL); + pIDL = Win32ShellFolder2.getNextPIDLEntry(pIDL); + } else { + // The list is empty if the parent is Desktop and pIDL is a shortcut to Desktop + break; + } + } + return parent; + } + + private static final int VIEW_LIST = 2; + private static final int VIEW_DETAILS = 3; + private static final int VIEW_PARENTFOLDER = 8; + private static final int VIEW_NEWFOLDER = 11; + + private static final Image[] STANDARD_VIEW_BUTTONS = new Image[12]; + + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + private static Image getStandardViewButton(int iconIndex) { + Image result = STANDARD_VIEW_BUTTONS[iconIndex]; + + if (result != null) { + return result; + } + + Bitmap bitmap = Win32ShellFolder2.getStandardViewButton0(iconIndex); + if( bitmap != null ) { + result = new BufferedImage(bitmap); + STANDARD_VIEW_BUTTONS[iconIndex] = result; + } + + return result; + } + + // Special folders + private static Win32ShellFolder2 desktop; + private static Win32ShellFolder2 drives; + private static Win32ShellFolder2 recent; + private static Win32ShellFolder2 network; + private static Win32ShellFolder2 personal; + + static Win32ShellFolder2 getDesktop() { + if (desktop == null) { + try { + desktop = new Win32ShellFolder2(DESKTOP); + } catch (SecurityException e) { + // Ignore error + } catch (IOException e) { + // Ignore error + } catch (InterruptedException e) { + // Ignore error + } + } + return desktop; + } + + static Win32ShellFolder2 getDrives() { + if (drives == null) { + try { + drives = new Win32ShellFolder2(DRIVES); + } catch (SecurityException e) { + // Ignore error + } catch (IOException e) { + // Ignore error + } catch (InterruptedException e) { + // Ignore error + } + } + return drives; + } + + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + static Win32ShellFolder2 getRecent() { + if (recent == null) { + try { + String path = Win32ShellFolder2.getFileSystemPath(RECENT); + if (path != null) { + recent = createShellFolder(getDesktop(), new File(path)); + } + } catch (SecurityException e) { + // Ignore error + } catch (InterruptedException e) { + // Ignore error + } catch (IOException e) { + // Ignore error + } + } + return recent; + } + + static Win32ShellFolder2 getNetwork() { + if (network == null) { + try { + network = new Win32ShellFolder2(NETWORK); + } catch (SecurityException e) { + // Ignore error + } catch (IOException e) { + // Ignore error + } catch (InterruptedException e) { + // Ignore error + } + } + return network; + } + + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + static Win32ShellFolder2 getPersonal() { + if (personal == null) { + try { + String path = Win32ShellFolder2.getFileSystemPath(PERSONAL); + if (path != null) { + Win32ShellFolder2 desktop = getDesktop(); + personal = desktop.getChildByPath(path); + if (personal == null) { + personal = createShellFolder(getDesktop(), new File(path)); + } + if (personal != null) { + personal.setIsPersonal(); + } + } + } catch (SecurityException e) { + // Ignore error + } catch (InterruptedException e) { + // Ignore error + } catch (IOException e) { + // Ignore error + } + } + return personal; + } + + + private static File[] roots; + + /** + * @param key a String + * "fileChooserDefaultFolder": + * Returns a File - the default shellfolder for a new filechooser + * "roots": + * Returns a File[] - containing the root(s) of the displayable hierarchy + * "fileChooserComboBoxFolders": + * Returns a File[] - an array of shellfolders representing the list to + * show by default in the file chooser's combobox + * "fileChooserShortcutPanelFolders": + * Returns a File[] - an array of shellfolders representing well-known + * folders, such as Desktop, Documents, History, Network, Home, etc. + * This is used in the shortcut panel of the filechooser on Windows 2000 + * and Windows Me. + * "fileChooserIcon ": + * Returns an Image - icon can be ListView, DetailsView, UpFolder, NewFolder or + * ViewMenu (Windows only). + * "optionPaneIcon iconName": + * Returns an Image - icon from the system icon list + * + * @return An Object matching the key string. + */ + public Object get(String key) { + if (key.equals("fileChooserDefaultFolder")) { + File file = getPersonal(); + if (file == null) { + file = getDesktop(); + } + return checkFile(file); + } else if (key.equals("roots")) { + // Should be "History" and "Desktop" ? + if (roots == null) { + File desktop = getDesktop(); + if (desktop != null) { + roots = new File[] { desktop }; + } else { + roots = (File[])super.get(key); + } + } + return checkFiles(roots); + } else if (key.equals("fileChooserComboBoxFolders")) { + Win32ShellFolder2 desktop = getDesktop(); + + if (desktop != null && checkFile(desktop) != null) { + ArrayList folders = new ArrayList(); + Win32ShellFolder2 drives = getDrives(); + + Win32ShellFolder2 recentFolder = getRecent(); + if (recentFolder != null && OSInfo.getWindowsVersion().compareTo(OSInfo.WINDOWS_2000) >= 0) { + folders.add(recentFolder); + } + + folders.add(desktop); + // Add all second level folders + File[] secondLevelFolders = checkFiles(desktop.listFiles()); + Arrays.sort(secondLevelFolders); + for (File secondLevelFolder : secondLevelFolders) { + Win32ShellFolder2 folder = (Win32ShellFolder2) secondLevelFolder; + if (!folder.isFileSystem() || (folder.isDirectory() && !folder.isLink())) { + folders.add(folder); + // Add third level for "My Computer" + if (folder.equals(drives)) { + File[] thirdLevelFolders = checkFiles(folder.listFiles()); + if (thirdLevelFolders != null && thirdLevelFolders.length > 0) { + List thirdLevelFoldersList = Arrays.asList(thirdLevelFolders); + + folder.sortChildren(thirdLevelFoldersList); + folders.addAll(thirdLevelFoldersList); + } + } + } + } + return checkFiles(folders); + } else { + return super.get(key); + } + } else if (key.equals("fileChooserShortcutPanelFolders")) { + Toolkit toolkit = Toolkit.getDefaultToolkit(); + ArrayList folders = new ArrayList(); + int i = 0; + Object value; + do { + value = toolkit.getDesktopProperty("win.comdlg.placesBarPlace" + i++); + try { + if (value instanceof Integer) { + // A CSIDL + folders.add(new Win32ShellFolder2((Integer)value)); + } else if (value instanceof String) { + // A path + folders.add(createShellFolder(new File((String)value))); + } + } catch (IOException e) { + // Skip this value + } catch (InterruptedException e) { + // Return empty result + return new File[0]; + } + } while (value != null); + + if (folders.size() == 0) { + // Use default list of places + for (File f : new File[] { + getRecent(), getDesktop(), getPersonal(), getDrives(), getNetwork() + }) { + if (f != null) { + folders.add(f); + } + } + } + return checkFiles(folders); + } else if (key.startsWith("fileChooserIcon ")) { + String name = key.substring(key.indexOf(" ") + 1); + + int iconIndex; + + if (name.equals("ListView") || name.equals("ViewMenu")) { + iconIndex = VIEW_LIST; + } else if (name.equals("DetailsView")) { + iconIndex = VIEW_DETAILS; + } else if (name.equals("UpFolder")) { + iconIndex = VIEW_PARENTFOLDER; + } else if (name.equals("NewFolder")) { + iconIndex = VIEW_NEWFOLDER; + } else { + return null; + } + + return getStandardViewButton(iconIndex); + } else if (key.startsWith("optionPaneIcon ")) { + cli.System.Drawing.Icon icon; + if (key == "optionPaneIcon Error") { + icon = SystemIcons.get_Error(); + } else if (key == "optionPaneIcon Information") { + icon = SystemIcons.get_Information(); + } else if (key == "optionPaneIcon Question") { + icon = SystemIcons.get_Question(); + } else if (key == "optionPaneIcon Warning") { + icon = SystemIcons.get_Warning(); + } else { + return null; + } + return new BufferedImage(icon.ToBitmap()); + } else if (key.startsWith("shell32Icon ") || key.startsWith("shell32LargeIcon ")) { + String name = key.substring(key.indexOf(" ") + 1); + try { + int i = Integer.parseInt(name); + if (i >= 0) { + return Win32ShellFolder2.getShell32Icon(i, key.startsWith("shell32LargeIcon ")); + } + } catch (NumberFormatException ex) { + } + } + return null; + } + + private File checkFile(File file) { + SecurityManager sm = System.getSecurityManager(); + return (sm == null || file == null) ? file : checkFile(file, sm); + } + + private File checkFile(File file, SecurityManager sm) { + try { + sm.checkRead(file.getPath()); + return file; + } catch (SecurityException se) { + return null; + } + } + + private File[] checkFiles(File[] files) { + SecurityManager sm = System.getSecurityManager(); + if (sm == null || files == null || files.length == 0) { + return files; + } + return checkFiles(Arrays.stream(files), sm); + } + + private File[] checkFiles(List files) { + SecurityManager sm = System.getSecurityManager(); + if (sm == null || files.isEmpty()) { + return files.toArray(new File[files.size()]); + } + return checkFiles(files.stream(), sm); + } + + private File[] checkFiles(Stream filesStream, SecurityManager sm) { + return filesStream.filter((file) -> checkFile(file, sm) != null) + .toArray(File[]::new); + } + + /** + * Does dir represent a "computer" such as a node on the network, or + * "My Computer" on the desktop. + */ + public boolean isComputerNode(final File dir) { + if (dir != null && dir == getDrives()) { + return true; + } else { + String path = AccessController.doPrivileged(new PrivilegedAction() { + public String run() { + return dir.getAbsolutePath(); + } + }); + + return (path.startsWith("\\\\") && path.indexOf("\\", 2) < 0); //Network path + } + } + + public boolean isFileSystemRoot(File dir) { + //Note: Removable drives don't "exist" but are listed in "My Computer" + if (dir != null) { + Win32ShellFolder2 drives = getDrives(); + if (dir instanceof Win32ShellFolder2) { + Win32ShellFolder2 sf = (Win32ShellFolder2)dir; + if (sf.isFileSystem()) { + if (sf.parent != null) { + return sf.parent.equals(drives); + } + // else fall through ... + } else { + return false; + } + } + String path = dir.getPath(); + + if (path.length() != 3 || path.charAt(1) != ':') { + return false; + } + + File[] files = drives.listFiles(); + + return files != null && Arrays.asList(files).contains(dir); + } + return false; + } + + private static List topFolderList = null; + static int compareShellFolders(Win32ShellFolder2 sf1, Win32ShellFolder2 sf2) { + boolean special1 = sf1.isSpecial(); + boolean special2 = sf2.isSpecial(); + + if (special1 || special2) { + if (topFolderList == null) { + ArrayList tmpTopFolderList = new ArrayList(); + tmpTopFolderList.add(Win32ShellFolderManager2.getPersonal()); + tmpTopFolderList.add(Win32ShellFolderManager2.getDesktop()); + tmpTopFolderList.add(Win32ShellFolderManager2.getDrives()); + tmpTopFolderList.add(Win32ShellFolderManager2.getNetwork()); + topFolderList = tmpTopFolderList; + } + int i1 = topFolderList.indexOf(sf1); + int i2 = topFolderList.indexOf(sf2); + if (i1 >= 0 && i2 >= 0) { + return (i1 - i2); + } else if (i1 >= 0) { + return -1; + } else if (i2 >= 0) { + return 1; + } + } + + // Non-file shellfolders sort before files + if (special1 && !special2) { + return -1; + } else if (special2 && !special1) { + return 1; + } + + return compareNames(sf1.getAbsolutePath(), sf2.getAbsolutePath()); + } + + static int compareNames(String name1, String name2) { + // First ignore case when comparing + int diff = name1.compareToIgnoreCase(name2); + if (diff != 0) { + return diff; + } else { + // May differ in case (e.g. "mail" vs. "Mail") + // We need this test for consistent sorting + return name1.compareTo(name2); + } + } +} diff --git a/openjdk/sun/awt/windows/WPrinterJob.java b/openjdk/sun/awt/windows/WPrinterJob.java new file mode 100644 index 0000000..08756ef --- /dev/null +++ b/openjdk/sun/awt/windows/WPrinterJob.java @@ -0,0 +1,126 @@ +/* + Copyright (C) 2009 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.awt.windows; + +import ikvm.awt.IkvmToolkit; + +import java.awt.Graphics; +import java.awt.HeadlessException; +import java.awt.Toolkit; +import java.awt.image.BufferedImage; +import java.awt.print.PageFormat; +import java.awt.print.Pageable; +import java.awt.print.Paper; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; + +import javax.print.PrintService; +import javax.print.attribute.PrintRequestAttributeSet; + +import cli.System.Drawing.Printing.*; + +import sun.print.PeekGraphics; +import sun.print.PrintPeer; +import sun.print.RasterPrinterJob; +import sun.print.Win32PrintService; + +import ikvm.internal.NotYetImplementedError; + +/** + * @author Volker Berlin + */ +public class WPrinterJob extends RasterPrinterJob{ + + @Override + protected void abortDoc(){ + throw new NotYetImplementedError(); + } + + @Override + protected void endDoc() throws PrinterException{ + throw new NotYetImplementedError(); + } + + @Override + protected void endPage(PageFormat format, Printable painter, int index) throws PrinterException{ + throw new NotYetImplementedError(); + } + + @Override + protected double getPhysicalPageHeight(Paper p){ + throw new NotYetImplementedError(); + } + + @Override + protected double getPhysicalPageWidth(Paper p){ + throw new NotYetImplementedError(); + } + + @Override + protected double getPhysicalPrintableHeight(Paper p){ + throw new NotYetImplementedError(); + } + + @Override + protected double getPhysicalPrintableWidth(Paper p){ + throw new NotYetImplementedError(); + } + + @Override + protected double getPhysicalPrintableX(Paper p){ + throw new NotYetImplementedError(); + } + + @Override + protected double getPhysicalPrintableY(Paper p){ + throw new NotYetImplementedError(); + } + + @Override + protected double getXRes(){ + throw new NotYetImplementedError(); + } + + @Override + protected double getYRes(){ + throw new NotYetImplementedError(); + } + + @Override + protected void printBand(byte[] data, int x, int y, int width, int height) throws PrinterException{ + throw new NotYetImplementedError(); + } + + @Override + protected void startDoc() throws PrinterException{ + throw new NotYetImplementedError(); + } + + @Override + protected void startPage(PageFormat format, Printable painter, int index, boolean paperChanged) + throws PrinterException{ + throw new NotYetImplementedError(); + } +} diff --git a/openjdk/sun/font/CompositeFont.java b/openjdk/sun/font/CompositeFont.java new file mode 100644 index 0000000..ba4c59f --- /dev/null +++ b/openjdk/sun/font/CompositeFont.java @@ -0,0 +1,152 @@ +/* + Copyright (C) 2009, 2011 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.font; + +import java.awt.font.FontRenderContext; +import java.awt.geom.AffineTransform; +import java.util.Locale; + +import cli.System.Drawing.Font; +import ikvm.internal.NotYetImplementedError; + + +/** + * + */ +public class CompositeFont extends Font2D{ + + private final PhysicalFont delegate; + + + public CompositeFont(PhysicalFont physicalFont, CompositeFont dialog2d) { + delegate = physicalFont; + } + + public CompositeFont(Font2D font2d){ + delegate = (PhysicalFont)font2d; + } + + public int getNumSlots() { + throw new NotYetImplementedError(); + } + + public PhysicalFont getSlotFont(int slot) { + if( slot == 0){ + return delegate; + } + throw new NotYetImplementedError(); + } + + public boolean isStdComposite() { + throw new NotYetImplementedError(); + } + + @Override + public int getStyle(){ + return delegate.getStyle(); + } + + @Override + public Font createNetFont(java.awt.Font font){ + return delegate.createNetFont(font); + } + + public FontStrike getStrike(java.awt.Font font, AffineTransform devTx, + int aa, int fm) { + return delegate.getStrike(font, devTx, aa, fm); + } + + public FontStrike getStrike(java.awt.Font font, FontRenderContext frc) { + return delegate.getStrike(font, frc); + } + + public void removeFromCache(FontStrikeDesc desc) { + delegate.removeFromCache(desc); + } + + public void getFontMetrics(java.awt.Font font, AffineTransform identityTx, + Object antiAliasingHint, Object fractionalMetricsHint, + float[] metrics) { + delegate.getFontMetrics(font, identityTx, antiAliasingHint, + fractionalMetricsHint, metrics); + } + + public void getStyleMetrics(float pointSize, float[] metrics, int offset) { + delegate.getStyleMetrics(pointSize, metrics, offset); + } + + public void getFontMetrics(java.awt.Font font, FontRenderContext frc, + float[] metrics) { + delegate.getFontMetrics(font, frc, metrics); + } + + public boolean useAAForPtSize(int ptsize) { + return delegate.useAAForPtSize(ptsize); + } + + public boolean hasSupplementaryChars() { + return delegate.hasSupplementaryChars(); + } + + public String getPostscriptName() { + return delegate.getPostscriptName(); + } + + public String getFontName(Locale l) { + return delegate.getFontName(l); + } + + public String getFamilyName(Locale l) { + return delegate.getFamilyName(l); + } + + public int getNumGlyphs() { + return delegate.getNumGlyphs(); + } + + public int charToGlyph(int wchar) { + return delegate.charToGlyph(wchar); + } + + public int getMissingGlyphCode() { + return delegate.getMissingGlyphCode(); + } + + public boolean canDisplay(char c) { + return delegate.canDisplay(c); + } + + public boolean canDisplay(int cp) { + return delegate.canDisplay(cp); + } + + public byte getBaselineFor(char c) { + return delegate.getBaselineFor(c); + } + + public float getItalicAngle(java.awt.Font font, AffineTransform at, + Object aaHint, Object fmHint) { + return delegate.getItalicAngle(font, at, aaHint, fmHint); + } +} diff --git a/openjdk/sun/font/Font2D.java b/openjdk/sun/font/Font2D.java new file mode 100644 index 0000000..7fc9eda --- /dev/null +++ b/openjdk/sun/font/Font2D.java @@ -0,0 +1,221 @@ +/* + Copyright (C) 2009 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.font; + +import java.awt.Font; +import java.awt.font.FontRenderContext; +import java.awt.geom.AffineTransform; +import java.util.Locale; + +import sun.awt.SunHints; + + + +/** + * + */ +public abstract class Font2D{ + + public Font2DHandle handle = new Font2DHandle(this); + + /* SunGraphics2D has font, tx, aa and fm. From this info + * can get a Strike object from the cache, creating it if necessary. + * This code is designed for multi-threaded access. + * For that reason it creates a local FontStrikeDesc rather than filling + * in a shared one. Up to two AffineTransforms and one FontStrikeDesc will + * be created by every lookup. This appears to perform more than + * adequately. But it may make sense to expose FontStrikeDesc + * as a parameter so a caller can use its own. + * In such a case if a FontStrikeDesc is stored as a key then + * we would need to use a private copy. + * + * Note that this code doesn't prevent two threads from creating + * two different FontStrike instances and having one of the threads + * overwrite the other in the map. This is likely to be a rare + * occurrence and the only consequence is that these callers will have + * different instances of the strike, and there'd be some duplication of + * population of the strikes. However since users of these strikes are + * transient, then the one that was overwritten would soon be freed. + * If there is any problem then a small synchronized block would be + * required with its attendant consequences for MP scalability. + */ + public FontStrike getStrike(Font font, AffineTransform devTx, int aa, int fm){ + return getStrike(font, new FontRenderContext(devTx, aa == SunHints.INTVAL_TEXT_ANTIALIAS_ON, + fm == SunHints.INTVAL_FRACTIONALMETRICS_ON)); + } + + public FontStrike getStrike(Font font, FontRenderContext frc) { + // TODO Auto-generated method stub + return null; + } + + public void removeFromCache(FontStrikeDesc desc){ + // TODO Auto-generated method stub + + } + + /** + * The length of the metrics array must be >= 8. This method will + * store the following elements in that array before returning: + * metrics[0]: ascent + * metrics[1]: descent + * metrics[2]: leading + * metrics[3]: max advance + * metrics[4]: strikethrough offset + * metrics[5]: strikethrough thickness + * metrics[6]: underline offset + * metrics[7]: underline thickness + */ + public void getFontMetrics(Font font, AffineTransform identityTx, Object antiAliasingHint, + Object fractionalMetricsHint, float[] metrics){ + FontRenderContext frc = new FontRenderContext(identityTx, antiAliasingHint, fractionalMetricsHint); + StrikeMetrics strikeMetrics = getStrike(font, frc).getFontMetrics(); + metrics[0] = strikeMetrics.getAscent(); + metrics[1] = strikeMetrics.getDescent(); + metrics[2] = strikeMetrics.getLeading(); + metrics[3] = strikeMetrics.getMaxAdvance(); + + getStyleMetrics(font.getSize2D(), metrics, 4); + } + + /** + * The length of the metrics array must be >= offset+4, and offset must be + * >= 0. Typically offset is 4. This method will + * store the following elements in that array before returning: + * metrics[off+0]: strikethrough offset + * metrics[off+1]: strikethrough thickness + * metrics[off+2]: underline offset + * metrics[off+3]: underline thickness + * + * Note that this implementation simply returns default values; + * subclasses can override this method to provide more accurate values. + */ + public void getStyleMetrics(float pointSize, float[] metrics, int offset) { + metrics[offset] = -metrics[0] / 2.5f; + metrics[offset+1] = pointSize / 12; + metrics[offset+2] = metrics[offset+1] / 1.5f; + metrics[offset+3] = metrics[offset+1]; + } + + /** + * The length of the metrics array must be >= 4. This method will + * store the following elements in that array before returning: + * metrics[0]: ascent + * metrics[1]: descent + * metrics[2]: leading + * metrics[3]: max advance + */ + public void getFontMetrics(Font font, FontRenderContext frc, + float metrics[]) { + StrikeMetrics strikeMetrics = getStrike(font, frc).getFontMetrics(); + metrics[0] = strikeMetrics.getAscent(); + metrics[1] = strikeMetrics.getDescent(); + metrics[2] = strikeMetrics.getLeading(); + metrics[3] = strikeMetrics.getMaxAdvance(); + } + + /* + * All the important subclasses override this which is principally for + * the TrueType 'gasp' table. + */ + public boolean useAAForPtSize(int ptsize) { + return true; + } + + public boolean hasSupplementaryChars() { + return false; + } + + /* The following methods implement public methods on java.awt.Font */ + public String getPostscriptName(){ + // TODO Auto-generated method stub + return null; + } + + public String getFontName(Locale l){ + // TODO Auto-generated method stub + return null; + } + + public String getFamilyName(Locale l){ + // TODO Auto-generated method stub + return null; + } + + public int getNumGlyphs(){ + // TODO Auto-generated method stub + return 0; + } + + public int charToGlyph(int wchar) { + return wchar; + } + + public int getMissingGlyphCode(){ + // TODO Auto-generated method stub + return 0; + } + + public boolean canDisplay(char c){ + //HACK There is no equivalent in C# http://msdn2.microsoft.com/en-us/library/sf4dhbw8(VS.80).aspx + return true; + } + + public boolean canDisplay(int cp){ + //HACK There is no equivalent in C# http://msdn2.microsoft.com/en-us/library/sf4dhbw8(VS.80).aspx + return true; + } + + public byte getBaselineFor(char c) { + return Font.ROMAN_BASELINE; + } + + public float getItalicAngle(Font font, AffineTransform at, + Object aaHint, Object fmHint) { + /* hardwire psz=12 as that's typical and AA vs non-AA for 'gasp' mode + * isn't important for the caret slope of this rarely used API. + */ + int aa = FontStrikeDesc.getAAHintIntVal(aaHint, this, 12); + int fm = FontStrikeDesc.getFMHintIntVal(fmHint); + FontStrike strike = getStrike(font, at, aa, fm); + StrikeMetrics metrics = strike.getFontMetrics(); + if (metrics.ascentY == 0 || metrics.ascentX == 0) { + return 0f; + } else { + /* ascent is "up" from the baseline so its typically + * a negative value, so we need to compensate + */ + return metrics.ascentX/-metrics.ascentY; + } + } + + /** Returns the "real" style of this Font2D. Eg the font face + * Lucida Sans Bold" has a real style of Font.BOLD, even though + * it may be able to used to simulate bold italic + */ + public abstract int getStyle(); + + public abstract cli.System.Drawing.Font createNetFont(Font font); + +} diff --git a/openjdk/sun/font/FontManager.java b/openjdk/sun/font/FontManager.java new file mode 100644 index 0000000..3f02cf0 --- /dev/null +++ b/openjdk/sun/font/FontManager.java @@ -0,0 +1,415 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (C) 2009 - 2011 Volker Berlin (i-net software) + * 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.font; + +import java.awt.Font; +import java.lang.reflect.Method; +import java.util.Locale; +import java.util.concurrent.ConcurrentHashMap; + +import javax.swing.plaf.FontUIResource; + +import cli.System.Drawing.FontFamily; +import ikvm.internal.NotYetImplementedError; + +/* + * Interface between Java Fonts (java.awt.Font) and the underlying + * font files/native font resources and the Java and native font scalers. + */ +public final class FontManager { + + public static final int NO_FALLBACK = 0; + public static final int PHYSICAL_FALLBACK = 1; + public static final int LOGICAL_FALLBACK = 2; + + /* deprecated, unsupported hack - actually invokes a bug! */ + private static boolean usePlatformFontMetrics = false; + + private static ConcurrentHashMap fontNameCache = new ConcurrentHashMap(); + + private static final Method getFont2D; + static{ + try{ + getFont2D = Font.class.getDeclaredMethod("getFont2D"); + getFont2D.setAccessible(true); + }catch(NoSuchMethodException ex){ + NoClassDefFoundError error = new NoClassDefFoundError(ex.toString()); + error.initCause(ex); + throw error; + } + } + + /* Revise the implementation to in fact mean "font is a composite font. + * This ensures that Swing components will always benefit from the + * fall back fonts + */ + public static boolean fontSupportsDefaultEncoding(Font font) { + // In Java the font must be a instanceof CompositeFont + // because .NET fonts are all already Composite Fonts (I think) that we can return true + // and does not need to implements CompositeFont + return true; + } + + /** + * This method is provided for internal and exclusive use by Swing. + * + * It may be used in conjunction with fontSupportsDefaultEncoding(Font) + * In the event that a desktop properties font doesn't directly + * support the default encoding, (ie because the host OS supports + * adding support for the current locale automatically for native apps), + * then Swing calls this method to get a font which uses the specified + * font for the code points it covers, but also supports this locale + * just as the standard composite fonts do. + * Note: this will over-ride any setting where an application + * specifies it prefers locale specific composite fonts. + * The logic for this, is that this method is used only where the user or + * application has specified that the native L&F be used, and that + * we should honour that request to use the same font as native apps use. + * + * The behaviour of this method is to construct a new composite + * Font object that uses the specified physical font as its first + * component, and adds all the components of "dialog" as fall back + * components. + * The method currently assumes that only the size and style attributes + * are set on the specified font. It doesn't copy the font transform or + * other attributes because they aren't set on a font created from + * the desktop. This will need to be fixed if use is broadened. + * + * Operations such as Font.deriveFont will work properly on the + * font returned by this method for deriving a different point size. + * Additionally it tries to support a different style by calling + * getNewComposite() below. That also supports replacing slot zero + * with a different physical font but that is expected to be "rare". + * Deriving with a different style is needed because its been shown + * that some applications try to do this for Swing FontUIResources. + * Also operations such as new Font(font.getFontName(..), Font.PLAIN, 14); + * will NOT yield the same result, as the new underlying CompositeFont + * cannot be "looked up" in the font registry. + * This returns a FontUIResource as that is the Font sub-class needed + * by Swing. + * Suggested usage is something like : + * FontUIResource fuir; + * Font desktopFont = getDesktopFont(..); + * // NOTE even if fontSupportsDefaultEncoding returns true because + * // you get Tahoma and are running in an English locale, you may + * // still want to just call getCompositeFontUIResource() anyway + * // as only then will you get fallback fonts - eg for CJK. + * if (FontManager.fontSupportsDefaultEncoding(desktopFont)) { + * fuir = new FontUIResource(..); + * } else { + * fuir = FontManager.getCompositeFontUIResource(desktopFont); + * } + * return fuir; + */ + public static FontUIResource getCompositeFontUIResource(Font font) { + throw new NotYetImplementedError(); + } + + public static Font2D getNewComposite(String family, int style, Font2D handle) { + throw new NotYetImplementedError(); + } + + /* + * return String representation of style prepended with "." + * This is useful for performance to avoid unnecessary string operations. + */ + private static String dotStyleStr(int num) { + switch(num){ + case Font.BOLD: + return ".bold"; + case Font.ITALIC: + return ".italic"; + case Font.ITALIC | Font.BOLD: + return ".bolditalic"; + default: + return ".plain"; + } + } + + /* + * The client supplies a name and a style. + * The name could be a family name, or a full name. + * A font may exist with the specified style, or it may + * exist only in some other style. For non-native fonts the scaler + * may be able to emulate the required style. + */ + public static Font2D findFont2D(String name, int style, int fallback){ + String lowerCaseName = name.toLowerCase(Locale.ENGLISH); + String mapName = lowerCaseName + dotStyleStr(style); + Font2D font2D = fontNameCache.get(mapName); + + if(font2D != null){ + return font2D; + } + font2D = new PhysicalFont(name,style); + fontNameCache.put(mapName, font2D); + return font2D; + } + + /** + * Create a new Font2D without caching. This is used from createFont + * + * @param family + * .NET FontFamily + * @param style + * the style + * @return a Font2D + */ + public static Font2D createFont2D( FontFamily family, int style ) { + return new PhysicalFont( family, style ); + } + + /* This method can be more efficient as it will only need to + * do the lookup once, and subsequent calls on the java.awt.Font + * instance can utilise the cached Font2D on that object. + * Its unfortunate it needs to be a native method, but the font2D + * variable has to be private. + */ + public static Font2D getFont2D(Font font){ + try{ + return (Font2D)getFont2D.invoke(font); + }catch(Exception ex){ + throw new RuntimeException(ex); + } + } + + /* Stuff below was in NativeFontWrapper and needed a new home */ + + /* + * Workaround for apps which are dependent on a font metrics bug + * in JDK 1.1. This is an unsupported win32 private setting. + */ + public static boolean usePlatformFontMetrics() { + return usePlatformFontMetrics; + } + + /* This method doesn't check if alternates are selected in this app + * context. Its used by the FontMetrics caching code which in such + * a case cannot retrieve a cached metrics solely on the basis of + * the Font.equals() method since it needs to also check if the Font2D + * is the same. + * We also use non-standard composites for Swing native L&F fonts on + * Windows. In that case the policy is that the metrics reported are + * based solely on the physical font in the first slot which is the + * visible java.awt.Font. So in that case the metrics cache which tests + * the Font does what we want. In the near future when we expand the GTK + * logical font definitions we may need to revisit this if GTK reports + * combined metrics instead. For now though this test can be simple. + */ + static boolean maybeUsingAlternateCompositeFonts() { + // TODO Auto-generated method stub + return false; + } + + public static synchronized void preferLocaleFonts() { + // TODO Auto-generated method stub + + } + + public static synchronized void preferProportionalFonts() { + // TODO Auto-generated method stub + } + + public static boolean registerFont(Font font) { + /* This method should not be called with "null". + * It is the caller's responsibility to ensure that. + */ + // TODO Auto-generated method stub + return false; + } + + /* This is called by Swing passing in a fontconfig family name + * such as "sans". In return Swing gets a FontUIResource instance + * that has queried fontconfig to resolve the font(s) used for this. + * Fontconfig will if asked return a list of fonts to give the largest + * possible code point coverage. + * For now we use only the first font returned by fontconfig, and + * back it up with the most closely matching JDK logical font. + * Essentially this means pre-pending what we return now with fontconfig's + * preferred physical font. This could lead to some duplication in cases, + * if we already included that font later. We probably should remove such + * duplicates, but it is not a significant problem. It can be addressed + * later as part of creating a Composite which uses more of the + * same fonts as fontconfig. At that time we also should pay more + * attention to the special rendering instructions fontconfig returns, + * such as whether we should prefer embedded bitmaps over antialiasing. + * There's no way to express that via a Font at present. + */ + public static FontUIResource getFontConfigFUIR( String fcFamily, int style, int size ) { + return new FontUIResource( fcFamily, style, size ); + } + + /* The following fields and methods which relate to layout + * perhaps belong in some other class but FontManager is already + * widely used as an entry point for other JDK code that needs + * access to the font system internals. + */ + + /** + * Referenced by code in the JDK which wants to test for the + * minimum char code for which layout may be required. + * Note that even basic latin text can benefit from ligatures, + * eg "ffi" but we presently apply those only if explicitly + * requested with TextAttribute.LIGATURES_ON. + * The value here indicates the lowest char code for which failing + * to invoke layout would prevent acceptable rendering. + */ + public static final int MIN_LAYOUT_CHARCODE = 0x0300; + + /** + * Referenced by code in the JDK which wants to test for the + * maximum char code for which layout may be required. + * Note this does not account for supplementary characters + * where the caller interprets 'layout' to mean any case where + * one 'char' (ie the java type char) does not map to one glyph + */ + public static final int MAX_LAYOUT_CHARCODE = 0x206F; + + /* If the character code falls into any of a number of unicode ranges + * where we know that simple left->right layout mapping chars to glyphs + * 1:1 and accumulating advances is going to produce incorrect results, + * we want to know this so the caller can use a more intelligent layout + * approach. A caller who cares about optimum performance may want to + * check the first case and skip the method call if its in that range. + * Although there's a lot of tests in here, knowing you can skip + * CTL saves a great deal more. The rest of the checks are ordered + * so that rather than checking explicitly if (>= start & <= end) + * which would mean all ranges would need to be checked so be sure + * CTL is not needed, the method returns as soon as it recognises + * the code point is outside of a CTL ranges. + * NOTE: Since this method accepts an 'int' it is asssumed to properly + * represent a CHARACTER. ie it assumes the caller has already + * converted surrogate pairs into supplementary characters, and so + * can handle this case and doesn't need to be told such a case is + * 'complex'. + */ + static boolean isComplexCharCode(int code) { + + if (code < MIN_LAYOUT_CHARCODE || code > MAX_LAYOUT_CHARCODE) { + return false; + } + else if (code <= 0x036f) { + // Trigger layout for combining diacriticals 0x0300->0x036f + return true; + } + else if (code < 0x0590) { + // No automatic layout for Greek, Cyrillic, Armenian. + return false; + } + else if (code <= 0x06ff) { + // Hebrew 0590 - 05ff + // Arabic 0600 - 06ff + return true; + } + else if (code < 0x0900) { + return false; // Syriac and Thaana + } + else if (code <= 0x0e7f) { + // if Indic, assume shaping for conjuncts, reordering: + // 0900 - 097F Devanagari + // 0980 - 09FF Bengali + // 0A00 - 0A7F Gurmukhi + // 0A80 - 0AFF Gujarati + // 0B00 - 0B7F Oriya + // 0B80 - 0BFF Tamil + // 0C00 - 0C7F Telugu + // 0C80 - 0CFF Kannada + // 0D00 - 0D7F Malayalam + // 0D80 - 0DFF Sinhala + // 0E00 - 0E7F if Thai, assume shaping for vowel, tone marks + return true; + } + else if (code < 0x1780) { + return false; + } + else if (code <= 0x17ff) { // 1780 - 17FF Khmer + return true; + } + else if (code < 0x200c) { + return false; + } + else if (code <= 0x200d) { // zwj or zwnj + return true; + } + else if (code >= 0x202a && code <= 0x202e) { // directional control + return true; + } + else if (code >= 0x206a && code <= 0x206f) { // directional control + return true; + } + return false; + } + + /* This is almost the same as the method above, except it takes a + * char which means it may include undecoded surrogate pairs. + * The distinction is made so that code which needs to identify all + * cases in which we do not have a simple mapping from + * char->unicode character->glyph can be be identified. + * For example measurement cannot simply sum advances of 'chars', + * the caret in editable text cannot advance one 'char' at a time, etc. + * These callers really are asking for more than whether 'layout' + * needs to be run, they need to know if they can assume 1->1 + * char->glyph mapping. + */ + static boolean isNonSimpleChar(char ch) { + return + isComplexCharCode(ch) || + (ch >= CharToGlyphMapper.HI_SURROGATE_START && + ch <= CharToGlyphMapper.LO_SURROGATE_END); + } + + /** + * If there is anything in the text which triggers a case + * where char->glyph does not map 1:1 in straightforward + * left->right ordering, then this method returns true. + * Scripts which might require it but are not treated as such + * due to JDK implementations will not return true. + * ie a 'true' return is an indication of the treatment by + * the implementation. + * Whether supplementary characters should be considered is dependent + * on the needs of the caller. Since this method accepts the 'char' type + * then such chars are always represented by a pair. From a rendering + * perspective these will all (in the cases I know of) still be one + * unicode character -> one glyph. But if a caller is using this to + * discover any case where it cannot make naive assumptions about + * the number of chars, and how to index through them, then it may + * need the option to have a 'true' return in such a case. + */ + public static boolean isComplexText(char [] chs, int start, int limit) { + + for (int i = start; i < limit; i++) { + if (chs[i] < MIN_LAYOUT_CHARCODE) { + continue; + } + else if (isNonSimpleChar(chs[i])) { + return true; + } + } + return false; + } + +} diff --git a/openjdk/sun/font/GlyphLayout.java b/openjdk/sun/font/GlyphLayout.java new file mode 100644 index 0000000..3d6ed7a --- /dev/null +++ b/openjdk/sun/font/GlyphLayout.java @@ -0,0 +1,76 @@ +/* + Copyright (C) 2009, 2011 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.font; + +import java.awt.Font; +import java.awt.font.FontRenderContext; + + + +/** + * + */ +public class GlyphLayout{ + + private static GlyphLayout glyphLayout = new GlyphLayout(); + + /** + * Return a new instance of GlyphLayout, using the provided layout engine factory. + * If null, the system layout engine factory will be used. + */ + public static GlyphLayout get(Object lef) { + return glyphLayout; //current this class has no state + } + + /** + * Return the old instance of GlyphLayout when you are done. This enables reuse + * of GlyphLayout objects. + */ + public static void done(GlyphLayout gl) { + } + + /** + * Create a glyph vector. + * @param font the font to use + * @param frc the font render context + * @param text the text, including optional context before start and after start + count + * @param offset the start of the text to lay out + * @param count the length of the text to lay out + * @param flags bidi and context flags {@see #java.awt.Font} + * @param result a StandardGlyphVector to modify, can be null + * @return the layed out glyphvector, if result was passed in, it is returned + */ + public StandardGlyphVector layout(Font font, FontRenderContext frc, + char[] text, int offset, int count, + int flags, StandardGlyphVector result) + { + if (text == null || offset < 0 || count < 0 || (count > text.length - offset)) { + throw new IllegalArgumentException(); + } + + return new StandardGlyphVector(font, text, offset, count, frc); + } + + +} diff --git a/openjdk/sun/font/PhysicalFont.java b/openjdk/sun/font/PhysicalFont.java new file mode 100644 index 0000000..ad9499b --- /dev/null +++ b/openjdk/sun/font/PhysicalFont.java @@ -0,0 +1,299 @@ +/* + Copyright (C) 2009, 2010 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.font; + +import java.awt.Font; +import java.awt.font.FontRenderContext; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.Locale; + +import cli.System.Drawing.FontFamily; +import cli.System.Drawing.FontStyle; +import cli.System.Globalization.CultureInfo; + +/** + * A Font2D implementation that based on .NET fonts. It replace the equals naming Sun class. + * A Font2D is define with the font name and the font style but it is independent of the size; + */ +class PhysicalFont extends Font2D{ + + private final FontFamily family; + + private String familyName; // family name for logical fonts + + private final FontStyle style; + + private static final FontStyle REGULAR = FontStyle.wrap(FontStyle.Regular); + + private static final FontStyle BOLD = FontStyle.wrap(FontStyle.Bold); + + private static final FontStyle ITALIC = FontStyle.wrap(FontStyle.Italic); + + private static final FontStyle BOLD_ITALIC = FontStyle.wrap(FontStyle.Bold + FontStyle.Italic); + + private static final cli.System.Drawing.GraphicsUnit PIXEL = cli.System.Drawing.GraphicsUnit + .wrap(cli.System.Drawing.GraphicsUnit.Pixel); + + //for method getStyleMetrics + //for Reflection to the .NET 3.0 API in namespace System.Windows.Media of PresentationCore + //If we switch to .NET 3.0 then we can access it directly + private static boolean isMediaLoaded; + private static Class classMediaFontFamily; + private static Constructor ctorMediaFontFamily; + private static Method getFamilyTypefaces; + private static Method getItem; + private static Method getStrikethroughPosition; + private static Method getStrikethroughThickness; + private static Method getUnderlinePosition; + private static Method getUnderlineThickness; + private float strikethroughPosition; + private float strikethroughThickness; + private float underlinePosition; + private float underlineThickness; + + + PhysicalFont(String name, int style){ + this.family = createFontFamily(name); + this.style = createFontStyle(family, style); + } + + PhysicalFont(FontFamily family, int style){ + this.family = family; + this.style = createFontStyle(family, style); + } + + + + /** + * {@inheritDoc} + */ + @Override + public cli.System.Drawing.Font createNetFont(Font font){ + float size2D = font.getSize2D(); + if(size2D <= 0){ + size2D = 1; + } + return new cli.System.Drawing.Font(family, size2D, style, PIXEL); + } + + /** + * Search for .NET FamilyName. For logical fonts it set the variable familyName + * @param name the name of the font. + * @return ever a FontFamily + */ + private FontFamily createFontFamily(String name){ + if(Font.MONOSPACED.equalsIgnoreCase(name)){ + familyName = Font.MONOSPACED; + return FontFamily.get_GenericMonospace(); + } + if(Font.SERIF.equalsIgnoreCase(name)){ + familyName = Font.SERIF; + return FontFamily.get_GenericSerif(); + } + if(name == null || Font.SANS_SERIF.equalsIgnoreCase(name)){ + familyName = Font.SANS_SERIF; + return FontFamily.get_GenericSansSerif(); + } + if(Font.DIALOG.equalsIgnoreCase(name)){ + familyName = Font.DIALOG; + return FontFamily.get_GenericSansSerif(); + } + if(Font.DIALOG_INPUT.equalsIgnoreCase(name)){ + familyName = Font.DIALOG_INPUT; + return FontFamily.get_GenericSansSerif(); + } + try{ + if(false) throw new cli.System.ArgumentException(); + return new FontFamily(name); + }catch(cli.System.ArgumentException ex){ + // continue + } + + //now we want map specific Name to a shorter Family Name like "Arial Bold" --> "Arial" + String shortName = name; + int spaceIdx = shortName.lastIndexOf(' '); + while(spaceIdx > 0){ + shortName = shortName.substring(0, spaceIdx).trim(); + try{ + if(false) throw new cli.System.ArgumentException(); + return new FontFamily(shortName); + }catch(cli.System.ArgumentException ex){ + // continue + } + spaceIdx = shortName.lastIndexOf(' '); + } + + //now we want map generic names to specific families like "courier" --> "Courier New" + FontFamily[] fontFanilies = FontFamily.get_Families(); + name = name.toLowerCase(); + for (int i = 0; i < fontFanilies.length; i++) { + FontFamily fontFamily = fontFanilies[i]; + if(fontFamily.get_Name().toLowerCase().startsWith(name)){ + return fontFamily; + } + } + + //we have not find a valid font, we use the default font + familyName = Font.DIALOG; + return FontFamily.get_GenericSansSerif(); + } + + + private static FontStyle createFontStyle(FontFamily family, int style){ + int fs = FontStyle.Regular; + if((style & java.awt.Font.BOLD) != 0){ + fs |= FontStyle.Bold; + } + if((style & java.awt.Font.ITALIC) != 0){ + fs |= FontStyle.Italic; + } + FontStyle fontStyle = FontStyle.wrap(fs); + if(!family.IsStyleAvailable(fontStyle)){ + // Some Fonts (for example Aharoni) does not support Regular style. This throw an exception else it is not + // documented. + if(family.IsStyleAvailable(REGULAR)){ + fontStyle = REGULAR; + }else if(family.IsStyleAvailable(BOLD)){ + fontStyle = BOLD; + }else if(family.IsStyleAvailable(ITALIC)){ + fontStyle = ITALIC; + }else if(family.IsStyleAvailable(BOLD_ITALIC)){ + fontStyle = BOLD_ITALIC; + } + } + return fontStyle; + } + + + /** + * {@inheritDoc} + */ + @Override + public FontStrike getStrike(Font font, FontRenderContext frc){ + return new PhysicalStrike(font, family, style, frc); + } + + + /** + * {@inheritDoc} + */ + @Override + public int getStyle(){ + return style.Value; + } + + + /** + * {@inheritDoc} + */ + @Override + public String getPostscriptName(){ + return family.get_Name(); + } + + + /** + * {@inheritDoc} + */ + @Override + public String getFontName(Locale locale){ + return family.GetName(getLanguage(locale)); + } + + + /** + * {@inheritDoc} + */ + @Override + public String getFamilyName(Locale locale){ + if(familyName != null){ + return familyName; + } + return family.GetName(getLanguage(locale)); + } + + /** + * Convert the Java locale to a language ID + */ + private int getLanguage(Locale locale){ + int language = 0; + try{ + language = CultureInfo.GetCultureInfo(locale.toString().replace("_", "-")).get_LCID(); + }catch(Throwable th){ + try{ + language = CultureInfo.GetCultureInfo(locale.getLanguage()).get_LCID(); + }catch(Throwable th2){} + } + return language; + } + + + /** + * {@inheritDoc} + */ + @Override + public void getStyleMetrics(float pointSize, float[] metrics, int offset) { + try{ + try{ + if(!isMediaLoaded){ + classMediaFontFamily = Class.forName("System.Windows.Media.FontFamily, PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); + ctorMediaFontFamily = classMediaFontFamily.getConstructor(String.class); + getFamilyTypefaces = classMediaFontFamily.getMethod("get_FamilyTypefaces"); + } + if(classMediaFontFamily != null){ + if(strikethroughPosition == 0.0){ + Object mediaFontFamily = ctorMediaFontFamily.newInstance(family.get_Name()); + Object familyTypefaces = getFamilyTypefaces.invoke(mediaFontFamily); + if(getItem == null){ + getItem = familyTypefaces.getClass().getMethod("get_Item", Integer.TYPE); + } + Object familyTypeface = getItem.invoke(familyTypefaces, 0); + if(getStrikethroughPosition == null){ + getStrikethroughPosition = familyTypeface.getClass().getMethod("get_StrikethroughPosition"); + getStrikethroughThickness = familyTypeface.getClass().getMethod( + "get_StrikethroughThickness"); + getUnderlinePosition = familyTypeface.getClass().getMethod("get_UnderlinePosition"); + getUnderlineThickness = familyTypeface.getClass().getMethod("get_UnderlineThickness"); + } + strikethroughPosition = ((Number)getStrikethroughPosition.invoke(familyTypeface)).floatValue(); + strikethroughThickness = ((Number)getStrikethroughThickness.invoke(familyTypeface)) + .floatValue(); + underlinePosition = ((Number)getUnderlinePosition.invoke(familyTypeface)).floatValue(); + underlineThickness = ((Number)getUnderlineThickness.invoke(familyTypeface)).floatValue(); + } + } + metrics[offset++] = -strikethroughPosition * pointSize; + metrics[offset++] = strikethroughThickness * pointSize; + metrics[offset++] = -underlinePosition * pointSize; + metrics[offset] = underlineThickness * pointSize; + }catch(Throwable ex){ + // ignore it, NET 3.0 is not available, use the default implementation + super.getStyleMetrics(pointSize, metrics, offset); + } + }finally{ + isMediaLoaded = true; + } + } +} diff --git a/openjdk/sun/font/PhysicalStrike.java b/openjdk/sun/font/PhysicalStrike.java new file mode 100644 index 0000000..cf22d94 --- /dev/null +++ b/openjdk/sun/font/PhysicalStrike.java @@ -0,0 +1,223 @@ +/* + Copyright (C) 2009 - 2011 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.font; + +import java.awt.Font; +import java.awt.Rectangle; +import java.awt.font.FontRenderContext; +import java.awt.geom.GeneralPath; +import java.awt.geom.Point2D.Float; + +import cli.System.Drawing.Bitmap; +import cli.System.Drawing.CharacterRange; +import cli.System.Drawing.FontFamily; +import cli.System.Drawing.FontStyle; +import cli.System.Drawing.Graphics; +import cli.System.Drawing.RectangleF; +import cli.System.Drawing.Region; +import cli.System.Drawing.SizeF; +import cli.System.Drawing.StringFormat; +import cli.System.Drawing.StringFormatFlags; +import cli.System.Drawing.StringTrimming; +import cli.System.Drawing.Drawing2D.PixelOffsetMode; +import cli.System.Drawing.Drawing2D.SmoothingMode; +import cli.System.Drawing.Text.TextRenderingHint; + +import ikvm.internal.NotYetImplementedError; + +/** + * A FontStrike implementation that based on .NET fonts. + * It replace the equals naming Sun class + */ +public class PhysicalStrike extends FontStrike{ + + private static final Bitmap BITMAP = new Bitmap( 1, 1 ); + private static Graphics FRACT_GRAPHICS = createGraphics(true); + private static Graphics FIXED_GRAPHICS = createGraphics(false); + + private final Font font; + private final FontFamily family; + private final FontStyle style; + private final FontRenderContext frc; + private final float size2D; + private final float factor; + + private StrikeMetrics strike; + + public PhysicalStrike(Font font, FontFamily family, FontStyle style, FontRenderContext frc){ + this.font = font; + this.family = family; + this.style = style; + this.frc = frc; + this.size2D = font.getNetFont().get_Size(); + this.factor = size2D / family.GetEmHeight(style); + } + + /** + * {@inheritDoc} + */ + @Override + Float getCharMetrics(char ch){ + return new Float(getCodePointAdvance(ch), 0); + } + + + /** + * Create a Graphics with the settings for fractional or fixed FontRenderContext + * + * @return + */ + private static Graphics createGraphics(boolean fractional){ + Graphics g = Graphics.FromImage(BITMAP); + g.set_SmoothingMode(SmoothingMode.wrap(fractional ? SmoothingMode.None : SmoothingMode.AntiAlias)); + g.set_PixelOffsetMode(PixelOffsetMode.wrap(fractional ? PixelOffsetMode.None : PixelOffsetMode.HighQuality)); + g.set_TextRenderingHint(TextRenderingHint.wrap(fractional ? TextRenderingHint.SingleBitPerPixelGridFit : TextRenderingHint.AntiAliasGridFit)); + return g; + } + + /** + * {@inheritDoc} + */ + @Override + float getCodePointAdvance( int cp ) { + StringFormat format = new StringFormat(StringFormat.get_GenericTypographic()); + + format.set_FormatFlags( StringFormatFlags.wrap( StringFormatFlags.MeasureTrailingSpaces | StringFormatFlags.NoWrap | + StringFormatFlags.FitBlackBox )); + format.set_Trimming( StringTrimming.wrap( StringTrimming.None ) ); + format.SetMeasurableCharacterRanges(new CharacterRange[] {new CharacterRange(0, 1)}); + boolean fractional = frc.usesFractionalMetrics(); + Graphics g = fractional ? FRACT_GRAPHICS : FIXED_GRAPHICS; + SizeF size; + synchronized (g) { + Region[] regions = g.MeasureCharacterRanges(String.valueOf((char)cp), font.getNetFont(), + new RectangleF(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE), format); + size = regions[0].GetBounds(g).get_Size(); + regions[0].Dispose(); + } + return frc.usesFractionalMetrics() ? size.get_Width() : Math.round(size.get_Width()); + } + + /** + * {@inheritDoc} + */ + @Override + StrikeMetrics getFontMetrics(){ + if(strike == null){ + float ascent = family.GetCellAscent(style) * factor; + float descent = family.GetCellDescent(style) * factor; + float height = family.GetLineSpacing(style) * factor; + float leading = height - ascent - descent; + strike = new StrikeMetrics( + 0, -ascent - leading/2, + 0, descent - leading/2, + 0.25f, 0, + 0, leading, + size2D * 2, 0); + } + return strike; + } + + + /** + * {@inheritDoc} + */ + @Override + float getGlyphAdvance(int glyphCode){ + return getCodePointAdvance( glyphCode ); + } + + + /** + * {@inheritDoc} + */ + @Override + void getGlyphImageBounds(int glyphcode, Float pt, Rectangle result){ + throw new NotYetImplementedError(); + } + + + /** + * {@inheritDoc} + */ + @Override + long getGlyphImagePtr(int glyphcode){ + throw new NotYetImplementedError(); + } + + + /** + * {@inheritDoc} + */ + @Override + void getGlyphImagePtrs(int[] glyphCodes, long[] images, int len){ + throw new NotYetImplementedError(); + } + + + /** + * {@inheritDoc} + */ + @Override + Float getGlyphMetrics(int glyphcode){ + return getCharMetrics((char)glyphcode); + } + + + /** + * {@inheritDoc} + */ + @Override + GeneralPath getGlyphOutline(int glyphCode, float x, float y){ + throw new NotYetImplementedError(); + } + + + /** + * {@inheritDoc} + */ + @Override + java.awt.geom.Rectangle2D.Float getGlyphOutlineBounds(int glyphCode){ + throw new NotYetImplementedError(); + } + + + /** + * {@inheritDoc} + */ + @Override + GeneralPath getGlyphVectorOutline(int[] glyphs, float x, float y){ + throw new NotYetImplementedError(); + } + + + /** + * {@inheritDoc} + */ + @Override + public int getNumGlyphs(){ + throw new NotYetImplementedError(); + } + +} diff --git a/openjdk/sun/font/StandardGlyphVector.java b/openjdk/sun/font/StandardGlyphVector.java new file mode 100644 index 0000000..fb3de31 --- /dev/null +++ b/openjdk/sun/font/StandardGlyphVector.java @@ -0,0 +1,511 @@ +/* + Copyright (C) 2009 - 2013 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.font; + +import ikvm.awt.IkvmToolkit; + +import java.awt.Font; +import java.awt.Shape; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphMetrics; +import java.awt.font.GlyphJustificationInfo; +import java.awt.font.GlyphVector; +import java.awt.font.LineMetrics; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.text.CharacterIterator; + +import ikvm.internal.NotYetImplementedError; + +/** + * Standard implementation of GlyphVector used by Font, GlyphList, and SunGraphics2D. + * + */ +public class StandardGlyphVector extends GlyphVector{ + private Font font; + private FontRenderContext frc; + private final String glyphs; // always + private float[] positions; // only if not default advances + + + + private Font2D font2D; + private FontStrike strike; + + + ///////////////////////////// + // Constructors and Factory methods + ///////////////////////////// + + public StandardGlyphVector(Font font, String str, FontRenderContext frc) { + if(str == null){ + throw new NullPointerException("Glyphs are null"); + } + this.font = font; + if( frc == null ){ + frc = new FontRenderContext( null, false, false ); + } + this.frc = frc; + this.glyphs = str; + this.font2D = FontUtilities.getFont2D(font); + this.strike = font2D.getStrike(font, frc); + } + + public StandardGlyphVector(Font font, char[] text, FontRenderContext frc) { + this(font, text, 0, text.length, frc); + } + + public StandardGlyphVector(Font font, char[] text, int start, int count, + FontRenderContext frc) { + this(font, new String(text, start, count), frc); + } + + private float getTracking(Font font) { + if (font.hasLayoutAttributes()) { + AttributeValues values = ((AttributeMap)font.getAttributes()).getValues(); + return values.getTracking(); + } + return 0; + } + + public StandardGlyphVector(Font font, CharacterIterator iter, FontRenderContext frc) { + this(font, getString(iter), frc); + } + + public StandardGlyphVector( Font font, int[] glyphs, FontRenderContext frc ) { + this( font, glyphs2chars(glyphs), frc ); + } + + /** + * Symmetric to {@link #getGlyphCodes(int, int, int[])} + * Currently there is no real mapping possible between the chars and the glyph IDs in the TTF file + */ + private static char[] glyphs2chars( int[] glyphs ) { + int count = glyphs.length; + char[] text = new char[count]; + for( int i = 0; i < count; ++i ) { + text[i] = (char)glyphs[i]; + } + return text; + } + + ///////////////////////////// + // GlyphVector API + ///////////////////////////// + + @Override + public Font getFont() { + return this.font; + } + + @Override + public FontRenderContext getFontRenderContext() { + return this.frc; + } + + @Override + public void performDefaultLayout() { + positions = null; + } + + @Override + public int getNumGlyphs() { + return glyphs.length(); + } + + @Override + public int getGlyphCode(int glyphIndex) { + return glyphs.charAt(glyphIndex); + } + + @Override + public int[] getGlyphCodes(int start, int count, int[] result) { + if (count < 0) { + throw new IllegalArgumentException("count = " + count); + } + if (start < 0) { + throw new IndexOutOfBoundsException("start = " + start); + } + if (start > glyphs.length() - count) { // watch out for overflow if index + count overlarge + throw new IndexOutOfBoundsException("start + count = " + (start + count)); + } + + if (result == null) { + result = new int[count]; + } + for (int i = 0; i < count; ++i) { + result[i] = glyphs.charAt(i + start); + } + return result; + } + + // !!! not cached, assume TextLayout will cache if necessary + // !!! reexamine for per-glyph-transforms + // !!! revisit for text-on-a-path, vertical + @Override + public Rectangle2D getLogicalBounds() { + initPositions(); + + LineMetrics lm = font.getLineMetrics("", frc); + + float minX, minY, maxX, maxY; + // horiz only for now... + minX = 0; + minY = -lm.getAscent(); + maxX = 0; + maxY = lm.getDescent() + lm.getLeading(); + if (glyphs.length() > 0) { + maxX = positions[positions.length - 2]; + } + + return new Rectangle2D.Float(minX, minY, maxX - minX, maxY - minY); + } + + // !!! not cached, assume TextLayout will cache if necessary + @Override + public Rectangle2D getVisualBounds() { + return getOutline().getBounds2D(); + } + + @Override + public Shape getOutline() { + return getOutline( 0, 0 ); + } + + @Override + public Shape getOutline(float x, float y) { + return IkvmToolkit.DefaultToolkit.get().outline( font, frc, glyphs, x, y ); + } + + @Override + public Shape getGlyphOutline( int glyphIndex ) { + return getGlyphOutline( glyphIndex, 0, 0 ); + } + + @Override + public Shape getGlyphOutline( int glyphIndex, float x, float y ) { + initPositions(); + + return IkvmToolkit.DefaultToolkit.get().outline( font, frc, glyphs.substring( glyphIndex, glyphIndex + 1 ), x + positions[glyphIndex * 2], y ); + } + + @Override + public Point2D getGlyphPosition(int ix) { + initPositions(); + + ix *= 2; + return new Point2D.Float(positions[ix], positions[ix + 1]); + } + + @Override + public void setGlyphPosition(int ix, Point2D pos) { + initPositions(); + + int ix2 = ix << 1; + positions[ix2] = (float)pos.getX(); + positions[ix2 + 1] = (float)pos.getY(); + } + + @Override + public AffineTransform getGlyphTransform(int ix) { + throw new NotYetImplementedError(); + } + + @Override + public float[] getGlyphPositions(int start, int count, float[] result) { + if (count < 0) { + throw new IllegalArgumentException("count = " + count); + } + if (start < 0) { + throw new IndexOutOfBoundsException("start = " + start); + } + if (start > this.glyphs.length() + 1 - count) { + throw new IndexOutOfBoundsException("start + count = " + (start + count)); + } + int count2 = count * 2; + if( result == null ) { + result = new float[count2]; + } + initPositions(); + System.arraycopy( positions, start * 2, result, 0, count2 ); + return result; + } + + @Override + public Shape getGlyphLogicalBounds(int ix) { + if (ix < 0 || ix >= glyphs.length()) { + throw new IndexOutOfBoundsException("ix = " + ix); + } + + initPositions(); + StrikeMetrics metrics = strike.getFontMetrics(); + float x = positions[ix * 2]; + return new Rectangle2D.Float( x, -metrics.getAscent(), positions[(ix + 1) * 2] - x, metrics.getAscent() + + metrics.getDescent() + metrics.getLeading() ); + } + + @Override + public Shape getGlyphVisualBounds(int ix) { + if (ix < 0 || ix >= glyphs.length()) { + throw new IndexOutOfBoundsException("ix = " + ix); + } + + initPositions(); + return IkvmToolkit.DefaultToolkit.get().outline( font, frc, glyphs.substring( ix, ix + 1 ), positions[ix * 2], 0 ); + } + + @Override + public GlyphMetrics getGlyphMetrics(int ix) { + if (ix < 0 || ix >= glyphs.length()) { + throw new IndexOutOfBoundsException("ix = " + ix); + } + + Rectangle2D vb = getGlyphVisualBounds(ix).getBounds2D(); + Point2D pt = getGlyphPosition(ix); + vb.setRect(vb.getMinX() - pt.getX(), + vb.getMinY() - pt.getY(), + vb.getWidth(), + vb.getHeight()); + Point2D.Float adv = + strike.getGlyphMetrics( glyphs.charAt( ix ) ); + GlyphMetrics gm = new GlyphMetrics(true, adv.x, adv.y, + vb, + (byte)0); + return gm; + } + + @Override + public GlyphJustificationInfo getGlyphJustificationInfo(int ix) { + if (ix < 0 || ix >= glyphs.length()) { + throw new IndexOutOfBoundsException("ix = " + ix); + } + + // currently we don't have enough information to do this right. should + // get info from the font and use real OT/GX justification. Right now + // sun/font/ExtendedTextSourceLabel assigns one of three infos + // based on whether the char is kanji, space, or other. + + return null; + } + + @Override + public boolean equals(GlyphVector rhs) { + if(!(rhs instanceof StandardGlyphVector)){ + return false; + } + StandardGlyphVector sgv = (StandardGlyphVector)rhs; + if(!glyphs.equals(sgv.glyphs)){ + return false; + } + if(equals(font, sgv.font)){ + return false; + } + if(equals(frc, sgv.frc)){ + return false; + } + return true; + } + + /** + * Compare 2 objects via equals where both can be null + */ + private static boolean equals(Object obj1, Object obj2){ + if(obj1 != null){ + if(!obj1.equals(obj2)){ + return false; + } + }else{ + if(obj2 != null){ + return false; + } + } + return true; + } + + /** + * As a concrete subclass of GlyphVector, this must implement clone. + */ + @Override + public Object clone() { + // positions, gti are mutable so we have to clone them + // font2d can be shared + // fsref is a cache and can be shared + try { + StandardGlyphVector result = (StandardGlyphVector)super.clone(); + + if (positions != null) { + result.positions = (float[])positions.clone(); + } + + return result; + } + catch (CloneNotSupportedException e) { + } + + return this; + } + + ////////////////////// + // StandardGlyphVector new public methods + ///////////////////// + + /** + * Set all the glyph positions, including the 'after last glyph' position. + * The srcPositions array must be of length (numGlyphs + 1) * 2. + */ + public void setGlyphPositions(float[] srcPositions) { + int requiredLength = glyphs.length() * 2 + 2; + if (srcPositions.length != requiredLength) { + throw new IllegalArgumentException("srcPositions.length != " + requiredLength); + } + + positions = (float[])srcPositions.clone(); + + } + + /** + * This is a convenience overload that gets all the glyph positions, which + * is what you usually want to do if you're getting more than one. + * !!! should I bother taking result parameter? + */ + public float[] getGlyphPositions(float[] result) { + initPositions(); + return positions; + } + + /** + * For each glyph return posx, posy, advx, advy, visx, visy, visw, vish. + */ + public float[] getGlyphInfo() { + initPositions(); + float[] result = new float[glyphs.length() * 8]; + for (int i = 0, n = 0; i < glyphs.length(); ++i, n += 8) { + float x = positions[i*2]; + float y = positions[i*2+1]; + result[n] = x; + result[n+1] = y; + + int glyphID = glyphs.charAt(i); + Point2D.Float adv = strike.getGlyphMetrics(glyphID); + result[n+2] = adv.x; + result[n+3] = adv.y; + + Rectangle2D vb = getGlyphVisualBounds(i).getBounds2D(); + result[n+4] = (float)(vb.getMinX()); + result[n+5] = (float)(vb.getMinY()); + result[n+6] = (float)(vb.getWidth()); + result[n+7] = (float)(vb.getHeight()); + } + return result; + } + + @Override + public void setGlyphTransform(int glyphIndex, AffineTransform newTX){ + throw new NotYetImplementedError(); + } + + + /** + * Convert a CharacterIterator to a string + * @param iterator the iterator + * @return the string + */ + private static String getString(java.text.CharacterIterator iterator){ + iterator.first(); + StringBuilder sb = new StringBuilder(); + + while(true){ + char c = iterator.current(); + if(c == CharacterIterator.DONE){ + break; + } + sb.append(c); + iterator.next(); + } + + return sb.toString(); + } + + /** + * Ensure that the positions array exists and holds position data. + * If the array is null, this allocates it and sets default positions. + */ + private void initPositions() { + if (positions == null) { + positions = new float[glyphs.length() * 2 + 2]; + + Point2D.Float trackPt = null; + float track = getTracking(font); + if (track != 0) { + track *= font.getSize2D(); + trackPt = new Point2D.Float(track, 0); // advance delta + } + + Point2D.Float pt = new Point2D.Float(0, 0); + if (font.isTransformed()) { + AffineTransform at = font.getTransform(); + at.transform(pt, pt); + positions[0] = pt.x; + positions[1] = pt.y; + + if (trackPt != null) { + at.deltaTransform(trackPt, trackPt); + } + } + for (int i = 0, n = 2; i < glyphs.length(); ++i, n += 2) { + addDefaultGlyphAdvance(glyphs.charAt(i), pt); + if (trackPt != null) { + pt.x += trackPt.x; + pt.y += trackPt.y; + } + positions[n] = pt.x; + positions[n+1] = pt.y; + } + } + } + + private void addDefaultGlyphAdvance(int glyphID, Point2D.Float result) { + Point2D.Float adv = strike.getGlyphMetrics(glyphID); + result.x += adv.x; + result.y += adv.y; + } + + /** + * If the text is a simple text and we can use FontDesignMetrics without a stackoverflow. + * @see FontDesignMetrics#stringWidth(String) + * @return true, if a simple text. false it is a complex text. + */ + public static boolean isSimpleString(Font font, String str) { + if (font.hasLayoutAttributes()) { + return false; + } + for (int i = 0; i < str.length(); ++i) { + if (FontUtilities.isNonSimpleChar(str.charAt(i))) { + return false; + } + } + return true; + } +} diff --git a/openjdk/sun/font/StrikeCache.java b/openjdk/sun/font/StrikeCache.java new file mode 100644 index 0000000..2660ae5 --- /dev/null +++ b/openjdk/sun/font/StrikeCache.java @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2003, 2013, 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.font; + +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.SoftReference; +import java.lang.ref.WeakReference; +import java.awt.Font; +import java.awt.FontFormatException; +import java.util.logging.Level; +import java.util.logging.Logger; + +import sun.java2d.Disposer; +import sun.misc.Unsafe; +import ikvm.internal.NotYetImplementedError; + +/** + +A FontStrike is the keeper of scaled glyph image data which is expensive +to compute so needs to be cached. +So long as that data may be being used it cannot be invalidated. +Yet we also need to limit the amount of native memory and number of +strike objects in use. +For scaleability and ease of use, a key goal is multi-threaded read +access to a strike, so that it may be shared by multiple client objects, +potentially executing on different threads, with no special reference +counting or "check-out/check-in" requirements which would pass on the +burden of keeping track of strike references to the SG2D and other clients. + +A cache of strikes is maintained via Reference objects. +This helps in two ways : +1. The VM will free references when memory is low or they have not been +used in a long time. +2. Reference queues provide a way to get notification of this so we can +free native memory resources. + + */ + +public final class StrikeCache { + + static final Unsafe unsafe = Unsafe.getUnsafe(); + + static ReferenceQueue refQueue = Disposer.getQueue(); + + /* Reference objects may have their referents cleared when GC chooses. + * During application client start-up there is typically at least one + * GC which causes the hotspot VM to clear soft (not just weak) references + * Thus not only is there a GC pause, but the work done do rasterise + * glyphs that are fairly certain to be needed again almost immediately + * is thrown away. So for performance reasons a simple optimisation is to + * keep up to 8 strong references to strikes to reduce the chance of + * GC'ing strikes that have been used recently. Note that this may not + * suffice in Solaris UTF-8 locales where a single composite strike may be + * composed of 15 individual strikes, plus the composite strike. + * And this assumes the new architecture doesn't maintain strikes for + * natively accessed bitmaps. It may be worth "tuning" the number of + * strikes kept around for the platform or locale. + * Since no attempt is made to ensure uniqueness or ensure synchronized + * access there is no guarantee that this cache will ensure that unique + * strikes are cached. Every time a strike is looked up it is added + * to the current index in this cache. All this cache has to do to be + * worthwhile is prevent excessive cache flushing of strikes that are + * referenced frequently. The logic that adds references here could be + * tweaked to keep only strikes that represent untransformed, screen + * sizes as that's the typical performance case. + */ + static int MINSTRIKES = 8; // can be overridden by property + static int recentStrikeIndex = 0; + static FontStrike[] recentStrikes; + static boolean cacheRefTypeWeak; + + /* + * Native sizes and offsets for glyph cache + * There are 10 values. + */ + static int nativeAddressSize; + static int glyphInfoSize; + static int xAdvanceOffset; + static int yAdvanceOffset; + static int boundsOffset; + static int widthOffset; + static int heightOffset; + static int rowBytesOffset; + static int topLeftXOffset; + static int topLeftYOffset; + static int pixelDataOffset; + static long invisibleGlyphPtr; + + /* Native method used to return information used for unsafe + * access to native data. + * return values as follows:- + * arr[0] = size of an address/pointer. + * arr[1] = size of a GlyphInfo + * arr[2] = offset of advanceX + * arr[3] = offset of advanceY + * arr[4] = offset of width + * arr[5] = offset of height + * arr[6] = offset of rowBytes + * arr[7] = offset of topLeftX + * arr[8] = offset of topLeftY + * arr[9] = offset of pixel data. + * arr[10] = address of a GlyphImageRef representing the invisible glyph + */ + static void getGlyphCacheDescription(long[] infoArray){ + throw new NotYetImplementedError(); + } + + static { + + long[] nativeInfo = new long[11]; + getGlyphCacheDescription(nativeInfo); + //Can also get address size from Unsafe class :- + //nativeAddressSize = unsafe.addressSize(); + nativeAddressSize = (int)nativeInfo[0]; + glyphInfoSize = (int)nativeInfo[1]; + xAdvanceOffset = (int)nativeInfo[2]; + yAdvanceOffset = (int)nativeInfo[3]; + widthOffset = (int)nativeInfo[4]; + heightOffset = (int)nativeInfo[5]; + rowBytesOffset = (int)nativeInfo[6]; + topLeftXOffset = (int)nativeInfo[7]; + topLeftYOffset = (int)nativeInfo[8]; + pixelDataOffset = (int)nativeInfo[9]; + invisibleGlyphPtr = nativeInfo[10]; + if (nativeAddressSize < 4) { + throw new InternalError("Unexpected address size for font data: " + + nativeAddressSize); + } + + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Object run() { + + /* Allow a client to override the reference type used to + * cache strikes. The default is "soft" which hints to keep + * the strikes around. This property allows the client to + * override this to "weak" which hint to the GC to free + * memory more agressively. + */ + String refType = + System.getProperty("sun.java2d.font.reftype", "soft"); + cacheRefTypeWeak = refType.equals("weak"); + + String minStrikesStr = + System.getProperty("sun.java2d.font.minstrikes"); + if (minStrikesStr != null) { + try { + MINSTRIKES = Integer.parseInt(minStrikesStr); + if (MINSTRIKES <= 0) { + MINSTRIKES = 1; + } + } catch (NumberFormatException e) { + } + } + + recentStrikes = new FontStrike[MINSTRIKES]; + + return null; + } + }); + } + + + static void refStrike(FontStrike strike) { + int index = recentStrikeIndex; + recentStrikes[index] = strike; + index++; + if (index == MINSTRIKES) { + index = 0; + } + recentStrikeIndex = index; + } + + static void disposeStrike(FontStrikeDisposer disposer) { + if (disposer.intGlyphImages != null) { + freeIntMemory(disposer.intGlyphImages, + disposer.pScalerContext); + } else if (disposer.longGlyphImages != null) { + freeLongMemory(disposer.longGlyphImages, + disposer.pScalerContext); + } else if (disposer.segIntGlyphImages != null) { + /* NB Now making multiple JNI calls in this case. + * But assuming that there's a reasonable amount of locality + * rather than sparse references then it should be OK. + */ + for (int i=0; i fontNameCache = + new ConcurrentHashMap(); + /* + * The client supplies a name and a style. + * The name could be a family name, or a full name. + * A font may exist with the specified style, or it may + * exist only in some other style. For non-native fonts the scaler + * may be able to emulate the required style. + */ + public Font2D findFont2D(String name, int style, int fallback) { + String lowerCaseName = name.toLowerCase(Locale.ENGLISH); + String mapName = lowerCaseName + dotStyleStr(style); + Font2D font; + + /* If preferLocaleFonts() or preferProportionalFonts() has been + * called we may be using an alternate set of composite fonts in this + * app context. The presence of a pre-built name map indicates whether + * this is so, and gives access to the alternate composite for the + * name. + */ + if (_usingPerAppContextComposites) { + ConcurrentHashMap altNameCache = + (ConcurrentHashMap) + AppContext.getAppContext().get(CompositeFont.class); + if (altNameCache != null) { + font = (Font2D)altNameCache.get(mapName); + } else { + font = null; + } + } else { + font = fontNameCache.get(mapName); + } + if (font != null) { + return font; + } + + if (FontUtilities.isLogging()) { + FontUtilities.getLogger().info("Search for font: " + name); + } + + // The check below is just so that the bitmap fonts being set by + // AWT and Swing thru the desktop properties do not trigger the + // the load fonts case. The two bitmap fonts are now mapped to + // appropriate equivalents for serif and sansserif. + // Note that the cost of this comparison is only for the first + // call until the map is filled. + if (FontUtilities.isWindows) { + if (lowerCaseName.equals("ms sans serif")) { + name = "sansserif"; + } else if (lowerCaseName.equals("ms serif")) { + name = "serif"; + } + } + + /* This isn't intended to support a client passing in the + * string default, but if a client passes in null for the name + * the java.awt.Font class internally substitutes this name. + * So we need to recognise it here to prevent a loadFonts + * on the unrecognised name. The only potential problem with + * this is it would hide any real font called "default"! + * But that seems like a potential problem we can ignore for now. + */ + if (lowerCaseName.equals("default")) { + lowerCaseName = name = "dialog"; + } + + font = new PhysicalFont(name,style); + + switch (lowerCaseName){ + case "dialog": + font = new CompositeFont(font); //dialog must a CompositeFont, else there are ClassCastExceptions + break; + } + fontNameCache.put(mapName, font); + return font; + } + + /* + * Workaround for apps which are dependent on a font metrics bug + * in JDK 1.1. This is an unsupported win32 private setting. + * Left in for a customer - do not remove. + */ + public boolean usePlatformFontMetrics() { + return usePlatformFontMetrics; + } + + public Font2D createFont2D(File fontFile, int fontFormat, + boolean isCopy, CreatedFontTracker tracker) + throws FontFormatException { + throw new NotYetImplementedError(); + } + /* + * This is called when font is determined to be invalid/bad. + * It designed to be called (for example) by the font scaler + * when in processing a font file it is discovered to be incorrect. + * This is different than the case where fonts are discovered to + * be incorrect during initial verification, as such fonts are + * never registered. + * Handles to this font held are re-directed to a default font. + * This default may not be an ideal substitute buts it better than + * crashing This code assumes a PhysicalFont parameter as it doesn't + * make sense for a Composite to be "bad". + */ + public synchronized void deRegisterBadFont(Font2D font2D) { + if (!(font2D instanceof PhysicalFont)) { + /* We should never reach here, but just in case */ + return; + } else { + if (FontUtilities.isLogging()) { + FontUtilities.getLogger() + .severe("Deregister bad font: " + font2D); + } + throw new NotYetImplementedError(); + } + } + + /* Supporting "alternate" composite fonts on 2D graphics objects + * is accessed by the application by calling methods on the local + * GraphicsEnvironment. The overall implementation is described + * in one place, here, since otherwise the implementation is spread + * around it may be difficult to track. + * The methods below call into SunGraphicsEnvironment which creates a + * new FontConfiguration instance. The FontConfiguration class, + * and its platform sub-classes are updated to take parameters requesting + * these behaviours. This is then used to create new composite font + * instances. Since this calls the initCompositeFont method in + * SunGraphicsEnvironment it performs the same initialization as is + * performed normally. There may be some duplication of effort, but + * that code is already written to be able to perform properly if called + * to duplicate work. The main difference is that if we detect we are + * running in an applet/browser/Java plugin environment these new fonts + * are not placed in the "default" maps but into an AppContext instance. + * The font lookup mechanism in java.awt.Font.getFont2D() is also updated + * so that look-up for composite fonts will in that case always + * do a lookup rather than returning a cached result. + * This is inefficient but necessary else singleton java.awt.Font + * instances would not retrieve the correct Font2D for the appcontext. + * sun.font.FontManager.findFont2D is also updated to that it uses + * a name map cache specific to that appcontext. + * + * Getting an AppContext is expensive, so there is a global variable + * that records whether these methods have ever been called and can + * avoid the expense for almost all applications. Once the correct + * CompositeFont is associated with the Font, everything should work + * through existing mechanisms. + * A special case is that GraphicsEnvironment.getAllFonts() must + * return an AppContext specific list. + * + * Calling the methods below is "heavyweight" but it is expected that + * these methods will be called very rarely. + * + * If _usingPerAppContextComposites is true, we are in "applet" + * (eg browser) enviroment and at least one context has selected + * an alternate composite font behaviour. + * If _usingAlternateComposites is true, we are not in an "applet" + * environment and the (single) application has selected + * an alternate composite font behaviour. + * + * - Printing: The implementation delegates logical fonts to an AWT + * mechanism which cannot use these alternate configurations. + * We can detect that alternate fonts are in use and back-off to 2D, but + * that uses outlines. Much of this can be fixed with additional work + * but that may have to wait. The results should be correct, just not + * optimal. + */ + private boolean _usingPerAppContextComposites = false; + private boolean _usingAlternateComposites = false; + + /* This method doesn't check if alternates are selected in this app + * context. Its used by the FontMetrics caching code which in such + * a case cannot retrieve a cached metrics solely on the basis of + * the Font.equals() method since it needs to also check if the Font2D + * is the same. + * We also use non-standard composites for Swing native L&F fonts on + * Windows. In that case the policy is that the metrics reported are + * based solely on the physical font in the first slot which is the + * visible java.awt.Font. So in that case the metrics cache which tests + * the Font does what we want. In the near future when we expand the GTK + * logical font definitions we may need to revisit this if GTK reports + * combined metrics instead. For now though this test can be simple. + */ + public boolean maybeUsingAlternateCompositeFonts() { + return false; + } + + public boolean usingAlternateFontforJALocales() { + return false; + } + + public synchronized void preferLocaleFonts() { + if (FontUtilities.isLogging()) { + FontUtilities.getLogger().info("Entered preferLocaleFonts()."); + } + /* Test if re-ordering will have any effect */ + if (!FontConfiguration.willReorderForStartupLocale()) { + return; + } + + } + + public synchronized void preferProportionalFonts() { + throw new NotYetImplementedError(); + } + + public boolean registerFont(Font font) { + /* This method should not be called with "null". + * It is the caller's responsibility to ensure that. + */ + if (font == null) { + return false; + } + throw new NotYetImplementedError(); + } + + /* Called to register fall back fonts */ + public void registerFontsInDir(String fallbackDirName) { + } + + /** + * Returns file name for default font, either absolute + * or relative as needed by registerFontFile. + */ + public synchronized String getDefaultFontFile() { + return null; + } + + /** + * Returns face name for default font, or null if + * no face names are used for CompositeFontDescriptors + * for this platform. + */ + public synchronized String getDefaultFontFaceName() { + return null; + } + + protected FontUIResource getFontConfigFUIR(String family, int style, + int size) + { + return new FontUIResource(family, style, size); + } + + /** + * Create a new Font2D without caching. This is used from createFont + * + * @param family + * .NET FontFamily + * @param style + * the style + * @return a Font2D + */ + public static Font2D createFont2D( cli.System.Drawing.FontFamily family, int style ) { + return new PhysicalFont( family, style ); + } +} diff --git a/openjdk/sun/font/TrueTypeFont.java b/openjdk/sun/font/TrueTypeFont.java new file mode 100644 index 0000000..8300032 --- /dev/null +++ b/openjdk/sun/font/TrueTypeFont.java @@ -0,0 +1,44 @@ +/* + Copyright (C) 2011 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.font; + +import cli.System.Drawing.FontFamily; + +public class TrueTypeFont extends PhysicalFont { + + public static final int GPOSTag = 0x47504F53; // 'GPOS' + public static final int GSUBTag = 0x47535542; // 'GSUB' + + public TrueTypeFont(String name, int style) { + super(name, style); + } + + public TrueTypeFont(FontFamily family, int style) { + super(family, style); + } + + Object getDirectoryEntry(int tag) { + return null; + } +} diff --git a/openjdk/sun/java2d/HeadlessGraphicsEnvironment.java b/openjdk/sun/java2d/HeadlessGraphicsEnvironment.java new file mode 100644 index 0000000..29c0538 --- /dev/null +++ b/openjdk/sun/java2d/HeadlessGraphicsEnvironment.java @@ -0,0 +1,168 @@ +/* + Copyright (C) 2009 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.java2d; + +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.HeadlessException; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; +import java.util.Locale; + + +/** + * Placeholder for not supported headless environment + */ +public class HeadlessGraphicsEnvironment extends GraphicsEnvironment{ + + private final GraphicsEnvironment env; + + + public HeadlessGraphicsEnvironment(GraphicsEnvironment env){ + this.env = env; + } + + /** + * {@inheritDoc} + */ + @Override + public Graphics2D createGraphics(BufferedImage img){ + return env.createGraphics(img); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj){ + return env.equals(obj); + } + + /** + * {@inheritDoc} + */ + @Override + public Font[] getAllFonts(){ + return env.getAllFonts(); + } + + /** + * {@inheritDoc} + */ + @Override + public String[] getAvailableFontFamilyNames(){ + return env.getAvailableFontFamilyNames(); + } + + /** + * {@inheritDoc} + */ + @Override + public String[] getAvailableFontFamilyNames(Locale l){ + return env.getAvailableFontFamilyNames(l); + } + + /** + * {@inheritDoc} + */ + @Override + public Point getCenterPoint() throws HeadlessException{ + return env.getCenterPoint(); + } + + /** + * {@inheritDoc} + */ + @Override + public GraphicsDevice getDefaultScreenDevice() throws HeadlessException{ + return env.getDefaultScreenDevice(); + } + + /** + * {@inheritDoc} + */ + @Override + public Rectangle getMaximumWindowBounds() throws HeadlessException{ + return env.getMaximumWindowBounds(); + } + + /** + * {@inheritDoc} + */ + @Override + public GraphicsDevice[] getScreenDevices() throws HeadlessException{ + return env.getScreenDevices(); + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode(){ + return env.hashCode(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isHeadlessInstance(){ + return env.isHeadlessInstance(); + } + + /** + * {@inheritDoc} + */ + @Override + public void preferLocaleFonts(){ + env.preferLocaleFonts(); + } + + /** + * {@inheritDoc} + */ + @Override + public void preferProportionalFonts(){ + env.preferProportionalFonts(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean registerFont(Font font){ + return env.registerFont(font); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString(){ + return env.toString(); + } +} diff --git a/openjdk/sun/java2d/SunCompositeContext.java b/openjdk/sun/java2d/SunCompositeContext.java new file mode 100644 index 0000000..25291c2 --- /dev/null +++ b/openjdk/sun/java2d/SunCompositeContext.java @@ -0,0 +1,316 @@ +/* AlphaCompositeContext.java -- CompositeContext impl for AlphaComposite + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package sun.java2d; + +import java.awt.AWTError; +import java.awt.AlphaComposite; +import java.awt.CompositeContext; +import java.awt.image.ColorModel; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; + +/** + * A CompositeContext implementation for {@link AlphaComposite}. + * + * @author Roman Kennke (kennke@aicas.com) + */ +public class SunCompositeContext + implements CompositeContext +{ + + /** + * The Composite object for which we perform compositing. + */ + private AlphaComposite composite; + + /** + * The source color model. + */ + private ColorModel srcColorModel; + + /** + * The destination color model. + */ + private ColorModel dstColorModel; + + /** + * The blending factor for the source. + */ + private float fs; + + /** + * The blending factor for the destination. + */ + private float fd; + + /** + * Creates a new AlphaCompositeContext. + * + * @param aComp the AlphaComposite object + * @param srcCM the source color model + * @param dstCM the destination color model + */ + public SunCompositeContext(AlphaComposite aComp, ColorModel srcCM, + ColorModel dstCM) + { + composite = aComp; + srcColorModel = srcCM; + dstColorModel = dstCM; + + + // Determine the blending factors according to the rule in the + // AlphaComposite. For some rules the factors must be determined + // dynamically because they depend on the actual pixel value. + switch (composite.getRule()) + { + case AlphaComposite.CLEAR: + fs = 0.F; + fd= 0.F; + break; + case AlphaComposite.DST: + fs = 0.F; + fd= 1.F; + break; + case AlphaComposite.DST_ATOP: + fs = 1.F; // Determined later as 1 - alpha_dst; + fd = 1.F; // Determined later as alpha_src; + break; + case AlphaComposite.DST_IN: + fs = 0.F; + fd = 0.F; // Determined later as alpha_src; + break; + case AlphaComposite.DST_OUT: + fs = 0.F; + fd = 0.F; // Determined later as 1 - alpha_src; + break; + case AlphaComposite.DST_OVER: + fs = 1.F; // Determined later as 1 - alpha_dst. + fd= 1.F; + break; + case AlphaComposite.SRC: + fs = 1.F; + fd= 0.F; + break; + case AlphaComposite.SRC_ATOP: + fs = 1.F; // Determined later as alpha_dst; + fd = 1.F; // Determined later as 1 - alpha_src; + break; + case AlphaComposite.SRC_IN: + fs = 0.F; // Determined later as alpha_dst; + fd = 0.F; + break; + case AlphaComposite.SRC_OUT: + fs = 0.F; // Determined later as 1 - alpha_dst; + fd = 0.F; + break; + case AlphaComposite.SRC_OVER: + fs = 1.F; + fd= 1.F; // Determined later as 1 - alpha_src. + break; + case AlphaComposite.XOR: + fs = 1.F; // Determined later as 1 - alpha_dst. + fd= 1.F; // Determined later as 1 - alpha_src. + break; + default: + throw new AWTError("Illegal AlphaComposite rule"); + } + + } + + /** + * Releases all resources held by this composite object. + */ + public void dispose() + { + // Nothing to do here yet. + } + + /** + * Performs compositing according to the rules specified in the + * AlphaComposite from the constructor. + */ + public void compose(Raster src, Raster dstIn, WritableRaster dstOut) + { + + // TODO: This implementation is very general and highly inefficient. There + // are two possible ways to optimize this: + // 1. Special cased implementations for common ColorModels and transfer + // types. + // 2. Native implementation. + + int x0 = src.getMinX(); + int y0 = src.getMinY(); + int width = src.getWidth(); + int height = src.getHeight(); + int x1 = x0 + width; + int y1 = y0 + height; + + Object srcPixel = null; + Object dstPixel = null; + + // Prepare the array that holds the color and alpha components of the + // source pixels. + float[] srcComponents; + int srcComponentsLength = srcColorModel.getNumComponents(); + if (! srcColorModel.hasAlpha()) + srcComponentsLength += 1; + srcComponents = new float[srcComponentsLength]; + + // Prepare the array that holds the color and alpha components of the + // destination pixels. + float[] dstComponents; + int dstComponentsLength = dstColorModel.getNumComponents(); + if (! dstColorModel.hasAlpha()) + dstComponentsLength += 1; + dstComponents = new float[dstComponentsLength]; + + if (srcComponentsLength != dstComponentsLength) + throw new AWTError("The color models of the source and destination have" + + "incompatible number of color components"); + + int srcTransferType = srcColorModel.getTransferType(); + int dstTransferType = dstColorModel.getTransferType(); + + for (int y = y0; y < y1; y++) + { + for (int x = x0; x < x1; x++) + { + // Fetch source pixel. + srcPixel = src.getDataElements(x, y, (int[]) srcPixel); + // Fetch destination pixel. + dstPixel = dstIn.getDataElements(x, y, dstPixel); + // Get normalized components. This is the only type that is + // guaranteed to be supported by all ColorModels. + srcComponents = + srcColorModel.getNormalizedComponents(srcPixel, srcComponents, 0); + if (! srcColorModel.hasAlpha()) + srcComponents[srcComponentsLength - 1] = 1.0F; + dstComponents = + dstColorModel.getNormalizedComponents(dstPixel, dstComponents, 0); + if (! dstColorModel.hasAlpha()) + dstComponents[dstComponentsLength - 1] = 1.0F; + + // Prepare the input. + float compositeAlpha = composite.getAlpha(); + srcComponents[srcComponentsLength - 1] *= compositeAlpha; + if (srcColorModel.isAlphaPremultiplied()) + { + for (int i = srcComponentsLength - 2; i >= 0; i--) + srcComponents[i] *= compositeAlpha; + } + else + { + for (int i = srcComponentsLength - 2; i >= 0; i--) + srcComponents[i] *= srcComponents[srcComponentsLength - 1]; + } + if (! dstColorModel.isAlphaPremultiplied()) + { + for (int i = dstComponentsLength - 2; i >= 0; i--) + dstComponents[i] *= dstComponents[dstComponents.length - 1]; + } + + // Determine the blending factors according to the rule in the + // AlphaComposite. For some rules the factors must be determined + // dynamically because they depend on the actual pixel value. + float srcAlpha = srcComponents[srcComponentsLength - 1]; + float dstAlpha = dstComponents[dstComponentsLength - 1]; + switch (composite.getRule()) + { + case AlphaComposite.DST_ATOP: + fs = 1.F - dstAlpha; + fd = srcAlpha; + break; + case AlphaComposite.DST_IN: + fd = srcAlpha; + break; + case AlphaComposite.DST_OUT: + fd = 1.F - srcAlpha; + break; + case AlphaComposite.DST_OVER: + fs = 1.F - dstAlpha; + break; + case AlphaComposite.SRC_ATOP: + fs = srcAlpha; + fd = 1.F - srcAlpha; + break; + case AlphaComposite.SRC_IN: + fs = dstAlpha; + break; + case AlphaComposite.SRC_OUT: + fs = 1.F - dstAlpha; + break; + case AlphaComposite.SRC_OVER: + fd= 1.F - srcAlpha; + break; + case AlphaComposite.XOR: + fs = 1.F - dstAlpha; + fd= 1.F - srcAlpha; + break; + default: + // For the other cases the factors have already been determined + // in the constructor. + } + + // Apply the blending equation to the pixels. + for (int i = 0; i < srcComponentsLength; i++) + { + dstComponents[i] = srcComponents[i] * fs + + dstComponents[i] * fd; + } + + // Convert the result back when the destination is not + // alpha-premultiplied. + dstAlpha = dstComponents[dstComponentsLength - 1]; + if (!dstColorModel.isAlphaPremultiplied() && dstAlpha != 0.F) + { + for (int i = 0; i < dstComponentsLength - 1; i++) + { + dstComponents[i] = dstComponents[i] / dstAlpha; + } + } + + // Store the result in the destination raster. + dstPixel = dstColorModel.getDataElements(dstComponents, 0, + dstPixel); + dstOut.setDataElements(x, y, dstPixel); + } // End X loop. + } // End Y loop. + } + +} diff --git a/openjdk/sun/java2d/SunGraphics2D.java b/openjdk/sun/java2d/SunGraphics2D.java new file mode 100644 index 0000000..443a062 --- /dev/null +++ b/openjdk/sun/java2d/SunGraphics2D.java @@ -0,0 +1,130 @@ +/* + Copyright (C) 2009, 2013 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.java2d; + +import java.awt.*; +import java.awt.RenderingHints.Key; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.awt.image.BufferedImageOp; +import java.awt.image.ImageObserver; +import java.awt.image.RenderedImage; +import java.awt.image.renderable.RenderableImage; +import java.text.AttributedCharacterIterator; +import java.util.Map; + +import sun.java2d.pipe.Region; +import ikvm.internal.NotYetImplementedError; + +/** + * A replacement of the Sun implementation that redirect to the NetGraphics + */ +public abstract class SunGraphics2D extends Graphics2D{ + /* + * Attribute States + */ + /* Paint */ + public static final int PAINT_CUSTOM = 6; /* Any other Paint object */ + public static final int PAINT_TEXTURE = 5; /* Tiled Image */ + public static final int PAINT_RAD_GRADIENT = 4; /* Color RadialGradient */ + public static final int PAINT_LIN_GRADIENT = 3; /* Color LinearGradient */ + public static final int PAINT_GRADIENT = 2; /* Color Gradient */ + public static final int PAINT_ALPHACOLOR = 1; /* Non-opaque Color */ + public static final int PAINT_OPAQUECOLOR = 0; /* Opaque Color */ + + /* Composite*/ + public static final int COMP_CUSTOM = 3;/* Custom Composite */ + public static final int COMP_XOR = 2;/* XOR Mode Composite */ + public static final int COMP_ALPHA = 1;/* AlphaComposite */ + public static final int COMP_ISCOPY = 0;/* simple stores into destination, + * i.e. Src, SrcOverNoEa, and other + * alpha modes which replace + * the destination. + */ + + /* Stroke */ + public static final int STROKE_CUSTOM = 3; /* custom Stroke */ + public static final int STROKE_WIDE = 2; /* BasicStroke */ + public static final int STROKE_THINDASHED = 1; /* BasicStroke */ + public static final int STROKE_THIN = 0; /* BasicStroke */ + + /* Transform */ + public static final int TRANSFORM_GENERIC = 4; /* any 3x2 */ + public static final int TRANSFORM_TRANSLATESCALE = 3; /* scale XY */ + public static final int TRANSFORM_ANY_TRANSLATE = 2; /* non-int translate */ + public static final int TRANSFORM_INT_TRANSLATE = 1; /* int translate */ + public static final int TRANSFORM_ISIDENT = 0; /* Identity */ + + /* Clipping */ + public static final int CLIP_SHAPE = 2; /* arbitrary clip */ + public static final int CLIP_RECTANGULAR = 1; /* rectangular clip */ + public static final int CLIP_DEVICE = 0; /* no clipping set */ + + private final SurfaceData surfaceData; + + public int constrainX; + public int constrainY; + + /** + * Create a new SunGraphics2D + */ + protected SunGraphics2D( SurfaceData surfaceData ) { + this.surfaceData = surfaceData; + } + + /** + * Constrain rendering for lightweight objects. + * + * REMIND: This method will back off to the "workaround" + * of using translate and clipRect if the Graphics + * to be constrained has a complex transform. The + * drawback of the workaround is that the resulting + * clip and device origin cannot be "enforced". + * + * @exception IllegalStateException If the Graphics + * to be constrained has a complex transform. + */ + public void constrain(int x, int y, int w, int h){ + throw new NotYetImplementedError(); + } + + /** + * Return the SurfaceData object assigned to manage the destination + * drawable surface of this Graphics2D. + */ + public final SurfaceData getSurfaceData() { + return surfaceData; + } + + /** + * Returns destination that this Graphics renders to. This could be + * either an Image or a Component; subclasses of SurfaceData are + * responsible for returning the appropriate object. + */ + public Object getDestination() { + return surfaceData.getDestination(); + } +} diff --git a/openjdk/sun/java2d/SunGraphicsEnvironment.java b/openjdk/sun/java2d/SunGraphicsEnvironment.java new file mode 100644 index 0000000..8f74614 --- /dev/null +++ b/openjdk/sun/java2d/SunGraphicsEnvironment.java @@ -0,0 +1,106 @@ +/* + Copyright (C) 2009, 2011 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.java2d; + +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Insets; +import java.awt.peer.ComponentPeer; +import java.awt.Rectangle; +import java.awt.Toolkit; + +import sun.awt.DisplayChangedListener; +import sun.awt.SunDisplayChanger; + + + +/** + * A replacement of the Sun implementation that will extends from from NetGraphicsEnvironment + */ +public abstract class SunGraphicsEnvironment extends GraphicsEnvironment{ + + /** + * Return the bounds of a GraphicsDevice, less its screen insets. + * See also java.awt.GraphicsEnvironment.getUsableBounds(); + */ + public static Rectangle getUsableBounds(GraphicsDevice gd) { + GraphicsConfiguration gc = gd.getDefaultConfiguration(); + Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc); + Rectangle usableBounds = gc.getBounds(); + + usableBounds.x += insets.left; + usableBounds.y += insets.top; + usableBounds.width -= (insets.left + insets.right); + usableBounds.height -= (insets.top + insets.bottom); + + return usableBounds; + } + + /** + * Returns true when the display is local, false for remote displays. + * + * @return true when the display is local, false for remote displays + */ + public abstract boolean isDisplayLocal(); + + /* + * ----DISPLAY CHANGE SUPPORT---- + */ + + protected SunDisplayChanger displayChanger = new SunDisplayChanger(); + + /** + * Add a DisplayChangeListener to be notified when the display settings + * are changed. + */ + public void addDisplayChangedListener(DisplayChangedListener client) { + displayChanger.add(client); + } + + /** + * Remove a DisplayChangeListener from Win32GraphicsEnvironment + */ + public void removeDisplayChangedListener(DisplayChangedListener client) { + displayChanger.remove(client); + } + + /* + * ----END DISPLAY CHANGE SUPPORT---- + */ + + /** + * Returns true if FlipBufferStrategy with COPIED buffer contents + * is preferred for this peer's GraphicsConfiguration over + * BlitBufferStrategy, false otherwise. + * + * The reason FlipBS could be preferred is that in some configurations + * an accelerated copy to the screen is supported (like Direct3D 9) + * + * @return true if flip strategy should be used, false otherwise + */ + public boolean isFlipStrategyPreferred(ComponentPeer peer) { + return false; + } +} diff --git a/openjdk/sun/java2d/SurfaceData.java b/openjdk/sun/java2d/SurfaceData.java new file mode 100644 index 0000000..6c9978a --- /dev/null +++ b/openjdk/sun/java2d/SurfaceData.java @@ -0,0 +1,41 @@ +/* + Copyright (C) 2011, 2013 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.java2d; + +public class SurfaceData { + + final Object destination; + + public SurfaceData( Object destination ) { + this.destination = destination; + } + + public boolean isSurfaceLost() { + return false; + } + + public Object getDestination() { + return destination; + } +} diff --git a/openjdk/sun/java2d/cmm/lcms/LCMS.java b/openjdk/sun/java2d/cmm/lcms/LCMS.java new file mode 100644 index 0000000..fa405d4 --- /dev/null +++ b/openjdk/sun/java2d/cmm/lcms/LCMS.java @@ -0,0 +1,180 @@ +/* + Copyright (C) 2009 Jeroen Frijters + Copyright (C) 2010 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package sun.java2d.cmm.lcms; + +import gnu.java.awt.color.TagEntry; + +import java.awt.color.CMMException; +import java.awt.color.ColorSpace; +import java.awt.color.ICC_Profile; +import java.awt.color.ICC_ProfileGray; +import java.awt.color.ICC_ProfileRGB; +import java.awt.image.BufferedImage; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Hashtable; + +import sun.java2d.cmm.ColorTransform; +import sun.java2d.cmm.PCMM; +import sun.java2d.cmm.Profile; + +// dummy color management implementation +public class LCMS implements PCMM { + + private static final int HEADER_SIZE = 128; + + public Profile loadProfile( byte[] data ) { + return new ProfileData(data.clone()); + } + + public void freeProfile(Profile p) { + } + + public int getProfileSize(Profile p) { + return ((ProfileData)p).data.length; + } + + public void getProfileData(Profile p, byte[] data) { + byte[] src = ((ProfileData)p).data; + System.arraycopy( src, 0, data, 0, src.length ); + } + + public void getTagData(Profile p, int tagSignature, byte[] data) { + ProfileData profile = (ProfileData)p; + if( tagSignature == ICC_Profile.icSigHead ) { + byte[] src = profile.data; + System.arraycopy( src, 0, data, 0, HEADER_SIZE ); + } else { + TagEntry entry = profile.tags.get( tagSignature ); + if( entry == null ){ + throw new CMMException( "tag does not exist: " + tagSignature ); + } + byte[] src = entry.getData(); + System.arraycopy( src, 0, data, 0, src.length ); + } + + } + + public int getTagSize(Profile p, int tagSignature) { + if( tagSignature == ICC_Profile.icSigHead ) { + return HEADER_SIZE; + } + ProfileData profile = (ProfileData)p; + TagEntry entry = profile.tags.get( tagSignature ); + if( entry == null ){ + throw new CMMException( "tag does not exist: " + tagSignature ); + } + return entry.getData().length; + } + + public void setTagData(Profile p, int tagSignature, byte[] data) + { + throw new CMMException("Not implemented"); + } + + public ColorTransform createTransform(ICC_Profile profile, int renderType, int transformType) + { + return new DummyColorTransform(); + } + + public ColorTransform createTransform(ColorTransform[] transforms) + { + return new DummyColorTransform(); + } + + public static LCMS getModule() { + return new LCMS(); + } + + private static final class ProfileData extends Profile { + + private final byte[] data; + private final Hashtable tags; + + private ProfileData(byte[] data){ + super(-1); + this.data = data; + this.tags = createTagTable( data ); + } + + private static Hashtable createTagTable( byte[] data ) throws IllegalArgumentException { + ByteBuffer buf = ByteBuffer.wrap( data ); + int nTags = buf.getInt( HEADER_SIZE ); + + Hashtable tagTable = new Hashtable(); + for( int i = 0; i < nTags; i++ ) { + int sig = buf.getInt( HEADER_SIZE + i * TagEntry.entrySize + 4 ); + int offset = buf.getInt( HEADER_SIZE + i * TagEntry.entrySize + 8 ); + int size = buf.getInt( HEADER_SIZE + i * TagEntry.entrySize + 12 ); + TagEntry te = new TagEntry( sig, offset, size, data ); + + if( tagTable.put( sig, te ) != null ) + throw new IllegalArgumentException( "Duplicate tag in profile:" + te ); + } + return tagTable; + } + + } + + static class DummyColorTransform implements ColorTransform + { + public int getNumInComponents() + { + throw new CMMException("Not implemented"); + } + + public int getNumOutComponents() + { + throw new CMMException("Not implemented"); + } + + public void colorConvert(BufferedImage src, BufferedImage dst) + { + throw new CMMException("Not implemented"); + } + + public void colorConvert(Raster src, WritableRaster dst, float[] srcMinVal, float[] srcMaxVal, float[] dstMinVal, float[]dstMaxVal) + { + throw new CMMException("Not implemented"); + } + + public void colorConvert(Raster src, WritableRaster dst) + { + throw new CMMException("Not implemented"); + } + + public short[] colorConvert(short[] src, short[] dest) + { + throw new CMMException("Not implemented"); + } + + public byte[] colorConvert(byte[] src, byte[] dest) + { + throw new CMMException("Not implemented"); + } + } +} diff --git a/openjdk/sun/java2d/loops/TransformHelper.java b/openjdk/sun/java2d/loops/TransformHelper.java new file mode 100644 index 0000000..29208ff --- /dev/null +++ b/openjdk/sun/java2d/loops/TransformHelper.java @@ -0,0 +1,27 @@ +/* + Copyright (C) 2015 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package sun.java2d.loops; + +// only needed at compile time, to satisfy import statement +public class TransformHelper { } diff --git a/openjdk/sun/java2d/pipe/ShapeSpanIterator.java b/openjdk/sun/java2d/pipe/ShapeSpanIterator.java new file mode 100644 index 0000000..f320ad1 --- /dev/null +++ b/openjdk/sun/java2d/pipe/ShapeSpanIterator.java @@ -0,0 +1,82 @@ +/* + Copyright (C) 2009 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.java2d.pipe; + +import java.awt.geom.PathIterator; +import ikvm.internal.NotYetImplementedError; + +/** + * Replacement for compiling only + */ +public class ShapeSpanIterator implements SpanIterator{ + + public ShapeSpanIterator(boolean normalize){ + throw new NotYetImplementedError(); + } + + public void setOutputArea(Region devBounds){ + // TODO Auto-generated method stub + + } + + public void appendPath(PathIterator pathIterator){ + // TODO Auto-generated method stub + + } + + public void getPathBox(int[] box){ + // TODO Auto-generated method stub + + } + + @Override + public long getNativeIterator(){ + // TODO Auto-generated method stub + return 0; + } + + @Override + public void intersectClipBox(int lox, int loy, int hix, int hiy){ + // TODO Auto-generated method stub + + } + + @Override + public boolean nextSpan(int[] spanbox){ + // TODO Auto-generated method stub + return false; + } + + @Override + public void skipDownTo(int y){ + // TODO Auto-generated method stub + + } + + public void dispose(){ + // TODO Auto-generated method stub + + } + +} diff --git a/openjdk/sun/jdbc/odbc/JdbcOdbcCallableStatement.java b/openjdk/sun/jdbc/odbc/JdbcOdbcCallableStatement.java new file mode 100644 index 0000000..12a15ff --- /dev/null +++ b/openjdk/sun/jdbc/odbc/JdbcOdbcCallableStatement.java @@ -0,0 +1,662 @@ +/* + Copyright (C) 2009, 2011 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.jdbc.odbc; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.*; +import java.util.Calendar; +import java.util.Map; + +import cli.System.Data.*; +import cli.System.Data.Common.*; +import cli.System.Data.Odbc.*; + + + +/** + * @author Volker Berlin + */ +public class JdbcOdbcCallableStatement extends JdbcOdbcPreparedStatement implements CallableStatement{ + + private final Parameters parameters = new Parameters(); + + public JdbcOdbcCallableStatement(JdbcOdbcConnection jdbcConn, OdbcCommand command, String sql, int resultSetType, int resultSetConcurrency){ + super(jdbcConn, command, sql, resultSetType, resultSetConcurrency); + } + + + public final Array getArray(int parameterIndex){ + return parameters.getArray(parameterIndex); + } + + + public final Array getArray(String parameterName) throws SQLException{ + return parameters.getArray(parameterName); + } + + + public final BigDecimal getBigDecimal(int parameterIndex, int scale) throws SQLException{ + return parameters.getBigDecimal(parameterIndex, scale); + } + + + public final BigDecimal getBigDecimal(int parameterIndex) throws SQLException{ + return parameters.getBigDecimal(parameterIndex); + } + + + public final BigDecimal getBigDecimal(String parameterName) throws SQLException{ + return parameters.getBigDecimal(parameterName); + } + + + public final Blob getBlob(int parameterIndex){ + return parameters.getBlob(parameterIndex); + } + + + public final Blob getBlob(String parameterName) throws SQLException{ + return parameters.getBlob(parameterName); + } + + + public final boolean getBoolean(int parameterIndex) throws SQLException{ + return parameters.getBoolean(parameterIndex); + } + + + public final boolean getBoolean(String parameterName) throws SQLException{ + return parameters.getBoolean(parameterName); + } + + + public final byte getByte(int parameterIndex) throws SQLException{ + return parameters.getByte(parameterIndex); + } + + + public final byte getByte(String parameterName) throws SQLException{ + return parameters.getByte(parameterName); + } + + + public final byte[] getBytes(int parameterIndex) throws SQLException{ + return parameters.getBytes(parameterIndex); + } + + + public final byte[] getBytes(String parameterName) throws SQLException{ + return parameters.getBytes(parameterName); + } + + + public final Reader getCharacterStream(int parameterIndex) throws SQLException{ + return parameters.getCharacterStream(parameterIndex); + } + + + public final Reader getCharacterStream(String parameterName) throws SQLException{ + return parameters.getCharacterStream(parameterName); + } + + + public final Clob getClob(int parameterIndex){ + return parameters.getClob(parameterIndex); + } + + + public final Clob getClob(String parameterName) throws SQLException{ + return parameters.getClob(parameterName); + } + + + public final Date getDate(int parameterIndex, Calendar cal) throws SQLException{ + return parameters.getDate(parameterIndex, cal); + } + + + public final Date getDate(int parameterIndex) throws SQLException{ + return parameters.getDate(parameterIndex); + } + + + public final Date getDate(String parameterName, Calendar cal) throws SQLException{ + return parameters.getDate(parameterName, cal); + } + + + public final Date getDate(String parameterName) throws SQLException{ + return parameters.getDate(parameterName); + } + + + public final double getDouble(int parameterIndex) throws SQLException{ + return parameters.getDouble(parameterIndex); + } + + + public final double getDouble(String parameterName) throws SQLException{ + return parameters.getDouble(parameterName); + } + + + public final float getFloat(int parameterIndex) throws SQLException{ + return parameters.getFloat(parameterIndex); + } + + + public final float getFloat(String parameterName) throws SQLException{ + return parameters.getFloat(parameterName); + } + + + public final int getInt(int parameterIndex) throws SQLException{ + return parameters.getInt(parameterIndex); + } + + + public final int getInt(String parameterName) throws SQLException{ + return parameters.getInt(parameterName); + } + + + public final long getLong(int parameterIndex) throws SQLException{ + return parameters.getLong(parameterIndex); + } + + + public final long getLong(String parameterName) throws SQLException{ + return parameters.getLong(parameterName); + } + + + public final Reader getNCharacterStream(int parameterIndex) throws SQLException{ + return parameters.getNCharacterStream(parameterIndex); + } + + + public final Reader getNCharacterStream(String parameterName) throws SQLException{ + return parameters.getNCharacterStream(parameterName); + } + + + public final NClob getNClob(int parameterIndex){ + return parameters.getNClob(parameterIndex); + } + + + public final NClob getNClob(String parameterName) throws SQLException{ + return parameters.getNClob(parameterName); + } + + + public final String getNString(int parameterIndex) throws SQLException{ + return parameters.getNString(parameterIndex); + } + + + public final String getNString(String parameterName) throws SQLException{ + return parameters.getNString(parameterName); + } + + + public final Object getObject(int parameterIndex, Map> map){ + return parameters.getObject(parameterIndex, map); + } + + + public final Object getObject(int parameterIndex) throws SQLException{ + return parameters.getObject(parameterIndex); + } + + + public final Object getObject(String parameterName, Map> map) throws SQLException{ + return parameters.getObject(parameterName, map); + } + + + public final Object getObject(String parameterName) throws SQLException{ + return parameters.getObject(parameterName); + } + + + public final Ref getRef(int parameterIndex){ + return parameters.getRef(parameterIndex); + } + + + public final Ref getRef(String parameterName) throws SQLException{ + return parameters.getRef(parameterName); + } + + + public final RowId getRowId(int parameterIndex){ + return parameters.getRowId(parameterIndex); + } + + + public final RowId getRowId(String parameterName) throws SQLException{ + return parameters.getRowId(parameterName); + } + + + public final short getShort(int parameterIndex) throws SQLException{ + return parameters.getShort(parameterIndex); + } + + + public final short getShort(String parameterName) throws SQLException{ + return parameters.getShort(parameterName); + } + + + public final SQLXML getSQLXML(int parameterIndex){ + return parameters.getSQLXML(parameterIndex); + } + + + public final SQLXML getSQLXML(String parameterName) throws SQLException{ + return parameters.getSQLXML(parameterName); + } + + + public final String getString(int parameterIndex) throws SQLException{ + return parameters.getString(parameterIndex); + } + + + public final String getString(String parameterName) throws SQLException{ + return parameters.getString(parameterName); + } + + + public final Time getTime(int parameterIndex, Calendar cal) throws SQLException{ + return parameters.getTime(parameterIndex, cal); + } + + + public final Time getTime(int parameterIndex) throws SQLException{ + return parameters.getTime(parameterIndex); + } + + + public final Time getTime(String parameterName, Calendar cal) throws SQLException{ + return parameters.getTime(parameterName, cal); + } + + + public final Time getTime(String parameterName) throws SQLException{ + return parameters.getTime(parameterName); + } + + + public final Timestamp getTimestamp(int parameterIndex, Calendar cal) throws SQLException{ + return parameters.getTimestamp(parameterIndex, cal); + } + + + public final Timestamp getTimestamp(int parameterIndex) throws SQLException{ + return parameters.getTimestamp(parameterIndex); + } + + + public final Timestamp getTimestamp(String parameterName, Calendar cal) throws SQLException{ + return parameters.getTimestamp(parameterName, cal); + } + + + public final Timestamp getTimestamp(String parameterName) throws SQLException{ + return parameters.getTimestamp(parameterName); + } + + + public final URL getURL(int parameterIndex) throws SQLException{ + return parameters.getURL(parameterIndex); + } + + + public final URL getURL(String parameterName) throws SQLException{ + return parameters.getURL(parameterName); + } + + + public final boolean wasNull(){ + return parameters.wasNull(); + } + + + public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException{ + registerOutParameter(parameterIndex, sqlType, -1); + } + + + public void registerOutParameter(String parameterName, int sqlType) throws SQLException{ + registerOutParameter(parameters.findColumn(parameterName), sqlType); + } + + + public void registerOutParameter(int parameterIndex, int sqlType, int scaleOrLength) throws SQLException{ + DbParameter para = getPara(parameterIndex); + int direction = para.get_Value() == null ? ParameterDirection.Output : ParameterDirection.InputOutput; + para.set_Direction(ParameterDirection.wrap(direction)); + + if(sqlType != Types.OTHER){ + para.set_DbType(DbType.wrap(JdbcOdbcUtils.convertJdbc2AdoNetType(sqlType))); + } + + if(scaleOrLength >= 0){ + switch(sqlType){ + case Types.DECIMAL: + case Types.NUMERIC: + para.set_Scale((byte)scaleOrLength); + } + } + } + + + public void registerOutParameter(int parameterIndex, int sqlType, String typeName){ + throw new UnsupportedOperationException(); + } + + + public void registerOutParameter(String parameterName, int sqlType, int scale) throws SQLException{ + registerOutParameter(parameters.findColumn(parameterName), sqlType, scale); + } + + + public void registerOutParameter(String parameterName, int sqlType, String typeName) throws SQLException{ + registerOutParameter(parameters.findColumn(parameterName), sqlType, typeName); + } + + + public void setAsciiStream(String parameterName, InputStream x) throws SQLException{ + setAsciiStream(parameters.findColumn(parameterName), x); + } + + + public void setAsciiStream(String parameterName, InputStream x, int length) throws SQLException{ + setAsciiStream(parameters.findColumn(parameterName), x, length); + } + + + public void setAsciiStream(String parameterName, InputStream x, long length) throws SQLException{ + setAsciiStream(parameters.findColumn(parameterName), x, length); + } + + + public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException{ + setBigDecimal(parameters.findColumn(parameterName), x); + } + + + public void setBinaryStream(String parameterName, InputStream x) throws SQLException{ + setBinaryStream(parameters.findColumn(parameterName), x); + } + + + public void setBinaryStream(String parameterName, InputStream x, int length) throws SQLException{ + setBinaryStream(parameters.findColumn(parameterName), x, length); + } + + + public void setBinaryStream(String parameterName, InputStream x, long length) throws SQLException{ + setBinaryStream(parameters.findColumn(parameterName), x, length); + } + + + public void setBlob(String parameterName, Blob x) throws SQLException{ + setBlob(parameters.findColumn(parameterName), x); + } + + + public void setBlob(String parameterName, InputStream x) throws SQLException{ + setBlob(parameters.findColumn(parameterName), x); + } + + + public void setBlob(String parameterName, InputStream x, long length) throws SQLException{ + setBlob(parameters.findColumn(parameterName), x, length); + } + + + public void setBoolean(String parameterName, boolean x) throws SQLException{ + setBoolean(parameters.findColumn(parameterName), x); + } + + + public void setByte(String parameterName, byte x) throws SQLException{ + setByte(parameters.findColumn(parameterName), x); + } + + + public void setBytes(String parameterName, byte[] x) throws SQLException{ + setBytes(parameters.findColumn(parameterName), x); + } + + + public void setCharacterStream(String parameterName, Reader x) throws SQLException{ + setCharacterStream(parameters.findColumn(parameterName), x); + } + + + public void setCharacterStream(String parameterName, Reader x, int length) throws SQLException{ + setCharacterStream(parameters.findColumn(parameterName), x, length); + } + + + public void setCharacterStream(String parameterName, Reader x, long length) throws SQLException{ + setCharacterStream(parameters.findColumn(parameterName), x, length); + } + + + public void setClob(String parameterName, Clob x) throws SQLException{ + setClob(parameters.findColumn(parameterName), x); + } + + + public void setClob(String parameterName, Reader x) throws SQLException{ + setClob(parameters.findColumn(parameterName), x); + } + + + public void setClob(String parameterName, Reader x, long length) throws SQLException{ + setClob(parameters.findColumn(parameterName), x, length); + } + + + public void setDate(String parameterName, Date x) throws SQLException{ + setDate(parameters.findColumn(parameterName), x); + } + + + public void setDate(String parameterName, Date x, Calendar cal) throws SQLException{ + setDate(parameters.findColumn(parameterName), x, cal); + } + + + public void setDouble(String parameterName, double x) throws SQLException{ + setDouble(parameters.findColumn(parameterName), x); + } + + + public void setFloat(String parameterName, float x) throws SQLException{ + setFloat(parameters.findColumn(parameterName), x); + } + + + public void setInt(String parameterName, int x) throws SQLException{ + setInt(parameters.findColumn(parameterName), x); + } + + + public void setLong(String parameterName, long x) throws SQLException{ + setLong(parameters.findColumn(parameterName), x); + } + + + public void setNCharacterStream(String parameterName, Reader x) throws SQLException{ + setNCharacterStream(parameters.findColumn(parameterName), x); + } + + + public void setNCharacterStream(String parameterName, Reader x, long length) throws SQLException{ + setNCharacterStream(parameters.findColumn(parameterName), x, length); + } + + + public void setNClob(String parameterName, NClob x) throws SQLException{ + setNClob(parameters.findColumn(parameterName), x); + } + + + public void setNClob(String parameterName, Reader x) throws SQLException{ + setNClob(parameters.findColumn(parameterName), x); + } + + + public void setNClob(String parameterName, Reader x, long length) throws SQLException{ + setNClob(parameters.findColumn(parameterName), x, length); + } + + + public void setNString(String parameterName, String x) throws SQLException{ + setNString(parameters.findColumn(parameterName), x); + } + + + public void setNull(String parameterName, int sqlType) throws SQLException{ + setNull(parameters.findColumn(parameterName), sqlType); + } + + + public void setNull(String parameterName, int sqlType, String typeName) throws SQLException{ + setNull(parameters.findColumn(parameterName), sqlType, typeName); + } + + + public void setObject(String parameterName, Object x) throws SQLException{ + setObject(parameters.findColumn(parameterName), x); + } + + + public void setObject(String parameterName, Object x, int targetSqlType) throws SQLException{ + setObject(parameters.findColumn(parameterName), x, targetSqlType); + } + + + public void setObject(String parameterName, Object x, int targetSqlType, int scaleOrLength) throws SQLException{ + setObject(parameters.findColumn(parameterName), x, targetSqlType, scaleOrLength); + } + + + public void setRowId(String parameterName, RowId x) throws SQLException{ + setRowId(parameters.findColumn(parameterName), x); + } + + + public void setSQLXML(String parameterName, SQLXML x) throws SQLException{ + setSQLXML(parameters.findColumn(parameterName), x); + } + + + public void setShort(String parameterName, short x) throws SQLException{ + setShort(parameters.findColumn(parameterName), x); + } + + + public void setString(String parameterName, String x) throws SQLException{ + setString(parameters.findColumn(parameterName), x); + } + + + public void setTime(String parameterName, Time x) throws SQLException{ + setTime(parameters.findColumn(parameterName), x); + } + + + public void setTime(String parameterName, Time x, Calendar cal) throws SQLException{ + setTime(parameters.findColumn(parameterName), x, cal); + } + + + public void setTimestamp(String parameterName, Timestamp x) throws SQLException{ + setTimestamp(parameters.findColumn(parameterName), x); + } + + + public void setTimestamp(String parameterName, Timestamp x, Calendar cal) throws SQLException{ + setTimestamp(parameters.findColumn(parameterName), x, cal); + } + + + public void setURL(String parameterName, URL x) throws SQLException{ + setURL(parameters.findColumn(parameterName), x); + } + + private class Parameters extends JdbcOdbcObject{ + + @Override + public int findColumn(String parameterName) throws SQLException{ + try{ + DbParameterCollection params = command.get_Parameters(); + for(int i=0; i T getObject(int parameterIndex, Class type) + throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + + /** + * {@inheritDoc} + */ + public T getObject(String parameterName, Class type) + throws SQLException { + throw new SQLFeatureNotSupportedException(); + } +} diff --git a/openjdk/sun/jdbc/odbc/JdbcOdbcConnection.java b/openjdk/sun/jdbc/odbc/JdbcOdbcConnection.java new file mode 100644 index 0000000..5e075b2 --- /dev/null +++ b/openjdk/sun/jdbc/odbc/JdbcOdbcConnection.java @@ -0,0 +1,490 @@ +/* + Copyright (C) 2009, 2011 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.jdbc.odbc; + +import cli.System.Data.*; +import cli.System.Data.Common.*; +import cli.System.Data.Odbc.*; + +import java.sql.*; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.Executor; + +/** + * This JDBC Driver is a wrapper to the ODBC.NET Data Provider + */ +public class JdbcOdbcConnection implements Connection{ + + private final OdbcConnection netConn; + + private DbTransaction transaction; + + private int isolation = TRANSACTION_READ_COMMITTED; + + + JdbcOdbcConnection(String connectString, Properties info) throws SQLException{ + try{ + boolean isDSN = connectString.indexOf('=') < 0; + StringBuilder connStr = new StringBuilder(); + if(isDSN){ + connStr.append("DSN="); + } + connStr.append(connectString); + + String uid = info.getProperty("user"); + String pwd = info.getProperty("password"); + + if(uid != null){ + connStr.append(";UID=").append(uid); + } + if(pwd != null){ + connStr.append(";PWD=").append(pwd); + } + + netConn = new OdbcConnection(connStr.toString()); + + netConn.Open(); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + @Override + public void clearWarnings() throws SQLException{ + // TODO Auto-generated method stub + + } + + + @Override + public void close() throws SQLException{ + try{ + netConn.Close(); + }catch(Throwable ex){ + throw JdbcOdbcUtils.createSQLException(ex); + } + } + + + @Override + public Array createArrayOf(String typeName, Object[] elements){ + throw new UnsupportedOperationException(); + } + + + @Override + public Blob createBlob(){ + throw new UnsupportedOperationException(); + } + + + @Override + public Clob createClob(){ + throw new UnsupportedOperationException(); + } + + + @Override + public NClob createNClob(){ + throw new UnsupportedOperationException(); + } + + + @Override + public SQLXML createSQLXML(){ + throw new UnsupportedOperationException(); + } + + + @Override + public Statement createStatement() throws SQLException{ + return createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + } + + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException{ + try{ + return new JdbcOdbcStatement(this, netConn.CreateCommand(), resultSetType, resultSetConcurrency); + }catch(Throwable ex){ + throw JdbcOdbcUtils.createSQLException(ex); + } + } + + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability){ + throw new UnsupportedOperationException(); + } + + + @Override + public Struct createStruct(String typeName, Object[] attributes){ + throw new UnsupportedOperationException(); + } + + + @Override + public void setAutoCommit(boolean autoCommit) throws SQLException{ + try{ + if(autoCommit && transaction != null){ + return; // no change + } + if(!autoCommit && transaction == null){ + return; // no change + } + int level; + switch(isolation){ + case TRANSACTION_READ_COMMITTED: + level = IsolationLevel.ReadUncommitted; + break; + case TRANSACTION_READ_UNCOMMITTED: + level = IsolationLevel.ReadCommitted; + break; + case TRANSACTION_REPEATABLE_READ: + level = IsolationLevel.RepeatableRead; + break; + case TRANSACTION_SERIALIZABLE: + level = IsolationLevel.Serializable; + break; + default: + level = IsolationLevel.ReadCommitted; + } + if(autoCommit){ + transaction = netConn.BeginTransaction(IsolationLevel.wrap(level)); + }else{ + transaction.Commit(); + transaction = null; + } + }catch(Throwable ex){ + throw JdbcOdbcUtils.createSQLException(ex); + } + } + + + @Override + public boolean getAutoCommit(){ + return transaction != null; + } + + + @Override + public void commit() throws SQLException{ + try{ + if(transaction == null){ + // auto commit == true + return; + } + transaction.Commit(); + transaction = netConn.BeginTransaction(transaction.get_IsolationLevel()); + }catch(Throwable ex){ + throw JdbcOdbcUtils.createSQLException(ex); + } + } + + + @Override + public void rollback() throws SQLException{ + try{ + if(transaction == null){ + // auto commit == true + return; + } + transaction.Rollback(); + transaction = netConn.BeginTransaction(transaction.get_IsolationLevel()); + }catch(Throwable ex){ + throw JdbcOdbcUtils.createSQLException(ex); + } + } + + + @Override + public void setTransactionIsolation(int level){ + isolation = level; + } + + + @Override + public int getTransactionIsolation(){ + return isolation; + } + + + @Override + public String getClientInfo(String name){ + throw new UnsupportedOperationException(); + } + + + @Override + public Properties getClientInfo(){ + throw new UnsupportedOperationException(); + } + + + @Override + public int getHoldability(){ + throw new UnsupportedOperationException(); + } + + + @Override + public DatabaseMetaData getMetaData(){ + return new JdbcOdbcDatabaseMetaData(this, netConn); + } + + + @Override + public Map> getTypeMap(){ + throw new UnsupportedOperationException(); + } + + + @Override + public SQLWarning getWarnings() throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + @Override + public boolean isClosed() throws SQLException{ + return netConn.get_State().Value == ConnectionState.Closed; + } + + + @Override + public boolean isReadOnly() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + @Override + public boolean isValid(int timeout) throws SQLException{ + throw new UnsupportedOperationException(); + } + + + @Override + public String nativeSQL(String sql) throws SQLException{ + // TODO Auto-generated method stub + return sql; + } + + + @Override + public CallableStatement prepareCall(String sql) throws SQLException{ + return prepareCall(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + } + + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException{ + try{ + return new JdbcOdbcCallableStatement(this, netConn.CreateCommand(), sql, resultSetType, + resultSetConcurrency); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, + int resultSetHoldability){ + throw new UnsupportedOperationException(); + } + + + @Override + public PreparedStatement prepareStatement(String sql) throws SQLException{ + return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + } + + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) + throws SQLException{ + try{ + return new JdbcOdbcPreparedStatement(this, netConn.CreateCommand(), sql, resultSetType, + resultSetConcurrency); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, + int resultSetHoldability){ + throw new UnsupportedOperationException(); + } + + + @Override + public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys){ + throw new UnsupportedOperationException(); + } + + + @Override + public PreparedStatement prepareStatement(String sql, int[] columnIndexes){ + throw new UnsupportedOperationException(); + } + + + @Override + public PreparedStatement prepareStatement(String sql, String[] columnNames){ + throw new UnsupportedOperationException(); + } + + + @Override + public void releaseSavepoint(Savepoint savepoint){ + throw new UnsupportedOperationException(); + } + + + @Override + public void rollback(Savepoint savepoint){ + throw new UnsupportedOperationException(); + } + + + @Override + public void setCatalog(String catalog) throws SQLException{ + try{ + netConn.ChangeDatabase(catalog); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + @Override + public String getCatalog(){ + return netConn.get_Database(); + } + + + @Override + public void setClientInfo(String name, String value){ + throw new UnsupportedOperationException(); + } + + + @Override + public void setClientInfo(Properties properties){ + throw new UnsupportedOperationException(); + } + + + @Override + public void setHoldability(int holdability){ + throw new UnsupportedOperationException(); + } + + + @Override + public void setReadOnly(boolean readOnly) throws SQLException{ + // TODO Auto-generated method stub + + } + + + @Override + public Savepoint setSavepoint(){ + throw new UnsupportedOperationException(); + } + + + @Override + public Savepoint setSavepoint(String name){ + throw new UnsupportedOperationException(); + } + + + @Override + public void setTypeMap(Map> map){ + throw new UnsupportedOperationException(); + } + + + @Override + public boolean isWrapperFor(Class iface){ + return iface.isAssignableFrom(this.getClass()); + } + + + @Override + public T unwrap(Class iface) throws SQLException{ + if(isWrapperFor(iface)){ + return (T)this; + } + throw new SQLException(this.getClass().getName() + " does not implements " + iface.getName() + ".", "01000"); + } + + + /** + * {@inheritDoc} + */ + public void setSchema(String schema) throws SQLException { + } + + + /** + * {@inheritDoc} + */ + public String getSchema() throws SQLException { + return null; + } + + + /** + * {@inheritDoc} + */ + public void abort(Executor executor) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + + /** + * {@inheritDoc} + */ + public void setNetworkTimeout(Executor executor, int milliseconds) + throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + + /** + * {@inheritDoc} + */ + public int getNetworkTimeout() throws SQLException { + throw new SQLFeatureNotSupportedException(); + } +} diff --git a/openjdk/sun/jdbc/odbc/JdbcOdbcDTResultSet.java b/openjdk/sun/jdbc/odbc/JdbcOdbcDTResultSet.java new file mode 100644 index 0000000..9de750a --- /dev/null +++ b/openjdk/sun/jdbc/odbc/JdbcOdbcDTResultSet.java @@ -0,0 +1,287 @@ +/* + Copyright (C) 2009 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.jdbc.odbc; + +import java.sql.*; + +import cli.System.Data.*; + +/** + * This JDBC Driver is a wrapper to the ODBC.NET Data Provider. This ResultSet based on DataTable. It is read only and + * scrollable. + */ +public class JdbcOdbcDTResultSet extends JdbcOdbcResultSet{ + + private final DataTable data; + + private DataRowCollection rows; + + private int rowIndex; // row index starting with 0; -1 means beforeFirst + + private cli.System.Data.DataRow row; + + + public JdbcOdbcDTResultSet(DataTable data){ + this(data, CONCUR_READ_ONLY); + } + public JdbcOdbcDTResultSet(DataTable data, int concurrency){ + super(null, TYPE_SCROLL_INSENSITIVE, concurrency); + this.data = data; + this.rows = data.get_Rows(); + this.rowIndex = -1; + } + + + @Override + public boolean absolute(int rowPosition) throws SQLException{ + if(rowPosition == 0){ + return !isBeforeFirst() && !isAfterLast(); + } + DataRowCollection dataRows = getRows(); + int count = dataRows.get_Count(); + if(rowPosition > 0){ + if(rowPosition > count){ + rowIndex = count; + setDataRow(); + return false; + } + rowIndex = rowPosition - 1; + setDataRow(); + return true; + }else{ + if(-rowPosition > count){ + rowIndex = -1; + setDataRow(); + return false; + } + rowIndex = count + rowPosition; + setDataRow(); + return true; + } + } + + + @Override + public void afterLast() throws SQLException{ + rowIndex = getRows().get_Count(); + setDataRow(); + } + + + @Override + public void beforeFirst() throws SQLException{ + rowIndex = -1; + setDataRow(); + } + + + @Override + public void close(){ + rows = null; + } + + + @Override + public int findColumn(String columnLabel) throws SQLException{ + getRows(); // Check if ResultSet is closed + int idx = data.get_Columns().IndexOf(columnLabel); + if(idx < 0){ + throw new SQLException("Column '" + columnLabel + "' not found.", "S0022"); + } + return idx + 1; + } + + + @Override + public boolean first() throws SQLException{ + beforeFirst(); + return next(); + } + + + @Override + public ResultSetMetaData getMetaData(){ + return new JdbcOdbcDTResultSetMetaData(data); + } + + + @Override + public int getRow() throws SQLException{ + return rowIndex < getRows().get_Count() ? rowIndex + 1 : 0; + } + + + @Override + public boolean isAfterLast() throws SQLException{ + int count = getRows().get_Count(); + return rowIndex >= count || count == 0; + } + + + @Override + public boolean isBeforeFirst() throws SQLException{ + return rowIndex <= -1 || getRows().get_Count() == 0; + } + + + @Override + public boolean isClosed(){ + return rows == null; + } + + + @Override + public boolean isFirst() throws SQLException{ + return rowIndex == 0 && getRows().get_Count() > 0; + } + + + @Override + public boolean isLast() throws SQLException{ + return rowIndex >= 0 && rowIndex == getRows().get_Count() - 1; + } + + + @Override + public boolean last() throws SQLException{ + afterLast(); + return previous(); + } + + + @Override + public boolean next() throws SQLException{ + DataRowCollection dataRows = getRows(); + if(rowIndex + 1 < dataRows.get_Count()){ + ++rowIndex; + setDataRow(); + return true; + }else{ + rowIndex = dataRows.get_Count(); + setDataRow(); + return false; + } + } + + + @Override + public boolean previous() throws SQLException{ + if(rowIndex > 0){ + --rowIndex; + setDataRow(); + return true; + }else{ + rowIndex = -1; + setDataRow(); + return false; + } + } + + + @Override + public void refreshRow(){ + // ignore it + } + + + @Override + public boolean relative(int rowPositions) throws SQLException{ + DataRowCollection dataRows = getRows(); + int newRowIndex = rowIndex + rowPositions; + if(newRowIndex < 0){ + rowIndex = -1; + setDataRow(); + return false; + } + int count = dataRows.get_Count(); + if(newRowIndex >= dataRows.get_Count()){ + rowIndex = count; + setDataRow(); + return false; + } + rowIndex = newRowIndex; + setDataRow(); + return true; + } + + + /** + * {@inheritDoc} + */ + @Override + protected Object getObjectImpl(int columnIndex) throws SQLException{ + try{ + return getDataRow().get_Item(columnIndex - 1); + }catch(ArrayIndexOutOfBoundsException ex){ + throw new SQLException("Invalid column number (" + columnIndex + "). A number between 1 and " + + data.get_Columns().get_Count() + " is valid.", "S1002"); + } + } + + + /** + * Check if this ResultSet is closed before access to the DataRowCollection + * + * @return the local rows object + * @throws SQLException + * If the ResultSet is closed. + */ + protected DataRowCollection getRows() throws SQLException{ + if(rows == null){ + throw new SQLException("ResultSet is closed.", "24000"); + } + return rows; + } + + + /** + * Get the current DataRow + * + * @return the DataRow + * @throws SQLException + * if closed or no current Row + */ + protected DataRow getDataRow() throws SQLException{ + getRows(); // checks if ResultSet is closed + if(row == null){ + throw new SQLException("No current row", "S1109"); + } + return row; + } + + /** + * Set the current row from the current rowIndex. If the rowIndex was not change + * then the row variable will be new set. + * @throws SQLException If the ResultSet is closed. + */ + protected void setDataRow() throws SQLException{ + DataRowCollection dataRows = getRows(); + if(rowIndex < 0 || rowIndex >= dataRows.get_Count()){ + row = null; + }else{ + row = dataRows.get_Item(rowIndex); + } + } + +} diff --git a/openjdk/sun/jdbc/odbc/JdbcOdbcDTResultSetMetaData.java b/openjdk/sun/jdbc/odbc/JdbcOdbcDTResultSetMetaData.java new file mode 100644 index 0000000..25c15fb --- /dev/null +++ b/openjdk/sun/jdbc/odbc/JdbcOdbcDTResultSetMetaData.java @@ -0,0 +1,180 @@ +/* + Copyright (C) 2009 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.jdbc.odbc; + +import java.sql.*; + +import cli.System.Data.*; + +/** + * This JDBC Driver is a wrapper to the ODBC.NET Data Provider + */ +public class JdbcOdbcDTResultSetMetaData implements ResultSetMetaData{ + + private final DataTable table; + + + public JdbcOdbcDTResultSetMetaData(DataTable table){ + this.table = table; + } + + + public String getCatalogName(int column){ + return ""; + } + + + public String getColumnClassName(int column){ + String type = getDataColumn(column).get_DataType().toString(); + return JdbcOdbcUtils.getJavaClassName(type); + } + + + public int getColumnCount(){ + return table.get_Columns().get_Count(); + } + + + public int getColumnDisplaySize(int column) throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public String getColumnLabel(int column) throws SQLException{ + return getDataColumn(column).get_Caption(); + } + + + public String getColumnName(int column) throws SQLException{ + return getDataColumn(column).get_ColumnName(); + } + + + public int getColumnType(int column) throws SQLException{ + cli.System.Type type = getDataColumn(column).get_DataType(); + // TODO Auto-generated method stub + return Types.OTHER; + } + + + public String getColumnTypeName(int column) throws SQLException{ + return ""; + } + + + public int getPrecision(int column) throws SQLException{ + return getDataColumn(column).get_MaxLength(); + } + + + public int getScale(int column) throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public String getSchemaName(int column) throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public String getTableName(int column) throws SQLException{ + return table.get_TableName(); + } + + + public boolean isAutoIncrement(int column) throws SQLException{ + return getDataColumn(column).get_AutoIncrement(); + } + + + public boolean isCaseSensitive(int column) throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean isCurrency(int column) throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean isDefinitelyWritable(int column) throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public int isNullable(int column) throws SQLException{ + return getDataColumn(column).get_AllowDBNull() ? columnNullable : columnNoNulls; + } + + + public boolean isReadOnly(int column) throws SQLException{ + return getDataColumn(column).get_ReadOnly(); + } + + + public boolean isSearchable(int column) throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean isSigned(int column) throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean isWritable(int column) throws SQLException{ + return !getDataColumn(column).get_ReadOnly(); + } + + + public boolean isWrapperFor(Class iface){ + return iface.isAssignableFrom(this.getClass()); + } + + + public T unwrap(Class iface) throws SQLException{ + if(isWrapperFor(iface)){ + return (T)this; + } + throw new SQLException(this.getClass().getName() + " does not implements " + iface.getName() + ".", "01000"); + } + + + /** + * Get a DataColumn from the DataTable + * @param column the JDBC column index starting with 1 + * @return the DataColumn + */ + private DataColumn getDataColumn(int column){ + return table.get_Columns().get_Item(column - 1); + } +} diff --git a/openjdk/sun/jdbc/odbc/JdbcOdbcDatabaseMetaData.java b/openjdk/sun/jdbc/odbc/JdbcOdbcDatabaseMetaData.java new file mode 100644 index 0000000..df631c5 --- /dev/null +++ b/openjdk/sun/jdbc/odbc/JdbcOdbcDatabaseMetaData.java @@ -0,0 +1,1211 @@ +/* + Copyright (C) 2009, 2011 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.jdbc.odbc; + +import ikvm.lang.CIL; + +import java.sql.*; +import java.util.HashSet; + +import cli.System.Data.*; +import cli.System.Data.Common.*; +import cli.System.Data.Odbc.*; + +/** + * @author Volker Berlin + */ +public class JdbcOdbcDatabaseMetaData implements DatabaseMetaData{ + + private JdbcOdbcConnection jdbcConn; + + private final OdbcConnection netConn; + + private DataRow dataSourceInfo; + + public JdbcOdbcDatabaseMetaData(JdbcOdbcConnection jdbcConn, OdbcConnection netConn){ + this.jdbcConn = jdbcConn; + this.netConn = netConn; + } + + + public boolean allProceduresAreCallable() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean allTablesAreSelectable() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean autoCommitFailureClosesAllResultSets(){ + throw new UnsupportedOperationException(); + } + + + public boolean dataDefinitionCausesTransactionCommit() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean dataDefinitionIgnoredInTransactions() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean deletesAreDetected(int type) throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean doesMaxRowSizeIncludeBlobs() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, + String attributeNamePattern){ + throw new UnsupportedOperationException(); + } + + + public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) + throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public String getCatalogSeparator() throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public String getCatalogTerm() throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public ResultSet getCatalogs() throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public ResultSet getClientInfoProperties(){ + throw new UnsupportedOperationException(); + } + + + public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) + throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) + throws SQLException{ + try{ + // the description of the restrictions can you request with GetSchema("Restrictions") + String[] restrictions = new String[]{catalog, schemaPattern, tableNamePattern, columnNamePattern}; + DataTable data = netConn.GetSchema(OdbcMetaDataCollectionNames.Columns, restrictions); + return new JdbcOdbcDTResultSet(data); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public Connection getConnection(){ + return jdbcConn; + } + + + public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, + String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public int getDatabaseMajorVersion(){ + String version = netConn.get_ServerVersion().trim(); + for(int i = 0; i < version.length(); i++){ + char ch = version.charAt(i); + if(ch < '0' || ch > '9'){ + return Integer.parseInt(version.substring(0, i)); + } + } + return Integer.parseInt(version); + } + + + public int getDatabaseMinorVersion(){ + String version = netConn.get_ServerVersion().trim(); + int idx = version.indexOf('.'); + if(idx < 0){ + return 0; + } + version = version.substring(idx + 1); + for(int i = 0; i < version.length(); i++){ + char ch = version.charAt(i); + if(ch < '0' || ch > '9'){ + return Integer.parseInt(version.substring(0, i)); + } + } + return Integer.parseInt(version); + } + + + public String getDatabaseProductName() throws SQLException{ + return String.valueOf(getInfo(DbMetaDataColumnNames.DataSourceProductName)); + } + + + public String getDatabaseProductVersion(){ + return netConn.get_ServerVersion(); + } + + + public int getDefaultTransactionIsolation(){ + return Connection.TRANSACTION_READ_COMMITTED; + } + + + public int getDriverMajorVersion(){ + return 2; + } + + + public int getDriverMinorVersion(){ + return 1; + } + + + public String getDriverName(){ + return "JDBC-ODBC Bridge (" + netConn.get_Driver() + ")"; + } + + + public String getDriverVersion(){ + return "2.0001"; + } + + + public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public String getExtraNameCharacters(){ + return ""; + } + + + public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, + String columnNamePattern){ + throw new UnsupportedOperationException(); + } + + + public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern){ + throw new UnsupportedOperationException(); + } + + + public String getIdentifierQuoteString() throws SQLException{ + String quote = (String)getInfo(DbMetaDataColumnNames.QuotedIdentifierPattern); + if(quote.length()>=2){ + char ch1 = quote.charAt(0); + char ch2 = quote.charAt(quote.length()-1); + if(ch1 == ch2){ + return quote.substring(0,1); + } + } + return "\""; // ANSI SQL and should work with the most DBMS + } + + + public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) + throws SQLException{ + try{ + // the description of the restrictions can you request with GetSchema("Restrictions") + String[] restrictions = new String[]{catalog, schema, table}; + DataTable data = netConn.GetSchema(OdbcMetaDataCollectionNames.Indexes, restrictions); + return new JdbcOdbcDTResultSet(data); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public int getJDBCMajorVersion(){ + return 2; + } + + + public int getJDBCMinorVersion(){ + return 0; + } + + + public int getMaxBinaryLiteralLength() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public int getMaxCatalogNameLength() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public int getMaxCharLiteralLength() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public int getMaxColumnNameLength() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public int getMaxColumnsInGroupBy() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public int getMaxColumnsInIndex() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public int getMaxColumnsInOrderBy() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public int getMaxColumnsInSelect() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public int getMaxColumnsInTable() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public int getMaxConnections() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public int getMaxCursorNameLength() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public int getMaxIndexLength() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public int getMaxProcedureNameLength() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public int getMaxRowSize() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public int getMaxSchemaNameLength() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public int getMaxStatementLength() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public int getMaxStatements() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public int getMaxTableNameLength() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public int getMaxTablesInSelect() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public int getMaxUserNameLength() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public String getNumericFunctions() throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, + String columnNamePattern) throws SQLException{ + try{ + // the description of the restrictions can you request with GetSchema("Restrictions") + String[] restrictions = new String[]{catalog, schemaPattern, procedureNamePattern, columnNamePattern}; + DataTable dt1 = netConn.GetSchema(OdbcMetaDataCollectionNames.ProcedureColumns, restrictions); + DataTable dt2 = netConn.GetSchema(OdbcMetaDataCollectionNames.ProcedureParameters, restrictions); + // concatenate the both DataTable + DataRowCollection rows1 = dt1.get_Rows(); + DataRowCollection rows2 = dt2.get_Rows(); + for(int i = 0; i < rows2.get_Count(); i++){ + DataRow row = rows2.get_Item(i); + rows1.Add(row.get_ItemArray()); + } + return new JdbcOdbcDTResultSet(dt1); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public String getProcedureTerm() throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) + throws SQLException{ + try{ + // the description of the restrictions can you request with GetSchema("Restrictions") + String[] restrictions = new String[]{catalog, schemaPattern, procedureNamePattern}; + DataTable data = netConn.GetSchema(OdbcMetaDataCollectionNames.Procedures, restrictions); + return new JdbcOdbcDTResultSet(data); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public int getResultSetHoldability(){ + throw new UnsupportedOperationException(); + } + + + public RowIdLifetime getRowIdLifetime(){ + throw new UnsupportedOperationException(); + } + + + public String getSQLKeywords() throws SQLException{ + try{ + DataTable dt = netConn.GetSchema(DbMetaDataCollectionNames.ReservedWords); + final DataRowCollection rows = dt.get_Rows(); + final int count = rows.get_Count(); + final StringBuilder builder = new StringBuilder(); + for(int i=0; i 0){ + builder.append(','); + } + builder.append(word); + } + return builder.toString(); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public int getSQLStateType() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public String getSchemaTerm() throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public ResultSet getSchemas() throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public ResultSet getSchemas(String catalog, String schemaPattern){ + throw new UnsupportedOperationException(); + } + + + public String getSearchStringEscape() throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public String getStringFunctions() throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern){ + throw new UnsupportedOperationException(); + } + + + public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern){ + throw new UnsupportedOperationException(); + } + + + public String getSystemFunctions() throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) + throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public ResultSet getTableTypes() throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) + throws SQLException{ + try{ + // the description of the restrictions can you request with GetSchema("Restrictions") + String[] restrictions = new String[]{catalog, schemaPattern, tableNamePattern}; + DataTable dt1 = netConn.GetSchema(OdbcMetaDataCollectionNames.Tables, restrictions); + DataTable dt2 = netConn.GetSchema(OdbcMetaDataCollectionNames.Views, restrictions); + // concatenate the both DataTable + DataRowCollection rows1 = dt1.get_Rows(); + DataRowCollection rows2 = dt2.get_Rows(); + for(int i = 0; i < rows2.get_Count(); i++){ + DataRow row = rows2.get_Item(i); + rows1.Add(row.get_ItemArray()); + } + if(types != null){ + RowLoop: + // Filter the types + for(int i = rows1.get_Count() - 1; i >= 0; i--){ + DataRow row = rows1.get_Item(i); + Object tableType = row.get_Item("TABLE_TYPE"); + for(String type : types){ + if(type.equals(tableType)){ + continue RowLoop; + } + } + rows1.RemoveAt(i); + } + } + return new JdbcOdbcDTResultSet(dt1); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public String getTimeDateFunctions() throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public ResultSet getTypeInfo() throws SQLException{ + try{ + //TODO Column Names and order are wrong + DataTable data = netConn.GetSchema(DbMetaDataCollectionNames.DataTypes); + return new JdbcOdbcDTResultSet(data); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types){ + throw new UnsupportedOperationException(); + } + + + public String getURL() throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public String getUserName() throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public boolean insertsAreDetected(int type) throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean isCatalogAtStart() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean isReadOnly() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean locatorsUpdateCopy(){ + throw new UnsupportedOperationException(); + } + + + public boolean nullPlusNonNullIsNull() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean nullsAreSortedAtEnd() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean nullsAreSortedAtStart() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean nullsAreSortedHigh() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean nullsAreSortedLow() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean othersDeletesAreVisible(int type) throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean othersInsertsAreVisible(int type) throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean othersUpdatesAreVisible(int type) throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean ownDeletesAreVisible(int type) throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean ownInsertsAreVisible(int type) throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean ownUpdatesAreVisible(int type) throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean storesLowerCaseIdentifiers() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean storesLowerCaseQuotedIdentifiers() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean storesMixedCaseIdentifiers() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean storesMixedCaseQuotedIdentifiers() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean storesUpperCaseIdentifiers() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean storesUpperCaseQuotedIdentifiers() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsANSI92EntryLevelSQL() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsANSI92FullSQL() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsANSI92IntermediateSQL() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsAlterTableWithAddColumn() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsAlterTableWithDropColumn() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsBatchUpdates() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsCatalogsInDataManipulation() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsCatalogsInIndexDefinitions() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsCatalogsInProcedureCalls() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsCatalogsInTableDefinitions() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsColumnAliasing() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsConvert() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsConvert(int fromType, int toType) throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsCoreSQLGrammar() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsCorrelatedSubqueries() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsDataManipulationTransactionsOnly() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsDifferentTableCorrelationNames() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsExpressionsInOrderBy() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsExtendedSQLGrammar() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsFullOuterJoins() throws SQLException{ + int join = CIL.unbox_int(getInfo(DbMetaDataColumnNames.SupportedJoinOperators)); + return (join & SupportedJoinOperators.FullOuter) > 0; + } + + + public boolean supportsGetGeneratedKeys() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsGroupBy() throws SQLException{ + int behavior = CIL.unbox_int(getInfo(DbMetaDataColumnNames.GroupByBehavior)); + return behavior != GroupByBehavior.NotSupported; + } + + + public boolean supportsGroupByBeyondSelect() throws SQLException{ + int behavior = CIL.unbox_int(getInfo(DbMetaDataColumnNames.GroupByBehavior)); + return behavior == GroupByBehavior.MustContainAll; + } + + + public boolean supportsGroupByUnrelated() throws SQLException{ + int behavior = CIL.unbox_int(getInfo(DbMetaDataColumnNames.GroupByBehavior)); + return behavior == GroupByBehavior.Unrelated; + } + + + public boolean supportsIntegrityEnhancementFacility() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsLikeEscapeClause() throws SQLException{ + return getSQLKeywords().toUpperCase().indexOf(",LIKE,") > 0; + } + + + public boolean supportsLimitedOuterJoins() throws SQLException{ + int join = CIL.unbox_int(getInfo(DbMetaDataColumnNames.SupportedJoinOperators)); + return join > 0; + } + + + public boolean supportsMinimumSQLGrammar() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsMixedCaseIdentifiers() throws SQLException{ + int identifierCase = CIL.unbox_int(getInfo(DbMetaDataColumnNames.IdentifierCase)); + return identifierCase == IdentifierCase.Sensitive; + } + + + public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException{ + int identifierCase = CIL.unbox_int(getInfo(DbMetaDataColumnNames.QuotedIdentifierCase)); + return identifierCase == IdentifierCase.Sensitive; + } + + + public boolean supportsMultipleOpenResults() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsMultipleResultSets() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsMultipleTransactions() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsNamedParameters() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsNonNullableColumns() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsOpenCursorsAcrossCommit() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsOpenCursorsAcrossRollback() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsOpenStatementsAcrossCommit() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsOpenStatementsAcrossRollback() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsOrderByUnrelated() throws SQLException{ + return CIL.unbox_boolean( getInfo(DbMetaDataColumnNames.OrderByColumnsInSelect)); + } + + + public boolean supportsOuterJoins() throws SQLException{ + int join = CIL.unbox_int(getInfo(DbMetaDataColumnNames.SupportedJoinOperators)); + return (join & SupportedJoinOperators.LeftOuter) > 0 || (join & SupportedJoinOperators.RightOuter) > 0; + } + + + public boolean supportsPositionedDelete() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsPositionedUpdate() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsResultSetHoldability(int holdability){ + throw new UnsupportedOperationException(); + } + + + public boolean supportsResultSetType(int type) throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsSavepoints() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsSchemasInDataManipulation() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsSchemasInIndexDefinitions() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsSchemasInProcedureCalls() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsSchemasInTableDefinitions() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsSelectForUpdate() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsStatementPooling(){ + throw new UnsupportedOperationException(); + } + + + public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException{ + throw new UnsupportedOperationException(); + } + + + public boolean supportsStoredProcedures() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsSubqueriesInComparisons() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsSubqueriesInExists() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsSubqueriesInIns() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsSubqueriesInQuantifieds() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsTableCorrelationNames() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsTransactionIsolationLevel(int level) throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsTransactions() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsUnion() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean supportsUnionAll() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean updatesAreDetected(int type) throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean usesLocalFilePerTable() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean usesLocalFiles() throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public boolean isWrapperFor(Class iface){ + return iface.isAssignableFrom(this.getClass()); + } + + + public T unwrap(Class iface) throws SQLException{ + if(isWrapperFor(iface)){ + return (T)this; + } + throw new SQLException(this.getClass().getName() + " does not implements " + iface.getName() + ".", "01000"); + } + + private Object getInfo(String key) throws SQLException{ + try{ + if(dataSourceInfo == null){ + DataTable td = netConn.GetSchema(DbMetaDataCollectionNames.DataSourceInformation); + dataSourceInfo = td.get_Rows().get_Item(0); + } + return dataSourceInfo.get_Item(key); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + /** + * {@inheritDoc} + */ + public ResultSet getPseudoColumns(String catalog, String schemaPattern, + String tableNamePattern, String columnNamePattern) + throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + + /** + * {@inheritDoc} + */ + public boolean generatedKeyAlwaysReturned() throws SQLException { + return false; + } +} diff --git a/openjdk/sun/jdbc/odbc/JdbcOdbcDriver.java b/openjdk/sun/jdbc/odbc/JdbcOdbcDriver.java new file mode 100644 index 0000000..9eb1d9d --- /dev/null +++ b/openjdk/sun/jdbc/odbc/JdbcOdbcDriver.java @@ -0,0 +1,111 @@ +/* + Copyright (C) 2009, 2011 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.jdbc.odbc; + +import java.sql.*; +import java.util.Properties; +import java.util.logging.Logger; + +/** + * This JDBC Driver is a wrapper to the ODBC.NET Data Provider + */ +public class JdbcOdbcDriver implements Driver{ + + private static final String URL_PREFIX = "jdbc:odbc:"; + + static{ + try{ + DriverManager.registerDriver(new JdbcOdbcDriver()); + }catch(SQLException ex){ + throw new ExceptionInInitializerError(ex); + } + } + + + /** + * {@inheritDoc} + */ + @Override + public boolean acceptsURL(String url){ + return url.startsWith(URL_PREFIX); + } + + + /** + * {@inheritDoc} + */ + @Override + public Connection connect(String url, Properties info) throws SQLException{ + if(!acceptsURL(url)){ + return null; + } + String connectString = url.substring(URL_PREFIX.length()); + return new JdbcOdbcConnection(connectString, info); + } + + + /** + * {@inheritDoc} + */ + @Override + public int getMajorVersion(){ + return 2; + } + + + /** + * {@inheritDoc} + */ + @Override + public int getMinorVersion(){ + return 1; + } + + + /** + * {@inheritDoc} + */ + @Override + public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException{ + return new DriverPropertyInfo[0]; + } + + + /** + * {@inheritDoc} + */ + @Override + public boolean jdbcCompliant(){ + return true; + } + + + /** + * {@inheritDoc} + */ + public Logger getParentLogger() throws SQLFeatureNotSupportedException { + throw new SQLFeatureNotSupportedException(); + } + +} diff --git a/openjdk/sun/jdbc/odbc/JdbcOdbcObject.java b/openjdk/sun/jdbc/odbc/JdbcOdbcObject.java new file mode 100644 index 0000000..32e9a40 --- /dev/null +++ b/openjdk/sun/jdbc/odbc/JdbcOdbcObject.java @@ -0,0 +1,650 @@ +/* + Copyright (C) 2009 Volker Berlin (i-net software) + Copyright (C) 2011 Karsten Heinrich (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.jdbc.odbc; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.Reader; +import java.io.StringReader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Date; +import java.sql.NClob; +import java.sql.Ref; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLXML; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Calendar; +import java.util.Map; + +import cli.System.Convert; +import cli.System.DBNull; +import cli.System.IConvertible; +import cli.System.Int16; +import cli.System.Int32; +import cli.System.Int64; +import cli.System.Single; + +/** + * @author Volker Berlin + */ +public abstract class JdbcOdbcObject{ + + private boolean wasNull; + + + /** + * Maps the given ResultSet column label to its ResultSet column index or the given CallableStatment parameter name + * to the parameter index. + * + * @param columnLabel + * the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, + * then the label is the name of the column + * @return the column index of the given column name + * @throws SQLException + * if the ResultSet object does not contain a column labeled columnLabel, a database access error occurs + * or this method is called on a closed result set + */ + public abstract int findColumn(String columnLabel) throws SQLException; + + + /** + * Read an Object from the current row store at the current row on the given column. + * + * @param columnIndex + * a JDBC column index starting with 1 + * @return a .NET Object, DBNull or null + * @throws SQLException + * if the result is closed or any other error occur. + */ + protected abstract Object getObjectImpl(int columnIndex) throws SQLException; + + + /** + * Read an Object from the current row store at the current row on the given column. Set the flag wasNull. + * + * @param columnIndex + * a JDBC column index starting with 1 + * @return a .NET Object or null + * @throws SQLException + * if the result is closed or any other error occur. + */ + private final Object getObjectSetWasNull(int columnIndex) throws SQLException{ + Object obj = getObjectImpl(columnIndex); + if(obj == null || obj == DBNull.Value){ + wasNull = true; + return null; + } + wasNull = false; + return obj; + } + + + public final Array getArray(int columnIndex){ + throw new UnsupportedOperationException(); + } + + + public final Array getArray(String columnLabel) throws SQLException{ + return getArray(findColumn(columnLabel)); + } + + + public final InputStream getAsciiStream(int columnIndex) throws SQLException{ + try{ + String str = getString(columnIndex); + if(str == null){ + return null; + } + return new ByteArrayInputStream(str.getBytes("Ascii")); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public final InputStream getAsciiStream(String columnLabel) throws SQLException{ + return getAsciiStream(findColumn(columnLabel)); + } + + + public final BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException{ + BigDecimal dec = getBigDecimal(columnIndex); + if(dec == null){ + return null; + } + if(dec.scale() != scale){ + return dec.setScale(scale, BigDecimal.ROUND_HALF_EVEN); + } + return dec; + } + + + public final BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException{ + return getBigDecimal(findColumn(columnLabel), scale); + } + + + public final BigDecimal getBigDecimal(int columnIndex) throws SQLException{ + try{ + Object obj = getObjectSetWasNull(columnIndex); + if(wasNull){ + return null; + } + String str = obj.toString(); + return new BigDecimal(str); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public final BigDecimal getBigDecimal(String columnLabel) throws SQLException{ + return getBigDecimal(findColumn(columnLabel)); + } + + + public final InputStream getBinaryStream(int columnIndex) throws SQLException{ + byte[] data = getBytes(columnIndex); + if(data == null){ + return null; + } + return new ByteArrayInputStream(data); + } + + + public final InputStream getBinaryStream(String columnLabel) throws SQLException{ + return getBinaryStream(findColumn(columnLabel)); + } + + + public final Blob getBlob(int columnIndex){ + throw new UnsupportedOperationException(); + } + + + public final Blob getBlob(String columnLabel) throws SQLException{ + return getBlob(findColumn(columnLabel)); + } + + + public final boolean getBoolean(int columnIndex) throws SQLException{ + try{ + Object obj = getObjectSetWasNull(columnIndex); + if(wasNull){ + return false; + } + if(obj instanceof IConvertible){ + return Convert.ToBoolean(obj); + } + String str = obj.toString(); + if(str.length() > 0){ + // special handling for boolean representation in old databases + char ch = str.charAt(0); + if(ch == 'T' || ch == 't'){ + return true; + } + if(ch == 'F' || ch == 'f'){ + return true; + } + } + return cli.System.Boolean.Parse(str); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public final boolean getBoolean(String columnLabel) throws SQLException{ + return getBoolean(findColumn(columnLabel)); + } + + + public final byte getByte(int columnIndex) throws SQLException{ + try{ + Object obj = getObjectSetWasNull(columnIndex); + if(wasNull){ + return 0; + } + if(obj instanceof IConvertible){ + return Convert.ToByte(obj); + } + String str = obj.toString(); + return cli.System.Byte.Parse(str); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public final byte getByte(String columnLabel) throws SQLException{ + return getByte(findColumn(columnLabel)); + } + + + public final byte[] getBytes(int columnIndex) throws SQLException{ + try{ + Object obj = getObjectSetWasNull(columnIndex); + if(wasNull){ + return null; + } + if(obj instanceof byte[]){ + return (byte[])obj; + } + String str = obj.toString(); + return str.getBytes(); // which encoding? + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public final byte[] getBytes(String columnLabel) throws SQLException{ + return getBytes(findColumn(columnLabel)); + } + + + public final Reader getCharacterStream(int columnIndex) throws SQLException{ + String str = getString(columnIndex); + if(str == null){ + return null; + } + return new StringReader(str); + } + + + public final Reader getCharacterStream(String columnLabel) throws SQLException{ + return getCharacterStream(findColumn(columnLabel)); + } + + + public final Clob getClob(int columnIndex){ + throw new UnsupportedOperationException(); + } + + + public final Clob getClob(String columnLabel) throws SQLException{ + return getClob(findColumn(columnLabel)); + } + + + public final Date getDate(int columnIndex) throws SQLException{ + try{ + Object obj = getObjectSetWasNull(columnIndex); + if(wasNull){ + return null; + } + if(obj instanceof cli.System.DateTime){ + cli.System.DateTime dt = (cli.System.DateTime)obj; + return new Date(dt.get_Year() - 1900, dt.get_Month() - 1, dt.get_Day()); + } + String str = obj.toString(); + return Date.valueOf(str); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public final Date getDate(String columnLabel) throws SQLException{ + return getDate(findColumn(columnLabel)); + } + + + public final Date getDate(int columnIndex, Calendar cal) throws SQLException{ + Date date = getDate(columnIndex); + JdbcOdbcUtils.convertLocalToCalendarDate(date, cal); + return date; + } + + + public final Date getDate(String columnLabel, Calendar cal) throws SQLException{ + return getDate(findColumn(columnLabel), cal); + } + + + public final double getDouble(int columnIndex) throws SQLException{ + try{ + Object obj = getObjectSetWasNull(columnIndex); + if(wasNull){ + return 0; + } + if(obj instanceof IConvertible){ + return Convert.ToDouble(obj); + } + String str = obj.toString(); + return cli.System.Double.Parse(str); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public final double getDouble(String columnLabel) throws SQLException{ + return getDouble(findColumn(columnLabel)); + } + + + public final float getFloat(int columnIndex) throws SQLException{ + try{ + Object obj = getObjectSetWasNull(columnIndex); + if(wasNull){ + return 0; + } + if(obj instanceof IConvertible){ + return Convert.ToSingle(obj); + } + String str = obj.toString(); + return Single.Parse(str); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public final float getFloat(String columnLabel) throws SQLException{ + return getFloat(findColumn(columnLabel)); + } + + + public final int getInt(int columnIndex) throws SQLException{ + try{ + Object obj = getObjectSetWasNull(columnIndex); + if(wasNull){ + return 0; + } + if(obj instanceof IConvertible){ + return Convert.ToInt32(obj); + } + String str = obj.toString(); + return Int32.Parse(str); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public final int getInt(String columnLabel) throws SQLException{ + return getInt(findColumn(columnLabel)); + } + + + public final long getLong(int columnIndex) throws SQLException{ + try{ + Object obj = getObjectSetWasNull(columnIndex); + if(wasNull){ + return 0; + } + if(obj instanceof IConvertible){ + return Convert.ToInt64(obj); + } + String str = obj.toString(); + return Int64.Parse(str); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public final long getLong(String columnLabel) throws SQLException{ + return getLong(findColumn(columnLabel)); + } + + + public final Reader getNCharacterStream(int columnIndex) throws SQLException{ + return getCharacterStream(columnIndex); + } + + + public final Reader getNCharacterStream(String columnLabel) throws SQLException{ + return getCharacterStream(columnLabel); + } + + + public final NClob getNClob(int columnIndex){ + throw new UnsupportedOperationException(); + } + + + public final NClob getNClob(String columnLabel) throws SQLException{ + return getNClob(findColumn(columnLabel)); + } + + + public final String getNString(int columnIndex) throws SQLException{ + return getString(columnIndex); + } + + + public final String getNString(String columnLabel) throws SQLException{ + return getString(columnLabel); + } + + + public final Object getObject(int columnIndex) throws SQLException{ + return JdbcOdbcUtils.convertNet2Java(getObjectSetWasNull(columnIndex)); + } + + + public final Object getObject(String columnLabel) throws SQLException{ + return getObject(findColumn(columnLabel)); + } + + + public final Object getObject(int columnIndex, Map> map){ + throw new UnsupportedOperationException(); + } + + + public final Object getObject(String columnLabel, Map> map) throws SQLException{ + return getObject(findColumn(columnLabel), map); + } + + + public final Ref getRef(int columnIndex){ + throw new UnsupportedOperationException(); + } + + + public final Ref getRef(String columnLabel) throws SQLException{ + return getRef(findColumn(columnLabel)); + } + + + public final RowId getRowId(int columnIndex){ + throw new UnsupportedOperationException(); + } + + + public final RowId getRowId(String columnLabel) throws SQLException{ + return getRowId(findColumn(columnLabel)); + } + + + public final SQLXML getSQLXML(int columnIndex){ + throw new UnsupportedOperationException(); + } + + + public final SQLXML getSQLXML(String columnLabel) throws SQLException{ + return getSQLXML(findColumn(columnLabel)); + } + + + public final short getShort(int columnIndex) throws SQLException{ + try{ + Object obj = getObjectSetWasNull(columnIndex); + if(wasNull){ + return 0; + } + if(obj instanceof IConvertible){ + return Convert.ToInt16(obj); + } + String str = obj.toString(); + return Int16.Parse(str); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public final short getShort(String columnLabel) throws SQLException{ + return getShort(findColumn(columnLabel)); + } + + + public final String getString(int columnIndex) throws SQLException{ + try{ + Object obj = getObjectSetWasNull(columnIndex); + if(wasNull){ + return null; + } + return obj.toString(); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public final String getString(String columnLabel) throws SQLException{ + return getString(findColumn(columnLabel)); + } + + + public final Time getTime(int columnIndex) throws SQLException{ + try{ + Object obj = getObjectSetWasNull(columnIndex); + if(wasNull){ + return null; + } + if(obj instanceof cli.System.DateTime){ + cli.System.DateTime dt = (cli.System.DateTime)obj; + return new Time(dt.get_Hour(), dt.get_Minute() - 1, dt.get_Second()); + } + if(obj instanceof cli.System.TimeSpan){ + cli.System.TimeSpan ts = (cli.System.TimeSpan)obj; + return new Time(ts.get_Hours(), ts.get_Minutes() - 1, ts.get_Seconds()); + } + String str = obj.toString(); + return Time.valueOf(str); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public final Time getTime(String columnLabel) throws SQLException{ + return getTime(findColumn(columnLabel)); + } + + + public final Time getTime(int columnIndex, Calendar cal) throws SQLException{ + Time time = getTime(columnIndex); + JdbcOdbcUtils.convertLocalToCalendarDate(time, cal); + return time; + } + + + public final Time getTime(String columnLabel, Calendar cal) throws SQLException{ + return getTime(findColumn(columnLabel), cal); + } + + + public final Timestamp getTimestamp(int columnIndex) throws SQLException{ + try{ + Object obj = getObjectSetWasNull(columnIndex); + if(wasNull){ + return null; + } + if(obj instanceof cli.System.DateTime){ + return JdbcOdbcUtils.convertDateTimeToTimestamp((cli.System.DateTime)obj); + } + String str = obj.toString(); + return Timestamp.valueOf(str); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public final Timestamp getTimestamp(String columnLabel) throws SQLException{ + return getTimestamp(findColumn(columnLabel)); + } + + + public final Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException{ + Timestamp ts = getTimestamp(columnIndex); + JdbcOdbcUtils.convertLocalToCalendarDate(ts, cal); + return ts; + } + + + public final Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException{ + return getTimestamp(findColumn(columnLabel), cal); + } + + + public final URL getURL(int columnIndex) throws SQLException{ + try{ + String url = getString(columnIndex); + if(wasNull){ + return null; + } + return new URL(url); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public final URL getURL(String columnLabel) throws SQLException{ + return getURL(findColumn(columnLabel)); + } + + + public final InputStream getUnicodeStream(int columnIndex) throws SQLException{ + try{ + return new ByteArrayInputStream(getString(columnIndex).getBytes("UTF16")); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public final InputStream getUnicodeStream(String columnLabel) throws SQLException{ + return getUnicodeStream(findColumn(columnLabel)); + } + + + public final boolean wasNull(){ + return wasNull; + } + +} diff --git a/openjdk/sun/jdbc/odbc/JdbcOdbcPreparedStatement.java b/openjdk/sun/jdbc/odbc/JdbcOdbcPreparedStatement.java new file mode 100644 index 0000000..93805fd --- /dev/null +++ b/openjdk/sun/jdbc/odbc/JdbcOdbcPreparedStatement.java @@ -0,0 +1,387 @@ +/* + Copyright (C) 2009 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.jdbc.odbc; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Date; +import java.sql.NClob; +import java.sql.ParameterMetaData; +import java.sql.PreparedStatement; +import java.sql.Ref; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLXML; +import java.sql.Time; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.Calendar; + +import cli.System.Data.*; +import cli.System.Data.Common.*; +import cli.System.Data.Odbc.*; + +/** + * @author Volker Berlin + */ +public class JdbcOdbcPreparedStatement extends JdbcOdbcStatement implements PreparedStatement{ + + public JdbcOdbcPreparedStatement(JdbcOdbcConnection jdbcConn, OdbcCommand command, String sql, int resultSetType, int resultSetConcurrency){ + super(jdbcConn, command, resultSetType, resultSetConcurrency); + command.set_CommandText(sql); + command.Prepare(); + } + + + public void addBatch() throws SQLException{ + // TODO Auto-generated method stub + + } + + + public void clearParameters(){ + DbParameterCollection params = command.get_Parameters(); + params.Clear(); + } + + + public boolean execute() throws SQLException{ + return super.execute(null); + } + + + public ResultSet executeQuery() throws SQLException{ + return super.executeQuery(null); + } + + + public int executeUpdate() throws SQLException{ + return super.executeUpdate(null); + } + + + public ResultSetMetaData getMetaData() throws SQLException{ + ResultSet rs = getResultSet(); + if(rs != null){ + rs.getMetaData(); + } + DbDataReader reader = command.ExecuteReader(CommandBehavior.wrap(CommandBehavior.SchemaOnly)); + JdbcOdbcResultSetMetaData metadata = new JdbcOdbcResultSetMetaData(reader); + reader.Close(); + return metadata; + } + + + public ParameterMetaData getParameterMetaData(){ + throw new UnsupportedOperationException(); + } + + + public void setArray(int parameterIndex, Array x) throws SQLException{ + setObject(parameterIndex, x, Types.ARRAY); + } + + + public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException{ + setObject(parameterIndex, x, Types.LONGVARCHAR); + } + + + public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException{ + setObject(parameterIndex, x, Types.LONGVARCHAR, length); + } + + + public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException{ + setObject(parameterIndex, x, Types.LONGVARCHAR, (int)length); + } + + + public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException{ + setObject(parameterIndex, x, Types.DECIMAL); + } + + + public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException{ + setObject(parameterIndex, x, Types.LONGVARBINARY); + } + + + public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException{ + setObject(parameterIndex, x, Types.LONGVARBINARY, length); + } + + + public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException{ + setObject(parameterIndex, x, Types.LONGVARBINARY, (int)length); + } + + + public void setBlob(int parameterIndex, Blob x) throws SQLException{ + setObject(parameterIndex, x, Types.BLOB); + } + + + public void setBlob(int parameterIndex, InputStream x) throws SQLException{ + setObject(parameterIndex, x, Types.BLOB); + } + + + public void setBlob(int parameterIndex, InputStream x, long length) throws SQLException{ + setObject(parameterIndex, x, Types.BLOB, (int)length); + } + + + public void setBoolean(int parameterIndex, boolean x) throws SQLException{ + setObject(parameterIndex, Boolean.valueOf(x), Types.BOOLEAN); + } + + + public void setByte(int parameterIndex, byte x) throws SQLException{ + setObject(parameterIndex, Byte.valueOf(x), Types.TINYINT); + } + + + public void setBytes(int parameterIndex, byte[] x) throws SQLException{ + setObject(parameterIndex, x, Types.BINARY); + } + + + public void setCharacterStream(int parameterIndex, Reader x) throws SQLException{ + setObject(parameterIndex, x, Types.LONGVARCHAR); + } + + + public void setCharacterStream(int parameterIndex, Reader x, int length) throws SQLException{ + setObject(parameterIndex, x, Types.NCLOB, length); + } + + + public void setCharacterStream(int parameterIndex, Reader x, long length) throws SQLException{ + setObject(parameterIndex, x, Types.LONGVARCHAR, (int)length); + } + + + public void setClob(int parameterIndex, Clob x) throws SQLException{ + setObject(parameterIndex, x, Types.CLOB); + } + + + public void setClob(int parameterIndex, Reader x) throws SQLException{ + setObject(parameterIndex, x, Types.CLOB); + } + + + public void setClob(int parameterIndex, Reader x, long length) throws SQLException{ + setObject(parameterIndex, x, Types.CLOB, (int)length); + } + + + public void setDate(int parameterIndex, Date x) throws SQLException{ + setObject(parameterIndex, x, Types.DATE); + } + + + public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException{ + JdbcOdbcUtils.convertCalendarToLocalDate(x, cal); + setObject(parameterIndex, x, Types.DATE); + } + + + public void setDouble(int parameterIndex, double x) throws SQLException{ + setObject(parameterIndex, Double.valueOf(x), Types.DOUBLE); + } + + + public void setFloat(int parameterIndex, float x) throws SQLException{ + setObject(parameterIndex, Float.valueOf(x), Types.FLOAT); + } + + + public void setInt(int parameterIndex, int x) throws SQLException{ + setObject(parameterIndex, Integer.valueOf(x), Types.INTEGER); + } + + + public void setLong(int parameterIndex, long x) throws SQLException{ + setObject(parameterIndex, Long.valueOf(x), Types.BIGINT); + } + + + public void setNCharacterStream(int parameterIndex, Reader x) throws SQLException{ + setObject(parameterIndex, x, Types.LONGNVARCHAR); + } + + + public void setNCharacterStream(int parameterIndex, Reader x, long length) throws SQLException{ + setObject(parameterIndex, x, Types.LONGNVARCHAR, (int)length); + } + + + public void setNClob(int parameterIndex, NClob x) throws SQLException{ + setObject(parameterIndex, x, Types.NCLOB); + } + + + public void setNClob(int parameterIndex, Reader x) throws SQLException{ + setObject(parameterIndex, x, Types.NCLOB); + } + + + public void setNClob(int parameterIndex, Reader x, long length) throws SQLException{ + setObject(parameterIndex, x, Types.NCLOB, (int)length); + } + + + public void setNString(int parameterIndex, String x) throws SQLException{ + setObject(parameterIndex, x, Types.NVARCHAR); + } + + + public void setNull(int parameterIndex, int sqlType) throws SQLException{ + setObject(parameterIndex, null, sqlType); + } + + + public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException{ + setObject(parameterIndex, null, sqlType); + } + + + public void setObject(int parameterIndex, Object x) throws SQLException{ + setObject(parameterIndex, x, Types.OTHER, -1); + } + + + public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException{ + setObject(parameterIndex, x, targetSqlType, -1); + } + + + public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException{ + DbParameter para = getPara(parameterIndex); + para.set_Value(JdbcOdbcUtils.convertJava2Net(x, scaleOrLength)); + if(para.get_Direction().Value == ParameterDirection.Output){ + para.set_Direction(ParameterDirection.wrap(ParameterDirection.InputOutput)); + } + + if(targetSqlType != Types.OTHER){ + para.set_DbType(DbType.wrap(JdbcOdbcUtils.convertJdbc2AdoNetType(targetSqlType))); + } + + if(scaleOrLength >= 0){ + switch(targetSqlType){ + case Types.DECIMAL: + case Types.NUMERIC: + para.set_Scale((byte)scaleOrLength); + } + } + } + + + public void setRef(int parameterIndex, Ref x) throws SQLException{ + setObject(parameterIndex, x, Types.REF); + } + + + public void setRowId(int parameterIndex, RowId x) throws SQLException{ + setObject(parameterIndex, x, Types.ROWID); + } + + + public void setSQLXML(int parameterIndex, SQLXML x) throws SQLException{ + setObject(parameterIndex, x, Types.SQLXML); + } + + + public void setShort(int parameterIndex, short x) throws SQLException{ + setObject(parameterIndex, Short.valueOf(x), Types.SMALLINT); + } + + + public void setString(int parameterIndex, String x) throws SQLException{ + setObject(parameterIndex, x, Types.VARCHAR); + } + + + public void setTime(int parameterIndex, Time x) throws SQLException{ + setObject(parameterIndex, x, Types.TIME); + } + + + public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException{ + JdbcOdbcUtils.convertCalendarToLocalDate(x, cal); + setObject(parameterIndex, x, Types.TIME); + } + + + public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException{ + setObject(parameterIndex, x, Types.TIMESTAMP); + } + + + public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException{ + JdbcOdbcUtils.convertCalendarToLocalDate(x, cal); + setObject(parameterIndex, x, Types.TIMESTAMP); + } + + + public void setURL(int parameterIndex, URL x) throws SQLException{ + setObject(parameterIndex, x, Types.DATALINK); + } + + + public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException{ + setObject(parameterIndex, x, Types.LONGNVARCHAR, length); + } + + + /** + * Get the DbParameter from the current command. If the parameter does not exits in the collection then add it. + * + * @param parameterIndex + * The JDBC parameter index starting with 1 + * @return the DbParameter for the index. + * @throws SQLException + * If any error occur. + */ + protected DbParameter getPara(int parameterIndex) throws SQLException{ + try{ + DbParameterCollection params = command.get_Parameters(); + while(params.get_Count() < parameterIndex){ + params.Add(command.CreateParameter()); + } + return params.get_Item(parameterIndex - 1); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } +} diff --git a/openjdk/sun/jdbc/odbc/JdbcOdbcResultSet.java b/openjdk/sun/jdbc/odbc/JdbcOdbcResultSet.java new file mode 100644 index 0000000..398f368 --- /dev/null +++ b/openjdk/sun/jdbc/odbc/JdbcOdbcResultSet.java @@ -0,0 +1,799 @@ +/* + Copyright (C) 2009, 2011 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.jdbc.odbc; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.sql.*; + +import cli.System.Data.Common.*; + +/** + * This JDBC Driver is a wrapper to the ODBC.NET Data Provider. This ResultSet based on a DataReader. + */ +public class JdbcOdbcResultSet extends JdbcOdbcObject implements ResultSet{ + + private DbDataReader reader; + + private final JdbcOdbcStatement statement; + + private final int holdability; + + private final int concurrency; + + private int fetchSize; + + private int row; + + private final int resultSetType; + + private ResultSetMetaData metaData; + + + /** + * Create a ResultSet that based on a DbDataReader + * + * @param statement + * the statement for getStatement(), can be null + * @param reader + * the reader for the data access, if it null then the resultset is closed. + */ + public JdbcOdbcResultSet(JdbcOdbcStatement statement, DbDataReader reader){ + this.statement = statement; + this.reader = reader; + this.resultSetType = TYPE_FORWARD_ONLY; + this.concurrency = CONCUR_READ_ONLY; + this.holdability = HOLD_CURSORS_OVER_COMMIT; + } + + + /** + * A constructor for extended classes. All methods that use the reader must be overridden if you use this + * constructor. + * + * @param statement + * the statement for getStatement(), can be null + * @param resultSetType + * a result set type; one of ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, or + * ResultSet.TYPE_SCROLL_SENSITIVE + * @param concurrency + * a concurrency type; one of ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE + */ + protected JdbcOdbcResultSet(JdbcOdbcStatement statement, int resultSetType, int concurrency){ + this.statement = statement; + this.reader = null; + this.resultSetType = resultSetType; + this.concurrency = concurrency; + this.holdability = HOLD_CURSORS_OVER_COMMIT; + } + + + public boolean absolute(int rowPosition) throws SQLException{ + throwForwardOnly(); + return false; // for Compiler + } + + + public void afterLast() throws SQLException{ + throwForwardOnly(); + } + + + public void beforeFirst() throws SQLException{ + throwForwardOnly(); + } + + + public void cancelRowUpdates() throws SQLException{ + throwReadOnly(); + } + + + public void clearWarnings() throws SQLException{ + // TODO Auto-generated method stub + + } + + + public void close(){ + reader = null; + statement.closeReaderIfPossible(); + } + + + public void deleteRow() throws SQLException{ + throwReadOnly(); + } + + + @Override + public int findColumn(String columnLabel) throws SQLException{ + try{ + return getReader().GetOrdinal(columnLabel) + 1; + }catch(ArrayIndexOutOfBoundsException ex){ + throw new SQLException("Column '" + columnLabel + "' not found.", "S0022", ex); + } + } + + + public boolean first() throws SQLException{ + throwForwardOnly(); + return false; // for compiler + } + + + public int getConcurrency(){ + return concurrency; + } + + + public String getCursorName() throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public int getFetchDirection(){ + return FETCH_UNKNOWN; + } + + + public int getFetchSize(){ + return fetchSize; + } + + + public int getHoldability(){ + return holdability; + } + + + public ResultSetMetaData getMetaData() throws SQLException{ + if(metaData == null){ + metaData = new JdbcOdbcResultSetMetaData(getReader()); + } + return metaData; + } + + + public int getRow() throws SQLException{ + getReader(); // checking for is closed + return row; + } + + + public Statement getStatement(){ + return statement; + } + + + public int getType(){ + return resultSetType; + } + + + public SQLWarning getWarnings() throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public void insertRow() throws SQLException{ + throwReadOnly(); + } + + + public boolean isAfterLast() throws SQLException{ + throwForwardOnly(); + return false; // only for compiler + } + + + public boolean isBeforeFirst() throws SQLException{ + throwForwardOnly(); + return false; // only for compiler + } + + + public boolean isClosed(){ + return reader == null; + } + + + public boolean isFirst() throws SQLException{ + throwForwardOnly(); + return false; // only for compiler + } + + + public boolean isLast() throws SQLException{ + throwForwardOnly(); + return false; // only for compiler + } + + + public boolean last() throws SQLException{ + throwForwardOnly(); + return false; // only for compiler + } + + + public void moveToCurrentRow() throws SQLException{ + throwReadOnly(); + } + + + public void moveToInsertRow() throws SQLException{ + throwReadOnly(); + } + + + public boolean next() throws SQLException{ + DbDataReader dataReader = getReader(); + //if we after the last row then we close the reader + //to prevent an error on repeating call of next() after the end + //that we check also get_IsClosed() + if(!dataReader.get_IsClosed() && dataReader.Read()){ + row++; + return true; + } + row = 0; + statement.closeReaderIfPossible(); + return false; + } + + + public boolean previous() throws SQLException{ + throwForwardOnly(); + return false; // only for compiler + } + + + public void refreshRow() throws SQLException{ + throwForwardOnly(); + } + + + public boolean relative(int rowPositions) throws SQLException{ + throwForwardOnly(); + return false; // only for compiler + } + + + public boolean rowDeleted() throws SQLException{ + throwReadOnly(); + return false; // only for compiler + } + + + public boolean rowInserted() throws SQLException{ + throwReadOnly(); + return false; // only for compiler + } + + + public boolean rowUpdated() throws SQLException{ + throwReadOnly(); + return false; // only for compiler + } + + + public void setFetchDirection(int direction){ + // ignore it + } + + + public void setFetchSize(int rows){ + // ignore it + } + + + public void updateArray(int columnIndex, Array x) throws SQLException{ + updateObject(columnIndex, x); + } + + + public void updateArray(String columnLabel, Array x) throws SQLException{ + updateArray(findColumn(columnLabel), x); + } + + + public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException{ + updateObject(columnIndex, x, length); + } + + + public void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException{ + updateObject(findColumn(columnLabel), x, length); + } + + + public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException{ + updateObject(columnIndex, x, (int)length); + } + + + public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException{ + updateObject(findColumn(columnLabel), x, (int)length); + } + + + public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException{ + updateObject(columnIndex, x); + } + + + public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException{ + updateObject(findColumn(columnLabel), x); + } + + + public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException{ + updateObject(columnIndex, x); + } + + + public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException{ + updateObject(findColumn(columnLabel), x); + } + + + public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException{ + updateObject(columnIndex, x, length); + } + + + public void updateBinaryStream(String columnLabel, InputStream x, int length) throws SQLException{ + updateObject(findColumn(columnLabel), x, length); + } + + + public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException{ + updateObject(columnIndex, x, (int)length); + } + + + public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException{ + updateObject(findColumn(columnLabel), x, (int)length); + } + + + public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException{ + updateObject(columnIndex, x); + } + + + public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException{ + updateObject(findColumn(columnLabel), x); + } + + + public void updateBlob(int columnIndex, Blob x) throws SQLException{ + updateObject(columnIndex, x); + } + + + public void updateBlob(String columnLabel, Blob x) throws SQLException{ + updateObject(findColumn(columnLabel), x); + } + + + public void updateBlob(int columnIndex, InputStream x, long length) throws SQLException{ + updateObject(columnIndex, x, (int)length); + } + + + public void updateBlob(String columnLabel, InputStream x, long length) throws SQLException{ + updateObject(findColumn(columnLabel), x, (int)length); + } + + + public void updateBlob(int columnIndex, InputStream x) throws SQLException{ + updateObject(columnIndex, x); + } + + + public void updateBlob(String columnLabel, InputStream x) throws SQLException{ + updateObject(findColumn(columnLabel), x); + } + + + public void updateBoolean(int columnIndex, boolean x) throws SQLException{ + updateObject(columnIndex, Boolean.valueOf(x)); + } + + + public void updateBoolean(String columnLabel, boolean x) throws SQLException{ + updateObject(findColumn(columnLabel), Boolean.valueOf(x)); + } + + + public void updateByte(int columnIndex, byte x) throws SQLException{ + updateObject(columnIndex, Byte.valueOf(x)); + } + + + public void updateByte(String columnLabel, byte x) throws SQLException{ + updateObject(findColumn(columnLabel), Byte.valueOf(x)); + } + + + public void updateBytes(int columnIndex, byte[] x) throws SQLException{ + updateObject(columnIndex, x); + } + + + public void updateBytes(String columnLabel, byte[] x) throws SQLException{ + updateObject(findColumn(columnLabel), x); + } + + + public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException{ + updateObject(columnIndex, x, length); + } + + + public void updateCharacterStream(String columnLabel, Reader x, int length) throws SQLException{ + updateObject(findColumn(columnLabel), x, length); + } + + + public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException{ + updateObject(columnIndex, x, (int)length); + } + + + public void updateCharacterStream(String columnLabel, Reader x, long length) throws SQLException{ + updateObject(findColumn(columnLabel), x, (int)length); + } + + + public void updateCharacterStream(int columnIndex, Reader x) throws SQLException{ + updateObject(columnIndex, x); + } + + + public void updateCharacterStream(String columnLabel, Reader x) throws SQLException{ + updateObject(findColumn(columnLabel), x); + } + + + public void updateClob(int columnIndex, Clob x) throws SQLException{ + updateObject(columnIndex, x); + } + + + public void updateClob(String columnLabel, Clob x) throws SQLException{ + updateObject(findColumn(columnLabel), x); + } + + + public void updateClob(int columnIndex, Reader x, long length) throws SQLException{ + updateObject(columnIndex, x, (int)length); + } + + + public void updateClob(String columnLabel, Reader x, long length) throws SQLException{ + updateObject(findColumn(columnLabel), x, (int)length); + } + + + public void updateClob(int columnIndex, Reader x) throws SQLException{ + updateObject(columnIndex, x); + } + + + public void updateClob(String columnLabel, Reader x) throws SQLException{ + updateObject(findColumn(columnLabel), x); + } + + + public void updateDate(int columnIndex, Date x) throws SQLException{ + updateObject(columnIndex, x); + } + + + public void updateDate(String columnLabel, Date x) throws SQLException{ + updateObject(findColumn(columnLabel), x); + } + + + public void updateDouble(int columnIndex, double x) throws SQLException{ + updateObject(columnIndex, Double.valueOf(x)); + } + + + public void updateDouble(String columnLabel, double x) throws SQLException{ + updateObject(findColumn(columnLabel), Double.valueOf(x)); + } + + + public void updateFloat(int columnIndex, float x) throws SQLException{ + updateObject(columnIndex, Float.valueOf(x)); + } + + + public void updateFloat(String columnLabel, float x) throws SQLException{ + updateObject(findColumn(columnLabel), Float.valueOf(x)); + } + + + public void updateInt(int columnIndex, int x) throws SQLException{ + updateObject(columnIndex, Integer.valueOf(x)); + } + + + public void updateInt(String columnLabel, int x) throws SQLException{ + updateObject(findColumn(columnLabel), Integer.valueOf(x)); + } + + + public void updateLong(int columnIndex, long x) throws SQLException{ + updateObject(columnIndex, Long.valueOf(x)); + } + + + public void updateLong(String columnLabel, long x) throws SQLException{ + updateObject(findColumn(columnLabel), Long.valueOf(x)); + } + + + public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException{ + updateObject(columnIndex, x, (int)length); + } + + + public void updateNCharacterStream(String columnLabel, Reader x, long length) throws SQLException{ + updateObject(findColumn(columnLabel), x, (int)length); + } + + + public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException{ + updateObject(columnIndex, x); + } + + + public void updateNCharacterStream(String columnLabel, Reader x) throws SQLException{ + updateObject(findColumn(columnLabel), x); + } + + + public void updateNClob(int columnIndex, NClob x) throws SQLException{ + updateObject(columnIndex, x); + } + + + public void updateNClob(String columnLabel, NClob x) throws SQLException{ + updateObject(findColumn(columnLabel), x); + } + + + public void updateNClob(int columnIndex, Reader x, long length) throws SQLException{ + updateObject(columnIndex, x, (int)length); + } + + + public void updateNClob(String columnLabel, Reader x, long length) throws SQLException{ + updateObject(findColumn(columnLabel), x, (int)length); + } + + + public void updateNClob(int columnIndex, Reader x) throws SQLException{ + updateObject(columnIndex, x); + } + + + public void updateNClob(String columnLabel, Reader x) throws SQLException{ + updateObject(findColumn(columnLabel), x); + } + + + public void updateNString(int columnIndex, String x) throws SQLException{ + updateObject(columnIndex, x); + } + + + public void updateNString(String columnLabel, String x) throws SQLException{ + updateObject(findColumn(columnLabel), x); + } + + + public void updateNull(int columnIndex) throws SQLException{ + updateObject(columnIndex, null); + } + + + public void updateNull(String columnLabel) throws SQLException{ + updateObject(findColumn(columnLabel), null); + } + + + public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException{ + throwReadOnly(); + } + + + public void updateObject(int columnIndex, Object x) throws SQLException{ + updateObject(columnIndex, x, -1); + } + + + public void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException{ + updateObject(findColumn(columnLabel), x, scaleOrLength); + } + + + public void updateObject(String columnLabel, Object x) throws SQLException{ + updateObject(findColumn(columnLabel), x); + } + + + public void updateRef(int columnIndex, Ref x) throws SQLException{ + updateObject(columnIndex, x); + } + + + public void updateRef(String columnLabel, Ref x) throws SQLException{ + updateObject(findColumn(columnLabel), x); + } + + + public void updateRow() throws SQLException{ + throwReadOnly(); + } + + + public void updateRowId(int columnIndex, RowId x) throws SQLException{ + updateObject(columnIndex, x); + } + + + public void updateRowId(String columnLabel, RowId x) throws SQLException{ + updateObject(findColumn(columnLabel), x); + } + + + public void updateSQLXML(int columnIndex, SQLXML x) throws SQLException{ + updateObject(columnIndex, x); + } + + + public void updateSQLXML(String columnLabel, SQLXML x) throws SQLException{ + updateObject(findColumn(columnLabel), x); + } + + + public void updateShort(int columnIndex, short x) throws SQLException{ + updateObject(columnIndex, Short.valueOf(x)); + } + + + public void updateShort(String columnLabel, short x) throws SQLException{ + updateObject(findColumn(columnLabel), Short.valueOf(x)); + } + + + public void updateString(int columnIndex, String x) throws SQLException{ + updateObject(columnIndex, x); + } + + + public void updateString(String columnLabel, String x) throws SQLException{ + updateObject(findColumn(columnLabel), x); + } + + + public void updateTime(int columnIndex, Time x) throws SQLException{ + updateObject(columnIndex, x); + } + + + public void updateTime(String columnLabel, Time x) throws SQLException{ + updateObject(findColumn(columnLabel), x); + } + + + public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException{ + updateObject(columnIndex, x); + } + + + public void updateTimestamp(String columnLabel, Timestamp x) throws SQLException{ + updateObject(findColumn(columnLabel), x); + } + + + public boolean isWrapperFor(Class iface){ + return iface.isAssignableFrom(this.getClass()); + } + + + public T unwrap(Class iface) throws SQLException{ + if(isWrapperFor(iface)){ + return (T)this; + } + throw new SQLException(this.getClass().getName() + " does not implements " + iface.getName() + ".", "01000"); + } + + + private void throwForwardOnly() throws SQLException{ + throw new SQLException("ResultSet is forward only.", "24000"); + } + + + private void throwReadOnly() throws SQLException{ + throw new SQLException("ResultSet is read only.", "24000"); + } + + + /** + * Check if this ResultSet is closed before access to the DbDataReader + * + * @return + * @throws SQLException + */ + private DbDataReader getReader() throws SQLException{ + if(reader == null){ + throw new SQLException("ResultSet is closed.", "24000"); + } + return reader; + } + + + /** + * {@inheritDoc} + */ + @Override + protected Object getObjectImpl(int columnIndex) throws SQLException{ + try{ + DbDataReader datareader = getReader(); + try{ + return datareader.get_Item(columnIndex-1); + }catch(ArrayIndexOutOfBoundsException aioobe){ + throw new SQLException( "Invalid column number ("+columnIndex+"). A number between 1 and "+datareader.get_FieldCount()+" is valid.", "S1002", aioobe); + } + }catch(Throwable ex){ + throw JdbcOdbcUtils.createSQLException(ex); + } + } + + + /** + * {@inheritDoc} + */ + public T getObject(int columnIndex, Class type) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + + /** + * {@inheritDoc} + */ + public T getObject(String columnLabel, Class type) + throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + +} diff --git a/openjdk/sun/jdbc/odbc/JdbcOdbcResultSetMetaData.java b/openjdk/sun/jdbc/odbc/JdbcOdbcResultSetMetaData.java new file mode 100644 index 0000000..a92fdaf --- /dev/null +++ b/openjdk/sun/jdbc/odbc/JdbcOdbcResultSetMetaData.java @@ -0,0 +1,269 @@ +/* + Copyright (C) 2009 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.jdbc.odbc; + +import ikvm.lang.CIL; + +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Types; + +import cli.System.Convert; +import cli.System.DBNull; +import cli.System.Data.*; +import cli.System.Data.Common.*; +import cli.System.Data.Odbc.OdbcType; + +/** + * This JDBC Driver is a wrapper to the ODBC.NET Data Provider. + */ +public class JdbcOdbcResultSetMetaData implements ResultSetMetaData{ + + private final DbDataReader reader; + + private final DataTable schema; + + JdbcOdbcResultSetMetaData(DbDataReader reader){ + this.reader = reader; + schema = reader.GetSchemaTable(); + } + + public String getCatalogName(int column) throws SQLException{ + Object obj = getColumnMeta(column, "BaseCatalogName"); + if(obj == null || obj == DBNull.Value){ + return ""; + } + return obj.toString(); + } + + + public String getColumnClassName(int column) throws SQLException{ + String type = getColumnMeta(column, "DataType").toString(); + return JdbcOdbcUtils.getJavaClassName(type); + } + + + public int getColumnCount(){ + return schema.get_Rows().get_Count(); + } + + + public int getColumnDisplaySize(int column) throws SQLException{ + int precision = getPrecision(column); + int type = CIL.unbox_int( getColumnMeta(column, "ProviderType") ); + switch(type){ + case OdbcType.Decimal: + case OdbcType.Numeric: + return precision + (getScale(column) > 0 ? 2 : 1); // + sign and comma + } + return precision; + } + + + public String getColumnLabel(int column) throws SQLException{ + return getColumnMeta(column, "ColumnName").toString(); + } + + + public String getColumnName(int column) throws SQLException{ + return getColumnMeta(column, "ColumnName").toString(); + } + + + public int getColumnType(int column) throws SQLException{ + int type = CIL.unbox_int( getColumnMeta(column, "ProviderType") ); + switch(type){ + case OdbcType.VarChar: + return Types.VARCHAR; + case OdbcType.Char: + return Types.CHAR; + case OdbcType.Binary: + case OdbcType.Timestamp: + return Types.BINARY; + case OdbcType.Bit: + return Types.BOOLEAN; + case OdbcType.TinyInt: + return Types.TINYINT; + case OdbcType.Date: + return Types.DATE; + case OdbcType.DateTime: + case OdbcType.SmallDateTime: + return Types.TIMESTAMP; + case OdbcType.Decimal: + return Types.DECIMAL; + case OdbcType.Double: + return Types.DOUBLE; + case OdbcType.UniqueIdentifier: + return Types.ROWID; + case OdbcType.SmallInt: + return Types.SMALLINT; + case OdbcType.Int: + return Types.INTEGER; + case OdbcType.BigInt: + return Types.BIGINT; + case OdbcType.Real: + return Types.FLOAT; + case OdbcType.NVarChar: + return Types.NVARCHAR; + case OdbcType.NChar: + return Types.NCHAR; + case OdbcType.NText: + return Types.LONGNVARCHAR; + case OdbcType.Text: + return Types.LONGVARCHAR; + case OdbcType.Image: + return Types.LONGVARBINARY; + case OdbcType.Time: + return Types.TIME; + case OdbcType.Numeric: + return Types.NUMERIC; + case OdbcType.VarBinary: + return Types.VARBINARY; + } + return Types.OTHER; + } + + + public String getColumnTypeName(int column) throws SQLException{ + try{ + return reader.GetDataTypeName(column - 1); + }catch(ArrayIndexOutOfBoundsException ex){ + throw new SQLException("Invalid column number ("+column+"). A number between 1 and "+schema.get_Rows().get_Count()+" is valid.", "S1002"); + }catch(Throwable ex){ + throw JdbcOdbcUtils.createSQLException(ex); + } + } + + + public int getPrecision(int column) throws SQLException{ + Object obj = getColumnMeta(column, "NumericPrecision"); + return Convert.ToInt32(obj); + } + + + public int getScale(int column) throws SQLException{ + Object obj = getColumnMeta(column, "NumericScale"); + return Convert.ToInt32(obj); + } + + + public String getSchemaName(int column) throws SQLException{ + Object obj = getColumnMeta(column, "BaseSchemaName"); + if(obj == null || obj == DBNull.Value){ + return ""; + } + return obj.toString(); + } + + + public String getTableName(int column) throws SQLException{ + Object obj = getColumnMeta(column, "BaseTableName"); + if(obj == null || obj == DBNull.Value){ + return ""; + } + return obj.toString(); + } + + + public boolean isAutoIncrement(int column) throws SQLException{ + Object obj = getColumnMeta(column, "IsAutoIncrement"); + return Convert.ToBoolean(obj); + } + + + public boolean isCaseSensitive(int column){ + return false; + } + + + public boolean isCurrency(int column) throws SQLException{ + return CIL.unbox_int( getColumnMeta(column, "ProviderType") ) == OdbcType.Decimal && getScale(column) == 4; + } + + + public boolean isDefinitelyWritable(int column){ + return false; + } + + + public int isNullable(int column) throws SQLException{ + Object obj = getColumnMeta(column, "AllowDBNull"); + return Convert.ToBoolean(obj) ? columnNullable : columnNoNulls; + } + + + public boolean isReadOnly(int column) throws SQLException{ + Object obj = getColumnMeta(column, "IsReadOnly"); + return Convert.ToBoolean(obj); + } + + + public boolean isSearchable(int column) throws SQLException{ + return !CIL.unbox_boolean( getColumnMeta(column, "IsLong") ); + } + + + public boolean isSigned(int column) throws SQLException{ + int type = CIL.unbox_int( getColumnMeta(column, "ProviderType") ); + switch(type){ + case OdbcType.Numeric: + case OdbcType.Decimal: + case OdbcType.Double: + case OdbcType.SmallInt: + case OdbcType.Int: + case OdbcType.BigInt: + case OdbcType.Real: + return true; + } + return false; + } + + + public boolean isWritable(int column) throws SQLException{ + Object obj = getColumnMeta(column, "IsReadOnly"); + return !Convert.ToBoolean(obj); + } + + + public boolean isWrapperFor(Class iface){ + return iface.isAssignableFrom(this.getClass()); + } + + + public T unwrap(Class iface) throws SQLException{ + if(isWrapperFor(iface)){ + return (T)this; + } + throw new SQLException(this.getClass().getName() + " does not implements " + iface.getName() + ".", "01000"); + } + + private Object getColumnMeta(int column, String metaKey) throws SQLException{ + try{ + DataRow columnMeta = schema.get_Rows().get_Item(column-1); + return columnMeta.get_Item(metaKey); + }catch(ArrayIndexOutOfBoundsException ex){ + throw new SQLException("Invalid column number ("+column+"). A number between 1 and "+schema.get_Rows().get_Count()+" is valid.", "S1002"); + } + } +} diff --git a/openjdk/sun/jdbc/odbc/JdbcOdbcStatement.java b/openjdk/sun/jdbc/odbc/JdbcOdbcStatement.java new file mode 100644 index 0000000..358ae0e --- /dev/null +++ b/openjdk/sun/jdbc/odbc/JdbcOdbcStatement.java @@ -0,0 +1,386 @@ +/* + Copyright (C) 2009, 2011 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.jdbc.odbc; + +import java.sql.*; + +import cli.System.Data.*; +import cli.System.Data.Common.*; +import cli.System.Data.Odbc.*; + +/** + * This JDBC Driver is a wrapper to the ODBC.NET Data Provider. + */ +public class JdbcOdbcStatement implements Statement{ + + private final JdbcOdbcConnection jdbcConn; + + protected final OdbcCommand command; + + private final int resultSetType; + + private final int resultSetConcurrency; + + private DbDataReader reader; + + private ResultSet rs; + + private int updateCount; + + private boolean isClosed; + + private ResultSet moreResults; + + public JdbcOdbcStatement(JdbcOdbcConnection jdbcConn, OdbcCommand command, int resultSetType, int resultSetConcurrency){ + this.jdbcConn = jdbcConn; + this.command = command; + this.resultSetType = resultSetType; + this.resultSetConcurrency = resultSetConcurrency; + } + + + public void addBatch(String sql) throws SQLException{ + // TODO Auto-generated method stub + + } + + + public void cancel() throws SQLException{ + try{ + command.Cancel(); + }catch(Throwable ex){ + throw JdbcOdbcUtils.createSQLException(ex); + } + } + + + public void clearBatch() throws SQLException{ + // TODO Auto-generated method stub + + } + + + public void clearWarnings() throws SQLException{ + // TODO Auto-generated method stub + + } + + + public void close() throws SQLException{ + isClosed = true; + if(rs != null){ + rs.close(); + } + if(reader != null){ + reader.Close(); + } + command.Dispose(); + } + + + public boolean execute(String sql) throws SQLException{ + try{ + if(sql != null){ + command.set_CommandText(sql); + } + command.ExecuteNonQuery(); + return false; + }catch(Throwable ex){ + throw JdbcOdbcUtils.createSQLException(ex); + } + } + + + public boolean execute(String sql, int autoGeneratedKeys){ + throw new UnsupportedOperationException(); + } + + + public boolean execute(String sql, int[] columnIndexes){ + throw new UnsupportedOperationException(); + } + + + public boolean execute(String sql, String[] columnNames){ + throw new UnsupportedOperationException(); + } + + + public int[] executeBatch() throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public ResultSet executeQuery(String sql) throws SQLException{ + try{ + if(sql != null){ + command.set_CommandText(sql); + } + if(resultSetConcurrency == ResultSet.CONCUR_UPDATABLE){ + rs = new JdbcOdbcUpdateableResultSet(command); + }else{ + if(resultSetType == ResultSet.TYPE_FORWARD_ONLY){ + reader = command.ExecuteReader(); + rs = new JdbcOdbcResultSet(this, reader); + }else{ + OdbcDataAdapter da = new OdbcDataAdapter(command); + DataTable dt = new DataTable(); + da.Fill(dt); + rs = new JdbcOdbcDTResultSet(dt); + } + } + return rs; + }catch(Throwable ex){ + throw JdbcOdbcUtils.createSQLException(ex); + } + } + + + public int executeUpdate(String sql) throws SQLException{ + try{ + if(sql != null){ + command.set_CommandText(sql); + } + updateCount = command.ExecuteNonQuery(); + return updateCount; + }catch(Throwable ex){ + throw JdbcOdbcUtils.createSQLException(ex); + } + } + + + public int executeUpdate(String sql, int autoGeneratedKeys){ + throw new UnsupportedOperationException(); + } + + + public int executeUpdate(String sql, int[] columnIndexes){ + throw new UnsupportedOperationException(); + } + + + public int executeUpdate(String sql, String[] columnNames){ + throw new UnsupportedOperationException(); + } + + + public Connection getConnection(){ + return jdbcConn; + } + + + public int getFetchDirection(){ + return ResultSet.FETCH_UNKNOWN; + } + + + public int getFetchSize(){ + return 0; + } + + + public ResultSet getGeneratedKeys(){ + throw new UnsupportedOperationException(); + } + + + public int getMaxFieldSize() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public int getMaxRows() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public boolean getMoreResults() throws SQLException{ + try{ + if(moreResults != null){ + rs = moreResults; + moreResults = null; + return true; + } + boolean isNext = reader.NextResult(); + if(isNext){ + rs = new JdbcOdbcResultSet(this, reader); + return true; + } + rs = null; + return false; + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + public boolean getMoreResults(int current) throws SQLException{ + // TODO Auto-generated method stub + return false; + } + + + public int getQueryTimeout(){ + return command.get_CommandTimeout(); + } + + + public ResultSet getResultSet(){ + return rs; + } + + + public int getResultSetConcurrency(){ + return resultSetConcurrency; + } + + + public int getResultSetHoldability() throws SQLException{ + // TODO Auto-generated method stub + return 0; + } + + + public int getResultSetType(){ + return resultSetType; + } + + + public int getUpdateCount(){ + return updateCount; + } + + + public SQLWarning getWarnings() throws SQLException{ + // TODO Auto-generated method stub + return null; + } + + + public boolean isClosed(){ + return isClosed; + } + + + public void setCursorName(String name) throws SQLException{ + // TODO Auto-generated method stub + + } + + + public void setEscapeProcessing(boolean enable) throws SQLException{ + // TODO Auto-generated method stub + + } + + + public void setFetchDirection(int direction){ + // ignore it + } + + + public void setFetchSize(int rows){ + // ignore it + } + + + public void setMaxFieldSize(int max) throws SQLException{ + // TODO Auto-generated method stub + + } + + + public void setMaxRows(int max) throws SQLException{ + // TODO Auto-generated method stub + + } + + + public boolean isPoolable(){ + return false; + } + + + public void setPoolable(boolean poolable) throws SQLException{ + // ignore it + } + + + public void setQueryTimeout(int seconds){ + command.set_CommandTimeout(seconds); + } + + + public boolean isWrapperFor(Class iface){ + return iface.isAssignableFrom(this.getClass()); + } + + + public T unwrap(Class iface) throws SQLException{ + if(isWrapperFor(iface)){ + return (T)this; + } + throw new SQLException(this.getClass().getName() + " does not implements " + iface.getName() + ".", "01000"); + } + + /** + * Close the DbDataReader if there are no more results. + * This give some blocking free without calling close() explicit. + * If there are more results then we need to save it. + */ + void closeReaderIfPossible(){ + ResultSet currentRs = rs; + boolean isMoreResults; + try{ + isMoreResults = getMoreResults(); + }catch(SQLException ex){ + isMoreResults = false; + } + if(!isMoreResults){ + reader.Close(); //this give the ODBC cursor free + }else{ + moreResults = rs; + } + rs = currentRs; + } + + + /** + * {@inheritDoc} + */ + public void closeOnCompletion() throws SQLException { + } + + + /** + * {@inheritDoc} + */ + public boolean isCloseOnCompletion() throws SQLException { + return false; + } + +} diff --git a/openjdk/sun/jdbc/odbc/JdbcOdbcUpdateableResultSet.java b/openjdk/sun/jdbc/odbc/JdbcOdbcUpdateableResultSet.java new file mode 100644 index 0000000..a3ce0ff --- /dev/null +++ b/openjdk/sun/jdbc/odbc/JdbcOdbcUpdateableResultSet.java @@ -0,0 +1,165 @@ +/* + Copyright (C) 2009 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.jdbc.odbc; + +import java.sql.*; + +import cli.System.Data.*; +import cli.System.Data.Odbc.*; + +/** + * @author Volker Berlin + */ +public class JdbcOdbcUpdateableResultSet extends JdbcOdbcDTResultSet{ + + private final OdbcDataAdapter da; + + private final DataTable data; + + private DataRow insertRow; + + + public JdbcOdbcUpdateableResultSet(OdbcCommand cmd){ + this(new DataTable(), cmd); + } + + + private JdbcOdbcUpdateableResultSet(DataTable data, OdbcCommand cmd){ + super(data, CONCUR_UPDATABLE); + this.data = data; + da = new OdbcDataAdapter(cmd); + da.Fill(data); + OdbcCommandBuilder cmdBldr = new OdbcCommandBuilder(da); + cmdBldr.GetUpdateCommand(); // throw an exception if update is not possible, we want a very early exception + } + + + @Override + protected DataRow getDataRow() throws SQLException{ + if(insertRow != null){ + return insertRow; + } + return super.getDataRow(); + } + + + @Override + protected void setDataRow() throws SQLException{ + insertRow = null; + super.setDataRow(); + } + + + @Override + public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException{ + try{ + x = JdbcOdbcUtils.convertJava2Net(x, scaleOrLength); + getDataRow().set_Item(columnIndex - 1, x); + }catch(ArrayIndexOutOfBoundsException ex){ + throw new SQLException("Invalid column number (" + columnIndex + "). A number between 1 and " + + data.get_Columns().get_Count() + " is valid.", "S1002", ex); + } + } + + + @Override + public void updateRow() throws SQLException{ + if(insertRow != null){ + throw new SQLException("Cursor is on the insert row."); + } + try{ + da.Update(data); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + @Override + public void deleteRow() throws SQLException{ + if(insertRow != null){ + throw new SQLException("Cursor is on the insert row."); + } + try{ + getDataRow().Delete(); // Delete the current row + da.Update(data); + setDataRow(); // set a new Current Row + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + } + + + @Override + public void insertRow() throws SQLException{ + if(insertRow == null){ + throw new SQLException("Cursor is not on the insert row."); + } + try{ + getRows().Add(insertRow); + insertRow = null; + da.Update(data); + last(); + }catch(Throwable th){ + throw JdbcOdbcUtils.createSQLException(th); + } + + } + + + @Override + public void moveToInsertRow(){ + insertRow = data.NewRow(); + } + + + @Override + public void moveToCurrentRow(){ + insertRow = null; + } + + + @Override + public void cancelRowUpdates() throws SQLException{ + getDataRow().CancelEdit(); + } + + + @Override + public boolean rowDeleted(){ + return false; + } + + + @Override + public boolean rowInserted(){ + return false; + } + + + @Override + public boolean rowUpdated(){ + return false; + } +} diff --git a/openjdk/sun/jdbc/odbc/JdbcOdbcUtils.java b/openjdk/sun/jdbc/odbc/JdbcOdbcUtils.java new file mode 100644 index 0000000..c5497e3 --- /dev/null +++ b/openjdk/sun/jdbc/odbc/JdbcOdbcUtils.java @@ -0,0 +1,372 @@ +/* + Copyright (C) 2009, 2010 Volker Berlin (i-net software) + Copyright (C) 2011 Karsten Heinrich (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.jdbc.odbc; + +import ikvm.lang.CIL; + +import java.math.BigDecimal; +import java.sql.*; +import java.util.Calendar; +import java.util.HashMap; + +import cli.System.DBNull; +import cli.System.TimeSpan; +import cli.System.Data.DbType; +import cli.System.Data.Common.DbException; +import cli.System.Data.Odbc.*; +import cli.System.Globalization.CultureInfo; + +/** + * @author Volker Berlin + */ +public class JdbcOdbcUtils{ + + private static final HashMap classNameMap = new HashMap(); + static{ + classNameMap.put("System.String", "java.lang.String"); + classNameMap.put("System.Int16", "java.lang.Short"); + classNameMap.put("System.Int32", "java.lang.Integer"); + classNameMap.put("System.Int64", "java.lang.Long"); + classNameMap.put("System.Double", "java.lang.Double"); + classNameMap.put("System.Decimal", "java.math.BigDecimal"); + classNameMap.put("System.DateTime", "java.sql.Timestamp"); + classNameMap.put("System.TimeSpan", "java.sql.Time"); + } + + + /** + * Solve a mapping between .NET class names and the equivalent Java class names for + * ResultSetMetaData.getColumnClassName + * + * @param netClassName + * the .NET class name + * @return the Java class name + */ + public static String getJavaClassName(String netClassName){ + String javaClassName = classNameMap.get(netClassName); + if(javaClassName != null){ + return javaClassName; + } + return "java.lang.Object"; + } + + + /** + * Convert a .NET Object in the equals Java Object. + * + * @param obj + * the .NET Object + * @return a Java Object + */ + public static java.lang.Object convertNet2Java(java.lang.Object obj){ + if(obj instanceof cli.System.Int64){ + return Long.valueOf(CIL.unbox_long(obj)); + } + if(obj instanceof cli.System.Int32){ + return Integer.valueOf(CIL.unbox_int(obj)); + } + if(obj instanceof cli.System.Int16){ + return Short.valueOf(CIL.unbox_short(obj)); + } + if(obj instanceof cli.System.Byte){ + return Byte.valueOf(CIL.unbox_byte(obj)); + } + if(obj instanceof cli.System.Double){ + return Double.valueOf(CIL.unbox_double(obj)); + } + if(obj instanceof cli.System.Single){ + return Float.valueOf(CIL.unbox_float(obj)); + } + if(obj instanceof cli.System.Boolean){ + return Boolean.valueOf(CIL.unbox_boolean(obj)); + } + if(obj instanceof cli.System.Decimal){ + return new BigDecimal(((cli.System.Decimal)obj).ToString(CultureInfo.get_InvariantCulture())); + } + if(obj instanceof cli.System.DateTime){ + return convertDateTimeToTimestamp((cli.System.DateTime)obj); + } + if(obj instanceof cli.System.TimeSpan){ + cli.System.TimeSpan ts = (cli.System.TimeSpan)obj; + return new Time(ts.get_Hours(), ts.get_Minutes(), ts.get_Seconds()); + } + if(obj instanceof cli.System.DBNull){ + return null; + } + return obj; + } + + /** + * Converts a .NET DateTime to a Timestamp in the current Timezone + * @param obj the dateTime + * @return the conveted time stamp + */ + public static Timestamp convertDateTimeToTimestamp( cli.System.DateTime obj) { + long javaMillis = getJavaMillis(obj); + int seconds = (int)(javaMillis / 1000); + int nanos = (int)((javaMillis % 1000) * 1000000); + return new Timestamp( 70, 0, 1, 0, 0, seconds, nanos ); + } + + + /** + * Convert a Java Object in the equals .NET Object. + * + * @param obj + * Java Object + * @param length + * the length of data if obj is a stream + * @return .NET Object + */ + public static Object convertJava2Net(Object obj, int length){ + // TODO use the length with streams + return convertJava2Net(obj); + } + + + /** + * Convert a Java Object in the equals .NET Object. + * + * @param obj + * Java Object + * @return a .NET Object + */ + public static Object convertJava2Net(Object obj){ + if(obj == null){ + return DBNull.Value; + } + if(obj instanceof Double){ + return CIL.box_double(((Double)obj).doubleValue()); + } + if(obj instanceof Float){ + return CIL.box_float(((Float)obj).floatValue()); + } + if(obj instanceof Long){ + return CIL.box_long(((Long)obj).longValue()); + } + if(obj instanceof Integer){ + return CIL.box_int(((Integer)obj).intValue()); + } + if(obj instanceof Short){ + return CIL.box_short(((Short)obj).shortValue()); + } + if(obj instanceof Byte){ + return CIL.box_byte(((Byte)obj).byteValue()); + } + if(obj instanceof Boolean){ + return CIL.box_boolean(((Boolean)obj).booleanValue()); + } + if(obj instanceof Time){ + Time ts = (Time)obj; + return new TimeSpan(ts.getHours(), ts.getMinutes(), ts.getSeconds()); + } + if(obj instanceof java.util.Date){ + long ticks = getNetTicks((java.util.Date)obj); + return new cli.System.DateTime(ticks); + } + if(obj instanceof BigDecimal){ + return cli.System.Decimal.Parse(obj.toString(), CultureInfo.get_InvariantCulture()); + } + return obj; + } + + + /** + * Get the milliseconds in the Java range from a .NET DateTime object. + * + * @param dt + * the DateTime object + * @return the milliseconds since 1970-01-01 + */ + public static long getJavaMillis(cli.System.DateTime dt){ + // calculation copied from System.currentTimeMillis() + long january_1st_1970 = 62135596800000L; + return dt.get_Ticks() / 10000L - january_1st_1970; + } + + + /** + * Get the ticks for a System.DateTime from a java.util.Date + * + * @param date + * the java.util.Date + * @return ticks + */ + public static long getNetTicks(java.util.Date date){ + // inverse from getJavaMillis + long january_1st_1970 = 62135596800000L; + return (date.getTime() + january_1st_1970) * 10000L; + } + + + /** + * Convert a local (current default) Date to a Date in the time zone of the given calendar. Do nothing if date or + * calendar is null. + * + * @param date + * the converting Date + * @param cal + * the Calendar with the time zone + */ + public static void convertLocalToCalendarDate(java.util.Date date, Calendar cal){ + if(date == null || cal == null){ + return; + } + cal.set(date.getYear() + 1900, date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date + .getSeconds()); + long millis = cal.getTimeInMillis() / 1000 * 1000 + date.getTime() % 1000; + date.setTime(millis); + } + + + /** + * Convert a Date in the calendar time zone to a date in the local (current default) time zone. Do nothing if date + * or calendar is null. + * + * @param date + * @param cal + */ + public static void convertCalendarToLocalDate(java.util.Date date, Calendar cal){ + if(date == null || cal == null){ + return; + } + cal.setTimeInMillis(date.getTime()); + date.setYear(cal.get(Calendar.YEAR) - 1900); + date.setMonth(cal.get(Calendar.MONTH)); + date.setDate(cal.get(Calendar.DAY_OF_MONTH)); + date.setHours(cal.get(Calendar.HOUR_OF_DAY)); + date.setMinutes(cal.get(Calendar.MINUTE)); + date.setSeconds(cal.get(Calendar.SECOND)); + } + + + /** + * The only valid Exception for JDBC is a SQLException. Here we create one based on the real exception. + * + * @param th + * any Throwable that occur + * @return a SQLException, never null + */ + public static SQLException createSQLException(Throwable th){ + if(th instanceof SQLException){ + return (SQLException)th; + } + if(th instanceof OdbcException){ + SQLException sqlEx = null; + OdbcErrorCollection errors = ((OdbcException)th).get_Errors(); + for(int e = 0; e < errors.get_Count(); e++){ + OdbcError err = errors.get_Item(e); + SQLException newEx = new SQLException(err.get_Message(), err.get_SQLState(), err.get_NativeError()); + if(sqlEx == null){ + sqlEx = newEx; + }else{ + sqlEx.setNextException(newEx); + } + } + if(sqlEx != null){ + sqlEx.initCause(th); + return sqlEx; + } + } + if(th instanceof DbException){ + DbException dbEx = (DbException)th; + return new SQLException(dbEx.get_Message(), "S1000", dbEx.get_ErrorCode(), th); + } + return new SQLException(th); + } + + + /** + * Convert a value from java.sql.Types to a value from to a System.Data.DbType + * + * @param type + * a JDBC type + * @return a ADO.NET type + * @throws SQLException + * if the type can not be converted + */ + public static int convertJdbc2AdoNetType(int type) throws SQLException{ + switch(type){ + case Types.BIGINT: + return DbType.Int64; + case Types.BINARY: + case Types.BLOB: + case Types.LONGVARBINARY: + case Types.VARBINARY: + return DbType.Binary; + case Types.BIT: + case Types.BOOLEAN: + return DbType.Boolean; + case Types.CHAR: + return DbType.AnsiStringFixedLength; + case Types.CLOB: + case Types.DATALINK: + case Types.LONGVARCHAR: + case Types.NULL: // we hope that the DBMS can map any NULL values from VARCHAR + case Types.VARCHAR: + return DbType.AnsiString; + case Types.DATE: + return DbType.Date; + case Types.DECIMAL: + case Types.NUMERIC: + return DbType.Decimal; + case Types.DOUBLE: + return DbType.Double; + case Types.FLOAT: + case Types.REAL: + return DbType.Single; + case Types.INTEGER: + return DbType.Int32; + case Types.JAVA_OBJECT: + return DbType.Object; + case Types.LONGNVARCHAR: + case Types.NCLOB: + case Types.NVARCHAR: + return DbType.String; + case Types.NCHAR: + return DbType.StringFixedLength; + case Types.ROWID: + return DbType.Guid; + case Types.SMALLINT: + return DbType.Int16; + case Types.SQLXML: + return DbType.Xml; + case Types.TIME: + return DbType.Time; + case Types.TIMESTAMP: + return DbType.DateTime; + case Types.TINYINT: + return DbType.Byte; + case Types.ARRAY: + case Types.DISTINCT: + case Types.OTHER: + case Types.REF: + case Types.STRUCT: + break; + + } + throw new SQLException("Not supported JDBC type:" + type); + } +} diff --git a/openjdk/sun/management/ManagementFactoryHelper.java b/openjdk/sun/management/ManagementFactoryHelper.java new file mode 100644 index 0000000..b5fd8d7 --- /dev/null +++ b/openjdk/sun/management/ManagementFactoryHelper.java @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2003, 2013, 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.management; + +import java.lang.management.*; + +import javax.management.DynamicMBean; +import javax.management.InstanceAlreadyExistsException; +import javax.management.InstanceNotFoundException; +import javax.management.MBeanServer; +import javax.management.MBeanRegistrationException; +import javax.management.NotCompliantMBeanException; +import javax.management.ObjectName; +import javax.management.RuntimeOperationsException; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; + +import sun.util.logging.LoggingSupport; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +import static java.lang.management.ManagementFactory.*; + +/** + * ManagementFactoryHelper provides static factory methods to create + * instances of the management interface. + */ +public class ManagementFactoryHelper { + private ManagementFactoryHelper() {}; + + private static VMManagement jvm; + + private static ClassLoadingImpl classMBean = null; + private static MemoryImpl memoryMBean = null; + private static ThreadImpl threadMBean = null; + private static RuntimeImpl runtimeMBean = null; + private static CompilationImpl compileMBean = null; + private static OperatingSystemImpl osMBean = null; + + public static synchronized ClassLoadingMXBean getClassLoadingMXBean() { + if (classMBean == null) { + classMBean = new ClassLoadingImpl(jvm); + } + return classMBean; + } + + public static synchronized MemoryMXBean getMemoryMXBean() { + if (memoryMBean == null) { + memoryMBean = new MemoryImpl(jvm); + } + return memoryMBean; + } + + public static synchronized ThreadMXBean getThreadMXBean() { + if (threadMBean == null) { + threadMBean = new ThreadImpl(jvm); + } + return threadMBean; + } + + public static synchronized RuntimeMXBean getRuntimeMXBean() { + if (runtimeMBean == null) { + runtimeMBean = new RuntimeImpl(jvm); + } + return runtimeMBean; + } + + public static synchronized CompilationMXBean getCompilationMXBean() { + if (compileMBean == null && jvm.getCompilerName() != null) { + compileMBean = new CompilationImpl(jvm); + } + return compileMBean; + } + + public static synchronized OperatingSystemMXBean getOperatingSystemMXBean() { + if (osMBean == null) { + osMBean = new OperatingSystemImpl(jvm); + } + return osMBean; + } + + public static List getMemoryPoolMXBeans() { + MemoryPoolMXBean[] pools = MemoryImpl.getMemoryPools(); + List list = new ArrayList<>(pools.length); + for (MemoryPoolMXBean p : pools) { + list.add(p); + } + return list; + } + + public static List getMemoryManagerMXBeans() { + MemoryManagerMXBean[] mgrs = MemoryImpl.getMemoryManagers(); + List result = new ArrayList<>(mgrs.length); + for (MemoryManagerMXBean m : mgrs) { + result.add(m); + } + return result; + } + + public static List getGarbageCollectorMXBeans() { + MemoryManagerMXBean[] mgrs = MemoryImpl.getMemoryManagers(); + List result = new ArrayList<>(mgrs.length); + for (MemoryManagerMXBean m : mgrs) { + if (GarbageCollectorMXBean.class.isInstance(m)) { + result.add(GarbageCollectorMXBean.class.cast(m)); + } + } + return result; + } + + public static PlatformLoggingMXBean getPlatformLoggingMXBean() { + if (LoggingSupport.isAvailable()) { + return PlatformLoggingImpl.instance; + } else { + return null; + } + } + + /** + * The logging MXBean object is an instance of + * PlatformLoggingMXBean and java.util.logging.LoggingMXBean + * but it can't directly implement two MXBean interfaces + * as a compliant MXBean implements exactly one MXBean interface, + * or if it implements one interface that is a subinterface of + * all the others; otherwise, it is a non-compliant MXBean + * and MBeanServer will throw NotCompliantMBeanException. + * See the Definition of an MXBean section in javax.management.MXBean spec. + * + * To create a compliant logging MXBean, define a LoggingMXBean interface + * that extend PlatformLoggingMXBean and j.u.l.LoggingMXBean + */ + public interface LoggingMXBean + extends PlatformLoggingMXBean, java.util.logging.LoggingMXBean { + } + + static class PlatformLoggingImpl implements LoggingMXBean + { + final static PlatformLoggingMXBean instance = new PlatformLoggingImpl(); + final static String LOGGING_MXBEAN_NAME = "java.util.logging:type=Logging"; + + private volatile ObjectName objname; // created lazily + @Override + public ObjectName getObjectName() { + ObjectName result = objname; + if (result == null) { + synchronized (this) { + result = objname; + if (result == null) { + result = Util.newObjectName(LOGGING_MXBEAN_NAME); + objname = result; + } + } + } + return result; + } + + @Override + public java.util.List getLoggerNames() { + return LoggingSupport.getLoggerNames(); + } + + @Override + public String getLoggerLevel(String loggerName) { + return LoggingSupport.getLoggerLevel(loggerName); + } + + @Override + public void setLoggerLevel(String loggerName, String levelName) { + LoggingSupport.setLoggerLevel(loggerName, levelName); + } + + @Override + public String getParentLoggerName(String loggerName) { + return LoggingSupport.getParentLoggerName(loggerName); + } + } + + private static List bufferPools = null; + public static synchronized List getBufferPoolMXBeans() { + if (bufferPools == null) { + bufferPools = new ArrayList<>(2); + bufferPools.add(createBufferPoolMXBean(sun.misc.SharedSecrets.getJavaNioAccess() + .getDirectBufferPool())); + bufferPools.add(createBufferPoolMXBean(sun.nio.ch.FileChannelImpl + .getMappedBufferPool())); + } + return bufferPools; + } + + private final static String BUFFER_POOL_MXBEAN_NAME = "java.nio:type=BufferPool"; + + /** + * Creates management interface for the given buffer pool. + */ + private static BufferPoolMXBean + createBufferPoolMXBean(final sun.misc.JavaNioAccess.BufferPool pool) + { + return new BufferPoolMXBean() { + private volatile ObjectName objname; // created lazily + @Override + public ObjectName getObjectName() { + ObjectName result = objname; + if (result == null) { + synchronized (this) { + result = objname; + if (result == null) { + result = Util.newObjectName(BUFFER_POOL_MXBEAN_NAME + + ",name=" + pool.getName()); + objname = result; + } + } + } + return result; + } + @Override + public String getName() { + return pool.getName(); + } + @Override + public long getCount() { + return pool.getCount(); + } + @Override + public long getTotalCapacity() { + return pool.getTotalCapacity(); + } + @Override + public long getMemoryUsed() { + return pool.getMemoryUsed(); + } + }; + } + + /** + * Registers a given MBean if not registered in the MBeanServer; + * otherwise, just return. + */ + private static void addMBean(MBeanServer mbs, Object mbean, String mbeanName) { + try { + final ObjectName objName = Util.newObjectName(mbeanName); + + // inner class requires these fields to be final + final MBeanServer mbs0 = mbs; + final Object mbean0 = mbean; + AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Void run() throws MBeanRegistrationException, + NotCompliantMBeanException { + try { + mbs0.registerMBean(mbean0, objName); + return null; + } catch (InstanceAlreadyExistsException e) { + // if an instance with the object name exists in + // the MBeanServer ignore the exception + } + return null; + } + }); + } catch (PrivilegedActionException e) { + throw Util.newException(e.getException()); + } + } + + public static HashMap getPlatformDynamicMBeans() { + HashMap map = new HashMap<>(); + return map; + } + + static void registerInternalMBeans(MBeanServer mbs) { + } + + static void unregisterInternalMBeans(MBeanServer mbs) { + } + + static { + jvm = new VMManagementImpl(); + } + + public static boolean isThreadSuspended(int state) { + return ((state & JMM_THREAD_STATE_FLAG_SUSPENDED) != 0); + } + + public static boolean isThreadRunningNative(int state) { + return ((state & JMM_THREAD_STATE_FLAG_NATIVE) != 0); + } + + public static Thread.State toThreadState(int state) { + // suspended and native bits may be set in state + int threadStatus = state & ~JMM_THREAD_STATE_FLAG_MASK; + return sun.misc.VM.toThreadState(threadStatus); + } + + // These values are defined in jmm.h + private static final int JMM_THREAD_STATE_FLAG_MASK = 0xFFF00000; + private static final int JMM_THREAD_STATE_FLAG_SUSPENDED = 0x00100000; + private static final int JMM_THREAD_STATE_FLAG_NATIVE = 0x00400000; + +} diff --git a/openjdk/sun/management/VMManagementImpl.java b/openjdk/sun/management/VMManagementImpl.java new file mode 100644 index 0000000..5f3686a --- /dev/null +++ b/openjdk/sun/management/VMManagementImpl.java @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2003, 2013, 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.management; + +import sun.misc.Perf; +import sun.management.counter.*; +import java.nio.ByteBuffer; +import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.List; +import java.util.Arrays; +import java.util.Collections; +import java.security.AccessController; +import java.security.PrivilegedAction; +import sun.security.action.GetPropertyAction; + +/** + * Implementation of VMManagement interface that accesses the management + * attributes and operations locally within the same Java virtual + * machine. + */ +class VMManagementImpl implements VMManagement { + + private static String version = "1.2"; + + private static boolean compTimeMonitoringSupport; + private static boolean threadContentionMonitoringSupport; + private static boolean currentThreadCpuTimeSupport = true; + private static boolean otherThreadCpuTimeSupport; + private static boolean bootClassPathSupport; + private static boolean objectMonitorUsageSupport; + private static boolean synchronizerUsageSupport; + private static boolean threadAllocatedMemorySupport; + private static boolean gcNotificationSupport; + private static boolean remoteDiagnosticCommandsSupport; + + // Optional supports + public boolean isCompilationTimeMonitoringSupported() { + return compTimeMonitoringSupport; + } + + public boolean isThreadContentionMonitoringSupported() { + return threadContentionMonitoringSupport; + } + + public boolean isCurrentThreadCpuTimeSupported() { + return currentThreadCpuTimeSupport; + } + + public boolean isOtherThreadCpuTimeSupported() { + return otherThreadCpuTimeSupport; + } + + public boolean isBootClassPathSupported() { + return bootClassPathSupport; + } + + public boolean isObjectMonitorUsageSupported() { + return objectMonitorUsageSupport; + } + + public boolean isSynchronizerUsageSupported() { + return synchronizerUsageSupport; + } + + public boolean isThreadAllocatedMemorySupported() { + return threadAllocatedMemorySupport; + } + + public boolean isGcNotificationSupported() { + return gcNotificationSupport; + } + + public boolean isRemoteDiagnosticCommandsSupported() { + return remoteDiagnosticCommandsSupport; + } + + public boolean isThreadContentionMonitoringEnabled() { + return false; + } + + public boolean isThreadCpuTimeEnabled() { + return true; + } + + public boolean isThreadAllocatedMemoryEnabled() { + return false; + } + + // Class Loading Subsystem + public int getLoadedClassCount() { + long count = getTotalClassCount() - getUnloadedClassCount(); + return (int) count; + } + public long getTotalClassCount() { + throw new Error("Not implemented"); + } + public long getUnloadedClassCount() { + throw new Error("Not implemented"); + } + + public boolean getVerboseClass() { + return false; + } + + // Memory Subsystem + public boolean getVerboseGC() { + return false; + } + + // Runtime Subsystem + public String getManagementVersion() { + return version; + } + + public String getVmId() { + int pid = getProcessId(); + String hostname = "localhost"; + try { + hostname = InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + // ignore + } + + return pid + "@" + hostname; + } + private int getProcessId() { + return cli.System.Diagnostics.Process.GetCurrentProcess().get_Id(); + } + + public String getVmName() { + return System.getProperty("java.vm.name"); + } + + public String getVmVendor() { + return System.getProperty("java.vm.vendor"); + } + public String getVmVersion() { + return System.getProperty("java.vm.version"); + } + public String getVmSpecName() { + return System.getProperty("java.vm.specification.name"); + } + public String getVmSpecVendor() { + return System.getProperty("java.vm.specification.vendor"); + } + public String getVmSpecVersion() { + return System.getProperty("java.vm.specification.version"); + } + public String getClassPath() { + return System.getProperty("java.class.path"); + } + public String getLibraryPath() { + return System.getProperty("java.library.path"); + } + + public String getBootClassPath( ) { + PrivilegedAction pa + = new GetPropertyAction("sun.boot.class.path"); + String result = AccessController.doPrivileged(pa); + return result; + } + + public long getUptime() { + return cli.System.DateTime.get_Now().Subtract(cli.System.Diagnostics.Process.GetCurrentProcess().get_StartTime()).get_Ticks() / 10000L; + } + + private List vmArgs = null; + public synchronized List getVmArguments() { + if (vmArgs == null) { + String[] args = getVmArguments0(); + List l = ((args != null && args.length != 0) ? Arrays.asList(args) : + Collections.emptyList()); + vmArgs = Collections.unmodifiableList(l); + } + return vmArgs; + } + public String[] getVmArguments0() { + return new String[0]; + } + + public long getStartupTime() { + return (long)(cli.System.Diagnostics.Process.GetCurrentProcess().get_StartTime().ToUniversalTime().Subtract(new cli.System.DateTime(1970, 1, 1))).get_TotalMilliseconds(); + } + public int getAvailableProcessors() { + return cli.System.Environment.get_ProcessorCount(); + } + + // Compilation Subsystem + public String getCompilerName() { + String name = AccessController.doPrivileged( + new PrivilegedAction() { + public String run() { + return System.getProperty("sun.management.compiler"); + } + }); + return name; + } + public long getTotalCompileTime() { + throw new Error("Not implemented"); + } + + // Thread Subsystem + public long getTotalThreadCount() { + throw new Error("Not implemented"); + } + public int getLiveThreadCount() { + throw new Error("Not implemented"); + } + public int getPeakThreadCount() { + throw new Error("Not implemented"); + } + public int getDaemonThreadCount() { + throw new Error("Not implemented"); + } + + // Operating System + public String getOsName() { + return System.getProperty("os.name"); + } + public String getOsArch() { + return System.getProperty("os.arch"); + } + public String getOsVersion() { + return System.getProperty("os.version"); + } + + // Hotspot-specific runtime support + public long getSafepointCount() { + throw new Error("Not implemented"); + } + public long getTotalSafepointTime() { + throw new Error("Not implemented"); + } + public long getSafepointSyncTime() { + throw new Error("Not implemented"); + } + public long getTotalApplicationNonStoppedTime() { + throw new Error("Not implemented"); + } + + public long getLoadedClassSize() { + throw new Error("Not implemented"); + } + public long getUnloadedClassSize() { + throw new Error("Not implemented"); + } + public long getClassLoadingTime() { + throw new Error("Not implemented"); + } + public long getMethodDataSize() { + throw new Error("Not implemented"); + } + public long getInitializedClassCount() { + throw new Error("Not implemented"); + } + public long getClassInitializationTime() { + throw new Error("Not implemented"); + } + public long getClassVerificationTime() { + throw new Error("Not implemented"); + } + + public List getInternalCounters(String pattern) { + return Collections.emptyList(); + } +} diff --git a/openjdk/sun/misc/FileURLMapper.java b/openjdk/sun/misc/FileURLMapper.java new file mode 100644 index 0000000..3fd43e4 --- /dev/null +++ b/openjdk/sun/misc/FileURLMapper.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2002, 2003, 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. + */ + +/*IKVM*/ +/* + * Modified for IKVM by Jeroen Frijters on May 22, 2007. + * + * This is a merged version of the Windows & Solaris platform specific versions. + * Since the IKVM class library binary can be used both on Windows and on *nix, + * I've merged the platform specific classes into a generic class that at + * runtime determines if it runs on Windows or not. + * +/*IKVM*/ + +package sun.misc; + +import java.net.URL; +import java.io.File; +import sun.net.www.ParseUtil; + +/** + * Platform specific handling for file: URLs . In particular deals + * with network paths mapping them to UNCs. + * + * @author Michael McMahon + * @version 1.10, 07/05/05 + */ + +public class FileURLMapper { + private static final boolean runningOnWindows = cli.System.Environment.get_OSVersion().ToString().indexOf("Unix") == -1; + URL url; + String file; + + public FileURLMapper (URL url) { + this.url = url; + } + + /** + * @returns the platform specific path corresponding to the URL, and in particular + * returns a UNC when the authority contains a hostname + */ + + public String getPath () { + if (file != null) { + return file; + } + if (runningOnWindows) { + String host = url.getHost(); + if (host != null && !host.equals("") && + !"localhost".equalsIgnoreCase(host)) { + String rest = url.getFile(); + String s = host + ParseUtil.decode (url.getFile()); + file = "\\\\"+ s.replace('/', '\\'); + return file; + } + String path = url.getFile().replace('/', '\\'); + file = ParseUtil.decode(path); + return file; + } else { + String host = url.getHost(); + if (host == null || "".equals(host) || "localhost".equalsIgnoreCase (host)) { + file = url.getFile(); + file = ParseUtil.decode (file); + } + return file; + } + } + + public boolean exists() { + String path = getPath(); + if (path == null) { + return false; + } + File f = new File (path); + return f.exists(); + } +} diff --git a/openjdk/sun/misc/MiscHelper.java b/openjdk/sun/misc/MiscHelper.java new file mode 100644 index 0000000..da8aae2 --- /dev/null +++ b/openjdk/sun/misc/MiscHelper.java @@ -0,0 +1,59 @@ +/* + Copyright (C) 2007 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package sun.misc; + +import cli.System.Reflection.Assembly; +import java.io.IOException; + +class MiscHelper +{ + // map.xml replaces ExtClassLoader.getExtClassLoader() invocation in Launcher constructor with a call to this method + static Launcher.ExtClassLoader getExtClassLoader() throws IOException + { + if ("".equals(System.getProperty("java.ext.dirs")) && "".equals(System.getProperty("java.class.path"))) + { + return null; + } + return Launcher.ExtClassLoader.getExtClassLoader(); + } + + // map.xml replaces AppClassLoader.getAppClassLoader() invocation in Launcher constructor with a call to this method + static ClassLoader getAppClassLoader(ClassLoader extcl) throws IOException + { + Assembly entryAssembly = Assembly.GetEntryAssembly(); + if (entryAssembly != null) + { + ClassLoader acl = getAssemblyClassLoader(entryAssembly, extcl); + if (acl != null) + { + // assembly has a custom assembly class loader, + // that overrides the Launcher.AppClassLoader + return acl; + } + } + return Launcher.AppClassLoader.getAppClassLoader(extcl); + } + + private static native ClassLoader getAssemblyClassLoader(Assembly asm, ClassLoader extcl); +} diff --git a/openjdk/sun/misc/OSEnvironment.java b/openjdk/sun/misc/OSEnvironment.java new file mode 100644 index 0000000..d51ac0f --- /dev/null +++ b/openjdk/sun/misc/OSEnvironment.java @@ -0,0 +1,32 @@ +/* + Copyright (C) 2007 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package sun.misc; + +public class OSEnvironment +{ + public static void initialize() + { + } +} diff --git a/openjdk/sun/misc/SharedSecrets.java b/openjdk/sun/misc/SharedSecrets.java new file mode 100644 index 0000000..f680fe4 --- /dev/null +++ b/openjdk/sun/misc/SharedSecrets.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2002, 2013, 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.misc; + +import java.util.jar.JarFile; +import java.io.Console; +import java.security.ProtectionDomain; + +import java.security.AccessController; + +/** A repository of "shared secrets", which are a mechanism for + calling implementation-private methods in another package without + using reflection. A package-private class implements a public + interface and provides the ability to call package-private methods + within that package; the object implementing that interface is + provided through a third package to which access is restricted. + This framework avoids the primary disadvantage of using reflection + for this purpose, namely the loss of compile-time checking. */ + +public class SharedSecrets { + private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static JavaUtilJarAccess javaUtilJarAccess; + private static JavaLangAccess javaLangAccess = LangHelper.getJavaLangAccess(); + private static JavaIOAccess javaIOAccess; + private static JavaNetAccess javaNetAccess; + private static JavaNetHttpCookieAccess javaNetHttpCookieAccess; + private static JavaNioAccess javaNioAccess; + private static JavaSecurityProtectionDomainAccess javaSecurityProtectionDomainAccess; + private static JavaSecurityAccess javaSecurityAccess; + private static JavaUtilZipFileAccess javaUtilZipFileAccess; + private static JavaAWTAccess javaAWTAccess; + + public static JavaUtilJarAccess javaUtilJarAccess() { + if (javaUtilJarAccess == null) { + // Ensure JarFile is initialized; we know that that class + // provides the shared secret + unsafe.ensureClassInitialized(JarFile.class); + } + return javaUtilJarAccess; + } + + public static void setJavaUtilJarAccess(JavaUtilJarAccess access) { + javaUtilJarAccess = access; + } + + public static JavaLangAccess getJavaLangAccess() { + return javaLangAccess; + } + + public static void setJavaNetAccess(JavaNetAccess jna) { + javaNetAccess = jna; + } + + public static JavaNetAccess getJavaNetAccess() { + return javaNetAccess; + } + + public static void setJavaNetHttpCookieAccess(JavaNetHttpCookieAccess a) { + javaNetHttpCookieAccess = a; + } + + public static JavaNetHttpCookieAccess getJavaNetHttpCookieAccess() { + if (javaNetHttpCookieAccess == null) + unsafe.ensureClassInitialized(java.net.HttpCookie.class); + return javaNetHttpCookieAccess; + } + + public static void setJavaNioAccess(JavaNioAccess jna) { + javaNioAccess = jna; + } + + public static JavaNioAccess getJavaNioAccess() { + if (javaNioAccess == null) { + // [IKVM] OpenJDK initializes java.nio.ByteOrder here, but that doesn't work + java.nio.ByteOrder.nativeOrder(); + } + return javaNioAccess; + } + + public static void setJavaIOAccess(JavaIOAccess jia) { + javaIOAccess = jia; + } + + public static JavaIOAccess getJavaIOAccess() { + if (javaIOAccess == null) { + unsafe.ensureClassInitialized(Console.class); + } + return javaIOAccess; + } + + public static void setJavaSecurityProtectionDomainAccess + (JavaSecurityProtectionDomainAccess jspda) { + javaSecurityProtectionDomainAccess = jspda; + } + + public static JavaSecurityProtectionDomainAccess + getJavaSecurityProtectionDomainAccess() { + if (javaSecurityProtectionDomainAccess == null) + unsafe.ensureClassInitialized(ProtectionDomain.class); + return javaSecurityProtectionDomainAccess; + } + + public static void setJavaSecurityAccess(JavaSecurityAccess jsa) { + javaSecurityAccess = jsa; + } + + public static JavaSecurityAccess getJavaSecurityAccess() { + if (javaSecurityAccess == null) { + // [IKVM] OpenJDK initializes AccessController here, but that's a bug + unsafe.ensureClassInitialized(ProtectionDomain.class); + } + return javaSecurityAccess; + } + + public static JavaUtilZipFileAccess getJavaUtilZipFileAccess() { + if (javaUtilZipFileAccess == null) + unsafe.ensureClassInitialized(java.util.zip.ZipFile.class); + return javaUtilZipFileAccess; + } + + public static void setJavaUtilZipFileAccess(JavaUtilZipFileAccess access) { + javaUtilZipFileAccess = access; + } + + public static void setJavaAWTAccess(JavaAWTAccess jaa) { + javaAWTAccess = jaa; + } + + public static JavaAWTAccess getJavaAWTAccess() { + // this may return null in which case calling code needs to + // provision for. + if (javaAWTAccess == null) { + return null; + } + return javaAWTAccess; + } +} diff --git a/openjdk/sun/misc/Unsafe.java b/openjdk/sun/misc/Unsafe.java new file mode 100644 index 0000000..4deac4b --- /dev/null +++ b/openjdk/sun/misc/Unsafe.java @@ -0,0 +1,1270 @@ +/* + Copyright (C) 2006-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package sun.misc; + +import cli.System.Buffer; +import cli.System.IntPtr; +import cli.System.Runtime.InteropServices.Marshal; +import cli.System.Security.Permissions.SecurityAction; +import cli.System.Security.Permissions.SecurityPermissionAttribute; +import ikvm.lang.Internal; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.security.ProtectionDomain; +import java.util.ArrayList; + +public final class Unsafe +{ + public static final int INVALID_FIELD_OFFSET = -1; + public static final int ARRAY_BYTE_BASE_OFFSET = 0; + // NOTE sun.corba.Bridge actually access this field directly (via reflection), + // so the name must match the JDK name. + private static final Unsafe theUnsafe = new Unsafe(); + private static final ArrayList fields = new ArrayList(); + + private Unsafe() { } + + @sun.reflect.CallerSensitive + public static Unsafe getUnsafe() + { + if(!VM.isSystemDomainLoader(ikvm.internal.CallerID.getCallerID().getCallerClassLoader())) + { + throw new SecurityException("Unsafe"); + } + return theUnsafe; + } + + private static native Field createFieldAndMakeAccessible(Class c, String field); + private static native Field copyFieldAndMakeAccessible(Field field); + + // this is the intrinsified version of objectFieldOffset(XXX.class.getDeclaredField("xxx")) + public long objectFieldOffset(Class c, String field) + { + return allocateUnsafeFieldId(createFieldAndMakeAccessible(c, field)); + } + + // NOTE we have a really lame (and slow) implementation! + public long objectFieldOffset(Field field) + { + if(Modifier.isStatic(field.getModifiers())) + { + throw new IllegalArgumentException(); + } + return allocateUnsafeFieldId(field); + } + + public long staticFieldOffset(Field field) + { + if(!Modifier.isStatic(field.getModifiers())) + { + throw new IllegalArgumentException(); + } + return allocateUnsafeFieldId(field); + } + + @Deprecated + public int fieldOffset(Field original) + { + return allocateUnsafeFieldId(original); + } + + static int allocateUnsafeFieldId(Field original) + { + Field copy = copyFieldAndMakeAccessible(original); + synchronized(fields) + { + int id = fields.size(); + fields.add(copy); + return id; + } + } + + public int arrayBaseOffset(Class c) + { + // don't change this, the Unsafe intrinsics depend on this value + return 0; + } + + public int arrayIndexScale(Class c) + { + if (c == byte[].class || c == boolean[].class) + { + return 1; + } + if (c == char[].class || c == short[].class) + { + return 2; + } + if (c == int[].class || c == float[].class) + { + return 4; + } + if (c == long[].class || c == double[].class) + { + return 8; + } + // don't change this, the Unsafe intrinsics depend on this value + return 1; + } + + static Field getField(long offset) + { + synchronized(fields) + { + return fields.get((int)offset); + } + } + + public final native boolean compareAndSwapObject(Object obj, long offset, Object expect, Object update); + + public void putObjectVolatile(Object obj, long offset, Object newValue) + { + if(obj instanceof Object[]) + { + synchronized(this) + { + ((Object[])obj)[(int)offset] = newValue; + } + } + else + { + Field field = getField(offset); + synchronized(field) + { + try + { + field.set(obj, newValue); + } + catch(IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + } + + public void putOrderedObject(Object obj, long offset, Object newValue) + { + putObjectVolatile(obj, offset, newValue); + } + + public Object getObjectVolatile(Object obj, long offset) + { + if(obj instanceof Object[]) + { + synchronized(this) + { + return ((Object[])obj)[(int)offset]; + } + } + else + { + Field field = getField(offset); + synchronized(field) + { + try + { + return field.get(obj); + } + catch(IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + } + + private static native short ReadInt16(Object obj, long offset); + private static native int ReadInt32(Object obj, long offset); + private static native long ReadInt64(Object obj, long offset); + private static native void WriteInt16(Object obj, long offset, short value); + private static native void WriteInt32(Object obj, long offset, int value); + private static native void WriteInt64(Object obj, long offset, long value); + + public final native boolean compareAndSwapInt(Object obj, long offset, int expect, int update); + + public void putIntVolatile(Object obj, long offset, int newValue) + { + if (obj instanceof cli.System.Array) + { + synchronized(this) + { + WriteInt32(obj, offset, newValue); + } + } + else + { + Field field = getField(offset); + synchronized(field) + { + try + { + field.setInt(obj, newValue); + } + catch(IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + } + + public void putOrderedInt(Object obj, long offset, int newValue) + { + putIntVolatile(obj, offset, newValue); + } + + public int getIntVolatile(Object obj, long offset) + { + if (obj instanceof cli.System.Array) + { + synchronized(this) + { + return ReadInt32(obj, offset); + } + } + else + { + Field field = getField(offset); + synchronized(field) + { + try + { + return field.getInt(obj); + } + catch(IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + } + + public final native boolean compareAndSwapLong(Object obj, long offset, long expect, long update); + + public void putLongVolatile(Object obj, long offset, long newValue) + { + if (obj instanceof cli.System.Array) + { + synchronized(this) + { + WriteInt64(obj, offset, newValue); + } + } + else + { + Field field = getField(offset); + synchronized(field) + { + try + { + field.setLong(obj, newValue); + } + catch(IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + } + + public void putOrderedLong(Object obj, long offset, long newValue) + { + putLongVolatile(obj, offset, newValue); + } + + public long getLongVolatile(Object obj, long offset) + { + if (obj instanceof cli.System.Array) + { + synchronized(this) + { + return ReadInt64(obj, offset); + } + } + else + { + Field field = getField(offset); + synchronized(field) + { + try + { + return field.getLong(obj); + } + catch(IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + } + + public void putBoolean(Object obj, long offset, boolean newValue) + { + if (obj instanceof cli.System.Array) + { + Buffer.SetByte((cli.System.Array)obj, (int)offset, newValue ? (byte)1 : (byte)0); + } + else + { + try + { + getField(offset).setBoolean(obj, newValue); + } + catch (IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + + public void putBooleanVolatile(Object obj, long offset, boolean newValue) + { + putBoolean(obj, offset, newValue); + } + + public boolean getBoolean(Object obj, long offset) + { + if (obj instanceof cli.System.Array) + { + return Buffer.GetByte((cli.System.Array)obj, (int)offset) != 0; + } + else + { + try + { + return getField(offset).getBoolean(obj); + } + catch (IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + + public boolean getBooleanVolatile(Object obj, long offset) + { + return getBoolean(obj, offset); + } + + public void putByte(Object obj, long offset, byte newValue) + { + if (obj instanceof cli.System.Array) + { + Buffer.SetByte((cli.System.Array)obj, (int)offset, newValue); + } + else + { + try + { + getField(offset).setByte(obj, newValue); + } + catch (IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + + public void putByteVolatile(Object obj, long offset, byte newValue) + { + putByte(obj, offset, newValue); + } + + public byte getByte(Object obj, long offset) + { + if (obj instanceof cli.System.Array) + { + return Buffer.GetByte((cli.System.Array)obj, (int)offset); + } + else + { + try + { + return getField(offset).getByte(obj); + } + catch (IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + + public byte getByteVolatile(Object obj, long offset) + { + return getByte(obj, offset); + } + + public void putChar(Object obj, long offset, char newValue) + { + if (obj instanceof cli.System.Array) + { + WriteInt16(obj, offset, (short)newValue); + } + else + { + try + { + getField(offset).setChar(obj, newValue); + } + catch (IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + + public void putCharVolatile(Object obj, long offset, char newValue) + { + putChar(obj, offset, newValue); + } + + public char getChar(Object obj, long offset) + { + if (obj instanceof cli.System.Array) + { + return (char)ReadInt16(obj, offset); + } + else + { + try + { + return getField(offset).getChar(obj); + } + catch (IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + + public char getCharVolatile(Object obj, long offset) + { + return getChar(obj, offset); + } + + public void putShort(Object obj, long offset, short newValue) + { + if (obj instanceof cli.System.Array) + { + WriteInt16(obj, offset, newValue); + } + else + { + try + { + getField(offset).setShort(obj, newValue); + } + catch (IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + + public void putShortVolatile(Object obj, long offset, short newValue) + { + putShort(obj, offset, newValue); + } + + public short getShort(Object obj, long offset) + { + if (obj instanceof cli.System.Array) + { + return ReadInt16(obj, offset); + } + else + { + try + { + return getField(offset).getShort(obj); + } + catch (IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + + public short getShortVolatile(Object obj, long offset) + { + return getShort(obj, offset); + } + + public void putInt(Object obj, long offset, int newValue) + { + if (obj instanceof cli.System.Array) + { + WriteInt32(obj, offset, newValue); + } + else + { + try + { + getField(offset).setInt(obj, newValue); + } + catch (IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + + public int getInt(Object obj, long offset) + { + if (obj instanceof cli.System.Array) + { + return ReadInt32(obj, offset); + } + else + { + try + { + return getField(offset).getInt(obj); + } + catch (IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + + public void putFloat(Object obj, long offset, float newValue) + { + if (obj instanceof cli.System.Array) + { + WriteInt32(obj, offset, Float.floatToRawIntBits(newValue)); + } + else + { + try + { + getField(offset).setFloat(obj, newValue); + } + catch (IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + + public void putFloatVolatile(Object obj, long offset, float newValue) + { + putFloat(obj, offset, newValue); + } + + public float getFloat(Object obj, long offset) + { + if (obj instanceof cli.System.Array) + { + return Float.intBitsToFloat(ReadInt32(obj, offset)); + } + else + { + try + { + return getField(offset).getFloat(obj); + } + catch (IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + + public float getFloatVolatile(Object obj, long offset) + { + return getFloat(obj, offset); + } + + public void putLong(Object obj, long offset, long newValue) + { + if (obj instanceof cli.System.Array) + { + WriteInt64(obj, offset, newValue); + } + else + { + try + { + getField(offset).setLong(obj, newValue); + } + catch (IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + + public long getLong(Object obj, long offset) + { + if (obj instanceof cli.System.Array) + { + return ReadInt64(obj, offset); + } + else + { + try + { + return getField(offset).getLong(obj); + } + catch (IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + + public void putDouble(Object obj, long offset, double newValue) + { + if (obj instanceof cli.System.Array) + { + WriteInt64(obj, offset, Double.doubleToRawLongBits(newValue)); + } + else + { + try + { + getField(offset).setDouble(obj, newValue); + } + catch (IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + + public void putDoubleVolatile(Object obj, long offset, double newValue) + { + synchronized (this) + { + putDouble(obj, offset, newValue); + } + } + + public double getDouble(Object obj, long offset) + { + if (obj instanceof cli.System.Array) + { + return Double.longBitsToDouble(ReadInt64(obj, offset)); + } + else + { + try + { + return getField(offset).getDouble(obj); + } + catch (IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + + public double getDoubleVolatile(Object obj, long offset) + { + synchronized (this) + { + return getDouble(obj, offset); + } + } + + public void putObject(Object obj, long offset, Object newValue) + { + if (obj instanceof Object[]) + { + ((Object[])obj)[(int)offset] = newValue; + } + else + { + try + { + getField(offset).set(obj, newValue); + } + catch (IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + + public Object getObject(Object obj, long offset) + { + if (obj instanceof Object[]) + { + return ((Object[])obj)[(int)offset]; + } + else + { + try + { + return getField(offset).get(obj); + } + catch (IllegalAccessException x) + { + throw (InternalError)new InternalError().initCause(x); + } + } + } + + @Deprecated + public int getInt(Object o, int offset) + { + return getInt(o, (long)offset); + } + + @Deprecated + public void putInt(Object o, int offset, int x) + { + putInt(o, (long)offset, x); + } + + @Deprecated + public Object getObject(Object o, int offset) + { + return getObject(o, (long)offset); + } + + @Deprecated + public void putObject(Object o, int offset, Object x) + { + putObject(o, (long)offset, x); + } + + @Deprecated + public boolean getBoolean(Object o, int offset) + { + return getBoolean(o, (long)offset); + } + + @Deprecated + public void putBoolean(Object o, int offset, boolean x) + { + putBoolean(o, (long)offset, x); + } + + @Deprecated + public byte getByte(Object o, int offset) + { + return getByte(o, (long)offset); + } + + @Deprecated + public void putByte(Object o, int offset, byte x) + { + putByte(o, (long)offset, x); + } + + @Deprecated + public short getShort(Object o, int offset) + { + return getShort(o, (long)offset); + } + + @Deprecated + public void putShort(Object o, int offset, short x) + { + putShort(o, (long)offset, x); + } + + @Deprecated + public char getChar(Object o, int offset) + { + return getChar(o, (long)offset); + } + + @Deprecated + public void putChar(Object o, int offset, char x) + { + putChar(o, (long)offset, x); + } + + @Deprecated + public long getLong(Object o, int offset) + { + return getLong(o, (long)offset); + } + + @Deprecated + public void putLong(Object o, int offset, long x) + { + putLong(o, (long)offset, x); + } + + @Deprecated + public float getFloat(Object o, int offset) + { + return getFloat(o, (long)offset); + } + + @Deprecated + public void putFloat(Object o, int offset, float x) + { + putFloat(o, (long)offset, x); + } + + @Deprecated + public double getDouble(Object o, int offset) + { + return getDouble(o, (long)offset); + } + + @Deprecated + public void putDouble(Object o, int offset, double x) + { + putDouble(o, (long)offset, x); + } + + public native void throwException(Throwable t); + + public native void ensureClassInitialized(Class clazz); + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, SerializationFormatter = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public native Object allocateInstance(Class clazz) throws InstantiationException; + + public int addressSize() + { + return IntPtr.get_Size(); + } + + public int pageSize() + { + return 4096; + } + + // The really unsafe methods start here. They are all have a LinkDemand for unmanaged code. + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public long allocateMemory(long bytes) + { + if (bytes == 0) + { + return 0; + } + try + { + if (false) throw new cli.System.OutOfMemoryException(); + return Marshal.AllocHGlobal(IntPtr.op_Explicit(bytes)).ToInt64(); + } + catch (cli.System.OutOfMemoryException x) + { + throw new OutOfMemoryError(x.get_Message()); + } + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public long reallocateMemory(long address, long bytes) + { + if (bytes == 0) + { + freeMemory(address); + return 0; + } + try + { + if (false) throw new cli.System.OutOfMemoryException(); + return Marshal.ReAllocHGlobal(IntPtr.op_Explicit(address), IntPtr.op_Explicit(bytes)).ToInt64(); + } + catch (cli.System.OutOfMemoryException x) + { + throw new OutOfMemoryError(x.get_Message()); + } + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public void freeMemory(long address) + { + Marshal.FreeHGlobal(IntPtr.op_Explicit(address)); + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public void setMemory(long address, long bytes, byte value) + { + while (bytes-- > 0) + { + putByte(address++, value); + } + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public void copyMemory(long srcAddress, long destAddress, long bytes) + { + while (bytes-- > 0) + { + putByte(destAddress++, getByte(srcAddress++)); + } + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public void copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes) + { + if (srcBase == null) + { + if (destBase instanceof byte[]) + { + cli.System.Runtime.InteropServices.Marshal.Copy(IntPtr.op_Explicit(srcOffset), (byte[])destBase, (int)destOffset, (int)bytes); + } + else if (destBase instanceof boolean[]) + { + byte[] tmp = new byte[(int)bytes]; + copyMemory(srcBase, srcOffset, tmp, 0, bytes); + copyMemory(tmp, 0, destBase, destOffset, bytes); + } + else if (destBase instanceof short[]) + { + cli.System.Runtime.InteropServices.Marshal.Copy(IntPtr.op_Explicit(srcOffset), (short[])destBase, (int)(destOffset >> 1), (int)(bytes >> 1)); + } + else if (destBase instanceof char[]) + { + cli.System.Runtime.InteropServices.Marshal.Copy(IntPtr.op_Explicit(srcOffset), (char[])destBase, (int)(destOffset >> 1), (int)(bytes >> 1)); + } + else if (destBase instanceof int[]) + { + cli.System.Runtime.InteropServices.Marshal.Copy(IntPtr.op_Explicit(srcOffset), (int[])destBase, (int)(destOffset >> 2), (int)(bytes >> 2)); + } + else if (destBase instanceof float[]) + { + cli.System.Runtime.InteropServices.Marshal.Copy(IntPtr.op_Explicit(srcOffset), (float[])destBase, (int)(destOffset >> 2), (int)(bytes >> 2)); + } + else if (destBase instanceof long[]) + { + cli.System.Runtime.InteropServices.Marshal.Copy(IntPtr.op_Explicit(srcOffset), (long[])destBase, (int)(destOffset >> 3), (int)(bytes >> 3)); + } + else if (destBase instanceof double[]) + { + cli.System.Runtime.InteropServices.Marshal.Copy(IntPtr.op_Explicit(srcOffset), (double[])destBase, (int)(destOffset >> 3), (int)(bytes >> 3)); + } + else if (destBase == null) + { + copyMemory(srcOffset, destOffset, bytes); + } + else + { + throw new IllegalArgumentException(); + } + } + else if (srcBase instanceof cli.System.Array && destBase instanceof cli.System.Array) + { + cli.System.Buffer.BlockCopy((cli.System.Array)srcBase, (int)srcOffset, (cli.System.Array)destBase, (int)destOffset, (int)bytes); + } + else + { + if (srcBase instanceof byte[]) + { + cli.System.Runtime.InteropServices.Marshal.Copy((byte[])srcBase, (int)srcOffset, IntPtr.op_Explicit(destOffset), (int)bytes); + } + else if (srcBase instanceof boolean[]) + { + byte[] tmp = new byte[(int)bytes]; + copyMemory(srcBase, srcOffset, tmp, 0, bytes); + copyMemory(tmp, 0, destBase, destOffset, bytes); + } + else if (srcBase instanceof short[]) + { + cli.System.Runtime.InteropServices.Marshal.Copy((short[])srcBase, (int)(srcOffset >> 1), IntPtr.op_Explicit(destOffset), (int)(bytes >> 1)); + } + else if (srcBase instanceof char[]) + { + cli.System.Runtime.InteropServices.Marshal.Copy((char[])srcBase, (int)(srcOffset >> 1), IntPtr.op_Explicit(destOffset), (int)(bytes >> 1)); + } + else if (srcBase instanceof int[]) + { + cli.System.Runtime.InteropServices.Marshal.Copy((int[])srcBase, (int)(srcOffset >> 2), IntPtr.op_Explicit(destOffset), (int)(bytes >> 2)); + } + else if (srcBase instanceof float[]) + { + cli.System.Runtime.InteropServices.Marshal.Copy((float[])srcBase, (int)(srcOffset >> 2), IntPtr.op_Explicit(destOffset), (int)(bytes >> 2)); + } + else if (srcBase instanceof long[]) + { + cli.System.Runtime.InteropServices.Marshal.Copy((long[])srcBase, (int)(srcOffset >> 3), IntPtr.op_Explicit(destOffset), (int)(bytes >> 3)); + } + else if (srcBase instanceof double[]) + { + cli.System.Runtime.InteropServices.Marshal.Copy((double[])srcBase, (int)(srcOffset >> 3), IntPtr.op_Explicit(destOffset), (int)(bytes >> 3)); + } + else + { + throw new IllegalArgumentException(); + } + } + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public byte getByte(long address) + { + return cli.System.Runtime.InteropServices.Marshal.ReadByte(IntPtr.op_Explicit(address)); + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public void putByte(long address, byte x) + { + cli.System.Runtime.InteropServices.Marshal.WriteByte(IntPtr.op_Explicit(address), x); + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public short getShort(long address) + { + return cli.System.Runtime.InteropServices.Marshal.ReadInt16(IntPtr.op_Explicit(address)); + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public void putShort(long address, short x) + { + cli.System.Runtime.InteropServices.Marshal.WriteInt16(IntPtr.op_Explicit(address), x); + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public char getChar(long address) + { + return (char)cli.System.Runtime.InteropServices.Marshal.ReadInt16(IntPtr.op_Explicit(address)); + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public void putChar(long address, char x) + { + cli.System.Runtime.InteropServices.Marshal.WriteInt16(IntPtr.op_Explicit(address), (short)x); + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public int getInt(long address) + { + return cli.System.Runtime.InteropServices.Marshal.ReadInt32(IntPtr.op_Explicit(address)); + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public void putInt(long address, int x) + { + cli.System.Runtime.InteropServices.Marshal.WriteInt32(IntPtr.op_Explicit(address), x); + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public long getLong(long address) + { + return cli.System.Runtime.InteropServices.Marshal.ReadInt64(IntPtr.op_Explicit(address)); + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public void putLong(long address, long x) + { + cli.System.Runtime.InteropServices.Marshal.WriteInt64(IntPtr.op_Explicit(address), x); + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public long getAddress(long address) + { + return cli.System.Runtime.InteropServices.Marshal.ReadIntPtr(IntPtr.op_Explicit(address)).ToInt64(); + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public void putAddress(long address, long x) + { + cli.System.Runtime.InteropServices.Marshal.WriteIntPtr(IntPtr.op_Explicit(address), IntPtr.op_Explicit(x)); + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public float getFloat(long address) + { + return Float.intBitsToFloat(getInt(address)); + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public void putFloat(long address, float x) + { + putInt(address, Float.floatToIntBits(x)); + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public double getDouble(long address) + { + return Double.longBitsToDouble(getLong(address)); + } + + @SecurityPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand, UnmanagedCode = true) + @cli.System.Security.SecurityCriticalAttribute.Annotation + public void putDouble(long address, double x) + { + putLong(address, Double.doubleToLongBits(x)); + } + + public int getLoadAverage(double[] loadavg, int nelems) + { + return -1; + } + + public void park(boolean isAbsolute, long time) + { + if (isAbsolute) + { + java.util.concurrent.locks.LockSupport.parkUntil(time); + } + else + { + if (time == 0) + { + time = Long.MAX_VALUE; + } + java.util.concurrent.locks.LockSupport.parkNanos(time); + } + } + + public void unpark(Object thread) + { + java.util.concurrent.locks.LockSupport.unpark((Thread)thread); + } + + public Object staticFieldBase(Field f) + { + return null; + } + + @Deprecated + public Object staticFieldBase(Class c) + { + return null; + } + + public native boolean shouldBeInitialized(Class c); + + public native Class defineClass(String name, byte[] buf, int offset, int length, ClassLoader cl, ProtectionDomain pd); + + @Deprecated + @sun.reflect.CallerSensitive + public native Class defineClass(String name, byte[] b, int off, int len); + + public native Class defineAnonymousClass(Class hostClass, byte[] data, Object[] cpPatches); + + public void monitorEnter(Object o) + { + cli.System.Threading.Monitor.Enter(o); + } + + public void monitorExit(Object o) + { + cli.System.Threading.Monitor.Exit(o); + } + + public boolean tryMonitorEnter(Object o) + { + return cli.System.Threading.Monitor.TryEnter(o); + } + + public final int getAndAddInt(Object o, long offset, int delta) + { + for (;;) + { + int value = getIntVolatile(o, offset); + if (compareAndSwapInt(o, offset, value, value + delta)) + { + return value; + } + } + } + + public final long getAndAddLong(Object o, long offset, long delta) + { + for (;;) + { + long value = getLongVolatile(o, offset); + if (compareAndSwapLong(o, offset, value, value + delta)) + { + return value; + } + } + } + + public final int getAndSetInt(Object o, long offset, int newValue) + { + for (;;) + { + int value = getIntVolatile(o, offset); + if (compareAndSwapInt(o, offset, value, newValue)) + { + return value; + } + } + } + + public final long getAndSetLong(Object o, long offset, long newValue) + { + for (;;) + { + long value = getLongVolatile(o, offset); + if (compareAndSwapLong(o, offset, value, newValue)) + { + return value; + } + } + } + + public final Object getAndSetObject(Object o, long offset, Object newValue) + { + for (;;) + { + Object value = getObjectVolatile(o, offset); + if (compareAndSwapObject(o, offset, value, newValue)) + { + return value; + } + } + } + + public void loadFence() + { + cli.System.Threading.Thread.MemoryBarrier(); + } + + public void storeFence() + { + cli.System.Threading.Thread.MemoryBarrier(); + } + + public void fullFence() + { + cli.System.Threading.Thread.MemoryBarrier(); + } +} diff --git a/openjdk/sun/misc/VM.java b/openjdk/sun/misc/VM.java new file mode 100644 index 0000000..2607d95 --- /dev/null +++ b/openjdk/sun/misc/VM.java @@ -0,0 +1,402 @@ +/* + * Copyright (c) 1996, 2014, 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.misc; + +import static java.lang.Thread.State.*; +import java.util.Properties; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class VM { + + /* The following methods used to be native methods that instruct + * the VM to selectively suspend certain threads in low-memory + * situations. They are inherently dangerous and not implementable + * on native threads. We removed them in JDK 1.2. The skeletons + * remain so that existing applications that use these methods + * will still work. + */ + private static boolean suspended = false; + + /** @deprecated */ + @Deprecated + public static boolean threadsSuspended() { + return suspended; + } + + @SuppressWarnings("deprecation") + public static boolean allowThreadSuspension(ThreadGroup g, boolean b) { + return g.allowThreadSuspension(b); + } + + /** @deprecated */ + @Deprecated + public static boolean suspendThreads() { + suspended = true; + return true; + } + + // Causes any suspended threadgroups to be resumed. + /** @deprecated */ + @Deprecated + public static void unsuspendThreads() { + suspended = false; + } + + // Causes threadgroups no longer marked suspendable to be resumed. + /** @deprecated */ + @Deprecated + public static void unsuspendSomeThreads() { + } + + /* Deprecated fields and methods -- Memory advice not supported in 1.2 */ + + /** @deprecated */ + @Deprecated + public static final int STATE_GREEN = 1; + + /** @deprecated */ + @Deprecated + public static final int STATE_YELLOW = 2; + + /** @deprecated */ + @Deprecated + public static final int STATE_RED = 3; + + /** @deprecated */ + @Deprecated + public static final int getState() { + return STATE_GREEN; + } + + /** @deprecated */ + @Deprecated + public static void registerVMNotification(VMNotification n) { } + + /** @deprecated */ + @Deprecated + public static void asChange(int as_old, int as_new) { } + + /** @deprecated */ + @Deprecated + public static void asChange_otherthread(int as_old, int as_new) { } + + /* + * Not supported in 1.2 because these will have to be exported as + * JVM functions, and we are not sure we want do that. Leaving + * here so it can be easily resurrected -- just remove the // + * comments. + */ + + /** + * Resume Java profiling. All profiling data is added to any + * earlier profiling, unless resetJavaProfiler is + * called in between. If profiling was not started from the + * command line, resumeJavaProfiler will start it. + *

+ * + * NOTE: Profiling must be enabled from the command line for a + * java.prof report to be automatically generated on exit; if not, + * writeJavaProfilerReport must be invoked to write a report. + * + * @see resetJavaProfiler + * @see writeJavaProfilerReport + */ + + // public native static void resumeJavaProfiler(); + + /** + * Suspend Java profiling. + */ + // public native static void suspendJavaProfiler(); + + /** + * Initialize Java profiling. Any accumulated profiling + * information is discarded. + */ + // public native static void resetJavaProfiler(); + + /** + * Write the current profiling contents to the file "java.prof". + * If the file already exists, it will be overwritten. + */ + // public native static void writeJavaProfilerReport(); + + + private static volatile boolean booted = false; + private static final Object lock = new Object(); + + static { + // [IKVM] force System properties initialization ("booting") + System.lineSeparator(); + } + + // Invoked by by System.initializeSystemClass just before returning. + // Subsystems that are invoked during initialization can check this + // property in order to avoid doing things that should wait until the + // application class loader has been set up. + // + // [IKVM] The above isn't applicable. We only use the booted flag + // for the system properties (this is required because the system properties + // use java.util.Hashtable (via java.util.Properties) and it relies on + // the booted flag to determine whether it is safe to query the system + // properties). + public static void booted() { + synchronized (lock) { + booted = true; + lock.notifyAll(); + } + } + + public static boolean isBooted() { + return booted; + } + + // Waits until VM completes initialization + // + // This method is invoked by the Finalizer thread + public static void awaitBooted() throws InterruptedException { + synchronized (lock) { + while (!booted) { + lock.wait(); + } + } + } + + // Returns the maximum amount of allocatable direct buffer memory. + // The directMemory variable is initialized during system initialization + // in the saveAndRemoveProperties method. + // + public static long maxDirectMemory() { + // we don't support -XX:MaxDirectMemorySize + return Long.MAX_VALUE; + } + + // User-controllable flag that determines if direct buffers should be page + // aligned. The "-XX:+PageAlignDirectMemory" option can be used to force + // buffers, allocated by ByteBuffer.allocateDirect, to be page aligned. + private static boolean pageAlignDirectMemory; + + // Returns {@code true} if the direct buffers should be page aligned. This + // variable is initialized by saveAndRemoveProperties. + public static boolean isDirectMemoryPageAligned() { + return pageAlignDirectMemory; + } + + // A user-settable boolean to determine whether ClassLoader.loadClass should + // accept array syntax. This value may be changed during VM initialization + // via the system property "sun.lang.ClassLoader.allowArraySyntax". + // + // The default for 1.5 is "true", array syntax is allowed. In 1.6, the + // default will be "false". The presence of this system property to + // control array syntax allows applications the ability to preview this new + // behaviour. + // + private static boolean defaultAllowArraySyntax = false; + private static boolean allowArraySyntax = defaultAllowArraySyntax; + + // The allowArraySyntax boolean is initialized during system initialization + // in the saveAndRemoveProperties method. + // + // It is initialized based on the value of the system property + // "sun.lang.ClassLoader.allowArraySyntax". If the system property is not + // provided, the default for 1.5 is "true". In 1.6, the default will be + // "false". If the system property is provided, then the value of + // allowArraySyntax will be equal to "true" if Boolean.parseBoolean() + // returns "true". Otherwise, the field will be set to "false". + // + public static boolean allowArraySyntax() { + return allowArraySyntax; + } + + /** + * Returns true if the given class loader is in the system domain + * in which all permissions are granted. + */ + public static boolean isSystemDomainLoader(ClassLoader loader) { + return loader == null; + } + + /** + * Returns the system property of the specified key saved at + * system initialization time. This method should only be used + * for the system properties that are not changed during runtime. + * It accesses a private copy of the system properties so + * that user's locking of the system properties object will not + * cause the library to deadlock. + * + * Note that the saved system properties do not include + * the ones set by sun.misc.Version.init(). + * + */ + public static String getSavedProperty(String key) { + if (Lazy.savedProps.isEmpty()) + throw new IllegalStateException("Should be non-empty if initialized"); + + return Lazy.savedProps.getProperty(key); + } + + // TODO: the Property Management needs to be refactored and + // the appropriate prop keys need to be accessible to the + // calling classes to avoid duplication of keys. + static final class Lazy { + static final Properties savedProps = new Properties(); + } + + // Save a private copy of the system properties and remove + // the system properties that are not intended for public access. + // + // This method can only be invoked during system initialization. + public static void saveAndRemoveProperties(Properties props) { + if (booted) + throw new IllegalStateException("System initialization has completed"); + + Lazy.savedProps.putAll(props); + + // Set the maximum amount of direct memory. This value is controlled + // by the vm option -XX:MaxDirectMemorySize=. + // The maximum amount of allocatable direct buffer memory (in bytes) + // from the system property sun.nio.MaxDirectMemorySize set by the VM. + // The system property will be removed. + String s = (String)props.remove("sun.nio.MaxDirectMemorySize"); + // [IKVM] we don't support the -XX:MaxDirectMemorySize= option. + + // Check if direct buffers should be page aligned + s = (String)props.remove("sun.nio.PageAlignDirectMemory"); + if ("true".equals(s)) + pageAlignDirectMemory = true; + + // Set a boolean to determine whether ClassLoader.loadClass accepts + // array syntax. This value is controlled by the system property + // "sun.lang.ClassLoader.allowArraySyntax". + s = props.getProperty("sun.lang.ClassLoader.allowArraySyntax"); + allowArraySyntax = (s == null + ? defaultAllowArraySyntax + : Boolean.parseBoolean(s)); + + // Remove other private system properties + // used by java.lang.Integer.IntegerCache + props.remove("java.lang.Integer.IntegerCache.high"); + + // used by java.util.zip.ZipFile + props.remove("sun.zip.disableMemoryMapping"); + + // used by sun.launcher.LauncherHelper + props.remove("sun.java.launcher.diag"); + + // used by sun.misc.URLClassPath + props.remove("sun.cds.enableSharedLookupCache"); + } + + // Initialize any miscellenous operating system settings that need to be + // set for the class libraries. + // + public static void initializeOSEnvironment() { + } + + /* Current count of objects pending for finalization */ + private static volatile int finalRefCount = 0; + + /* Peak count of objects pending for finalization */ + private static volatile int peakFinalRefCount = 0; + + /* + * Gets the number of objects pending for finalization. + * + * @return the number of objects pending for finalization. + */ + public static int getFinalRefCount() { + return finalRefCount; + } + + /* + * Gets the peak number of objects pending for finalization. + * + * @return the peak number of objects pending for finalization. + */ + public static int getPeakFinalRefCount() { + return peakFinalRefCount; + } + + /* + * Add n to the objects pending for finalization count. + * + * @param n an integer value to be added to the objects pending + * for finalization count + */ + public static void addFinalRefCount(int n) { + // The caller must hold lock to synchronize the update. + + finalRefCount += n; + if (finalRefCount > peakFinalRefCount) { + peakFinalRefCount = finalRefCount; + } + } + + /** + * Returns Thread.State for the given threadStatus + */ + public static Thread.State toThreadState(int threadStatus) { + if ((threadStatus & JVMTI_THREAD_STATE_RUNNABLE) != 0) { + return RUNNABLE; + } else if ((threadStatus & JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER) != 0) { + return BLOCKED; + } else if ((threadStatus & JVMTI_THREAD_STATE_WAITING_INDEFINITELY) != 0) { + return WAITING; + } else if ((threadStatus & JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT) != 0) { + return TIMED_WAITING; + } else if ((threadStatus & JVMTI_THREAD_STATE_TERMINATED) != 0) { + return TERMINATED; + } else if ((threadStatus & JVMTI_THREAD_STATE_ALIVE) == 0) { + return NEW; + } else { + return RUNNABLE; + } + } + + /* The threadStatus field is set by the VM at state transition + * in the hotspot implementation. Its value is set according to + * the JVM TI specification GetThreadState function. + */ + private final static int JVMTI_THREAD_STATE_ALIVE = 0x0001; + private final static int JVMTI_THREAD_STATE_TERMINATED = 0x0002; + private final static int JVMTI_THREAD_STATE_RUNNABLE = 0x0004; + private final static int JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER = 0x0400; + private final static int JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010; + private final static int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020; + + /* + * Returns the first non-null class loader up the execution stack, + * or null if only code from the null class loader is on the stack. + */ + public static native ClassLoader latestUserDefinedLoader(); + + static { + initialize(); + } + private native static void initialize(); +} diff --git a/openjdk/sun/misc/Version.java b/openjdk/sun/misc/Version.java new file mode 100644 index 0000000..e11b367 --- /dev/null +++ b/openjdk/sun/misc/Version.java @@ -0,0 +1,345 @@ +/* + * Copyright (c) 1999, 2013, 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.misc; +import java.io.PrintStream; + +public class Version { + + + private static final String launcher_name = + "openjdk"; + + private static final String java_version = + "1.8.0-internal"; + + private static final String java_runtime_name = + "OpenJDK Runtime Environment"; + + private static final String java_profile_name = + ""; + + private static final String java_runtime_version = + "1.8.0-internal-jeroen_2015_06_02_10_38-b00"; + + static { + init(); + } + + public static void init() { + } + + private static boolean versionsInitialized = false; + private static int jvm_major_version = 0; + private static int jvm_minor_version = 0; + private static int jvm_micro_version = 0; + private static int jvm_update_version = 0; + private static int jvm_build_number = 0; + private static String jvm_special_version = null; + private static int jdk_major_version = 0; + private static int jdk_minor_version = 0; + private static int jdk_micro_version = 0; + private static int jdk_update_version = 0; + private static int jdk_build_number = 0; + private static String jdk_special_version = null; + + /** + * In case you were wondering this method is called by java -version. + * Sad that it prints to stderr; would be nicer if default printed on + * stdout. + */ + public static void print() { + print(System.err); + } + + /** + * This is the same as print except that it adds an extra line-feed + * at the end, typically used by the -showversion in the launcher + */ + public static void println() { + print(System.err); + System.err.println(); + } + + /** + * Give a stream, it will print version info on it. + */ + public static void print(PrintStream ps) { + boolean isHeadless = false; + + /* Report that we're running headless if the property is true */ + String headless = System.getProperty("java.awt.headless"); + if ( (headless != null) && (headless.equalsIgnoreCase("true")) ) { + isHeadless = true; + } + + /* First line: platform version. */ + ps.println(launcher_name + " version \"" + java_version + "\""); + + /* Second line: runtime version (ie, libraries). */ + + ps.print(java_runtime_name + " (build " + java_runtime_version); + + if (java_profile_name.length() > 0) { + // profile name + ps.print(", profile " + java_profile_name); + } + + if (java_runtime_name.indexOf("Embedded") != -1 && isHeadless) { + // embedded builds report headless state + ps.print(", headless"); + } + ps.println(')'); + + /* Third line: JVM information. */ + String java_vm_name = System.getProperty("java.vm.name"); + String java_vm_version = System.getProperty("java.vm.version"); + String java_vm_info = System.getProperty("java.vm.info"); + ps.println(java_vm_name + " (build " + java_vm_version + ", " + + java_vm_info + ")"); + } + + + /** + * Returns the major version of the running JVM if it's 1.6 or newer + * or any RE VM build. It will return 0 if it's an internal 1.5 or + * 1.4.x build. + * + * @since 1.6 + */ + public static synchronized int jvmMajorVersion() { + if (!versionsInitialized) { + initVersions(); + } + return jvm_major_version; + } + + /** + * Returns the minor version of the running JVM if it's 1.6 or newer + * or any RE VM build. It will return 0 if it's an internal 1.5 or + * 1.4.x build. + * @since 1.6 + */ + public static synchronized int jvmMinorVersion() { + if (!versionsInitialized) { + initVersions(); + } + return jvm_minor_version; + } + + + /** + * Returns the micro version of the running JVM if it's 1.6 or newer + * or any RE VM build. It will return 0 if it's an internal 1.5 or + * 1.4.x build. + * @since 1.6 + */ + public static synchronized int jvmMicroVersion() { + if (!versionsInitialized) { + initVersions(); + } + return jvm_micro_version; + } + + /** + * Returns the update release version of the running JVM if it's + * a RE build. It will return 0 if it's an internal build. + * @since 1.6 + */ + public static synchronized int jvmUpdateVersion() { + if (!versionsInitialized) { + initVersions(); + } + return jvm_update_version; + } + + public static synchronized String jvmSpecialVersion() { + if (!versionsInitialized) { + initVersions(); + } + if (jvm_special_version == null) { + jvm_special_version = getJvmSpecialVersion(); + } + return jvm_special_version; + } + public static native String getJvmSpecialVersion(); + + /** + * Returns the build number of the running JVM if it's a RE build + * It will return 0 if it's an internal build. + * @since 1.6 + */ + public static synchronized int jvmBuildNumber() { + if (!versionsInitialized) { + initVersions(); + } + return jvm_build_number; + } + + /** + * Returns the major version of the running JDK. + * + * @since 1.6 + */ + public static synchronized int jdkMajorVersion() { + if (!versionsInitialized) { + initVersions(); + } + return jdk_major_version; + } + + /** + * Returns the minor version of the running JDK. + * @since 1.6 + */ + public static synchronized int jdkMinorVersion() { + if (!versionsInitialized) { + initVersions(); + } + return jdk_minor_version; + } + + /** + * Returns the micro version of the running JDK. + * @since 1.6 + */ + public static synchronized int jdkMicroVersion() { + if (!versionsInitialized) { + initVersions(); + } + return jdk_micro_version; + } + + /** + * Returns the update release version of the running JDK if it's + * a RE build. It will return 0 if it's an internal build. + * @since 1.6 + */ + public static synchronized int jdkUpdateVersion() { + if (!versionsInitialized) { + initVersions(); + } + return jdk_update_version; + } + + public static synchronized String jdkSpecialVersion() { + if (!versionsInitialized) { + initVersions(); + } + if (jdk_special_version == null) { + jdk_special_version = getJdkSpecialVersion(); + } + return jdk_special_version; + } + public static native String getJdkSpecialVersion(); + + /** + * Returns the build number of the running JDK if it's a RE build + * It will return 0 if it's an internal build. + * @since 1.6 + */ + public static synchronized int jdkBuildNumber() { + if (!versionsInitialized) { + initVersions(); + } + return jdk_build_number; + } + + // true if JVM exports the version info including the capabilities + private static boolean jvmVersionInfoAvailable; + private static synchronized void initVersions() { + if (versionsInitialized) { + return; + } + jvmVersionInfoAvailable = getJvmVersionInfo(); + if (!jvmVersionInfoAvailable) { + // parse java.vm.version for older JVM before the + // new JVM_GetVersionInfo is added. + // valid format of the version string is: + // n.n.n[_uu[c]][-]-bxx + CharSequence cs = System.getProperty("java.vm.version"); + if (cs.length() >= 5 && + Character.isDigit(cs.charAt(0)) && cs.charAt(1) == '.' && + Character.isDigit(cs.charAt(2)) && cs.charAt(3) == '.' && + Character.isDigit(cs.charAt(4))) { + jvm_major_version = Character.digit(cs.charAt(0), 10); + jvm_minor_version = Character.digit(cs.charAt(2), 10); + jvm_micro_version = Character.digit(cs.charAt(4), 10); + cs = cs.subSequence(5, cs.length()); + if (cs.charAt(0) == '_' && cs.length() >= 3 && + Character.isDigit(cs.charAt(1)) && + Character.isDigit(cs.charAt(2))) { + int nextChar = 3; + try { + String uu = cs.subSequence(1, 3).toString(); + jvm_update_version = Integer.valueOf(uu).intValue(); + if (cs.length() >= 4) { + char c = cs.charAt(3); + if (c >= 'a' && c <= 'z') { + jvm_special_version = Character.toString(c); + nextChar++; + } + } + } catch (NumberFormatException e) { + // not conforming to the naming convention + return; + } + cs = cs.subSequence(nextChar, cs.length()); + } + if (cs.charAt(0) == '-') { + // skip the first character + // valid format: -bxx or bxx + // non-product VM will have -debug|-release appended + cs = cs.subSequence(1, cs.length()); + String[] res = cs.toString().split("-"); + for (String s : res) { + if (s.charAt(0) == 'b' && s.length() == 3 && + Character.isDigit(s.charAt(1)) && + Character.isDigit(s.charAt(2))) { + jvm_build_number = + Integer.valueOf(s.substring(1, 3)).intValue(); + break; + } + } + } + } + } + getJdkVersionInfo(); + versionsInitialized = true; + } + + // Gets the JVM version info if available and sets the jvm_*_version fields + // and its capabilities. + // + // Return false if not available which implies an old VM (Tiger or before). + private static native boolean getJvmVersionInfo(); + private static native void getJdkVersionInfo(); +} + +// Help Emacs a little because this file doesn't end in .java. +// +// Local Variables: *** +// mode: java *** +// End: *** diff --git a/openjdk/sun/net/dns/ResolverConfigurationImpl.java b/openjdk/sun/net/dns/ResolverConfigurationImpl.java new file mode 100644 index 0000000..d0e3acb --- /dev/null +++ b/openjdk/sun/net/dns/ResolverConfigurationImpl.java @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2002, 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.net.dns; + +import java.util.List; +import java.util.LinkedList; +import java.util.StringTokenizer; +import java.io.IOException; +import cli.System.Net.NetworkInformation.IPAddressCollection; +import cli.System.Net.NetworkInformation.IPInterfaceProperties; +import cli.System.Net.NetworkInformation.NetworkInterface; + +/* + * An implementation of sun.net.ResolverConfiguration for Windows. + */ + +public class ResolverConfigurationImpl + extends ResolverConfiguration +{ + // Lock helds whilst loading configuration or checking + private static Object lock = new Object(); + + // Resolver options + private final Options opts; + + // Addreses have changed + private static boolean changed = false; + + // Time of last refresh. + private static long lastRefresh = -1; + + // Cache timeout (120 seconds) - should be converted into property + // or configured as preference in the future. + private static final int TIMEOUT = 120000; + + // DNS suffix list and name servers populated by native method + private static String os_searchlist; + private static String os_nameservers; + + // Cached lists + private static LinkedList searchlist; + private static LinkedList nameservers; + + // Parse string that consists of token delimited by space or commas + // and return LinkedHashMap + private LinkedList stringToList(String str) { + LinkedList ll = new LinkedList<>(); + + // comma and space are valid delimites + StringTokenizer st = new StringTokenizer(str, ", "); + while (st.hasMoreTokens()) { + String s = st.nextToken(); + if (!ll.contains(s)) { + ll.add(s); + } + } + return ll; + } + + // Load DNS configuration from OS + + private void loadConfig() { + assert Thread.holdsLock(lock); + + // if address have changed then DNS probably changed aswell; + // otherwise check if cached settings have expired. + // + if (changed) { + changed = false; + } else { + if (lastRefresh >= 0) { + long currTime = System.currentTimeMillis(); + if ((currTime - lastRefresh) < TIMEOUT) { + return; + } + } + } + + // load DNS configuration, update timestamp, create + // new HashMaps from the loaded configuration + // + loadDNSconfig0(); + + lastRefresh = System.currentTimeMillis(); + searchlist = stringToList(os_searchlist); + nameservers = stringToList(os_nameservers); + os_searchlist = null; // can be GC'ed + os_nameservers = null; + } + + ResolverConfigurationImpl() { + opts = new OptionsImpl(); + } + + @SuppressWarnings("unchecked") // clone() + public List searchlist() { + synchronized (lock) { + loadConfig(); + + // List is mutable so return a shallow copy + return (List)searchlist.clone(); + } + } + + @SuppressWarnings("unchecked") // clone() + public List nameservers() { + synchronized (lock) { + loadConfig(); + + // List is mutable so return a shallow copy + return (List)nameservers.clone(); + } + } + + public Options options() { + return opts; + } + + // --- Address Change Listener + + static class AddressChangeListener extends Thread { + public void run() { + for (;;) { + // wait for configuration to change + if (notifyAddrChange0() != 0) + return; + synchronized (lock) { + changed = true; + } + } + } + } + + + // --- Native methods -- + + static void init0() { + } + + static void loadDNSconfig0() { + String searchlist = ""; + String nameservers = ""; + for (NetworkInterface iface : NetworkInterface.GetAllNetworkInterfaces()) { + IPInterfaceProperties props = iface.GetIPProperties(); + IPAddressCollection addresses = props.get_DnsAddresses(); + for (int i = 0; i < addresses.get_Count(); i++) { + cli.System.Net.IPAddress addr = addresses.get_Item(i); + // no IPv6 support + if (addr.get_AddressFamily().Value == cli.System.Net.Sockets.AddressFamily.InterNetwork) { + nameservers = strAppend(nameservers, addr.toString()); + } + } + try { + if (false) throw new cli.System.PlatformNotSupportedException(); + searchlist = strAppend(searchlist, props.get_DnsSuffix()); + } + catch (cli.System.PlatformNotSupportedException _) { + } + } + os_searchlist = searchlist; + os_nameservers = nameservers; + } + + private static String strAppend(String s, String app) { + if (s.equals("")) { + return app; + } + if (app.equals("")) { + return s; + } + return s + " " + app; + } + + static int notifyAddrChange0() { + // TODO we could use System.Net.NetworkInformation.NetworkChange to detect changes + return -1; + } + + static { + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("net"); + return null; + } + }); + init0(); + + // start the address listener thread + AddressChangeListener thr = new AddressChangeListener(); + thr.setDaemon(true); + thr.start(); + } +} + +/** + * Implementation of {@link ResolverConfiguration.Options} + */ +class OptionsImpl extends ResolverConfiguration.Options { +} diff --git a/openjdk/sun/net/sdp/SdpSupport.java b/openjdk/sun/net/sdp/SdpSupport.java new file mode 100644 index 0000000..9a7437e --- /dev/null +++ b/openjdk/sun/net/sdp/SdpSupport.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2010, 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.net.sdp; + +import java.io.IOException; +import java.io.FileDescriptor; + + +/** + * This class defines methods for creating SDP sockets or "converting" existing + * file descriptors, referencing (unbound) TCP sockets, to SDP. + */ + +public final class SdpSupport { + + private SdpSupport() { } + + /** + * Creates a SDP socket, returning file descriptor referencing the socket. + */ + public static FileDescriptor createSocket() throws IOException { + throw new UnsupportedOperationException("SDP not supported on this platform"); + } + + /** + * Converts an existing file descriptor, that references an unbound TCP socket, + * to SDP. + */ + public static void convertSocket(FileDescriptor fd) throws IOException { + throw new UnsupportedOperationException("SDP not supported on this platform"); + } +} diff --git a/openjdk/sun/net/www/protocol/file/FileURLConnection.java b/openjdk/sun/net/www/protocol/file/FileURLConnection.java new file mode 100644 index 0000000..43c94b3 --- /dev/null +++ b/openjdk/sun/net/www/protocol/file/FileURLConnection.java @@ -0,0 +1,238 @@ +/* + * Copyright (c) 1995, 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. + */ + +/** + * Open an file input stream given a URL. + * @author James Gosling + * @author Steven B. Byrne + */ + +package sun.net.www.protocol.file; + +import java.net.URL; +import java.net.FileNameMap; +import java.io.*; +import java.text.Collator; +import java.security.Permission; +import sun.net.*; +import sun.net.www.*; +import java.util.*; +import java.text.SimpleDateFormat; + +import sun.security.action.GetPropertyAction; +import sun.security.action.GetIntegerAction; +import sun.security.action.GetBooleanAction; + +public class FileURLConnection extends URLConnection { + + static String CONTENT_LENGTH = "content-length"; + static String CONTENT_TYPE = "content-type"; + static String TEXT_PLAIN = "text/plain"; + static String LAST_MODIFIED = "last-modified"; + + String contentType; + InputStream is; + + File file; + String filename; + boolean isDirectory = false; + boolean exists = false; + List files; + + long length = -1; + long lastModified = 0; + + protected FileURLConnection(URL u, File file) { + super(u); + this.file = file; + } + + /* + * Note: the semantics of FileURLConnection object is that the + * results of the various URLConnection calls, such as + * getContentType, getInputStream or getContentLength reflect + * whatever was true when connect was called. + */ + public void connect() throws IOException { + if (!connected) { + try { + filename = file.toString(); + isDirectory = file.isDirectory(); + if (isDirectory) { + String[] fileList = file.list(); + if (fileList == null) + throw new FileNotFoundException(filename + " exists, but is not accessible"); + files = Arrays.asList(fileList); + } else { + + is = new BufferedInputStream(new FileInputStream(filename)); + + // Check if URL should be metered + boolean meteredInput = ProgressMonitor.getDefault().shouldMeterInput(url, "GET"); + if (meteredInput) { + ProgressSource pi = new ProgressSource(url, "GET", file.length()); + is = new MeteredStream(is, pi, file.length()); + } + } + } catch (IOException e) { + throw e; + } + connected = true; + } + } + + private boolean initializedHeaders = false; + + private void initializeHeaders() { + try { + connect(); + exists = file.exists(); + } catch (IOException e) { + } + if (!initializedHeaders || !exists) { + length = file.length(); + lastModified = file.lastModified(); + + if (!isDirectory) { + FileNameMap map = java.net.URLConnection.getFileNameMap(); + contentType = map.getContentTypeFor(filename); + if (contentType != null) { + properties.add(CONTENT_TYPE, contentType); + } + properties.add(CONTENT_LENGTH, String.valueOf(length)); + + /* + * Format the last-modified field into the preferred + * Internet standard - ie: fixed-length subset of that + * defined by RFC 1123 + */ + if (lastModified != 0) { + Date date = new Date(lastModified); + SimpleDateFormat fo = + new SimpleDateFormat ("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US); + fo.setTimeZone(TimeZone.getTimeZone("GMT")); + properties.add(LAST_MODIFIED, fo.format(date)); + } + } else { + properties.add(CONTENT_TYPE, TEXT_PLAIN); + } + initializedHeaders = true; + } + } + + public String getHeaderField(String name) { + initializeHeaders(); + return super.getHeaderField(name); + } + + public String getHeaderField(int n) { + initializeHeaders(); + return super.getHeaderField(n); + } + + public int getContentLength() { + initializeHeaders(); + if (length > Integer.MAX_VALUE) + return -1; + return (int) length; + } + + public long getContentLengthLong() { + initializeHeaders(); + return length; + } + + public String getHeaderFieldKey(int n) { + initializeHeaders(); + return super.getHeaderFieldKey(n); + } + + public MessageHeader getProperties() { + initializeHeaders(); + return super.getProperties(); + } + + public long getLastModified() { + initializeHeaders(); + return lastModified; + } + + public synchronized InputStream getInputStream() + throws IOException { + + int iconHeight; + int iconWidth; + + connect(); + + if (is == null) { + if (isDirectory) { + FileNameMap map = java.net.URLConnection.getFileNameMap(); + + StringBuffer buf = new StringBuffer(); + + if (files == null) { + throw new FileNotFoundException(filename); + } + + sort(files); + + for (int i = 0 ; i < files.size() ; i++) { + String fileName = files.get(i); + buf.append(fileName); + buf.append("\n"); + } + // Put it into a (default) locale-specific byte-stream. + is = new ByteArrayInputStream(buf.toString().getBytes()); + } else { + throw new FileNotFoundException(filename); + } + } + return is; + } + + // IKVM specific method (sorting moved here to delay java.text.Collator dependency) + private static void sort(List files) { + Collections.sort(files, Collator.getInstance()); + } + + Permission permission; + + /* since getOutputStream isn't supported, only read permission is + * relevant + */ + public Permission getPermission() throws IOException { + if (permission == null) { + String decodedPath = ParseUtil.decode(url.getPath()); + if (File.separatorChar == '/') { + permission = new FilePermission(decodedPath, "read"); + } else { + permission = new FilePermission( + decodedPath.replace('/',File.separatorChar), "read"); + } + } + return permission; + } +} diff --git a/openjdk/sun/net/www/protocol/file/Handler.java b/openjdk/sun/net/www/protocol/file/Handler.java new file mode 100644 index 0000000..88688c3 --- /dev/null +++ b/openjdk/sun/net/www/protocol/file/Handler.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 1999, 2003, 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.net.www.protocol.file; + +import java.net.InetAddress; +import java.net.URLConnection; +import java.net.URL; +import java.net.Proxy; +import java.net.MalformedURLException; +import java.net.URLStreamHandler; +import java.io.InputStream; +import java.io.IOException; +import sun.net.www.ParseUtil; +import java.io.File; + +/** + * Open an file input stream given a URL. + * @author James Gosling + */ +public class Handler extends URLStreamHandler { + + private String getHost(URL url) { + String host = url.getHost(); + if (host == null) + host = ""; + return host; + } + + + protected void parseURL(URL u, String spec, int start, int limit) { + /* + * Ugly backwards compatibility. Flip any file separator + * characters to be forward slashes. This is a nop on Unix + * and "fixes" win32 file paths. According to RFC 2396, + * only forward slashes may be used to represent hierarchy + * separation in a URL but previous releases unfortunately + * performed this "fixup" behavior in the file URL parsing code + * rather than forcing this to be fixed in the caller of the URL + * class where it belongs. Since backslash is an "unwise" + * character that would normally be encoded if literally intended + * as a non-seperator character the damage of veering away from the + * specification is presumably limited. + */ + super.parseURL(u, spec.replace(File.separatorChar, '/'), start, limit); + } + + public synchronized URLConnection openConnection(URL url) + throws IOException { + return openConnection(url, null); + } + + public synchronized URLConnection openConnection(URL url, Proxy p) + throws IOException { + + String path; + String file = url.getFile(); + String host = url.getHost(); + + if (ikvm.internal.Util.WINDOWS) { + path = ParseUtil.decode(file); + path = path.replace('/', '\\'); + path = path.replace('|', ':'); + } else { + path = ParseUtil.decode(url.getPath()); + } + + if ((host == null) || host.equals("") || + host.equalsIgnoreCase("localhost") || + host.equals("~")) { + return createFileURLConnection(url, new File(path)); + } + + /* + * attempt to treat this as a UNC path. See 4180841 + */ + if (ikvm.internal.Util.WINDOWS) { + path = "\\\\" + host + path; + File f = new File(path); + if (f.exists()) { + return createFileURLConnection(url, f); + } + } + + /* + * Now attempt an ftp connection. + */ + URLConnection uc; + URL newurl; + + try { + newurl = new URL("ftp", host, file + + (url.getRef() == null ? "": + "#" + url.getRef())); + if (p != null) { + uc = newurl.openConnection(p); + } else { + uc = newurl.openConnection(); + } + } catch (IOException e) { + uc = null; + } + if (uc == null) { + throw new IOException("Unable to connect to: " + + url.toExternalForm()); + } + return uc; + } + + /** + * Template method to be overriden by Java Plug-in. [stanleyh] + */ + protected URLConnection createFileURLConnection(URL url, File file) { + return new FileURLConnection(url, file); + } + + /** + * Compares the host components of two URLs. + * @param u1 the URL of the first host to compare + * @param u2 the URL of the second host to compare + * @return true if and only if they + * are equal, false otherwise. + */ + protected boolean hostsEqual(URL u1, URL u2) { + /* + * Special case for file: URLs + * per RFC 1738 no hostname is equivalent to 'localhost' + * i.e. file:///path is equal to file://localhost/path + */ + String s1 = u1.getHost(); + String s2 = u2.getHost(); + if ("localhost".equalsIgnoreCase(s1) && ( s2 == null || "".equals(s2))) + return true; + if ("localhost".equalsIgnoreCase(s2) && ( s1 == null || "".equals(s1))) + return true; + return super.hostsEqual(u1, u2); + } +} diff --git a/openjdk/sun/net/www/protocol/ikvmres/Handler.java b/openjdk/sun/net/www/protocol/ikvmres/Handler.java new file mode 100644 index 0000000..972ca31 --- /dev/null +++ b/openjdk/sun/net/www/protocol/ikvmres/Handler.java @@ -0,0 +1,29 @@ +/* + Copyright (C) 2007 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package sun.net.www.protocol.ikvmres; + +public class Handler extends gnu.java.net.protocol.ikvmres.Handler +{ +} diff --git a/openjdk/sun/net/www/protocol/jar/JarFileFactory.java b/openjdk/sun/net/www/protocol/jar/JarFileFactory.java new file mode 100644 index 0000000..e1f8541 --- /dev/null +++ b/openjdk/sun/net/www/protocol/jar/JarFileFactory.java @@ -0,0 +1,184 @@ +/* + * Copyright (c) 1999, 2013, 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. + */ + +/*IKVM*/ +/* + * Modified for IKVM by Jeroen Frijters on May 22, 2007. + * + * This is a merged version of the Windows & Solaris platform specific versions. + * Since the IKVM class library binary can be used both on Windows and on *nix, + * I've merged the platform specific classes into a generic class that at + * runtime determines if it runs on Windows or not. + * +/*IKVM*/ + +package sun.net.www.protocol.jar; + +import java.io.IOException; +import java.io.FileNotFoundException; +import java.net.URL; +import java.net.URLConnection; +import java.util.HashMap; +import java.util.jar.JarFile; +import java.security.Permission; +import sun.net.util.URLUtil; + +/* A factory for cached JAR file. This class is used to both retrieve + * and cache Jar files. + * + * @author Benjamin Renaud + * @since JDK1.2 + */ +class JarFileFactory implements URLJarFile.URLJarFileCloseController { + + /* the url to file cache */ + private static final HashMap fileCache = new HashMap<>(); + + /* the file to url cache */ + private static final HashMap urlCache = new HashMap<>(); + + private static final JarFileFactory instance = new JarFileFactory(); + + private JarFileFactory() { } + + public static JarFileFactory getInstance() { + return instance; + } + + URLConnection getConnection(JarFile jarFile) throws IOException { + URL u; + synchronized (instance) { + u = urlCache.get(jarFile); + } + if (u != null) + return u.openConnection(); + + return null; + } + + public JarFile get(URL url) throws IOException { + return get(url, true); + } + + JarFile get(URL url, boolean useCaches) throws IOException { + if (ikvm.internal.Util.WINDOWS && url.getProtocol().equalsIgnoreCase("file")) { + // Deal with UNC pathnames specially. See 4180841 + + String host = url.getHost(); + if (host != null && !host.equals("") && + !host.equalsIgnoreCase("localhost")) { + + url = new URL("file", "", "//" + host + url.getPath()); + } + } + + JarFile result; + JarFile local_result; + + if (useCaches) { + synchronized (instance) { + result = getCachedJarFile(url); + } + if (result == null) { + local_result = URLJarFile.getJarFile(url, this); + synchronized (instance) { + result = getCachedJarFile(url); + if (result == null) { + fileCache.put(URLUtil.urlNoFragString(url), local_result); + urlCache.put(local_result, url); + result = local_result; + } else { + if (local_result != null) { + local_result.close(); + } + } + } + } + } else { + result = URLJarFile.getJarFile(url, this); + } + if (result == null) + throw new FileNotFoundException(url.toString()); + + return result; + } + + /** + * Callback method of the URLJarFileCloseController to + * indicate that the JarFile is close. This way we can + * remove the JarFile from the cache + */ + public void close(JarFile jarFile) { + synchronized (instance) { + URL urlRemoved = urlCache.remove(jarFile); + if (urlRemoved != null) + fileCache.remove(URLUtil.urlNoFragString(urlRemoved)); + } + } + + private JarFile getCachedJarFile(URL url) { + assert Thread.holdsLock(instance); + JarFile result = fileCache.get(URLUtil.urlNoFragString(url)); + + /* if the JAR file is cached, the permission will always be there */ + if (result != null) { + Permission perm = getPermission(result); + if (perm != null) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + try { + sm.checkPermission(perm); + } catch (SecurityException se) { + // fallback to checkRead/checkConnect for pre 1.2 + // security managers + if ((perm instanceof java.io.FilePermission) && + perm.getActions().indexOf("read") != -1) { + sm.checkRead(perm.getName()); + } else if ((perm instanceof + java.net.SocketPermission) && + perm.getActions().indexOf("connect") != -1) { + sm.checkConnect(url.getHost(), url.getPort()); + } else { + throw se; + } + } + } + } + } + return result; + } + + private Permission getPermission(JarFile jarFile) { + try { + URLConnection uc = getConnection(jarFile); + if (uc != null) + return uc.getPermission(); + } catch (IOException ioe) { + // gulp + } + + return null; + } +} diff --git a/openjdk/sun/nio/ch/DatagramChannelImpl.java b/openjdk/sun/nio/ch/DatagramChannelImpl.java new file mode 100644 index 0000000..b2c8607 --- /dev/null +++ b/openjdk/sun/nio/ch/DatagramChannelImpl.java @@ -0,0 +1,1143 @@ +/* + * Copyright (c) 2001, 2013, 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.nio.ch; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.net.*; +import java.nio.ByteBuffer; +import java.nio.channels.*; +import java.nio.channels.spi.*; +import java.util.*; +import sun.net.ResourceManager; +import sun.net.ExtendedOptionsImpl; + +/** + * An implementation of DatagramChannels. + */ + +class DatagramChannelImpl + extends DatagramChannel + implements SelChImpl +{ + + // Used to make native read and write calls + private static NativeDispatcher nd = new SocketDispatcher(); + + // Our file descriptor + private final FileDescriptor fd; + + // fd value needed for dev/poll. This value will remain valid + // even after the value in the file descriptor object has been set to -1 + private final int fdVal; + + // The protocol family of the socket + private final ProtocolFamily family; + + // IDs of native threads doing reads and writes, for signalling + private volatile long readerThread = 0; + private volatile long writerThread = 0; + + // Cached InetAddress and port for unconnected DatagramChannels + // used by receive0 + private InetAddress cachedSenderInetAddress; + private int cachedSenderPort; + + // Lock held by current reading or connecting thread + private final Object readLock = new Object(); + + // Lock held by current writing or connecting thread + private final Object writeLock = new Object(); + + // Lock held by any thread that modifies the state fields declared below + // DO NOT invoke a blocking I/O operation while holding this lock! + private final Object stateLock = new Object(); + + // -- The following fields are protected by stateLock + + // State (does not necessarily increase monotonically) + private static final int ST_UNINITIALIZED = -1; + private static final int ST_UNCONNECTED = 0; + private static final int ST_CONNECTED = 1; + private static final int ST_KILLED = 2; + private int state = ST_UNINITIALIZED; + + // Binding + private InetSocketAddress localAddress; + private InetSocketAddress remoteAddress; + + // Our socket adaptor, if any + private DatagramSocket socket; + + // Multicast support + private MembershipRegistry registry; + + // set true when socket is bound and SO_REUSEADDRESS is emulated + private boolean reuseAddressEmulated; + + // set true/false when socket is already bound and SO_REUSEADDR is emulated + private boolean isReuseAddress; + + // -- End of fields protected by stateLock + + + public DatagramChannelImpl(SelectorProvider sp) + throws IOException + { + super(sp); + ResourceManager.beforeUdpCreate(); + try { + this.family = Net.isIPv6Available() ? + StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; + this.fd = Net.socket(family, false); + this.fdVal = IOUtil.fdVal(fd); + this.state = ST_UNCONNECTED; + } catch (IOException ioe) { + ResourceManager.afterUdpClose(); + throw ioe; + } + } + + public DatagramChannelImpl(SelectorProvider sp, ProtocolFamily family) + throws IOException + { + super(sp); + if ((family != StandardProtocolFamily.INET) && + (family != StandardProtocolFamily.INET6)) + { + if (family == null) + throw new NullPointerException("'family' is null"); + else + throw new UnsupportedOperationException("Protocol family not supported"); + } + if (family == StandardProtocolFamily.INET6) { + if (!Net.isIPv6Available()) { + throw new UnsupportedOperationException("IPv6 not available"); + } + } + this.family = family; + this.fd = Net.socket(family, false); + this.fdVal = IOUtil.fdVal(fd); + this.state = ST_UNCONNECTED; + } + + public DatagramChannelImpl(SelectorProvider sp, FileDescriptor fd) + throws IOException + { + super(sp); + this.family = Net.isIPv6Available() ? + StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; + this.fd = fd; + this.fdVal = IOUtil.fdVal(fd); + this.state = ST_UNCONNECTED; + this.localAddress = Net.localAddress(fd); + } + + public DatagramSocket socket() { + synchronized (stateLock) { + if (socket == null) + socket = DatagramSocketAdaptor.create(this); + return socket; + } + } + + @Override + public SocketAddress getLocalAddress() throws IOException { + synchronized (stateLock) { + if (!isOpen()) + throw new ClosedChannelException(); + // Perform security check before returning address + return Net.getRevealedLocalAddress(localAddress); + } + } + + @Override + public SocketAddress getRemoteAddress() throws IOException { + synchronized (stateLock) { + if (!isOpen()) + throw new ClosedChannelException(); + return remoteAddress; + } + } + + @Override + public DatagramChannel setOption(SocketOption name, T value) + throws IOException + { + if (name == null) + throw new NullPointerException(); + if (!supportedOptions().contains(name)) + throw new UnsupportedOperationException("'" + name + "' not supported"); + + synchronized (stateLock) { + ensureOpen(); + + if (name == StandardSocketOptions.IP_TOS || + name == StandardSocketOptions.IP_MULTICAST_TTL || + name == StandardSocketOptions.IP_MULTICAST_LOOP) + { + // options are protocol dependent + Net.setSocketOption(fd, family, name, value); + return this; + } + + if (name == StandardSocketOptions.IP_MULTICAST_IF) { + if (value == null) + throw new IllegalArgumentException("Cannot set IP_MULTICAST_IF to 'null'"); + NetworkInterface interf = (NetworkInterface)value; + if (family == StandardProtocolFamily.INET6) { + int index = interf.getIndex(); + if (index == -1) + throw new IOException("Network interface cannot be identified"); + Net.setInterface6(fd, index); + } else { + // need IPv4 address to identify interface + Inet4Address target = Net.anyInet4Address(interf); + if (target == null) + throw new IOException("Network interface not configured for IPv4"); + int targetAddress = Net.inet4AsInt(target); + Net.setInterface4(fd, targetAddress); + } + return this; + } + if (name == StandardSocketOptions.SO_REUSEADDR && + Net.useExclusiveBind() && localAddress != null) + { + reuseAddressEmulated = true; + this.isReuseAddress = (Boolean)value; + } + + // remaining options don't need any special handling + Net.setSocketOption(fd, Net.UNSPEC, name, value); + return this; + } + } + + @Override + @SuppressWarnings("unchecked") + public T getOption(SocketOption name) + throws IOException + { + if (name == null) + throw new NullPointerException(); + if (!supportedOptions().contains(name)) + throw new UnsupportedOperationException("'" + name + "' not supported"); + + synchronized (stateLock) { + ensureOpen(); + + if (name == StandardSocketOptions.IP_TOS || + name == StandardSocketOptions.IP_MULTICAST_TTL || + name == StandardSocketOptions.IP_MULTICAST_LOOP) + { + return (T) Net.getSocketOption(fd, family, name); + } + + if (name == StandardSocketOptions.IP_MULTICAST_IF) { + if (family == StandardProtocolFamily.INET) { + int address = Net.getInterface4(fd); + if (address == 0) + return null; // default interface + + InetAddress ia = Net.inet4FromInt(address); + NetworkInterface ni = NetworkInterface.getByInetAddress(ia); + if (ni == null) + throw new IOException("Unable to map address to interface"); + return (T) ni; + } else { + int index = Net.getInterface6(fd); + if (index == 0) + return null; // default interface + + NetworkInterface ni = NetworkInterface.getByIndex(index); + if (ni == null) + throw new IOException("Unable to map index to interface"); + return (T) ni; + } + } + + if (name == StandardSocketOptions.SO_REUSEADDR && + reuseAddressEmulated) + { + return (T)Boolean.valueOf(isReuseAddress); + } + + // no special handling + return (T) Net.getSocketOption(fd, Net.UNSPEC, name); + } + } + + private static class DefaultOptionsHolder { + static final Set> defaultOptions = defaultOptions(); + + private static Set> defaultOptions() { + HashSet> set = new HashSet>(8); + set.add(StandardSocketOptions.SO_SNDBUF); + set.add(StandardSocketOptions.SO_RCVBUF); + set.add(StandardSocketOptions.SO_REUSEADDR); + set.add(StandardSocketOptions.SO_BROADCAST); + set.add(StandardSocketOptions.IP_TOS); + set.add(StandardSocketOptions.IP_MULTICAST_IF); + set.add(StandardSocketOptions.IP_MULTICAST_TTL); + set.add(StandardSocketOptions.IP_MULTICAST_LOOP); + if (ExtendedOptionsImpl.flowSupported()) { + set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); + } + return Collections.unmodifiableSet(set); + } + } + + @Override + public final Set> supportedOptions() { + return DefaultOptionsHolder.defaultOptions; + } + + private void ensureOpen() throws ClosedChannelException { + if (!isOpen()) + throw new ClosedChannelException(); + } + + SocketAddress sender; // Set by receive0 (## ugh) + + public SocketAddress receive(ByteBuffer dst) throws IOException { + if (dst.isReadOnly()) + throw new IllegalArgumentException("Read-only buffer"); + if (dst == null) + throw new NullPointerException(); + synchronized (readLock) { + ensureOpen(); + // Socket was not bound before attempting receive + if (localAddress() == null) + bind(null); + int n = 0; + ByteBuffer bb = null; + try { + begin(); + if (!isOpen()) + return null; + SecurityManager security = System.getSecurityManager(); + readerThread = NativeThread.current(); + if (isConnected() || (security == null)) { + do { + n = receive(fd, dst); + } while ((n == IOStatus.INTERRUPTED) && isOpen()); + if (n == IOStatus.UNAVAILABLE) + return null; + } else { + bb = ByteBuffer.allocate(dst.remaining()); + for (;;) { + do { + n = receive(fd, bb); + } while ((n == IOStatus.INTERRUPTED) && isOpen()); + if (n == IOStatus.UNAVAILABLE) + return null; + InetSocketAddress isa = (InetSocketAddress)sender; + try { + security.checkAccept( + isa.getAddress().getHostAddress(), + isa.getPort()); + } catch (SecurityException se) { + // Ignore packet + bb.clear(); + n = 0; + continue; + } + bb.flip(); + dst.put(bb); + break; + } + } + return sender; + } finally { + readerThread = 0; + end((n > 0) || (n == IOStatus.UNAVAILABLE)); + assert IOStatus.check(n); + } + } + } + + private int receive(FileDescriptor fd, ByteBuffer dst) + throws IOException + { + int pos = dst.position(); + int lim = dst.limit(); + assert (pos <= lim); + int rem = (pos <= lim ? lim - pos : 0); + if (dst.hasArray() && rem > 0) + return receiveIntoManagedBuffer(fd, dst, rem, pos); + + // Substitute a managed buffer. If the supplied buffer is empty + // we must instead use a nonempty buffer, otherwise the call + // will not block waiting for a datagram on some platforms. + int newSize = Math.max(rem, 1); + ByteBuffer bb = ByteBuffer.allocate(newSize); + try { + int n = receiveIntoManagedBuffer(fd, bb, newSize, 0); + bb.flip(); + if (n > 0 && rem > 0) + dst.put(bb); + return n; + } finally { + } + } + + private int receiveIntoManagedBuffer(FileDescriptor fd, ByteBuffer bb, + int rem, int pos) + throws IOException + { + int n = receive0(fd, bb.array(), bb.arrayOffset() + pos, rem, + isConnected()); + if (n > 0) + bb.position(pos + n); + return n; + } + + public int send(ByteBuffer src, SocketAddress target) + throws IOException + { + if (src == null) + throw new NullPointerException(); + + synchronized (writeLock) { + ensureOpen(); + InetSocketAddress isa = Net.checkAddress(target); + InetAddress ia = isa.getAddress(); + if (ia == null) + throw new IOException("Target address not resolved"); + synchronized (stateLock) { + if (!isConnected()) { + if (target == null) + throw new NullPointerException(); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + if (ia.isMulticastAddress()) { + sm.checkMulticast(ia); + } else { + sm.checkConnect(ia.getHostAddress(), + isa.getPort()); + } + } + } else { // Connected case; Check address then write + if (!target.equals(remoteAddress)) { + throw new IllegalArgumentException( + "Connected address not equal to target address"); + } + return write(src); + } + } + + int n = 0; + try { + begin(); + if (!isOpen()) + return 0; + writerThread = NativeThread.current(); + do { + n = send(fd, src, isa); + } while ((n == IOStatus.INTERRUPTED) && isOpen()); + + synchronized (stateLock) { + if (isOpen() && (localAddress == null)) { + localAddress = Net.localAddress(fd); + } + } + return IOStatus.normalize(n); + } finally { + writerThread = 0; + end((n > 0) || (n == IOStatus.UNAVAILABLE)); + assert IOStatus.check(n); + } + } + } + + private int send(FileDescriptor fd, ByteBuffer src, InetSocketAddress target) + throws IOException + { + if (src.hasArray()) + return sendFromManagedBuffer(fd, src, target); + + // Substitute a managed buffer + int pos = src.position(); + int lim = src.limit(); + assert (pos <= lim); + int rem = (pos <= lim ? lim - pos : 0); + + ByteBuffer bb = ByteBuffer.allocate(rem); + try { + bb.put(src); + bb.flip(); + // Do not update src until we see how many bytes were written + src.position(pos); + + int n = sendFromManagedBuffer(fd, bb, target); + if (n > 0) { + // now update src + src.position(pos + n); + } + return n; + } finally { + } + } + + private int sendFromManagedBuffer(FileDescriptor fd, ByteBuffer bb, + InetSocketAddress target) + throws IOException + { + int pos = bb.position(); + int lim = bb.limit(); + assert (pos <= lim); + int rem = (pos <= lim ? lim - pos : 0); + + boolean preferIPv6 = (family != StandardProtocolFamily.INET); + int written; + try { + written = send0(preferIPv6, fd, bb.array(), bb.arrayOffset() + pos, + rem, target.getAddress(), target.getPort()); + } catch (PortUnreachableException pue) { + if (isConnected()) + throw pue; + written = rem; + } + if (written > 0) + bb.position(pos + written); + return written; + } + + public int read(ByteBuffer buf) throws IOException { + if (buf == null) + throw new NullPointerException(); + synchronized (readLock) { + synchronized (stateLock) { + ensureOpen(); + if (!isConnected()) + throw new NotYetConnectedException(); + } + int n = 0; + try { + begin(); + if (!isOpen()) + return 0; + readerThread = NativeThread.current(); + do { + n = IOUtil.read(fd, buf, -1, nd); + } while ((n == IOStatus.INTERRUPTED) && isOpen()); + return IOStatus.normalize(n); + } finally { + readerThread = 0; + end((n > 0) || (n == IOStatus.UNAVAILABLE)); + assert IOStatus.check(n); + } + } + } + + public long read(ByteBuffer[] dsts, int offset, int length) + throws IOException + { + if ((offset < 0) || (length < 0) || (offset > dsts.length - length)) + throw new IndexOutOfBoundsException(); + synchronized (readLock) { + synchronized (stateLock) { + ensureOpen(); + if (!isConnected()) + throw new NotYetConnectedException(); + } + long n = 0; + try { + begin(); + if (!isOpen()) + return 0; + readerThread = NativeThread.current(); + do { + n = IOUtil.read(fd, dsts, offset, length, nd); + } while ((n == IOStatus.INTERRUPTED) && isOpen()); + return IOStatus.normalize(n); + } finally { + readerThread = 0; + end((n > 0) || (n == IOStatus.UNAVAILABLE)); + assert IOStatus.check(n); + } + } + } + + public int write(ByteBuffer buf) throws IOException { + if (buf == null) + throw new NullPointerException(); + synchronized (writeLock) { + synchronized (stateLock) { + ensureOpen(); + if (!isConnected()) + throw new NotYetConnectedException(); + } + int n = 0; + try { + begin(); + if (!isOpen()) + return 0; + writerThread = NativeThread.current(); + do { + n = IOUtil.write(fd, buf, -1, nd); + } while ((n == IOStatus.INTERRUPTED) && isOpen()); + return IOStatus.normalize(n); + } finally { + writerThread = 0; + end((n > 0) || (n == IOStatus.UNAVAILABLE)); + assert IOStatus.check(n); + } + } + } + + public long write(ByteBuffer[] srcs, int offset, int length) + throws IOException + { + if ((offset < 0) || (length < 0) || (offset > srcs.length - length)) + throw new IndexOutOfBoundsException(); + synchronized (writeLock) { + synchronized (stateLock) { + ensureOpen(); + if (!isConnected()) + throw new NotYetConnectedException(); + } + long n = 0; + try { + begin(); + if (!isOpen()) + return 0; + writerThread = NativeThread.current(); + do { + n = IOUtil.write(fd, srcs, offset, length, nd); + } while ((n == IOStatus.INTERRUPTED) && isOpen()); + return IOStatus.normalize(n); + } finally { + writerThread = 0; + end((n > 0) || (n == IOStatus.UNAVAILABLE)); + assert IOStatus.check(n); + } + } + } + + protected void implConfigureBlocking(boolean block) throws IOException { + IOUtil.configureBlocking(fd, block); + } + + public SocketAddress localAddress() { + synchronized (stateLock) { + return localAddress; + } + } + + public SocketAddress remoteAddress() { + synchronized (stateLock) { + return remoteAddress; + } + } + + @Override + public DatagramChannel bind(SocketAddress local) throws IOException { + synchronized (readLock) { + synchronized (writeLock) { + synchronized (stateLock) { + ensureOpen(); + if (localAddress != null) + throw new AlreadyBoundException(); + InetSocketAddress isa; + if (local == null) { + // only Inet4Address allowed with IPv4 socket + if (family == StandardProtocolFamily.INET) { + isa = new InetSocketAddress(InetAddress.getByName("0.0.0.0"), 0); + } else { + isa = new InetSocketAddress(0); + } + } else { + isa = Net.checkAddress(local); + + // only Inet4Address allowed with IPv4 socket + if (family == StandardProtocolFamily.INET) { + InetAddress addr = isa.getAddress(); + if (!(addr instanceof Inet4Address)) + throw new UnsupportedAddressTypeException(); + } + } + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkListen(isa.getPort()); + } + Net.bind(family, fd, isa.getAddress(), isa.getPort()); + localAddress = Net.localAddress(fd); + } + } + } + return this; + } + + public boolean isConnected() { + synchronized (stateLock) { + return (state == ST_CONNECTED); + } + } + + void ensureOpenAndUnconnected() throws IOException { // package-private + synchronized (stateLock) { + if (!isOpen()) + throw new ClosedChannelException(); + if (state != ST_UNCONNECTED) + throw new IllegalStateException("Connect already invoked"); + } + } + + @Override + public DatagramChannel connect(SocketAddress sa) throws IOException { + int localPort = 0; + + synchronized(readLock) { + synchronized(writeLock) { + synchronized (stateLock) { + ensureOpenAndUnconnected(); + InetSocketAddress isa = Net.checkAddress(sa); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkConnect(isa.getAddress().getHostAddress(), + isa.getPort()); + int n = Net.connect(family, + fd, + isa.getAddress(), + isa.getPort()); + if (n <= 0) + throw new Error(); // Can't happen + + // Connection succeeded; disallow further invocation + state = ST_CONNECTED; + remoteAddress = isa; + sender = isa; + cachedSenderInetAddress = isa.getAddress(); + cachedSenderPort = isa.getPort(); + + // set or refresh local address + localAddress = Net.localAddress(fd); + + // flush any packets already received. + boolean blocking = false; + synchronized (blockingLock()) { + try { + blocking = isBlocking(); + // remainder of each packet thrown away + ByteBuffer tmpBuf = ByteBuffer.allocate(1); + if (blocking) { + configureBlocking(false); + } + do { + tmpBuf.clear(); + } while (receive(tmpBuf) != null); + } finally { + if (blocking) { + configureBlocking(true); + } + } + } + } + } + } + return this; + } + + public DatagramChannel disconnect() throws IOException { + synchronized(readLock) { + synchronized(writeLock) { + synchronized (stateLock) { + if (!isConnected() || !isOpen()) + return this; + InetSocketAddress isa = remoteAddress; + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkConnect(isa.getAddress().getHostAddress(), + isa.getPort()); + boolean isIPv6 = (family == StandardProtocolFamily.INET6); + disconnect0(fd, isIPv6); + remoteAddress = null; + state = ST_UNCONNECTED; + + // refresh local address + localAddress = Net.localAddress(fd); + } + } + } + return this; + } + + /** + * Joins channel's socket to the given group/interface and + * optional source address. + */ + private MembershipKey innerJoin(InetAddress group, + NetworkInterface interf, + InetAddress source) + throws IOException + { + if (!group.isMulticastAddress()) + throw new IllegalArgumentException("Group not a multicast address"); + + // check multicast address is compatible with this socket + if (group instanceof Inet4Address) { + if (family == StandardProtocolFamily.INET6 && !Net.canIPv6SocketJoinIPv4Group()) + throw new IllegalArgumentException("IPv6 socket cannot join IPv4 multicast group"); + } else if (group instanceof Inet6Address) { + if (family != StandardProtocolFamily.INET6) + throw new IllegalArgumentException("Only IPv6 sockets can join IPv6 multicast group"); + } else { + throw new IllegalArgumentException("Address type not supported"); + } + + // check source address + if (source != null) { + if (source.isAnyLocalAddress()) + throw new IllegalArgumentException("Source address is a wildcard address"); + if (source.isMulticastAddress()) + throw new IllegalArgumentException("Source address is multicast address"); + if (source.getClass() != group.getClass()) + throw new IllegalArgumentException("Source address is different type to group"); + } + + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkMulticast(group); + + synchronized (stateLock) { + if (!isOpen()) + throw new ClosedChannelException(); + + // check the registry to see if we are already a member of the group + if (registry == null) { + registry = new MembershipRegistry(); + } else { + // return existing membership key + MembershipKey key = registry.checkMembership(group, interf, source); + if (key != null) + return key; + } + + MembershipKeyImpl key; + if ((family == StandardProtocolFamily.INET6) && + ((group instanceof Inet6Address) || Net.canJoin6WithIPv4Group())) + { + int index = interf.getIndex(); + if (index == -1) + throw new IOException("Network interface cannot be identified"); + + // need multicast and source address as byte arrays + byte[] groupAddress = Net.inet6AsByteArray(group); + byte[] sourceAddress = (source == null) ? null : + Net.inet6AsByteArray(source); + + // join the group + int n = Net.join6(fd, groupAddress, index, sourceAddress); + if (n == IOStatus.UNAVAILABLE) + throw new UnsupportedOperationException(); + + key = new MembershipKeyImpl.Type6(this, group, interf, source, + groupAddress, index, sourceAddress); + + } else { + // need IPv4 address to identify interface + Inet4Address target = Net.anyInet4Address(interf); + if (target == null) + throw new IOException("Network interface not configured for IPv4"); + + int groupAddress = Net.inet4AsInt(group); + int targetAddress = Net.inet4AsInt(target); + int sourceAddress = (source == null) ? 0 : Net.inet4AsInt(source); + + // join the group + int n = Net.join4(fd, groupAddress, targetAddress, sourceAddress); + if (n == IOStatus.UNAVAILABLE) + throw new UnsupportedOperationException(); + + key = new MembershipKeyImpl.Type4(this, group, interf, source, + groupAddress, targetAddress, sourceAddress); + } + + registry.add(key); + return key; + } + } + + @Override + public MembershipKey join(InetAddress group, + NetworkInterface interf) + throws IOException + { + return innerJoin(group, interf, null); + } + + @Override + public MembershipKey join(InetAddress group, + NetworkInterface interf, + InetAddress source) + throws IOException + { + if (source == null) + throw new NullPointerException("source address is null"); + return innerJoin(group, interf, source); + } + + // package-private + void drop(MembershipKeyImpl key) { + assert key.channel() == this; + + synchronized (stateLock) { + if (!key.isValid()) + return; + + try { + if (key instanceof MembershipKeyImpl.Type6) { + MembershipKeyImpl.Type6 key6 = + (MembershipKeyImpl.Type6)key; + Net.drop6(fd, key6.groupAddress(), key6.index(), key6.source()); + } else { + MembershipKeyImpl.Type4 key4 = (MembershipKeyImpl.Type4)key; + Net.drop4(fd, key4.groupAddress(), key4.interfaceAddress(), + key4.source()); + } + } catch (IOException ioe) { + // should not happen + throw new AssertionError(ioe); + } + + key.invalidate(); + registry.remove(key); + } + } + + /** + * Block datagrams from given source if a memory to receive all + * datagrams. + */ + void block(MembershipKeyImpl key, InetAddress source) + throws IOException + { + assert key.channel() == this; + assert key.sourceAddress() == null; + + synchronized (stateLock) { + if (!key.isValid()) + throw new IllegalStateException("key is no longer valid"); + if (source.isAnyLocalAddress()) + throw new IllegalArgumentException("Source address is a wildcard address"); + if (source.isMulticastAddress()) + throw new IllegalArgumentException("Source address is multicast address"); + if (source.getClass() != key.group().getClass()) + throw new IllegalArgumentException("Source address is different type to group"); + + int n; + if (key instanceof MembershipKeyImpl.Type6) { + MembershipKeyImpl.Type6 key6 = + (MembershipKeyImpl.Type6)key; + n = Net.block6(fd, key6.groupAddress(), key6.index(), + Net.inet6AsByteArray(source)); + } else { + MembershipKeyImpl.Type4 key4 = + (MembershipKeyImpl.Type4)key; + n = Net.block4(fd, key4.groupAddress(), key4.interfaceAddress(), + Net.inet4AsInt(source)); + } + if (n == IOStatus.UNAVAILABLE) { + // ancient kernel + throw new UnsupportedOperationException(); + } + } + } + + /** + * Unblock given source. + */ + void unblock(MembershipKeyImpl key, InetAddress source) { + assert key.channel() == this; + assert key.sourceAddress() == null; + + synchronized (stateLock) { + if (!key.isValid()) + throw new IllegalStateException("key is no longer valid"); + + try { + if (key instanceof MembershipKeyImpl.Type6) { + MembershipKeyImpl.Type6 key6 = + (MembershipKeyImpl.Type6)key; + Net.unblock6(fd, key6.groupAddress(), key6.index(), + Net.inet6AsByteArray(source)); + } else { + MembershipKeyImpl.Type4 key4 = + (MembershipKeyImpl.Type4)key; + Net.unblock4(fd, key4.groupAddress(), key4.interfaceAddress(), + Net.inet4AsInt(source)); + } + } catch (IOException ioe) { + // should not happen + throw new AssertionError(ioe); + } + } + } + + protected void implCloseSelectableChannel() throws IOException { + synchronized (stateLock) { + if (state != ST_KILLED) + nd.preClose(fd); + ResourceManager.afterUdpClose(); + + // if member of mulitcast group then invalidate all keys + if (registry != null) + registry.invalidateAll(); + + long th; + if ((th = readerThread) != 0) + NativeThread.signal(th); + if ((th = writerThread) != 0) + NativeThread.signal(th); + if (!isRegistered()) + kill(); + } + } + + public void kill() throws IOException { + synchronized (stateLock) { + if (state == ST_KILLED) + return; + if (state == ST_UNINITIALIZED) { + state = ST_KILLED; + return; + } + assert !isOpen() && !isRegistered(); + nd.close(fd); + state = ST_KILLED; + } + } + + /** + * Translates native poll revent set into a ready operation set + */ + public boolean translateReadyOps(int ops, int initialOps, + SelectionKeyImpl sk) { + int intOps = sk.nioInterestOps(); // Do this just once, it synchronizes + int oldOps = sk.nioReadyOps(); + int newOps = initialOps; + + if ((ops & Net.POLLNVAL) != 0) { + // This should only happen if this channel is pre-closed while a + // selection operation is in progress + // ## Throw an error if this channel has not been pre-closed + return false; + } + + if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) { + newOps = intOps; + sk.nioReadyOps(newOps); + return (newOps & ~oldOps) != 0; + } + + if (((ops & Net.POLLIN) != 0) && + ((intOps & SelectionKey.OP_READ) != 0)) + newOps |= SelectionKey.OP_READ; + + if (((ops & Net.POLLOUT) != 0) && + ((intOps & SelectionKey.OP_WRITE) != 0)) + newOps |= SelectionKey.OP_WRITE; + + sk.nioReadyOps(newOps); + return (newOps & ~oldOps) != 0; + } + + public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) { + return translateReadyOps(ops, sk.nioReadyOps(), sk); + } + + public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) { + return translateReadyOps(ops, 0, sk); + } + + // package-private + int poll(int events, long timeout) throws IOException { + assert Thread.holdsLock(blockingLock()) && !isBlocking(); + + synchronized (readLock) { + int n = 0; + try { + begin(); + synchronized (stateLock) { + if (!isOpen()) + return 0; + readerThread = NativeThread.current(); + } + n = Net.poll(fd, events, timeout); + } finally { + readerThread = 0; + end(n > 0); + } + return n; + } + } + + /** + * Translates an interest operation set into a native poll event set + */ + public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) { + int newOps = 0; + + if ((ops & SelectionKey.OP_READ) != 0) + newOps |= Net.POLLIN; + if ((ops & SelectionKey.OP_WRITE) != 0) + newOps |= Net.POLLOUT; + if ((ops & SelectionKey.OP_CONNECT) != 0) + newOps |= Net.POLLIN; + sk.selector.putEventOps(sk, newOps); + } + + public FileDescriptor getFD() { + return fd; + } + + public int getFDVal() { + return fdVal; + } + + + // -- Native methods -- + + private static native void initIDs(); + + private static native void disconnect0(FileDescriptor fd, boolean isIPv6) + throws IOException; + + private native int receive0(FileDescriptor fd, byte[] buf, int pos, int len, + boolean connected) + throws IOException; + + private native int send0(boolean preferIPv6, FileDescriptor fd, byte[] buf, int pos, + int len, InetAddress addr, int port) + throws IOException; + + static { + IOUtil.load(); + initIDs(); + } + +} diff --git a/openjdk/sun/nio/ch/DefaultSelectorProvider.java b/openjdk/sun/nio/ch/DefaultSelectorProvider.java new file mode 100644 index 0000000..8c5cf03 --- /dev/null +++ b/openjdk/sun/nio/ch/DefaultSelectorProvider.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2001, 2002, 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.nio.ch; + +import java.io.IOException; +import java.nio.channels.spi.AbstractSelector; +import java.nio.channels.spi.SelectorProvider; + + +/** + * Creates this platform's default SelectorProvider + */ + +public class DefaultSelectorProvider { + + /** + * Prevent instantiation. + */ + private DefaultSelectorProvider() { } + + /** + * Returns the default SelectorProvider. + */ + public static SelectorProvider create() { + return new SelectorProviderImpl() { + public AbstractSelector openSelector() throws IOException { + return new DotNetSelectorImpl(this); + } + }; + } + +} diff --git a/openjdk/sun/nio/ch/DotNetSelectorImpl.java b/openjdk/sun/nio/ch/DotNetSelectorImpl.java new file mode 100644 index 0000000..5f20394 --- /dev/null +++ b/openjdk/sun/nio/ch/DotNetSelectorImpl.java @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2002, 2007, 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. + */ + +// Parts Copyright (C) 2002-2007 Jeroen Frijters + +package sun.nio.ch; + +import cli.System.Net.Sockets.Socket; +import cli.System.Net.Sockets.SocketException; +import cli.System.Net.Sockets.AddressFamily; +import cli.System.Net.Sockets.SocketType; +import cli.System.Net.Sockets.ProtocolType; +import cli.System.Net.Sockets.SelectMode; +import cli.System.Collections.ArrayList; +import java.io.IOException; +import java.nio.channels.ClosedSelectorException; +import java.nio.channels.Pipe; +import java.nio.channels.SelectableChannel; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.spi.AbstractSelectableChannel; +import java.nio.channels.spi.AbstractSelector; +import java.nio.channels.spi.SelectorProvider; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +final class DotNetSelectorImpl extends SelectorImpl +{ + private ArrayList channelArray = new ArrayList(); + private long updateCount = 0; + + //Pipe used as a wakeup object. + private final Pipe wakeupPipe; + + // File descriptors corresponding to source and sink + private final Socket wakeupSourceFd, wakeupSinkFd; + + // Lock for interrupt triggering and clearing + private final Object interruptLock = new Object(); + private volatile boolean interruptTriggered = false; + + // class for fdMap entries + private final static class MapEntry + { + SelectionKeyImpl ski; + long updateCount = 0; + long clearedCount = 0; + MapEntry(SelectionKeyImpl ski) + { + this.ski = ski; + } + } + private final HashMap fdMap = new HashMap(); + + DotNetSelectorImpl(SelectorProvider sp) throws IOException + { + super(sp); + wakeupPipe = Pipe.open(); + wakeupSourceFd = ((SelChImpl)wakeupPipe.source()).getFD().getSocket(); + + // Disable the Nagle algorithm so that the wakeup is more immediate + SinkChannelImpl sink = (SinkChannelImpl)wakeupPipe.sink(); + (sink.sc).socket().setTcpNoDelay(true); + wakeupSinkFd = ((SelChImpl)sink).getFD().getSocket(); + } + + protected int doSelect(long timeout) throws IOException + { + if (channelArray == null) + throw new ClosedSelectorException(); + processDeregisterQueue(); + if (interruptTriggered) + { + resetWakeupSocket(); + return 0; + } + + ArrayList read = new ArrayList(); + ArrayList write = new ArrayList(); + ArrayList error = new ArrayList(); + for (int i = 0; i < channelArray.get_Count(); i++) + { + SelectionKeyImpl ski = (SelectionKeyImpl)channelArray.get_Item(i); + int ops = ski.interestOps(); + if (ski.channel() instanceof SocketChannelImpl) + { + // TODO there's a race condition here... + if (((SocketChannelImpl)ski.channel()).isConnected()) + { + ops &= SelectionKey.OP_READ | SelectionKey.OP_WRITE; + } + else + { + ops &= SelectionKey.OP_CONNECT; + } + } + if ((ops & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0) + { + read.Add(ski.getSocket()); + } + if ((ops & (SelectionKey.OP_WRITE | SelectionKey.OP_CONNECT)) != 0) + { + write.Add(ski.getSocket()); + } + if ((ops & SelectionKey.OP_CONNECT) != 0) + { + error.Add(ski.getSocket()); + } + } + read.Add(wakeupSourceFd); + try + { + begin(); + int microSeconds = 1000 * (int)Math.min(Integer.MAX_VALUE / 1000, timeout); + try + { + if (false) throw new SocketException(); + // FXBUG docs say that -1 is infinite timeout, but that doesn't appear to work + Socket.Select(read, write, error, timeout < 0 ? Integer.MAX_VALUE : microSeconds); + } + catch (SocketException _) + { + read.Clear(); + write.Clear(); + error.Clear(); + } + } + finally + { + end(); + } + processDeregisterQueue(); + int updated = updateSelectedKeys(read, write, error); + // Done with poll(). Set wakeupSocket to nonsignaled for the next run. + resetWakeupSocket(); + return updated; + } + + private int updateSelectedKeys(ArrayList read, ArrayList write, ArrayList error) + { + updateCount++; + int keys = processFDSet(updateCount, read, Net.POLLIN); + keys += processFDSet(updateCount, write, Net.POLLCONN | Net.POLLOUT); + keys += processFDSet(updateCount, error, Net.POLLIN | Net.POLLCONN | Net.POLLOUT); + return keys; + } + + private int processFDSet(long updateCount, ArrayList sockets, int rOps) + { + int numKeysUpdated = 0; + for (int i = 0; i < sockets.get_Count(); i++) + { + Socket desc = (Socket)sockets.get_Item(i); + if (desc == wakeupSourceFd) + { + synchronized (interruptLock) + { + interruptTriggered = true; + } + continue; + } + MapEntry me = fdMap.get(desc); + // If me is null, the key was deregistered in the previous + // processDeregisterQueue. + if (me == null) + continue; + SelectionKeyImpl sk = me.ski; + if (selectedKeys.contains(sk)) + { // Key in selected set + if (me.clearedCount != updateCount) + { + if (sk.channel.translateAndSetReadyOps(rOps, sk) && + (me.updateCount != updateCount)) + { + me.updateCount = updateCount; + numKeysUpdated++; + } + } + else + { // The readyOps have been set; now add + if (sk.channel.translateAndUpdateReadyOps(rOps, sk) && + (me.updateCount != updateCount)) + { + me.updateCount = updateCount; + numKeysUpdated++; + } + } + me.clearedCount = updateCount; + } + else + { // Key is not in selected set yet + if (me.clearedCount != updateCount) + { + sk.channel.translateAndSetReadyOps(rOps, sk); + if ((sk.nioReadyOps() & sk.nioInterestOps()) != 0) + { + selectedKeys.add(sk); + me.updateCount = updateCount; + numKeysUpdated++; + } + } + else + { // The readyOps have been set; now add + sk.channel.translateAndUpdateReadyOps(rOps, sk); + if ((sk.nioReadyOps() & sk.nioInterestOps()) != 0) + { + selectedKeys.add(sk); + me.updateCount = updateCount; + numKeysUpdated++; + } + } + me.clearedCount = updateCount; + } + } + return numKeysUpdated; + } + + protected void implClose() throws IOException + { + if (channelArray != null) + { + // prevent further wakeup + synchronized (interruptLock) { + interruptTriggered = true; + } + wakeupPipe.sink().close(); + wakeupPipe.source().close(); + for (int i = 0; i < channelArray.get_Count(); i++) + { // Deregister channels + SelectionKeyImpl ski = (SelectionKeyImpl)channelArray.get_Item(i); + deregister(ski); + SelectableChannel selch = ski.channel(); + if (!selch.isOpen() && !selch.isRegistered()) + ((SelChImpl)selch).kill(); + } + selectedKeys = null; + channelArray = null; + } + } + + protected void implRegister(SelectionKeyImpl ski) + { + channelArray.Add(ski); + fdMap.put(ski.getSocket(), new MapEntry(ski)); + keys.add(ski); + } + + protected void implDereg(SelectionKeyImpl ski) throws IOException + { + channelArray.Remove(ski); + fdMap.remove(ski.getSocket()); + keys.remove(ski); + selectedKeys.remove(ski); + deregister(ski); + SelectableChannel selch = ski.channel(); + if (!selch.isOpen() && !selch.isRegistered()) + { + ((SelChImpl)selch).kill(); + } + } + + public Selector wakeup() + { + synchronized (interruptLock) + { + if (!interruptTriggered) + { + setWakeupSocket(); + interruptTriggered = true; + } + } + return this; + } + + // Sets Windows wakeup socket to a signaled state. + private void setWakeupSocket() { + wakeupSinkFd.Send(new byte[1]); + } + + // Sets Windows wakeup socket to a non-signaled state. + private void resetWakeupSocket() { + synchronized (interruptLock) + { + if (interruptTriggered == false) + return; + resetWakeupSocket0(wakeupSourceFd); + interruptTriggered = false; + } + } + + private static void resetWakeupSocket0(Socket wakeupSourceFd) + { + while (wakeupSourceFd.get_Available() > 0) + { + wakeupSourceFd.Receive(new byte[1]); + } + } +} diff --git a/openjdk/sun/nio/ch/FileChannelImpl.java b/openjdk/sun/nio/ch/FileChannelImpl.java new file mode 100644 index 0000000..e0b4f8b --- /dev/null +++ b/openjdk/sun/nio/ch/FileChannelImpl.java @@ -0,0 +1,1145 @@ +/* + * Copyright (c) 2000, 2013, 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.nio.ch; + +import cli.Microsoft.Win32.SafeHandles.SafeFileHandle; +import cli.System.IntPtr; +import cli.System.IO.FileStream; +import cli.System.Runtime.InteropServices.DllImportAttribute; +import java.io.FileDescriptor; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.MappedByteBuffer; +import java.nio.channels.ClosedByInterruptException; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.channels.FileLockInterruptionException; +import java.nio.channels.NonReadableChannelException; +import java.nio.channels.NonWritableChannelException; +import java.nio.channels.OverlappingFileLockException; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.security.AccessController; +import java.util.ArrayList; +import java.util.List; + +import sun.misc.Cleaner; +import sun.security.action.GetPropertyAction; + +public class FileChannelImpl + extends FileChannel +{ + private static final boolean win32 = ikvm.internal.Util.WINDOWS; + + // Memory allocation size for mapping buffers + private static final long allocationGranularity = 64 * 1024; // HACK we're using a hard coded value here that works on all mainstream platforms + + // Used to make native read and write calls + private final FileDispatcher nd; + + // File descriptor + private final FileDescriptor fd; + + // File access mode (immutable) + private final boolean writable; + private final boolean readable; + private final boolean append; + + // Required to prevent finalization of creating stream (immutable) + private final Object parent; + + // The path of the referenced file + // (null if the parent stream is created with a file descriptor) + private final String path; + + // Thread-safe set of IDs of native threads, for signalling + private final NativeThreadSet threads = new NativeThreadSet(2); + + // Lock for operations involving position and size + private final Object positionLock = new Object(); + + private FileChannelImpl(FileDescriptor fd, String path, boolean readable, + boolean writable, boolean append, Object parent) + { + this.fd = fd; + this.readable = readable; + this.writable = writable; + this.append = append; + this.parent = parent; + this.path = path; + this.nd = new FileDispatcherImpl(append); + } + + // Used by FileInputStream.getChannel() and RandomAccessFile.getChannel() + public static FileChannel open(FileDescriptor fd, String path, + boolean readable, boolean writable, + Object parent) + { + return new FileChannelImpl(fd, path, readable, writable, false, parent); + } + + // Used by FileOutputStream.getChannel + public static FileChannel open(FileDescriptor fd, String path, + boolean readable, boolean writable, + boolean append, Object parent) + { + return new FileChannelImpl(fd, path, readable, writable, append, parent); + } + + private void ensureOpen() throws IOException { + if (!isOpen()) + throw new ClosedChannelException(); + } + + + // -- Standard channel operations -- + + protected void implCloseChannel() throws IOException { + // Release and invalidate any locks that we still hold + if (fileLockTable != null) { + for (FileLock fl: fileLockTable.removeAll()) { + synchronized (fl) { + if (fl.isValid()) { + nd.release(fd, fl.position(), fl.size()); + ((FileLockImpl)fl).invalidate(); + } + } + } + } + + // signal any threads blocked on this channel + threads.signalAndWait(); + + if (parent != null) { + + // Close the fd via the parent stream's close method. The parent + // will reinvoke our close method, which is defined in the + // superclass AbstractInterruptibleChannel, but the isOpen logic in + // that method will prevent this method from being reinvoked. + // + ((java.io.Closeable)parent).close(); + } else { + nd.close(fd); + } + + } + + public int read(ByteBuffer dst) throws IOException { + ensureOpen(); + if (!readable) + throw new NonReadableChannelException(); + synchronized (positionLock) { + int n = 0; + int ti = -1; + try { + begin(); + ti = threads.add(); + if (!isOpen()) + return 0; + do { + n = IOUtil.read(fd, dst, -1, nd); + } while ((n == IOStatus.INTERRUPTED) && isOpen()); + return IOStatus.normalize(n); + } finally { + threads.remove(ti); + end(n > 0); + assert IOStatus.check(n); + } + } + } + + public long read(ByteBuffer[] dsts, int offset, int length) + throws IOException + { + if ((offset < 0) || (length < 0) || (offset > dsts.length - length)) + throw new IndexOutOfBoundsException(); + ensureOpen(); + if (!readable) + throw new NonReadableChannelException(); + synchronized (positionLock) { + long n = 0; + int ti = -1; + try { + begin(); + ti = threads.add(); + if (!isOpen()) + return 0; + do { + n = IOUtil.read(fd, dsts, offset, length, nd); + } while ((n == IOStatus.INTERRUPTED) && isOpen()); + return IOStatus.normalize(n); + } finally { + threads.remove(ti); + end(n > 0); + assert IOStatus.check(n); + } + } + } + + public int write(ByteBuffer src) throws IOException { + ensureOpen(); + if (!writable) + throw new NonWritableChannelException(); + synchronized (positionLock) { + int n = 0; + int ti = -1; + try { + begin(); + ti = threads.add(); + if (!isOpen()) + return 0; + do { + n = IOUtil.write(fd, src, -1, nd); + } while ((n == IOStatus.INTERRUPTED) && isOpen()); + return IOStatus.normalize(n); + } finally { + threads.remove(ti); + end(n > 0); + assert IOStatus.check(n); + } + } + } + + public long write(ByteBuffer[] srcs, int offset, int length) + throws IOException + { + if ((offset < 0) || (length < 0) || (offset > srcs.length - length)) + throw new IndexOutOfBoundsException(); + ensureOpen(); + if (!writable) + throw new NonWritableChannelException(); + synchronized (positionLock) { + long n = 0; + int ti = -1; + try { + begin(); + ti = threads.add(); + if (!isOpen()) + return 0; + do { + n = IOUtil.write(fd, srcs, offset, length, nd); + } while ((n == IOStatus.INTERRUPTED) && isOpen()); + return IOStatus.normalize(n); + } finally { + threads.remove(ti); + end(n > 0); + assert IOStatus.check(n); + } + } + } + + // -- Other operations -- + + public long position() throws IOException { + ensureOpen(); + synchronized (positionLock) { + long p = -1; + int ti = -1; + try { + begin(); + ti = threads.add(); + if (!isOpen()) + return 0; + do { + // in append-mode then position is advanced to end before writing + p = (append) ? nd.size(fd) : position0(fd, -1); + } while ((p == IOStatus.INTERRUPTED) && isOpen()); + return IOStatus.normalize(p); + } finally { + threads.remove(ti); + end(p > -1); + assert IOStatus.check(p); + } + } + } + + public FileChannel position(long newPosition) throws IOException { + ensureOpen(); + if (newPosition < 0) + throw new IllegalArgumentException(); + synchronized (positionLock) { + long p = -1; + int ti = -1; + try { + begin(); + ti = threads.add(); + if (!isOpen()) + return null; + do { + p = position0(fd, newPosition); + } while ((p == IOStatus.INTERRUPTED) && isOpen()); + return this; + } finally { + threads.remove(ti); + end(p > -1); + assert IOStatus.check(p); + } + } + } + + public long size() throws IOException { + ensureOpen(); + synchronized (positionLock) { + long s = -1; + int ti = -1; + try { + begin(); + ti = threads.add(); + if (!isOpen()) + return -1; + do { + s = nd.size(fd); + } while ((s == IOStatus.INTERRUPTED) && isOpen()); + return IOStatus.normalize(s); + } finally { + threads.remove(ti); + end(s > -1); + assert IOStatus.check(s); + } + } + } + + public FileChannel truncate(long newSize) throws IOException { + ensureOpen(); + if (newSize < 0) + throw new IllegalArgumentException("Negative size"); + if (!writable) + throw new NonWritableChannelException(); + synchronized (positionLock) { + int rv = -1; + long p = -1; + int ti = -1; + try { + begin(); + ti = threads.add(); + if (!isOpen()) + return null; + + // get current size + long size; + do { + size = nd.size(fd); + } while ((size == IOStatus.INTERRUPTED) && isOpen()); + if (!isOpen()) + return null; + + // get current position + do { + p = position0(fd, -1); + } while ((p == IOStatus.INTERRUPTED) && isOpen()); + if (!isOpen()) + return null; + assert p >= 0; + + // truncate file if given size is less than the current size + if (newSize < size) { + do { + rv = nd.truncate(fd, newSize); + } while ((rv == IOStatus.INTERRUPTED) && isOpen()); + if (!isOpen()) + return null; + } + + // [IKVM] in append mode we're not allowed to seek backwards, but the atomic append will honor the new file size + if (append) + return this; + + // if position is beyond new size then adjust it + if (p > newSize) + p = newSize; + do { + rv = (int)position0(fd, p); + } while ((rv == IOStatus.INTERRUPTED) && isOpen()); + return this; + } finally { + threads.remove(ti); + end(rv > -1); + assert IOStatus.check(rv); + } + } + } + + public void force(boolean metaData) throws IOException { + ensureOpen(); + int rv = -1; + int ti = -1; + try { + begin(); + ti = threads.add(); + if (!isOpen()) + return; + do { + rv = nd.force(fd, metaData); + } while ((rv == IOStatus.INTERRUPTED) && isOpen()); + } finally { + threads.remove(ti); + end(rv > -1); + assert IOStatus.check(rv); + } + } + + private long transferToArbitraryChannel(long position, int icount, + WritableByteChannel target) + throws IOException + { + // Untrusted target: Use a newly-erased buffer + int c = Math.min(icount, TRANSFER_SIZE); + ByteBuffer bb = ByteBuffer.allocate(c); + long tw = 0; // Total bytes written + long pos = position; + try { + while (tw < icount) { + bb.limit(Math.min((int)(icount - tw), TRANSFER_SIZE)); + int nr = read(bb, pos); + if (nr <= 0) + break; + bb.flip(); + // ## Bug: Will block writing target if this channel + // ## is asynchronously closed + int nw = target.write(bb); + tw += nw; + if (nw != nr) + break; + pos += nw; + bb.clear(); + } + return tw; + } catch (IOException x) { + if (tw > 0) + return tw; + throw x; + } + } + + public long transferTo(long position, long count, + WritableByteChannel target) + throws IOException + { + ensureOpen(); + if (!target.isOpen()) + throw new ClosedChannelException(); + if (!readable) + throw new NonReadableChannelException(); + if (target instanceof FileChannelImpl && + !((FileChannelImpl)target).writable) + throw new NonWritableChannelException(); + if ((position < 0) || (count < 0)) + throw new IllegalArgumentException(); + long sz = size(); + if (position > sz) + return 0; + int icount = (int)Math.min(count, Integer.MAX_VALUE); + if ((sz - position) < icount) + icount = (int)(sz - position); + + // Slow path for untrusted targets + return transferToArbitraryChannel(position, icount, target); + } + + private long transferFromFileChannel(FileChannelImpl src, + long position, long count) + throws IOException + { + if (!src.readable) + throw new NonReadableChannelException(); + return transferFromArbitraryChannel(src, position, count); + } + + private static final int TRANSFER_SIZE = 8192; + + private long transferFromArbitraryChannel(ReadableByteChannel src, + long position, long count) + throws IOException + { + // Untrusted target: Use a newly-erased buffer + int c = (int)Math.min(count, TRANSFER_SIZE); + ByteBuffer bb = ByteBuffer.allocate(c); + long tw = 0; // Total bytes written + long pos = position; + try { + while (tw < count) { + bb.limit((int)Math.min((count - tw), (long)TRANSFER_SIZE)); + // ## Bug: Will block reading src if this channel + // ## is asynchronously closed + int nr = src.read(bb); + if (nr <= 0) + break; + bb.flip(); + int nw = write(bb, pos); + tw += nw; + if (nw != nr) + break; + pos += nw; + bb.clear(); + } + return tw; + } catch (IOException x) { + if (tw > 0) + return tw; + throw x; + } + } + + public long transferFrom(ReadableByteChannel src, + long position, long count) + throws IOException + { + ensureOpen(); + if (!src.isOpen()) + throw new ClosedChannelException(); + if (!writable) + throw new NonWritableChannelException(); + if ((position < 0) || (count < 0)) + throw new IllegalArgumentException(); + if (position > size()) + return 0; + if (src instanceof FileChannelImpl) + return transferFromFileChannel((FileChannelImpl)src, + position, count); + + return transferFromArbitraryChannel(src, position, count); + } + + public int read(ByteBuffer dst, long position) throws IOException { + if (dst == null) + throw new NullPointerException(); + if (position < 0) + throw new IllegalArgumentException("Negative position"); + if (!readable) + throw new NonReadableChannelException(); + ensureOpen(); + if (nd.needsPositionLock()) { + synchronized (positionLock) { + return readInternal(dst, position); + } + } else { + return readInternal(dst, position); + } + } + + private int readInternal(ByteBuffer dst, long position) throws IOException { + assert !nd.needsPositionLock() || Thread.holdsLock(positionLock); + int n = 0; + int ti = -1; + try { + begin(); + ti = threads.add(); + if (!isOpen()) + return -1; + do { + n = IOUtil.read(fd, dst, position, nd); + } while ((n == IOStatus.INTERRUPTED) && isOpen()); + return IOStatus.normalize(n); + } finally { + threads.remove(ti); + end(n > 0); + assert IOStatus.check(n); + } + } + + public int write(ByteBuffer src, long position) throws IOException { + if (src == null) + throw new NullPointerException(); + if (position < 0) + throw new IllegalArgumentException("Negative position"); + if (!writable) + throw new NonWritableChannelException(); + ensureOpen(); + if (nd.needsPositionLock()) { + synchronized (positionLock) { + return writeInternal(src, position); + } + } else { + return writeInternal(src, position); + } + } + + private int writeInternal(ByteBuffer src, long position) throws IOException { + assert !nd.needsPositionLock() || Thread.holdsLock(positionLock); + int n = 0; + int ti = -1; + try { + begin(); + ti = threads.add(); + if (!isOpen()) + return -1; + do { + n = IOUtil.write(fd, src, position, nd); + } while ((n == IOStatus.INTERRUPTED) && isOpen()); + return IOStatus.normalize(n); + } finally { + threads.remove(ti); + end(n > 0); + assert IOStatus.check(n); + } + } + + + // -- Memory-mapped buffers -- + + private static class Unmapper + implements Runnable + { + // may be required to close file + private static final NativeDispatcher nd = new FileDispatcherImpl(); + + // keep track of mapped buffer usage + static volatile int count; + static volatile long totalSize; + static volatile long totalCapacity; + + private volatile long address; + private final long size; + private final int cap; + private final FileDescriptor fd; + + private Unmapper(long address, long size, int cap, + FileDescriptor fd) + { + assert (address != 0); + this.address = address; + this.size = size; + this.cap = cap; + this.fd = fd; + + synchronized (Unmapper.class) { + count++; + totalSize += size; + totalCapacity += cap; + } + } + + public void run() { + if (address == 0) + return; + unmap0(address, size); + address = 0; + + // if this mapping has a valid file descriptor then we close it + if (fd.valid()) { + try { + nd.close(fd); + } catch (IOException ignore) { + // nothing we can do + } + } + + synchronized (Unmapper.class) { + count--; + totalSize -= size; + totalCapacity -= cap; + } + } + } + + private static void unmap(MappedByteBuffer bb) { + Cleaner cl = ((DirectBuffer)bb).cleaner(); + if (cl != null) + cl.clean(); + } + + private static final int MAP_RO = 0; + private static final int MAP_RW = 1; + private static final int MAP_PV = 2; + + public MappedByteBuffer map(MapMode mode, long position, long size) + throws IOException + { + ensureOpen(); + if (mode == null) + throw new NullPointerException("Mode is null"); + if (position < 0L) + throw new IllegalArgumentException("Negative position"); + if (size < 0L) + throw new IllegalArgumentException("Negative size"); + if (position + size < 0) + throw new IllegalArgumentException("Position + size overflow"); + if (size > Integer.MAX_VALUE) + throw new IllegalArgumentException("Size exceeds Integer.MAX_VALUE"); + + int imode = -1; + if (mode == MapMode.READ_ONLY) + imode = MAP_RO; + else if (mode == MapMode.READ_WRITE) + imode = MAP_RW; + else if (mode == MapMode.PRIVATE) + imode = MAP_PV; + assert (imode >= 0); + if ((mode != MapMode.READ_ONLY) && !writable) + throw new NonWritableChannelException(); + if (!readable) + throw new NonReadableChannelException(); + + long addr = -1; + int ti = -1; + try { + begin(); + ti = threads.add(); + if (!isOpen()) + return null; + + long filesize; + do { + filesize = nd.size(fd); + } while ((filesize == IOStatus.INTERRUPTED) && isOpen()); + if (!isOpen()) + return null; + + if (filesize < position + size) { // Extend file size + if (!writable) { + throw new IOException("Channel not open for writing " + + "- cannot extend file to required size"); + } + int rv; + do { + rv = nd.truncate(fd, position + size); + } while ((rv == IOStatus.INTERRUPTED) && isOpen()); + if (!isOpen()) + return null; + } + if (size == 0) { + addr = 0; + // a valid file descriptor is not required + FileDescriptor dummy = new FileDescriptor(); + if ((!writable) || (imode == MAP_RO)) + return Util.newMappedByteBufferR(0, 0, dummy, null); + else + return Util.newMappedByteBuffer(0, 0, dummy, null); + } + + int pagePosition = (int)(position % allocationGranularity); + long mapPosition = position - pagePosition; + long mapSize = size + pagePosition; + try { + // If no exception was thrown from map0, the address is valid + addr = map0(imode, mapPosition, mapSize); + } catch (OutOfMemoryError x) { + // An OutOfMemoryError may indicate that we've exhausted memory + // so force gc and re-attempt map + System.gc(); + try { + Thread.sleep(100); + } catch (InterruptedException y) { + Thread.currentThread().interrupt(); + } + try { + addr = map0(imode, mapPosition, mapSize); + } catch (OutOfMemoryError y) { + // After a second OOME, fail + throw new IOException("Map failed", y); + } + } + + // On Windows, and potentially other platforms, we need an open + // file descriptor for some mapping operations. + FileDescriptor mfd; + try { + mfd = nd.duplicateForMapping(fd); + } catch (IOException ioe) { + unmap0(addr, mapSize); + throw ioe; + } + + assert (IOStatus.checkAll(addr)); + assert (addr % allocationGranularity == 0); + int isize = (int)size; + Unmapper um = new Unmapper(addr, mapSize, isize, mfd); + if ((!writable) || (imode == MAP_RO)) { + return Util.newMappedByteBufferR(isize, + addr + pagePosition, + mfd, + um); + } else { + return Util.newMappedByteBuffer(isize, + addr + pagePosition, + mfd, + um); + } + } finally { + threads.remove(ti); + end(IOStatus.checkAll(addr)); + } + } + + /** + * Invoked by sun.management.ManagementFactoryHelper to create the management + * interface for mapped buffers. + */ + public static sun.misc.JavaNioAccess.BufferPool getMappedBufferPool() { + return new sun.misc.JavaNioAccess.BufferPool() { + @Override + public String getName() { + return "mapped"; + } + @Override + public long getCount() { + return Unmapper.count; + } + @Override + public long getTotalCapacity() { + return Unmapper.totalCapacity; + } + @Override + public long getMemoryUsed() { + return Unmapper.totalSize; + } + }; + } + + // -- Locks -- + + + + // keeps track of locks on this file + private volatile FileLockTable fileLockTable; + + // indicates if file locks are maintained system-wide (as per spec) + private static boolean isSharedFileLockTable; + + // indicates if the disableSystemWideOverlappingFileLockCheck property + // has been checked + private static volatile boolean propertyChecked; + + // The lock list in J2SE 1.4/5.0 was local to each FileChannel instance so + // the overlap check wasn't system wide when there were multiple channels to + // the same file. This property is used to get 1.4/5.0 behavior if desired. + private static boolean isSharedFileLockTable() { + if (!propertyChecked) { + synchronized (FileChannelImpl.class) { + if (!propertyChecked) { + String value = AccessController.doPrivileged( + new GetPropertyAction( + "sun.nio.ch.disableSystemWideOverlappingFileLockCheck")); + isSharedFileLockTable = ((value == null) || value.equals("false")); + propertyChecked = true; + } + } + } + return isSharedFileLockTable; + } + + private FileLockTable fileLockTable() throws IOException { + if (fileLockTable == null) { + synchronized (this) { + if (fileLockTable == null) { + if (isSharedFileLockTable()) { + int ti = threads.add(); + try { + ensureOpen(); + fileLockTable = FileLockTable.newSharedFileLockTable(this, fd); + } finally { + threads.remove(ti); + } + } else { + fileLockTable = new SimpleFileLockTable(); + } + } + } + } + return fileLockTable; + } + + public FileLock lock(long position, long size, boolean shared) + throws IOException + { + ensureOpen(); + if (shared && !readable) + throw new NonReadableChannelException(); + if (!shared && !writable) + throw new NonWritableChannelException(); + FileLockImpl fli = new FileLockImpl(this, position, size, shared); + FileLockTable flt = fileLockTable(); + flt.add(fli); + boolean completed = false; + int ti = -1; + try { + begin(); + ti = threads.add(); + if (!isOpen()) + return null; + int n; + do { + n = nd.lock(fd, true, position, size, shared); + } while ((n == FileDispatcher.INTERRUPTED) && isOpen()); + if (isOpen()) { + if (n == FileDispatcher.RET_EX_LOCK) { + assert shared; + FileLockImpl fli2 = new FileLockImpl(this, position, size, + false); + flt.replace(fli, fli2); + fli = fli2; + } + completed = true; + } + } finally { + if (!completed) + flt.remove(fli); + threads.remove(ti); + try { + end(completed); + } catch (ClosedByInterruptException e) { + throw new FileLockInterruptionException(); + } + } + return fli; + } + + public FileLock tryLock(long position, long size, boolean shared) + throws IOException + { + ensureOpen(); + if (shared && !readable) + throw new NonReadableChannelException(); + if (!shared && !writable) + throw new NonWritableChannelException(); + FileLockImpl fli = new FileLockImpl(this, position, size, shared); + FileLockTable flt = fileLockTable(); + flt.add(fli); + int result; + + int ti = threads.add(); + try { + try { + ensureOpen(); + result = nd.lock(fd, false, position, size, shared); + } catch (IOException e) { + flt.remove(fli); + throw e; + } + if (result == FileDispatcher.NO_LOCK) { + flt.remove(fli); + return null; + } + if (result == FileDispatcher.RET_EX_LOCK) { + assert shared; + FileLockImpl fli2 = new FileLockImpl(this, position, size, + false); + flt.replace(fli, fli2); + return fli2; + } + return fli; + } finally { + threads.remove(ti); + } + } + + void release(FileLockImpl fli) throws IOException { + int ti = threads.add(); + try { + ensureOpen(); + nd.release(fd, fli.position(), fli.size()); + } finally { + threads.remove(ti); + } + assert fileLockTable != null; + fileLockTable.remove(fli); + } + + // -- File lock support -- + + /** + * A simple file lock table that maintains a list of FileLocks obtained by a + * FileChannel. Use to get 1.4/5.0 behaviour. + */ + private static class SimpleFileLockTable extends FileLockTable { + // synchronize on list for access + private final List lockList = new ArrayList(2); + + public SimpleFileLockTable() { + } + + private void checkList(long position, long size) + throws OverlappingFileLockException + { + assert Thread.holdsLock(lockList); + for (FileLock fl: lockList) { + if (fl.overlaps(position, size)) { + throw new OverlappingFileLockException(); + } + } + } + + public void add(FileLock fl) throws OverlappingFileLockException { + synchronized (lockList) { + checkList(fl.position(), fl.size()); + lockList.add(fl); + } + } + + public void remove(FileLock fl) { + synchronized (lockList) { + lockList.remove(fl); + } + } + + public List removeAll() { + synchronized(lockList) { + List result = new ArrayList(lockList); + lockList.clear(); + return result; + } + } + + public void replace(FileLock fl1, FileLock fl2) { + synchronized (lockList) { + lockList.remove(fl1); + lockList.add(fl2); + } + } + } + + // -- Native methods -- + + // Creates a new mapping + private long map0(int prot, long position, long length) throws IOException + { + FileStream fs = (FileStream)fd.getStream(); + if (win32) + return mapViewOfFileWin32(fs, prot, position, length); + else + return mapViewOfFilePosix(fs, prot, position, length); + } + + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + private static long mapViewOfFileWin32(FileStream fs, int prot, long position, long length) throws IOException + { + try + { + int PAGE_READONLY = 2; + int PAGE_READWRITE = 4; + int PAGE_WRITECOPY = 8; + + int FILE_MAP_WRITE = 2; + int FILE_MAP_READ = 4; + int FILE_MAP_COPY = 1; + + int fileProtect; + int mapAccess; + + switch (prot) + { + case MAP_RO: + fileProtect = PAGE_READONLY; + mapAccess = FILE_MAP_READ; + break; + case MAP_RW: + fileProtect = PAGE_READWRITE; + mapAccess = FILE_MAP_WRITE; + break; + case MAP_PV: + fileProtect = PAGE_WRITECOPY; + mapAccess = FILE_MAP_COPY; + break; + default: + throw new Error(); + } + + long maxSize = length + position; + SafeFileHandle hFileMapping = CreateFileMapping(fs.get_SafeFileHandle(), IntPtr.Zero, fileProtect, (int)(maxSize >> 32), (int)maxSize, null); + int err = cli.System.Runtime.InteropServices.Marshal.GetLastWin32Error(); + if (hFileMapping.get_IsInvalid()) + { + throw new IOException("Win32 error " + err); + } + IntPtr p = MapViewOfFile(hFileMapping, mapAccess, (int)(position >> 32), (int)position, IntPtr.op_Explicit(length)); + err = cli.System.Runtime.InteropServices.Marshal.GetLastWin32Error(); + hFileMapping.Close(); + if (p.Equals(IntPtr.Zero)) + { + if (err == 8 /*ERROR_NOT_ENOUGH_MEMORY*/) + { + throw new OutOfMemoryError("Map failed"); + } + throw new IOException("Win32 error " + err); + } + cli.System.GC.AddMemoryPressure(length); + return p.ToInt64(); + } + finally + { + cli.System.GC.KeepAlive(fs); + } + } + + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + private static long mapViewOfFilePosix(FileStream fs, int prot, long position, long length) throws IOException + { + byte writeable = prot != MAP_RO ? (byte)1 : (byte)0; + byte copy_on_write = prot == MAP_PV ? (byte)1 : (byte)0; + IntPtr p = ikvm_mmap(fs.get_SafeFileHandle(), writeable, copy_on_write, position, (int)length); + cli.System.GC.KeepAlive(fs); + // HACK ikvm_mmap should really be changed to return a null pointer on failure, + // instead of whatever MAP_FAILED is defined to on the particular system we're running on, + // common values for MAP_FAILED are 0 and -1, so we test for these. + if (p.Equals(IntPtr.Zero) || p.Equals(new IntPtr(-1))) + { + throw new IOException("file mapping failed"); + } + cli.System.GC.AddMemoryPressure(length); + return p.ToInt64(); + } + + @DllImportAttribute.Annotation(value="kernel32", SetLastError=true) + private static native SafeFileHandle CreateFileMapping(SafeFileHandle hFile, IntPtr lpAttributes, int flProtect, int dwMaximumSizeHigh, int dwMaximumSizeLow, String lpName); + + @DllImportAttribute.Annotation(value="kernel32", SetLastError=true) + private static native IntPtr MapViewOfFile(SafeFileHandle hFileMapping, int dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow, IntPtr dwNumberOfBytesToMap); + + @DllImportAttribute.Annotation("kernel32") + private static native int UnmapViewOfFile(IntPtr lpBaseAddress); + + @DllImportAttribute.Annotation("ikvm-native") + private static native int ikvm_munmap(IntPtr address, int size); + + @DllImportAttribute.Annotation("ikvm-native") + private static native IntPtr ikvm_mmap(SafeFileHandle handle, byte writeable, byte copy_on_write, long position, int size); + + // Removes an existing mapping + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + static int unmap0(long address, long length) + { + if (win32) + UnmapViewOfFile(IntPtr.op_Explicit(address)); + else + ikvm_munmap(IntPtr.op_Explicit(address), (int)length); + cli.System.GC.RemoveMemoryPressure(length); + return 0; + } + + // Sets or reports this file's position + // If offset is -1, the current position is returned + // otherwise the position is set to offset + private static long position0(FileDescriptor fd, long offset) throws IOException + { + if (offset == -1) + { + return fd.getFilePointer(); + } + fd.seek(offset); + return offset; + } +} diff --git a/openjdk/sun/nio/ch/FileDispatcherImpl.java b/openjdk/sun/nio/ch/FileDispatcherImpl.java new file mode 100644 index 0000000..23bb90c --- /dev/null +++ b/openjdk/sun/nio/ch/FileDispatcherImpl.java @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2000, 2013, 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.nio.ch; + +import java.io.*; +import java.nio.ByteBuffer; +import cli.Microsoft.Win32.SafeHandles.SafeFileHandle; +import cli.System.IntPtr; +import cli.System.IO.FileStream; +import cli.System.Runtime.InteropServices.DllImportAttribute; +import cli.System.Runtime.InteropServices.StructLayoutAttribute; +import cli.System.Runtime.InteropServices.LayoutKind; +import cli.System.Runtime.InteropServices.Marshal; +import static ikvm.internal.Util.WINDOWS; + +class FileDispatcherImpl extends FileDispatcher +{ + /** + * Indicates if the dispatcher should first advance the file position + * to the end of file when writing. + */ + private final boolean append; + + FileDispatcherImpl(boolean append) { + this.append = append; + } + + FileDispatcherImpl() { + this(false); + } + + @Override + boolean needsPositionLock() { + return true; + } + + int read(FileDescriptor fd, byte[] buf, int offset, int length) throws IOException { + return fd.readBytes(buf, offset, length); + } + + int write(FileDescriptor fd, byte[] buf, int offset, int length) throws IOException { + fd.writeBytes(buf, offset, length); + return length; + } + + long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length) throws IOException { + long totalRead = 0; + try + { + for (int i = offset; i < offset + length; i++) + { + int size = bufs[i].remaining(); + if (size > 0) + { + int read = IOUtil.read(fd, bufs[i], -1, this); + if (read < 0) + { + break; + } + totalRead += read; + if (read < size || fd.available() == 0) + { + break; + } + } + } + } + catch (IOException x) + { + if (totalRead == 0) + { + throw x; + } + } + return totalRead; + } + + long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length) throws IOException { + long totalWritten = 0; + try + { + for (int i = offset; i < offset + length; i++) + { + int size = bufs[i].remaining(); + if (size > 0) + { + int written = IOUtil.write(fd, bufs[i], -1, this); + totalWritten += written; + if (written < size) + { + break; + } + } + } + } + catch (IOException x) + { + if (totalWritten == 0) + { + throw x; + } + } + return totalWritten; + } + + int force(FileDescriptor fd, boolean metaData) throws IOException { + fd.sync(); + return 0; + } + + int truncate(FileDescriptor fd, long size) throws IOException { + if (append) { + // HACK in append mode we're not allowed to truncate, so we try to reopen the file and truncate that + try (FileOutputStream fos = new FileOutputStream(((FileStream)fd.getStream()).get_Name())) { + fos.getFD().setLength(size); + } + } else { + fd.setLength(size); + } + return 0; + } + + long size(FileDescriptor fd) throws IOException { + return fd.length(); + } + + @StructLayoutAttribute.Annotation(LayoutKind.__Enum.Sequential) + private static final class OVERLAPPED extends cli.System.Object + { + IntPtr Internal; + IntPtr InternalHigh; + int OffsetLow; + int OffsetHigh; + IntPtr hEvent; + } + + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + int lock(FileDescriptor fd, boolean blocking, long pos, long size, + boolean shared) throws IOException + { + FileStream fs = (FileStream)fd.getStream(); + if (WINDOWS) + { + int LOCKFILE_FAIL_IMMEDIATELY = 1; + int LOCKFILE_EXCLUSIVE_LOCK = 2; + int ERROR_LOCK_VIOLATION = 33; + int flags = 0; + OVERLAPPED o = new OVERLAPPED(); + o.OffsetLow = (int)pos; + o.OffsetHigh = (int)(pos >> 32); + if (!blocking) + { + flags |= LOCKFILE_FAIL_IMMEDIATELY; + } + if (!shared) + { + flags |= LOCKFILE_EXCLUSIVE_LOCK; + } + int result = LockFileEx(fs.get_SafeFileHandle(), flags, 0, (int)size, (int)(size >> 32), o); + if (result == 0) + { + int error = Marshal.GetLastWin32Error(); + if (!blocking && error == ERROR_LOCK_VIOLATION) + { + return NO_LOCK; + } + throw new IOException("Lock failed"); + } + return LOCKED; + } + else + { + try + { + if (false) throw new cli.System.ArgumentOutOfRangeException(); + for (;;) + { + try + { + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.ObjectDisposedException(""); + fs.Lock(pos, size); + return shared ? RET_EX_LOCK : LOCKED; + } + catch (cli.System.IO.IOException x) + { + if (!blocking) + { + return NO_LOCK; + } + cli.System.Threading.Thread.Sleep(100); + } + catch (cli.System.ObjectDisposedException x) + { + throw new IOException(x.getMessage()); + } + } + } + catch (cli.System.ArgumentOutOfRangeException x) + { + throw new IOException(x.getMessage()); + } + } + } + + @cli.System.Security.SecuritySafeCriticalAttribute.Annotation + void release(FileDescriptor fd, long pos, long size) throws IOException { + FileStream fs = (FileStream)fd.getStream(); + if (WINDOWS) + { + int ERROR_NOT_LOCKED = 158; + OVERLAPPED o = new OVERLAPPED(); + o.OffsetLow = (int)pos; + o.OffsetHigh = (int)(pos >> 32); + int result = UnlockFileEx(fs.get_SafeFileHandle(), 0, (int)size, (int)(size >> 32), o); + if (result == 0 && Marshal.GetLastWin32Error() != ERROR_NOT_LOCKED) + { + throw new IOException("Release failed"); + } + } + else + { + try + { + if (false) throw new cli.System.ArgumentOutOfRangeException(); + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.ObjectDisposedException(""); + fs.Unlock(pos, size); + } + catch (cli.System.IO.IOException x) + { + if (!NotLockedHack.isErrorNotLocked(x)) + { + throw new IOException(x.getMessage()); + } + } + catch (cli.System.ArgumentOutOfRangeException + | cli.System.ObjectDisposedException x) + { + throw new IOException(x.getMessage()); + } + } + } + + static class NotLockedHack { + private static String msg; + static { + try { + File tmp = File.createTempFile("lock", null); + try (FileStream fs = new FileStream(tmp.getPath(), cli.System.IO.FileMode.wrap(cli.System.IO.FileMode.Create))) { + try { + if (false) throw new cli.System.IO.IOException(); + fs.Unlock(0, 1); + } catch (cli.System.IO.IOException x) { + msg = x.get_Message(); + } + } + tmp.delete(); + } catch (Throwable _) { + } + } + static boolean isErrorNotLocked(cli.System.IO.IOException x) { + return x.get_Message().equals(msg); + } + } + + + void close(FileDescriptor fd) throws IOException { + fd.close(); + } + + FileDescriptor duplicateForMapping(FileDescriptor fd) throws IOException { + // we return a dummy FileDescriptor, because we don't need it for mapping operations + // and we don't want the original to be closed + return new FileDescriptor(); + } + + @DllImportAttribute.Annotation(value="kernel32", SetLastError=true) + private static native int LockFileEx(SafeFileHandle hFile, int dwFlags, int dwReserved, int nNumberOfBytesToLockLow, int nNumberOfBytesToLockHigh, OVERLAPPED lpOverlapped); + + @DllImportAttribute.Annotation(value="kernel32", SetLastError=true) + private static native int UnlockFileEx(SafeFileHandle hFile, int dwReserved, int nNumberOfBytesToUnlockLow, int nNumberOfBytesToUnlockHigh, OVERLAPPED lpOverlapped); +} diff --git a/openjdk/sun/nio/ch/FileKey.java b/openjdk/sun/nio/ch/FileKey.java new file mode 100644 index 0000000..4feec5d --- /dev/null +++ b/openjdk/sun/nio/ch/FileKey.java @@ -0,0 +1,57 @@ +/* + Copyright (C) 2007 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package sun.nio.ch; + +import java.io.File; +import java.io.FileDescriptor; +import java.io.IOException; + +public class FileKey +{ + private String path; + + public static FileKey create(FileDescriptor fd) + { + FileKey fk = new FileKey(); + fk.path = ((cli.System.IO.FileStream)fd.getStream()).get_Name(); + try + { + fk.path = new File(fk.path).getCanonicalPath(); + } + catch (IOException x) + { + } + return fk; + } + + public int hashCode() + { + return path.hashCode(); + } + + public boolean equals(Object obj) + { + return obj == this || (obj instanceof FileKey && ((FileKey)obj).path.equals(path)); + } +} diff --git a/openjdk/sun/nio/ch/IOUtil.java b/openjdk/sun/nio/ch/IOUtil.java new file mode 100644 index 0000000..1965768 --- /dev/null +++ b/openjdk/sun/nio/ch/IOUtil.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2000, 2013, 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.nio.ch; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.net.*; +import java.nio.ByteBuffer; +import java.nio.channels.*; +import java.nio.channels.spi.*; + + +/** + * File-descriptor based I/O utilities that are shared by NIO classes. + */ + +public class IOUtil { + + private IOUtil() { } // No instantiation + + static boolean randomBytes(byte[] someBytes) + { + try + { + if (false) throw new cli.System.Security.Cryptography.CryptographicException(); + cli.System.Security.Cryptography.RNGCryptoServiceProvider csp = new cli.System.Security.Cryptography.RNGCryptoServiceProvider(); + csp.GetBytes(someBytes); + return true; + } + catch (cli.System.Security.Cryptography.CryptographicException _) + { + return false; + } + } + + static void configureBlocking(FileDescriptor fd, boolean blocking) throws IOException + { + fd.setSocketBlocking(blocking); + } + + // this is a dummy method to allow us to use unmodified socket channel impls + static int fdVal(FileDescriptor fd) + { + return 0xbadc0de; + } + + static int read(FileDescriptor fd, ByteBuffer dst, long position, + NativeDispatcher nd) + throws IOException + { + if (dst.isReadOnly()) + throw new IllegalArgumentException("Read-only buffer"); + + if (position != -1) + { + long prevpos = fd.getFilePointer(); + try + { + fd.seek(position); + return read(fd, dst, -1, nd); + } + finally + { + fd.seek(prevpos); + } + } + + if (dst.hasArray()) + { + byte[] buf = dst.array(); + int len = nd.read(fd, buf, dst.arrayOffset() + dst.position(), dst.remaining()); + if (len > 0) + { + dst.position(dst.position() + len); + } + return len; + } + else + { + byte[] buf = new byte[dst.remaining()]; + int len = nd.read(fd, buf, 0, buf.length); + if (len > 0) + { + dst.put(buf, 0, len); + } + return len; + } + } + + static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length, NativeDispatcher nd) + throws IOException + { + return nd.read(fd, bufs, offset, length); + } + + static int write(FileDescriptor fd, ByteBuffer src, long position, + NativeDispatcher nd) + throws IOException + { + if (position != -1) + { + long prevpos = fd.getFilePointer(); + try + { + fd.seek(position); + return write(fd, src, -1, nd); + } + finally + { + fd.seek(prevpos); + } + } + + if (src.hasArray()) + { + byte[] buf = src.array(); + int len = nd.write(fd, buf, src.arrayOffset() + src.position(), src.remaining()); + if (len > 0) + { + src.position(src.position() + len); + } + return len; + } + else + { + int pos = src.position(); + byte[] buf = new byte[src.remaining()]; + src.get(buf); + src.position(pos); + int len = nd.write(fd, buf, 0, buf.length); + if (len > 0) + { + src.position(pos + len); + } + return len; + } + } + + static long write(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd) + throws IOException + { + return nd.write(fd, bufs, 0, bufs.length); + } + + static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length, NativeDispatcher nd) + throws IOException + { + return nd.write(fd, bufs, offset, length); + } + + /** + * Used to trigger loading of native libraries + */ + public static void load() { } +} diff --git a/openjdk/sun/nio/ch/Iocp.java b/openjdk/sun/nio/ch/Iocp.java new file mode 100644 index 0000000..79403bf --- /dev/null +++ b/openjdk/sun/nio/ch/Iocp.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2008, 2013, 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.nio.ch; + +import java.nio.channels.*; +import java.nio.channels.spi.AsynchronousChannelProvider; +import java.io.Closeable; +import java.io.IOException; +import java.io.FileDescriptor; +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import ikvm.internal.NotYetImplementedError; + +/** + * Windows implementation of AsynchronousChannelGroup encapsulating an I/O + * completion port. + */ + +class Iocp extends AsynchronousChannelGroupImpl { + private static final boolean supportsThreadAgnosticIo; + + // true if port has been closed + private boolean closed; + + // the set of "stale" OVERLAPPED structures. These OVERLAPPED structures + // relate to I/O operations where the completion notification was not + // received in a timely manner after the channel is closed. + private final Set staleIoSet = new HashSet(); + + Iocp(AsynchronousChannelProvider provider, ThreadPool pool) + throws IOException + { + super(provider, pool); + } + + Iocp start() { + return this; + } + + /* + * Channels implements this interface support overlapped I/O and can be + * associated with a completion port. + */ + static interface OverlappedChannel extends Closeable { + /** + * Returns a reference to the pending I/O result. + */ + PendingFuture getByOverlapped(long overlapped); + } + + /** + * Indicates if this operating system supports thread agnostic I/O. + */ + static boolean supportsThreadAgnosticIo() { + return supportsThreadAgnosticIo; + } + + // release all resources + void implClose() { + synchronized (this) { + if (closed) + return; + closed = true; + } + } + + @Override + boolean isEmpty() { + return true; + } + + @Override + final Object attachForeignChannel(final Channel channel, FileDescriptor fdObj) + throws IOException + { + throw new NotYetImplementedError(); + } + + @Override + final void detachForeignChannel(Object key) { + throw new NotYetImplementedError(); + } + + @Override + void closeAllChannels() { + } + + @Override + void executeOnHandlerTask(Runnable task) { + throw new NotYetImplementedError(); + } + + @Override + void shutdownHandlerTasks() { + } + + /** + * The handler for consuming the result of an asynchronous I/O operation. + */ + static interface ResultHandler { + /** + * Invoked if the I/O operation completes successfully. + */ + public void completed(int bytesTransferred, boolean canInvokeDirect); + + /** + * Invoked if the I/O operation fails. + */ + public void failed(int error, IOException ioe); + } + + static { + supportsThreadAgnosticIo = true; + } +} diff --git a/openjdk/sun/nio/ch/NativeDispatcher.java b/openjdk/sun/nio/ch/NativeDispatcher.java new file mode 100644 index 0000000..9582e6a --- /dev/null +++ b/openjdk/sun/nio/ch/NativeDispatcher.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2000, 2013, 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.nio.ch; + +import java.io.*; +import java.nio.ByteBuffer; + +/** + * Allows different platforms to call different native methods + * for read and write operations. + */ + +abstract class NativeDispatcher +{ + abstract int read(FileDescriptor fd, byte[] buf, int offset, int length) throws IOException; + + /** + * Returns {@code true} if pread/pwrite needs to be synchronized with + * position sensitive methods. + */ + boolean needsPositionLock() { + return false; + } + + abstract int write(FileDescriptor fd, byte[] buf, int offset, int length) throws IOException; + + abstract long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length) throws IOException; + + abstract long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length) throws IOException; + + abstract void close(FileDescriptor fd) throws IOException; + + // Prepare the given fd for closing by duping it to a known internal fd + // that's already closed. This is necessary on some operating systems + // (Solaris and Linux) to prevent fd recycling. + // + void preClose(FileDescriptor fd) throws IOException { + // Do nothing by default; this is only needed on Unix + } + +} diff --git a/openjdk/sun/nio/ch/Net.java b/openjdk/sun/nio/ch/Net.java new file mode 100644 index 0000000..edf52a6 --- /dev/null +++ b/openjdk/sun/nio/ch/Net.java @@ -0,0 +1,616 @@ +/* + * Copyright (c) 2000, 2013, 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.nio.ch; + +import java.io.*; +import java.net.*; +import jdk.net.*; +import java.nio.channels.*; +import java.util.*; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedExceptionAction; +import sun.net.ExtendedOptionsImpl; + + +public class Net { + + private Net() { } + + // unspecified protocol family + static final ProtocolFamily UNSPEC = new ProtocolFamily() { + public String name() { + return "UNSPEC"; + } + }; + + // set to true if exclusive binding is on for Windows + private static final boolean exclusiveBind; + + static { + int availLevel = isExclusiveBindAvailable(); + if (availLevel >= 0) { + String exclBindProp = + java.security.AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public String run() { + return System.getProperty( + "sun.net.useExclusiveBind"); + } + }); + if (exclBindProp != null) { + exclusiveBind = exclBindProp.length() == 0 ? + true : Boolean.parseBoolean(exclBindProp); + } else if (availLevel == 1) { + exclusiveBind = true; + } else { + exclusiveBind = false; + } + } else { + exclusiveBind = false; + } + } + + // -- Miscellaneous utilities -- + + private static volatile boolean checkedIPv6 = false; + private static volatile boolean isIPv6Available; + + /** + * Tells whether dual-IPv4/IPv6 sockets should be used. + */ + static boolean isIPv6Available() { + if (!checkedIPv6) { + isIPv6Available = isIPv6Available0(); + checkedIPv6 = true; + } + return isIPv6Available; + } + + /** + * Returns true if exclusive binding is on + */ + static boolean useExclusiveBind() { + return exclusiveBind; + } + + /** + * Tells whether IPv6 sockets can join IPv4 multicast groups + */ + static boolean canIPv6SocketJoinIPv4Group() { + return canIPv6SocketJoinIPv4Group0(); + } + + /** + * Tells whether {@link #join6} can be used to join an IPv4 + * multicast group (IPv4 group as IPv4-mapped IPv6 address) + */ + static boolean canJoin6WithIPv4Group() { + return canJoin6WithIPv4Group0(); + } + + public static InetSocketAddress checkAddress(SocketAddress sa) { + if (sa == null) + throw new NullPointerException(); + if (!(sa instanceof InetSocketAddress)) + throw new UnsupportedAddressTypeException(); // ## needs arg + InetSocketAddress isa = (InetSocketAddress)sa; + if (isa.isUnresolved()) + throw new UnresolvedAddressException(); // ## needs arg + InetAddress addr = isa.getAddress(); + if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) + throw new IllegalArgumentException("Invalid address type"); + return isa; + } + + static InetSocketAddress asInetSocketAddress(SocketAddress sa) { + if (!(sa instanceof InetSocketAddress)) + throw new UnsupportedAddressTypeException(); + return (InetSocketAddress)sa; + } + + static void translateToSocketException(Exception x) + throws SocketException + { + if (x instanceof SocketException) + throw (SocketException)x; + Exception nx = x; + if (x instanceof ClosedChannelException) + nx = new SocketException("Socket is closed"); + else if (x instanceof NotYetConnectedException) + nx = new SocketException("Socket is not connected"); + else if (x instanceof AlreadyBoundException) + nx = new SocketException("Already bound"); + else if (x instanceof NotYetBoundException) + nx = new SocketException("Socket is not bound yet"); + else if (x instanceof UnsupportedAddressTypeException) + nx = new SocketException("Unsupported address type"); + else if (x instanceof UnresolvedAddressException) { + nx = new SocketException("Unresolved address"); + } + if (nx != x) + nx.initCause(x); + + if (nx instanceof SocketException) + throw (SocketException)nx; + else if (nx instanceof RuntimeException) + throw (RuntimeException)nx; + else + throw new Error("Untranslated exception", nx); + } + + static void translateException(Exception x, + boolean unknownHostForUnresolved) + throws IOException + { + if (x instanceof IOException) + throw (IOException)x; + // Throw UnknownHostException from here since it cannot + // be thrown as a SocketException + if (unknownHostForUnresolved && + (x instanceof UnresolvedAddressException)) + { + throw new UnknownHostException(); + } + translateToSocketException(x); + } + + static void translateException(Exception x) + throws IOException + { + translateException(x, false); + } + + /** + * Returns the local address after performing a SecurityManager#checkConnect. + */ + static InetSocketAddress getRevealedLocalAddress(InetSocketAddress addr) { + SecurityManager sm = System.getSecurityManager(); + if (addr == null || sm == null) + return addr; + + try{ + sm.checkConnect(addr.getAddress().getHostAddress(), -1); + // Security check passed + } catch (SecurityException e) { + // Return loopback address only if security check fails + addr = getLoopbackAddress(addr.getPort()); + } + return addr; + } + + static String getRevealedLocalAddressAsString(InetSocketAddress addr) { + return System.getSecurityManager() == null ? addr.toString() : + getLoopbackAddress(addr.getPort()).toString(); + } + + private static InetSocketAddress getLoopbackAddress(int port) { + return new InetSocketAddress(InetAddress.getLoopbackAddress(), + port); + } + + /** + * Returns any IPv4 address of the given network interface, or + * null if the interface does not have any IPv4 addresses. + */ + static Inet4Address anyInet4Address(final NetworkInterface interf) { + return AccessController.doPrivileged(new PrivilegedAction() { + public Inet4Address run() { + Enumeration addrs = interf.getInetAddresses(); + while (addrs.hasMoreElements()) { + InetAddress addr = addrs.nextElement(); + if (addr instanceof Inet4Address) { + return (Inet4Address)addr; + } + } + return null; + } + }); + } + + /** + * Returns an IPv4 address as an int. + */ + static int inet4AsInt(InetAddress ia) { + if (ia instanceof Inet4Address) { + byte[] addr = ia.getAddress(); + int address = addr[3] & 0xFF; + address |= ((addr[2] << 8) & 0xFF00); + address |= ((addr[1] << 16) & 0xFF0000); + address |= ((addr[0] << 24) & 0xFF000000); + return address; + } + throw new AssertionError("Should not reach here"); + } + + /** + * Returns an InetAddress from the given IPv4 address + * represented as an int. + */ + static InetAddress inet4FromInt(int address) { + byte[] addr = new byte[4]; + addr[0] = (byte) ((address >>> 24) & 0xFF); + addr[1] = (byte) ((address >>> 16) & 0xFF); + addr[2] = (byte) ((address >>> 8) & 0xFF); + addr[3] = (byte) (address & 0xFF); + try { + return InetAddress.getByAddress(addr); + } catch (UnknownHostException uhe) { + throw new AssertionError("Should not reach here"); + } + } + + /** + * Returns an IPv6 address as a byte array + */ + static byte[] inet6AsByteArray(InetAddress ia) { + if (ia instanceof Inet6Address) { + return ia.getAddress(); + } + + // need to construct IPv4-mapped address + if (ia instanceof Inet4Address) { + byte[] ip4address = ia.getAddress(); + byte[] address = new byte[16]; + address[10] = (byte)0xff; + address[11] = (byte)0xff; + address[12] = ip4address[0]; + address[13] = ip4address[1]; + address[14] = ip4address[2]; + address[15] = ip4address[3]; + return address; + } + + throw new AssertionError("Should not reach here"); + } + + // -- Socket options + + static void setSocketOption(FileDescriptor fd, ProtocolFamily family, + SocketOption name, Object value) + throws IOException + { + if (value == null) + throw new IllegalArgumentException("Invalid option value"); + + // only simple values supported by this method + Class type = name.type(); + + if (type == SocketFlow.class) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new NetworkPermission("setOption.SO_FLOW_SLA")); + } + ExtendedOptionsImpl.setFlowOption(fd, (SocketFlow)value); + return; + } + + if (type != Integer.class && type != Boolean.class) + throw new AssertionError("Should not reach here"); + + // special handling + if (name == StandardSocketOptions.SO_RCVBUF || + name == StandardSocketOptions.SO_SNDBUF) + { + int i = ((Integer)value).intValue(); + if (i < 0) + throw new IllegalArgumentException("Invalid send/receive buffer size"); + } + if (name == StandardSocketOptions.SO_LINGER) { + int i = ((Integer)value).intValue(); + if (i < 0) + value = Integer.valueOf(-1); + if (i > 65535) + value = Integer.valueOf(65535); + } + if (name == StandardSocketOptions.IP_TOS) { + int i = ((Integer)value).intValue(); + if (i < 0 || i > 255) + throw new IllegalArgumentException("Invalid IP_TOS value"); + } + if (name == StandardSocketOptions.IP_MULTICAST_TTL) { + int i = ((Integer)value).intValue(); + if (i < 0 || i > 255) + throw new IllegalArgumentException("Invalid TTL/hop value"); + } + + // map option name to platform level/name + OptionKey key = SocketOptionRegistry.findOption(name, family); + if (key == null) + throw new AssertionError("Option not found"); + + int arg; + if (type == Integer.class) { + arg = ((Integer)value).intValue(); + } else { + boolean b = ((Boolean)value).booleanValue(); + arg = (b) ? 1 : 0; + } + + boolean mayNeedConversion = (family == UNSPEC); + boolean isIPv6 = (family == StandardProtocolFamily.INET6); + setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg, isIPv6); + } + + static Object getSocketOption(FileDescriptor fd, ProtocolFamily family, + SocketOption name) + throws IOException + { + Class type = name.type(); + + if (type == SocketFlow.class) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new NetworkPermission("getOption.SO_FLOW_SLA")); + } + SocketFlow flow = SocketFlow.create(); + ExtendedOptionsImpl.getFlowOption(fd, flow); + return flow; + } + + // only simple values supported by this method + if (type != Integer.class && type != Boolean.class) + throw new AssertionError("Should not reach here"); + + // map option name to platform level/name + OptionKey key = SocketOptionRegistry.findOption(name, family); + if (key == null) + throw new AssertionError("Option not found"); + + boolean mayNeedConversion = (family == UNSPEC); + int value = getIntOption0(fd, mayNeedConversion, key.level(), key.name()); + + if (type == Integer.class) { + return Integer.valueOf(value); + } else { + return (value == 0) ? Boolean.FALSE : Boolean.TRUE; + } + } + + // -- Socket operations -- + + private static native boolean isIPv6Available0(); + + /* + * Returns 1 for Windows versions that support exclusive binding by default, 0 + * for those that do not, and -1 for Solaris/Linux/Mac OS + */ + private static native int isExclusiveBindAvailable(); + + private static native boolean canIPv6SocketJoinIPv4Group0(); + + private static native boolean canJoin6WithIPv4Group0(); + + static FileDescriptor socket(boolean stream) throws IOException { + return socket(UNSPEC, stream); + } + + static FileDescriptor socket(ProtocolFamily family, boolean stream) + throws IOException { + boolean preferIPv6 = isIPv6Available() && + (family != StandardProtocolFamily.INET); + return socket0(preferIPv6, stream, false); + } + + static FileDescriptor serverSocket(boolean stream) { + return socket0(isIPv6Available(), stream, true); + } + + // Due to oddities SO_REUSEADDR on windows reuse is ignored + private static native FileDescriptor socket0(boolean preferIPv6, boolean stream, boolean reuse); + + public static void bind(FileDescriptor fd, InetAddress addr, int port) + throws IOException + { + bind(UNSPEC, fd, addr, port); + } + + static void bind(ProtocolFamily family, FileDescriptor fd, + InetAddress addr, int port) throws IOException + { + boolean preferIPv6 = isIPv6Available() && + (family != StandardProtocolFamily.INET); + bind0(fd, preferIPv6, exclusiveBind, addr, port); + } + + private static native void bind0(FileDescriptor fd, boolean preferIPv6, + boolean useExclBind, InetAddress addr, + int port) + throws IOException; + + static native void listen(FileDescriptor fd, int backlog) throws IOException; + + static int connect(FileDescriptor fd, InetAddress remote, int remotePort) + throws IOException + { + return connect(UNSPEC, fd, remote, remotePort); + } + + static int connect(ProtocolFamily family, FileDescriptor fd, InetAddress remote, int remotePort) + throws IOException + { + boolean preferIPv6 = isIPv6Available() && + (family != StandardProtocolFamily.INET); + return connect0(preferIPv6, fd, remote, remotePort); + } + + private static native int connect0(boolean preferIPv6, + FileDescriptor fd, + InetAddress remote, + int remotePort) + throws IOException; + + + public final static int SHUT_RD = 0; + public final static int SHUT_WR = 1; + public final static int SHUT_RDWR = 2; + + static native void shutdown(FileDescriptor fd, int how) throws IOException; + + private static native int localPort(FileDescriptor fd) + throws IOException; + + private static native InetAddress localInetAddress(FileDescriptor fd) + throws IOException; + + public static InetSocketAddress localAddress(FileDescriptor fd) + throws IOException + { + return new InetSocketAddress(localInetAddress(fd), localPort(fd)); + } + + private static native int remotePort(FileDescriptor fd) + throws IOException; + + private static native InetAddress remoteInetAddress(FileDescriptor fd) + throws IOException; + + static InetSocketAddress remoteAddress(FileDescriptor fd) + throws IOException + { + return new InetSocketAddress(remoteInetAddress(fd), remotePort(fd)); + } + + private static native int getIntOption0(FileDescriptor fd, boolean mayNeedConversion, + int level, int opt) + throws IOException; + + private static native void setIntOption0(FileDescriptor fd, boolean mayNeedConversion, + int level, int opt, int arg, boolean isIPv6) + throws IOException; + + static native int poll(FileDescriptor fd, int events, long timeout) + throws IOException; + + // -- Multicast support -- + + + /** + * Join IPv4 multicast group + */ + static int join4(FileDescriptor fd, int group, int interf, int source) + throws IOException + { + return joinOrDrop4(true, fd, group, interf, source); + } + + /** + * Drop membership of IPv4 multicast group + */ + static void drop4(FileDescriptor fd, int group, int interf, int source) + throws IOException + { + joinOrDrop4(false, fd, group, interf, source); + } + + private static native int joinOrDrop4(boolean join, FileDescriptor fd, int group, int interf, int source) + throws IOException; + + /** + * Block IPv4 source + */ + static int block4(FileDescriptor fd, int group, int interf, int source) + throws IOException + { + return blockOrUnblock4(true, fd, group, interf, source); + } + + /** + * Unblock IPv6 source + */ + static void unblock4(FileDescriptor fd, int group, int interf, int source) + throws IOException + { + blockOrUnblock4(false, fd, group, interf, source); + } + + private static native int blockOrUnblock4(boolean block, FileDescriptor fd, int group, + int interf, int source) + throws IOException; + + /** + * Join IPv6 multicast group + */ + static int join6(FileDescriptor fd, byte[] group, int index, byte[] source) + throws IOException + { + return joinOrDrop6(true, fd, group, index, source); + } + + /** + * Drop membership of IPv6 multicast group + */ + static void drop6(FileDescriptor fd, byte[] group, int index, byte[] source) + throws IOException + { + joinOrDrop6(false, fd, group, index, source); + } + + private static native int joinOrDrop6(boolean join, FileDescriptor fd, byte[] group, int index, byte[] source) + throws IOException; + + /** + * Block IPv6 source + */ + static int block6(FileDescriptor fd, byte[] group, int index, byte[] source) + throws IOException + { + return blockOrUnblock6(true, fd, group, index, source); + } + + /** + * Unblock IPv6 source + */ + static void unblock6(FileDescriptor fd, byte[] group, int index, byte[] source) + throws IOException + { + blockOrUnblock6(false, fd, group, index, source); + } + + static native int blockOrUnblock6(boolean block, FileDescriptor fd, byte[] group, int index, byte[] source) + throws IOException; + + static native void setInterface4(FileDescriptor fd, int interf) throws IOException; + + static native int getInterface4(FileDescriptor fd) throws IOException; + + static native void setInterface6(FileDescriptor fd, int index) throws IOException; + + static native int getInterface6(FileDescriptor fd) throws IOException; + + /** + * Event masks for the various poll system calls. + * They will be set platform dependant in the static initializer below. + */ + public static final short POLLIN = 0x0001; + public static final short POLLCONN = 0x0002; + public static final short POLLOUT = 0x0004; + public static final short POLLERR = 0x0008; + public static final short POLLHUP = 0x0010; + public static final short POLLNVAL = 0x0020; + public static final short POLLREMOVE = 0x0800; +} diff --git a/openjdk/sun/nio/ch/SelectionKeyImpl.java b/openjdk/sun/nio/ch/SelectionKeyImpl.java new file mode 100644 index 0000000..5edc300 --- /dev/null +++ b/openjdk/sun/nio/ch/SelectionKeyImpl.java @@ -0,0 +1,118 @@ +/* + Copyright (C) 2002, 2003, 2004, 2005, 2006 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package sun.nio.ch; + +import java.nio.channels.CancelledKeyException; +import java.nio.channels.SelectableChannel; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.spi.AbstractSelectionKey; + +final class SelectionKeyImpl extends AbstractSelectionKey +{ + final SelChImpl channel; + final SelectorImpl selector; + private final cli.System.Net.Sockets.Socket socket; + private int readyOps; + private volatile int interestOps; + + SelectionKeyImpl(SelChImpl ch, SelectorImpl sel) + { + this.channel = ch; + this.selector = sel; + socket = ch.getFD().getSocket(); + } + + public SelectableChannel channel() + { + return (SelectableChannel)channel; + } + + public int readyOps() + { + if (!isValid()) + throw new CancelledKeyException(); + + return readyOps; + } + + void readyOps(int ops) + { + readyOps = ops; + } + + public synchronized int interestOps() + { + if (!isValid()) + throw new CancelledKeyException(); + + return interestOps; + } + + public synchronized SelectionKey interestOps(int ops) + { + if (!isValid()) + throw new CancelledKeyException(); + + if ((ops & ~channel.validOps()) != 0) + throw new IllegalArgumentException(); + + interestOps = ops; + return this; + } + + public Selector selector() + { + return selector; + } + + cli.System.Net.Sockets.Socket getSocket() + { + return socket; + } + + void nioReadyOps(int ops) + { + readyOps = ops; + } + + int nioReadyOps() + { + return readyOps; + } + + int nioInterestOps() + { + return interestOps; + } + + SelectionKey nioInterestOps(int ops) + { + if ((ops & ~channel().validOps()) != 0) + throw new IllegalArgumentException(); + channel.translateAndSetInterestOps(ops, this); + interestOps = ops; + return this; + } +} diff --git a/openjdk/sun/nio/ch/SocketDispatcher.java b/openjdk/sun/nio/ch/SocketDispatcher.java new file mode 100644 index 0000000..30ffd89 --- /dev/null +++ b/openjdk/sun/nio/ch/SocketDispatcher.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2000, 2013, 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.nio.ch; + +import java.io.*; +import java.net.SocketException; +import java.net.SocketUtil; +import java.nio.ByteBuffer; +import cli.System.Net.Sockets.SocketFlags; + +/** + * Allows different platforms to call different native methods + * for read and write operations. + */ + +class SocketDispatcher extends NativeDispatcher +{ + int read(FileDescriptor fd, byte[] buf, int offset, int length) throws IOException { + if (length == 0) + { + return 0; + } + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + int read = fd.getSocket().Receive(buf, offset, length, SocketFlags.wrap(SocketFlags.None)); + return read == 0 ? IOStatus.EOF : read; + } + catch (cli.System.Net.Sockets.SocketException x) + { + if (x.get_ErrorCode() == SocketUtil.WSAESHUTDOWN) + { + // the socket was shutdown, so we have to return EOF + return IOStatus.EOF; + } + else if (x.get_ErrorCode() == SocketUtil.WSAEWOULDBLOCK) + { + // nothing to read and would block + return IOStatus.UNAVAILABLE; + } + throw SocketUtil.convertSocketExceptionToIOException(x); + } + catch (cli.System.ObjectDisposedException x1) + { + throw new SocketException("Socket is closed"); + } + } + + int write(FileDescriptor fd, byte[] buf, int offset, int length) throws IOException { + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + return fd.getSocket().Send(buf, offset, length, SocketFlags.wrap(SocketFlags.None)); + } + catch (cli.System.Net.Sockets.SocketException x) + { + if (x.get_ErrorCode() == SocketUtil.WSAEWOULDBLOCK) + { + return IOStatus.UNAVAILABLE; + } + throw SocketUtil.convertSocketExceptionToIOException(x); + } + catch (cli.System.ObjectDisposedException x1) + { + throw new SocketException("Socket is closed"); + } + } + + native long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length) throws IOException; + + native long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length) throws IOException; + + void close(FileDescriptor fd) throws IOException { + } + + void preClose(FileDescriptor fd) throws IOException { + closeImpl(fd); + } + + static void closeImpl(FileDescriptor fd) throws IOException { + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + fd.getSocket().Close(); + } + catch (cli.System.Net.Sockets.SocketException x) + { + throw java.net.SocketUtil.convertSocketExceptionToIOException(x); + } + catch (cli.System.ObjectDisposedException x1) + { + throw new java.net.SocketException("Socket is closed"); + } + } +} diff --git a/openjdk/sun/nio/ch/SocketOptionRegistry.java b/openjdk/sun/nio/ch/SocketOptionRegistry.java new file mode 100644 index 0000000..f8e3306 --- /dev/null +++ b/openjdk/sun/nio/ch/SocketOptionRegistry.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2008, 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. + * + */ +// AUTOMATICALLY GENERATED FILE - DO NOT EDIT +package sun.nio.ch; +import java.net.SocketOption; +import java.net.StandardSocketOptions; +import java.net.ProtocolFamily; +import java.net.StandardProtocolFamily; +import java.util.Map; +import java.util.HashMap; +import cli.System.Net.Sockets.SocketOptionLevel; +import cli.System.Net.Sockets.SocketOptionName; +class SocketOptionRegistry { + private SocketOptionRegistry() { } + private static class RegistryKey { + private final SocketOption name; + private final ProtocolFamily family; + RegistryKey(SocketOption name, ProtocolFamily family) { + this.name = name; + this.family = family; + } + public int hashCode() { + return name.hashCode() + family.hashCode(); + } + public boolean equals(Object ob) { + if (ob == null) return false; + if (!(ob instanceof RegistryKey)) return false; + RegistryKey other = (RegistryKey)ob; + if (this.name != other.name) return false; + if (this.family != other.family) return false; + return true; + } + } + private static class LazyInitialization { + static final Map options = options(); + private static Map options() { + Map map = + new HashMap(); + map.put(new RegistryKey(StandardSocketOptions.SO_BROADCAST, Net.UNSPEC), new OptionKey(SocketOptionLevel.Socket, SocketOptionName.Broadcast)); + map.put(new RegistryKey(StandardSocketOptions.SO_KEEPALIVE, Net.UNSPEC), new OptionKey(SocketOptionLevel.Socket, SocketOptionName.KeepAlive)); + map.put(new RegistryKey(StandardSocketOptions.SO_LINGER, Net.UNSPEC), new OptionKey(SocketOptionLevel.Socket, SocketOptionName.Linger)); + map.put(new RegistryKey(StandardSocketOptions.SO_SNDBUF, Net.UNSPEC), new OptionKey(SocketOptionLevel.Socket, SocketOptionName.SendBuffer)); + map.put(new RegistryKey(StandardSocketOptions.SO_RCVBUF, Net.UNSPEC), new OptionKey(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer)); + map.put(new RegistryKey(StandardSocketOptions.SO_REUSEADDR, Net.UNSPEC), new OptionKey(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress)); + map.put(new RegistryKey(StandardSocketOptions.TCP_NODELAY, Net.UNSPEC), new OptionKey(SocketOptionLevel.Tcp, SocketOptionName.NoDelay)); + map.put(new RegistryKey(StandardSocketOptions.IP_TOS, StandardProtocolFamily.INET), new OptionKey(SocketOptionLevel.IP, SocketOptionName.TypeOfService)); + map.put(new RegistryKey(StandardSocketOptions.IP_MULTICAST_IF, StandardProtocolFamily.INET), new OptionKey(SocketOptionLevel.IP, SocketOptionName.MulticastInterface)); + map.put(new RegistryKey(StandardSocketOptions.IP_MULTICAST_TTL, StandardProtocolFamily.INET), new OptionKey(SocketOptionLevel.IP, SocketOptionName.IpTimeToLive)); + map.put(new RegistryKey(StandardSocketOptions.IP_MULTICAST_LOOP, StandardProtocolFamily.INET), new OptionKey(SocketOptionLevel.IP, SocketOptionName.MulticastLoopback)); + map.put(new RegistryKey(StandardSocketOptions.IP_TOS, StandardProtocolFamily.INET6), new OptionKey(SocketOptionLevel.IPv6, ikvm.internal.Winsock.IPV6_TCLASS)); + map.put(new RegistryKey(StandardSocketOptions.IP_MULTICAST_IF, StandardProtocolFamily.INET6), new OptionKey(SocketOptionLevel.IPv6, SocketOptionName.MulticastInterface)); + map.put(new RegistryKey(StandardSocketOptions.IP_MULTICAST_TTL, StandardProtocolFamily.INET6), new OptionKey(SocketOptionLevel.IPv6, SocketOptionName.IpTimeToLive)); + map.put(new RegistryKey(StandardSocketOptions.IP_MULTICAST_LOOP, StandardProtocolFamily.INET6), new OptionKey(SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback)); + map.put(new RegistryKey(ExtendedSocketOption.SO_OOBINLINE, Net.UNSPEC), new OptionKey(SocketOptionLevel.Socket, SocketOptionName.OutOfBandInline)); + return map; + } + } + public static OptionKey findOption(SocketOption name, ProtocolFamily family) { + RegistryKey key = new RegistryKey(name, family); + return LazyInitialization.options.get(key); + } +} diff --git a/openjdk/sun/nio/ch/Util.java b/openjdk/sun/nio/ch/Util.java new file mode 100644 index 0000000..4522419 --- /dev/null +++ b/openjdk/sun/nio/ch/Util.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2000, 2013, 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.nio.ch; + +import java.lang.ref.SoftReference; +import java.lang.reflect.*; +import java.io.IOException; +import java.io.FileDescriptor; +import java.nio.ByteBuffer; +import java.nio.MappedByteBuffer; +import java.nio.channels.*; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.*; +import sun.misc.Unsafe; +import sun.misc.Cleaner; +import sun.security.action.GetPropertyAction; + + +public class Util { + + + // -- Random stuff -- + + static ByteBuffer[] subsequence(ByteBuffer[] bs, int offset, int length) { + if ((offset == 0) && (length == bs.length)) + return bs; + int n = length; + ByteBuffer[] bs2 = new ByteBuffer[n]; + for (int i = 0; i < n; i++) + bs2[i] = bs[offset + i]; + return bs2; + } + + static Set ungrowableSet(final Set s) { + return new Set() { + + public int size() { return s.size(); } + public boolean isEmpty() { return s.isEmpty(); } + public boolean contains(Object o) { return s.contains(o); } + public Object[] toArray() { return s.toArray(); } + public T[] toArray(T[] a) { return s.toArray(a); } + public String toString() { return s.toString(); } + public Iterator iterator() { return s.iterator(); } + public boolean equals(Object o) { return s.equals(o); } + public int hashCode() { return s.hashCode(); } + public void clear() { s.clear(); } + public boolean remove(Object o) { return s.remove(o); } + + public boolean containsAll(Collection coll) { + return s.containsAll(coll); + } + public boolean removeAll(Collection coll) { + return s.removeAll(coll); + } + public boolean retainAll(Collection coll) { + return s.retainAll(coll); + } + + public boolean add(E o){ + throw new UnsupportedOperationException(); + } + public boolean addAll(Collection coll) { + throw new UnsupportedOperationException(); + } + + }; + } + + + private static volatile Constructor directByteBufferConstructor = null; + + private static void initDBBConstructor() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + try { + Class cl = Class.forName("java.nio.DirectByteBuffer"); + Constructor ctor = cl.getDeclaredConstructor( + new Class[] { int.class, + long.class, + FileDescriptor.class, + Runnable.class }); + ctor.setAccessible(true); + directByteBufferConstructor = ctor; + } catch (ClassNotFoundException | + NoSuchMethodException | + IllegalArgumentException | + ClassCastException x) { + throw new InternalError(x); + } + return null; + }}); + } + + static MappedByteBuffer newMappedByteBuffer(int size, long addr, + FileDescriptor fd, + Runnable unmapper) + { + MappedByteBuffer dbb; + if (directByteBufferConstructor == null) + initDBBConstructor(); + try { + dbb = (MappedByteBuffer)directByteBufferConstructor.newInstance( + new Object[] { new Integer(size), + new Long(addr), + fd, + unmapper }); + } catch (InstantiationException | + IllegalAccessException | + InvocationTargetException e) { + throw new InternalError(e); + } + return dbb; + } + + private static volatile Constructor directByteBufferRConstructor = null; + + private static void initDBBRConstructor() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + try { + Class cl = Class.forName("java.nio.DirectByteBufferR"); + Constructor ctor = cl.getDeclaredConstructor( + new Class[] { int.class, + long.class, + FileDescriptor.class, + Runnable.class }); + ctor.setAccessible(true); + directByteBufferRConstructor = ctor; + } catch (ClassNotFoundException | + NoSuchMethodException | + IllegalArgumentException | + ClassCastException x) { + throw new InternalError(x); + } + return null; + }}); + } + + static MappedByteBuffer newMappedByteBufferR(int size, long addr, + FileDescriptor fd, + Runnable unmapper) + { + MappedByteBuffer dbb; + if (directByteBufferRConstructor == null) + initDBBRConstructor(); + try { + dbb = (MappedByteBuffer)directByteBufferRConstructor.newInstance( + new Object[] { new Integer(size), + new Long(addr), + fd, + unmapper }); + } catch (InstantiationException | + IllegalAccessException | + InvocationTargetException e) { + throw new InternalError(e); + } + return dbb; + } + + + // -- Bug compatibility -- + + private static volatile String bugLevel = null; + + static boolean atBugLevel(String bl) { // package-private + if (bugLevel == null) { + if (!sun.misc.VM.isBooted()) + return false; + String value = AccessController.doPrivileged( + new GetPropertyAction("sun.nio.ch.bugLevel")); + bugLevel = (value != null) ? value : ""; + } + return bugLevel.equals(bl); + } + +} diff --git a/openjdk/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java b/openjdk/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java new file mode 100644 index 0000000..a13f65f --- /dev/null +++ b/openjdk/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java @@ -0,0 +1,687 @@ +/* + * Copyright (c) 2008, 2013, 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.nio.ch; + +import java.nio.channels.*; +import java.util.concurrent.*; +import java.nio.ByteBuffer; +import java.nio.BufferOverflowException; +import java.io.IOException; +import java.io.FileDescriptor; +import cli.System.AsyncCallback; +import cli.System.IAsyncResult; +import cli.System.IO.FileStream; +import cli.System.IO.SeekOrigin; + +/** + * Windows implementation of AsynchronousFileChannel using overlapped I/O. + */ + +public class WindowsAsynchronousFileChannelImpl + extends AsynchronousFileChannelImpl + implements Groupable +{ + // error when EOF is detected asynchronously. + private static final int ERROR_HANDLE_EOF = 38; + + // Lazy initialization of default I/O completion port + private static class DefaultIocpHolder { + static final Iocp defaultIocp = defaultIocp(); + private static Iocp defaultIocp() { + try { + return new Iocp(null, ThreadPool.createDefault()).start(); + } catch (IOException ioe) { + throw new InternalError(ioe); + } + } + } + + // Used for force/truncate/size methods + private static final FileDispatcher nd = new FileDispatcherImpl(); + + // I/O completion port (group) + private final Iocp iocp; + + private final boolean isDefaultIocp; + + + private WindowsAsynchronousFileChannelImpl(FileDescriptor fdObj, + boolean reading, + boolean writing, + Iocp iocp, + boolean isDefaultIocp) + throws IOException + { + super(fdObj, reading, writing, iocp.executor()); + this.iocp = iocp; + this.isDefaultIocp = isDefaultIocp; + } + + public static AsynchronousFileChannel open(FileDescriptor fdo, + boolean reading, + boolean writing, + ThreadPool pool) + throws IOException + { + Iocp iocp; + boolean isDefaultIocp; + if (pool == null) { + iocp = DefaultIocpHolder.defaultIocp; + isDefaultIocp = true; + } else { + iocp = new Iocp(null, pool).start(); + isDefaultIocp = false; + } + try { + return new + WindowsAsynchronousFileChannelImpl(fdo, reading, writing, iocp, isDefaultIocp); + } catch (IOException x) { + // error binding to port so need to close it (if created for this channel) + if (!isDefaultIocp) + iocp.implClose(); + throw x; + } + } + + @Override + public void close() throws IOException { + closeLock.writeLock().lock(); + try { + if (closed) + return; // already closed + closed = true; + } finally { + closeLock.writeLock().unlock(); + } + + // invalidate all locks held for this channel + invalidateAllLocks(); + + // close the file + fdObj.close(); + + // for the non-default group close the port + if (!isDefaultIocp) + iocp.detachFromThreadPool(); + } + + @Override + public AsynchronousChannelGroupImpl group() { + return iocp; + } + + /** + * Translates Throwable to IOException + */ + private static IOException toIOException(Throwable x) { + if (x instanceof cli.System.ArgumentException) { + return new IOException(x.getMessage()); + } + if (x instanceof cli.System.IO.IOException) { + return new IOException(x.getMessage()); + } + if (x instanceof IOException) { + if (x instanceof ClosedChannelException) + x = new AsynchronousCloseException(); + return (IOException)x; + } + return new IOException(x); + } + + @Override + public long size() throws IOException { + try { + begin(); + return nd.size(fdObj); + } finally { + end(); + } + } + + @Override + public AsynchronousFileChannel truncate(long size) throws IOException { + if (size < 0) + throw new IllegalArgumentException("Negative size"); + if (!writing) + throw new NonWritableChannelException(); + try { + begin(); + if (size > nd.size(fdObj)) + return this; + nd.truncate(fdObj, size); + } finally { + end(); + } + return this; + } + + @Override + public void force(boolean metaData) throws IOException { + try { + begin(); + nd.force(fdObj, metaData); + } finally { + end(); + } + } + + // -- file locking -- + + /** + * Task that initiates locking operation and handles completion result. + */ + private class LockTask implements Runnable, Iocp.ResultHandler { + private final long position; + private final FileLockImpl fli; + private final PendingFuture result; + + LockTask(long position, + FileLockImpl fli, + PendingFuture result) + { + this.position = position; + this.fli = fli; + this.result = result; + } + + @Override + public void run() { + FileStream fs = (FileStream)fdObj.getStream(); + for (;;) { + try { + begin(); + + try { + if (false) throw new cli.System.IO.IOException(); + fs.Lock(position, fli.size()); + result.setResult(fli); + break; + } catch (cli.System.IO.IOException _) { + // we failed to acquire the lock, try again next iteration + } + } catch (Throwable x) { + // lock failed or channel closed + removeFromFileLockTable(fli); + result.setFailure(toIOException(x)); + } finally { + end(); + } + cli.System.Threading.Thread.Sleep(100); + } + + // invoke completion handler + Invoker.invoke(result); + } + + @Override + public void completed(int bytesTransferred, boolean canInvokeDirect) { + // release waiters and invoke completion handler + result.setResult(fli); + if (canInvokeDirect) { + Invoker.invokeUnchecked(result); + } else { + Invoker.invoke(result); + } + } + + @Override + public void failed(int error, IOException x) { + // lock not acquired so remove from lock table + removeFromFileLockTable(fli); + + // release waiters + if (isOpen()) { + result.setFailure(x); + } else { + result.setFailure(new AsynchronousCloseException()); + } + Invoker.invoke(result); + } + } + + @Override + Future implLock(final long position, + final long size, + final boolean shared, + A attachment, + final CompletionHandler handler) + { + if (shared && !reading) + throw new NonReadableChannelException(); + if (!shared && !writing) + throw new NonWritableChannelException(); + + // add to lock table + FileLockImpl fli = addToFileLockTable(position, size, shared); + if (fli == null) { + Throwable exc = new ClosedChannelException(); + if (handler == null) + return CompletedFuture.withFailure(exc); + Invoker.invoke(this, handler, attachment, null, exc); + return null; + } + + // create Future and task that will be invoked to acquire lock + PendingFuture result = + new PendingFuture(this, handler, attachment); + LockTask lockTask = new LockTask(position, fli, result); + result.setContext(lockTask); + + // initiate I/O + if (false) { + lockTask.run(); + } else { + boolean executed = false; + try { + Invoker.invokeOnThreadInThreadPool(this, lockTask); + executed = true; + } finally { + if (!executed) { + // rollback + removeFromFileLockTable(fli); + } + } + } + return result; + } + + static final int NO_LOCK = -1; // Failed to lock + static final int LOCKED = 0; // Obtained requested lock + + @Override + public FileLock tryLock(long position, long size, boolean shared) + throws IOException + { + if (shared && !reading) + throw new NonReadableChannelException(); + if (!shared && !writing) + throw new NonWritableChannelException(); + + // add to lock table + final FileLockImpl fli = addToFileLockTable(position, size, shared); + if (fli == null) + throw new ClosedChannelException(); + + boolean gotLock = false; + try { + begin(); + // try to acquire the lock + int res; + try { + if (false) throw new cli.System.IO.IOException(); + FileStream fs = (FileStream)fdObj.getStream(); + fs.Lock(position, size); + res = LOCKED; + } catch (cli.System.IO.IOException _) { + res = NO_LOCK; + } + if (res == NO_LOCK) + return null; + gotLock = true; + return fli; + } finally { + if (!gotLock) + removeFromFileLockTable(fli); + end(); + } + } + + @Override + protected void implRelease(FileLockImpl fli) throws IOException { + try { + if (false) throw new cli.System.IO.IOException(); + FileStream fs = (FileStream)fdObj.getStream(); + fs.Unlock(fli.position(), fli.size()); + } catch (cli.System.IO.IOException x) { + if (!FileDispatcherImpl.NotLockedHack.isErrorNotLocked(x)) { + throw new IOException(x.getMessage()); + } + } + } + + /** + * Task that initiates read operation and handles completion result. + */ + private class ReadTask implements Runnable, Iocp.ResultHandler, AsyncCallback.Method { + private final ByteBuffer dst; + private final int pos, rem; // buffer position/remaining + private final long position; // file position + private final PendingFuture result; + + // set to dst if direct; otherwise set to substituted direct buffer + private volatile ByteBuffer buf; + + ReadTask(ByteBuffer dst, + int pos, + int rem, + long position, + PendingFuture result) + { + this.dst = dst; + this.pos = pos; + this.rem = rem; + this.position = position; + this.result = result; + } + + void updatePosition(int bytesTransferred) { + // if the I/O succeeded then adjust buffer position + if (bytesTransferred > 0) { + if (buf == dst) { + try { + dst.position(pos + bytesTransferred); + } catch (IllegalArgumentException x) { + // someone has changed the position; ignore + } + } else { + // had to substitute direct buffer + buf.position(bytesTransferred).flip(); + try { + dst.put(buf); + } catch (BufferOverflowException x) { + // someone has changed the position; ignore + } + } + } + } + + @Override + public void run() { + // Substitute an array backed buffer if not + if (dst.hasArray()) { + buf = dst; + } else { + buf = ByteBuffer.allocate(rem); + } + + try { + begin(); + + // initiate read + FileStream fs = (FileStream)fdObj.getStream(); + fs.Seek(position, SeekOrigin.wrap(SeekOrigin.Begin)); + fs.BeginRead(buf.array(), buf.arrayOffset() + pos, rem, new AsyncCallback(this), null); + return; + + } catch (Throwable x) { + // failed to initiate read + result.setFailure(toIOException(x)); + } finally { + end(); + } + + // invoke completion handler + Invoker.invoke(result); + } + + public void Invoke(IAsyncResult ar) { + try { + FileStream fs = (FileStream)fdObj.getStream(); + completed(fs.EndRead(ar), false); + } catch (Throwable x) { + failed(0, toIOException(x)); + } + } + + /** + * Executed when the I/O has completed + */ + @Override + public void completed(int bytesTransferred, boolean canInvokeDirect) { + updatePosition(bytesTransferred); + + // release waiters and invoke completion handler + result.setResult(bytesTransferred); + if (canInvokeDirect) { + Invoker.invokeUnchecked(result); + } else { + Invoker.invoke(result); + } + } + + @Override + public void failed(int error, IOException x) { + // if EOF detected asynchronously then it is reported as error + if (error == ERROR_HANDLE_EOF) { + completed(-1, false); + } else { + // release waiters + if (isOpen()) { + result.setFailure(x); + } else { + result.setFailure(new AsynchronousCloseException()); + } + Invoker.invoke(result); + } + } + } + + @Override + Future implRead(ByteBuffer dst, + long position, + A attachment, + CompletionHandler handler) + { + if (!reading) + throw new NonReadableChannelException(); + if (position < 0) + throw new IllegalArgumentException("Negative position"); + if (dst.isReadOnly()) + throw new IllegalArgumentException("Read-only buffer"); + + // check if channel is closed + if (!isOpen()) { + Throwable exc = new ClosedChannelException(); + if (handler == null) + return CompletedFuture.withFailure(exc); + Invoker.invoke(this, handler, attachment, null, exc); + return null; + } + + int pos = dst.position(); + int lim = dst.limit(); + assert (pos <= lim); + int rem = (pos <= lim ? lim - pos : 0); + + // no space remaining + if (rem == 0) { + if (handler == null) + return CompletedFuture.withResult(0); + Invoker.invoke(this, handler, attachment, 0, null); + return null; + } + + // create Future and task that initiates read + PendingFuture result = + new PendingFuture(this, handler, attachment); + ReadTask readTask = new ReadTask(dst, pos, rem, position, result); + result.setContext(readTask); + + // initiate I/O + if (Iocp.supportsThreadAgnosticIo()) { + readTask.run(); + } else { + Invoker.invokeOnThreadInThreadPool(this, readTask); + } + return result; + } + + /** + * Task that initiates write operation and handles completion result. + */ + private class WriteTask implements Runnable, Iocp.ResultHandler, AsyncCallback.Method { + private final ByteBuffer src; + private final int pos, rem; // buffer position/remaining + private final long position; // file position + private final PendingFuture result; + + // set to src if direct; otherwise set to substituted direct buffer + private volatile ByteBuffer buf; + + WriteTask(ByteBuffer src, + int pos, + int rem, + long position, + PendingFuture result) + { + this.src = src; + this.pos = pos; + this.rem = rem; + this.position = position; + this.result = result; + } + + void updatePosition(int bytesTransferred) { + // if the I/O succeeded then adjust buffer position + if (bytesTransferred > 0) { + try { + src.position(pos + bytesTransferred); + } catch (IllegalArgumentException x) { + // someone has changed the position + } + } + } + + @Override + public void run() { + // Substitute an array backed buffer if not + if (src.hasArray()) { + buf = src; + } else { + buf = ByteBuffer.allocate(rem); + buf.put(src); + buf.flip(); + // temporarily restore position as we don't know how many bytes + // will be written + src.position(pos); + } + + try { + begin(); + + // initiate the write + FileStream fs = (FileStream)fdObj.getStream(); + fs.Seek(position, SeekOrigin.wrap(SeekOrigin.Begin)); + fs.BeginWrite(buf.array(), buf.arrayOffset() + pos, rem, new AsyncCallback(this), null); + return; + + } catch (Throwable x) { + // failed to initiate read: + result.setFailure(toIOException(x)); + + } finally { + end(); + } + + // invoke completion handler + Invoker.invoke(result); + } + + public void Invoke(IAsyncResult ar) { + try { + FileStream fs = (FileStream)fdObj.getStream(); + fs.EndWrite(ar); + completed(rem, false); + } catch (Throwable x) { + failed(0, toIOException(x)); + } + } + + /** + * Executed when the I/O has completed + */ + @Override + public void completed(int bytesTransferred, boolean canInvokeDirect) { + updatePosition(bytesTransferred); + + // release waiters and invoke completion handler + result.setResult(bytesTransferred); + if (canInvokeDirect) { + Invoker.invokeUnchecked(result); + } else { + Invoker.invoke(result); + } + } + + @Override + public void failed(int error, IOException x) { + // release waiters and invoker completion handler + if (isOpen()) { + result.setFailure(x); + } else { + result.setFailure(new AsynchronousCloseException()); + } + Invoker.invoke(result); + } + } + + Future implWrite(ByteBuffer src, + long position, + A attachment, + CompletionHandler handler) + { + if (!writing) + throw new NonWritableChannelException(); + if (position < 0) + throw new IllegalArgumentException("Negative position"); + + // check if channel is closed + if (!isOpen()) { + Throwable exc = new ClosedChannelException(); + if (handler == null) + return CompletedFuture.withFailure(exc); + Invoker.invoke(this, handler, attachment, null, exc); + return null; + } + + int pos = src.position(); + int lim = src.limit(); + assert (pos <= lim); + int rem = (pos <= lim ? lim - pos : 0); + + // nothing to write + if (rem == 0) { + if (handler == null) + return CompletedFuture.withResult(0); + Invoker.invoke(this, handler, attachment, 0, null); + return null; + } + + // create Future and task to initiate write + PendingFuture result = + new PendingFuture(this, handler, attachment); + WriteTask writeTask = new WriteTask(src, pos, rem, position, result); + result.setContext(writeTask); + + // initiate I/O + if (Iocp.supportsThreadAgnosticIo()) { + writeTask.run(); + } else { + Invoker.invokeOnThreadInThreadPool(this, writeTask); + } + return result; + } +} diff --git a/openjdk/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java b/openjdk/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java new file mode 100644 index 0000000..b8cae29 --- /dev/null +++ b/openjdk/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2008, 2013, 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.nio.ch; + +import java.nio.channels.*; +import java.net.InetSocketAddress; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicBoolean; +import java.io.FileDescriptor; +import java.io.IOException; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * Windows implementation of AsynchronousServerSocketChannel using overlapped I/O. + */ + +class WindowsAsynchronousServerSocketChannelImpl + extends AsynchronousServerSocketChannelImpl +{ + private final Iocp iocp; + + // flag to indicate that an accept operation is outstanding + private AtomicBoolean accepting = new AtomicBoolean(); + + + WindowsAsynchronousServerSocketChannelImpl(Iocp iocp) throws IOException { + super(iocp); + + this.iocp = iocp; + } + + @Override + void implClose() throws IOException { + // close socket (which may cause outstanding accept to be aborted). + SocketDispatcher.closeImpl(fd); + } + + @Override + public AsynchronousChannelGroupImpl group() { + return iocp; + } + + /** + * Task to initiate accept operation and to handle result. + */ + private class AcceptTask implements Runnable, Iocp.ResultHandler { + private final WindowsAsynchronousSocketChannelImpl channel; + private final AccessControlContext acc; + private final PendingFuture result; + + AcceptTask(WindowsAsynchronousSocketChannelImpl channel, + AccessControlContext acc, + PendingFuture result) + { + this.channel = channel; + this.acc = acc; + this.result = result; + } + + void enableAccept() { + accepting.set(false); + } + + void closeChildChannel() { + try { + channel.close(); + } catch (IOException ignore) { } + } + + // caller must have acquired read lock for the listener and child channel. + void finishAccept() throws IOException { + /** + * Set local/remote addresses. This is currently very inefficient + * in that it requires 2 calls to getsockname and 2 calls to getpeername. + * (should change this to use GetAcceptExSockaddrs) + */ + updateAcceptContext(fd, channel.fd); + + InetSocketAddress local = Net.localAddress(channel.fd); + final InetSocketAddress remote = Net.remoteAddress(channel.fd); + channel.setConnected(local, remote); + + // permission check (in context of initiating thread) + if (acc != null) { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + SecurityManager sm = System.getSecurityManager(); + sm.checkAccept(remote.getAddress().getHostAddress(), + remote.getPort()); + return null; + } + }, acc); + } + } + + /** + * Initiates the accept operation. + */ + @Override + public void run() { + + try { + // begin usage of listener socket + begin(); + try { + // begin usage of child socket (as it is registered with + // completion port and so may be closed in the event that + // the group is forcefully closed). + channel.begin(); + + synchronized (result) { + + int n = accept0(fd, channel.fd, this); + if (n == IOStatus.UNAVAILABLE) { + return; + } + + // connection accepted immediately + finishAccept(); + + // allow another accept before the result is set + enableAccept(); + result.setResult(channel); + } + } finally { + // end usage on child socket + channel.end(); + } + } catch (Throwable x) { + // failed to initiate accept so release resources + closeChildChannel(); + if (x instanceof ClosedChannelException) + x = new AsynchronousCloseException(); + if (!(x instanceof IOException) && !(x instanceof SecurityException)) + x = new IOException(x); + enableAccept(); + result.setFailure(x); + } finally { + // end of usage of listener socket + end(); + } + + // accept completed immediately but may not have executed on + // initiating thread in which case the operation may have been + // cancelled. + if (result.isCancelled()) { + closeChildChannel(); + } + + // invoke completion handler + Invoker.invokeIndirectly(result); + } + + /** + * Executed when the I/O has completed + */ + @Override + public void completed(int bytesTransferred, boolean canInvokeDirect) { + try { + // connection accept after group has shutdown + if (iocp.isShutdown()) { + throw new IOException(new ShutdownChannelGroupException()); + } + + // finish the accept + try { + begin(); + try { + channel.begin(); + finishAccept(); + } finally { + channel.end(); + } + } finally { + end(); + } + + // allow another accept before the result is set + enableAccept(); + result.setResult(channel); + } catch (Throwable x) { + enableAccept(); + closeChildChannel(); + if (x instanceof ClosedChannelException) + x = new AsynchronousCloseException(); + if (!(x instanceof IOException) && !(x instanceof SecurityException)) + x = new IOException(x); + result.setFailure(x); + } + + // if an async cancel has already cancelled the operation then + // close the new channel so as to free resources + if (result.isCancelled()) { + closeChildChannel(); + } + + // invoke handler (but not directly) + Invoker.invokeIndirectly(result); + } + + @Override + public void failed(int error, IOException x) { + enableAccept(); + closeChildChannel(); + + // release waiters + if (isOpen()) { + result.setFailure(x); + } else { + result.setFailure(new AsynchronousCloseException()); + } + Invoker.invokeIndirectly(result); + } + } + + @Override + Future implAccept(Object attachment, + final CompletionHandler handler) + { + if (!isOpen()) { + Throwable exc = new ClosedChannelException(); + if (handler == null) + return CompletedFuture.withFailure(exc); + Invoker.invokeIndirectly(this, handler, attachment, null, exc); + return null; + } + if (isAcceptKilled()) + throw new RuntimeException("Accept not allowed due to cancellation"); + + // ensure channel is bound to local address + if (localAddress == null) + throw new NotYetBoundException(); + + // create the socket that will be accepted. The creation of the socket + // is enclosed by a begin/end for the listener socket to ensure that + // we check that the listener is open and also to prevent the I/O + // port from being closed as the new socket is registered. + WindowsAsynchronousSocketChannelImpl ch = null; + IOException ioe = null; + try { + begin(); + ch = new WindowsAsynchronousSocketChannelImpl(iocp, false); + } catch (IOException x) { + ioe = x; + } finally { + end(); + } + if (ioe != null) { + if (handler == null) + return CompletedFuture.withFailure(ioe); + Invoker.invokeIndirectly(this, handler, attachment, null, ioe); + return null; + } + + // need calling context when there is security manager as + // permission check may be done in a different thread without + // any application call frames on the stack + AccessControlContext acc = (System.getSecurityManager() == null) ? + null : AccessController.getContext(); + + PendingFuture result = + new PendingFuture(this, handler, attachment); + AcceptTask task = new AcceptTask(ch, acc, result); + result.setContext(task); + + // check and set flag to prevent concurrent accepting + if (!accepting.compareAndSet(false, true)) + throw new AcceptPendingException(); + + // initiate I/O + if (Iocp.supportsThreadAgnosticIo()) { + task.run(); + } else { + Invoker.invokeOnThreadInThreadPool(this, task); + } + return result; + } + + // -- Native methods -- + + private static native void initIDs(); + + private static native int accept0(FileDescriptor listenSocket, FileDescriptor acceptSocket, + Iocp.ResultHandler handler) throws IOException; + + private static native void updateAcceptContext(FileDescriptor listenSocket, + FileDescriptor acceptSocket) throws IOException; + + private static native void closesocket0(long socket) throws IOException; + + static { + IOUtil.load(); + initIDs(); + } +} diff --git a/openjdk/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java b/openjdk/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java new file mode 100644 index 0000000..5aa53e9 --- /dev/null +++ b/openjdk/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java @@ -0,0 +1,842 @@ +/* + * Copyright (c) 2008, 2013, 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.nio.ch; + +import java.nio.channels.*; +import java.nio.ByteBuffer; +import java.nio.BufferOverflowException; +import java.net.*; +import java.util.concurrent.*; +import java.io.FileDescriptor; +import java.io.IOException; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; + +/** + * Windows implementation of AsynchronousSocketChannel using overlapped I/O. + */ + +class WindowsAsynchronousSocketChannelImpl + extends AsynchronousSocketChannelImpl +{ + // maximum vector size for scatter/gather I/O + private static final int MAX_WSABUF = 16; + + // I/O completion port that the socket is associated with + private final Iocp iocp; + + + WindowsAsynchronousSocketChannelImpl(Iocp iocp, boolean failIfGroupShutdown) + throws IOException + { + super(iocp); + + this.iocp = iocp; + } + + WindowsAsynchronousSocketChannelImpl(Iocp iocp) throws IOException { + this(iocp, true); + } + + @Override + public AsynchronousChannelGroupImpl group() { + return iocp; + } + + // invoked by WindowsAsynchronousServerSocketChannelImpl when new connection + // accept + void setConnected(InetSocketAddress localAddress, + InetSocketAddress remoteAddress) + { + synchronized (stateLock) { + state = ST_CONNECTED; + this.localAddress = localAddress; + this.remoteAddress = remoteAddress; + } + } + + @Override + void implClose() throws IOException { + // close socket (may cause outstanding async I/O operations to fail). + SocketDispatcher.closeImpl(fd); + } + + @Override + public void onCancel(PendingFuture task) { + if (task.getContext() instanceof ConnectTask) + killConnect(); + if (task.getContext() instanceof ReadTask) + killReading(); + if (task.getContext() instanceof WriteTask) + killWriting(); + } + + /** + * Implements the task to initiate a connection and the handler to + * consume the result when the connection is established (or fails). + */ + private class ConnectTask implements Runnable, Iocp.ResultHandler { + private final InetSocketAddress remote; + private final PendingFuture result; + + ConnectTask(InetSocketAddress remote, PendingFuture result) { + this.remote = remote; + this.result = result; + } + + private void closeChannel() { + try { + close(); + } catch (IOException ignore) { } + } + + private IOException toIOException(Throwable x) { + if (x instanceof IOException) { + if (x instanceof ClosedChannelException) + x = new AsynchronousCloseException(); + return (IOException)x; + } + return new IOException(x); + } + + /** + * Invoke after a connection is successfully established. + */ + private void afterConnect() throws IOException { + updateConnectContext(fd); + synchronized (stateLock) { + state = ST_CONNECTED; + remoteAddress = remote; + } + } + + /** + * Task to initiate a connection. + */ + @Override + public void run() { + Throwable exc = null; + try { + begin(); + + // synchronize on result to allow this thread handle the case + // where the connection is established immediately. + synchronized (result) { + // initiate the connection + int n = connect0(fd, Net.isIPv6Available(), remote.getAddress(), + remote.getPort(), this); + if (n == IOStatus.UNAVAILABLE) { + // connection is pending + return; + } + + // connection established immediately + afterConnect(); + result.setResult(null); + } + } catch (Throwable x) { + exc = x; + } finally { + end(); + } + + if (exc != null) { + closeChannel(); + result.setFailure(toIOException(exc)); + } + Invoker.invoke(result); + } + + /** + * Invoked by handler thread when connection established. + */ + @Override + public void completed(int bytesTransferred, boolean canInvokeDirect) { + Throwable exc = null; + try { + begin(); + afterConnect(); + result.setResult(null); + } catch (Throwable x) { + // channel is closed or unable to finish connect + exc = x; + } finally { + end(); + } + + // can't close channel while in begin/end block + if (exc != null) { + closeChannel(); + result.setFailure(toIOException(exc)); + } + + if (canInvokeDirect) { + Invoker.invokeUnchecked(result); + } else { + Invoker.invoke(result); + } + } + + /** + * Invoked by handler thread when failed to establish connection. + */ + @Override + public void failed(int error, IOException x) { + if (isOpen()) { + closeChannel(); + result.setFailure(x); + } else { + result.setFailure(new AsynchronousCloseException()); + } + Invoker.invoke(result); + } + } + + private void doPrivilegedBind(final SocketAddress sa) throws IOException { + try { + AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Void run() throws IOException { + bind(sa); + return null; + } + }); + } catch (PrivilegedActionException e) { + throw (IOException) e.getException(); + } + } + + @Override + Future implConnect(SocketAddress remote, + A attachment, + CompletionHandler handler) + { + if (!isOpen()) { + Throwable exc = new ClosedChannelException(); + if (handler == null) + return CompletedFuture.withFailure(exc); + Invoker.invoke(this, handler, attachment, null, exc); + return null; + } + + InetSocketAddress isa = Net.checkAddress(remote); + + // permission check + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort()); + + // check and update state + // ConnectEx requires the socket to be bound to a local address + IOException bindException = null; + synchronized (stateLock) { + if (state == ST_CONNECTED) + throw new AlreadyConnectedException(); + if (state == ST_PENDING) + throw new ConnectionPendingException(); + if (localAddress == null) { + try { + SocketAddress any = new InetSocketAddress(0); + if (sm == null) { + bind(any); + } else { + doPrivilegedBind(any); + } + } catch (IOException x) { + bindException = x; + } + } + if (bindException == null) + state = ST_PENDING; + } + + // handle bind failure + if (bindException != null) { + try { + close(); + } catch (IOException ignore) { } + if (handler == null) + return CompletedFuture.withFailure(bindException); + Invoker.invoke(this, handler, attachment, null, bindException); + return null; + } + + // setup task + PendingFuture result = + new PendingFuture(this, handler, attachment); + ConnectTask task = new ConnectTask(isa, result); + result.setContext(task); + + // initiate I/O + if (Iocp.supportsThreadAgnosticIo()) { + task.run(); + } else { + Invoker.invokeOnThreadInThreadPool(this, task); + } + return result; + } + + /** + * Implements the task to initiate a read and the handler to consume the + * result when the read completes. + */ + private class ReadTask implements Runnable, Iocp.ResultHandler { + private final ByteBuffer[] bufs; + private final int numBufs; + private final boolean scatteringRead; + private final PendingFuture result; + + // set by run method + private ByteBuffer[] shadow; + + ReadTask(ByteBuffer[] bufs, + boolean scatteringRead, + PendingFuture result) + { + this.bufs = bufs; + this.numBufs = (bufs.length > MAX_WSABUF) ? MAX_WSABUF : bufs.length; + this.scatteringRead = scatteringRead; + this.result = result; + } + + /** + * Invoked prior to read to prepare the WSABUF array. Where necessary, + * it substitutes direct buffers with managed buffers. + */ + void prepareBuffers() { + shadow = new ByteBuffer[numBufs]; + for (int i=0; i= len) { + bytesRead -= len; + int newPosition = pos + len; + try { + nextBuffer.position(newPosition); + } catch (IllegalArgumentException x) { + // position changed by another + } + } else { // Buffers not completely filled + if (bytesRead > 0) { + assert(pos + bytesRead < (long)Integer.MAX_VALUE); + int newPosition = pos + bytesRead; + try { + nextBuffer.position(newPosition); + } catch (IllegalArgumentException x) { + // position changed by another + } + } + break; + } + } + + // Put results from shadow into the slow buffers + for (int i=0; i Future implRead(boolean isScatteringRead, + ByteBuffer dst, + ByteBuffer[] dsts, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler) + { + // setup task + PendingFuture result = + new PendingFuture(this, handler, attachment); + ByteBuffer[] bufs; + if (isScatteringRead) { + bufs = dsts; + } else { + bufs = new ByteBuffer[1]; + bufs[0] = dst; + } + final ReadTask readTask = + new ReadTask(bufs, isScatteringRead, result); + result.setContext(readTask); + + // schedule timeout + if (timeout > 0L) { + Future timeoutTask = iocp.schedule(new Runnable() { + public void run() { + readTask.timeout(); + } + }, timeout, unit); + result.setTimeoutTask(timeoutTask); + } + + // initiate I/O + if (Iocp.supportsThreadAgnosticIo()) { + readTask.run(); + } else { + Invoker.invokeOnThreadInThreadPool(this, readTask); + } + return result; + } + + /** + * Implements the task to initiate a write and the handler to consume the + * result when the write completes. + */ + private class WriteTask implements Runnable, Iocp.ResultHandler { + private final ByteBuffer[] bufs; + private final int numBufs; + private final boolean gatheringWrite; + private final PendingFuture result; + + // set by run method + private ByteBuffer[] shadow; + + WriteTask(ByteBuffer[] bufs, + boolean gatheringWrite, + PendingFuture result) + { + this.bufs = bufs; + this.numBufs = (bufs.length > MAX_WSABUF) ? MAX_WSABUF : bufs.length; + this.gatheringWrite = gatheringWrite; + this.result = result; + } + + /** + * Invoked prior to write to prepare the WSABUF array. Where necessary, + * it substitutes direct buffers with managed buffers. + */ + void prepareBuffers() { + shadow = new ByteBuffer[numBufs]; + for (int i=0; i= len) { + bytesWritten -= len; + int newPosition = pos + len; + try { + nextBuffer.position(newPosition); + } catch (IllegalArgumentException x) { + // position changed by someone else + } + } else { // Buffers not completely filled + if (bytesWritten > 0) { + assert(pos + bytesWritten < (long)Integer.MAX_VALUE); + int newPosition = pos + bytesWritten; + try { + nextBuffer.position(newPosition); + } catch (IllegalArgumentException x) { + // position changed by someone else + } + } + break; + } + } + } + + void releaseBuffers() { + } + + @Override + //@SuppressWarnings("unchecked") + public void run() { + boolean prepared = false; + boolean pending = false; + boolean shutdown = false; + + try { + begin(); + + // substitute direct buffers + prepareBuffers(); + prepared = true; + + int n = write0(fd, shadow, this); + if (n == IOStatus.UNAVAILABLE) { + // I/O is pending + pending = true; + return; + } + if (n == IOStatus.EOF) { + // special case for shutdown output + shutdown = true; + throw new ClosedChannelException(); + } + // write completed immediately + updateBuffers(n); + releaseBuffers(); + enableWriting(); + if (gatheringWrite) { + result.setResult((V)Long.valueOf(n)); + } else { + result.setResult((V)Integer.valueOf(n)); + } + } catch (Throwable x) { + // write failed. Enable writing before releasing waiters. + enableWriting(); + if (!shutdown && (x instanceof ClosedChannelException)) + x = new AsynchronousCloseException(); + if (!(x instanceof IOException)) + x = new IOException(x); + result.setFailure(x); + } finally { + // release resources if I/O not pending + if (!pending) { + if (prepared) + releaseBuffers(); + } + end(); + } + + // invoke completion handler + Invoker.invoke(result); + } + + /** + * Executed when the I/O has completed + */ + @Override + @SuppressWarnings("unchecked") + public void completed(int bytesTransferred, boolean canInvokeDirect) { + updateBuffers(bytesTransferred); + + // return direct buffer to cache if substituted + releaseBuffers(); + + // release waiters if not already released by timeout + synchronized (result) { + if (result.isDone()) + return; + enableWriting(); + if (gatheringWrite) { + result.setResult((V)Long.valueOf(bytesTransferred)); + } else { + result.setResult((V)Integer.valueOf(bytesTransferred)); + } + } + if (canInvokeDirect) { + Invoker.invokeUnchecked(result); + } else { + Invoker.invoke(result); + } + } + + @Override + public void failed(int error, IOException x) { + // return direct buffer to cache if substituted + releaseBuffers(); + + // release waiters if not already released by timeout + if (!isOpen()) + x = new AsynchronousCloseException(); + + synchronized (result) { + if (result.isDone()) + return; + enableWriting(); + result.setFailure(x); + } + Invoker.invoke(result); + } + + /** + * Invoked if timeout expires before it is cancelled + */ + void timeout() { + // synchronize on result as the I/O could complete/fail + synchronized (result) { + if (result.isDone()) + return; + + // kill further writing before releasing waiters + enableWriting(true); + result.setFailure(new InterruptedByTimeoutException()); + } + + // invoke handler without any locks + Invoker.invoke(result); + } + } + + @Override + Future implWrite(boolean gatheringWrite, + ByteBuffer src, + ByteBuffer[] srcs, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler) + { + // setup task + PendingFuture result = + new PendingFuture(this, handler, attachment); + ByteBuffer[] bufs; + if (gatheringWrite) { + bufs = srcs; + } else { + bufs = new ByteBuffer[1]; + bufs[0] = src; + } + final WriteTask writeTask = + new WriteTask(bufs, gatheringWrite, result); + result.setContext(writeTask); + + // schedule timeout + if (timeout > 0L) { + Future timeoutTask = iocp.schedule(new Runnable() { + public void run() { + writeTask.timeout(); + } + }, timeout, unit); + result.setTimeoutTask(timeoutTask); + } + + // initiate I/O (can only be done from thread in thread pool) + // initiate I/O + if (Iocp.supportsThreadAgnosticIo()) { + writeTask.run(); + } else { + Invoker.invokeOnThreadInThreadPool(this, writeTask); + } + return result; + } + + // -- Native methods -- + + private static native void initIDs(); + + private static native int connect0(FileDescriptor fd, boolean preferIPv6, + InetAddress remote, int remotePort, Iocp.ResultHandler handler) throws IOException; + + private static native void updateConnectContext(FileDescriptor fd) throws IOException; + + private static native int read0(FileDescriptor fd, ByteBuffer[] bufs, Iocp.ResultHandler handler) + throws IOException; + + private static native int write0(FileDescriptor fd, ByteBuffer[] bufs, Iocp.ResultHandler handler) + throws IOException; + + private static native void shutdown0(long socket, int how) throws IOException; + + private static native void closesocket0(long socket) throws IOException; + + static { + IOUtil.load(); + initIDs(); + } +} diff --git a/openjdk/sun/nio/cs/StandardCharsets.java b/openjdk/sun/nio/cs/StandardCharsets.java new file mode 100644 index 0000000..b2f3b1b --- /dev/null +++ b/openjdk/sun/nio/cs/StandardCharsets.java @@ -0,0 +1,715 @@ +/* + * Copyright (c) 2000, 2007, 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. + * + */ + +// -- This file was mechanically generated: Do not edit! -- // + +package sun.nio.cs; + +import java.nio.charset.*; + + +public class StandardCharsets + extends FastCharsetProvider +{ + + static final String[] aliases_US_ASCII = new String[] { + "iso-ir-6", + "ANSI_X3.4-1986", + "ISO_646.irv:1991", + "ASCII", + "ISO646-US", + "us", + "IBM367", + "cp367", + "csASCII", + "default", + "646", + "iso_646.irv:1983", + "ANSI_X3.4-1968", + "ascii7", + }; + + static final String[] aliases_UTF_8 = new String[] { + "UTF8", + "unicode-1-1-utf-8", + }; + + static final String[] aliases_CESU_8 = new String[] { + "CESU8", + "csCESU-8", + }; + + static final String[] aliases_UTF_16 = new String[] { + "UTF_16", + "utf16", + "unicode", + "UnicodeBig", + }; + + static final String[] aliases_UTF_16BE = new String[] { + "UTF_16BE", + "ISO-10646-UCS-2", + "X-UTF-16BE", + "UnicodeBigUnmarked", + }; + + static final String[] aliases_UTF_16LE = new String[] { + "UTF_16LE", + "X-UTF-16LE", + "UnicodeLittleUnmarked", + }; + + static final String[] aliases_UTF_16LE_BOM = new String[] { + "UnicodeLittle", + }; + + static final String[] aliases_UTF_32 = new String[] { + "UTF_32", + "UTF32", + }; + + static final String[] aliases_UTF_32LE = new String[] { + "UTF_32LE", + "X-UTF-32LE", + }; + + static final String[] aliases_UTF_32BE = new String[] { + "UTF_32BE", + "X-UTF-32BE", + }; + + static final String[] aliases_UTF_32LE_BOM = new String[] { + "UTF_32LE_BOM", + "UTF-32LE-BOM", + }; + + static final String[] aliases_UTF_32BE_BOM = new String[] { + "UTF_32BE_BOM", + "UTF-32BE-BOM", + }; + + static final String[] aliases_ISO_8859_1 = new String[] { + "iso-ir-100", + "ISO_8859-1", + "latin1", + "l1", + "IBM819", + "cp819", + "csISOLatin1", + "819", + "IBM-819", + "ISO8859_1", + "ISO_8859-1:1987", + "ISO_8859_1", + "8859_1", + "ISO8859-1", + }; + + static final String[] aliases_ISO_8859_2 = new String[] { + "iso8859_2", + "8859_2", + "iso-ir-101", + "ISO_8859-2", + "ISO_8859-2:1987", + "ISO8859-2", + "latin2", + "l2", + "ibm912", + "ibm-912", + "cp912", + "912", + "csISOLatin2", + }; + + static final String[] aliases_ISO_8859_4 = new String[] { + "iso8859_4", + "iso8859-4", + "8859_4", + "iso-ir-110", + "ISO_8859-4", + "ISO_8859-4:1988", + "latin4", + "l4", + "ibm914", + "ibm-914", + "cp914", + "914", + "csISOLatin4", + }; + + static final String[] aliases_ISO_8859_5 = new String[] { + "iso8859_5", + "8859_5", + "iso-ir-144", + "ISO_8859-5", + "ISO_8859-5:1988", + "ISO8859-5", + "cyrillic", + "ibm915", + "ibm-915", + "cp915", + "915", + "csISOLatinCyrillic", + }; + + static final String[] aliases_ISO_8859_7 = new String[] { + "iso8859_7", + "8859_7", + "iso-ir-126", + "ISO_8859-7", + "ISO_8859-7:1987", + "ELOT_928", + "ECMA-118", + "greek", + "greek8", + "csISOLatinGreek", + "sun_eu_greek", + "ibm813", + "ibm-813", + "813", + "cp813", + "iso8859-7", + }; + + static final String[] aliases_ISO_8859_9 = new String[] { + "iso8859_9", + "8859_9", + "iso-ir-148", + "ISO_8859-9", + "ISO_8859-9:1989", + "ISO8859-9", + "latin5", + "l5", + "ibm920", + "ibm-920", + "920", + "cp920", + "csISOLatin5", + }; + + static final String[] aliases_ISO_8859_13 = new String[] { + "iso8859_13", + "8859_13", + "iso_8859-13", + "ISO8859-13", + }; + + static final String[] aliases_ISO_8859_15 = new String[] { + "ISO_8859-15", + "8859_15", + "ISO-8859-15", + "ISO8859_15", + "ISO8859-15", + "IBM923", + "IBM-923", + "cp923", + "923", + "LATIN0", + "LATIN9", + "L9", + "csISOlatin0", + "csISOlatin9", + "ISO8859_15_FDIS", + }; + + static final String[] aliases_KOI8_R = new String[] { + "koi8_r", + "koi8", + "cskoi8r", + }; + + static final String[] aliases_KOI8_U = new String[] { + "koi8_u", + }; + + static final String[] aliases_MS1250 = new String[] { + "cp1250", + "cp5346", + }; + + static final String[] aliases_MS1251 = new String[] { + "cp1251", + "cp5347", + "ansi-1251", + }; + + static final String[] aliases_MS1252 = new String[] { + "cp1252", + "cp5348", + }; + + static final String[] aliases_MS1253 = new String[] { + "cp1253", + "cp5349", + }; + + static final String[] aliases_MS1254 = new String[] { + "cp1254", + "cp5350", + }; + + static final String[] aliases_MS1257 = new String[] { + "cp1257", + "cp5353", + }; + + static final String[] aliases_IBM437 = new String[] { + "cp437", + "ibm437", + "ibm-437", + "437", + "cspc8codepage437", + "windows-437", + }; + + static final String[] aliases_IBM737 = new String[] { + "cp737", + "ibm737", + "ibm-737", + "737", + }; + + static final String[] aliases_IBM775 = new String[] { + "cp775", + "ibm775", + "ibm-775", + "775", + }; + + static final String[] aliases_IBM850 = new String[] { + "cp850", + "ibm-850", + "ibm850", + "850", + "cspc850multilingual", + }; + + static final String[] aliases_IBM852 = new String[] { + "cp852", + "ibm852", + "ibm-852", + "852", + "csPCp852", + }; + + static final String[] aliases_IBM855 = new String[] { + "cp855", + "ibm-855", + "ibm855", + "855", + "cspcp855", + }; + + static final String[] aliases_IBM857 = new String[] { + "cp857", + "ibm857", + "ibm-857", + "857", + "csIBM857", + }; + + static final String[] aliases_IBM858 = new String[] { + "cp858", + "ccsid00858", + "cp00858", + "858", + "PC-Multilingual-850+euro", + }; + + static final String[] aliases_IBM862 = new String[] { + "cp862", + "ibm862", + "ibm-862", + "862", + "csIBM862", + "cspc862latinhebrew", + }; + + static final String[] aliases_IBM866 = new String[] { + "cp866", + "ibm866", + "ibm-866", + "866", + "csIBM866", + }; + + static final String[] aliases_IBM874 = new String[] { + "cp874", + "ibm874", + "ibm-874", + "874", + }; + + private static final class Aliases + extends sun.util.PreHashedMap + { + + private static final int ROWS = 1024; + private static final int SIZE = 211; + private static final int SHIFT = 0; + private static final int MASK = 0x3ff; + + private Aliases() { + super(ROWS, SIZE, SHIFT, MASK); + } + + protected void init(Object[] ht) { + ht[1] = new Object[] { "csisolatin0", "iso-8859-15" }; + ht[2] = new Object[] { "csisolatin1", "iso-8859-1" }; + ht[3] = new Object[] { "csisolatin2", "iso-8859-2" }; + ht[5] = new Object[] { "csisolatin4", "iso-8859-4" }; + ht[6] = new Object[] { "csisolatin5", "iso-8859-9" }; + ht[10] = new Object[] { "csisolatin9", "iso-8859-15" }; + ht[19] = new Object[] { "unicodelittle", "x-utf-16le-bom" }; + ht[24] = new Object[] { "iso646-us", "us-ascii" }; + ht[25] = new Object[] { "iso_8859-7:1987", "iso-8859-7" }; + ht[26] = new Object[] { "912", "iso-8859-2" }; + ht[28] = new Object[] { "914", "iso-8859-4" }; + ht[29] = new Object[] { "915", "iso-8859-5" }; + ht[55] = new Object[] { "920", "iso-8859-9" }; + ht[58] = new Object[] { "923", "iso-8859-15" }; + ht[86] = new Object[] { "csisolatincyrillic", "iso-8859-5", + new Object[] { "8859_1", "iso-8859-1" } }; + ht[87] = new Object[] { "8859_2", "iso-8859-2" }; + ht[89] = new Object[] { "8859_4", "iso-8859-4" }; + ht[90] = new Object[] { "813", "iso-8859-7", + new Object[] { "8859_5", "iso-8859-5" } }; + ht[92] = new Object[] { "8859_7", "iso-8859-7" }; + ht[94] = new Object[] { "8859_9", "iso-8859-9" }; + ht[95] = new Object[] { "iso_8859-1:1987", "iso-8859-1" }; + ht[96] = new Object[] { "819", "iso-8859-1" }; + ht[106] = new Object[] { "unicode-1-1-utf-8", "utf-8" }; + ht[121] = new Object[] { "x-utf-16le", "utf-16le" }; + ht[125] = new Object[] { "ecma-118", "iso-8859-7" }; + ht[134] = new Object[] { "koi8_r", "koi8-r" }; + ht[137] = new Object[] { "koi8_u", "koi8-u" }; + ht[141] = new Object[] { "cp912", "iso-8859-2" }; + ht[143] = new Object[] { "cp914", "iso-8859-4" }; + ht[144] = new Object[] { "cp915", "iso-8859-5" }; + ht[170] = new Object[] { "cp920", "iso-8859-9" }; + ht[173] = new Object[] { "cp923", "iso-8859-15" }; + ht[177] = new Object[] { "utf_32le_bom", "x-utf-32le-bom" }; + ht[192] = new Object[] { "utf_16be", "utf-16be" }; + ht[199] = new Object[] { "cspc8codepage437", "ibm437", + new Object[] { "ansi-1251", "windows-1251" } }; + ht[205] = new Object[] { "cp813", "iso-8859-7" }; + ht[211] = new Object[] { "850", "ibm850", + new Object[] { "cp819", "iso-8859-1" } }; + ht[213] = new Object[] { "852", "ibm852" }; + ht[216] = new Object[] { "855", "ibm855" }; + ht[218] = new Object[] { "857", "ibm857", + new Object[] { "iso-ir-6", "us-ascii" } }; + ht[219] = new Object[] { "858", "ibm00858", + new Object[] { "737", "x-ibm737" } }; + ht[225] = new Object[] { "csascii", "us-ascii" }; + ht[244] = new Object[] { "862", "ibm862" }; + ht[248] = new Object[] { "866", "ibm866" }; + ht[253] = new Object[] { "x-utf-32be", "utf-32be" }; + ht[254] = new Object[] { "iso_8859-2:1987", "iso-8859-2" }; + ht[259] = new Object[] { "unicodebig", "utf-16" }; + ht[269] = new Object[] { "iso8859_15_fdis", "iso-8859-15" }; + ht[277] = new Object[] { "874", "x-ibm874" }; + ht[280] = new Object[] { "unicodelittleunmarked", "utf-16le" }; + ht[283] = new Object[] { "iso8859_1", "iso-8859-1" }; + ht[284] = new Object[] { "iso8859_2", "iso-8859-2" }; + ht[286] = new Object[] { "iso8859_4", "iso-8859-4" }; + ht[287] = new Object[] { "iso8859_5", "iso-8859-5" }; + ht[289] = new Object[] { "iso8859_7", "iso-8859-7" }; + ht[291] = new Object[] { "iso8859_9", "iso-8859-9" }; + ht[294] = new Object[] { "ibm912", "iso-8859-2" }; + ht[296] = new Object[] { "ibm914", "iso-8859-4" }; + ht[297] = new Object[] { "ibm915", "iso-8859-5" }; + ht[305] = new Object[] { "iso_8859-13", "iso-8859-13" }; + ht[307] = new Object[] { "iso_8859-15", "iso-8859-15" }; + ht[312] = new Object[] { "greek8", "iso-8859-7", + new Object[] { "646", "us-ascii" } }; + ht[321] = new Object[] { "ibm-912", "iso-8859-2" }; + ht[323] = new Object[] { "ibm920", "iso-8859-9", + new Object[] { "ibm-914", "iso-8859-4" } }; + ht[324] = new Object[] { "ibm-915", "iso-8859-5" }; + ht[325] = new Object[] { "l1", "iso-8859-1" }; + ht[326] = new Object[] { "cp850", "ibm850", + new Object[] { "ibm923", "iso-8859-15", + new Object[] { "l2", "iso-8859-2" } } }; + ht[327] = new Object[] { "cyrillic", "iso-8859-5" }; + ht[328] = new Object[] { "cp852", "ibm852", + new Object[] { "l4", "iso-8859-4" } }; + ht[329] = new Object[] { "l5", "iso-8859-9" }; + ht[331] = new Object[] { "cp855", "ibm855" }; + ht[333] = new Object[] { "cp857", "ibm857", + new Object[] { "l9", "iso-8859-15" } }; + ht[334] = new Object[] { "cp858", "ibm00858", + new Object[] { "cp737", "x-ibm737" } }; + ht[336] = new Object[] { "iso_8859_1", "iso-8859-1" }; + ht[339] = new Object[] { "koi8", "koi8-r" }; + ht[341] = new Object[] { "775", "ibm775" }; + ht[345] = new Object[] { "iso_8859-9:1989", "iso-8859-9" }; + ht[350] = new Object[] { "ibm-920", "iso-8859-9" }; + ht[353] = new Object[] { "ibm-923", "iso-8859-15" }; + ht[358] = new Object[] { "ibm813", "iso-8859-7" }; + ht[359] = new Object[] { "cp862", "ibm862" }; + ht[363] = new Object[] { "cp866", "ibm866" }; + ht[364] = new Object[] { "ibm819", "iso-8859-1" }; + ht[378] = new Object[] { "ansi_x3.4-1968", "us-ascii" }; + ht[385] = new Object[] { "ibm-813", "iso-8859-7" }; + ht[391] = new Object[] { "ibm-819", "iso-8859-1" }; + ht[392] = new Object[] { "cp874", "x-ibm874" }; + ht[405] = new Object[] { "iso-ir-100", "iso-8859-1" }; + ht[406] = new Object[] { "iso-ir-101", "iso-8859-2" }; + ht[408] = new Object[] { "437", "ibm437" }; + ht[421] = new Object[] { "iso-8859-15", "iso-8859-15" }; + ht[428] = new Object[] { "latin0", "iso-8859-15" }; + ht[429] = new Object[] { "latin1", "iso-8859-1" }; + ht[430] = new Object[] { "latin2", "iso-8859-2" }; + ht[432] = new Object[] { "latin4", "iso-8859-4" }; + ht[433] = new Object[] { "latin5", "iso-8859-9" }; + ht[436] = new Object[] { "iso-ir-110", "iso-8859-4" }; + ht[437] = new Object[] { "latin9", "iso-8859-15" }; + ht[438] = new Object[] { "ansi_x3.4-1986", "us-ascii" }; + ht[443] = new Object[] { "utf-32be-bom", "x-utf-32be-bom" }; + ht[456] = new Object[] { "cp775", "ibm775" }; + ht[473] = new Object[] { "iso-ir-126", "iso-8859-7" }; + ht[479] = new Object[] { "ibm850", "ibm850" }; + ht[481] = new Object[] { "ibm852", "ibm852" }; + ht[484] = new Object[] { "ibm855", "ibm855" }; + ht[486] = new Object[] { "ibm857", "ibm857" }; + ht[487] = new Object[] { "ibm737", "x-ibm737" }; + ht[502] = new Object[] { "utf_16le", "utf-16le" }; + ht[506] = new Object[] { "ibm-850", "ibm850" }; + ht[508] = new Object[] { "ibm-852", "ibm852" }; + ht[511] = new Object[] { "ibm-855", "ibm855" }; + ht[512] = new Object[] { "ibm862", "ibm862" }; + ht[513] = new Object[] { "ibm-857", "ibm857" }; + ht[514] = new Object[] { "ibm-737", "x-ibm737" }; + ht[516] = new Object[] { "ibm866", "ibm866" }; + ht[520] = new Object[] { "unicodebigunmarked", "utf-16be" }; + ht[523] = new Object[] { "cp437", "ibm437" }; + ht[524] = new Object[] { "utf16", "utf-16" }; + ht[533] = new Object[] { "iso-ir-144", "iso-8859-5" }; + ht[537] = new Object[] { "iso-ir-148", "iso-8859-9" }; + ht[539] = new Object[] { "ibm-862", "ibm862" }; + ht[543] = new Object[] { "ibm-866", "ibm866" }; + ht[545] = new Object[] { "ibm874", "x-ibm874" }; + ht[563] = new Object[] { "x-utf-32le", "utf-32le" }; + ht[572] = new Object[] { "ibm-874", "x-ibm874" }; + ht[573] = new Object[] { "iso_8859-4:1988", "iso-8859-4" }; + ht[577] = new Object[] { "default", "us-ascii" }; + ht[582] = new Object[] { "utf32", "utf-32" }; + ht[583] = new Object[] { "pc-multilingual-850+euro", "ibm00858" }; + ht[588] = new Object[] { "elot_928", "iso-8859-7" }; + ht[593] = new Object[] { "csisolatingreek", "iso-8859-7" }; + ht[598] = new Object[] { "csibm857", "ibm857" }; + ht[609] = new Object[] { "ibm775", "ibm775" }; + ht[617] = new Object[] { "cp1250", "windows-1250" }; + ht[618] = new Object[] { "cp1251", "windows-1251" }; + ht[619] = new Object[] { "cp1252", "windows-1252" }; + ht[620] = new Object[] { "cp1253", "windows-1253" }; + ht[621] = new Object[] { "cp1254", "windows-1254" }; + ht[624] = new Object[] { "csibm862", "ibm862", + new Object[] { "cp1257", "windows-1257" } }; + ht[628] = new Object[] { "csibm866", "ibm866", + new Object[] { "cesu8", "cesu-8" } }; + ht[632] = new Object[] { "iso8859_13", "iso-8859-13" }; + ht[634] = new Object[] { "iso8859_15", "iso-8859-15", + new Object[] { "utf_32be", "utf-32be" } }; + ht[635] = new Object[] { "utf_32be_bom", "x-utf-32be-bom" }; + ht[636] = new Object[] { "ibm-775", "ibm775" }; + ht[654] = new Object[] { "cp00858", "ibm00858" }; + ht[669] = new Object[] { "8859_13", "iso-8859-13" }; + ht[670] = new Object[] { "us", "us-ascii" }; + ht[671] = new Object[] { "8859_15", "iso-8859-15" }; + ht[676] = new Object[] { "ibm437", "ibm437" }; + ht[679] = new Object[] { "cp367", "us-ascii" }; + ht[686] = new Object[] { "iso-10646-ucs-2", "utf-16be" }; + ht[703] = new Object[] { "ibm-437", "ibm437" }; + ht[710] = new Object[] { "iso8859-13", "iso-8859-13" }; + ht[712] = new Object[] { "iso8859-15", "iso-8859-15" }; + ht[732] = new Object[] { "iso_8859-5:1988", "iso-8859-5" }; + ht[733] = new Object[] { "unicode", "utf-16" }; + ht[768] = new Object[] { "greek", "iso-8859-7" }; + ht[774] = new Object[] { "ascii7", "us-ascii" }; + ht[781] = new Object[] { "iso8859-1", "iso-8859-1" }; + ht[782] = new Object[] { "iso8859-2", "iso-8859-2" }; + ht[783] = new Object[] { "cskoi8r", "koi8-r" }; + ht[784] = new Object[] { "iso8859-4", "iso-8859-4" }; + ht[785] = new Object[] { "iso8859-5", "iso-8859-5" }; + ht[787] = new Object[] { "iso8859-7", "iso-8859-7" }; + ht[789] = new Object[] { "iso8859-9", "iso-8859-9" }; + ht[813] = new Object[] { "ccsid00858", "ibm00858" }; + ht[818] = new Object[] { "cspc862latinhebrew", "ibm862" }; + ht[832] = new Object[] { "ibm367", "us-ascii" }; + ht[834] = new Object[] { "iso_8859-1", "iso-8859-1" }; + ht[835] = new Object[] { "iso_8859-2", "iso-8859-2", + new Object[] { "x-utf-16be", "utf-16be" } }; + ht[836] = new Object[] { "sun_eu_greek", "iso-8859-7" }; + ht[837] = new Object[] { "iso_8859-4", "iso-8859-4" }; + ht[838] = new Object[] { "iso_8859-5", "iso-8859-5" }; + ht[840] = new Object[] { "cspcp852", "ibm852", + new Object[] { "iso_8859-7", "iso-8859-7" } }; + ht[842] = new Object[] { "iso_8859-9", "iso-8859-9" }; + ht[843] = new Object[] { "cspcp855", "ibm855" }; + ht[846] = new Object[] { "windows-437", "ibm437" }; + ht[849] = new Object[] { "ascii", "us-ascii" }; + ht[863] = new Object[] { "cscesu-8", "cesu-8" }; + ht[881] = new Object[] { "utf8", "utf-8" }; + ht[896] = new Object[] { "iso_646.irv:1983", "us-ascii" }; + ht[909] = new Object[] { "cp5346", "windows-1250" }; + ht[910] = new Object[] { "cp5347", "windows-1251" }; + ht[911] = new Object[] { "cp5348", "windows-1252" }; + ht[912] = new Object[] { "cp5349", "windows-1253" }; + ht[925] = new Object[] { "iso_646.irv:1991", "us-ascii" }; + ht[934] = new Object[] { "cp5350", "windows-1254" }; + ht[937] = new Object[] { "cp5353", "windows-1257" }; + ht[944] = new Object[] { "utf_32le", "utf-32le" }; + ht[957] = new Object[] { "utf_16", "utf-16" }; + ht[993] = new Object[] { "cspc850multilingual", "ibm850" }; + ht[1009] = new Object[] { "utf-32le-bom", "x-utf-32le-bom" }; + ht[1015] = new Object[] { "utf_32", "utf-32" }; + } + + } + + private static final class Classes + extends sun.util.PreHashedMap + { + + private static final int ROWS = 32; + private static final int SIZE = 39; + private static final int SHIFT = 1; + private static final int MASK = 0x1f; + + private Classes() { + super(ROWS, SIZE, SHIFT, MASK); + } + + protected void init(Object[] ht) { + ht[0] = new Object[] { "ibm862", "IBM862" }; + ht[2] = new Object[] { "ibm866", "IBM866", + new Object[] { "utf-32", "UTF_32", + new Object[] { "utf-16le", "UTF_16LE" } } }; + ht[3] = new Object[] { "windows-1251", "MS1251", + new Object[] { "windows-1250", "MS1250" } }; + ht[4] = new Object[] { "windows-1253", "MS1253", + new Object[] { "windows-1252", "MS1252", + new Object[] { "utf-32be", "UTF_32BE" } } }; + ht[5] = new Object[] { "windows-1254", "MS1254", + new Object[] { "utf-16", "UTF_16" } }; + ht[6] = new Object[] { "windows-1257", "MS1257" }; + ht[7] = new Object[] { "utf-16be", "UTF_16BE" }; + ht[8] = new Object[] { "iso-8859-2", "ISO_8859_2", + new Object[] { "iso-8859-1", "ISO_8859_1" } }; + ht[9] = new Object[] { "iso-8859-4", "ISO_8859_4", + new Object[] { "utf-8", "UTF_8" } }; + ht[10] = new Object[] { "iso-8859-5", "ISO_8859_5" }; + ht[11] = new Object[] { "x-ibm874", "IBM874", + new Object[] { "iso-8859-7", "ISO_8859_7" } }; + ht[12] = new Object[] { "iso-8859-9", "ISO_8859_9" }; + ht[14] = new Object[] { "x-ibm737", "IBM737" }; + ht[15] = new Object[] { "ibm850", "IBM850" }; + ht[16] = new Object[] { "ibm852", "IBM852", + new Object[] { "ibm775", "IBM775" } }; + ht[17] = new Object[] { "iso-8859-13", "ISO_8859_13", + new Object[] { "us-ascii", "US_ASCII" } }; + ht[18] = new Object[] { "ibm855", "IBM855", + new Object[] { "ibm437", "IBM437", + new Object[] { "iso-8859-15", "ISO_8859_15" } } }; + ht[19] = new Object[] { "ibm00858", "IBM858", + new Object[] { "ibm857", "IBM857", + new Object[] { "x-utf-32le-bom", "UTF_32LE_BOM" } } }; + ht[22] = new Object[] { "x-utf-16le-bom", "UTF_16LE_BOM" }; + ht[23] = new Object[] { "cesu-8", "CESU_8" }; + ht[24] = new Object[] { "x-utf-32be-bom", "UTF_32BE_BOM" }; + ht[28] = new Object[] { "koi8-r", "KOI8_R" }; + ht[29] = new Object[] { "koi8-u", "KOI8_U" }; + ht[31] = new Object[] { "utf-32le", "UTF_32LE" }; + } + + } + + private static final class Cache + extends sun.util.PreHashedMap + { + + private static final int ROWS = 32; + private static final int SIZE = 39; + private static final int SHIFT = 1; + private static final int MASK = 0x1f; + + private Cache() { + super(ROWS, SIZE, SHIFT, MASK); + } + + protected void init(Object[] ht) { + // [IKVM] we pre-populate some cache entries to avoid reflection when instantiating the common charsets + ht[0] = new Object[] { "ibm862", null }; + ht[2] = new Object[] { "ibm866", null, + new Object[] { "utf-32", null, + new Object[] { "utf-16le", null } } }; + ht[3] = new Object[] { "windows-1251", null, + new Object[] { "windows-1250", null } }; + ht[4] = new Object[] { "windows-1253", null, + new Object[] { "windows-1252", new MS1252(), + new Object[] { "utf-32be", null } } }; + ht[5] = new Object[] { "windows-1254", null, + new Object[] { "utf-16", null } }; + ht[6] = new Object[] { "windows-1257", null }; + ht[7] = new Object[] { "utf-16be", null }; + ht[8] = new Object[] { "iso-8859-2", null, + new Object[] { "iso-8859-1", null } }; + ht[9] = new Object[] { "iso-8859-4", null, + new Object[] { "utf-8", new UTF_8() } }; + ht[10] = new Object[] { "iso-8859-5", null }; + ht[11] = new Object[] { "x-ibm874", null, + new Object[] { "iso-8859-7", null } }; + ht[12] = new Object[] { "iso-8859-9", null }; + ht[14] = new Object[] { "x-ibm737", null }; + ht[15] = new Object[] { "ibm850", null }; + ht[16] = new Object[] { "ibm852", null, + new Object[] { "ibm775", null } }; + ht[17] = new Object[] { "iso-8859-13", null, + new Object[] { "us-ascii", null } }; + ht[18] = new Object[] { "ibm855", null, + new Object[] { "ibm437", null, + new Object[] { "iso-8859-15", null } } }; + ht[19] = new Object[] { "ibm00858", null, + new Object[] { "ibm857", null, + new Object[] { "x-utf-32le-bom", null } } }; + ht[22] = new Object[] { "x-utf-16le-bom", null }; + ht[23] = new Object[] { "cesu-8", null }; + ht[24] = new Object[] { "x-utf-32be-bom", null }; + ht[28] = new Object[] { "koi8-r", null }; + ht[29] = new Object[] { "koi8-u", null }; + ht[31] = new Object[] { "utf-32le", null }; + } + + } + + public StandardCharsets() { + super("sun.nio.cs", new Aliases(), new Classes(), new Cache()); + } + +} diff --git a/openjdk/sun/nio/fs/DefaultFileSystemProvider.java b/openjdk/sun/nio/fs/DefaultFileSystemProvider.java new file mode 100644 index 0000000..6ef8d07 --- /dev/null +++ b/openjdk/sun/nio/fs/DefaultFileSystemProvider.java @@ -0,0 +1,35 @@ +/* + Copyright (C) 2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package sun.nio.fs; + +import java.nio.file.spi.FileSystemProvider; + +public class DefaultFileSystemProvider +{ + public static FileSystemProvider create() + { + return new NetFileSystemProvider(); + } +} diff --git a/openjdk/sun/nio/fs/DefaultFileTypeDetector.java b/openjdk/sun/nio/fs/DefaultFileTypeDetector.java new file mode 100644 index 0000000..5da0812 --- /dev/null +++ b/openjdk/sun/nio/fs/DefaultFileTypeDetector.java @@ -0,0 +1,41 @@ +/* + Copyright (C) 2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package sun.nio.fs; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.spi.FileTypeDetector; + +public class DefaultFileTypeDetector +{ + public static FileTypeDetector create() + { + return new AbstractFileTypeDetector() { + public String implProbeContentType(Path obj) throws IOException { + return null; + } + }; + } +} diff --git a/openjdk/sun/nio/fs/NetFileSystem.java b/openjdk/sun/nio/fs/NetFileSystem.java new file mode 100644 index 0000000..9c07f60 --- /dev/null +++ b/openjdk/sun/nio/fs/NetFileSystem.java @@ -0,0 +1,498 @@ +/* + Copyright (C) 2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package sun.nio.fs; + +import cli.System.IO.DriveInfo; +import cli.System.IO.ErrorEventArgs; +import cli.System.IO.ErrorEventHandler; +import cli.System.IO.FileSystemEventArgs; +import cli.System.IO.FileSystemEventHandler; +import cli.System.IO.FileSystemWatcher; +import cli.System.IO.WatcherChangeTypes; +import java.io.IOException; +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.nio.file.spi.FileSystemProvider; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; +import static ikvm.internal.Util.WINDOWS; + +final class NetFileSystem extends FileSystem +{ + private static final Set attributes = Collections.unmodifiableSet(new HashSet(Arrays.asList("basic"))); + private final NetFileSystemProvider provider; + private final String separator = Character.toString(cli.System.IO.Path.DirectorySeparatorChar); + + NetFileSystem(NetFileSystemProvider provider) + { + this.provider = provider; + } + + public FileSystemProvider provider() + { + return provider; + } + + public void close() throws IOException + { + throw new UnsupportedOperationException(); + } + + public boolean isOpen() + { + return true; + } + + public boolean isReadOnly() + { + return false; + } + + public String getSeparator() + { + return separator; + } + + public Iterable getRootDirectories() + { + SecurityManager sm = System.getSecurityManager(); + ArrayList list = new ArrayList<>(); + for (DriveInfo info : DriveInfo.GetDrives()) + { + try + { + if (sm != null) + { + sm.checkRead(info.get_Name()); + } + } + catch (SecurityException _) + { + continue; + } + list.add(getPath(info.get_Name())); + } + return list; + } + + public Iterable getFileStores() + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + { + try + { + sm.checkPermission(new RuntimePermission("getFileStoreAttributes")); + } + catch (SecurityException _) + { + return Collections.emptyList(); + } + } + ArrayList list = new ArrayList<>(); + for (DriveInfo info : DriveInfo.GetDrives()) + { + try + { + if (sm != null) + { + sm.checkRead(info.get_Name()); + } + } + catch (SecurityException _) + { + continue; + } + try + { + list.add(provider.getFileStore(info)); + } + catch (IOException _) + { + } + } + return list; + } + + public Set supportedFileAttributeViews() + { + return attributes; + } + + public Path getPath(String first, String... more) + { + if (more.length == 0) + { + return new NetPath(this, first); + } + else + { + StringBuilder sb = new StringBuilder(first); + String sep = sb.length() == 0 ? "" : separator; + for (String s : more) + { + if (s.length() != 0) + { + sb.append(sep); + sb.append(s); + sep = separator; + } + } + return new NetPath(this, sb.toString()); + } + } + + public PathMatcher getPathMatcher(String syntaxAndPattern) + { + String regex; + if (syntaxAndPattern.startsWith("glob:")) + { + String pattern = syntaxAndPattern.substring(5); + if (WINDOWS) + { + regex = Globs.toWindowsRegexPattern(pattern); + } + else + { + regex = Globs.toUnixRegexPattern(pattern); + } + } + else if (syntaxAndPattern.startsWith("regex:")) + { + regex = syntaxAndPattern.substring(6); + } + else if (syntaxAndPattern.indexOf(':') <= 0) + { + throw new IllegalArgumentException(); + } + else + { + throw new UnsupportedOperationException(); + } + final Pattern pattern = Pattern.compile(regex, WINDOWS ? Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE : 0); + return new PathMatcher() { + @Override + public boolean matches(Path path) { + return pattern.matcher(path.toString()).matches(); + } + }; + } + + public UserPrincipalLookupService getUserPrincipalLookupService() + { + throw new UnsupportedOperationException(); + } + + static final class NetWatchService implements WatchService + { + static final WatchEvent overflowEvent = new WatchEvent() { + public Object context() { + return null; + } + public int count() { + return 1; + } + public WatchEvent.Kind kind() { + return StandardWatchEventKinds.OVERFLOW; + } + }; + private static final WatchKey CLOSED = new WatchKey() { + public boolean isValid() { return false; } + public List> pollEvents() { return null; } + public boolean reset() { return false; } + public void cancel() { } + public Watchable watchable() { return null; } + }; + private boolean closed; + private final ArrayList keys = new ArrayList<>(); + private final LinkedBlockingQueue queue = new LinkedBlockingQueue<>(); + + public synchronized void close() + { + if (!closed) + { + closed = true; + for (NetWatchKey key : keys) + { + key.close(); + } + enqueue(CLOSED); + } + } + + private WatchKey checkClosed(WatchKey key) + { + if (key == CLOSED) + { + enqueue(CLOSED); + throw new ClosedWatchServiceException(); + } + return key; + } + + public WatchKey poll() + { + return checkClosed(queue.poll()); + } + + public WatchKey poll(long timeout, TimeUnit unit) throws InterruptedException + { + return checkClosed(queue.poll(timeout, unit)); + } + + public WatchKey take() throws InterruptedException + { + return checkClosed(queue.take()); + } + + void enqueue(WatchKey key) + { + for (;;) + { + try + { + queue.put(key); + return; + } + catch (InterruptedException _) + { + } + } + } + + private final class NetWatchKey implements WatchKey + { + private final NetPath path; + private FileSystemWatcher fsw; + private ArrayList> list = new ArrayList<>(); + private HashSet modified = new HashSet<>(); + private boolean signaled; + + NetWatchKey(NetPath path) + { + this.path = path; + } + + synchronized void init(final boolean create, final boolean delete, final boolean modify, final boolean overflow, final boolean subtree) + { + if (fsw != null) + { + // we could reuse the FileSystemWatcher, but for now we just recreate it + // (and we run the risk of missing some events while we're doing that) + fsw.Dispose(); + fsw = null; + } + fsw = new FileSystemWatcher(path.path); + if (create) + { + fsw.add_Created(new FileSystemEventHandler(new FileSystemEventHandler.Method() { + public void Invoke(Object sender, FileSystemEventArgs e) { + addEvent(createEvent(e), null); + } + })); + } + if (delete) + { + fsw.add_Deleted(new FileSystemEventHandler(new FileSystemEventHandler.Method() { + public void Invoke(Object sender, FileSystemEventArgs e) { + addEvent(createEvent(e), null); + } + })); + } + if (modify) + { + fsw.add_Changed(new FileSystemEventHandler(new FileSystemEventHandler.Method() { + public void Invoke(Object sender, FileSystemEventArgs e) { + synchronized (NetWatchKey.this) { + if (modified.contains(e.get_Name())) { + // we already have an ENTRY_MODIFY event pending + return; + } + } + addEvent(createEvent(e), e.get_Name()); + } + })); + } + fsw.add_Error(new ErrorEventHandler(new ErrorEventHandler.Method() { + public void Invoke(Object sender, ErrorEventArgs e) { + if (e.GetException() instanceof cli.System.ComponentModel.Win32Exception + && ((cli.System.ComponentModel.Win32Exception)e.GetException()).get_ErrorCode() == -2147467259) { + // the directory we were watching was deleted + cancelledByError(); + } else if (overflow) { + addEvent(overflowEvent, null); + } + } + })); + if (subtree) + { + fsw.set_IncludeSubdirectories(true); + } + fsw.set_EnableRaisingEvents(true); + } + + WatchEvent createEvent(final FileSystemEventArgs e) + { + return new WatchEvent() { + public Path context() { + return new NetPath((NetFileSystem)path.getFileSystem(), e.get_Name()); + } + public int count() { + return 1; + } + public WatchEvent.Kind kind() { + switch (e.get_ChangeType().Value) { + case WatcherChangeTypes.Created: + return StandardWatchEventKinds.ENTRY_CREATE; + case WatcherChangeTypes.Deleted: + return StandardWatchEventKinds.ENTRY_DELETE; + default: + return StandardWatchEventKinds.ENTRY_MODIFY; + } + } + }; + } + + void cancelledByError() + { + cancel(); + synchronized (this) + { + if (!signaled) + { + signaled = true; + enqueue(this); + } + } + } + + synchronized void addEvent(WatchEvent event, String modified) + { + list.add(event); + if (modified != null) + { + this.modified.add(modified); + } + if (!signaled) + { + signaled = true; + enqueue(this); + } + } + + public synchronized boolean isValid() + { + return fsw != null; + } + + public synchronized List> pollEvents() + { + ArrayList> r = list; + list = new ArrayList<>(); + modified.clear(); + return r; + } + + public synchronized boolean reset() + { + if (fsw == null) + { + return false; + } + if (signaled) + { + if (list.size() == 0) + { + signaled = false; + } + else + { + enqueue(this); + } + } + return true; + } + + void close() + { + if (fsw != null) + { + fsw.Dispose(); + fsw = null; + } + } + + public void cancel() + { + synchronized (NetWatchService.this) + { + keys.remove(this); + close(); + } + } + + public Watchable watchable() + { + return path; + } + } + + synchronized WatchKey register(NetPath path, boolean create, boolean delete, boolean modify, boolean overflow, boolean subtree) + { + if (closed) + { + throw new ClosedWatchServiceException(); + } + NetWatchKey existing = null; + for (NetWatchKey key : keys) + { + if (key.watchable().equals(path)) + { + existing = key; + break; + } + } + if (existing == null) + { + existing = new NetWatchKey(path); + keys.add(existing); + } + existing.init(create, delete, modify, overflow, subtree); + return existing; + } + } + + public WatchService newWatchService() throws IOException + { + return new NetWatchService(); + } +} diff --git a/openjdk/sun/nio/fs/NetFileSystemProvider.java b/openjdk/sun/nio/fs/NetFileSystemProvider.java new file mode 100644 index 0000000..b49c6cd --- /dev/null +++ b/openjdk/sun/nio/fs/NetFileSystemProvider.java @@ -0,0 +1,1467 @@ +/* + Copyright (C) 2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package sun.nio.fs; + +import ikvm.internal.NotYetImplementedError; +import static ikvm.internal.Util.WINDOWS; +import cli.System.IO.Directory; +import cli.System.IO.DirectoryInfo; +import cli.System.IO.DriveInfo; +import cli.System.IO.File; +import cli.System.IO.FileAttributes; +import cli.System.IO.FileInfo; +import cli.System.IO.FileMode; +import cli.System.IO.FileShare; +import cli.System.IO.FileStream; +import cli.System.IO.FileOptions; +import cli.System.Runtime.InteropServices.DllImportAttribute; +import cli.System.Runtime.InteropServices.Marshal; +import cli.System.Security.AccessControl.FileSystemRights; +import com.sun.nio.file.ExtendedOpenOption; +import java.io.FileDescriptor; +import java.io.IOException; +import java.net.URI; +import java.nio.channels.*; +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.nio.file.spi.FileSystemProvider; +import java.util.concurrent.ExecutorService; +import java.util.Iterator; +import java.util.HashMap; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import sun.nio.ch.WindowsAsynchronousFileChannelImpl; +import sun.nio.ch.FileChannelImpl; +import sun.nio.ch.ThreadPool; + +final class NetFileSystemProvider extends AbstractFileSystemProvider +{ + private final NetFileSystem fs = new NetFileSystem(this); + private final HashMap stores = new HashMap(); + + final synchronized FileStore getFileStore(DriveInfo drive) throws IOException + { + String name = drive.get_Name().toLowerCase(); + FileStore fs = stores.get(name); + if (fs == null) + { + fs = new NetFileStore(drive); + stores.put(name, fs); + } + return fs; + } + + public String getScheme() + { + return "file"; + } + + public FileSystem newFileSystem(URI uri, Map env) throws IOException + { + throw new FileSystemAlreadyExistsException(); + } + + public FileSystem getFileSystem(URI uri) + { + return fs; + } + + public Path getPath(URI uri) + { + if (WINDOWS) + { + return WindowsUriSupport.fromUri(fs, uri); + } + else + { + return UnixUriUtils.fromUri(fs, uri); + } + } + + public AsynchronousFileChannel newAsynchronousFileChannel(Path path, Set opts, ExecutorService executor, FileAttribute... attrs) throws IOException + { + NetPath npath = NetPath.from(path); + for (FileAttribute attr : attrs) + { + // null check + attr.getClass(); + throw new NotYetImplementedError(); + } + int mode = FileMode.Open; + int share = FileShare.ReadWrite | FileShare.Delete; + int options = FileOptions.Asynchronous; + boolean read = false; + boolean write = false; + boolean truncate = false; + for (OpenOption opt : opts) + { + if (opt instanceof StandardOpenOption) + { + switch ((StandardOpenOption)opt) + { + case CREATE: + mode = FileMode.Create; + break; + case CREATE_NEW: + mode = FileMode.CreateNew; + break; + case DELETE_ON_CLOSE: + options |= FileOptions.DeleteOnClose; + break; + case DSYNC: + options |= FileOptions.WriteThrough; + break; + case READ: + read = true; + break; + case SPARSE: + break; + case SYNC: + options |= FileOptions.WriteThrough; + break; + case TRUNCATE_EXISTING: + truncate = true; + break; + case WRITE: + write = true; + break; + default: + throw new UnsupportedOperationException(); + } + } + else if (opt instanceof ExtendedOpenOption) + { + switch ((ExtendedOpenOption)opt) + { + case NOSHARE_READ: + share &= ~FileShare.Read; + break; + case NOSHARE_WRITE: + share &= ~FileShare.Write; + break; + case NOSHARE_DELETE: + share &= ~FileShare.Delete; + break; + default: + throw new UnsupportedOperationException(); + } + } + else + { + // null check + opt.getClass(); + throw new UnsupportedOperationException(); + } + } + + if (!read && !write) + { + read = true; + } + + if (truncate) + { + if (mode == FileMode.Open) + { + mode = FileMode.Truncate; + } + } + + int rights = 0; + if (read) + { + rights |= FileSystemRights.Read; + } + if (write) + { + rights |= FileSystemRights.Write; + } + + ThreadPool pool; + if (executor == null) + { + pool = null; + } + else + { + pool = ThreadPool.wrap(executor, 0); + } + + return WindowsAsynchronousFileChannelImpl.open(open(npath.path, mode, rights, share, options), read, write, pool); + } + + public SeekableByteChannel newByteChannel(Path path, Set opts, FileAttribute... attrs) throws IOException + { + return newFileChannel(path, opts, attrs); + } + + public FileChannel newFileChannel(Path path, Set opts, FileAttribute... attrs) throws IOException + { + NetPath npath = NetPath.from(path); + for (FileAttribute attr : attrs) + { + // null check + attr.getClass(); + throw new NotYetImplementedError(); + } + int mode = FileMode.Open; + int share = FileShare.ReadWrite | FileShare.Delete; + int options = FileOptions.None; + boolean read = false; + boolean write = false; + boolean append = false; + boolean truncate = false; + for (OpenOption opt : opts) + { + if (opt instanceof StandardOpenOption) + { + switch ((StandardOpenOption)opt) + { + case APPEND: + append = true; + write = true; + mode = FileMode.Append; + break; + case CREATE: + mode = FileMode.Create; + break; + case CREATE_NEW: + mode = FileMode.CreateNew; + break; + case DELETE_ON_CLOSE: + options |= FileOptions.DeleteOnClose; + break; + case DSYNC: + options |= FileOptions.WriteThrough; + break; + case READ: + read = true; + break; + case SPARSE: + break; + case SYNC: + options |= FileOptions.WriteThrough; + break; + case TRUNCATE_EXISTING: + truncate = true; + break; + case WRITE: + write = true; + break; + default: + throw new UnsupportedOperationException(); + } + } + else if (opt instanceof ExtendedOpenOption) + { + switch ((ExtendedOpenOption)opt) + { + case NOSHARE_READ: + share &= ~FileShare.Read; + break; + case NOSHARE_WRITE: + share &= ~FileShare.Write; + break; + case NOSHARE_DELETE: + share &= ~FileShare.Delete; + break; + default: + throw new UnsupportedOperationException(); + } + } + else + { + // null check + opt.getClass(); + throw new UnsupportedOperationException(); + } + } + + if (!read && !write) + { + read = true; + } + + if (read && append) + { + throw new IllegalArgumentException("READ + APPEND not allowed"); + } + + if (truncate) + { + if (append) + { + throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed"); + } + if (mode == FileMode.Open) + { + mode = FileMode.Truncate; + } + } + + int rights = 0; + if (append) + { + // for atomic append to work, we can't set FileSystemRights.Write + rights |= FileSystemRights.AppendData; + } + else + { + if (read) + { + rights |= FileSystemRights.Read; + } + if (write) + { + rights |= FileSystemRights.Write; + } + } + + return FileChannelImpl.open(open(npath.path, mode, rights, share, options), npath.path, read, write, append, null); + } + + private static FileDescriptor open(String path, int mode, int rights, int share, int options) throws IOException + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + { + if ((rights & FileSystemRights.Read) != 0) + { + sm.checkRead(path); + } + if ((rights & (FileSystemRights.Write | FileSystemRights.AppendData)) != 0) + { + sm.checkWrite(path); + } + if ((options & FileOptions.DeleteOnClose) != 0) + { + sm.checkDelete(path); + } + } + + try + { + if (false) throw new cli.System.ArgumentException(); + if (false) throw new cli.System.IO.FileNotFoundException(); + if (false) throw new cli.System.IO.DirectoryNotFoundException(); + if (false) throw new cli.System.PlatformNotSupportedException(); + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.Security.SecurityException(); + if (false) throw new cli.System.UnauthorizedAccessException(); + return FileDescriptor.fromStream(new FileStream(path, FileMode.wrap(mode), FileSystemRights.wrap(rights), FileShare.wrap(share), 8, FileOptions.wrap(options))); + } + catch (cli.System.ArgumentException x) + { + throw new FileSystemException(path, null, x.getMessage()); + } + catch (cli.System.IO.FileNotFoundException _) + { + throw new NoSuchFileException(path); + } + catch (cli.System.IO.DirectoryNotFoundException _) + { + throw new NoSuchFileException(path); + } + catch (cli.System.PlatformNotSupportedException x) + { + throw new UnsupportedOperationException(x.getMessage()); + } + catch (cli.System.IO.IOException x) + { + if (mode == FileMode.CreateNew && File.Exists(path)) + { + throw new FileAlreadyExistsException(path); + } + throw new FileSystemException(path, null, x.getMessage()); + } + catch (cli.System.Security.SecurityException _) + { + throw new AccessDeniedException(path); + } + catch (cli.System.UnauthorizedAccessException _) + { + throw new AccessDeniedException(path); + } + } + + public DirectoryStream newDirectoryStream(Path dir, final DirectoryStream.Filter filter) throws IOException + { + final String ndir = NetPath.from(dir).path; + // null check + filter.getClass(); + + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + { + sm.checkRead(ndir); + } + + try + { + if (false) throw new cli.System.ArgumentException(); + if (false) throw new cli.System.IO.DirectoryNotFoundException(); + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.Security.SecurityException(); + if (false) throw new cli.System.UnauthorizedAccessException(); + final String[] files = Directory.GetFileSystemEntries(ndir); + return new DirectoryStream() { + private boolean closed; + public Iterator iterator() { + if (closed) { + throw new IllegalStateException(); + } + closed = true; + return new Iterator() { + private int pos; + private Path filtered; + public boolean hasNext() { + if (filtered == null) { + while (pos != files.length) { + Path p = new NetPath(fs, cli.System.IO.Path.Combine(ndir, files[pos++])); + try { + if (filter.accept(p)) { + filtered = p; + break; + } + } catch (IOException x) { + throw new DirectoryIteratorException(x); + } + } + } + return filtered != null; + } + public Path next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + Path p = filtered; + filtered = null; + return p; + } + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + public void close() { + closed = true; + } + }; + } + catch (cli.System.ArgumentException + | cli.System.IO.IOException + | cli.System.Security.SecurityException + | cli.System.UnauthorizedAccessException x) + { + if (File.Exists(ndir)) + { + throw new NotDirectoryException(ndir); + } + throw new IOException(x.getMessage()); + } + } + + public void createDirectory(Path dir, FileAttribute... attrs) throws IOException + { + NetPath ndir = NetPath.from(dir); + for (FileAttribute attr : attrs) + { + // null check + attr.getClass(); + throw new NotYetImplementedError(); + } + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + { + sm.checkWrite(ndir.path); + } + try + { + if (false) throw new cli.System.ArgumentException(); + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.Security.SecurityException(); + if (false) throw new cli.System.UnauthorizedAccessException(); + Directory.CreateDirectory(ndir.path); + } + catch (cli.System.ArgumentException + | cli.System.IO.IOException + | cli.System.Security.SecurityException + | cli.System.UnauthorizedAccessException x) + { + if (File.Exists(ndir.path)) + { + throw new FileAlreadyExistsException(ndir.path); + } + throw new IOException(x.getMessage()); + } + } + + public void copy(Path source, Path target, CopyOption... options) throws IOException + { + NetPath nsource = NetPath.from(source); + NetPath ntarget = NetPath.from(target); + boolean overwrite = false; + boolean copyAttribs = false; + for (CopyOption opt : options) + { + if (opt == StandardCopyOption.REPLACE_EXISTING) + { + overwrite = true; + } + else if (opt == StandardCopyOption.COPY_ATTRIBUTES) + { + copyAttribs = true; + } + else + { + // null check + opt.getClass(); + throw new UnsupportedOperationException("Unsupported copy option"); + } + } + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + { + sm.checkRead(nsource.path); + sm.checkWrite(ntarget.path); + } + try + { + if (false) throw new cli.System.ArgumentException(); + if (false) throw new cli.System.IO.FileNotFoundException(); + if (false) throw new cli.System.IO.DirectoryNotFoundException(); + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.Security.SecurityException(); + if (false) throw new cli.System.UnauthorizedAccessException(); + if (File.Exists(ntarget.path)) + { + if (!overwrite) + { + throw new FileAlreadyExistsException(ntarget.path); + } + File.Delete(ntarget.path); + } + if (Directory.Exists(ntarget.path)) + { + if (!overwrite) + { + throw new FileAlreadyExistsException(ntarget.path); + } + try + { + if (false) throw new cli.System.IO.IOException(); + Directory.Delete(ntarget.path); + } + catch (cli.System.IO.IOException _) + { + // HACK we assume that the IOException is caused by the directory not being empty + throw new DirectoryNotEmptyException(ntarget.path); + } + } + if (Directory.Exists(nsource.path)) + { + Directory.CreateDirectory(ntarget.path); + } + else + { + File.Copy(nsource.path, ntarget.path, overwrite); + } + if (copyAttribs) + { + if (Directory.Exists(ntarget.path)) + { + File.SetAttributes(ntarget.path, File.GetAttributes(nsource.path)); + Directory.SetCreationTimeUtc(ntarget.path, File.GetCreationTimeUtc(nsource.path)); + Directory.SetLastAccessTimeUtc(ntarget.path, File.GetLastAccessTimeUtc(nsource.path)); + Directory.SetLastWriteTimeUtc(ntarget.path, File.GetLastWriteTimeUtc(nsource.path)); + } + else + { + File.SetAttributes(ntarget.path, File.GetAttributes(nsource.path)); + File.SetCreationTimeUtc(ntarget.path, File.GetCreationTimeUtc(nsource.path)); + File.SetLastAccessTimeUtc(ntarget.path, File.GetLastAccessTimeUtc(nsource.path)); + File.SetLastWriteTimeUtc(ntarget.path, File.GetLastWriteTimeUtc(nsource.path)); + } + } + } + catch (cli.System.IO.FileNotFoundException x) + { + throw new NoSuchFileException(x.get_FileName()); + } + catch (cli.System.IO.DirectoryNotFoundException x) + { + throw new NoSuchFileException(nsource.path, ntarget.path, x.getMessage()); + } + catch (cli.System.IO.IOException | cli.System.ArgumentException x) + { + throw new FileSystemException(nsource.path, ntarget.path, x.getMessage()); + } + catch (cli.System.Security.SecurityException | cli.System.UnauthorizedAccessException x) + { + throw new AccessDeniedException(nsource.path, ntarget.path, x.getMessage()); + } + } + + public void move(Path source, Path target, CopyOption... options) throws IOException + { + NetPath nsource = NetPath.from(source); + NetPath ntarget = NetPath.from(target); + boolean overwrite = false; + boolean atomicMove = false; + for (CopyOption opt : options) + { + if (opt == StandardCopyOption.REPLACE_EXISTING) + { + overwrite = true; + } + else if (opt == StandardCopyOption.ATOMIC_MOVE) + { + if (WINDOWS) + { + atomicMove = true; + } + else + { + throw new AtomicMoveNotSupportedException(nsource.path, ntarget.path, "Unsupported copy option"); + } + } + else + { + // null check + opt.getClass(); + throw new UnsupportedOperationException("Unsupported copy option"); + } + } + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + { + sm.checkRead(nsource.path); + sm.checkWrite(ntarget.path); + } + if (atomicMove) + { + int MOVEFILE_REPLACE_EXISTING = 1; + if (MoveFileEx(nsource.path, ntarget.path, MOVEFILE_REPLACE_EXISTING) == 0) + { + final int ERROR_FILE_NOT_FOUND = 2; + final int ERROR_PATH_NOT_FOUND = 3; + final int ERROR_ACCESS_DENIED = 5; + final int ERROR_NOT_SAME_DEVICE = 17; + final int ERROR_FILE_EXISTS = 80; + final int ERROR_ALREADY_EXISTS = 183; + int lastError = Marshal.GetLastWin32Error(); + switch (lastError) + { + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + throw new NoSuchFileException(nsource.path, ntarget.path, null); + case ERROR_ACCESS_DENIED: + throw new AccessDeniedException(nsource.path, ntarget.path, null); + case ERROR_NOT_SAME_DEVICE: + throw new AtomicMoveNotSupportedException(nsource.path, ntarget.path, "Unsupported copy option"); + case ERROR_FILE_EXISTS: + case ERROR_ALREADY_EXISTS: + throw new FileAlreadyExistsException(nsource.path, ntarget.path, null); + default: + throw new FileSystemException(nsource.path, ntarget.path, "Error " + lastError); + } + } + return; + } + try + { + if (false) throw new cli.System.ArgumentException(); + if (false) throw new cli.System.IO.FileNotFoundException(); + if (false) throw new cli.System.IO.DirectoryNotFoundException(); + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.Security.SecurityException(); + if (false) throw new cli.System.UnauthorizedAccessException(); + if (File.Exists(ntarget.path)) + { + if (!overwrite) + { + throw new FileAlreadyExistsException(ntarget.path); + } + File.Delete(ntarget.path); + } + if (Directory.Exists(ntarget.path)) + { + if (!overwrite) + { + throw new FileAlreadyExistsException(ntarget.path); + } + try + { + if (false) throw new cli.System.IO.IOException(); + Directory.Delete(ntarget.path); + } + catch (cli.System.IO.IOException _) + { + // HACK we assume that the IOException is caused by the directory not being empty + throw new DirectoryNotEmptyException(ntarget.path); + } + } + if (Directory.Exists(nsource.path)) + { + Directory.Move(nsource.path, ntarget.path); + } + else + { + File.Move(nsource.path, ntarget.path); + } + } + catch (cli.System.IO.FileNotFoundException x) + { + throw new NoSuchFileException(x.get_FileName()); + } + catch (cli.System.IO.DirectoryNotFoundException x) + { + throw new NoSuchFileException(nsource.path, ntarget.path, x.getMessage()); + } + catch (cli.System.IO.IOException | cli.System.ArgumentException x) + { + throw new FileSystemException(nsource.path, ntarget.path, x.getMessage()); + } + catch (cli.System.Security.SecurityException | cli.System.UnauthorizedAccessException x) + { + throw new AccessDeniedException(nsource.path, ntarget.path, x.getMessage()); + } + } + + @DllImportAttribute.Annotation(value="kernel32", SetLastError=true) + private static native int MoveFileEx(String lpExistingFileName, String lpNewFileName, int dwFlags); + + public boolean isSameFile(Path path, Path path2) throws IOException + { + if (path.equals(path2)) + { + return true; + } + if (!(path instanceof NetPath && path2 instanceof NetPath)) + { + // null check + path2.getClass(); + return false; + } + return path.toRealPath().equals(path2.toRealPath()); + } + + public boolean isHidden(Path path) throws IOException + { + String npath = NetPath.from(path).path; + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + { + sm.checkRead(npath); + } + try + { + if (false) throw new cli.System.ArgumentException(); + if (false) throw new cli.System.IO.FileNotFoundException(); + if (false) throw new cli.System.IO.IOException(); + return (File.GetAttributes(npath).Value & (cli.System.IO.FileAttributes.Hidden | cli.System.IO.FileAttributes.Directory)) == cli.System.IO.FileAttributes.Hidden; + } + catch (cli.System.IO.FileNotFoundException x) + { + throw new NoSuchFileException(npath); + } + catch (cli.System.IO.IOException | cli.System.ArgumentException x) + { + throw new IOException(x.getMessage()); + } + } + + private static class NetFileStore extends FileStore + { + private final DriveInfo info; + private final String name; + private final String type; + + NetFileStore(DriveInfo info) throws IOException + { + this.info = info; + try + { + if (false) throw new cli.System.IO.IOException(); + name = info.get_VolumeLabel(); + type = info.get_DriveFormat(); + } + catch (cli.System.IO.IOException x) + { + throw new IOException(x.getMessage()); + } + } + + public Object getAttribute(String attribute) throws IOException + { + switch (attribute) + { + case "totalSpace": + return getTotalSpace(); + case "unallocatedSpace": + return getUnallocatedSpace(); + case "usableSpace": + return getUsableSpace(); + default: + throw new UnsupportedOperationException(); + } + } + + public V getFileStoreAttributeView(Class type) + { + return null; + } + + public long getTotalSpace() throws IOException + { + try + { + if (false) throw new cli.System.IO.IOException(); + return info.get_TotalSize(); + } + catch (cli.System.IO.IOException x) + { + throw new IOException(x.getMessage()); + } + } + + public long getUnallocatedSpace() throws IOException + { + try + { + if (false) throw new cli.System.IO.IOException(); + return info.get_TotalFreeSpace(); + } + catch (cli.System.IO.IOException x) + { + throw new IOException(x.getMessage()); + } + } + + public long getUsableSpace() throws IOException + { + try + { + if (false) throw new cli.System.IO.IOException(); + return info.get_AvailableFreeSpace(); + } + catch (cli.System.IO.IOException x) + { + throw new IOException(x.getMessage()); + } + } + + public boolean isReadOnly() + { + return false; + } + + public String name() + { + return name; + } + + public boolean supportsFileAttributeView(Class type) + { + // null check + type.getClass(); + return type == BasicFileAttributeView.class || type == DosFileAttributeView.class; + } + + public boolean supportsFileAttributeView(String name) + { + return name.equals("basic") || name.equals("dos"); + } + + public String type() + { + return type; + } + + public String toString() + { + return name + " (" + info.get_Name().charAt(0) + ":)"; + } + } + + public FileStore getFileStore(Path path) throws IOException + { + NetPath npath = NetPath.from(path.toAbsolutePath()); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + { + sm.checkRead(npath.path); + } + return getFileStore(new DriveInfo(npath.path)); + } + + public void checkAccess(Path path, AccessMode... modes) throws IOException + { + String npath = NetPath.from(path).path; + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + { + if (modes.length == 0) + { + sm.checkRead(npath); + } + for (AccessMode m : modes) + { + switch (m) + { + case READ: + sm.checkRead(npath); + break; + case WRITE: + sm.checkWrite(npath); + break; + case EXECUTE: + sm.checkExec(npath); + break; + default: + throw new UnsupportedOperationException(); + } + } + } + try + { + if (false) throw new cli.System.ArgumentException(); + if (false) throw new cli.System.IO.DirectoryNotFoundException(); + if (false) throw new cli.System.IO.FileNotFoundException(); + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.NotSupportedException(); + if (false) throw new cli.System.Security.SecurityException(); + if (false) throw new cli.System.UnauthorizedAccessException(); + // note that File.GetAttributes() works for directories as well + int attr = File.GetAttributes(npath).Value; + for (AccessMode m : modes) + { + switch (m) + { + case READ: + case EXECUTE: + break; + case WRITE: + if ((attr & (cli.System.IO.FileAttributes.ReadOnly | cli.System.IO.FileAttributes.Directory)) == cli.System.IO.FileAttributes.ReadOnly) + { + throw new AccessDeniedException(npath, null, "file has read-only attribute set"); + } + if (getFileStore(path).isReadOnly()) + { + throw new AccessDeniedException(npath, null, "volume is read-only"); + } + break; + default: + throw new UnsupportedOperationException(); + } + } + } + catch (cli.System.IO.FileNotFoundException | cli.System.IO.DirectoryNotFoundException _) + { + throw new NoSuchFileException(npath); + } + catch (cli.System.Security.SecurityException | cli.System.UnauthorizedAccessException x) + { + throw new AccessDeniedException(npath, null, x.getMessage()); + } + catch (cli.System.ArgumentException | cli.System.IO.IOException | cli.System.NotSupportedException x) + { + throw new IOException(x.getMessage()); + } + } + + private static class BasicFileAttributesViewImpl extends AbstractBasicFileAttributeView + { + protected final String path; + + BasicFileAttributesViewImpl(String path) + { + this.path = path; + } + + public BasicFileAttributes readAttributes() throws IOException + { + return DosFileAttributesViewImpl.readAttributesImpl(path); + } + + public void setTimes(FileTime lastModifiedTime, FileTime lastAccessTime, FileTime createTime) throws IOException + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + { + sm.checkWrite(path); + } + try + { + if (false) throw new cli.System.ArgumentException(); + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.NotSupportedException(); + if (false) throw new cli.System.Security.SecurityException(); + if (false) throw new cli.System.UnauthorizedAccessException(); + if (File.Exists(path)) + { + if (lastModifiedTime != null) + { + File.SetLastWriteTimeUtc(path, toDateTime(lastModifiedTime)); + } + if (lastAccessTime != null) + { + File.SetLastAccessTimeUtc(path, toDateTime(lastAccessTime)); + } + if (createTime != null) + { + File.SetCreationTimeUtc(path, toDateTime(createTime)); + } + } + else if (Directory.Exists(path)) + { + if (lastModifiedTime != null) + { + Directory.SetLastWriteTimeUtc(path, toDateTime(lastModifiedTime)); + } + if (lastAccessTime != null) + { + Directory.SetLastAccessTimeUtc(path, toDateTime(lastAccessTime)); + } + if (createTime != null) + { + Directory.SetCreationTimeUtc(path, toDateTime(createTime)); + } + } + else + { + throw new NoSuchFileException(path); + } + } + catch (cli.System.ArgumentException + | cli.System.IO.IOException + | cli.System.NotSupportedException + | cli.System.Security.SecurityException + | cli.System.UnauthorizedAccessException x) + { + throw new IOException(x.getMessage()); + } + } + } + + private static class DosFileAttributesViewImpl extends BasicFileAttributesViewImpl implements DosFileAttributeView + { + private static final String READONLY_NAME = "readonly"; + private static final String ARCHIVE_NAME = "archive"; + private static final String SYSTEM_NAME = "system"; + private static final String HIDDEN_NAME = "hidden"; + private static final String ATTRIBUTES_NAME = "attributes"; + private static final Set dosAttributeNames = Util.newSet(basicAttributeNames, READONLY_NAME, ARCHIVE_NAME, SYSTEM_NAME, HIDDEN_NAME, ATTRIBUTES_NAME); + + DosFileAttributesViewImpl(String path) + { + super(path); + } + + public String name() + { + return "dos"; + } + + public DosFileAttributes readAttributes() throws IOException + { + return readAttributesImpl(path); + } + + private static class DosFileAttributesImpl implements DosFileAttributes + { + private final FileInfo info; + + DosFileAttributesImpl(FileInfo info) + { + this.info = info; + } + + int attributes() + { + return info.get_Attributes().Value; + } + + public FileTime creationTime() + { + return toFileTime(info.get_CreationTimeUtc()); + } + + public Object fileKey() + { + return null; + } + + public boolean isDirectory() + { + return (info.get_Attributes().Value & cli.System.IO.FileAttributes.Directory) != 0; + } + + public boolean isOther() + { + return false; + } + + public boolean isRegularFile() + { + return (info.get_Attributes().Value & cli.System.IO.FileAttributes.Directory) == 0; + } + + public boolean isSymbolicLink() + { + return false; + } + + public FileTime lastAccessTime() + { + return toFileTime(info.get_LastAccessTimeUtc()); + } + + public FileTime lastModifiedTime() + { + return toFileTime(info.get_LastWriteTimeUtc()); + } + + public long size() + { + return info.get_Exists() ? info.get_Length() : 0; + } + + public boolean isArchive() + { + return (info.get_Attributes().Value & cli.System.IO.FileAttributes.Archive) != 0; + } + + public boolean isHidden() + { + return (info.get_Attributes().Value & cli.System.IO.FileAttributes.Hidden) != 0; + } + + public boolean isReadOnly() + { + return (info.get_Attributes().Value & cli.System.IO.FileAttributes.ReadOnly) != 0; + } + + public boolean isSystem() + { + return (info.get_Attributes().Value & cli.System.IO.FileAttributes.System) != 0; + } + } + + static DosFileAttributesImpl readAttributesImpl(String path) throws IOException + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + { + sm.checkRead(path); + } + try + { + if (false) throw new cli.System.ArgumentException(); + if (false) throw new cli.System.IO.FileNotFoundException(); + if (false) throw new cli.System.IO.IOException(); + FileInfo info = new FileInfo(path); + // We have to rely on the (undocumented) fact that FileInfo.Attributes returns -1 + // when the path does not exist. We need this to work for both files and directories + // and this is the only efficient way to do that. + if (info.get_Attributes().Value == -1) + { + throw new NoSuchFileException(path); + } + return new DosFileAttributesImpl(info); + } + catch (cli.System.IO.FileNotFoundException _) + { + throw new NoSuchFileException(path); + } + catch (cli.System.IO.IOException | cli.System.ArgumentException x) + { + throw new IOException(x.getMessage()); + } + } + + public void setArchive(boolean value) throws IOException + { + setAttribute(cli.System.IO.FileAttributes.Archive, value); + } + + public void setHidden(boolean value) throws IOException + { + setAttribute(cli.System.IO.FileAttributes.Hidden, value); + } + + public void setReadOnly(boolean value) throws IOException + { + setAttribute(cli.System.IO.FileAttributes.ReadOnly, value); + } + + public void setSystem(boolean value) throws IOException + { + setAttribute(cli.System.IO.FileAttributes.System, value); + } + + private void setAttribute(int attr, boolean value) throws IOException + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + { + sm.checkWrite(path); + } + try + { + if (false) throw new cli.System.ArgumentException(); + if (false) throw new cli.System.IO.IOException(); + FileInfo info = new FileInfo(path); + if (value) + { + info.set_Attributes(cli.System.IO.FileAttributes.wrap(info.get_Attributes().Value | attr)); + } + else + { + info.set_Attributes(cli.System.IO.FileAttributes.wrap(info.get_Attributes().Value & ~attr)); + } + } + catch (cli.System.IO.FileNotFoundException _) + { + throw new NoSuchFileException(path); + } + catch (cli.System.ArgumentException + | cli.System.IO.IOException x) + { + throw new IOException(x.getMessage()); + } + } + + public Map readAttributes(String[] attributes) throws IOException + { + AttributesBuilder builder = AttributesBuilder.create(dosAttributeNames, attributes); + DosFileAttributesImpl attrs = readAttributesImpl(path); + addRequestedBasicAttributes(attrs, builder); + if (builder.match(READONLY_NAME)) + { + builder.add(READONLY_NAME, attrs.isReadOnly()); + } + if (builder.match(ARCHIVE_NAME)) + { + builder.add(ARCHIVE_NAME, attrs.isArchive()); + } + if (builder.match(SYSTEM_NAME)) + { + builder.add(SYSTEM_NAME, attrs.isSystem()); + } + if (builder.match(HIDDEN_NAME)) + { + builder.add(HIDDEN_NAME, attrs.isHidden()); + } + if (builder.match(ATTRIBUTES_NAME)) + { + builder.add(ATTRIBUTES_NAME, attrs.attributes()); + } + return builder.unmodifiableMap(); + } + + public void setAttribute(String attribute, Object value) throws IOException + { + switch (attribute) + { + case READONLY_NAME: + setReadOnly((Boolean)value); + break; + case ARCHIVE_NAME: + setArchive((Boolean)value); + break; + case SYSTEM_NAME: + setSystem((Boolean)value); + break; + case HIDDEN_NAME: + setHidden((Boolean)value); + break; + default: + super.setAttribute(attribute, value); + break; + } + } + } + + private static void validateLinkOption(LinkOption... options) + { + for (LinkOption option : options) + { + if (option == LinkOption.NOFOLLOW_LINKS) + { + // ignored + } + else + { + // null check + option.getClass(); + throw new UnsupportedOperationException(); + } + } + } + + public V getFileAttributeView(Path path, Class type, LinkOption... options) + { + String npath = NetPath.from(path).path; + validateLinkOption(options); + if (type == BasicFileAttributeView.class) + { + return (V)new BasicFileAttributesViewImpl(npath); + } + else if (type == DosFileAttributeView.class) + { + return (V)new DosFileAttributesViewImpl(npath); + } + else + { + // null check + type.getClass(); + return null; + } + } + + public A readAttributes(Path path, Class type, LinkOption... options) throws IOException + { + String npath = NetPath.from(path).path; + // null check + type.getClass(); + validateLinkOption(options); + if (type != BasicFileAttributes.class && type != DosFileAttributes.class) + { + throw new UnsupportedOperationException(); + } + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + { + sm.checkRead(npath); + } + return (A)DosFileAttributesViewImpl.readAttributesImpl(npath); + } + + DynamicFileAttributeView getFileAttributeView(Path file, String name, LinkOption... options) + { + validateLinkOption(options); + if (name.equals("basic")) + { + return new BasicFileAttributesViewImpl(NetPath.from(file).path); + } + else if (name.equals("dos")) + { + return new DosFileAttributesViewImpl(NetPath.from(file).path); + } + else + { + return null; + } + } + + boolean implDelete(Path file, boolean failIfNotExists) throws IOException + { + String path = NetPath.from(file).path; + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + { + sm.checkDelete(path); + } + try + { + if (false) throw new cli.System.ArgumentException(); + if (false) throw new cli.System.IO.FileNotFoundException(); + if (false) throw new cli.System.IO.DirectoryNotFoundException(); + if (false) throw new cli.System.IO.IOException(); + if (false) throw new cli.System.Security.SecurityException(); + if (false) throw new cli.System.UnauthorizedAccessException(); + int attr = cli.System.IO.File.GetAttributes(path).Value; + if ((attr & cli.System.IO.FileAttributes.Directory) != 0) + { + try + { + if (false) throw new cli.System.IO.IOException(); + cli.System.IO.Directory.Delete(path); + } + catch (cli.System.IO.IOException _) + { + // HACK we assume that the IOException is caused by the directory not being empty + throw new DirectoryNotEmptyException(path); + } + return true; + } + else + { + cli.System.IO.File.Delete(path); + return true; + } + } + catch (cli.System.ArgumentException x) + { + throw new FileSystemException(path, null, x.getMessage()); + } + catch (cli.System.IO.FileNotFoundException _) + { + if (failIfNotExists) + { + throw new NoSuchFileException(path); + } + else + { + return false; + } + } + catch (cli.System.IO.DirectoryNotFoundException _) + { + if (failIfNotExists) + { + throw new NoSuchFileException(path); + } + else + { + return false; + } + } + catch (cli.System.IO.IOException x) + { + throw new FileSystemException(path, null, x.getMessage()); + } + catch (cli.System.Security.SecurityException _) + { + throw new AccessDeniedException(path); + } + catch (cli.System.UnauthorizedAccessException _) + { + throw new AccessDeniedException(path); + } + } + + static FileTime toFileTime(cli.System.DateTime dateTime) + { + return FileTime.from((dateTime.get_Ticks() - 621355968000000000L) / 10, java.util.concurrent.TimeUnit.MICROSECONDS); + } + + static cli.System.DateTime toDateTime(FileTime fileTime) + { + return new cli.System.DateTime(fileTime.to(java.util.concurrent.TimeUnit.MICROSECONDS) * 10 + 621355968000000000L); + } +} diff --git a/openjdk/sun/nio/fs/NetPath.java b/openjdk/sun/nio/fs/NetPath.java new file mode 100644 index 0000000..6861a1e --- /dev/null +++ b/openjdk/sun/nio/fs/NetPath.java @@ -0,0 +1,569 @@ +/* + Copyright (C) 2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package sun.nio.fs; + +import com.sun.nio.file.ExtendedWatchEventModifier; +import com.sun.nio.file.SensitivityWatchEventModifier; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.nio.file.*; +import java.util.ArrayList; +import java.util.Iterator; +import static ikvm.internal.Util.MACOSX; +import static ikvm.internal.Util.WINDOWS; + +final class NetPath extends AbstractPath +{ + private static final char[] invalid = cli.System.IO.Path.GetInvalidFileNameChars(); + private final NetFileSystem fs; + final String path; + + NetPath(NetFileSystem fs, String path) + { + if (WINDOWS) + { + path = WindowsPathParser.parse(path).path(); + } + else + { + StringBuilder sb = null; + int separatorCount = 0; + boolean prevWasSeparator = false; + for (int i = 0; i < path.length(); i++) + { + char c = path.charAt(i); + if (c == 0) + { + throw new InvalidPathException(path, "Nul character not allowed"); + } + else if (c == '/') + { + if (prevWasSeparator) + { + if (sb == null) + { + sb = new StringBuilder(); + sb.append(path, 0, i); + } + continue; + } + separatorCount++; + prevWasSeparator = true; + } + else + { + prevWasSeparator = false; + } + if (sb != null) + { + sb.append(c); + } + } + if (sb != null) + { + path = sb.toString(); + } + if (path.length() > 1 && path.charAt(path.length() - 1) == '/') + { + path = path.substring(0, path.length() - 1); + } + } + this.fs = fs; + this.path = path; + } + + public FileSystem getFileSystem() + { + return fs; + } + + public boolean isAbsolute() + { + return cli.System.IO.Path.IsPathRooted(path) + && (!WINDOWS || path.startsWith("\\\\") || (path.length() >= 3 && path.charAt(1) == ':' && path.charAt(2) == '\\')); + } + + public Path getRoot() + { + int len = getRootLength(); + return len == 0 ? null : new NetPath(fs, path.substring(0, len)); + } + + private int getRootLength() + { + if (WINDOWS) + { + if (path.length() >= 2 && path.charAt(1) == ':') + { + if (path.length() >= 3 && path.charAt(2) == '\\') + { + return 3; + } + else + { + return 2; + } + } + else if (path.startsWith("\\\\")) + { + return path.indexOf('\\', path.indexOf('\\', 2) + 1) + 1; + } + } + + if (path.length() >= 1 && path.charAt(0) == cli.System.IO.Path.DirectorySeparatorChar) + { + return 1; + } + else + { + return 0; + } + } + + public Path getFileName() + { + if (path.length() == 0) + { + return this; + } + if (path.length() == getRootLength()) + { + return null; + } + String name = cli.System.IO.Path.GetFileName(path); + if (name == null || name.length() == 0) + { + return null; + } + return new NetPath(fs, name); + } + + public Path getParent() + { + if (path.length() == getRootLength()) + { + return null; + } + String parent = cli.System.IO.Path.GetDirectoryName(path); + if (parent == null || parent.length() == 0) + { + return null; + } + return new NetPath(fs, parent); + } + + public int getNameCount() + { + int len = getRootLength(); + if (path.length() == len) + { + return len == 0 ? 1 : 0; + } + int count = 1; + for (int i = len; i < path.length(); i++) + { + if (path.charAt(i) == cli.System.IO.Path.DirectorySeparatorChar) + { + count++; + } + } + return count; + } + + public Path getName(int index) + { + return new NetPath(fs, getNameImpl(index)); + } + + private String getNameImpl(int index) + { + for (int pos = getRootLength(); pos < path.length(); index--) + { + int next = path.indexOf(cli.System.IO.Path.DirectorySeparatorChar, pos); + if (index == 0) + { + return next == -1 ? path.substring(pos) : path.substring(pos, next); + } + if (next == -1) + { + break; + } + pos = next + 1; + } + if (path.length() == 0 && index == 0) + { + return ""; + } + throw new IllegalArgumentException(); + } + + public Path subpath(int beginIndex, int endIndex) + { + StringBuilder sb = new StringBuilder(); + for (int i = beginIndex; i < endIndex; i++) + { + if (i != beginIndex) + { + sb.append(cli.System.IO.Path.DirectorySeparatorChar); + } + sb.append(getNameImpl(i)); + } + return new NetPath(fs, sb.toString()); + } + + public boolean startsWith(Path other) + { + String npath = NetPath.from(other).path; + if (npath.length() == 0) + { + return path.length() == 0; + } + return path.regionMatches(WINDOWS, 0, npath, 0, npath.length()) + && (npath.length() == getRootLength() + || (npath.length() > getRootLength() + && (path.length() == npath.length() + || (path.length() > npath.length() && path.charAt(npath.length()) == cli.System.IO.Path.DirectorySeparatorChar)))); + } + + public boolean endsWith(Path other) + { + NetPath nother = NetPath.from(other); + String npath = nother.path; + if (npath.length() > path.length()) + { + return false; + } + if (npath.length() == 0) + { + return path.length() == 0; + } + int nameCount = getNameCount(); + int otherNameCount = nother.getNameCount(); + if (otherNameCount > nameCount) + { + return false; + } + int otherRootLength = nother.getRootLength(); + if (otherRootLength > 0) + { + if (otherNameCount != nameCount + || getRootLength() != otherRootLength + || !path.regionMatches(WINDOWS, 0, npath, 0, otherRootLength)) + { + return false; + } + } + int skip = nameCount - otherNameCount; + for (int i = 0; i < otherNameCount; i++) + { + String s1 = getNameImpl(i + skip); + String s2 = nother.getNameImpl(i); + if (s1.length() != s2.length() || !s1.regionMatches(WINDOWS, 0, s2, 0, s1.length())) + { + return false; + } + } + return true; + } + + public Path normalize() + { + int rootLength = getRootLength(); + ArrayList list = new ArrayList<>(); + for (int i = 0, count = getNameCount(); i < count; i++) + { + String s = getNameImpl(i); + if (s.equals("..")) + { + if (list.size() == 0) + { + if (rootLength == 0 || (WINDOWS && rootLength == 2)) + { + list.add(".."); + } + } + else if (list.get(list.size() - 1).equals("..")) + { + list.add(".."); + } + else + { + list.remove(list.size() - 1); + } + } + else if (!s.equals(".")) + { + list.add(s); + } + } + StringBuilder sb = new StringBuilder(); + sb.append(path.substring(0, getRootLength())); + for (int i = 0; i < list.size(); i++) + { + if (i != 0) + { + sb.append(cli.System.IO.Path.DirectorySeparatorChar); + } + sb.append(list.get(i)); + } + return new NetPath(fs, sb.toString()); + } + + public Path resolve(Path other) + { + NetPath nother = NetPath.from(other); + String npath = nother.path; + if (nother.isAbsolute()) + { + return other; + } + if (npath.length() == 0) + { + return this; + } + if (WINDOWS) + { + if (nother.getRootLength() == 2 && getRootLength() == 3 && (path.charAt(0) | 0x20) == (npath.charAt(0) | 0x20)) + { + // we're in the case where we have a root "x:\" and other "x:", so we have to chop off "x:" from other because + // otherwise Path.Combine will just return other + npath = npath.substring(2); + } + else if (nother.getRootLength() == 1 && getRootLength() > 3) + { + // we're in the case where we have a root "\\host\share\" and other "\", + // we have to manually handle this because Path.Combine doesn't do the right thing + return new NetPath(fs, path.substring(0, getRootLength()) + npath); + } + } + return new NetPath(fs, cli.System.IO.Path.Combine(path, npath)); + } + + public Path relativize(Path other) + { + NetPath nother = NetPath.from(other); + if (equals(nother)) + { + return new NetPath(fs, ""); + } + int rootLength = getRootLength(); + if (nother.getRootLength() != rootLength || !path.regionMatches(true, 0, nother.path, 0, rootLength)) + { + throw new IllegalArgumentException("'other' has different root"); + } + int nameCount = getNameCount(); + int otherNameCount = nother.getNameCount(); + int count = Math.min(nameCount, otherNameCount); + int i = 0; + // skip the common parts + for (; i < count && getNameImpl(i).equals(nother.getNameImpl(i)); i++) + { + } + // remove the unused parts of our path + StringBuilder sb = new StringBuilder(); + for (int j = i; j < nameCount; j++) + { + sb.append("..\\"); + } + // append the new parts of other + for (int j = i; j < otherNameCount; j++) + { + if (j != i) + { + sb.append("\\"); + } + sb.append(nother.getNameImpl(j)); + } + return new NetPath(fs, sb.toString()); + } + + public URI toUri() + { + if (WINDOWS) + { + return WindowsUriSupport.toUri(this); + } + else + { + return UnixUriUtils.toUri(this); + } + } + + public NetPath toAbsolutePath() + { + if (isAbsolute()) + { + return this; + } + // System.getProperty("user.dir") will trigger the specified security check + return new NetPath(fs, cli.System.IO.Path.GetFullPath(cli.System.IO.Path.Combine(System.getProperty("user.dir"), path))); + } + + public Path toRealPath(LinkOption... options) throws IOException + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + { + sm.checkRead(path); + if (!isAbsolute()) + { + sm.checkPropertyAccess("user.dir"); + } + } + return new NetPath(fs, toRealPathImpl(path)); + } + + private static native String toRealPathImpl(String path); + + public WatchKey register(WatchService watcher, WatchEvent.Kind[] events, WatchEvent.Modifier... modifiers) throws IOException + { + if (!(watcher instanceof NetFileSystem.NetWatchService)) + { + // null check + watcher.getClass(); + throw new ProviderMismatchException(); + } + boolean create = false; + boolean delete = false; + boolean modify = false; + boolean overflow = false; + boolean subtree = false; + for (WatchEvent.Kind kind : events) + { + if (kind == StandardWatchEventKinds.ENTRY_CREATE) + { + create = true; + } + else if (kind == StandardWatchEventKinds.ENTRY_DELETE) + { + delete = true; + } + else if (kind == StandardWatchEventKinds.ENTRY_MODIFY) + { + modify = true; + } + else if (kind == StandardWatchEventKinds.OVERFLOW) + { + overflow = true; + } + else + { + // null check + kind.getClass(); + throw new UnsupportedOperationException(); + } + } + if (!create && !delete && !modify) + { + throw new IllegalArgumentException(); + } + for (WatchEvent.Modifier modifier : modifiers) + { + if (modifier == ExtendedWatchEventModifier.FILE_TREE) + { + subtree = true; + } + else if (modifier instanceof SensitivityWatchEventModifier) + { + // ignore + } + else + { + // null check + modifier.getClass(); + throw new UnsupportedOperationException(); + } + } + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + { + sm.checkRead(path); + if (subtree) + { + sm.checkRead(path + cli.System.IO.Path.DirectorySeparatorChar + '-'); + } + } + return ((NetFileSystem.NetWatchService)watcher).register(this, create, delete, modify, overflow, subtree); + } + + public int compareTo(Path other) + { + String path2 = ((NetPath)other).path; + int len1 = path.length(); + int len2 = path2.length(); + int min = Math.min(len1, len2); + for (int i = 0; i < min; i++) + { + char c1 = path.charAt(i); + char c2 = path2.charAt(i); + if (c1 != c2 && Character.toUpperCase(c1) != Character.toUpperCase(c2)) + { + return c1 - c2; + } + } + return len1 - len2; + } + + public boolean equals(Object other) + { + if (!(other instanceof NetPath)) + { + return false; + } + return compareTo((NetPath)other) == 0; + } + + public int hashCode() + { + int hash = 0; + for (int i = 0; i < path.length(); i++) + { + hash = 97 * hash + Character.toUpperCase(path.charAt(i)); + } + return hash; + } + + public String toString() + { + return path; + } + + boolean isUnc() + { + return WINDOWS && getRootLength() > 3; + } + + static NetPath from(Path path) + { + if (!(path instanceof NetPath)) + { + // null check + path.getClass(); + throw new ProviderMismatchException(); + } + return (NetPath)path; + } +} diff --git a/openjdk/sun/nio/fs/UnixUriUtils.java b/openjdk/sun/nio/fs/UnixUriUtils.java new file mode 100644 index 0000000..0542681 --- /dev/null +++ b/openjdk/sun/nio/fs/UnixUriUtils.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2008, 2013, 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.nio.fs; + +import java.nio.file.Path; +import java.io.File; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Arrays; + +/** + * Unix specific Path <--> URI conversion + */ + +class UnixUriUtils { + private UnixUriUtils() { } + + /** + * Converts URI to Path + */ + static Path fromUri(NetFileSystem fs, URI uri) { + if (!uri.isAbsolute()) + throw new IllegalArgumentException("URI is not absolute"); + if (uri.isOpaque()) + throw new IllegalArgumentException("URI is not hierarchical"); + String scheme = uri.getScheme(); + if ((scheme == null) || !scheme.equalsIgnoreCase("file")) + throw new IllegalArgumentException("URI scheme is not \"file\""); + if (uri.getAuthority() != null) + throw new IllegalArgumentException("URI has an authority component"); + if (uri.getFragment() != null) + throw new IllegalArgumentException("URI has a fragment component"); + if (uri.getQuery() != null) + throw new IllegalArgumentException("URI has a query component"); + + // compatibility with java.io.File + if (!uri.toString().startsWith("file:///")) + return new File(uri).toPath(); + + // transformation use raw path + String p = uri.getRawPath(); + int len = p.length(); + if (len == 0) + throw new IllegalArgumentException("URI path component is empty"); + + // transform escaped octets and unescaped characters to bytes + if (p.endsWith("/") && len > 1) + p = p.substring(0, len - 1); + + return new NetPath(fs, p); + } + + /** + * Converts Path to URI + */ + static URI toUri(NetPath up) { + byte[] path = up.toAbsolutePath().toString().getBytes(); + StringBuilder sb = new StringBuilder("file:///"); + assert path[0] == '/'; + for (int i=1; i> 4) & 0x0f]); + sb.append(hexDigits[(c) & 0x0f]); + } + } + + // trailing slash if directory + if (sb.charAt(sb.length()-1) != '/') { + try { + if (cli.System.IO.Directory.Exists(up.path)) + sb.append('/'); + } catch (Throwable x) { + // ignore + } + } + + try { + return new URI(sb.toString()); + } catch (URISyntaxException x) { + throw new AssertionError(x); // should not happen + } + } + + // The following is copied from java.net.URI + + // Compute the low-order mask for the characters in the given string + private static long lowMask(String chars) { + int n = chars.length(); + long m = 0; + for (int i = 0; i < n; i++) { + char c = chars.charAt(i); + if (c < 64) + m |= (1L << c); + } + return m; + } + + // Compute the high-order mask for the characters in the given string + private static long highMask(String chars) { + int n = chars.length(); + long m = 0; + for (int i = 0; i < n; i++) { + char c = chars.charAt(i); + if ((c >= 64) && (c < 128)) + m |= (1L << (c - 64)); + } + return m; + } + + // Compute a low-order mask for the characters + // between first and last, inclusive + private static long lowMask(char first, char last) { + long m = 0; + int f = Math.max(Math.min(first, 63), 0); + int l = Math.max(Math.min(last, 63), 0); + for (int i = f; i <= l; i++) + m |= 1L << i; + return m; + } + + // Compute a high-order mask for the characters + // between first and last, inclusive + private static long highMask(char first, char last) { + long m = 0; + int f = Math.max(Math.min(first, 127), 64) - 64; + int l = Math.max(Math.min(last, 127), 64) - 64; + for (int i = f; i <= l; i++) + m |= 1L << i; + return m; + } + + // Tell whether the given character is permitted by the given mask pair + private static boolean match(char c, long lowMask, long highMask) { + if (c < 64) + return ((1L << c) & lowMask) != 0; + if (c < 128) + return ((1L << (c - 64)) & highMask) != 0; + return false; + } + + // decode + private static int decode(char c) { + if ((c >= '0') && (c <= '9')) + return c - '0'; + if ((c >= 'a') && (c <= 'f')) + return c - 'a' + 10; + if ((c >= 'A') && (c <= 'F')) + return c - 'A' + 10; + throw new AssertionError(); + } + + // digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | + // "8" | "9" + private static final long L_DIGIT = lowMask('0', '9'); + private static final long H_DIGIT = 0L; + + // upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | + // "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | + // "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" + private static final long L_UPALPHA = 0L; + private static final long H_UPALPHA = highMask('A', 'Z'); + + // lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | + // "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | + // "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" + private static final long L_LOWALPHA = 0L; + private static final long H_LOWALPHA = highMask('a', 'z'); + + // alpha = lowalpha | upalpha + private static final long L_ALPHA = L_LOWALPHA | L_UPALPHA; + private static final long H_ALPHA = H_LOWALPHA | H_UPALPHA; + + // alphanum = alpha | digit + private static final long L_ALPHANUM = L_DIGIT | L_ALPHA; + private static final long H_ALPHANUM = H_DIGIT | H_ALPHA; + + // mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | + // "(" | ")" + private static final long L_MARK = lowMask("-_.!~*'()"); + private static final long H_MARK = highMask("-_.!~*'()"); + + // unreserved = alphanum | mark + private static final long L_UNRESERVED = L_ALPHANUM | L_MARK; + private static final long H_UNRESERVED = H_ALPHANUM | H_MARK; + + // pchar = unreserved | escaped | + // ":" | "@" | "&" | "=" | "+" | "$" | "," + private static final long L_PCHAR + = L_UNRESERVED | lowMask(":@&=+$,"); + private static final long H_PCHAR + = H_UNRESERVED | highMask(":@&=+$,"); + + // All valid path characters + private static final long L_PATH = L_PCHAR | lowMask(";/"); + private static final long H_PATH = H_PCHAR | highMask(";/"); + + private final static char[] hexDigits = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + }; +} diff --git a/openjdk/sun/nio/fs/WindowsUriSupport.java b/openjdk/sun/nio/fs/WindowsUriSupport.java new file mode 100644 index 0000000..0301bf9 --- /dev/null +++ b/openjdk/sun/nio/fs/WindowsUriSupport.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2008, 2009, 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.nio.fs; + +import java.net.URI; +import java.net.URISyntaxException; + +/** + * Utility methods to convert between Path and URIs. + */ + +class WindowsUriSupport { + private WindowsUriSupport() { + } + + // suffix for IPv6 literal address + private static final String IPV6_LITERAL_SUFFIX = ".ipv6-literal.net"; + + /** + * Returns URI to represent the given (absolute) path + */ + private static URI toUri(String path, boolean isUnc, boolean addSlash) { + String uriHost; + String uriPath; + + if (isUnc) { + int slash = path.indexOf('\\', 2); + uriHost = path.substring(2, slash); + uriPath = path.substring(slash).replace('\\', '/'); + + // handle IPv6 literal addresses + // 1. drop .ivp6-literal.net + // 2. replace "-" with ":" + // 3. replace "s" with "%" (zone/scopeID delimiter) + if (uriHost.endsWith(IPV6_LITERAL_SUFFIX)) { + uriHost = uriHost + .substring(0, uriHost.length() - IPV6_LITERAL_SUFFIX.length()) + .replace('-', ':') + .replace('s', '%'); + } + } else { + uriHost = ""; + uriPath = "/" + path.replace('\\', '/'); + } + + // append slash if known to be directory + if (addSlash) + uriPath += "/"; + + // return file:///C:/My%20Documents or file://server/share/foo + try { + return new URI("file", uriHost, uriPath, null); + } catch (URISyntaxException x) { + if (!isUnc) + throw new AssertionError(x); + } + + // if we get here it means we've got a UNC with reserved characters + // in the server name. The authority component cannot contain escaped + // octets so fallback to encoding the server name into the URI path + // component. + uriPath = "//" + path.replace('\\', '/'); + if (addSlash) + uriPath += "/"; + try { + return new URI("file", null, uriPath, null); + } catch (URISyntaxException x) { + throw new AssertionError(x); + } + } + + /** + * Converts given Path to a URI + */ + static URI toUri(NetPath path) { + path = path.toAbsolutePath(); + String s = path.toString(); + + // trailing slash will be added if file is a directory. Skip check if + // already have trailing space + boolean addSlash = false; + if (!s.endsWith("\\")) { + try { + addSlash = cli.System.IO.Directory.Exists(s); + } catch (Throwable x) { + } + } + + return toUri(s, path.isUnc(), addSlash); + } + + /** + * Converts given URI to a Path + */ + static NetPath fromUri(NetFileSystem fs, URI uri) { + if (!uri.isAbsolute()) + throw new IllegalArgumentException("URI is not absolute"); + if (uri.isOpaque()) + throw new IllegalArgumentException("URI is not hierarchical"); + String scheme = uri.getScheme(); + if ((scheme == null) || !scheme.equalsIgnoreCase("file")) + throw new IllegalArgumentException("URI scheme is not \"file\""); + if (uri.getFragment() != null) + throw new IllegalArgumentException("URI has a fragment component"); + if (uri.getQuery() != null) + throw new IllegalArgumentException("URI has a query component"); + String path = uri.getPath(); + if (path.equals("")) + throw new IllegalArgumentException("URI path component is empty"); + + // UNC + String auth = uri.getAuthority(); + if (auth != null && !auth.equals("")) { + String host = uri.getHost(); + if (host == null) + throw new IllegalArgumentException("URI authority component has undefined host"); + if (uri.getUserInfo() != null) + throw new IllegalArgumentException("URI authority component has user-info"); + if (uri.getPort() != -1) + throw new IllegalArgumentException("URI authority component has port number"); + + // IPv6 literal + // 1. drop enclosing brackets + // 2. replace ":" with "-" + // 3. replace "%" with "s" (zone/scopeID delimiter) + // 4. Append .ivp6-literal.net + if (host.startsWith("[")) { + host = host.substring(1, host.length()-1) + .replace(':', '-') + .replace('%', 's'); + host += IPV6_LITERAL_SUFFIX; + } + + // reconstitute the UNC + path = "\\\\" + host + path; + } else { + if ((path.length() > 2) && (path.charAt(2) == ':')) { + // "/c:/foo" --> "c:/foo" + path = path.substring(1); + } + } + return new NetPath(fs, path); + } +} diff --git a/openjdk/sun/print/PrintPeer.java b/openjdk/sun/print/PrintPeer.java new file mode 100644 index 0000000..892d591 --- /dev/null +++ b/openjdk/sun/print/PrintPeer.java @@ -0,0 +1,42 @@ +/* + Copyright (C) 2009 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.print; + +import java.awt.Graphics2D; + + + +/** + * A helper interface for implementing the print API for IKVM + */ +public interface PrintPeer{ + + public Object getPrinterStatus(String PrinterName, Class category); + + public String getDefaultPrinterName(); + + public String[] getAllPrinterNames(); + + public Graphics2D createGraphics(cli.System.Drawing.Graphics g); +} diff --git a/openjdk/sun/print/UnixPrintServiceLookup.java b/openjdk/sun/print/UnixPrintServiceLookup.java new file mode 100644 index 0000000..8c18f4e --- /dev/null +++ b/openjdk/sun/print/UnixPrintServiceLookup.java @@ -0,0 +1,33 @@ +/* + Copyright (C) 2009 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +package sun.print; + + + +/** + * Currently this class is called via Reflection. + */ +public class UnixPrintServiceLookup extends Win32PrintServiceLookup{ + +} diff --git a/openjdk/sun/print/Win32PrintJob.java b/openjdk/sun/print/Win32PrintJob.java new file mode 100644 index 0000000..d061795 --- /dev/null +++ b/openjdk/sun/print/Win32PrintJob.java @@ -0,0 +1,1126 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (C) 2009, 2012 Volker Berlin (i-net software) + * Copyright (C) 2010, 2011 Karsten Heinrich (i-net software) + * 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.print; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.awt.print.PageFormat; +import java.awt.print.Pageable; +import java.awt.print.Paper; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.TreeSet; + +import javax.print.CancelablePrintJob; +import javax.print.Doc; +import javax.print.DocFlavor; +import javax.print.PrintException; +import javax.print.PrintService; +import javax.print.attribute.Attribute; +import javax.print.attribute.AttributeSetUtilities; +import javax.print.attribute.DocAttributeSet; +import javax.print.attribute.HashPrintJobAttributeSet; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.PrintJobAttribute; +import javax.print.attribute.PrintJobAttributeSet; +import javax.print.attribute.PrintRequestAttribute; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.print.attribute.standard.Chromaticity; +import javax.print.attribute.standard.Copies; +import javax.print.attribute.standard.Destination; +import javax.print.attribute.standard.DocumentName; +import javax.print.attribute.standard.Fidelity; +import javax.print.attribute.standard.JobName; +import javax.print.attribute.standard.JobOriginatingUserName; +import javax.print.attribute.standard.Media; +import javax.print.attribute.standard.MediaPrintableArea; +import javax.print.attribute.standard.MediaSize; +import javax.print.attribute.standard.MediaSizeName; +import javax.print.attribute.standard.MediaTray; +import javax.print.attribute.standard.OrientationRequested; +import javax.print.attribute.standard.PageRanges; +import javax.print.attribute.standard.PrinterIsAcceptingJobs; +import javax.print.attribute.standard.PrinterState; +import javax.print.attribute.standard.PrinterStateReason; +import javax.print.attribute.standard.PrinterStateReasons; +import javax.print.attribute.standard.RequestingUserName; +import javax.print.attribute.standard.SheetCollate; +import javax.print.event.PrintJobAttributeListener; +import javax.print.event.PrintJobEvent; +import javax.print.event.PrintJobListener; + +import sun.awt.windows.WPrinterJob; +import sun.print.Win32PrintService.NetMediaTray; + +import cli.System.Drawing.Printing.*; + +/** + * @author Volker Berlin + */ +public class Win32PrintJob implements CancelablePrintJob{ + + private ArrayList jobListeners; + + private ArrayList attrListeners; + + private ArrayList listenedAttributeSets; + + private final Win32PrintService service; + + + private boolean printing; + private boolean printReturned; + + private PrintRequestAttributeSet reqAttrSet; + + private PrintJobAttributeSet jobAttrSet; + + private PrinterJob job = new WPrinterJob(); + private Doc doc; + private String mDestination; + + /* these variables used globally to store reference to the print + * data retrieved as a stream. On completion these are always closed + * if non-null. + */ + private InputStream instream; + + /* default values overridden by those extracted from the attributes */ + private boolean fidelity; + private boolean printColor; + private String jobName = "Java Printing"; + private int copies; + private MediaSizeName mediaName; + private MediaSize mediaSize; + private OrientationRequested orient; + + private final PrintPeer peer; + private PrinterException printerException; + + private PageNumberConverter pageRanges; + + private MediaTray mediaTray; + + + Win32PrintJob(Win32PrintService service, PrintPeer peer){ + this.service = service; + this.peer = peer; + } + + + @Override + public PrintService getPrintService(){ + return service; + } + + + @Override + public PrintJobAttributeSet getAttributes(){ + synchronized(this){ + if(jobAttrSet == null){ + /* just return an empty set until the job is submitted */ + PrintJobAttributeSet jobSet = new HashPrintJobAttributeSet(); + return AttributeSetUtilities.unmodifiableView(jobSet); + }else{ + return jobAttrSet; + } + } + } + + + @Override + public void addPrintJobListener(PrintJobListener listener){ + synchronized(this){ + if(listener == null){ + return; + } + if(jobListeners == null){ + jobListeners = new ArrayList(); + } + jobListeners.add(listener); + } + } + + + @Override + public void removePrintJobListener(PrintJobListener listener){ + synchronized(this){ + if(listener == null || jobListeners == null){ + return; + } + jobListeners.remove(listener); + if(jobListeners.isEmpty()){ + jobListeners = null; + } + } + } + + + /* Closes any stream already retrieved for the data. + * We want to avoid unnecessarily asking the Doc to create a stream only + * to get a reference in order to close it because the job failed. + * If the representation class is itself a "stream", this + * closes that stream too. + */ + private void closeDataStreams() { + // TODO + } + + private void notifyEvent(int reason) { + + /* since this method should always get called, here's where + * we will perform the clean up of any data stream supplied. + */ + switch (reason) { + case PrintJobEvent.DATA_TRANSFER_COMPLETE: + case PrintJobEvent.JOB_CANCELED : + case PrintJobEvent.JOB_FAILED : + case PrintJobEvent.NO_MORE_EVENTS : + case PrintJobEvent.JOB_COMPLETE : + closeDataStreams(); + } + + synchronized (this) { + if (jobListeners != null) { + PrintJobListener listener; + PrintJobEvent event = new PrintJobEvent(this, reason); + for (int i = 0; i < jobListeners.size(); i++) { + listener = jobListeners.get(i); + switch (reason) { + + case PrintJobEvent.JOB_COMPLETE : + listener.printJobCompleted(event); + break; + + case PrintJobEvent.JOB_CANCELED : + listener.printJobCanceled(event); + break; + + case PrintJobEvent.JOB_FAILED : + listener.printJobFailed(event); + break; + + case PrintJobEvent.DATA_TRANSFER_COMPLETE : + listener.printDataTransferCompleted(event); + break; + + case PrintJobEvent.NO_MORE_EVENTS : + listener.printJobNoMoreEvents(event); + break; + + default: + break; + } + } + } + } + } + + @Override + public void addPrintJobAttributeListener(PrintJobAttributeListener listener, PrintJobAttributeSet attributes){ + synchronized(this){ + if(listener == null){ + return; + } + if(attrListeners == null){ + attrListeners = new ArrayList(); + listenedAttributeSets = new ArrayList(); + } + attrListeners.add(listener); + if(attributes == null){ + attributes = new HashPrintJobAttributeSet(); + } + listenedAttributeSets.add(attributes); + } + } + + + @Override + public void removePrintJobAttributeListener(PrintJobAttributeListener listener){ + synchronized(this){ + if(listener == null || attrListeners == null){ + return; + } + int index = attrListeners.indexOf(listener); + if(index == -1){ + return; + }else{ + attrListeners.remove(index); + listenedAttributeSets.remove(index); + if(attrListeners.isEmpty()){ + attrListeners = null; + listenedAttributeSets = null; + } + } + } + } + + + @Override + public void print(Doc doc, PrintRequestAttributeSet attributes) throws PrintException{ + + synchronized(this){ + if(printing){ + throw new PrintException("already printing"); + }else{ + printing = true; + } + } + + PrinterState prnState = (PrinterState)service.getAttribute(PrinterState.class); + if(prnState == PrinterState.STOPPED){ + PrinterStateReasons prnStateReasons = (PrinterStateReasons)service.getAttribute(PrinterStateReasons.class); + if((prnStateReasons != null) && (prnStateReasons.containsKey(PrinterStateReason.SHUTDOWN))){ + throw new PrintException("PrintService is no longer available."); + } + } + + if((PrinterIsAcceptingJobs)(service.getAttribute(PrinterIsAcceptingJobs.class)) == PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS){ + throw new PrintException("Printer is not accepting job."); + } + + this.doc = doc; + /* check if the parameters are valid before doing much processing */ + DocFlavor flavor = doc.getDocFlavor(); + Object data; + + try{ + data = doc.getPrintData(); + }catch(IOException e){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException("can't get print data: " + e.toString()); + } + + if (data == null) { + throw new PrintException("Null print data."); + } + + if(flavor == null || (!service.isDocFlavorSupported(flavor))){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintJobFlavorException("invalid flavor", flavor); + } + + initializeAttributeSets(doc, attributes); + + getAttributeValues(flavor); + + String repClassName = flavor.getRepresentationClassName(); + + if(flavor.equals(DocFlavor.INPUT_STREAM.GIF) || flavor.equals(DocFlavor.INPUT_STREAM.JPEG) + || flavor.equals(DocFlavor.INPUT_STREAM.PNG) || flavor.equals(DocFlavor.BYTE_ARRAY.GIF) + || flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) || flavor.equals(DocFlavor.BYTE_ARRAY.PNG)){ + try{ + instream = doc.getStreamForBytes(); + if(instream == null){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException("No stream for data"); + } + printableJob(new ImagePrinter(instream)); + service.wakeNotifier(); + return; + }catch(ClassCastException cce){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(cce); + }catch(IOException ioe){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(ioe); + } + }else if(flavor.equals(DocFlavor.URL.GIF) || flavor.equals(DocFlavor.URL.JPEG) + || flavor.equals(DocFlavor.URL.PNG)){ + try{ + printableJob(new ImagePrinter((URL)data)); + service.wakeNotifier(); + return; + }catch(ClassCastException cce){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(cce); + } + }else if(repClassName.equals("java.awt.print.Pageable")){ + try{ + pageableJob((Pageable)doc.getPrintData()); + service.wakeNotifier(); + return; + }catch(ClassCastException cce){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(cce); + }catch(IOException ioe){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(ioe); + } + }else if(repClassName.equals("java.awt.print.Printable")){ + try{ + printableJob((Printable)doc.getPrintData()); + service.wakeNotifier(); + return; + }catch(ClassCastException cce){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(cce); + }catch(IOException ioe){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(ioe); + } + }else if(repClassName.equals("[B") || repClassName.equals("java.io.InputStream") + || repClassName.equals("java.net.URL")){ + + if(repClassName.equals("java.net.URL")){ + URL url = (URL)data; + try{ + instream = url.openStream(); + }catch(IOException e){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(e.toString()); + } + }else{ + try{ + instream = doc.getStreamForBytes(); + }catch(IOException ioe){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(ioe.toString()); + } + } + + if(instream == null){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException("No stream for data"); + } + + if(mDestination != null){ // if destination attribute is set + try{ + FileOutputStream fos = new FileOutputStream(mDestination); + byte[] buffer = new byte[1024]; + int cread; + + while((cread = instream.read(buffer, 0, buffer.length)) >= 0){ + fos.write(buffer, 0, cread); + } + fos.flush(); + fos.close(); + }catch(FileNotFoundException fnfe){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(fnfe.toString()); + }catch(IOException ioe){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(ioe.toString()); + } + notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE); + notifyEvent(PrintJobEvent.JOB_COMPLETE); + service.wakeNotifier(); + return; + } + + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException("Print job failed. IKVM does not support raw data currently."); + }else{ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException("unrecognized class: " + repClassName); + } + } + + + public void printableJob(Printable printable) throws PrintException { + throw new PrintException("Win32PrintJob.printableJob() not implemented:"); + } + + public void pageableJob(Pageable pageable) throws PrintException { + // a general hint for this code here: The PrintJob implementation (WPrinterJob) in the Oracle + // JRE implements SunPrinterJobService - which we don't here. Unfortunately this is used as a hint + // to distinguish between the build-in printer service and custom printer services. So for the RasterPrinterJob + // this implementation of the Win32PrintJob is a custom print job! That's why several methods of + // RasterPrintJob(which only apply to the SunPrinterJobService otherwise) had to be moved here. + // This includes the attribute resolving and the media patch for instance. + try { + PrintDocument printDocument = createPrintDocument( ); + pageable = patchMedia( pageable ); + + printDocument.add_QueryPageSettings(new QueryPageSettingsEventHandler(new QueryPage( pageable, printColor, mediaTray ) ) ); + printDocument.add_PrintPage(new PrintPageEventHandler(new PrintPage(pageable))); + printDocument.Print(); + if(printerException != null){ + throw printerException; + } + //TODO throw exception on Cancel + notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE); + return; + } catch (PrinterException pe) { + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(pe); + } finally { + printReturned = true; + notifyEvent(PrintJobEvent.NO_MORE_EVENTS); + } + } + + + private PrintDocument createPrintDocument() throws PrintException{ + PrintDocument printDocument = new PrintDocument(); + PrinterSettings settings = printDocument.get_PrinterSettings(); + settings.set_PrinterName( service.getName() ); + if( !settings.get_IsValid() ){ + throw new PrintException("Printer name ''" + service.getName() + "' is invalid."); + } + + if( jobName != null ){ + printDocument.set_DocumentName( jobName ); + } + printDocument.get_DefaultPageSettings().set_Color(printColor); + + Attribute destination = reqAttrSet.get(Destination.class); + if(destination instanceof Destination){ + File destFile = new File(((Destination)destination).getURI()); + settings.set_PrintFileName(destFile.getAbsolutePath()); + settings.set_PrintToFile(true); + } + + settings.set_Copies((short)copies); + boolean collated = false; + if(copies > 1){ + Object collate = reqAttrSet.get(SheetCollate.class); + if( collate == null ){ + collate = service.getDefaultAttributeValue(SheetCollate.class); + } + collated = collate == SheetCollate.COLLATED; + settings.set_Collate( collated ); + } + Attribute pageRangeObj = reqAttrSet.get(PageRanges.class); + if( pageRangeObj != null ){ + int[][] ranges = ((PageRanges)pageRangeObj).getMembers(); + if( ranges.length > 1 ){ + settings.set_PrintRange( PrintRange.wrap( PrintRange.Selection ) ); + } else { + if( ranges.length > 0 ){ + settings.set_FromPage(ranges[0][0]); + settings.set_ToPage(ranges[0][1]); + settings.set_PrintRange( PrintRange.wrap( PrintRange.SomePages ) ); + } // else allPages??? + } + } else { + settings.set_PrintRange( PrintRange.wrap( PrintRange.AllPages ) ); + } + pageRanges = new PageNumberConverter( (PageRanges)pageRangeObj, copies, collated ); + return printDocument; + } + + // copied from RasterPrintJob + // Since we don't implement SunPrinterJobService the hack in RasterPrintService which applies + // the media format to the auto-generated OpenBook doesn't work here. So we have to modify + // the page format of the OpenBook here - equal to the code in RasterPrintJob + private Pageable patchMedia( Pageable pageable ){ + /* OpenBook is used internally only when app uses Printable. + * This is the case when we use the values from the attribute set. + */ + Media media = (Media)reqAttrSet.get(Media.class); + OrientationRequested orientReq = (OrientationRequested)reqAttrSet.get(OrientationRequested.class); + MediaPrintableArea mpa = (MediaPrintableArea)reqAttrSet.get(MediaPrintableArea.class); + + if ((orientReq != null || media != null || mpa != null) && pageable instanceof OpenBook) { + + /* We could almost(!) use PrinterJob.getPageFormat() except + * here we need to start with the PageFormat from the OpenBook : + */ + Printable printable = pageable.getPrintable(0); + PageFormat pf = (PageFormat)pageable.getPageFormat(0).clone(); + Paper paper = pf.getPaper(); + + /* If there's a media but no media printable area, we can try + * to retrieve the default value for mpa and use that. + */ + if (mpa == null && media != null && service.isAttributeCategorySupported(MediaPrintableArea.class)) { + Object mpaVals = service. getSupportedAttributeValues(MediaPrintableArea.class, null, reqAttrSet); + if (mpaVals instanceof MediaPrintableArea[] && ((MediaPrintableArea[])mpaVals).length > 0) { + mpa = ((MediaPrintableArea[])mpaVals)[0]; + } + } + + if (isSupportedValue(orientReq, reqAttrSet) || (!fidelity && orientReq != null)) { + int orient; + if (orientReq.equals(OrientationRequested.REVERSE_LANDSCAPE)) { + orient = PageFormat.REVERSE_LANDSCAPE; + } else if (orientReq.equals(OrientationRequested.LANDSCAPE)) { + orient = PageFormat.LANDSCAPE; + } else { + orient = PageFormat.PORTRAIT; + } + pf.setOrientation(orient); + } + + if (isSupportedValue(media, reqAttrSet) || (!fidelity && media != null)) { + if (media instanceof MediaSizeName) { + MediaSizeName msn = (MediaSizeName)media; + MediaSize msz = MediaSize.getMediaSizeForName(msn); + if (msz != null) { + float paperWid = msz.getX(MediaSize.INCH) * 72.0f; + float paperHgt = msz.getY(MediaSize.INCH) * 72.0f; + paper.setSize(paperWid, paperHgt); + if (mpa == null) { + paper.setImageableArea(72.0, 72.0, paperWid-144.0, paperHgt-144.0); + } + } + } + } + + if (isSupportedValue(mpa, reqAttrSet) || (!fidelity && mpa != null)) { + float [] printableArea = mpa.getPrintableArea(MediaPrintableArea.INCH); + for (int i=0; i < printableArea.length; i++) { + printableArea[i] = printableArea[i]*72.0f; + } + paper.setImageableArea(printableArea[0], printableArea[1], printableArea[2], printableArea[3]); + } + + pf.setPaper(paper); + pf = validatePage(pf); + return new OpenBook(pf, printable); + } + return pageable; + } + + // copied from RasterPrintJob to since we don't implement SunPrinterJobService + /** + * The passed in PageFormat is cloned and altered to be usable on + * the PrinterJob's current printer. + */ + private PageFormat validatePage(PageFormat page) { + PageFormat newPage = (PageFormat)page.clone(); + Paper newPaper = new Paper(); + validatePaper(newPage.getPaper(), newPaper); + newPage.setPaper(newPaper); + + return newPage; + } + + // copied from RasterPrintJob to since we don't implement SunPrinterJobService + /** + * updates a Paper object to reflect the current printer's selected + * paper size and imageable area for that paper size. + * Default implementation copies settings from the original, applies + * applies some validity checks, changes them only if they are + * clearly unreasonable, then sets them into the new Paper. + * Subclasses are expected to override this method to make more + * informed decisons. + */ + protected void validatePaper(Paper origPaper, Paper newPaper) { + if (origPaper == null || newPaper == null) { + return; + } else { + double wid = origPaper.getWidth(); + double hgt = origPaper.getHeight(); + double ix = origPaper.getImageableX(); + double iy = origPaper.getImageableY(); + double iw = origPaper.getImageableWidth(); + double ih = origPaper.getImageableHeight(); + + /* Assume any +ve values are legal. Overall paper dimensions + * take precedence. Make sure imageable area fits on the paper. + */ + Paper defaultPaper = new Paper(); + wid = ((wid > 0.0) ? wid : defaultPaper.getWidth()); + hgt = ((hgt > 0.0) ? hgt : defaultPaper.getHeight()); + ix = ((ix > 0.0) ? ix : defaultPaper.getImageableX()); + iy = ((iy > 0.0) ? iy : defaultPaper.getImageableY()); + iw = ((iw > 0.0) ? iw : defaultPaper.getImageableWidth()); + ih = ((ih > 0.0) ? ih : defaultPaper.getImageableHeight()); + /* full width/height is not likely to be imageable, but since we + * don't know the limits we have to allow it + */ + if (iw > wid) { + iw = wid; + } + if (ih > hgt) { + ih = hgt; + } + if ((ix + iw) > wid) { + ix = wid - iw; + } + if ((iy + ih) > hgt) { + iy = hgt - ih; + } + newPaper.setSize(wid, hgt); + newPaper.setImageableArea(ix, iy, iw, ih); + } + } + + // copied from RasterPrintJob + /** + * Checks whether a certain attribute value is valid for the current print service + * @param attrval the attribute value + * @param attrset Set of printing attributes for a supposed job (both job-level attributes and document-level attributes), or null. + * @return true if valid + */ + protected boolean isSupportedValue(Attribute attrval, PrintRequestAttributeSet attrset) { + return (attrval != null && service != null && service.isAttributeValueSupported(attrval, DocFlavor.SERVICE_FORMATTED.PAGEABLE, attrset)); + } + + + /* + * There's some inefficiency here as the job set is created even though it may never be requested. + */ + private synchronized void initializeAttributeSets(Doc doc, PrintRequestAttributeSet reqSet){ + + reqAttrSet = new HashPrintRequestAttributeSet(); + jobAttrSet = new HashPrintJobAttributeSet(); + + Attribute[] attrs; + if(reqSet != null){ + reqAttrSet.addAll(reqSet); + attrs = reqSet.toArray(); + for(int i = 0; i < attrs.length; i++){ + if(attrs[i] instanceof PrintJobAttribute){ + jobAttrSet.add(attrs[i]); + } + } + } + + DocAttributeSet docSet = doc.getAttributes(); + if(docSet != null){ + attrs = docSet.toArray(); + for(int i = 0; i < attrs.length; i++){ + if(attrs[i] instanceof PrintRequestAttribute){ + reqAttrSet.add(attrs[i]); + } + if(attrs[i] instanceof PrintJobAttribute){ + jobAttrSet.add(attrs[i]); + } + } + } + + /* add the user name to the job */ + String userName = ""; + try{ + userName = System.getProperty("user.name"); + }catch(SecurityException se){ + } + + if(userName == null || userName.equals("")){ + RequestingUserName ruName = (RequestingUserName)reqSet.get(RequestingUserName.class); + if(ruName != null){ + jobAttrSet.add(new JobOriginatingUserName(ruName.getValue(), ruName.getLocale())); + }else{ + jobAttrSet.add(new JobOriginatingUserName("", null)); + } + }else{ + jobAttrSet.add(new JobOriginatingUserName(userName, null)); + } + + /* + * if no job name supplied use doc name (if supplied), if none and its a URL use that, else finally anything .. + */ + if(jobAttrSet.get(JobName.class) == null){ + JobName jobName; + if(docSet != null && docSet.get(DocumentName.class) != null){ + DocumentName docName = (DocumentName)docSet.get(DocumentName.class); + jobName = new JobName(docName.getValue(), docName.getLocale()); + jobAttrSet.add(jobName); + }else{ + String str = "JPS Job:" + doc; + try{ + Object printData = doc.getPrintData(); + if(printData instanceof URL){ + str = ((URL)(doc.getPrintData())).toString(); + } + }catch(IOException e){ + } + jobName = new JobName(str, null); + jobAttrSet.add(jobName); + } + } + + jobAttrSet = AttributeSetUtilities.unmodifiableView(jobAttrSet); + } + + private void getAttributeValues(DocFlavor flavor) throws PrintException { + + if (reqAttrSet.get(Fidelity.class) == Fidelity.FIDELITY_TRUE) { + fidelity = true; + } else { + fidelity = false; + } + + Attribute chroma = reqAttrSet.get( Chromaticity.class ); + // TODO check whether supported by the print service + printColor = chroma == Chromaticity.COLOR; + + Attribute newTray = reqAttrSet.get( Media.class ); + if( newTray instanceof MediaTray ){ + mediaTray = (MediaTray)newTray; + } + // TODO check whether supported by the print service + + Class category; + Attribute [] attrs = reqAttrSet.toArray(); + for (int i=0; i= 0 ){ + printable = pageable.getPrintable(realPage); + pageFormat = pageable.getPageFormat(realPage); + int pageResult = printable.print(peekGraphics, pageFormat, realPage); + ev.set_HasMorePages( pageResult == Printable.PAGE_EXISTS ); + } else { + ev.set_HasMorePages( false ); + } + }catch(PrinterException ex){ + printerException = ex; + ex.printStackTrace(); + ev.set_HasMorePages(false); + } + + } + + } + + private class QueryPage implements QueryPageSettingsEventHandler.Method{ + + private final Pageable pageable; + private int pageIndex; + private final boolean printColor; + private final MediaTray tray; + + + QueryPage(Pageable pageable, boolean printColor, MediaTray tray ){ + this.printColor = printColor; + this.pageable = pageable; + this.tray = tray; + } + + @Override + public void Invoke(Object source, QueryPageSettingsEventArgs e) { + int realPage = pageRanges.getPageForIndex(pageIndex); + // apply page settings to the current page + PageFormat format = pageable.getPageFormat(realPage); + PageSettings pageSettings = e.get_PageSettings(); + pageSettings.set_Color( printColor ); + PaperSource paperSource = service.getPaperSourceForTray( tray ); + if( paperSource != null ){ + pageSettings.set_PaperSource( paperSource ); + } + + PaperSize ps = new PaperSize(); + ps.set_Height( java2netLength( format.getHeight() ) ); + ps.set_Width( java2netLength( format.getWidth() ) ); + pageSettings.set_PaperSize( ps ); + + Margins margins = new Margins(); + margins.set_Left( java2netLength( format.getImageableX() ) ); + margins.set_Top( java2netLength( format.getImageableY() ) ); + margins.set_Right( java2netLength(format.getWidth() - format.getImageableX() - format.getImageableWidth() ) ); + margins.set_Bottom( java2netLength(format.getHeight() - format.getImageableY() - format.getImageableHeight() ) ); + pageSettings.set_Margins( margins ); + pageIndex++; + } + } + + /** + * Determines which logical page to print for a certain physical page + */ + public static class PageNumberConverter{ + + private List ranges; + private int totalPages = -1; + private final int copies; + + public PageNumberConverter( PageRanges pages, int copies, boolean collated ) { + // NOTE: uncollated is handled by the printer driver! If we would handle that here, + // we would get copies^2 copies! + this.copies = collated ? copies : 1; + if( pages != null && pages.getMembers() != null && pages.getMembers().length > 0 ){ + TreeSet rangesSort = new TreeSet(); + OUTER: + for( int[] range : pages.getMembers() ){ + Range r = new Range( range[0], range[1] + 1 ); // +1 to inlucde the uppre end + for( Range recent : rangesSort ){ + if( recent.canMerge(r) ){ + recent.merge(r); + continue OUTER; + } + } + rangesSort.add( r ); + } + // finally merge + Range recent = null; + ranges = new ArrayList(); + for( Range r : rangesSort ){ + if( recent != null && recent.canMerge( r ) ){ + recent.merge( r ); + } else { + ranges.add( r ); + recent = r; + } + } + // calculate total pages, required for collated copies + totalPages = 0; + for( Range r : rangesSort ){ + int diff = r.end - r.start; + totalPages += diff; + } + } + } + + /** + * Must be called in case the printable returns no-more-pages. Will return whether the print job + * will continue due to pending copies + * @param index the current page index + * @return if false, the print job will continue with copies, if true terminate the job + */ + public boolean checkJobComplete( int index ){ + if( ranges != null ){ + return true; + } + if( totalPages < 0 ){ + // this is the first time, this was called for 'all-pages' so it's the total number + totalPages = index; + } + return index > copies * totalPages; + } + + /** + * Returns which page to be printed for a certain page index + * @param index the inex to be printed + * @return the page number or -1, if there is no page for this index + */ + public int getPageForIndex( int index ){ + if( index < 0 || ( totalPages >=0 && index >= copies * totalPages ) ){ + return -1; + } + if( ranges == null ){ + return totalPages >=0 ? index % totalPages : index; + } + int counter = 0; + if( copies > 1 ){ + counter += (index / totalPages) * totalPages; + } + for( Range r : ranges ){ + int upper = counter + (r.end - r.start); + if( index < upper ){ + // so we're in the correct range + return r.start + ( index - counter ) - 1; + } else { + counter = upper; + } + } + return -1; + } + + /** + * A singular page range + */ + private static class Range implements Comparable { + + public int start; + public int end; + + public Range(int start, int end) { + this.start = start; + this.end = end; + } + + /** + * Checks whether the ranges intersect of have no gap in between + * @param otherRange the range to be checked + * @return true, if the ranges can be merged + */ + public boolean canMerge( Range otherRange ){ + if( otherRange.end >= start && otherRange.end <= end ){ + return true; + } + if( otherRange.start >= start && otherRange.start <= end ){ + return true; + } + return false; + } + + /** + * Merges the other range into this range. Ignores the gap between the ranges if there is any + * @param otherRange the range to be merged + */ + public void merge( Range otherRange ){ + start = Math.min(start, otherRange.start); + end = Math.max(end, otherRange.end); + } + + public int compareTo(Range o) { + return start - o.start; + } + } + } +} diff --git a/openjdk/sun/print/Win32PrintService.java b/openjdk/sun/print/Win32PrintService.java new file mode 100644 index 0000000..134c7a9 --- /dev/null +++ b/openjdk/sun/print/Win32PrintService.java @@ -0,0 +1,920 @@ +/* + * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (C) 2009, 2012 Volker Berlin (i-net software) + * Copyright (C) 2010, 2011 Karsten Heinrich (i-net software) + * 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.print; + +import java.io.File; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.List; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.print.DocFlavor; +import javax.print.DocPrintJob; +import javax.print.PrintService; +import javax.print.ServiceUIFactory; +import javax.print.attribute.Attribute; +import javax.print.attribute.AttributeSet; +import javax.print.attribute.AttributeSetUtilities; +import javax.print.attribute.HashPrintServiceAttributeSet; +import javax.print.attribute.PrintServiceAttribute; +import javax.print.attribute.PrintServiceAttributeSet; +import javax.print.attribute.standard.Chromaticity; +import javax.print.attribute.standard.ColorSupported; +import javax.print.attribute.standard.Copies; +import javax.print.attribute.standard.CopiesSupported; +import javax.print.attribute.standard.Destination; +import javax.print.attribute.standard.Fidelity; +import javax.print.attribute.standard.JobName; +import javax.print.attribute.standard.Media; +import javax.print.attribute.standard.MediaPrintableArea; +import javax.print.attribute.standard.MediaSize; +import javax.print.attribute.standard.MediaSizeName; +import javax.print.attribute.standard.MediaTray; +import javax.print.attribute.standard.OrientationRequested; +import javax.print.attribute.standard.PageRanges; +import javax.print.attribute.standard.PrintQuality; +import javax.print.attribute.standard.PrinterIsAcceptingJobs; +import javax.print.attribute.standard.PrinterName; +import javax.print.attribute.standard.PrinterResolution; +import javax.print.attribute.standard.PrinterState; +import javax.print.attribute.standard.PrinterStateReasons; +import javax.print.attribute.standard.QueuedJobCount; +import javax.print.attribute.standard.RequestingUserName; +import javax.print.attribute.standard.SheetCollate; +import javax.print.attribute.standard.Sides; +import javax.print.event.PrintServiceAttributeListener; + +import cli.System.NewsStyleUriParser; +import cli.System.Type; +import cli.System.Collections.IEnumerator; +import cli.System.Drawing.RectangleF; +import cli.System.Drawing.Printing.Duplex; +import cli.System.Drawing.Printing.PaperKind; +import cli.System.Drawing.Printing.PaperSize; +import cli.System.Drawing.Printing.PaperSource; +import cli.System.Drawing.Printing.PrintDocument; +import cli.System.Drawing.Printing.PrinterSettings; +import cli.System.Drawing.Printing.PrinterSettings.PaperSizeCollection; +import cli.System.Drawing.Printing.PrinterSettings.PaperSourceCollection; +import cli.System.Drawing.Printing.PrinterSettings.PrinterResolutionCollection; +import cli.System.Net.Mime.MediaTypeNames; + +/** + * @author Volker Berlin + */ +public class Win32PrintService implements PrintService { + // note: the Win32PrintService is implemented as foreign service (doesn't implement SunPrinterJobService) + // to avoid implementing the WPrinterJob + + private static final DocFlavor[] supportedFlavors = { + DocFlavor.SERVICE_FORMATTED.PAGEABLE, + DocFlavor.SERVICE_FORMATTED.PRINTABLE, + }; + + /** Mapping for PageSize.RawKind to predefined MediaSizeName */ + private static final MediaSizeName[] MEDIA_NAMES = new MediaSizeName[70]; + + private static final Hashtable CUSTOM_MEDIA_NAME = new Hashtable<>(); + + /* it turns out to be inconvenient to store the other categories + * separately because many attributes are in multiple categories. + */ + private static Class[] otherAttrCats = { + JobName.class, + RequestingUserName.class, + Copies.class, + Destination.class, + OrientationRequested.class, + PageRanges.class, + Media.class, + MediaPrintableArea.class, + Fidelity.class, + // We support collation on 2D printer jobs, even if the driver can't. + SheetCollate.class, + SunAlternateMedia.class, + Chromaticity.class + }; + + // conversion from 1/100 Inch (.NET) to um (Java) + private static final int INCH100_TO_MYM = 254; + private static final int MATCH_DIFF = 500; // 0.5 mm + + static { + MEDIA_NAMES[0] = MediaSizeName.NA_LETTER; + MEDIA_NAMES[1] = MediaSizeName.NA_LETTER ; + MEDIA_NAMES[2] = MediaSizeName.TABLOID ; + MEDIA_NAMES[3] = MediaSizeName.LEDGER ; + MEDIA_NAMES[4] = MediaSizeName.NA_LEGAL ; + MEDIA_NAMES[5] = MediaSizeName.INVOICE ; // Statement + MEDIA_NAMES[6] = MediaSizeName.EXECUTIVE ; + MEDIA_NAMES[7] = MediaSizeName.ISO_A3 ; + MEDIA_NAMES[8] = MediaSizeName.ISO_A4 ; + MEDIA_NAMES[9] = MediaSizeName.ISO_A4 ; // A4Small, 10 + MEDIA_NAMES[10] = MediaSizeName.ISO_A5 ; + MEDIA_NAMES[11] = MediaSizeName.JIS_B4 ; + MEDIA_NAMES[12] = MediaSizeName.JIS_B5 ; + MEDIA_NAMES[13] = MediaSizeName.FOLIO ; + MEDIA_NAMES[14] = MediaSizeName.QUARTO ; + MEDIA_NAMES[15] = MediaSizeName.NA_10X14_ENVELOPE ; + MEDIA_NAMES[16] = MediaSizeName.B ; // 10x17 Envelope + MEDIA_NAMES[17] = MediaSizeName.NA_LETTER ; // Note + MEDIA_NAMES[18] = MediaSizeName.NA_NUMBER_9_ENVELOPE ; + MEDIA_NAMES[19] = MediaSizeName.NA_NUMBER_10_ENVELOPE ; // 20 + MEDIA_NAMES[20] = MediaSizeName.NA_NUMBER_11_ENVELOPE ; + MEDIA_NAMES[21] = MediaSizeName.NA_NUMBER_12_ENVELOPE ; + MEDIA_NAMES[22] = MediaSizeName.NA_NUMBER_14_ENVELOPE ; + MEDIA_NAMES[23] = MediaSizeName.C ; + MEDIA_NAMES[24] = MediaSizeName.D ; + MEDIA_NAMES[25] = MediaSizeName.E ; + MEDIA_NAMES[26] = MediaSizeName.ISO_DESIGNATED_LONG ; + MEDIA_NAMES[27] = MediaSizeName.ISO_C5 ; + MEDIA_NAMES[28] = MediaSizeName.ISO_C3 ; + MEDIA_NAMES[29] = MediaSizeName.ISO_C4 ; // 30 + MEDIA_NAMES[30] = MediaSizeName.ISO_C6 ; + MEDIA_NAMES[31] = MediaSizeName.ITALY_ENVELOPE ; + MEDIA_NAMES[32] = MediaSizeName.ISO_B4 ; + MEDIA_NAMES[33] = MediaSizeName.ISO_B5 ; + MEDIA_NAMES[34] = MediaSizeName.ISO_B6 ; + MEDIA_NAMES[35] = MediaSizeName.ITALY_ENVELOPE ; + MEDIA_NAMES[36] = MediaSizeName.MONARCH_ENVELOPE ; + MEDIA_NAMES[37] = MediaSizeName.PERSONAL_ENVELOPE ; + MEDIA_NAMES[38] = MediaSizeName.NA_10X15_ENVELOPE ; // USStandardFanfold + MEDIA_NAMES[39] = MediaSizeName.NA_9X12_ENVELOPE ; // GermanStandardFanfold, 40 + MEDIA_NAMES[40] = MediaSizeName.FOLIO ; // GermanLegalFanfold + MEDIA_NAMES[41] = MediaSizeName.ISO_B4 ; + MEDIA_NAMES[42] = MediaSizeName.JAPANESE_POSTCARD ; + MEDIA_NAMES[43] = MediaSizeName.NA_9X11_ENVELOPE ; + + MEDIA_NAMES[65] = MediaSizeName.ISO_A2 ; + + MEDIA_NAMES[69] = MediaSizeName.ISO_A6 ; + +// // augment the media size with the .NET default sizes available on the printer +// PrinterSettings ps = new PrinterSettings(); +// IEnumerator printers = PrinterSettings.get_InstalledPrinters().GetEnumerator(); +// printers.Reset(); +// while( printers.MoveNext() ){ +// ps.set_PrinterName( (String) printers.get_Current() ); +// IEnumerator sizes = ps.get_PaperSizes().GetEnumerator(); +// sizes.Reset(); +// while( sizes.MoveNext() ){ +// PaperSize size = (PaperSize) sizes.get_Current(); +// int kind = size.get_RawKind(); +// if( kind >= 0 && kind < MEDIA_NAMES.length && MEDIA_NAMES[kind] == null ){ +// MEDIA_NAMES[kind] = new CustomMediaSizeName( size.get_PaperName() ); +// int x = size.get_Width(); +// int y = size.get_Height(); +// if( x > y ){ // not allowed by MediaSize +// int tmp = x; +// x = y; +// y = tmp; +// } +// new MediaSize(x, y, INCH100_TO_MYM, MEDIA_NAMES[kind]); // cache entry in map +// } +// } +// } + } + + private final PrintPeer peer; + + private final String printer; + private final PrinterSettings settings; + private PrinterName name; + + private MediaTray[] mediaTrays; + + transient private ServiceNotifier notifier = null; + + public Win32PrintService(String name, PrintPeer peer){ + if(name == null){ + throw new IllegalArgumentException("null printer name"); + } + this.peer = peer; + printer = name; + settings = new PrintDocument().get_PrinterSettings(); + settings.set_PrinterName(printer); + } + + + @Override + public String getName(){ + return printer; + } + + + private PrinterName getPrinterName(){ + if(name == null){ + name = new PrinterName(printer, null); + } + return name; + } + + + public void wakeNotifier() { + synchronized (this) { + if (notifier != null) { + notifier.wake(); + } + } + } + + + @Override + public void addPrintServiceAttributeListener(PrintServiceAttributeListener listener){ + synchronized (this) { + if (listener == null) { + return; + } + if (notifier == null) { + notifier = new ServiceNotifier(this); + } + notifier.addListener(listener); + } + } + + + @Override + public void removePrintServiceAttributeListener(PrintServiceAttributeListener listener){ + synchronized (this) { + if (listener == null || notifier == null ) { + return; + } + notifier.removeListener(listener); + if (notifier.isEmpty()) { + notifier.stopNotifier(); + notifier = null; + } + } + } + + + @Override + public DocPrintJob createPrintJob(){ + SecurityManager security = System.getSecurityManager(); + if(security != null){ + security.checkPrintJobAccess(); + } + return new Win32PrintJob(this, peer); + } + + + @Override + public T getAttribute(Class category){ + if(category == null){ + throw new NullPointerException("category"); + } + if(!(PrintServiceAttribute.class.isAssignableFrom(category))){ + throw new IllegalArgumentException("The categhory '" + category + "' is not a valid PrintServiceAttribute"); + } + if(category == ColorSupported.class){ + // works better than settings.get_SupportsColor(); + if(settings.get_DefaultPageSettings().get_Color()){ + return (T)ColorSupported.SUPPORTED; + }else{ + return (T)ColorSupported.NOT_SUPPORTED; + } + }else if(category == PrinterName.class){ + return (T)getPrinterName(); + } else { + // QueuedJobCount and PrinterIsAcceptingJobs + return (T)peer.getPrinterStatus(printer, category); + } + } + + + @Override + public PrintServiceAttributeSet getAttributes(){ + PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet(); + attrs.add(getPrinterName()); + PrinterIsAcceptingJobs acptJobs = getAttribute(PrinterIsAcceptingJobs.class); + if(acptJobs != null){ + attrs.add(acptJobs); + } + PrinterState prnState = getAttribute(PrinterState.class); + if(prnState != null){ + attrs.add(prnState); + } + PrinterStateReasons prnStateReasons = getAttribute(PrinterStateReasons.class); + if(prnStateReasons != null){ + attrs.add(prnStateReasons); + } + QueuedJobCount jobCount = getAttribute(QueuedJobCount.class); + if(jobCount != null){ + attrs.add(jobCount); + } + // TODO: Seems to be more accurate than settings.get_SupportsColor(), which doesn't work for CutePDF + if(settings.get_DefaultPageSettings().get_Color()){ + attrs.add(ColorSupported.SUPPORTED); + }else{ + attrs.add(ColorSupported.NOT_SUPPORTED); + } + + return AttributeSetUtilities.unmodifiableView(attrs); + } + + + @Override + public Object getDefaultAttributeValue(Class category){ + if (category == null) { + throw new NullPointerException("category must not be null"); + } + if ( !Attribute.class.isAssignableFrom( category ) ) { + throw new IllegalArgumentException( category +" has to be an " + Attribute.class.getName() ); + } + if ( !isAttributeCategorySupported( category ) ) { + return null; + } + if (category == Copies.class) { + short copies = settings.get_Copies(); + return new Copies( copies > 0 ? copies : 1 ); + } else if (category == Chromaticity.class) { + // NOTE: this works for CutePDF, settings.get_SupportsColor() does not + return settings.get_DefaultPageSettings().get_Color() ? Chromaticity.COLOR : Chromaticity.MONOCHROME; + } else if (category == JobName.class) { + return new JobName( "Java Printing", null ); // TODO this is Java-Default, use another one for IKVM? + } else if (category == OrientationRequested.class) { + return settings.get_DefaultPageSettings().get_Landscape() ? OrientationRequested.LANDSCAPE : OrientationRequested.PORTRAIT; + } else if (category == PageRanges.class) { + return new PageRanges(1, Integer.MAX_VALUE ); + } else if (category == Media.class) { + int rawKind = settings.get_DefaultPageSettings().get_PaperSize().get_RawKind(); + if( rawKind > MEDIA_NAMES.length || rawKind < 1 || MEDIA_NAMES[ rawKind - 1 ] == null ){ // custom page format + return findMatchingMedia( settings.get_DefaultPageSettings().get_PaperSize() ); + } else { + return MEDIA_NAMES[ rawKind - 1 ]; + } + } else if (category == MediaPrintableArea.class) { + RectangleF area = settings.get_DefaultPageSettings().get_PrintableArea(); + // get_PrintableArea is in 1/100 inch, see http://msdn.microsoft.com/de-de/library/system.drawing.printing.pagesettings.printablearea(v=VS.90).aspx + return new MediaPrintableArea(area.get_X()/100, area.get_Y()/100, area.get_Width()/100, area.get_Height()/100, MediaPrintableArea.INCH); + } else if (category == Destination.class) { + String path = "out.prn"; + try { + return new Destination( ( new File( path ) ).toURI() ); + } catch (SecurityException se) { + try { + return new Destination( new URI( "file:" + path) ); + } catch (URISyntaxException e) { + return null; + } + } + } else if (category == Sides.class) { + switch( settings.get_Duplex().Value ){ + case cli.System.Drawing.Printing.Duplex.Default: // MSDN: 'The printer's default duplex setting.' - what ever that might be + case cli.System.Drawing.Printing.Duplex.Simplex: + return Sides.ONE_SIDED; + case cli.System.Drawing.Printing.Duplex.Horizontal: + return Sides.TWO_SIDED_LONG_EDGE; + case cli.System.Drawing.Printing.Duplex.Vertical: + return Sides.TWO_SIDED_SHORT_EDGE; + } + } else if (category == PrinterResolution.class) { + cli.System.Drawing.Printing.PrinterResolution pRes = settings.get_DefaultPageSettings().get_PrinterResolution(); + int xRes = pRes.get_X(); + int yRes = pRes.get_Y(); + if ((xRes <= 0) || (yRes <= 0)) { + int res = (yRes > xRes) ? yRes : xRes; + if (res > 0) { + return new PrinterResolution(res, res, PrinterResolution.DPI); + } + } + else { + return new PrinterResolution(xRes, yRes, PrinterResolution.DPI); + } + } else if (category == ColorSupported.class) { + if ( settings.get_SupportsColor() ) { + return ColorSupported.SUPPORTED; + } else { + return ColorSupported.NOT_SUPPORTED; + } + } else if( category == PrintQuality.class ){ + cli.System.Drawing.Printing.PrinterResolutionKind kind = settings.get_DefaultPageSettings().get_PrinterResolution().get_Kind(); + switch (kind.Value) { + case cli.System.Drawing.Printing.PrinterResolutionKind.High: + return PrintQuality.HIGH; + case cli.System.Drawing.Printing.PrinterResolutionKind.Medium: + case cli.System.Drawing.Printing.PrinterResolutionKind.Low: + return PrintQuality.NORMAL; + case cli.System.Drawing.Printing.PrinterResolutionKind.Draft: + return PrintQuality.DRAFT; + } + } else if (category == RequestingUserName.class) { + try{ + return new RequestingUserName( System.getProperty("user.name", ""), null); + } catch( SecurityException e ){ + return new RequestingUserName( "", null); + } + } else if (category == SheetCollate.class){ + return settings.get_Collate() ? SheetCollate.COLLATED : SheetCollate.UNCOLLATED; + } else if (category == Fidelity.class) { + return Fidelity.FIDELITY_FALSE; + } + return null; + } + + + @Override + public ServiceUIFactory getServiceUIFactory(){ + return null; + } + + + @Override + public Class[] getSupportedAttributeCategories(){ + ArrayList categList = new ArrayList(otherAttrCats.length+3); + for (int i=0; i < otherAttrCats.length; i++) { + categList.add(otherAttrCats[i]); + } + + if (settings.get_CanDuplex()) { + categList.add(Sides.class); + } + + if (settings.get_PrinterResolutions().get_Count() > 0) { + categList.add(PrinterResolution.class); + } + + return categList.toArray(new Class[categList.size()]); + } + + + @Override + public Object getSupportedAttributeValues(Class category, DocFlavor flavor, AttributeSet attributes){ + if ( category == null || !Attribute.class.isAssignableFrom( category ) ) { + throw new IllegalArgumentException( "The category '" + category + "' is not an Attribute" ); + } + if( !isAttributeCategorySupported(category) ){ + return null; + } + if (category == JobName.class || category == RequestingUserName.class || category == ColorSupported.class + || category == Destination.class ) { + return getDefaultAttributeValue(category); + } + if( category == Copies.class ){ + return new CopiesSupported(1, settings.get_MaximumCopies() ); + } + if( category == Media.class ){ + PaperSizeCollection sizes = settings.get_PaperSizes(); + List medias = new ArrayList(); + for( int i = 0; i < sizes.get_Count(); i++ ){ + PaperSize media = sizes.get_Item(i); + MediaSizeName mediaName = findMatchingMedia( sizes.get_Item(i) ); + if( mediaName != null + && !medias.contains( mediaName )){ // slow but better than creating a HashSet here + medias.add( mediaName); + } + } + // add media trays + MediaTray[] trays = getMediaTrays(); + for( MediaTray tray : trays ){ + medias.add( tray ); + } + return medias.size() > 0 ? medias.toArray( new Media[medias.size() ] ) : null; + } + if (category == PageRanges.class) { + if (flavor == null|| flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) + || flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) { + PageRanges[] arr = new PageRanges[1]; + arr[0] = new PageRanges(1, Integer.MAX_VALUE); + return arr; + } else { + return null; + } + } + if (category == Fidelity.class) { + return new Fidelity[]{ Fidelity.FIDELITY_FALSE, Fidelity.FIDELITY_TRUE}; + } + if (category == PrintQuality.class) { + return new PrintQuality[]{ PrintQuality.DRAFT, PrintQuality.HIGH, PrintQuality.NORMAL }; + } + + boolean printPageAble = flavor == null|| flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) + || flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE); + if (category == Sides.class) { + if ( printPageAble ) { + return new Sides[]{ Sides.ONE_SIDED, Sides.TWO_SIDED_LONG_EDGE, Sides.TWO_SIDED_SHORT_EDGE}; + } else { + return null; + } + } + if (category == SheetCollate.class) { + if ( printPageAble ) { + return new SheetCollate[]{ SheetCollate.COLLATED, SheetCollate.UNCOLLATED} ; + } else { + return null; + } + } + boolean imageBased = printPageAble || flavor.equals(DocFlavor.INPUT_STREAM.GIF) + || flavor.equals(DocFlavor.INPUT_STREAM.JPEG) + || flavor.equals(DocFlavor.INPUT_STREAM.PNG) + || flavor.equals(DocFlavor.BYTE_ARRAY.GIF) + || flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) + || flavor.equals(DocFlavor.BYTE_ARRAY.PNG) + || flavor.equals(DocFlavor.URL.GIF) + || flavor.equals(DocFlavor.URL.JPEG) + || flavor.equals(DocFlavor.URL.PNG); + if (category == OrientationRequested.class) { + if( imageBased ){ + return new OrientationRequested[]{ OrientationRequested.PORTRAIT, OrientationRequested.LANDSCAPE, OrientationRequested.REVERSE_LANDSCAPE }; + } else { + return null; + } + } + if (category == Chromaticity.class) { + if( imageBased ){ + if( settings.get_DefaultPageSettings().get_Color() ){ + return new Chromaticity[]{ Chromaticity.MONOCHROME, Chromaticity.COLOR }; + } else { + return new Chromaticity[]{ Chromaticity.MONOCHROME }; + } + } else { + return null; + } + } + return null; + } + + private MediaTray[] getMediaTrays(){ + if( mediaTrays != null ){ + // the print service is a singleton per printer so we only do this once + return mediaTrays; + } + PaperSourceCollection trays = settings.get_PaperSources(); + int count = trays.get_Count(); + List trayList = new ArrayList(); + for( int i=0; i < count; i++ ){ + PaperSource tray = trays.get_Item(i); + MediaTray javaTray = getDefaultTray(tray); + if( javaTray != null ){ + trayList.add( javaTray ); + } else { + trayList.add( new NetMediaTray( tray ) ); + } + } + mediaTrays = trayList.toArray( new MediaTray[trayList.size()]); + return mediaTrays; + } + + + @Override + public DocFlavor[] getSupportedDocFlavors(){ + int len = supportedFlavors.length; + DocFlavor[] result = new DocFlavor[len]; + System.arraycopy(supportedFlavors, 0, result, 0, len); + return result; + } + + + @Override + public AttributeSet getUnsupportedAttributes(DocFlavor flavor, AttributeSet attributes){ + // TODO Auto-generated method stub + return null; + } + + + @Override + public boolean isAttributeCategorySupported(Class category){ + if ( category == null || !Attribute.class.isAssignableFrom( category ) ) { + throw new IllegalArgumentException( "The category '" + category + "' is not an Attribute" ); + } + Class[] supported = getSupportedAttributeCategories(); + for( int i=0; i < supported.length; i++ ){ + if( category == supported[i] ){ + return true; + } + } + return false; + } + + + private boolean isPostScriptFlavor(DocFlavor flavor) { + if (flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT) || + flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) || + flavor.equals(DocFlavor.URL.POSTSCRIPT)) { + return true; + } + else { + return false; + } + } + + private boolean isPSDocAttr(Class category) { + if (category == OrientationRequested.class || category == Copies.class) { + return true; + } + else { + return false; + } + } + + private boolean isAutoSense(DocFlavor flavor) { + if (flavor.equals(DocFlavor.BYTE_ARRAY.AUTOSENSE) || + flavor.equals(DocFlavor.INPUT_STREAM.AUTOSENSE) || + flavor.equals(DocFlavor.URL.AUTOSENSE)) { + return true; + } + else { + return false; + } + } + + @Override + public boolean isAttributeValueSupported(Attribute attr, DocFlavor flavor, AttributeSet attributes){ + if (attr == null) { + throw new NullPointerException("null attribute"); + } + Class category = attr.getCategory(); + if (flavor != null) { + if (!isDocFlavorSupported(flavor)) { + throw new IllegalArgumentException(flavor + + " is an unsupported flavor"); + // if postscript & category is already specified within the PostScript data + // we return false + } else if (isAutoSense(flavor) || (isPostScriptFlavor(flavor) && + (isPSDocAttr(category)))) { + return false; + } + } + + if (!isAttributeCategorySupported(category)) { + return false; + } + else if (category == Chromaticity.class) { + if ((flavor == null) || + flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || + flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) || + flavor.equals(DocFlavor.BYTE_ARRAY.GIF) || + flavor.equals(DocFlavor.INPUT_STREAM.GIF) || + flavor.equals(DocFlavor.URL.GIF) || + flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) || + flavor.equals(DocFlavor.INPUT_STREAM.JPEG) || + flavor.equals(DocFlavor.URL.JPEG) || + flavor.equals(DocFlavor.BYTE_ARRAY.PNG) || + flavor.equals(DocFlavor.INPUT_STREAM.PNG) || + flavor.equals(DocFlavor.URL.PNG)) { + if (settings.get_DefaultPageSettings().get_Color()) { + return true; + } else { + return attr == Chromaticity.MONOCHROME; + } + } else { + return false; + } + } else if (category == Copies.class) { + return ((Copies)attr).getValue() >= 1 && ((Copies)attr).getValue() <= settings.get_MaximumCopies(); + + } else if (category == Destination.class) { + URI uri = ((Destination)attr).getURI(); + if ("file".equals(uri.getScheme()) && + !(uri.getSchemeSpecificPart().equals(""))) { + return true; + } else { + return false; + } + + } else if (category == Media.class) { + Media[] medias = (Media[])getSupportedAttributeValues( Media.class, flavor, attributes ); + if( medias != null ) { + return Arrays.asList( medias ).contains( attr ); + } + + } else if (category == MediaPrintableArea.class) { + //TODO + return true; + + } else if (category == SunAlternateMedia.class) { + Media media = ((SunAlternateMedia)attr).getMedia(); + return isAttributeValueSupported(media, flavor, attributes); + + } else if (category == PageRanges.class || + category == SheetCollate.class || + category == Sides.class) { + if (flavor != null && + !(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || + flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) { + return false; + } + } else if (category == PrinterResolution.class) { + if (attr instanceof PrinterResolution) { + int[] jRes = ((PrinterResolution)attr).getResolution( PrinterResolution.DPI ); + PrinterResolutionCollection resolutions = settings.get_PrinterResolutions(); + for( int i=0; i< resolutions.get_Count(); i++ ) { + cli.System.Drawing.Printing.PrinterResolution nRes = resolutions.get_Item( i ); + if( nRes.get_X() == jRes[0] && nRes.get_Y() == jRes[1] ) { + return true; + } + } + return false; + } + } else if (category == OrientationRequested.class) { + if (attr == OrientationRequested.REVERSE_PORTRAIT || + (flavor != null) && + !(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || + flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) || + flavor.equals(DocFlavor.INPUT_STREAM.GIF) || + flavor.equals(DocFlavor.INPUT_STREAM.JPEG) || + flavor.equals(DocFlavor.INPUT_STREAM.PNG) || + flavor.equals(DocFlavor.BYTE_ARRAY.GIF) || + flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) || + flavor.equals(DocFlavor.BYTE_ARRAY.PNG) || + flavor.equals(DocFlavor.URL.GIF) || + flavor.equals(DocFlavor.URL.JPEG) || + flavor.equals(DocFlavor.URL.PNG))) { + return false; + } + + } else if (category == ColorSupported.class) { + boolean isColorSup = settings.get_DefaultPageSettings().get_Color(); + if ((!isColorSup && (attr == ColorSupported.SUPPORTED)) || + (isColorSup && (attr == ColorSupported.NOT_SUPPORTED))) { + return false; + } + } + return true; + } + + + @Override + public boolean isDocFlavorSupported(DocFlavor flavor){ + for (int f=0; f 0 && rawKind <= MEDIA_NAMES.length ){ + // match to predefined size + MediaSizeName media = MEDIA_NAMES[ rawKind - 1 ]; + if( media != null ) { + return media; + } + } + int x = paper.get_Width() * INCH100_TO_MYM; + int y = paper.get_Height() * INCH100_TO_MYM; + if( x > y ){ // MediaSizes are always portrait! + int tmp = x; + x = y; + y = tmp; + } + for( MediaSizeName name : MEDIA_NAMES ){ + MediaSize media = MediaSize.getMediaSizeForName(name); + if( media != null ){ + if( Math.abs( x - media.getX(1) ) < MATCH_DIFF && Math.abs( y - media.getY(1) ) < MATCH_DIFF ){ + return name; + } + } + } + MediaSizeName media = CUSTOM_MEDIA_NAME.get(paper.get_PaperName()); + if (media == null) { + media = new CustomMediaSizeName(paper.get_PaperName()); + CUSTOM_MEDIA_NAME.put(paper.get_PaperName(), media); + new MediaSize( x, y, MediaSize.INCH/100, media); + } + return media; + } + + /** + * Returns the Java-default {@link MediaTray} for a paper source. This is required since these default + * trays are public constants which can be used without checking for the actually present media trays + * @param source the .NET paper source to get the predefined source for + * @return the media tray or null, in case there is no mapping for the paper source + */ + private MediaTray getDefaultTray( PaperSource source ){ + // convert from .NET kind to java's pre defined MediaTrays + switch( source.get_RawKind() ){ + case 1 : return MediaTray.TOP; + case 2 : return MediaTray.BOTTOM; + case 3 : return MediaTray.MIDDLE; + case 4 : return MediaTray.MANUAL; + case 5 : return MediaTray.ENVELOPE; + case 6 : return Win32MediaTray.ENVELOPE_MANUAL; + case 7 : return Win32MediaTray.AUTO; + case 8 : return Win32MediaTray.TRACTOR; + case 9 : return Win32MediaTray.SMALL_FORMAT; + case 10 : return Win32MediaTray.LARGE_FORMAT; + case 11 : return MediaTray.LARGE_CAPACITY; + case 14 : return MediaTray.MAIN; + case 15 : return Win32MediaTray.FORMSOURCE; + // FIXME which PaperSourceKind is MediaTray.SIDE ??? + } + return null; + } + + /** + * Returns the .NET {@link PaperSource} for a media tray. This will be done either by mapping or + * directly in case the tray is a {@link NetMediaTray} + * @param tray the tray to get the paper source for, must not be null + * @return the selected {@link PaperSource} or null, in case there is no matching {@link PaperSource} + */ + public PaperSource getPaperSourceForTray( MediaTray tray ){ + if( tray instanceof NetMediaTray ){ + return ((NetMediaTray)tray).getPaperSource( this ); + } + // try to find the appropriate paper source for the Java-Defined tray + PaperSourceCollection trays = settings.get_PaperSources(); + int count = trays.get_Count(); + for( int i=0; i < count; i++ ){ + PaperSource paperSource = trays.get_Item(i); + if( getDefaultTray( paperSource ) == tray ){ + return paperSource; + } + } + return null; + } + + public static class NetMediaTray extends MediaTray{ + + private static final long serialVersionUID = 1L; + + /** Not really used but required by the EnumSyntax super class */ + private static AtomicInteger idCounter = new AtomicInteger(8); + + private int rawKind; + private String name; + private transient PaperSource netSource; + + public NetMediaTray( PaperSource netSource ) { + super( idCounter.getAndIncrement() ); + this.rawKind = netSource.get_RawKind(); + this.name = netSource.get_SourceName(); + this.netSource = netSource; + } + + public PaperSource getPaperSource( Win32PrintService service ){ + if( netSource == null ){ + PaperSourceCollection sources = service.settings.get_PaperSources(); + int count = sources.get_Count(); + for( int i=0; i < count; i++ ){ + PaperSource source = sources.get_Item(i); + if( source.get_RawKind() == rawKind ){ + netSource = source; + break; + } + } + } + return netSource; + } + + @Override + public String toString() { + return netSource != null ? netSource.get_SourceName() : name; + } + } +} diff --git a/openjdk/sun/print/Win32PrintServiceLookup.java b/openjdk/sun/print/Win32PrintServiceLookup.java new file mode 100644 index 0000000..f230c85 --- /dev/null +++ b/openjdk/sun/print/Win32PrintServiceLookup.java @@ -0,0 +1,264 @@ +/* + Copyright (C) 2009 Volker Berlin (i-net software) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + + */ +package sun.print; + +import ikvm.awt.IkvmToolkit; + +import java.awt.Toolkit; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.IOException; +import java.util.ArrayList; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import javax.print.DocFlavor; +import javax.print.MultiDocPrintService; +import javax.print.PrintService; +import javax.print.PrintServiceLookup; +import javax.print.attribute.Attribute; +import javax.print.attribute.AttributeSet; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.HashPrintServiceAttributeSet; +import javax.print.attribute.PrintRequestAttribute; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.print.attribute.PrintServiceAttribute; +import javax.print.attribute.PrintServiceAttributeSet; +import javax.print.attribute.standard.PrinterName; + +public class Win32PrintServiceLookup extends PrintServiceLookup { + + private final PrintPeer peer = IkvmToolkit.DefaultToolkit.get().getPrintPeer(); + + private String defaultPrinter; + private PrintService defaultPrintService; + private String[] printers; /* excludes the default printer */ + private PrintService[] printServices; /* includes the default printer */ + + + /* Want the PrintService which is default print service to have + * equality of reference with the equivalent in list of print services + * This isn't required by the API and there's a risk doing this will + * lead people to assume its guaranteed. + */ + public synchronized PrintService[] getPrintServices() { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkPrintJobAccess(); + } + if (printServices == null) { + refreshServices(); + } + return printServices; + } + + private synchronized void refreshServices() { + printers = peer.getAllPrinterNames(); + if (printers == null) { + // In Windows it is safe to assume no default if printers == null so we + // don't get the default. + printServices = new PrintService[0]; + return; + } + + PrintService[] newServices = new PrintService[printers.length]; + PrintService defService = getDefaultPrintService(); + for (int p = 0; p < printers.length; p++) { + if (defService != null && + printers[p].equals(defService.getName())) { + newServices[p] = defService; + } else { + if (printServices == null) { + newServices[p] = new Win32PrintService(printers[p], peer); + } else { + int j; + for (j = 0; j < printServices.length; j++) { + if ((printServices[j]!= null) && + (printers[p].equals(printServices[j].getName()))) { + newServices[p] = printServices[j]; + printServices[j] = null; + break; + } + } + if (j == printServices.length) { + newServices[p] = new Win32PrintService(printers[p], peer); + } + } + } + } + + printServices = newServices; + } + + + public synchronized PrintService getPrintServiceByName(String name) { + + if (name == null || name.equals("")) { + return null; + } else { + /* getPrintServices() is now very fast. */ + PrintService[] printServices = getPrintServices(); + for (int i=0; i)attrs[i].getCategory()); + if (serviceAttr == null || !serviceAttr.equals(attrs[i])) { + return false; + } + } + } + return true; + } + + public PrintService[] getPrintServices(DocFlavor flavor, + AttributeSet attributes) { + + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkPrintJobAccess(); + } + PrintRequestAttributeSet requestSet = null; + PrintServiceAttributeSet serviceSet = null; + + if (attributes != null && !attributes.isEmpty()) { + + requestSet = new HashPrintRequestAttributeSet(); + serviceSet = new HashPrintServiceAttributeSet(); + + Attribute[] attrs = attributes.toArray(); + for (int i=0; i,String[]> fieldFilterMap; + private static volatile Map,String[]> methodFilterMap; + + static { + Map,String[]> map = new HashMap,String[]>(); + map.put(Reflection.class, + new String[] {"fieldFilterMap", "methodFilterMap"}); + map.put(System.class, new String[] {"security"}); + map.put(Class.class, new String[] {"classLoader"}); + fieldFilterMap = map; + + methodFilterMap = new HashMap<>(); + // [IKVM] to avoid initialization order issues, we actually add + // Unsafe.getUnsafe() here, instead of in Unsafe's class initializer + methodFilterMap.put(sun.misc.Unsafe.class, new String[] {"getUnsafe"}); + } + + /** Returns the class of the caller of the method calling this method, + ignoring frames associated with java.lang.reflect.Method.invoke() + and its implementation. */ + @CallerSensitive + public static native Class getCallerClass(); + + /** + * @deprecated This method will be removed in JDK 9. + * This method is a private JDK API and retained temporarily for + * existing code to run until a replacement API is defined. + */ + @Deprecated + public static native Class getCallerClass(int depth); + + /** Retrieves the access flags written to the class file. For + inner classes these flags may differ from those returned by + Class.getModifiers(), which searches the InnerClasses + attribute to find the source-level access flags. This is used + instead of Class.getModifiers() for run-time access checks due + to compatibility reasons; see 4471811. Only the values of the + low 13 bits (i.e., a mask of 0x1FFF) are guaranteed to be + valid. */ + public static native int getClassAccessFlags(Class c); + + /** A quick "fast-path" check to try to avoid getCallerClass() + calls. */ + public static boolean quickCheckMemberAccess(Class memberClass, + int modifiers) + { + return Modifier.isPublic(getClassAccessFlags(memberClass) & modifiers); + } + + public static void ensureMemberAccess(Class currentClass, + Class memberClass, + Object target, + int modifiers) + throws IllegalAccessException + { + if (currentClass == null || memberClass == null) { + throw new InternalError(); + } + + if (!verifyMemberAccess(currentClass, memberClass, target, modifiers)) { + throw new IllegalAccessException("Class " + currentClass.getName() + + " can not access a member of class " + + memberClass.getName() + + " with modifiers \"" + + Modifier.toString(modifiers) + + "\""); + } + } + + /*IKVM*/ + private static native boolean checkInternalAccess(Class currentClass, Class memberClass); + + public static boolean verifyMemberAccess(Class currentClass, + // Declaring class of field + // or method + Class memberClass, + // May be NULL in case of statics + Object target, + int modifiers) + { + // Verify that currentClass can access a field, method, or + // constructor of memberClass, where that member's access bits are + // "modifiers". + + boolean gotIsSameClassPackage = false; + boolean isSameClassPackage = false; + + if (currentClass == memberClass) { + // Always succeeds + return true; + } + + if (!Modifier.isPublic(getClassAccessFlags(memberClass))) { + isSameClassPackage = isSameClassPackage(currentClass, memberClass); + gotIsSameClassPackage = true; + /*IKVM*/ + if (!isSameClassPackage && !checkInternalAccess(currentClass, memberClass)) { + return false; + } + } + + // At this point we know that currentClass can access memberClass. + + if (Modifier.isPublic(modifiers)) { + return true; + } + + /*IKVM*/ + // Is the member @ikvm.lang.Internal accessible? + if ((modifiers & 0x40000000) != 0) { + return currentClass.getClassLoader() == memberClass.getClassLoader(); + } + + boolean successSoFar = false; + + if (Modifier.isProtected(modifiers)) { + // See if currentClass is a subclass of memberClass + if (isSubclassOf(currentClass, memberClass)) { + successSoFar = true; + } + } + + if (!successSoFar && !Modifier.isPrivate(modifiers)) { + if (!gotIsSameClassPackage) { + isSameClassPackage = isSameClassPackage(currentClass, + memberClass); + gotIsSameClassPackage = true; + } + + if (isSameClassPackage) { + successSoFar = true; + } + } + + if (!successSoFar) { + return false; + } + + if (Modifier.isProtected(modifiers)) { + // Additional test for protected members: JLS 6.6.2 + Class targetClass = (target == null ? memberClass : target.getClass()); + if (targetClass != currentClass) { + if (!gotIsSameClassPackage) { + isSameClassPackage = isSameClassPackage(currentClass, memberClass); + gotIsSameClassPackage = true; + } + if (!isSameClassPackage) { + if (!isSubclassOf(targetClass, currentClass)) { + return false; + } + } + } + } + + return true; + } + + private static boolean isSameClassPackage(Class c1, Class c2) { + return isSameClassPackage(c1.getClassLoader(), c1.getName(), + c2.getClassLoader(), c2.getName()); + } + + /** Returns true if two classes are in the same package; classloader + and classname information is enough to determine a class's package */ + private static boolean isSameClassPackage(ClassLoader loader1, String name1, + ClassLoader loader2, String name2) + { + if (loader1 != loader2) { + return false; + } else { + int lastDot1 = name1.lastIndexOf('.'); + int lastDot2 = name2.lastIndexOf('.'); + if ((lastDot1 == -1) || (lastDot2 == -1)) { + // One of the two doesn't have a package. Only return true + // if the other one also doesn't have a package. + return (lastDot1 == lastDot2); + } else { + int idx1 = 0; + int idx2 = 0; + + // Skip over '['s + if (name1.charAt(idx1) == '[') { + do { + idx1++; + } while (name1.charAt(idx1) == '['); + if (name1.charAt(idx1) != 'L') { + // Something is terribly wrong. Shouldn't be here. + throw new InternalError("Illegal class name " + name1); + } + } + if (name2.charAt(idx2) == '[') { + do { + idx2++; + } while (name2.charAt(idx2) == '['); + if (name2.charAt(idx2) != 'L') { + // Something is terribly wrong. Shouldn't be here. + throw new InternalError("Illegal class name " + name2); + } + } + + // Check that package part is identical + int length1 = lastDot1 - idx1; + int length2 = lastDot2 - idx2; + + if (length1 != length2) { + return false; + } + return name1.regionMatches(false, idx1, name2, idx2, length1); + } + } + } + + static boolean isSubclassOf(Class queryClass, + Class ofClass) + { + while (queryClass != null) { + if (queryClass == ofClass) { + return true; + } + queryClass = queryClass.getSuperclass(); + } + return false; + } + + // fieldNames must contain only interned Strings + public static synchronized void registerFieldsToFilter(Class containingClass, + String ... fieldNames) { + fieldFilterMap = + registerFilter(fieldFilterMap, containingClass, fieldNames); + } + + // methodNames must contain only interned Strings + public static synchronized void registerMethodsToFilter(Class containingClass, + String ... methodNames) { + methodFilterMap = + registerFilter(methodFilterMap, containingClass, methodNames); + } + + private static Map,String[]> registerFilter(Map,String[]> map, + Class containingClass, String ... names) { + if (map.get(containingClass) != null) { + throw new IllegalArgumentException + ("Filter already registered: " + containingClass); + } + map = new HashMap,String[]>(map); + map.put(containingClass, names); + return map; + } + + public static Field[] filterFields(Class containingClass, + Field[] fields) { + if (fieldFilterMap == null) { + // Bootstrapping + return fields; + } + return (Field[])filter(fields, fieldFilterMap.get(containingClass)); + } + + public static Method[] filterMethods(Class containingClass, Method[] methods) { + if (methodFilterMap == null) { + // Bootstrapping + return methods; + } + return (Method[])filter(methods, methodFilterMap.get(containingClass)); + } + + private static Member[] filter(Member[] members, String[] filteredNames) { + if ((filteredNames == null) || (members.length == 0)) { + return members; + } + int numNewMembers = 0; + for (Member member : members) { + boolean shouldSkip = false; + for (String filteredName : filteredNames) { + if (member.getName() == filteredName) { + shouldSkip = true; + break; + } + } + if (!shouldSkip) { + ++numNewMembers; + } + } + Member[] newMembers = + (Member[])Array.newInstance(members[0].getClass(), numNewMembers); + int destIdx = 0; + for (Member member : members) { + boolean shouldSkip = false; + for (String filteredName : filteredNames) { + if (member.getName() == filteredName) { + shouldSkip = true; + break; + } + } + if (!shouldSkip) { + newMembers[destIdx++] = member; + } + } + return newMembers; + } + + /** + * Tests if the given method is caller-sensitive and the declaring class + * is defined by either the bootstrap class loader or extension class loader. + */ + public static boolean isCallerSensitive(Method m) { + final ClassLoader loader = m.getDeclaringClass().getClassLoader(); + if (sun.misc.VM.isSystemDomainLoader(loader) || isExtClassLoader(loader)) { + return m.isAnnotationPresent(CallerSensitive.class); + } + return false; + } + + private static boolean isExtClassLoader(ClassLoader loader) { + ClassLoader cl = ClassLoader.getSystemClassLoader(); + while (cl != null) { + if (cl.getParent() == null && cl == loader) { + return true; + } + cl = cl.getParent(); + } + return false; + } +} diff --git a/openjdk/sun/reflect/ReflectionFactory.java b/openjdk/sun/reflect/ReflectionFactory.java new file mode 100644 index 0000000..35cae84 --- /dev/null +++ b/openjdk/sun/reflect/ReflectionFactory.java @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2001, 2013, 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. + */ + +/*IKVM*/ +/* + * May 29, 2007 Modified for IKVM.NET by Jeroen Frijters + * + */ + +package sun.reflect; + +import java.lang.reflect.Field; +import java.lang.reflect.Executable; +import java.lang.reflect.Method; +import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; +import java.security.AccessController; +import java.security.Permission; +import java.security.PrivilegedAction; +import sun.reflect.misc.ReflectUtil; + +/**

The master factory for all reflective objects, both those in + java.lang.reflect (Fields, Methods, Constructors) as well as their + delegates (FieldAccessors, MethodAccessors, ConstructorAccessors). +

+ +

The methods in this class are extremely unsafe and can cause + subversion of both the language and the verifier. For this reason, + they are all instance methods, and access to the constructor of + this factory is guarded by a security check, in similar style to + {@link sun.misc.Unsafe}.

+*/ + +public class ReflectionFactory { + + private static final Permission reflectionFactoryAccessPerm + = new RuntimePermission("reflectionFactoryAccess"); + private static final ReflectionFactory soleInstance = new ReflectionFactory(); + // Provides access to package-private mechanisms in java.lang.reflect + private static volatile LangReflectAccess langReflectAccess; + + private ReflectionFactory() { + } + + /** + * A convenience class for acquiring the capability to instantiate + * reflective objects. Use this instead of a raw call to {@link + * #getReflectionFactory} in order to avoid being limited by the + * permissions of your callers. + * + *

An instance of this class can be used as the argument of + * AccessController.doPrivileged. + */ + public static final class GetReflectionFactoryAction + implements PrivilegedAction { + public ReflectionFactory run() { + return getReflectionFactory(); + } + } + + /** + * Provides the caller with the capability to instantiate reflective + * objects. + * + *

First, if there is a security manager, its + * checkPermission method is called with a {@link + * java.lang.RuntimePermission} with target + * "reflectionFactoryAccess". This may result in a + * security exception. + * + *

The returned ReflectionFactory object should be + * carefully guarded by the caller, since it can be used to read and + * write private data and invoke private methods, as well as to load + * unverified bytecodes. It must never be passed to untrusted code. + * + * @exception SecurityException if a security manager exists and its + * checkPermission method doesn't allow + * access to the RuntimePermission "reflectionFactoryAccess". */ + public static ReflectionFactory getReflectionFactory() { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + // TO DO: security.checkReflectionFactoryAccess(); + security.checkPermission(reflectionFactoryAccessPerm); + } + return soleInstance; + } + + //-------------------------------------------------------------------------- + // + // Routines used by java.lang.reflect + // + // + + /** Called only by java.lang.reflect.Modifier's static initializer */ + public void setLangReflectAccess(LangReflectAccess access) { + langReflectAccess = access; + } + + /** + * Note: this routine can cause the declaring class for the field + * be initialized and therefore must not be called until the + * first get/set of this field. + * @param field the field + * @param override true if caller has overridden aaccessibility + */ + public native FieldAccessor newFieldAccessor(Field field, boolean override); + + public native MethodAccessor newMethodAccessor(Method method); + + private native ConstructorAccessor newConstructorAccessor0(Constructor c); + + public ConstructorAccessor newConstructorAccessor(Constructor c) { + Class declaringClass = c.getDeclaringClass(); + if (Modifier.isAbstract(declaringClass.getModifiers())) { + return new InstantiationExceptionConstructorAccessorImpl(null); + } + if (declaringClass == Class.class) { + return new InstantiationExceptionConstructorAccessorImpl + ("Can not instantiate java.lang.Class"); + } + return newConstructorAccessor0(c); + } + + //-------------------------------------------------------------------------- + // + // Routines used by java.lang + // + // + + /** Creates a new java.lang.reflect.Field. Access checks as per + java.lang.reflect.AccessibleObject are not overridden. */ + public Field newField(Class declaringClass, + String name, + Class type, + int modifiers, + int slot, + String signature, + byte[] annotations) + { + return langReflectAccess().newField(declaringClass, + name, + type, + modifiers, + slot, + signature, + annotations); + } + + /** Creates a new java.lang.reflect.Method. Access checks as per + java.lang.reflect.AccessibleObject are not overridden. */ + public Method newMethod(Class declaringClass, + String name, + Class[] parameterTypes, + Class returnType, + Class[] checkedExceptions, + int modifiers, + int slot, + String signature, + byte[] annotations, + byte[] parameterAnnotations, + byte[] annotationDefault) + { + return langReflectAccess().newMethod(declaringClass, + name, + parameterTypes, + returnType, + checkedExceptions, + modifiers, + slot, + signature, + annotations, + parameterAnnotations, + annotationDefault); + } + + /** Creates a new java.lang.reflect.Constructor. Access checks as + per java.lang.reflect.AccessibleObject are not overridden. */ + public Constructor newConstructor(Class declaringClass, + Class[] parameterTypes, + Class[] checkedExceptions, + int modifiers, + int slot, + String signature, + byte[] annotations, + byte[] parameterAnnotations) + { + return langReflectAccess().newConstructor(declaringClass, + parameterTypes, + checkedExceptions, + modifiers, + slot, + signature, + annotations, + parameterAnnotations); + } + + /** Gets the MethodAccessor object for a java.lang.reflect.Method */ + public MethodAccessor getMethodAccessor(Method m) { + return langReflectAccess().getMethodAccessor(m); + } + + /** Sets the MethodAccessor object for a java.lang.reflect.Method */ + public void setMethodAccessor(Method m, MethodAccessor accessor) { + langReflectAccess().setMethodAccessor(m, accessor); + } + + /** Gets the ConstructorAccessor object for a + java.lang.reflect.Constructor */ + public ConstructorAccessor getConstructorAccessor(Constructor c) { + return langReflectAccess().getConstructorAccessor(c); + } + + /** Sets the ConstructorAccessor object for a + java.lang.reflect.Constructor */ + public void setConstructorAccessor(Constructor c, + ConstructorAccessor accessor) + { + langReflectAccess().setConstructorAccessor(c, accessor); + } + + /** Makes a copy of the passed method. The returned method is a + "child" of the passed one; see the comments in Method.java for + details. */ + public Method copyMethod(Method arg) { + return langReflectAccess().copyMethod(arg); + } + + /** Makes a copy of the passed field. The returned field is a + "child" of the passed one; see the comments in Field.java for + details. */ + public Field copyField(Field arg) { + return langReflectAccess().copyField(arg); + } + + /** Makes a copy of the passed constructor. The returned + constructor is a "child" of the passed one; see the comments + in Constructor.java for details. */ + public Constructor copyConstructor(Constructor arg) { + return langReflectAccess().copyConstructor(arg); + } + + /** Gets the byte[] that encodes TypeAnnotations on an executable. + */ + public byte[] getExecutableTypeAnnotationBytes(Executable ex) { + return langReflectAccess().getExecutableTypeAnnotationBytes(ex); + } + + //-------------------------------------------------------------------------- + // + // Routines used by serialization + // + // + + private static native ConstructorAccessor newConstructorAccessorForSerialization(Class classToInstantiate, Constructor constructorToCall); + + public Constructor newConstructorForSerialization + (Class classToInstantiate, Constructor constructorToCall) + { + // Fast path + if (constructorToCall.getDeclaringClass() == classToInstantiate) { + return constructorToCall; + } + + ConstructorAccessor acc = newConstructorAccessorForSerialization(classToInstantiate, constructorToCall); + Constructor c = newConstructor(constructorToCall.getDeclaringClass(), + constructorToCall.getParameterTypes(), + constructorToCall.getExceptionTypes(), + constructorToCall.getModifiers(), + langReflectAccess(). + getConstructorSlot(constructorToCall), + langReflectAccess(). + getConstructorSignature(constructorToCall), + langReflectAccess(). + getConstructorAnnotations(constructorToCall), + langReflectAccess(). + getConstructorParameterAnnotations(constructorToCall)); + setConstructorAccessor(c, acc); + return c; + } + + //-------------------------------------------------------------------------- + // + // Internals only below this point + // + + private static LangReflectAccess langReflectAccess() { + if (langReflectAccess == null) { + // Call a static method to get class java.lang.reflect.Modifier + // initialized. Its static initializer will cause + // setLangReflectAccess() to be called from the context of the + // java.lang.reflect package. + Modifier.isPublic(Modifier.PUBLIC); + } + return langReflectAccess; + } +} diff --git a/openjdk/sun/reflect/annotation/AnnotationType.java b/openjdk/sun/reflect/annotation/AnnotationType.java new file mode 100644 index 0000000..8028001 --- /dev/null +++ b/openjdk/sun/reflect/annotation/AnnotationType.java @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2003, 2013, 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.reflect.annotation; + +import sun.misc.JavaLangAccess; + +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.util.*; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * Represents an annotation type at run time. Used to type-check annotations + * and apply member defaults. + * + * @author Josh Bloch + * @since 1.5 + */ +public class AnnotationType { + /** + * Member name -> type mapping. Note that primitive types + * are represented by the class objects for the corresponding wrapper + * types. This matches the return value that must be used for a + * dynamic proxy, allowing for a simple isInstance test. + */ + private final Map> memberTypes; + + /** + * Member name -> default value mapping. + */ + private final Map memberDefaults; + + /** + * Member name -> Method object mapping. This (and its assoicated + * accessor) are used only to generate AnnotationTypeMismatchExceptions. + */ + private final Map members; + + /** + * The retention policy for this annotation type. + */ + private final RetentionPolicy retention; + + /** + * Whether this annotation type is inherited. + */ + private final boolean inherited; + + /** + * Returns an AnnotationType instance for the specified annotation type. + * + * @throw IllegalArgumentException if the specified class object for + * does not represent a valid annotation type + */ + public static AnnotationType getInstance( + Class annotationClass) + { + JavaLangAccess jla = sun.misc.SharedSecrets.getJavaLangAccess(); + AnnotationType result = jla.getAnnotationType(annotationClass); // volatile read + if (result == null) { + result = new AnnotationType(annotationClass); + // try to CAS the AnnotationType: null -> result + if (!jla.casAnnotationType(annotationClass, null, result)) { + // somebody was quicker -> read it's result + result = jla.getAnnotationType(annotationClass); + assert result != null; + } + } + + return result; + } + + /** + * Sole constructor. + * + * @param annotationClass the class object for the annotation type + * @throw IllegalArgumentException if the specified class object for + * does not represent a valid annotation type + */ + private AnnotationType(final Class annotationClass) { + if (!annotationClass.isAnnotation()) + throw new IllegalArgumentException("Not an annotation type"); + + Method[] methods = + AccessController.doPrivileged(new PrivilegedAction() { + public Method[] run() { + // Initialize memberTypes and defaultValues + return annotationClass.getDeclaredMethods(); + } + }); + + memberTypes = new HashMap>(methods.length+1, 1.0f); + memberDefaults = new HashMap(0); + members = new HashMap(methods.length+1, 1.0f); + + for (Method method : methods) { + if (method.getParameterTypes().length != 0) + throw new IllegalArgumentException(method + " has params"); + String name = method.getName(); + Class type = method.getReturnType(); + memberTypes.put(name, invocationHandlerReturnType(type)); + members.put(name, method); + + Object defaultValue = method.getDefaultValue(); + if (defaultValue != null) + memberDefaults.put(name, defaultValue); + } + + // Initialize retention, & inherited fields. Special treatment + // of the corresponding annotation types breaks infinite recursion. + if (annotationClass != Retention.class && + annotationClass != Inherited.class) { + Retention ret = (Retention) annotationClass.getDeclaredAnnotation(Retention.class); + retention = (ret == null ? RetentionPolicy.CLASS : ret.value()); + inherited = annotationClass.isAnnotationPresent(Inherited.class); + } + else { + retention = RetentionPolicy.RUNTIME; + inherited = false; + } + } + + /** + * Returns the type that must be returned by the invocation handler + * of a dynamic proxy in order to have the dynamic proxy return + * the specified type (which is assumed to be a legal member type + * for an annotation). + */ + public static Class invocationHandlerReturnType(Class type) { + // Translate primitives to wrappers + if (type == byte.class) + return Byte.class; + if (type == char.class) + return Character.class; + if (type == double.class) + return Double.class; + if (type == float.class) + return Float.class; + if (type == int.class) + return Integer.class; + if (type == long.class) + return Long.class; + if (type == short.class) + return Short.class; + if (type == boolean.class) + return Boolean.class; + + // Otherwise, just return declared type + return type; + } + + /** + * Returns member types for this annotation type + * (member name -> type mapping). + */ + public Map> memberTypes() { + return memberTypes; + } + + /** + * Returns members of this annotation type + * (member name -> associated Method object mapping). + */ + public Map members() { + return members; + } + + /** + * Returns the default values for this annotation type + * (Member name -> default value mapping). + */ + public Map memberDefaults() { + return memberDefaults; + } + + /** + * Returns the retention policy for this annotation type. + */ + public RetentionPolicy retention() { + return retention; + } + + /** + * Returns true if this this annotation type is inherited. + */ + public boolean isInherited() { + return inherited; + } + + /** + * For debugging. + */ + public String toString() { + return "Annotation Type:\n" + + " Member types: " + memberTypes + "\n" + + " Member defaults: " + memberDefaults + "\n" + + " Retention policy: " + retention + "\n" + + " Inherited: " + inherited; + } +} diff --git a/openjdk/sun/security/jgss/wrapper/NativeGSSFactory.java b/openjdk/sun/security/jgss/wrapper/NativeGSSFactory.java new file mode 100644 index 0000000..08ac04d --- /dev/null +++ b/openjdk/sun/security/jgss/wrapper/NativeGSSFactory.java @@ -0,0 +1,75 @@ +/* + Copyright (C) 2007 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package sun.security.jgss.wrapper; + +// this is a compilation stub only +public abstract class NativeGSSFactory implements sun.security.jgss.spi.MechanismFactory +{ + private NativeGSSFactory() { } + /* + public Oid getMechanismOid() + { + throw new UnsupportedOperationException(); + } + + public Provider getProvider() + { + throw new UnsupportedOperationException(); + } + + public Oid[] getNameTypes() + { + throw new UnsupportedOperationException(); + } + + public GSSCredentialSpi getCredentialElement(GSSNameSpi name, int initLifetime, int acceptLifetime, int usage) + { + throw new UnsupportedOperationException(); + } + + public GSSNameSpi getNameElement(String nameStr, Oid nameType) + { + throw new UnsupportedOperationException(); + } + + public GSSNameSpi getNameElement(byte[] name, Oid nameType) + { + throw new UnsupportedOperationException(); + } + + public GSSContextSpi getMechanismContext(GSSNameSpi peer, GSSCredentialSpi myInitiatorCred, int lifetime) + { + } + + public GSSContextSpi getMechanismContext(GSSCredentialSpi myAcceptorCred) + { + } + + public GSSContextSpi getMechanismContext(byte[] exportedContext) + { + } +*/ + public abstract void setMech(org.ietf.jgss.Oid mech); +} diff --git a/openjdk/sun/security/jgss/wrapper/SunNativeProvider.java b/openjdk/sun/security/jgss/wrapper/SunNativeProvider.java new file mode 100644 index 0000000..42e027d --- /dev/null +++ b/openjdk/sun/security/jgss/wrapper/SunNativeProvider.java @@ -0,0 +1,40 @@ +/* + Copyright (C) 2007 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +package sun.security.jgss.wrapper; + +// this is a compilation stub only +public final class SunNativeProvider extends java.security.Provider +{ + public static final SunNativeProvider INSTANCE = new SunNativeProvider(); + + public SunNativeProvider() + { + super(null, 0.0, null); + } + + static void debug(String message) + { + } +} diff --git a/openjdk/swingawt.xml b/openjdk/swingawt.xml new file mode 100644 index 0000000..d40f3a4 --- /dev/null +++ b/openjdk/swingawt.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + diff --git a/openjdk/tools.rsp b/openjdk/tools.rsp new file mode 100644 index 0000000..630a944 --- /dev/null +++ b/openjdk/tools.rsp @@ -0,0 +1,206 @@ +# +# Copyright (C) 2002-2014 Jeroen Frijters +# +# This software is provided 'as-is', without any express or implied +# warranty. In no event will the authors be held liable for any damages +# arising from the use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software +# in a product, an acknowledgment in the product documentation would be +# appreciated but is not required. +# 2. Altered source versions must be plainly marked as such, and must not be +# misrepresented as being the original software. +# 3. This notice may not be removed or altered from any source distribution. +# +# Jeroen Frijters +# jeroen@frijters.net +# + +-compressresources +-strictfinalfieldsemantics +-removeassertions +{ + -out:../bin/IKVM.OpenJDK.Tools.dll + -resource:META-INF/services/com.sun.jdi.connect.Connector=@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/META-INF/services/com.sun.jdi.connect.Connector + -resource:META-INF/services/com.sun.jdi.connect.spi.TransportService=@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/META-INF/services/com.sun.jdi.connect.spi.TransportService + -resource:META-INF/services/com.sun.tools.internal.xjc.Plugin=@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/etc/META-INF/services/com.sun.tools.internal.xjc.Plugin + -resource:META-INF/services/com.sun.tools.xjc.Plugin=@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/classes/META-INF/services/com.sun.tools.xjc.Plugin + -resource:META-INF/services/com.sun.tools.attach.spi.AttachProvider=@OPENJDK@/jdk/src/share/classes/sun/tools/attach/META-INF/services/com.sun.tools.attach.spi.AttachProvider + -resource:com/sun/tools/corba/se/idl/idl.prp=@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/idl.prp + -resource:com/sun/tools/corba/se/idl/idl_ja.prp=@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/idl_ja.prp + -resource:com/sun/tools/corba/se/idl/idl_zh_CN.prp=@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/idl_zh_CN.prp + -resource:com/sun/tools/corba/se/idl/toJavaPortable/toJavaPortable.prp=@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/toJavaPortable.prp + -resource:com/sun/tools/corba/se/idl/toJavaPortable/toJavaPortable_ja.prp=@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/toJavaPortable_ja.prp + -resource:com/sun/tools/corba/se/idl/toJavaPortable/toJavaPortable_zh_CN.prp=@OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/toJavaPortable_zh_CN.prp + -recurse:@OPENJDK@/langtools/src/share/classes/*.properties + -assemblyattributes:commonAttributes.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/tools/jdi/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/com/sun/tools/jdi/resources/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/tools/jar/resources/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/doclets/formats/html/resources/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/doclets/internal/toolkit/resources/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javac/resources/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javadoc/resources/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javah/resources/*.class + @OPENJDK@/build/linux-x86_64-normal-server-release/langtools/gensrc/com/sun/tools/javap/resources/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/*.class + @OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/*.class + @OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/*.class + @OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/som/cff/*.class + @OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/som/idlemit/*.class + @OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/*.class + @OPENJDK@/corba/src/share/classes/com/sun/tools/corba/se/logutil/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/istack/internal/tools/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/ap/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/api/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/api/impl/j2s/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/gen/config/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/jxc/model/nav/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/api/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/api/wsdl/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/generator/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/exporter/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/java/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/model/jaxb/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/annotation/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/wsdl/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/resources/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/spi/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/util/xml/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/http/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/jaxws/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/mime/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/schema/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/document/soap/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/framework/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/addon/accessors/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/addon/at_generated/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/addon/code_injector/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/addon/episode/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/addon/locator/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/addon/sync/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/impl/s2j/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/annotation/spec/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/bean/field/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/generator/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/nav/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/outline/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/bindinfo/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/dtd/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/gbind/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/relaxng/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ct/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/parser/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/runtime/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/writer/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/dtdparser/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/builder/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/om/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/ast/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/binary/visitor/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/digested/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/dt/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/dt/builtin/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/nc/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/compact/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/host/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/parse/xml/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/xml/sax/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/xml/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/parser/state/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/scd/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/impl/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/parser/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/visitor/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/org/relaxng/datatype/*.class + @OPENJDK@/jaxws/src/share/jaxws_classes/org/relaxng/datatype/helpers/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jarsigner/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jdi/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jdi/connect/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jdi/connect/spi/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jdi/event/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/jdi/request/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/tools/attach/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/tools/attach/spi/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/*.class + @OPENJDK@/jdk/src/share/classes/com/sun/tools/script/shell/*.class + @OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/*.class + @OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/newrmic/*.class + @OPENJDK@/jdk/src/share/classes/sun/rmi/rmic/newrmic/jrmp/*.class + @OPENJDK@/jdk/src/share/classes/sun/tools/asm/*.class + @OPENJDK@/jdk/src/share/classes/sun/tools/jar/*.class + @OPENJDK@/jdk/src/share/classes/sun/tools/java/*.class + @OPENJDK@/jdk/src/share/classes/sun/tools/javac/*.class + @OPENJDK@/jdk/src/share/classes/sun/tools/native2ascii/*.class + @OPENJDK@/jdk/src/share/classes/sun/tools/native2ascii/resources/*.class + @OPENJDK@/jdk/src/share/classes/sun/tools/serialver/*.class + @OPENJDK@/jdk/src/share/classes/sun/tools/tree/*.class + @OPENJDK@/jdk/src/share/classes/sun/tools/util/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/javadoc/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/source/doctree/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/source/tree/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/source/util/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/classfile/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/standard/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/links/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/doclint/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/api/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/code/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/file/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/jvm/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/nio/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/main/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/model/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/parser/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/processing/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/sym/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/tree/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/javah/*.class + @OPENJDK@/langtools/src/share/classes/com/sun/tools/javap/*.class +} diff --git a/reflect/AmbiguousMatchException.cs b/reflect/AmbiguousMatchException.cs new file mode 100644 index 0000000..6a43621 --- /dev/null +++ b/reflect/AmbiguousMatchException.cs @@ -0,0 +1,54 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; + +namespace IKVM.Reflection +{ +#if !CORECLR + [Serializable] +#endif + public sealed class AmbiguousMatchException : Exception + { + public AmbiguousMatchException() + { + } + + public AmbiguousMatchException(string message) + : base(message) + { + } + + public AmbiguousMatchException(string message, Exception inner) + : base(message, inner) + { + } + +#if !CORECLR + private AmbiguousMatchException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) + : base(info, context) + { + } +#endif + } +} diff --git a/reflect/Assembly.cs b/reflect/Assembly.cs new file mode 100644 index 0000000..990c408 --- /dev/null +++ b/reflect/Assembly.cs @@ -0,0 +1,264 @@ +/* + Copyright (C) 2009-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; + +namespace IKVM.Reflection +{ + public delegate Module ModuleResolveEventHandler(object sender, ResolveEventArgs e); + + public abstract class Assembly : ICustomAttributeProvider + { + internal readonly Universe universe; + protected string fullName; // AssemblyBuilder needs access to this field to clear it when the name changes + protected List resolvers; + + internal Assembly(Universe universe) + { + this.universe = universe; + } + + public sealed override string ToString() + { + return FullName; + } + + public event ModuleResolveEventHandler ModuleResolve + { + add + { + if (resolvers == null) + { + resolvers = new List(); + } + resolvers.Add(value); + } + remove + { + resolvers.Remove(value); + } + } + + public abstract Type[] GetTypes(); + public abstract AssemblyName GetName(); + public abstract string ImageRuntimeVersion { get; } + public abstract Module ManifestModule { get; } + public abstract MethodInfo EntryPoint { get; } + public abstract string Location { get; } + public abstract AssemblyName[] GetReferencedAssemblies(); + public abstract Module[] GetModules(bool getResourceModules); + public abstract Module[] GetLoadedModules(bool getResourceModules); + public abstract Module GetModule(string name); + public abstract string[] GetManifestResourceNames(); + public abstract ManifestResourceInfo GetManifestResourceInfo(string resourceName); + public abstract System.IO.Stream GetManifestResourceStream(string name); + + internal abstract Type FindType(TypeName name); + internal abstract Type FindTypeIgnoreCase(TypeName lowerCaseName); + + // The differences between ResolveType and FindType are: + // - ResolveType is only used when a type is assumed to exist (because another module's metadata claims it) + // - ResolveType can return a MissingType + internal Type ResolveType(Module requester, TypeName typeName) + { + return FindType(typeName) ?? universe.GetMissingTypeOrThrow(requester, this.ManifestModule, null, typeName); + } + + public string FullName + { + get { return fullName ?? (fullName = GetName().FullName); } + } + + public Module[] GetModules() + { + return GetModules(true); + } + + public IEnumerable Modules + { + get { return GetLoadedModules(); } + } + + public Module[] GetLoadedModules() + { + return GetLoadedModules(true); + } + + public AssemblyName GetName(bool copiedName) + { + return GetName(); + } + + public bool ReflectionOnly + { + get { return true; } + } + + public Type[] GetExportedTypes() + { + List list = new List(); + foreach (Type type in GetTypes()) + { + if (type.IsVisible) + { + list.Add(type); + } + } + return list.ToArray(); + } + + public IEnumerable ExportedTypes + { + get { return GetExportedTypes(); } + } + + public IEnumerable DefinedTypes + { + get + { + Type[] types = GetTypes(); + TypeInfo[] typeInfos = new TypeInfo[types.Length]; + for (int i = 0; i < types.Length; i++) + { + typeInfos[i] = types[i].GetTypeInfo(); + } + return typeInfos; + } + } + + public Type GetType(string name) + { + return GetType(name, false); + } + + public Type GetType(string name, bool throwOnError) + { + return GetType(name, throwOnError, false); + } + + public Type GetType(string name, bool throwOnError, bool ignoreCase) + { + TypeNameParser parser = TypeNameParser.Parse(name, throwOnError); + if (parser.Error) + { + return null; + } + if (parser.AssemblyName != null) + { + if (throwOnError) + { + throw new ArgumentException("Type names passed to Assembly.GetType() must not specify an assembly."); + } + else + { + return null; + } + } + TypeName typeName = TypeName.Split(TypeNameParser.Unescape(parser.FirstNamePart)); + Type type = ignoreCase + ? FindTypeIgnoreCase(typeName.ToLowerInvariant()) + : FindType(typeName); + if (type == null && __IsMissing) + { + throw new MissingAssemblyException((MissingAssembly)this); + } + return parser.Expand(type, this.ManifestModule, throwOnError, name, false, ignoreCase); + } + + public virtual Module LoadModule(string moduleName, byte[] rawModule) + { + throw new NotSupportedException(); + } + + public Module LoadModule(string moduleName, byte[] rawModule, byte[] rawSymbolStore) + { + return LoadModule(moduleName, rawModule); + } + + public bool IsDefined(Type attributeType, bool inherit) + { + return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit).Count != 0; + } + + public IList __GetCustomAttributes(Type attributeType, bool inherit) + { + return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit); + } + + public IList GetCustomAttributesData() + { + return CustomAttributeData.GetCustomAttributes(this); + } + + public IEnumerable CustomAttributes + { + get { return GetCustomAttributesData(); } + } + + public static string CreateQualifiedName(string assemblyName, string typeName) + { + return typeName + ", " + assemblyName; + } + + public static Assembly GetAssembly(Type type) + { + return type.Assembly; + } + + public string CodeBase + { + get + { + string path = this.Location.Replace(System.IO.Path.DirectorySeparatorChar, '/'); + if (!path.StartsWith("/")) + { + path = "/" + path; + } + return "file://" + path; + } + } + + public virtual bool IsDynamic + { + get { return false; } + } + + public virtual bool __IsMissing + { + get { return false; } + } + + public AssemblyNameFlags __AssemblyFlags + { + get { return GetAssemblyFlags(); } + } + + protected virtual AssemblyNameFlags GetAssemblyFlags() + { + return GetName().Flags; + } + + internal abstract IList GetCustomAttributesData(Type attributeType); + } +} diff --git a/reflect/AssemblyName.cs b/reflect/AssemblyName.cs new file mode 100644 index 0000000..43c25e8 --- /dev/null +++ b/reflect/AssemblyName.cs @@ -0,0 +1,538 @@ +/* + Copyright (C) 2009-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Globalization; +using System.Configuration.Assemblies; +using System.IO; +using System.Security.Cryptography; +using System.Text; +using IKVM.Reflection.Reader; + +namespace IKVM.Reflection +{ + public sealed class AssemblyName +#if !CORECLR + : ICloneable +#endif + { + private string name; + private string culture; + private Version version; + private byte[] publicKeyToken; + private byte[] publicKey; + private StrongNameKeyPair keyPair; + private AssemblyNameFlags flags; + private AssemblyHashAlgorithm hashAlgorithm; + private AssemblyVersionCompatibility versionCompatibility = AssemblyVersionCompatibility.SameMachine; + private string codeBase; + internal byte[] hash; + + public AssemblyName() + { + } + + public AssemblyName(string assemblyName) + { + if (assemblyName == null) + { + throw new ArgumentNullException("assemblyName"); + } + if (assemblyName == "") + { + throw new ArgumentException(); + } + ParsedAssemblyName parsed; + switch (Fusion.ParseAssemblyName(assemblyName, out parsed)) + { + case ParseAssemblyResult.GenericError: + case ParseAssemblyResult.DuplicateKey: + throw new FileLoadException(); + } + if (!ParseVersion(parsed.Version, parsed.Retargetable.HasValue, out version)) + { + throw new FileLoadException(); + } + name = parsed.Name; + if (parsed.Culture != null) + { + if (parsed.Culture.Equals("neutral", StringComparison.OrdinalIgnoreCase)) + { + culture = ""; + } + else if (parsed.Culture == "") + { + throw new FileLoadException(); + } + else + { + culture = new CultureInfo(parsed.Culture).Name; + } + } + if (parsed.PublicKeyToken != null) + { + if (parsed.PublicKeyToken.Equals("null", StringComparison.OrdinalIgnoreCase)) + { + publicKeyToken = Empty.Array; + } + else if (parsed.PublicKeyToken.Length != 16) + { + throw new FileLoadException(); + } + else + { + publicKeyToken = ParseKey(parsed.PublicKeyToken); + } + } + if (parsed.Retargetable.HasValue) + { + if (parsed.Culture == null || parsed.PublicKeyToken == null || version == null) + { + throw new FileLoadException(); + } + if (parsed.Retargetable.Value) + { + flags |= AssemblyNameFlags.Retargetable; + } + } + ProcessorArchitecture = parsed.ProcessorArchitecture; + if (parsed.WindowsRuntime) + { + ContentType = AssemblyContentType.WindowsRuntime; + } + } + + private static byte[] ParseKey(string key) + { + if ((key.Length & 1) != 0) + { + throw new FileLoadException(); + } + byte[] buf = new byte[key.Length / 2]; + for (int i = 0; i < buf.Length; i++) + { + buf[i] = (byte)(ParseHexDigit(key[i * 2]) * 16 + ParseHexDigit(key[i * 2 + 1])); + } + return buf; + } + + private static int ParseHexDigit(char digit) + { + if (digit >= '0' && digit <= '9') + { + return digit - '0'; + } + else + { + digit |= (char)0x20; + if (digit >= 'a' && digit <= 'f') + { + return 10 + digit - 'a'; + } + else + { + throw new FileLoadException(); + } + } + } + + public override string ToString() + { + return FullName; + } + + public string Name + { + get { return name; } + set { name = value; } + } + + public CultureInfo CultureInfo + { + get { return culture == null ? null : new CultureInfo(culture); } + set { culture = value == null ? null : value.Name; } + } + + public string CultureName + { + get { return culture; } + } + + internal string Culture + { + get { return culture; } + set { culture = value; } + } + + public Version Version + { + get { return version; } + set { version = value; } + } + + public StrongNameKeyPair KeyPair + { + get { return keyPair; } + set { keyPair = value; } + } + + public string CodeBase + { + get { return codeBase; } + set { codeBase = value; } + } + +#if !CORECLR + public string EscapedCodeBase + { + get + { + // HACK use the real AssemblyName to escape the codebase + System.Reflection.AssemblyName tmp = new System.Reflection.AssemblyName(); + tmp.CodeBase = codeBase; + return tmp.EscapedCodeBase; + } + } +#endif + + public ProcessorArchitecture ProcessorArchitecture + { + get { return (ProcessorArchitecture)(((int)flags & 0x70) >> 4); } + set + { + if (value >= ProcessorArchitecture.None && value <= ProcessorArchitecture.Arm) + { + flags = (flags & ~(AssemblyNameFlags)0x70) | (AssemblyNameFlags)((int)value << 4); + } + } + } + + public AssemblyNameFlags Flags + { + get { return flags & (AssemblyNameFlags)~0xEF0; } + set { flags = (flags & (AssemblyNameFlags)0xEF0) | (value & (AssemblyNameFlags)~0xEF0); } + } + + public AssemblyVersionCompatibility VersionCompatibility + { + get { return versionCompatibility; } + set { versionCompatibility = value; } + } + + public AssemblyContentType ContentType + { + get { return (AssemblyContentType)(((int)flags & 0xE00) >> 9); } + set + { + if (value >= AssemblyContentType.Default && value <= AssemblyContentType.WindowsRuntime) + { + flags = (flags & ~(AssemblyNameFlags)0xE00) | (AssemblyNameFlags)((int)value << 9); + } + } + } + + public byte[] GetPublicKey() + { + return publicKey; + } + + public void SetPublicKey(byte[] publicKey) + { + this.publicKey = publicKey; + flags = (flags & ~AssemblyNameFlags.PublicKey) | (publicKey == null ? 0 : AssemblyNameFlags.PublicKey); + } + + public byte[] GetPublicKeyToken() + { + if (publicKeyToken == null && publicKey != null) + { + // note that GetPublicKeyToken() has a side effect in this case, because we retain this token even after the public key subsequently gets changed + publicKeyToken = ComputePublicKeyToken(publicKey); + } + return publicKeyToken; + } + + public void SetPublicKeyToken(byte[] publicKeyToken) + { + this.publicKeyToken = publicKeyToken; + } + + public AssemblyHashAlgorithm HashAlgorithm + { + get { return hashAlgorithm; } + set { hashAlgorithm = value; } + } + + public byte[] __Hash + { + get { return hash; } + } + + public string FullName + { + get + { + if (name == null) + { + return ""; + } + ushort versionMajor = 0xFFFF; + ushort versionMinor = 0xFFFF; + ushort versionBuild = 0xFFFF; + ushort versionRevision = 0xFFFF; + if (version != null) + { + versionMajor = (ushort)version.Major; + versionMinor = (ushort)version.Minor; + versionBuild = (ushort)version.Build; + versionRevision = (ushort)version.Revision; + } + byte[] publicKeyToken = this.publicKeyToken; + if ((publicKeyToken == null || publicKeyToken.Length == 0) && publicKey != null) + { + publicKeyToken = ComputePublicKeyToken(publicKey); + } + return GetFullName(name, versionMajor, versionMinor, versionBuild, versionRevision, culture, publicKeyToken, (int)flags); + } + } + + internal static string GetFullName(string name, ushort versionMajor, ushort versionMinor, ushort versionBuild, ushort versionRevision, string culture, byte[] publicKeyToken, int flags) + { + StringBuilder sb = new StringBuilder(); + bool doubleQuotes = name.StartsWith(" ") || name.EndsWith(" ") || name.IndexOf('\'') != -1; + bool singleQuotes = name.IndexOf('"') != -1; + if (singleQuotes) + { + sb.Append('\''); + } + else if (doubleQuotes) + { + sb.Append('"'); + } + if (name.IndexOf(',') != -1 || name.IndexOf('\\') != -1 || name.IndexOf('=') != -1 || (singleQuotes && name.IndexOf('\'') != -1)) + { + for (int i = 0; i < name.Length; i++) + { + char c = name[i]; + if (c == ',' || c == '\\' || c == '=' || (singleQuotes && c == '\'')) + { + sb.Append('\\'); + } + sb.Append(c); + } + } + else + { + sb.Append(name); + } + if (singleQuotes) + { + sb.Append('\''); + } + else if (doubleQuotes) + { + sb.Append('"'); + } + if (versionMajor != 0xFFFF) + { + sb.Append(", Version=").Append(versionMajor); + if (versionMinor != 0xFFFF) + { + sb.Append('.').Append(versionMinor); + if (versionBuild != 0xFFFF) + { + sb.Append('.').Append(versionBuild); + if (versionRevision != 0xFFFF) + { + sb.Append('.').Append(versionRevision); + } + } + } + } + if (culture != null) + { + sb.Append(", Culture=").Append(culture == "" ? "neutral" : culture); + } + if (publicKeyToken != null) + { + sb.Append(", PublicKeyToken="); + if (publicKeyToken.Length == 0) + { + sb.Append("null"); + } + else + { + AppendPublicKey(sb, publicKeyToken); + } + } + if ((flags & (int)AssemblyNameFlags.Retargetable) != 0) + { + sb.Append(", Retargetable=Yes"); + } + if ((AssemblyContentType)((flags & 0xE00) >> 9) == AssemblyContentType.WindowsRuntime) + { + sb.Append(", ContentType=WindowsRuntime"); + } + return sb.ToString(); + } + + internal static byte[] ComputePublicKeyToken(byte[] publicKey) + { + if (publicKey.Length == 0) + { + return publicKey; + } + byte[] hash = new SHA1Managed().ComputeHash(publicKey); + byte[] token = new byte[8]; + for (int i = 0; i < token.Length; i++) + { + token[i] = hash[hash.Length - 1 - i]; + } + return token; + } + + internal static string ComputePublicKeyToken(string publicKey) + { + StringBuilder sb = new StringBuilder(16); + AppendPublicKey(sb, ComputePublicKeyToken(ParseKey(publicKey))); + return sb.ToString(); + } + + private static void AppendPublicKey(StringBuilder sb, byte[] publicKey) + { + for (int i = 0; i < publicKey.Length; i++) + { + sb.Append("0123456789abcdef"[publicKey[i] >> 4]); + sb.Append("0123456789abcdef"[publicKey[i] & 0x0F]); + } + } + + public override bool Equals(object obj) + { + AssemblyName other = obj as AssemblyName; + return other != null && other.FullName == this.FullName; + } + + public override int GetHashCode() + { + return FullName.GetHashCode(); + } + + public object Clone() + { + AssemblyName copy = (AssemblyName)MemberwiseClone(); + copy.publicKey = Copy(publicKey); + copy.publicKeyToken = Copy(publicKeyToken); + return copy; + } + + private static byte[] Copy(byte[] b) + { + return b == null || b.Length == 0 ? b : (byte[])b.Clone(); + } + +#if !CORECLR + public static bool ReferenceMatchesDefinition(AssemblyName reference, AssemblyName definition) + { + // HACK use the real AssemblyName to implement the (broken) ReferenceMatchesDefinition method + return System.Reflection.AssemblyName.ReferenceMatchesDefinition(new System.Reflection.AssemblyName(reference.FullName), new System.Reflection.AssemblyName(definition.FullName)); + } +#endif + + public static AssemblyName GetAssemblyName(string path) + { + try + { + path = Path.GetFullPath(path); + using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + ModuleReader module = new ModuleReader(null, null, fs, path, false); + if (module.Assembly == null) + { + throw new BadImageFormatException("Module does not contain a manifest"); + } + return module.Assembly.GetName(); + } + } + catch (IOException x) + { + throw new FileNotFoundException(x.Message, x); + } + catch (UnauthorizedAccessException x) + { + throw new FileNotFoundException(x.Message, x); + } + } + + internal AssemblyNameFlags RawFlags + { + get { return flags; } + set { flags = value; } + } + + private static bool ParseVersion(string str, bool mustBeComplete, out Version version) + { + if (str == null) + { + version = null; + return true; + } + string[] parts = str.Split('.'); + if (parts.Length < 2 || parts.Length > 4) + { + version = null; + ushort dummy; + // if the version consists of a single integer, it is invalid, but not invalid enough to fail the parse of the whole assembly name + return parts.Length == 1 && ushort.TryParse(parts[0], NumberStyles.Integer, null, out dummy); + } + if (parts[0] == "" || parts[1] == "") + { + // this is a strange scenario, the version is invalid, but not invalid enough to fail the parse of the whole assembly name + version = null; + return true; + } + ushort major, minor, build = 65535, revision = 65535; + if (ushort.TryParse(parts[0], NumberStyles.Integer, null, out major) + && ushort.TryParse(parts[1], NumberStyles.Integer, null, out minor) + && (parts.Length <= 2 || parts[2] == "" || ushort.TryParse(parts[2], NumberStyles.Integer, null, out build)) + && (parts.Length <= 3 || parts[3] == "" || (parts[2] != "" && ushort.TryParse(parts[3], NumberStyles.Integer, null, out revision)))) + { + if (mustBeComplete && (parts.Length < 4 || parts[2] == "" || parts[3] == "")) + { + version = null; + } + else if (major == 65535 || minor == 65535) + { + version = null; + } + else + { + version = new Version(major, minor, build, revision); + } + return true; + } + version = null; + return false; + } + } +} diff --git a/reflect/BadImageFormatException.cs b/reflect/BadImageFormatException.cs new file mode 100644 index 0000000..5704434 --- /dev/null +++ b/reflect/BadImageFormatException.cs @@ -0,0 +1,54 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; + +namespace IKVM.Reflection +{ +#if !CORECLR + [Serializable] +#endif + public sealed class BadImageFormatException : Exception + { + public BadImageFormatException() + { + } + + public BadImageFormatException(string message) + : base(message) + { + } + + public BadImageFormatException(string message, Exception inner) + : base(message, inner) + { + } + +#if !CORECLR + private BadImageFormatException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) + : base(info, context) + { + } +#endif + } +} diff --git a/reflect/Binder.cs b/reflect/Binder.cs new file mode 100644 index 0000000..ca12f6b --- /dev/null +++ b/reflect/Binder.cs @@ -0,0 +1,403 @@ +/* + Copyright (C) 2010-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Globalization; + +namespace IKVM.Reflection +{ + public abstract class Binder + { + protected Binder() + { + } + + public virtual MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] names, out object state) + { + throw new InvalidOperationException(); + } + + public virtual FieldInfo BindToField(BindingFlags bindingAttr, FieldInfo[] match, object value, CultureInfo culture) + { + throw new InvalidOperationException(); + } + + public virtual object ChangeType(object value, Type type, CultureInfo culture) + { + throw new InvalidOperationException(); + } + + public virtual void ReorderArgumentArray(ref object[] args, object state) + { + throw new InvalidOperationException(); + } + + public abstract MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers); + public abstract PropertyInfo SelectProperty(BindingFlags bindingAttr, PropertyInfo[] match, Type returnType, Type[] indexes, ParameterModifier[] modifiers); + } + + sealed class DefaultBinder : Binder + { + public override MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers) + { + int matchCount = 0; + foreach (MethodBase method in match) + { + if (MatchParameterTypes(method.GetParameters(), types)) + { + match[matchCount++] = method; + } + } + + if (matchCount == 0) + { + return null; + } + + MethodBase bestMatch = match[0]; + bool ambiguous = false; + for (int i = 1; i < matchCount; i++) + { + SelectBestMatch(match[i], types, ref bestMatch, ref ambiguous); + } + if (ambiguous) + { + throw new AmbiguousMatchException(); + } + return bestMatch; + } + + private static bool MatchParameterTypes(ParameterInfo[] parameters, Type[] types) + { + if (parameters.Length != types.Length) + { + return false; + } + for (int i = 0; i < parameters.Length; i++) + { + Type sourceType = types[i]; + Type targetType = parameters[i].ParameterType; + if (sourceType != targetType + && !targetType.IsAssignableFrom(sourceType) + && !IsAllowedPrimitiveConversion(sourceType, targetType)) + { + return false; + } + } + return true; + } + + private static void SelectBestMatch(MethodBase candidate, Type[] types, ref MethodBase currentBest, ref bool ambiguous) + { + switch (MatchSignatures(currentBest.MethodSignature, candidate.MethodSignature, types)) + { + case 1: + return; + case 2: + ambiguous = false; + currentBest = candidate; + return; + } + + if (currentBest.MethodSignature.MatchParameterTypes(candidate.MethodSignature)) + { + int depth1 = GetInheritanceDepth(currentBest.DeclaringType); + int depth2 = GetInheritanceDepth(candidate.DeclaringType); + if (depth1 > depth2) + { + return; + } + else if (depth1 < depth2) + { + ambiguous = false; + currentBest = candidate; + return; + } + } + + ambiguous = true; + } + + private static int GetInheritanceDepth(Type type) + { + int depth = 0; + while (type != null) + { + depth++; + type = type.BaseType; + } + return depth; + } + + private static int MatchSignatures(MethodSignature sig1, MethodSignature sig2, Type[] types) + { + for (int i = 0; i < sig1.GetParameterCount(); i++) + { + Type type1 = sig1.GetParameterType(i); + Type type2 = sig2.GetParameterType(i); + if (type1 != type2) + { + return MatchTypes(type1, type2, types[i]); + } + } + return 0; + } + + private static int MatchSignatures(PropertySignature sig1, PropertySignature sig2, Type[] types) + { + for (int i = 0; i < sig1.ParameterCount; i++) + { + Type type1 = sig1.GetParameter(i); + Type type2 = sig2.GetParameter(i); + if (type1 != type2) + { + return MatchTypes(type1, type2, types[i]); + } + } + return 0; + } + + private static int MatchTypes(Type type1, Type type2, Type type) + { + if (type1 == type) + { + return 1; + } + if (type2 == type) + { + return 2; + } + bool conv = type1.IsAssignableFrom(type2); + return conv == type2.IsAssignableFrom(type1) ? 0 : conv ? 2 : 1; + } + + private static bool IsAllowedPrimitiveConversion(Type source, Type target) + { + // we need to check for primitives, because GetTypeCode will return the underlying type for enums + if (!source.IsPrimitive || !target.IsPrimitive) + { + return false; + } + TypeCode sourceType = Type.GetTypeCode(source); + TypeCode targetType = Type.GetTypeCode(target); + switch (sourceType) + { + case TypeCode.Char: + switch (targetType) + { + case TypeCode.UInt16: + case TypeCode.UInt32: + case TypeCode.Int32: + case TypeCode.UInt64: + case TypeCode.Int64: + case TypeCode.Single: + case TypeCode.Double: + return true; + default: + return false; + } + case TypeCode.Byte: + switch (targetType) + { + case TypeCode.Char: + case TypeCode.UInt16: + case TypeCode.Int16: + case TypeCode.UInt32: + case TypeCode.Int32: + case TypeCode.UInt64: + case TypeCode.Int64: + case TypeCode.Single: + case TypeCode.Double: + return true; + default: + return false; + } + case TypeCode.SByte: + switch (targetType) + { + case TypeCode.Int16: + case TypeCode.Int32: + case TypeCode.Int64: + case TypeCode.Single: + case TypeCode.Double: + return true; + default: + return false; + } + case TypeCode.UInt16: + switch (targetType) + { + case TypeCode.UInt32: + case TypeCode.Int32: + case TypeCode.UInt64: + case TypeCode.Int64: + case TypeCode.Single: + case TypeCode.Double: + return true; + default: + return false; + } + case TypeCode.Int16: + switch (targetType) + { + case TypeCode.Int32: + case TypeCode.Int64: + case TypeCode.Single: + case TypeCode.Double: + return true; + default: + return false; + } + case TypeCode.UInt32: + switch (targetType) + { + case TypeCode.UInt64: + case TypeCode.Int64: + case TypeCode.Single: + case TypeCode.Double: + return true; + default: + return false; + } + case TypeCode.Int32: + switch (targetType) + { + case TypeCode.Int64: + case TypeCode.Single: + case TypeCode.Double: + return true; + default: + return false; + } + case TypeCode.UInt64: + switch (targetType) + { + case TypeCode.Single: + case TypeCode.Double: + return true; + default: + return false; + } + case TypeCode.Int64: + switch (targetType) + { + case TypeCode.Single: + case TypeCode.Double: + return true; + default: + return false; + } + case TypeCode.Single: + switch (targetType) + { + case TypeCode.Double: + return true; + default: + return false; + } + default: + return false; + } + } + + public override PropertyInfo SelectProperty(BindingFlags bindingAttr, PropertyInfo[] match, Type returnType, Type[] indexes, ParameterModifier[] modifiers) + { + int matchCount = 0; + foreach (PropertyInfo property in match) + { + if (indexes == null || MatchParameterTypes(property.GetIndexParameters(), indexes)) + { + if (returnType != null) + { + if (property.PropertyType.IsPrimitive) + { + if (!IsAllowedPrimitiveConversion(returnType, property.PropertyType)) + { + continue; + } + } + else + { + if (!property.PropertyType.IsAssignableFrom(returnType)) + { + continue; + } + } + } + match[matchCount++] = property; + } + } + + if (matchCount == 0) + { + return null; + } + + if (matchCount == 1) + { + return match[0]; + } + + PropertyInfo bestMatch = match[0]; + bool ambiguous = false; + for (int i = 1; i < matchCount; i++) + { + int best = MatchTypes(bestMatch.PropertyType, match[i].PropertyType, returnType); + if (best == 0 && indexes != null) + { + best = MatchSignatures(bestMatch.PropertySignature, match[i].PropertySignature, indexes); + } + if (best == 0) + { + int depth1 = GetInheritanceDepth(bestMatch.DeclaringType); + int depth2 = GetInheritanceDepth(match[i].DeclaringType); + if (bestMatch.Name == match[i].Name && depth1 != depth2) + { + if (depth1 > depth2) + { + best = 1; + } + else + { + best = 2; + } + } + else + { + ambiguous = true; + } + } + if (best == 2) + { + ambiguous = false; + bestMatch = match[i]; + } + } + if (ambiguous) + { + throw new AmbiguousMatchException(); + } + return bestMatch; + } + } +} diff --git a/reflect/ConstructorInfo.cs b/reflect/ConstructorInfo.cs new file mode 100644 index 0000000..11d18a7 --- /dev/null +++ b/reflect/ConstructorInfo.cs @@ -0,0 +1,239 @@ +/* + Copyright (C) 2009-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace IKVM.Reflection +{ + public abstract class ConstructorInfo : MethodBase + { + // prevent external subclasses + internal ConstructorInfo() + { + } + + public sealed override string ToString() + { + return GetMethodInfo().ToString(); + } + + public static readonly string ConstructorName = ".ctor"; + public static readonly string TypeConstructorName = ".cctor"; + + internal abstract MethodInfo GetMethodInfo(); + + internal override MethodBase BindTypeParameters(Type type) + { + return new ConstructorInfoImpl((MethodInfo)GetMethodInfo().BindTypeParameters(type)); + } + + public sealed override MethodBase __GetMethodOnTypeDefinition() + { + return new ConstructorInfoImpl((MethodInfo)GetMethodInfo().__GetMethodOnTypeDefinition()); + } + + public sealed override MemberTypes MemberType + { + get { return MemberTypes.Constructor; } + } + + public sealed override int __MethodRVA + { + get { return GetMethodInfo().__MethodRVA; } + } + + public sealed override bool ContainsGenericParameters + { + get { return GetMethodInfo().ContainsGenericParameters; } + } + + public ParameterInfo __ReturnParameter + { + get { return new ParameterInfoWrapper(this, GetMethodInfo().ReturnParameter); } + } + + public sealed override ParameterInfo[] GetParameters() + { + ParameterInfo[] parameters = GetMethodInfo().GetParameters(); + for (int i = 0; i < parameters.Length; i++) + { + parameters[i] = new ParameterInfoWrapper(this, parameters[i]); + } + return parameters; + } + + public sealed override CallingConventions CallingConvention + { + get { return GetMethodInfo().CallingConvention; } + } + + public sealed override MethodAttributes Attributes + { + get { return GetMethodInfo().Attributes; } + } + + public sealed override MethodImplAttributes GetMethodImplementationFlags() + { + return GetMethodInfo().GetMethodImplementationFlags(); + } + + public sealed override Type DeclaringType + { + get { return GetMethodInfo().DeclaringType; } + } + + public sealed override string Name + { + get { return GetMethodInfo().Name; } + } + + public sealed override int MetadataToken + { + get { return GetMethodInfo().MetadataToken; } + } + + public sealed override Module Module + { + get { return GetMethodInfo().Module; } + } + + public sealed override MethodBody GetMethodBody() + { + return GetMethodInfo().GetMethodBody(); + } + + public sealed override bool __IsMissing + { + get { return GetMethodInfo().__IsMissing; } + } + + internal sealed override int ParameterCount + { + get { return GetMethodInfo().ParameterCount; } + } + + internal sealed override MemberInfo SetReflectedType(Type type) + { + return new ConstructorInfoWithReflectedType(type, this); + } + + internal sealed override int GetCurrentToken() + { + return GetMethodInfo().GetCurrentToken(); + } + + internal sealed override List GetPseudoCustomAttributes(Type attributeType) + { + return GetMethodInfo().GetPseudoCustomAttributes(attributeType); + } + + internal sealed override bool IsBaked + { + get { return GetMethodInfo().IsBaked; } + } + + internal sealed override MethodSignature MethodSignature + { + get { return GetMethodInfo().MethodSignature; } + } + + internal sealed override int ImportTo(Emit.ModuleBuilder module) + { + return GetMethodInfo().ImportTo(module); + } + } + + sealed class ConstructorInfoImpl : ConstructorInfo + { + private readonly MethodInfo method; + + internal ConstructorInfoImpl(MethodInfo method) + { + this.method = method; + } + + public override bool Equals(object obj) + { + ConstructorInfoImpl other = obj as ConstructorInfoImpl; + return other != null && other.method.Equals(method); + } + + public override int GetHashCode() + { + return method.GetHashCode(); + } + + internal override MethodInfo GetMethodInfo() + { + return method; + } + + internal override MethodInfo GetMethodOnTypeDefinition() + { + return method.GetMethodOnTypeDefinition(); + } + } + + sealed class ConstructorInfoWithReflectedType : ConstructorInfo + { + private readonly Type reflectedType; + private readonly ConstructorInfo ctor; + + internal ConstructorInfoWithReflectedType(Type reflectedType, ConstructorInfo ctor) + { + Debug.Assert(reflectedType != ctor.DeclaringType); + this.reflectedType = reflectedType; + this.ctor = ctor; + } + + public override bool Equals(object obj) + { + ConstructorInfoWithReflectedType other = obj as ConstructorInfoWithReflectedType; + return other != null + && other.reflectedType == reflectedType + && other.ctor == ctor; + } + + public override int GetHashCode() + { + return reflectedType.GetHashCode() ^ ctor.GetHashCode(); + } + + public override Type ReflectedType + { + get { return reflectedType; } + } + + internal override MethodInfo GetMethodInfo() + { + return ctor.GetMethodInfo(); + } + + internal override MethodInfo GetMethodOnTypeDefinition() + { + return ctor.GetMethodOnTypeDefinition(); + } + } +} diff --git a/reflect/CustomAttributeData.cs b/reflect/CustomAttributeData.cs new file mode 100644 index 0000000..b9574d5 --- /dev/null +++ b/reflect/CustomAttributeData.cs @@ -0,0 +1,1022 @@ +/* + Copyright (C) 2009-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; +using IKVM.Reflection.Reader; +using IKVM.Reflection.Emit; +using IKVM.Reflection.Metadata; + +namespace IKVM.Reflection +{ + public sealed class CustomAttributeData + { + internal static readonly IList EmptyList = new List(0).AsReadOnly(); + + /* + * There are several states a CustomAttributeData object can be in: + * + * 1) Unresolved Custom Attribute + * - customAttributeIndex >= 0 + * - declSecurityIndex == -1 + * - declSecurityBlob == null + * - lazyConstructor = null + * - lazyConstructorArguments = null + * - lazyNamedArguments = null + * + * 2) Resolved Custom Attribute + * - customAttributeIndex >= 0 + * - declSecurityIndex == -1 + * - declSecurityBlob == null + * - lazyConstructor != null + * - lazyConstructorArguments != null + * - lazyNamedArguments != null + * + * 3) Pre-resolved Custom Attribute + * - customAttributeIndex = -1 + * - declSecurityIndex == -1 + * - declSecurityBlob == null + * - lazyConstructor != null + * - lazyConstructorArguments != null + * - lazyNamedArguments != null + * + * 4) Pseudo Custom Attribute, .NET 1.x declarative security or result of CustomAttributeBuilder.ToData() + * - customAttributeIndex = -1 + * - declSecurityIndex == -1 + * - declSecurityBlob == null + * - lazyConstructor != null + * - lazyConstructorArguments != null + * - lazyNamedArguments != null + * + * 5) Unresolved declarative security + * - customAttributeIndex = -1 + * - declSecurityIndex >= 0 + * - declSecurityBlob != null + * - lazyConstructor != null + * - lazyConstructorArguments != null + * - lazyNamedArguments == null + * + * 6) Resolved declarative security + * - customAttributeIndex = -1 + * - declSecurityIndex >= 0 + * - declSecurityBlob == null + * - lazyConstructor != null + * - lazyConstructorArguments != null + * - lazyNamedArguments != null + * + */ + private readonly Module module; + private readonly int customAttributeIndex; + private readonly int declSecurityIndex; + private readonly byte[] declSecurityBlob; + private ConstructorInfo lazyConstructor; + private IList lazyConstructorArguments; + private IList lazyNamedArguments; + + // 1) Unresolved Custom Attribute + internal CustomAttributeData(Module module, int index) + { + this.module = module; + this.customAttributeIndex = index; + this.declSecurityIndex = -1; + } + + // 4) Pseudo Custom Attribute, .NET 1.x declarative security + internal CustomAttributeData(Module module, ConstructorInfo constructor, object[] args, List namedArguments) + : this(module, constructor, WrapConstructorArgs(args, constructor.MethodSignature), namedArguments) + { + } + + private static List WrapConstructorArgs(object[] args, MethodSignature sig) + { + List list = new List(); + for (int i = 0; i < args.Length; i++) + { + list.Add(new CustomAttributeTypedArgument(sig.GetParameterType(i), args[i])); + } + return list; + } + + // 4) Pseudo Custom Attribute, .NET 1.x declarative security or result of CustomAttributeBuilder.ToData() + internal CustomAttributeData(Module module, ConstructorInfo constructor, List constructorArgs, List namedArguments) + { + this.module = module; + this.customAttributeIndex = -1; + this.declSecurityIndex = -1; + this.lazyConstructor = constructor; + lazyConstructorArguments = constructorArgs.AsReadOnly(); + if (namedArguments == null) + { + this.lazyNamedArguments = Empty.Array; + } + else + { + this.lazyNamedArguments = namedArguments.AsReadOnly(); + } + } + + // 3) Pre-resolved Custom Attribute + internal CustomAttributeData(Assembly asm, ConstructorInfo constructor, ByteReader br) + { + this.module = asm.ManifestModule; + this.customAttributeIndex = -1; + this.declSecurityIndex = -1; + this.lazyConstructor = constructor; + if (br.Length == 0) + { + // it's legal to have an empty blob + lazyConstructorArguments = Empty.Array; + lazyNamedArguments = Empty.Array; + } + else + { + if (br.ReadUInt16() != 1) + { + throw new BadImageFormatException(); + } + lazyConstructorArguments = ReadConstructorArguments(module, br, constructor); + lazyNamedArguments = ReadNamedArguments(module, br, br.ReadUInt16(), constructor.DeclaringType, true); + } + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append('['); + sb.Append(Constructor.DeclaringType.FullName); + sb.Append('('); + string sep = ""; + ParameterInfo[] parameters = Constructor.GetParameters(); + IList args = ConstructorArguments; + for (int i = 0; i < parameters.Length; i++) + { + sb.Append(sep); + sep = ", "; + AppendValue(sb, parameters[i].ParameterType, args[i]); + } + foreach (CustomAttributeNamedArgument named in NamedArguments) + { + sb.Append(sep); + sep = ", "; + sb.Append(named.MemberInfo.Name); + sb.Append(" = "); + FieldInfo fi = named.MemberInfo as FieldInfo; + Type type = fi != null ? fi.FieldType : ((PropertyInfo)named.MemberInfo).PropertyType; + AppendValue(sb, type, named.TypedValue); + } + sb.Append(')'); + sb.Append(']'); + return sb.ToString(); + } + + private static void AppendValue(StringBuilder sb, Type type, CustomAttributeTypedArgument arg) + { + if (arg.ArgumentType == arg.ArgumentType.Module.universe.System_String) + { + sb.Append('"').Append(arg.Value).Append('"'); + } + else if (arg.ArgumentType.IsArray) + { + Type elementType = arg.ArgumentType.GetElementType(); + string elementTypeName; + if (elementType.IsPrimitive + || elementType == type.Module.universe.System_Object + || elementType == type.Module.universe.System_String + || elementType == type.Module.universe.System_Type) + { + elementTypeName = elementType.Name; + } + else + { + elementTypeName = elementType.FullName; + } + sb.Append("new ").Append(elementTypeName).Append("[").Append(((Array)arg.Value).Length).Append("] { "); + string sep = ""; + foreach (CustomAttributeTypedArgument elem in (CustomAttributeTypedArgument[])arg.Value) + { + sb.Append(sep); + sep = ", "; + AppendValue(sb, elementType, elem); + } + sb.Append(" }"); + } + else + { + if (arg.ArgumentType != type || (type.IsEnum && !arg.Value.Equals(0))) + { + sb.Append('('); + sb.Append(arg.ArgumentType.FullName); + sb.Append(')'); + } + sb.Append(arg.Value); + } + } + + internal static void ReadDeclarativeSecurity(Module module, int index, List list) + { + Universe u = module.universe; + Assembly asm = module.Assembly; + int action = module.DeclSecurity.records[index].Action; + ByteReader br = module.GetBlob(module.DeclSecurity.records[index].PermissionSet); + if (br.PeekByte() == '.') + { + br.ReadByte(); + int count = br.ReadCompressedUInt(); + for (int j = 0; j < count; j++) + { + Type type = ReadType(module, br); + ConstructorInfo constructor = type.GetPseudoCustomAttributeConstructor(u.System_Security_Permissions_SecurityAction); + // LAMESPEC there is an additional length here (probably of the named argument list) + byte[] blob = br.ReadBytes(br.ReadCompressedUInt()); + list.Add(new CustomAttributeData(asm, constructor, action, blob, index)); + } + } + else + { + // .NET 1.x format (xml) + char[] buf = new char[br.Length / 2]; + for (int i = 0; i < buf.Length; i++) + { + buf[i] = br.ReadChar(); + } + string xml = new String(buf); + ConstructorInfo constructor = u.System_Security_Permissions_PermissionSetAttribute.GetPseudoCustomAttributeConstructor(u.System_Security_Permissions_SecurityAction); + List args = new List(); + args.Add(new CustomAttributeNamedArgument(GetProperty(null, u.System_Security_Permissions_PermissionSetAttribute, "XML", u.System_String), + new CustomAttributeTypedArgument(u.System_String, xml))); + list.Add(new CustomAttributeData(asm.ManifestModule, constructor, new object[] { action }, args)); + } + } + + // 5) Unresolved declarative security + internal CustomAttributeData(Assembly asm, ConstructorInfo constructor, int securityAction, byte[] blob, int index) + { + this.module = asm.ManifestModule; + this.customAttributeIndex = -1; + this.declSecurityIndex = index; + Universe u = constructor.Module.universe; + this.lazyConstructor = constructor; + List list = new List(); + list.Add(new CustomAttributeTypedArgument(u.System_Security_Permissions_SecurityAction, securityAction)); + this.lazyConstructorArguments = list.AsReadOnly(); + this.declSecurityBlob = blob; + } + + private static Type ReadFieldOrPropType(Module context, ByteReader br) + { + Universe u = context.universe; + switch (br.ReadByte()) + { + case Signature.ELEMENT_TYPE_BOOLEAN: + return u.System_Boolean; + case Signature.ELEMENT_TYPE_CHAR: + return u.System_Char; + case Signature.ELEMENT_TYPE_I1: + return u.System_SByte; + case Signature.ELEMENT_TYPE_U1: + return u.System_Byte; + case Signature.ELEMENT_TYPE_I2: + return u.System_Int16; + case Signature.ELEMENT_TYPE_U2: + return u.System_UInt16; + case Signature.ELEMENT_TYPE_I4: + return u.System_Int32; + case Signature.ELEMENT_TYPE_U4: + return u.System_UInt32; + case Signature.ELEMENT_TYPE_I8: + return u.System_Int64; + case Signature.ELEMENT_TYPE_U8: + return u.System_UInt64; + case Signature.ELEMENT_TYPE_R4: + return u.System_Single; + case Signature.ELEMENT_TYPE_R8: + return u.System_Double; + case Signature.ELEMENT_TYPE_STRING: + return u.System_String; + case Signature.ELEMENT_TYPE_SZARRAY: + return ReadFieldOrPropType(context, br).MakeArrayType(); + case 0x55: + return ReadType(context, br); + case 0x50: + return u.System_Type; + case 0x51: + return u.System_Object; + default: + throw new BadImageFormatException(); + } + } + + private static CustomAttributeTypedArgument ReadFixedArg(Module context, ByteReader br, Type type) + { + Universe u = context.universe; + if (type == u.System_String) + { + return new CustomAttributeTypedArgument(type, br.ReadString()); + } + else if (type == u.System_Boolean) + { + return new CustomAttributeTypedArgument(type, br.ReadByte() != 0); + } + else if (type == u.System_Char) + { + return new CustomAttributeTypedArgument(type, br.ReadChar()); + } + else if (type == u.System_Single) + { + return new CustomAttributeTypedArgument(type, br.ReadSingle()); + } + else if (type == u.System_Double) + { + return new CustomAttributeTypedArgument(type, br.ReadDouble()); + } + else if (type == u.System_SByte) + { + return new CustomAttributeTypedArgument(type, br.ReadSByte()); + } + else if (type == u.System_Int16) + { + return new CustomAttributeTypedArgument(type, br.ReadInt16()); + } + else if (type == u.System_Int32) + { + return new CustomAttributeTypedArgument(type, br.ReadInt32()); + } + else if (type == u.System_Int64) + { + return new CustomAttributeTypedArgument(type, br.ReadInt64()); + } + else if (type == u.System_Byte) + { + return new CustomAttributeTypedArgument(type, br.ReadByte()); + } + else if (type == u.System_UInt16) + { + return new CustomAttributeTypedArgument(type, br.ReadUInt16()); + } + else if (type == u.System_UInt32) + { + return new CustomAttributeTypedArgument(type, br.ReadUInt32()); + } + else if (type == u.System_UInt64) + { + return new CustomAttributeTypedArgument(type, br.ReadUInt64()); + } + else if (type == u.System_Type) + { + return new CustomAttributeTypedArgument(type, ReadType(context, br)); + } + else if (type == u.System_Object) + { + return ReadFixedArg(context, br, ReadFieldOrPropType(context, br)); + } + else if (type.IsArray) + { + int length = br.ReadInt32(); + if (length == -1) + { + return new CustomAttributeTypedArgument(type, null); + } + Type elementType = type.GetElementType(); + CustomAttributeTypedArgument[] array = new CustomAttributeTypedArgument[length]; + for (int i = 0; i < length; i++) + { + array[i] = ReadFixedArg(context, br, elementType); + } + return new CustomAttributeTypedArgument(type, array); + } + else if (type.IsEnum) + { + return new CustomAttributeTypedArgument(type, ReadFixedArg(context, br, type.GetEnumUnderlyingTypeImpl()).Value); + } + else + { + throw new InvalidOperationException(); + } + } + + private static Type ReadType(Module context, ByteReader br) + { + string typeName = br.ReadString(); + if (typeName == null) + { + return null; + } + if (typeName.Length > 0 && typeName[typeName.Length - 1] == 0) + { + // there are broken compilers that emit an extra NUL character after the type name + typeName = typeName.Substring(0, typeName.Length - 1); + } + return TypeNameParser.Parse(typeName, true).GetType(context.universe, context, true, typeName, true, false); + } + + private static IList ReadConstructorArguments(Module context, ByteReader br, ConstructorInfo constructor) + { + MethodSignature sig = constructor.MethodSignature; + int count = sig.GetParameterCount(); + List list = new List(count); + for (int i = 0; i < count; i++) + { + list.Add(ReadFixedArg(context, br, sig.GetParameterType(i))); + } + return list.AsReadOnly(); + } + + private static IList ReadNamedArguments(Module context, ByteReader br, int named, Type type, bool required) + { + List list = new List(named); + for (int i = 0; i < named; i++) + { + byte fieldOrProperty = br.ReadByte(); + Type fieldOrPropertyType = ReadFieldOrPropType(context, br); + if (fieldOrPropertyType.__IsMissing && !required) + { + return null; + } + string name = br.ReadString(); + CustomAttributeTypedArgument value = ReadFixedArg(context, br, fieldOrPropertyType); + MemberInfo member; + switch (fieldOrProperty) + { + case 0x53: + member = GetField(context, type, name, fieldOrPropertyType); + break; + case 0x54: + member = GetProperty(context, type, name, fieldOrPropertyType); + break; + default: + throw new BadImageFormatException(); + } + list.Add(new CustomAttributeNamedArgument(member, value)); + } + return list.AsReadOnly(); + } + + private static FieldInfo GetField(Module context, Type type, string name, Type fieldType) + { + Type org = type; + for (; type != null && !type.__IsMissing; type = type.BaseType) + { + foreach (FieldInfo field in type.__GetDeclaredFields()) + { + if (field.IsPublic && !field.IsStatic && field.Name == name) + { + return field; + } + } + } + // if the field is missing, we stick the missing field on the first missing base type + if (type == null) + { + type = org; + } + FieldSignature sig = FieldSignature.Create(fieldType, new CustomModifiers()); + return type.FindField(name, sig) + ?? type.Module.universe.GetMissingFieldOrThrow(context, type, name, sig); + } + + private static PropertyInfo GetProperty(Module context, Type type, string name, Type propertyType) + { + Type org = type; + for (; type != null && !type.__IsMissing; type = type.BaseType) + { + foreach (PropertyInfo property in type.__GetDeclaredProperties()) + { + if (property.IsPublic && !property.IsStatic && property.Name == name) + { + return property; + } + } + } + // if the property is missing, we stick the missing property on the first missing base type + if (type == null) + { + type = org; + } + return type.Module.universe.GetMissingPropertyOrThrow(context, type, name, + PropertySignature.Create(CallingConventions.Standard | CallingConventions.HasThis, propertyType, null, new PackedCustomModifiers())); + } + + [Obsolete("Use AttributeType property instead.")] + internal bool __TryReadTypeName(out string ns, out string name) + { + if (Constructor.DeclaringType.IsNested) + { + ns = null; + name = null; + return false; + } + TypeName typeName = AttributeType.TypeName; + ns = typeName.Namespace; + name = typeName.Name; + return true; + } + + public byte[] __GetBlob() + { + if (declSecurityBlob != null) + { + return (byte[])declSecurityBlob.Clone(); + } + else if (customAttributeIndex == -1) + { + return __ToBuilder().GetBlob(module.Assembly); + } + else + { + return ((ModuleReader)module).GetBlobCopy(module.CustomAttribute.records[customAttributeIndex].Value); + } + } + + public int __Parent + { + get + { + return customAttributeIndex >= 0 + ? module.CustomAttribute.records[customAttributeIndex].Parent + : declSecurityIndex >= 0 + ? module.DeclSecurity.records[declSecurityIndex].Parent + : 0; + } + } + + // .NET 4.5 API + public Type AttributeType + { + get { return Constructor.DeclaringType; } + } + + public ConstructorInfo Constructor + { + get + { + if (lazyConstructor == null) + { + lazyConstructor = (ConstructorInfo)module.ResolveMethod(module.CustomAttribute.records[customAttributeIndex].Type); + } + return lazyConstructor; + } + } + + public IList ConstructorArguments + { + get + { + if (lazyConstructorArguments == null) + { + LazyParseArguments(false); + } + return lazyConstructorArguments; + } + } + + public IList NamedArguments + { + get + { + if (lazyNamedArguments == null) + { + if (customAttributeIndex >= 0) + { + // 1) Unresolved Custom Attribute + LazyParseArguments(true); + } + else + { + // 5) Unresolved declarative security + ByteReader br = new ByteReader(declSecurityBlob, 0, declSecurityBlob.Length); + // LAMESPEC the count of named arguments is a compressed integer (instead of UInt16 as NumNamed in custom attributes) + lazyNamedArguments = ReadNamedArguments(module, br, br.ReadCompressedUInt(), Constructor.DeclaringType, true); + } + } + return lazyNamedArguments; + } + } + + private void LazyParseArguments(bool requireNameArguments) + { + ByteReader br = module.GetBlob(module.CustomAttribute.records[customAttributeIndex].Value); + if (br.Length == 0) + { + // it's legal to have an empty blob + lazyConstructorArguments = Empty.Array; + lazyNamedArguments = Empty.Array; + } + else + { + if (br.ReadUInt16() != 1) + { + throw new BadImageFormatException(); + } + lazyConstructorArguments = ReadConstructorArguments(module, br, Constructor); + lazyNamedArguments = ReadNamedArguments(module, br, br.ReadUInt16(), Constructor.DeclaringType, requireNameArguments); + } + } + + public CustomAttributeBuilder __ToBuilder() + { + ParameterInfo[] parameters = Constructor.GetParameters(); + object[] args = new object[ConstructorArguments.Count]; + for (int i = 0; i < args.Length; i++) + { + args[i] = RewrapArray(parameters[i].ParameterType, ConstructorArguments[i]); + } + List namedProperties = new List(); + List propertyValues = new List(); + List namedFields = new List(); + List fieldValues = new List(); + foreach (CustomAttributeNamedArgument named in NamedArguments) + { + PropertyInfo pi = named.MemberInfo as PropertyInfo; + if (pi != null) + { + namedProperties.Add(pi); + propertyValues.Add(RewrapArray(pi.PropertyType, named.TypedValue)); + } + else + { + FieldInfo fi = (FieldInfo)named.MemberInfo; + namedFields.Add(fi); + fieldValues.Add(RewrapArray(fi.FieldType, named.TypedValue)); + } + } + return new CustomAttributeBuilder(Constructor, args, namedProperties.ToArray(), propertyValues.ToArray(), namedFields.ToArray(), fieldValues.ToArray()); + } + + private static object RewrapArray(Type type, CustomAttributeTypedArgument arg) + { + IList list = arg.Value as IList; + if (list != null) + { + Type elementType = arg.ArgumentType.GetElementType(); + object[] arr = new object[list.Count]; + for (int i = 0; i < arr.Length; i++) + { + arr[i] = RewrapArray(elementType, list[i]); + } + if (type == type.Module.universe.System_Object) + { + return CustomAttributeBuilder.__MakeTypedArgument(arg.ArgumentType, arr); + } + return arr; + } + else + { + return arg.Value; + } + } + + public static IList GetCustomAttributes(MemberInfo member) + { + return __GetCustomAttributes(member, null, false); + } + + public static IList GetCustomAttributes(Assembly assembly) + { + return assembly.GetCustomAttributesData(null); + } + + public static IList GetCustomAttributes(Module module) + { + return __GetCustomAttributes(module, null, false); + } + + public static IList GetCustomAttributes(ParameterInfo parameter) + { + return __GetCustomAttributes(parameter, null, false); + } + + public static IList __GetCustomAttributes(Assembly assembly, Type attributeType, bool inherit) + { + return assembly.GetCustomAttributesData(attributeType); + } + + public static IList __GetCustomAttributes(Module module, Type attributeType, bool inherit) + { + if (module.__IsMissing) + { + throw new MissingModuleException((MissingModule)module); + } + return GetCustomAttributesImpl(null, module, 0x00000001, attributeType) ?? EmptyList; + } + + public static IList __GetCustomAttributes(ParameterInfo parameter, Type attributeType, bool inherit) + { + Module module = parameter.Module; + List list = null; + if (module.universe.ReturnPseudoCustomAttributes) + { + if (attributeType == null || attributeType.IsAssignableFrom(parameter.Module.universe.System_Runtime_InteropServices_MarshalAsAttribute)) + { + FieldMarshal spec; + if (parameter.__TryGetFieldMarshal(out spec)) + { + if (list == null) + { + list = new List(); + } + list.Add(CustomAttributeData.CreateMarshalAsPseudoCustomAttribute(parameter.Module, spec)); + } + } + } + ModuleBuilder mb = module as ModuleBuilder; + int token = parameter.MetadataToken; + if (mb != null && mb.IsSaved && ModuleBuilder.IsPseudoToken(token)) + { + token = mb.ResolvePseudoToken(token); + } + return GetCustomAttributesImpl(list, module, token, attributeType) ?? EmptyList; + } + + public static IList __GetCustomAttributes(MemberInfo member, Type attributeType, bool inherit) + { + if (!member.IsBaked) + { + // like .NET we we don't return custom attributes for unbaked members + throw new NotImplementedException(); + } + if (!inherit || !IsInheritableAttribute(attributeType)) + { + return GetCustomAttributesImpl(null, member, attributeType) ?? EmptyList; + } + List list = new List(); + for (; ; ) + { + GetCustomAttributesImpl(list, member, attributeType); + Type type = member as Type; + if (type != null) + { + type = type.BaseType; + if (type == null) + { + return list; + } + member = type; + continue; + } + MethodInfo method = member as MethodInfo; + if (method != null) + { + MemberInfo prev = member; + method = method.GetBaseDefinition(); + if (method == null || method == prev) + { + return list; + } + member = method; + continue; + } + return list; + } + } + + private static List GetCustomAttributesImpl(List list, MemberInfo member, Type attributeType) + { + if (member.Module.universe.ReturnPseudoCustomAttributes) + { + List pseudo = member.GetPseudoCustomAttributes(attributeType); + if (list == null) + { + list = pseudo; + } + else if (pseudo != null) + { + list.AddRange(pseudo); + } + } + return GetCustomAttributesImpl(list, member.Module, member.GetCurrentToken(), attributeType); + } + + internal static List GetCustomAttributesImpl(List list, Module module, int token, Type attributeType) + { + foreach (int i in module.CustomAttribute.Filter(token)) + { + if (attributeType == null) + { + if (list == null) + { + list = new List(); + } + list.Add(new CustomAttributeData(module, i)); + } + else + { + if (attributeType.IsAssignableFrom(module.ResolveMethod(module.CustomAttribute.records[i].Type).DeclaringType)) + { + if (list == null) + { + list = new List(); + } + list.Add(new CustomAttributeData(module, i)); + } + } + } + return list; + } + + public static IList __GetCustomAttributes(Type type, Type interfaceType, Type attributeType, bool inherit) + { + Module module = type.Module; + foreach (int i in module.InterfaceImpl.Filter(type.MetadataToken)) + { + if (module.ResolveType(module.InterfaceImpl.records[i].Interface, type) == interfaceType) + { + return GetCustomAttributesImpl(null, module, (InterfaceImplTable.Index << 24) | (i + 1), attributeType) ?? EmptyList; + } + } + return EmptyList; + } + + public static IList __GetDeclarativeSecurity(Assembly assembly) + { + if (assembly.__IsMissing) + { + throw new MissingAssemblyException((MissingAssembly)assembly); + } + return assembly.ManifestModule.GetDeclarativeSecurity(0x20000001); + } + + public static IList __GetDeclarativeSecurity(Type type) + { + if ((type.Attributes & TypeAttributes.HasSecurity) != 0) + { + return type.Module.GetDeclarativeSecurity(type.MetadataToken); + } + else + { + return EmptyList; + } + } + + public static IList __GetDeclarativeSecurity(MethodBase method) + { + if ((method.Attributes & MethodAttributes.HasSecurity) != 0) + { + return method.Module.GetDeclarativeSecurity(method.MetadataToken); + } + else + { + return EmptyList; + } + } + + private static bool IsInheritableAttribute(Type attribute) + { + Type attributeUsageAttribute = attribute.Module.universe.System_AttributeUsageAttribute; + IList attr = __GetCustomAttributes(attribute, attributeUsageAttribute, false); + if (attr.Count != 0) + { + foreach (CustomAttributeNamedArgument named in attr[0].NamedArguments) + { + if (named.MemberInfo.Name == "Inherited") + { + return (bool)named.TypedValue.Value; + } + } + } + return true; + } + + internal static CustomAttributeData CreateDllImportPseudoCustomAttribute(Module module, ImplMapFlags flags, string entryPoint, string dllName, MethodImplAttributes attr) + { + Type type = module.universe.System_Runtime_InteropServices_DllImportAttribute; + ConstructorInfo constructor = type.GetPseudoCustomAttributeConstructor(module.universe.System_String); + List list = new List(); + System.Runtime.InteropServices.CharSet charSet; + switch (flags & ImplMapFlags.CharSetMask) + { + case ImplMapFlags.CharSetAnsi: + charSet = System.Runtime.InteropServices.CharSet.Ansi; + break; + case ImplMapFlags.CharSetUnicode: + charSet = System.Runtime.InteropServices.CharSet.Unicode; + break; + case ImplMapFlags.CharSetAuto: + charSet = System.Runtime.InteropServices.CharSet.Auto; + break; + case ImplMapFlags.CharSetNotSpec: + default: + charSet = System.Runtime.InteropServices.CharSet.None; + break; + } + System.Runtime.InteropServices.CallingConvention callingConvention; + switch (flags & ImplMapFlags.CallConvMask) + { + case ImplMapFlags.CallConvCdecl: + callingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl; + break; + case ImplMapFlags.CallConvFastcall: + callingConvention = System.Runtime.InteropServices.CallingConvention.FastCall; + break; + case ImplMapFlags.CallConvStdcall: + callingConvention = System.Runtime.InteropServices.CallingConvention.StdCall; + break; + case ImplMapFlags.CallConvThiscall: + callingConvention = System.Runtime.InteropServices.CallingConvention.ThisCall; + break; + case ImplMapFlags.CallConvWinapi: + callingConvention = System.Runtime.InteropServices.CallingConvention.Winapi; + break; + default: + callingConvention = 0; + break; + } + AddNamedArgument(list, type, "EntryPoint", entryPoint); + AddNamedArgument(list, type, "CharSet", module.universe.System_Runtime_InteropServices_CharSet, (int)charSet); + AddNamedArgument(list, type, "ExactSpelling", (int)flags, (int)ImplMapFlags.NoMangle); + AddNamedArgument(list, type, "SetLastError", (int)flags, (int)ImplMapFlags.SupportsLastError); + AddNamedArgument(list, type, "PreserveSig", (int)attr, (int)MethodImplAttributes.PreserveSig); + AddNamedArgument(list, type, "CallingConvention", module.universe.System_Runtime_InteropServices_CallingConvention, (int)callingConvention); + AddNamedArgument(list, type, "BestFitMapping", (int)flags, (int)ImplMapFlags.BestFitOn); + AddNamedArgument(list, type, "ThrowOnUnmappableChar", (int)flags, (int)ImplMapFlags.CharMapErrorOn); + return new CustomAttributeData(module, constructor, new object[] { dllName }, list); + } + + internal static CustomAttributeData CreateMarshalAsPseudoCustomAttribute(Module module, FieldMarshal fm) + { + Type typeofMarshalAs = module.universe.System_Runtime_InteropServices_MarshalAsAttribute; + Type typeofUnmanagedType = module.universe.System_Runtime_InteropServices_UnmanagedType; + Type typeofVarEnum = module.universe.System_Runtime_InteropServices_VarEnum; + Type typeofType = module.universe.System_Type; + List named = new List(); + AddNamedArgument(named, typeofMarshalAs, "ArraySubType", typeofUnmanagedType, (int)(fm.ArraySubType ?? 0)); + AddNamedArgument(named, typeofMarshalAs, "SizeParamIndex", module.universe.System_Int16, fm.SizeParamIndex ?? 0); + AddNamedArgument(named, typeofMarshalAs, "SizeConst", module.universe.System_Int32, fm.SizeConst ?? 0); + AddNamedArgument(named, typeofMarshalAs, "IidParameterIndex", module.universe.System_Int32, fm.IidParameterIndex ?? 0); + AddNamedArgument(named, typeofMarshalAs, "SafeArraySubType", typeofVarEnum, (int)(fm.SafeArraySubType ?? 0)); + if (fm.SafeArrayUserDefinedSubType != null) + { + AddNamedArgument(named, typeofMarshalAs, "SafeArrayUserDefinedSubType", typeofType, fm.SafeArrayUserDefinedSubType); + } + if (fm.MarshalType != null) + { + AddNamedArgument(named, typeofMarshalAs, "MarshalType", module.universe.System_String, fm.MarshalType); + } + if (fm.MarshalTypeRef != null) + { + AddNamedArgument(named, typeofMarshalAs, "MarshalTypeRef", module.universe.System_Type, fm.MarshalTypeRef); + } + if (fm.MarshalCookie != null) + { + AddNamedArgument(named, typeofMarshalAs, "MarshalCookie", module.universe.System_String, fm.MarshalCookie); + } + ConstructorInfo constructor = typeofMarshalAs.GetPseudoCustomAttributeConstructor(typeofUnmanagedType); + return new CustomAttributeData(module, constructor, new object[] { (int)fm.UnmanagedType }, named); + } + + private static void AddNamedArgument(List list, Type type, string fieldName, string value) + { + AddNamedArgument(list, type, fieldName, type.Module.universe.System_String, value); + } + + private static void AddNamedArgument(List list, Type type, string fieldName, int flags, int flagMask) + { + AddNamedArgument(list, type, fieldName, type.Module.universe.System_Boolean, (flags & flagMask) != 0); + } + + private static void AddNamedArgument(List list, Type attributeType, string fieldName, Type valueType, object value) + { + // some fields are not available on the .NET Compact Framework version of DllImportAttribute/MarshalAsAttribute + FieldInfo field = attributeType.FindField(fieldName, FieldSignature.Create(valueType, new CustomModifiers())); + if (field != null) + { + list.Add(new CustomAttributeNamedArgument(field, new CustomAttributeTypedArgument(valueType, value))); + } + } + + internal static CustomAttributeData CreateFieldOffsetPseudoCustomAttribute(Module module, int offset) + { + Type type = module.universe.System_Runtime_InteropServices_FieldOffsetAttribute; + ConstructorInfo constructor = type.GetPseudoCustomAttributeConstructor(module.universe.System_Int32); + return new CustomAttributeData(module, constructor, new object[] { offset }, null); + } + + internal static CustomAttributeData CreatePreserveSigPseudoCustomAttribute(Module module) + { + Type type = module.universe.System_Runtime_InteropServices_PreserveSigAttribute; + ConstructorInfo constructor = type.GetPseudoCustomAttributeConstructor(); + return new CustomAttributeData(module, constructor, Empty.Array, null); + } + } +} diff --git a/reflect/CustomAttributeNamedArgument.cs b/reflect/CustomAttributeNamedArgument.cs new file mode 100644 index 0000000..4b4a8ea --- /dev/null +++ b/reflect/CustomAttributeNamedArgument.cs @@ -0,0 +1,81 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; + +namespace IKVM.Reflection +{ + public struct CustomAttributeNamedArgument + { + private readonly MemberInfo member; + private readonly CustomAttributeTypedArgument value; + + internal CustomAttributeNamedArgument(MemberInfo member, CustomAttributeTypedArgument value) + { + this.member = member; + this.value = value; + } + + public override bool Equals(object obj) + { + return this == obj as CustomAttributeNamedArgument?; + } + + public override int GetHashCode() + { + return member.GetHashCode() ^ 53 * value.GetHashCode(); + } + + public MemberInfo MemberInfo + { + get { return member; } + } + + public CustomAttributeTypedArgument TypedValue + { + get { return value; } + } + + public bool IsField + { + get { return member.MemberType == MemberTypes.Field; } + } + + public string MemberName + { + get { return member.Name; } + } + + public static bool operator ==(CustomAttributeNamedArgument arg1, CustomAttributeNamedArgument arg2) + { + return arg1.member.Equals(arg2.member) && arg1.value == arg2.value; + } + + public static bool operator !=(CustomAttributeNamedArgument arg1, CustomAttributeNamedArgument arg2) + { + return !(arg1 == arg2); + } + } +} diff --git a/reflect/CustomAttributeTypedArgument.cs b/reflect/CustomAttributeTypedArgument.cs new file mode 100644 index 0000000..3403135 --- /dev/null +++ b/reflect/CustomAttributeTypedArgument.cs @@ -0,0 +1,71 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; + +namespace IKVM.Reflection +{ + public struct CustomAttributeTypedArgument + { + private readonly Type type; + private readonly object value; + + internal CustomAttributeTypedArgument(Type type, object value) + { + this.type = type; + this.value = value; + } + + public override bool Equals(object obj) + { + return this == obj as CustomAttributeTypedArgument?; + } + + public override int GetHashCode() + { + return type.GetHashCode() ^ 77 * (value == null ? 0 : value.GetHashCode()); + } + + public Type ArgumentType + { + get { return type; } + } + + public Object Value + { + get { return value; } + } + + public static bool operator ==(CustomAttributeTypedArgument arg1, CustomAttributeTypedArgument arg2) + { + return arg1.type.Equals(arg2.type) && (arg1.value == arg2.value || (arg1.value != null && arg1.value.Equals(arg2.value))); + } + + public static bool operator !=(CustomAttributeTypedArgument arg1, CustomAttributeTypedArgument arg2) + { + return !(arg1 == arg2); + } + } +} diff --git a/reflect/CustomModifiers.cs b/reflect/CustomModifiers.cs new file mode 100644 index 0000000..58a1639 --- /dev/null +++ b/reflect/CustomModifiers.cs @@ -0,0 +1,357 @@ +/* + Copyright (C) 2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using IKVM.Reflection.Emit; +using IKVM.Reflection.Reader; + +namespace IKVM.Reflection +{ + public struct CustomModifiers : IEquatable, IEnumerable + { + // note that FromReqOpt assumes that Initial == ModOpt + private static Type Initial { get { return MarkerType.ModOpt; } } + private readonly Type[] types; + + internal CustomModifiers(List list) + { + bool required = Initial == MarkerType.ModReq; + int count = list.Count; + foreach (CustomModifiersBuilder.Item item in list) + { + if (item.required != required) + { + required = item.required; + count++; + } + } + types = new Type[count]; + required = Initial == MarkerType.ModReq; + int index = 0; + foreach (CustomModifiersBuilder.Item item in list) + { + if (item.required != required) + { + required = item.required; + types[index++] = required ? MarkerType.ModReq : MarkerType.ModOpt; + } + types[index++] = item.type; + } + } + + private CustomModifiers(Type[] types) + { + Debug.Assert(types == null || types.Length != 0); + this.types = types; + } + + public struct Enumerator : IEnumerator + { + private readonly Type[] types; + private int index; + private bool required; + + internal Enumerator(Type[] types) + { + this.types = types; + this.index = -1; + this.required = Initial == MarkerType.ModReq; + } + + void System.Collections.IEnumerator.Reset() + { + this.index = -1; + this.required = Initial == MarkerType.ModReq; + } + + public Entry Current + { + get { return new Entry(types[index], required); } + } + + public bool MoveNext() + { + if (types == null || index == types.Length) + { + return false; + } + index++; + if (index == types.Length) + { + return false; + } + else if (types[index] == MarkerType.ModOpt) + { + required = false; + index++; + } + else if (types[index] == MarkerType.ModReq) + { + required = true; + index++; + } + return true; + } + + object System.Collections.IEnumerator.Current + { + get { return Current; } + } + + void IDisposable.Dispose() + { + } + } + + public struct Entry + { + private readonly Type type; + private readonly bool required; + + internal Entry(Type type, bool required) + { + this.type = type; + this.required = required; + } + + public Type Type + { + get { return type; } + } + + public bool IsRequired + { + get { return required; } + } + } + + public Enumerator GetEnumerator() + { + return new Enumerator(types); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public bool IsEmpty + { + get { return types == null; } + } + + public bool Equals(CustomModifiers other) + { + return Util.ArrayEquals(types, other.types); + } + + public override bool Equals(object obj) + { + CustomModifiers? other = obj as CustomModifiers?; + return other != null && Equals(other.Value); + } + + public override int GetHashCode() + { + return Util.GetHashCode(types); + } + + public override string ToString() + { + if (types == null) + { + return string.Empty; + } + StringBuilder sb = new StringBuilder(); + string sep = ""; + foreach (Entry e in this) + { + sb.Append(sep).Append(e.IsRequired ? "modreq(" : "modopt(").Append(e.Type.FullName).Append(')'); + sep = " "; + } + return sb.ToString(); + } + + public bool ContainsMissingType + { + get { return Type.ContainsMissingType(types); } + } + + private Type[] GetRequiredOrOptional(bool required) + { + if (types == null) + { + return Type.EmptyTypes; + } + int count = 0; + foreach (Entry e in this) + { + if (e.IsRequired == required) + { + count++; + } + } + Type[] result = new Type[count]; + foreach (Entry e in this) + { + if (e.IsRequired == required) + { + // FXBUG reflection (and ildasm) return custom modifiers in reverse order + // while SRE writes them in the specified order + result[--count] = e.Type; + } + } + return result; + } + + internal Type[] GetRequired() + { + return GetRequiredOrOptional(true); + } + + internal Type[] GetOptional() + { + return GetRequiredOrOptional(false); + } + + internal CustomModifiers Bind(IGenericBinder binder) + { + if (types == null) + { + return this; + } + Type[] result = types; + for (int i = 0; i < types.Length; i++) + { + if (types[i] == MarkerType.ModOpt || types[i] == MarkerType.ModReq) + { + continue; + } + Type type = types[i].BindTypeParameters(binder); + if (!ReferenceEquals(type, types[i])) + { + if (result == types) + { + result = (Type[])types.Clone(); + } + result[i] = type; + } + } + return new CustomModifiers(result); + } + + internal static CustomModifiers Read(ModuleReader module, ByteReader br, IGenericContext context) + { + byte b = br.PeekByte(); + if (!IsCustomModifier(b)) + { + return new CustomModifiers(); + } + List list = new List(); + Type mode = Initial; + do + { + Type cmod = br.ReadByte() == Signature.ELEMENT_TYPE_CMOD_REQD ? MarkerType.ModReq : MarkerType.ModOpt; + if (mode != cmod) + { + mode = cmod; + list.Add(mode); + } + list.Add(Signature.ReadTypeDefOrRefEncoded(module, br, context)); + b = br.PeekByte(); + } + while (IsCustomModifier(b)); + return new CustomModifiers(list.ToArray()); + } + + internal static void Skip(ByteReader br) + { + byte b = br.PeekByte(); + while (IsCustomModifier(b)) + { + br.ReadByte(); + br.ReadCompressedUInt(); + b = br.PeekByte(); + } + } + + internal static CustomModifiers FromReqOpt(Type[] req, Type[] opt) + { + List list = null; + if (opt != null && opt.Length != 0) + { + Debug.Assert(Initial == MarkerType.ModOpt); + list = new List(opt); + } + if (req != null && req.Length != 0) + { + if (list == null) + { + list = new List(); + } + list.Add(MarkerType.ModReq); + list.AddRange(req); + } + if (list == null) + { + return new CustomModifiers(); + } + else + { + return new CustomModifiers(list.ToArray()); + } + } + + private static bool IsCustomModifier(byte b) + { + return b == Signature.ELEMENT_TYPE_CMOD_OPT || b == Signature.ELEMENT_TYPE_CMOD_REQD; + } + + internal static CustomModifiers Combine(CustomModifiers mods1, CustomModifiers mods2) + { + if (mods1.IsEmpty) + { + return mods2; + } + else if (mods2.IsEmpty) + { + return mods1; + } + else + { + Type[] combo = new Type[mods1.types.Length + mods2.types.Length]; + Array.Copy(mods1.types, combo, mods1.types.Length); + Array.Copy(mods2.types, 0, combo, mods1.types.Length, mods2.types.Length); + return new CustomModifiers(combo); + } + } + } +} diff --git a/reflect/Emit/AssemblyBuilder.cs b/reflect/Emit/AssemblyBuilder.cs new file mode 100644 index 0000000..a1ba717 --- /dev/null +++ b/reflect/Emit/AssemblyBuilder.cs @@ -0,0 +1,841 @@ +/* + Copyright (C) 2008-2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Configuration.Assemblies; +using System.IO; +using System.Diagnostics; +using System.Globalization; +using System.Resources; +using System.Security.Cryptography; +using System.Security; +using IKVM.Reflection.Metadata; +using IKVM.Reflection.Impl; +using IKVM.Reflection.Writer; + +namespace IKVM.Reflection.Emit +{ + public sealed class AssemblyBuilder : Assembly + { + private readonly string name; + private ushort majorVersion; + private ushort minorVersion; + private ushort buildVersion; + private ushort revisionVersion; + private string culture; + private AssemblyNameFlags flags; + private AssemblyHashAlgorithm hashAlgorithm; + private StrongNameKeyPair keyPair; + private byte[] publicKey; + internal readonly string dir; + private PEFileKinds fileKind = PEFileKinds.Dll; + private MethodInfo entryPoint; + private VersionInfo versionInfo; + private byte[] win32icon; + private byte[] win32manifest; + private byte[] win32resources; + private string imageRuntimeVersion; + internal int mdStreamVersion = 0x20000; + private Module pseudoManifestModule; + private readonly List resourceFiles = new List(); + private readonly List modules = new List(); + private readonly List addedModules = new List(); + private readonly List customAttributes = new List(); + private readonly List declarativeSecurity = new List(); + private readonly List typeForwarders = new List(); + + struct TypeForwarder + { + internal readonly Type Type; + internal readonly bool IncludeNested; + + internal TypeForwarder(Type type, bool includeNested) + { + this.Type = type; + this.IncludeNested = includeNested; + } + } + + private struct ResourceFile + { + internal string Name; + internal string FileName; + internal ResourceAttributes Attributes; +#if !CORECLR + internal ResourceWriter Writer; +#endif + } + + internal AssemblyBuilder(Universe universe, AssemblyName name, string dir, IEnumerable customAttributes) + : base(universe) + { + this.name = name.Name; + SetVersionHelper(name.Version); + if (!string.IsNullOrEmpty(name.Culture)) + { + this.culture = name.Culture; + } + this.flags = name.RawFlags; + this.hashAlgorithm = name.HashAlgorithm; + if (this.hashAlgorithm == AssemblyHashAlgorithm.None) + { + this.hashAlgorithm = AssemblyHashAlgorithm.SHA1; + } + this.keyPair = name.KeyPair; + if (this.keyPair != null) + { + this.publicKey = this.keyPair.PublicKey; + } + else + { + byte[] publicKey = name.GetPublicKey(); + if (publicKey != null && publicKey.Length != 0) + { + this.publicKey = (byte[])publicKey.Clone(); + } + } + this.dir = dir ?? "."; + if (customAttributes != null) + { + this.customAttributes.AddRange(customAttributes); + } + if (universe.HasMscorlib && !universe.Mscorlib.__IsMissing && universe.Mscorlib.ImageRuntimeVersion != null) + { + this.imageRuntimeVersion = universe.Mscorlib.ImageRuntimeVersion; + } + else + { + this.imageRuntimeVersion = typeof(object).Assembly.ImageRuntimeVersion; + } + universe.RegisterDynamicAssembly(this); + } + + private void SetVersionHelper(Version version) + { + if (version == null) + { + majorVersion = 0; + minorVersion = 0; + buildVersion = 0; + revisionVersion = 0; + } + else + { + majorVersion = (ushort)version.Major; + minorVersion = (ushort)version.Minor; + buildVersion = version.Build == -1 ? (ushort)0 : (ushort)version.Build; + revisionVersion = version.Revision == -1 ? (ushort)0 : (ushort)version.Revision; + } + } + + private void Rename(AssemblyName oldName) + { + this.fullName = null; + universe.RenameAssembly(this, oldName); + } + + public void __SetAssemblyVersion(Version version) + { + AssemblyName oldName = GetName(); + SetVersionHelper(version); + Rename(oldName); + } + + public void __SetAssemblyCulture(string cultureName) + { + AssemblyName oldName = GetName(); + this.culture = cultureName; + Rename(oldName); + } + + public void __SetAssemblyKeyPair(StrongNameKeyPair keyPair) + { + AssemblyName oldName = GetName(); + this.keyPair = keyPair; + if (keyPair != null) + { + this.publicKey = keyPair.PublicKey; + } + Rename(oldName); + } + + // this is used in combination with delay signing + public void __SetAssemblyPublicKey(byte[] publicKey) + { + AssemblyName oldName = GetName(); + this.publicKey = publicKey == null ? null : (byte[])publicKey.Clone(); + Rename(oldName); + } + + public void __SetAssemblyAlgorithmId(AssemblyHashAlgorithm hashAlgorithm) + { + this.hashAlgorithm = hashAlgorithm; + } + + [Obsolete("Use __AssemblyFlags property instead.")] + public void __SetAssemblyFlags(AssemblyNameFlags flags) + { + this.__AssemblyFlags = flags; + } + + protected override AssemblyNameFlags GetAssemblyFlags() + { + return flags; + } + + public new AssemblyNameFlags __AssemblyFlags + { + get { return flags; } + set + { + AssemblyName oldName = GetName(); + this.flags = value; + Rename(oldName); + } + } + + internal string Name + { + get { return name; } + } + + public override AssemblyName GetName() + { + AssemblyName n = new AssemblyName(); + n.Name = name; + n.Version = new Version(majorVersion, minorVersion, buildVersion, revisionVersion); + n.Culture = culture ?? ""; + n.HashAlgorithm = hashAlgorithm; + n.RawFlags = flags; + n.SetPublicKey(publicKey != null ? (byte[])publicKey.Clone() : Empty.Array); + n.KeyPair = keyPair; + return n; + } + + public override string Location + { + get { throw new NotSupportedException(); } + } + + public ModuleBuilder DefineDynamicModule(string name, string fileName) + { + return DefineDynamicModule(name, fileName, false); + } + + public ModuleBuilder DefineDynamicModule(string name, string fileName, bool emitSymbolInfo) + { + ModuleBuilder module = new ModuleBuilder(this, name, fileName, emitSymbolInfo); + modules.Add(module); + return module; + } + + public ModuleBuilder GetDynamicModule(string name) + { + foreach (ModuleBuilder module in modules) + { + if (module.Name == name) + { + return module; + } + } + return null; + } + + public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) + { + SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute)); + } + + public void SetCustomAttribute(CustomAttributeBuilder customBuilder) + { + customAttributes.Add(customBuilder); + } + + public void __AddDeclarativeSecurity(CustomAttributeBuilder customBuilder) + { + declarativeSecurity.Add(customBuilder); + } + + public void __AddTypeForwarder(Type type) + { + __AddTypeForwarder(type, true); + } + + public void __AddTypeForwarder(Type type, bool includeNested) + { + typeForwarders.Add(new TypeForwarder(type, includeNested)); + } + + public void SetEntryPoint(MethodInfo entryMethod) + { + SetEntryPoint(entryMethod, PEFileKinds.ConsoleApplication); + } + + public void SetEntryPoint(MethodInfo entryMethod, PEFileKinds fileKind) + { + this.entryPoint = entryMethod; + this.fileKind = fileKind; + } + + public void __Save(Stream stream, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine) + { + if (!stream.CanRead || !stream.CanWrite || !stream.CanSeek || stream.Position != 0) + { + throw new ArgumentException("Stream must support read/write/seek and current position must be zero.", "stream"); + } + if (modules.Count != 1) + { + throw new NotSupportedException("Saving to a stream is only supported for single module assemblies."); + } + SaveImpl(modules[0].fileName, stream, portableExecutableKind, imageFileMachine); + } + + public void Save(string assemblyFileName) + { + Save(assemblyFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386); + } + + public void Save(string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine) + { + SaveImpl(assemblyFileName, null, portableExecutableKind, imageFileMachine); + } + + private void SaveImpl(string assemblyFileName, Stream streamOrNull, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine) + { + ModuleBuilder manifestModule = null; + + foreach (ModuleBuilder moduleBuilder in modules) + { + moduleBuilder.SetIsSaved(); + moduleBuilder.PopulatePropertyAndEventTables(); + + if (manifestModule == null + && string.Compare(moduleBuilder.fileName, assemblyFileName, StringComparison.OrdinalIgnoreCase) == 0) + { + manifestModule = moduleBuilder; + } + } + + if (manifestModule == null) + { + manifestModule = DefineDynamicModule("RefEmit_OnDiskManifestModule", assemblyFileName, false); + } + + AssemblyTable.Record assemblyRecord = new AssemblyTable.Record(); + assemblyRecord.HashAlgId = (int)hashAlgorithm; + assemblyRecord.Name = manifestModule.Strings.Add(name); + assemblyRecord.MajorVersion = majorVersion; + assemblyRecord.MinorVersion = minorVersion; + assemblyRecord.BuildNumber = buildVersion; + assemblyRecord.RevisionNumber = revisionVersion; + if (publicKey != null) + { + assemblyRecord.PublicKey = manifestModule.Blobs.Add(ByteBuffer.Wrap(publicKey)); + assemblyRecord.Flags = (int)(flags | AssemblyNameFlags.PublicKey); + } + else + { + assemblyRecord.Flags = (int)(flags & ~AssemblyNameFlags.PublicKey); + } + if (culture != null) + { + assemblyRecord.Culture = manifestModule.Strings.Add(culture); + } + manifestModule.AssemblyTable.AddRecord(assemblyRecord); + + ResourceSection unmanagedResources = versionInfo != null || win32icon != null || win32manifest != null || win32resources != null + ? new ResourceSection() + : null; + + if (versionInfo != null) + { + versionInfo.SetName(GetName()); + versionInfo.SetFileName(assemblyFileName); + foreach (CustomAttributeBuilder cab in customAttributes) + { + // .NET doesn't support copying blob custom attributes into the version info + if (!cab.HasBlob || universe.DecodeVersionInfoAttributeBlobs) + { + versionInfo.SetAttribute(this, cab); + } + } + ByteBuffer versionInfoData = new ByteBuffer(512); + versionInfo.Write(versionInfoData); + unmanagedResources.AddVersionInfo(versionInfoData); + } + + if (win32icon != null) + { + unmanagedResources.AddIcon(win32icon); + } + + if (win32manifest != null) + { + unmanagedResources.AddManifest(win32manifest, fileKind == PEFileKinds.Dll ? (ushort)2 : (ushort)1); + } + + if (win32resources != null) + { + unmanagedResources.ExtractResources(win32resources); + } + + foreach (CustomAttributeBuilder cab in customAttributes) + { + // we intentionally don't filter out the version info (pseudo) custom attributes (to be compatible with .NET) + manifestModule.SetCustomAttribute(0x20000001, cab); + } + + manifestModule.AddDeclarativeSecurity(0x20000001, declarativeSecurity); + + foreach (TypeForwarder fwd in typeForwarders) + { + manifestModule.AddTypeForwarder(fwd.Type, fwd.IncludeNested); + } + + foreach (ResourceFile resfile in resourceFiles) + { +#if !CORECLR + if (resfile.Writer != null) + { + resfile.Writer.Generate(); + resfile.Writer.Close(); + } +#endif + int fileToken = AddFile(manifestModule, resfile.FileName, 1 /*ContainsNoMetaData*/); + ManifestResourceTable.Record rec = new ManifestResourceTable.Record(); + rec.Offset = 0; + rec.Flags = (int)resfile.Attributes; + rec.Name = manifestModule.Strings.Add(resfile.Name); + rec.Implementation = fileToken; + manifestModule.ManifestResource.AddRecord(rec); + } + + int entryPointToken = 0; + + foreach (ModuleBuilder moduleBuilder in modules) + { + moduleBuilder.FillAssemblyRefTable(); + moduleBuilder.EmitResources(); + if (moduleBuilder != manifestModule) + { + int fileToken; + if (entryPoint != null && entryPoint.Module == moduleBuilder) + { + ModuleWriter.WriteModule(null, null, moduleBuilder, fileKind, portableExecutableKind, imageFileMachine, moduleBuilder.unmanagedResources, entryPoint.MetadataToken); + entryPointToken = fileToken = AddFile(manifestModule, moduleBuilder.fileName, 0 /*ContainsMetaData*/); + } + else + { + ModuleWriter.WriteModule(null, null, moduleBuilder, fileKind, portableExecutableKind, imageFileMachine, moduleBuilder.unmanagedResources, 0); + fileToken = AddFile(manifestModule, moduleBuilder.fileName, 0 /*ContainsMetaData*/); + } + moduleBuilder.ExportTypes(fileToken, manifestModule); + } + moduleBuilder.CloseResources(); + } + + foreach (Module module in addedModules) + { + int fileToken = AddFile(manifestModule, module.FullyQualifiedName, 0 /*ContainsMetaData*/); + module.ExportTypes(fileToken, manifestModule); + } + + if (entryPointToken == 0 && entryPoint != null) + { + entryPointToken = entryPoint.MetadataToken; + } + + // finally, write the manifest module + ModuleWriter.WriteModule(keyPair, publicKey, manifestModule, fileKind, portableExecutableKind, imageFileMachine, unmanagedResources ?? manifestModule.unmanagedResources, entryPointToken, streamOrNull); + } + + private int AddFile(ModuleBuilder manifestModule, string fileName, int flags) + { + SHA1Managed hash = new SHA1Managed(); + string fullPath = fileName; + if (dir != null) + { + fullPath = Path.Combine(dir, fileName); + } + using (FileStream fs = new FileStream(fullPath, FileMode.Open, FileAccess.Read)) + { + using (CryptoStream cs = new CryptoStream(Stream.Null, hash, CryptoStreamMode.Write)) + { + byte[] buf = new byte[8192]; + ModuleWriter.HashChunk(fs, cs, buf, (int)fs.Length); + } + } + return manifestModule.__AddModule(flags, Path.GetFileName(fileName), hash.Hash); + } + + public void AddResourceFile(string name, string fileName) + { + AddResourceFile(name, fileName, ResourceAttributes.Public); + } + + public void AddResourceFile(string name, string fileName, ResourceAttributes attribs) + { + ResourceFile resfile = new ResourceFile(); + resfile.Name = name; + resfile.FileName = fileName; + resfile.Attributes = attribs; + resourceFiles.Add(resfile); + } + +#if !CORECLR + public IResourceWriter DefineResource(string name, string description, string fileName) + { + return DefineResource(name, description, fileName, ResourceAttributes.Public); + } + + public IResourceWriter DefineResource(string name, string description, string fileName, ResourceAttributes attribute) + { + // FXBUG we ignore the description, because there is no such thing + + string fullPath = fileName; + if (dir != null) + { + fullPath = Path.Combine(dir, fileName); + } + ResourceWriter rw = new ResourceWriter(fullPath); + ResourceFile resfile; + resfile.Name = name; + resfile.FileName = fileName; + resfile.Attributes = attribute; + resfile.Writer = rw; + resourceFiles.Add(resfile); + return rw; + } +#endif + + public void DefineVersionInfoResource() + { + if (versionInfo != null || win32resources != null) + { + throw new ArgumentException("Native resource has already been defined."); + } + versionInfo = new VersionInfo(); + } + + public void DefineVersionInfoResource(string product, string productVersion, string company, string copyright, string trademark) + { + if (versionInfo != null || win32resources != null) + { + throw new ArgumentException("Native resource has already been defined."); + } + versionInfo = new VersionInfo(); + versionInfo.product = product; + versionInfo.informationalVersion = productVersion; + versionInfo.company = company; + versionInfo.copyright = copyright; + versionInfo.trademark = trademark; + } + + public void __DefineIconResource(byte[] iconFile) + { + if (win32icon != null || win32resources != null) + { + throw new ArgumentException("Native resource has already been defined."); + } + win32icon = (byte[])iconFile.Clone(); + } + + public void __DefineManifestResource(byte[] manifest) + { + if (win32manifest != null || win32resources != null) + { + throw new ArgumentException("Native resource has already been defined."); + } + win32manifest = (byte[])manifest.Clone(); + } + + public void __DefineUnmanagedResource(byte[] resource) + { + if (versionInfo != null || win32icon != null || win32manifest != null || win32resources != null) + { + throw new ArgumentException("Native resource has already been defined."); + } + // The standard .NET DefineUnmanagedResource(byte[]) is useless, because it embeds "resource" (as-is) as the .rsrc section, + // but it doesn't set the PE file Resource Directory entry to point to it. That's why we have a renamed version, which behaves + // like DefineUnmanagedResource(string). + win32resources = (byte[])resource.Clone(); + } + + public void DefineUnmanagedResource(string resourceFileName) + { + // This method reads the specified resource file (Win32 .res file) and converts it into the appropriate format and embeds it in the .rsrc section, + // also setting the Resource Directory entry. + __DefineUnmanagedResource(File.ReadAllBytes(resourceFileName)); + } + + public override Type[] GetTypes() + { + List list = new List(); + foreach (ModuleBuilder module in modules) + { + module.GetTypesImpl(list); + } + foreach (Module module in addedModules) + { + module.GetTypesImpl(list); + } + return list.ToArray(); + } + + internal override Type FindType(TypeName typeName) + { + foreach (ModuleBuilder mb in modules) + { + Type type = mb.FindType(typeName); + if (type != null) + { + return type; + } + } + foreach (Module module in addedModules) + { + Type type = module.FindType(typeName); + if (type != null) + { + return type; + } + } + return null; + } + + internal override Type FindTypeIgnoreCase(TypeName lowerCaseName) + { + foreach (ModuleBuilder mb in modules) + { + Type type = mb.FindTypeIgnoreCase(lowerCaseName); + if (type != null) + { + return type; + } + } + foreach (Module module in addedModules) + { + Type type = module.FindTypeIgnoreCase(lowerCaseName); + if (type != null) + { + return type; + } + } + return null; + } + + public override string ImageRuntimeVersion + { + get { return imageRuntimeVersion; } + } + + public void __SetImageRuntimeVersion(string imageRuntimeVersion, int mdStreamVersion) + { + this.imageRuntimeVersion = imageRuntimeVersion; + this.mdStreamVersion = mdStreamVersion; + } + + public override Module ManifestModule + { + get + { + if (pseudoManifestModule == null) + { + pseudoManifestModule = new ManifestModule(this); + } + return pseudoManifestModule; + } + } + + public override MethodInfo EntryPoint + { + get { return entryPoint; } + } + + public override AssemblyName[] GetReferencedAssemblies() + { + return Empty.Array; + } + + public override Module[] GetLoadedModules(bool getResourceModules) + { + return GetModules(getResourceModules); + } + + public override Module[] GetModules(bool getResourceModules) + { + List list = new List(); + foreach (ModuleBuilder module in modules) + { + if (getResourceModules || !module.IsResource()) + { + list.Add(module); + } + } + foreach (Module module in addedModules) + { + if (getResourceModules || !module.IsResource()) + { + list.Add(module); + } + } + return list.ToArray(); + } + + public override Module GetModule(string name) + { + foreach (ModuleBuilder module in modules) + { + if (module.Name.Equals(name, StringComparison.OrdinalIgnoreCase)) + { + return module; + } + } + foreach (Module module in addedModules) + { + if (module.Name.Equals(name, StringComparison.OrdinalIgnoreCase)) + { + return module; + } + } + return null; + } + + public Module __AddModule(RawModule module) + { + Module mod = module.ToModule(this); + addedModules.Add(mod); + return mod; + } + + public override ManifestResourceInfo GetManifestResourceInfo(string resourceName) + { + throw new NotSupportedException(); + } + + public override string[] GetManifestResourceNames() + { + throw new NotSupportedException(); + } + + public override Stream GetManifestResourceStream(string resourceName) + { + throw new NotSupportedException(); + } + + public override bool IsDynamic + { + get { return true; } + } + + public static AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access) + { + return new Universe().DefineDynamicAssembly(name, access); + } + + public static AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access, IEnumerable assemblyAttributes) + { + return new Universe().DefineDynamicAssembly(name, access, assemblyAttributes); + } + + internal override IList GetCustomAttributesData(Type attributeType) + { + List list = new List(); + foreach (CustomAttributeBuilder cab in customAttributes) + { + if (attributeType == null || attributeType.IsAssignableFrom(cab.Constructor.DeclaringType)) + { + list.Add(cab.ToData(this)); + } + } + return list; + } + + internal bool IsWindowsRuntime + { + get { return (flags & (AssemblyNameFlags)0x200) != 0; } + } + } + + sealed class ManifestModule : NonPEModule + { + private readonly AssemblyBuilder assembly; + private readonly Guid guid = Guid.NewGuid(); + + internal ManifestModule(AssemblyBuilder assembly) + : base(assembly.universe) + { + this.assembly = assembly; + } + + public override int MDStreamVersion + { + get { return assembly.mdStreamVersion; } + } + + public override Assembly Assembly + { + get { return assembly; } + } + + internal override Type FindType(TypeName typeName) + { + return null; + } + + internal override Type FindTypeIgnoreCase(TypeName lowerCaseName) + { + return null; + } + + internal override void GetTypesImpl(List list) + { + } + + public override string FullyQualifiedName + { + get { return Path.Combine(assembly.dir, "RefEmit_InMemoryManifestModule"); } + } + + public override string Name + { + get { return ""; } + } + + public override Guid ModuleVersionId + { + get { return guid; } + } + + public override string ScopeName + { + get { return "RefEmit_InMemoryManifestModule"; } + } + + protected override Exception NotSupportedException() + { + return new InvalidOperationException(); + } + } +} diff --git a/reflect/Emit/ConstructorBuilder.cs b/reflect/Emit/ConstructorBuilder.cs new file mode 100644 index 0000000..d54041f --- /dev/null +++ b/reflect/Emit/ConstructorBuilder.cs @@ -0,0 +1,143 @@ +/* + Copyright (C) 2008-2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; + +namespace IKVM.Reflection.Emit +{ + public sealed class ConstructorBuilder : ConstructorInfo + { + private readonly MethodBuilder methodBuilder; + + internal ConstructorBuilder(MethodBuilder mb) + { + this.methodBuilder = mb; + } + + public override bool Equals(object obj) + { + ConstructorBuilder other = obj as ConstructorBuilder; + return other != null && other.methodBuilder.Equals(methodBuilder); + } + + public override int GetHashCode() + { + return methodBuilder.GetHashCode(); + } + + public void __SetSignature(Type returnType, CustomModifiers returnTypeCustomModifiers, Type[] parameterTypes, CustomModifiers[] parameterTypeCustomModifiers) + { + methodBuilder.__SetSignature(returnType, returnTypeCustomModifiers, parameterTypes, parameterTypeCustomModifiers); + } + + [Obsolete("Please use __SetSignature(Type, CustomModifiers, Type[], CustomModifiers[]) instead.")] + public void __SetSignature(Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers) + { + methodBuilder.SetSignature(returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers); + } + + public ParameterBuilder DefineParameter(int position, ParameterAttributes attributes, string strParamName) + { + return methodBuilder.DefineParameter(position, attributes, strParamName); + } + + public void SetCustomAttribute(CustomAttributeBuilder customBuilder) + { + methodBuilder.SetCustomAttribute(customBuilder); + } + + public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) + { + methodBuilder.SetCustomAttribute(con, binaryAttribute); + } + + public void __AddDeclarativeSecurity(CustomAttributeBuilder customBuilder) + { + methodBuilder.__AddDeclarativeSecurity(customBuilder); + } + +#if !CORECLR + public void AddDeclarativeSecurity(System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet) + { + methodBuilder.AddDeclarativeSecurity(securityAction, permissionSet); + } +#endif + + public void SetImplementationFlags(MethodImplAttributes attributes) + { + methodBuilder.SetImplementationFlags(attributes); + } + + public ILGenerator GetILGenerator() + { + return methodBuilder.GetILGenerator(); + } + + public ILGenerator GetILGenerator(int streamSize) + { + return methodBuilder.GetILGenerator(streamSize); + } + + public void __ReleaseILGenerator() + { + methodBuilder.__ReleaseILGenerator(); + } + + public Type ReturnType + { + get { return methodBuilder.ReturnType; } + } + + public Module GetModule() + { + return methodBuilder.GetModule(); + } + + public MethodToken GetToken() + { + return methodBuilder.GetToken(); + } + + public bool InitLocals + { + get { return methodBuilder.InitLocals; } + set { methodBuilder.InitLocals = value; } + } + + public void SetMethodBody(byte[] il, int maxStack, byte[] localSignature, IEnumerable exceptionHandlers, IEnumerable tokenFixups) + { + methodBuilder.SetMethodBody(il, maxStack, localSignature, exceptionHandlers, tokenFixups); + } + + internal override MethodInfo GetMethodInfo() + { + return methodBuilder; + } + + internal override MethodInfo GetMethodOnTypeDefinition() + { + return methodBuilder; + } + } +} diff --git a/reflect/Emit/CustomAttributeBuilder.cs b/reflect/Emit/CustomAttributeBuilder.cs new file mode 100644 index 0000000..9387524 --- /dev/null +++ b/reflect/Emit/CustomAttributeBuilder.cs @@ -0,0 +1,752 @@ +/* + Copyright (C) 2008-2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.IO; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using IKVM.Reflection.Writer; + +namespace IKVM.Reflection.Emit +{ + public sealed class CustomAttributeBuilder + { + internal static readonly ConstructorInfo LegacyPermissionSet = new ConstructorBuilder(null); + private readonly ConstructorInfo con; + private readonly byte[] blob; + private readonly object[] constructorArgs; + private readonly PropertyInfo[] namedProperties; + private readonly object[] propertyValues; + private readonly FieldInfo[] namedFields; + private readonly object[] fieldValues; + + internal CustomAttributeBuilder(ConstructorInfo con, byte[] blob) + { + this.con = con; + this.blob = blob; + } + + private CustomAttributeBuilder(ConstructorInfo con, int securityAction, byte[] blob) + { + this.con = con; + this.blob = blob; + this.constructorArgs = new object[] { securityAction }; + } + + public CustomAttributeBuilder(ConstructorInfo con, object[] constructorArgs) + : this(con, constructorArgs, null, null, null,null) + { + } + + public CustomAttributeBuilder(ConstructorInfo con, object[] constructorArgs, FieldInfo[] namedFields, object[] fieldValues) + : this(con, constructorArgs, null, null, namedFields, fieldValues) + { + } + + public CustomAttributeBuilder(ConstructorInfo con, object[] constructorArgs, PropertyInfo[] namedProperties, object[] propertyValues) + : this(con, constructorArgs, namedProperties, propertyValues, null, null) + { + } + + public CustomAttributeBuilder(ConstructorInfo con, object[] constructorArgs, PropertyInfo[] namedProperties, object[] propertyValues, FieldInfo[] namedFields, object[] fieldValues) + { + this.con = con; + this.constructorArgs = constructorArgs; + this.namedProperties = namedProperties; + this.propertyValues = propertyValues; + this.namedFields = namedFields; + this.fieldValues = fieldValues; + } + + public static CustomAttributeBuilder __FromBlob(ConstructorInfo con, byte[] blob) + { + return new CustomAttributeBuilder(con, blob); + } + + public static CustomAttributeBuilder __FromBlob(ConstructorInfo con, int securityAction, byte[] blob) + { + return new CustomAttributeBuilder(con, securityAction, blob); + } + + public static CustomAttributeTypedArgument __MakeTypedArgument(Type type, object value) + { + return new CustomAttributeTypedArgument(type, value); + } + + private sealed class BlobWriter + { + private readonly Assembly assembly; + private readonly CustomAttributeBuilder cab; + private readonly ByteBuffer bb; + + internal BlobWriter(Assembly assembly, CustomAttributeBuilder cab, ByteBuffer bb) + { + this.assembly = assembly; + this.cab = cab; + this.bb = bb; + } + + internal void WriteCustomAttributeBlob() + { + // prolog + WriteUInt16(1); + ParameterInfo[] pi = cab.con.GetParameters(); + for (int i = 0; i < pi.Length; i++) + { + WriteFixedArg(pi[i].ParameterType, cab.constructorArgs[i]); + } + WriteNamedArguments(false); + } + + internal void WriteNamedArguments(bool forDeclSecurity) + { + // NumNamed + int named = 0; + if (cab.namedFields != null) + { + named += cab.namedFields.Length; + } + if (cab.namedProperties != null) + { + named += cab.namedProperties.Length; + } + if (forDeclSecurity) + { + WritePackedLen(named); + } + else + { + WriteUInt16((ushort)named); + } + if (cab.namedFields != null) + { + for (int i = 0; i < cab.namedFields.Length; i++) + { + WriteNamedArg(0x53, cab.namedFields[i].FieldType, cab.namedFields[i].Name, cab.fieldValues[i]); + } + } + if (cab.namedProperties != null) + { + for (int i = 0; i < cab.namedProperties.Length; i++) + { + WriteNamedArg(0x54, cab.namedProperties[i].PropertyType, cab.namedProperties[i].Name, cab.propertyValues[i]); + } + } + } + + private void WriteNamedArg(byte fieldOrProperty, Type type, string name, object value) + { + WriteByte(fieldOrProperty); + WriteFieldOrPropType(type); + WriteString(name); + WriteFixedArg(type, value); + } + + private void WriteByte(byte value) + { + bb.Write(value); + } + + private void WriteUInt16(ushort value) + { + bb.Write(value); + } + + private void WriteInt32(int value) + { + bb.Write(value); + } + + private void WriteFixedArg(Type type, object value) + { + Universe u = assembly.universe; + if (type == u.System_String) + { + WriteString((string)value); + } + else if (type == u.System_Boolean) + { + WriteByte((bool)value ? (byte)1 : (byte)0); + } + else if (type == u.System_Char) + { + WriteUInt16((char)value); + } + else if (type == u.System_SByte) + { + WriteByte((byte)(sbyte)value); + } + else if (type == u.System_Byte) + { + WriteByte((byte)value); + } + else if (type == u.System_Int16) + { + WriteUInt16((ushort)(short)value); + } + else if (type == u.System_UInt16) + { + WriteUInt16((ushort)value); + } + else if (type == u.System_Int32) + { + WriteInt32((int)value); + } + else if (type == u.System_UInt32) + { + WriteInt32((int)(uint)value); + } + else if (type == u.System_Int64) + { + WriteInt64((long)value); + } + else if (type == u.System_UInt64) + { + WriteInt64((long)(ulong)value); + } + else if (type == u.System_Single) + { + WriteSingle((float)value); + } + else if (type == u.System_Double) + { + WriteDouble((double)value); + } + else if (type == u.System_Type) + { + WriteTypeName((Type)value); + } + else if (type == u.System_Object) + { + if (value == null) + { + type = u.System_String; + } + else if (value is Type) + { + // value.GetType() would return a subclass of Type, but we don't want to deal with that + type = u.System_Type; + } + else if (value is CustomAttributeTypedArgument) + { + CustomAttributeTypedArgument cta = (CustomAttributeTypedArgument)value; + value = cta.Value; + type = cta.ArgumentType; + } + else + { + type = u.Import(value.GetType()); + } + WriteFieldOrPropType(type); + WriteFixedArg(type, value); + } + else if (type.IsArray) + { + if (value == null) + { + WriteInt32(-1); + } + else + { + Array array = (Array)value; + Type elemType = type.GetElementType(); + WriteInt32(array.Length); + foreach (object val in array) + { + WriteFixedArg(elemType, val); + } + } + } + else if (type.IsEnum) + { + WriteFixedArg(type.GetEnumUnderlyingTypeImpl(), value); + } + else + { + throw new ArgumentException(); + } + } + + private void WriteInt64(long value) + { + bb.Write(value); + } + + private void WriteSingle(float value) + { + bb.Write(value); + } + + private void WriteDouble(double value) + { + bb.Write(value); + } + + private void WriteTypeName(Type type) + { + string name = null; + if (type != null) + { + StringBuilder sb = new StringBuilder(); + GetTypeName(sb, type, false); + name = sb.ToString(); + } + WriteString(name); + } + + private void GetTypeName(StringBuilder sb, Type type, bool isTypeParam) + { + bool v1 = !assembly.ManifestModule.__IsMissing && assembly.ManifestModule.MDStreamVersion < 0x20000; + bool includeAssemblyName = type.Assembly != assembly && (!v1 || type.Assembly != type.Module.universe.Mscorlib); + if (isTypeParam && includeAssemblyName) + { + sb.Append('['); + } + GetTypeNameImpl(sb, type); + if (includeAssemblyName) + { + if (v1) + { + sb.Append(','); + } + else + { + sb.Append(", "); + } + if (isTypeParam) + { + sb.Append(type.Assembly.FullName.Replace("]", "\\]")).Append(']'); + } + else + { + sb.Append(type.Assembly.FullName); + } + } + } + + private void GetTypeNameImpl(StringBuilder sb, Type type) + { + if (type.HasElementType) + { + GetTypeNameImpl(sb, type.GetElementType()); + sb.Append(((ElementHolderType)type).GetSuffix()); + } + else if (type.IsConstructedGenericType) + { + sb.Append(type.GetGenericTypeDefinition().FullName); + sb.Append('['); + string sep = ""; + foreach (Type typeParam in type.GetGenericArguments()) + { + sb.Append(sep); + GetTypeName(sb, typeParam, true); + sep = ","; + } + sb.Append(']'); + } + else + { + sb.Append(type.FullName); + } + } + + private void WriteString(string val) + { + bb.Write(val); + } + + private void WritePackedLen(int len) + { + bb.WriteCompressedUInt(len); + } + + private void WriteFieldOrPropType(Type type) + { + Universe u = type.Module.universe; + if (type == u.System_Type) + { + WriteByte(0x50); + } + else if (type == u.System_Object) + { + WriteByte(0x51); + } + else if (type == u.System_Boolean) + { + WriteByte(0x02); + } + else if (type == u.System_Char) + { + WriteByte(0x03); + } + else if (type == u.System_SByte) + { + WriteByte(0x04); + } + else if (type == u.System_Byte) + { + WriteByte(0x05); + } + else if (type == u.System_Int16) + { + WriteByte(0x06); + } + else if (type == u.System_UInt16) + { + WriteByte(0x07); + } + else if (type == u.System_Int32) + { + WriteByte(0x08); + } + else if (type == u.System_UInt32) + { + WriteByte(0x09); + } + else if (type == u.System_Int64) + { + WriteByte(0x0A); + } + else if (type == u.System_UInt64) + { + WriteByte(0x0B); + } + else if (type == u.System_Single) + { + WriteByte(0x0C); + } + else if (type == u.System_Double) + { + WriteByte(0x0D); + } + else if (type == u.System_String) + { + WriteByte(0x0E); + } + else if (type.IsArray) + { + WriteByte(0x1D); + WriteFieldOrPropType(type.GetElementType()); + } + else if (type.IsEnum) + { + WriteByte(0x55); + WriteTypeName(type); + } + else + { + throw new ArgumentException(); + } + } + } + + internal ConstructorInfo Constructor + { + get { return con; } + } + + internal int WriteBlob(ModuleBuilder moduleBuilder) + { + ByteBuffer bb; + if (blob != null) + { + bb = ByteBuffer.Wrap(blob); + } + else + { + bb = new ByteBuffer(100); + BlobWriter bw = new BlobWriter(moduleBuilder.Assembly, this, bb); + bw.WriteCustomAttributeBlob(); + } + return moduleBuilder.Blobs.Add(bb); + } + + internal object GetConstructorArgument(int pos) + { + return constructorArgs[pos]; + } + + internal int ConstructorArgumentCount + { + get { return constructorArgs == null ? 0 : constructorArgs.Length; } + } + + internal T? GetFieldValue(string name) where T : struct + { + object val = GetFieldValue(name); + if (val is T) + { + return (T)val; + } + else if (val != null) + { + if (typeof(T).IsEnum) + { + Debug.Assert(Enum.GetUnderlyingType(typeof(T)) == val.GetType()); + return (T)Enum.ToObject(typeof(T), val); + } + else + { + Debug.Assert(Enum.GetUnderlyingType(val.GetType()) == typeof(T)); + return (T)Convert.ChangeType(val, typeof(T)); + } + } + else + { + return null; + } + } + + internal object GetFieldValue(string name) + { + if (namedFields != null) + { + for (int i = 0; i < namedFields.Length; i++) + { + if (namedFields[i].Name == name) + { + return fieldValues[i]; + } + } + } + return null; + } + + internal bool IsLegacyDeclSecurity + { + get + { + return ReferenceEquals(con, LegacyPermissionSet) + || (con.DeclaringType == con.Module.universe.System_Security_Permissions_PermissionSetAttribute + && blob == null + && (namedFields == null || namedFields.Length == 0) + && namedProperties != null + && namedProperties.Length == 1 + && namedProperties[0].Name == "XML" + && propertyValues[0] is string); + } + } + + internal int WriteLegacyDeclSecurityBlob(ModuleBuilder moduleBuilder) + { + if (blob != null) + { + return moduleBuilder.Blobs.Add(ByteBuffer.Wrap(blob)); + } + else + { + return moduleBuilder.Blobs.Add(ByteBuffer.Wrap(Encoding.Unicode.GetBytes((string)propertyValues[0]))); + } + } + + internal void WriteNamedArgumentsForDeclSecurity(ModuleBuilder moduleBuilder, ByteBuffer bb) + { + if (blob != null) + { + bb.Write(blob); + } + else + { + BlobWriter bw = new BlobWriter(moduleBuilder.Assembly, this, bb); + bw.WriteNamedArguments(true); + } + } + + internal CustomAttributeData ToData(Assembly asm) + { + if (blob != null) + { + if (constructorArgs != null) + { + return new CustomAttributeData(asm, con, (int)constructorArgs[0], blob, -1); + } + return new CustomAttributeData(asm, con, new IKVM.Reflection.Reader.ByteReader(blob, 0, blob.Length)); + } + else + { + List namedArgs = new List(); + if (namedProperties != null) + { + for (int i = 0; i < namedProperties.Length; i++) + { + namedArgs.Add(new CustomAttributeNamedArgument(namedProperties[i], RewrapValue(namedProperties[i].PropertyType, propertyValues[i]))); + } + } + if (namedFields != null) + { + for (int i = 0; i < namedFields.Length; i++) + { + namedArgs.Add(new CustomAttributeNamedArgument(namedFields[i], RewrapValue(namedFields[i].FieldType, fieldValues[i]))); + } + } + List args = new List(constructorArgs.Length); + ParameterInfo[] parameters = this.Constructor.GetParameters(); + for (int i = 0; i < constructorArgs.Length; i++) + { + args.Add(RewrapValue(parameters[i].ParameterType, constructorArgs[i])); + } + return new CustomAttributeData(asm.ManifestModule, con, args, namedArgs); + } + } + + private static CustomAttributeTypedArgument RewrapValue(Type type, object value) + { + if (value is Array) + { + Array array = (Array)value; + Type arrayType = type.Module.universe.Import(array.GetType()); + return RewrapArray(arrayType, array); + } + else if (value is CustomAttributeTypedArgument) + { + CustomAttributeTypedArgument arg = (CustomAttributeTypedArgument)value; + if (arg.Value is Array) + { + return RewrapArray(arg.ArgumentType, (Array)arg.Value); + } + return arg; + } + else + { + return new CustomAttributeTypedArgument(type, value); + } + } + + private static CustomAttributeTypedArgument RewrapArray(Type arrayType, Array array) + { + Type elementType = arrayType.GetElementType(); + CustomAttributeTypedArgument[] newArray = new CustomAttributeTypedArgument[array.Length]; + for (int i = 0; i < newArray.Length; i++) + { + newArray[i] = RewrapValue(elementType, array.GetValue(i)); + } + return new CustomAttributeTypedArgument(arrayType, newArray); + } + + internal bool HasBlob + { + get { return blob != null; } + } + + internal CustomAttributeBuilder DecodeBlob(Assembly asm) + { + if (blob == null) + { + return this; + } + else + { + return ToData(asm).__ToBuilder(); + } + } + + internal byte[] GetBlob(Assembly asm) + { + ByteBuffer bb = new ByteBuffer(100); + BlobWriter bw = new BlobWriter(asm, this, bb); + bw.WriteCustomAttributeBlob(); + return bb.ToArray(); + } + + internal KnownCA KnownCA + { + get + { + TypeName typeName = con.DeclaringType.TypeName; + switch (typeName.Namespace) + { + case "System": + switch (typeName.Name) + { + case "SerializableAttribute": + return KnownCA.SerializableAttribute; + case "NonSerializedAttribute": + return KnownCA.NonSerializedAttribute; + } + break; + case "System.Runtime.CompilerServices": + switch (typeName.Name) + { + case "MethodImplAttribute": + return KnownCA.MethodImplAttribute; + case "SpecialNameAttribute": + return KnownCA.SpecialNameAttribute; + } + break; + case "System.Runtime.InteropServices": + switch (typeName.Name) + { + case "DllImportAttribute": + return KnownCA.DllImportAttribute; + case "ComImportAttribute": + return KnownCA.ComImportAttribute; + case "MarshalAsAttribute": + return KnownCA.MarshalAsAttribute; + case "PreserveSigAttribute": + return KnownCA.PreserveSigAttribute; + case "InAttribute": + return KnownCA.InAttribute; + case "OutAttribute": + return KnownCA.OutAttribute; + case "OptionalAttribute": + return KnownCA.OptionalAttribute; + case "StructLayoutAttribute": + return KnownCA.StructLayoutAttribute; + case "FieldOffsetAttribute": + return KnownCA.FieldOffsetAttribute; + } + break; + } + if (typeName.Matches("System.Security.SuppressUnmanagedCodeSecurityAttribute")) + { + return KnownCA.SuppressUnmanagedCodeSecurityAttribute; + } + return KnownCA.Unknown; + } + } + } + + // These are the pseudo-custom attributes that are recognized by name by the runtime (i.e. the type identity is not considered). + // The corresponding list in the runtime is at https://github.com/dotnet/coreclr/blob/1afe5ce4f45045d724a4e129df4b816655d486fb/src/md/compiler/custattr_emit.cpp#L38 + // Note that we only need to handle a subset of the types, since we don't need the ones that are only used for validation by the runtime. + enum KnownCA + { + Unknown, + DllImportAttribute, + ComImportAttribute, + SerializableAttribute, + NonSerializedAttribute, + MethodImplAttribute, + MarshalAsAttribute, + PreserveSigAttribute, + InAttribute, + OutAttribute, + OptionalAttribute, + StructLayoutAttribute, + FieldOffsetAttribute, + SpecialNameAttribute, + // the following is not part of the runtime known custom attributes, but we handle it here for efficiency and convenience + SuppressUnmanagedCodeSecurityAttribute, + } +} diff --git a/reflect/Emit/CustomModifiersBuilder.cs b/reflect/Emit/CustomModifiersBuilder.cs new file mode 100644 index 0000000..91f5b83 --- /dev/null +++ b/reflect/Emit/CustomModifiersBuilder.cs @@ -0,0 +1,75 @@ +/* + Copyright (C) 2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; + +namespace IKVM.Reflection.Emit +{ + public sealed class CustomModifiersBuilder + { + private readonly List list = new List(); + + internal struct Item + { + internal Type type; + internal bool required; + } + + public void AddRequired(Type type) + { + Item item; + item.type = type; + item.required = true; + list.Add(item); + } + + public void AddOptional(Type type) + { + Item item; + item.type = type; + item.required = false; + list.Add(item); + } + + // this adds the custom modifiers in the same order as the normal SRE APIs + // (the advantage over using the SRE APIs is that a CustomModifiers object is slightly more efficient, + // because unlike the Type arrays it doesn't need to be copied) + public void Add(Type[] requiredCustomModifiers, Type[] optionalCustomModifiers) + { + foreach (CustomModifiers.Entry entry in CustomModifiers.FromReqOpt(requiredCustomModifiers, optionalCustomModifiers)) + { + Item item; + item.type = entry.Type; + item.required = entry.IsRequired; + list.Add(item); + } + } + + public CustomModifiers Create() + { + return new CustomModifiers(list); + } + } +} diff --git a/reflect/Emit/EnumBuilder.cs b/reflect/Emit/EnumBuilder.cs new file mode 100644 index 0000000..d396ae2 --- /dev/null +++ b/reflect/Emit/EnumBuilder.cs @@ -0,0 +1,119 @@ +/* + Copyright (C) 2010 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; + +namespace IKVM.Reflection.Emit +{ + public sealed class EnumBuilder : TypeInfo + { + private readonly TypeBuilder typeBuilder; + private readonly FieldBuilder fieldBuilder; + + internal EnumBuilder(TypeBuilder typeBuilder, FieldBuilder fieldBuilder) + : base(typeBuilder) + { + this.typeBuilder = typeBuilder; + this.fieldBuilder = fieldBuilder; + } + + internal override TypeName TypeName + { + get { return typeBuilder.TypeName; } + } + + public override string Name + { + get { return typeBuilder.Name; } + } + + public override string FullName + { + get { return typeBuilder.FullName; } + } + + public override Type BaseType + { + get { return typeBuilder.BaseType; } + } + + public override TypeAttributes Attributes + { + get { return typeBuilder.Attributes; } + } + + public override Module Module + { + get { return typeBuilder.Module; } + } + + public FieldBuilder DefineLiteral(string literalName, object literalValue) + { + FieldBuilder fb = typeBuilder.DefineField(literalName, typeBuilder, FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal); + fb.SetConstant(literalValue); + return fb; + } + + public Type CreateType() + { + return typeBuilder.CreateType(); + } + + public TypeInfo CreateTypeInfo() + { + return typeBuilder.CreateTypeInfo(); + } + + public TypeToken TypeToken + { + get { return typeBuilder.TypeToken; } + } + + public FieldBuilder UnderlyingField + { + get { return fieldBuilder; } + } + + public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) + { + typeBuilder.SetCustomAttribute(con, binaryAttribute); + } + + public void SetCustomAttribute(CustomAttributeBuilder customBuilder) + { + typeBuilder.SetCustomAttribute(customBuilder); + } + + public override Type GetEnumUnderlyingType() + { + return fieldBuilder.FieldType; + } + + internal override bool IsBaked + { + get { return typeBuilder.IsBaked; } + } + } +} diff --git a/reflect/Emit/Enums.cs b/reflect/Emit/Enums.cs new file mode 100644 index 0000000..7c85a55 --- /dev/null +++ b/reflect/Emit/Enums.cs @@ -0,0 +1,129 @@ +/* + Copyright (C) 2008 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +namespace IKVM.Reflection.Emit +{ + public enum AssemblyBuilderAccess + { + Save = 2, + ReflectionOnly = 6, + } + + public enum OpCodeType + { + Annotation = 0, + Macro = 1, + Nternal = 2, + Objmodel = 3, + Prefix = 4, + Primitive = 5, + } + + public enum OperandType + { + InlineBrTarget = 0, + InlineField = 1, + InlineI = 2, + InlineI8 = 3, + InlineMethod = 4, + InlineNone = 5, + InlinePhi = 6, + InlineR = 7, + InlineSig = 9, + InlineString = 10, + InlineSwitch = 11, + InlineTok = 12, + InlineType = 13, + InlineVar = 14, + ShortInlineBrTarget = 15, + ShortInlineI = 16, + ShortInlineR = 17, + ShortInlineVar = 18, + } + + public enum FlowControl + { + Branch = 0, + Break = 1, + Call = 2, + Cond_Branch = 3, + Meta = 4, + Next = 5, + Return = 7, + Throw = 8, + } + + public enum PackingSize + { + Unspecified = 0, + Size1 = 1, + Size2 = 2, + Size4 = 4, + Size8 = 8, + Size16 = 16, + Size32 = 32, + Size64 = 64, + Size128 = 128, + } + + public enum PEFileKinds + { + Dll = 1, + ConsoleApplication = 2, + WindowApplication = 3, + } + + public enum StackBehaviour + { + Pop0 = 0, + Pop1 = 1, + Pop1_pop1 = 2, + Popi = 3, + Popi_pop1 = 4, + Popi_popi = 5, + Popi_popi8 = 6, + Popi_popi_popi = 7, + Popi_popr4 = 8, + Popi_popr8 = 9, + Popref = 10, + Popref_pop1 = 11, + Popref_popi = 12, + Popref_popi_popi = 13, + Popref_popi_popi8 = 14, + Popref_popi_popr4 = 15, + Popref_popi_popr8 = 16, + Popref_popi_popref = 17, + Push0 = 18, + Push1 = 19, + Push1_push1 = 20, + Pushi = 21, + Pushi8 = 22, + Pushr4 = 23, + Pushr8 = 24, + Pushref = 25, + Varpop = 26, + Varpush = 27, + Popref_popi_pop1 = 28, + } +} diff --git a/reflect/Emit/EventBuilder.cs b/reflect/Emit/EventBuilder.cs new file mode 100644 index 0000000..dd3c18e --- /dev/null +++ b/reflect/Emit/EventBuilder.cs @@ -0,0 +1,280 @@ +/* + Copyright (C) 2009-2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using IKVM.Reflection.Metadata; +using IKVM.Reflection.Writer; + +namespace IKVM.Reflection.Emit +{ + public sealed class EventBuilder : EventInfo + { + private readonly TypeBuilder typeBuilder; + private readonly string name; + private EventAttributes attributes; + private readonly int eventtype; + private MethodBuilder addOnMethod; + private MethodBuilder removeOnMethod; + private MethodBuilder fireMethod; + private readonly List accessors = new List(); + private int lazyPseudoToken; + + private struct Accessor + { + internal short Semantics; + internal MethodBuilder Method; + } + + internal EventBuilder(TypeBuilder typeBuilder, string name, EventAttributes attributes, Type eventtype) + { + this.typeBuilder = typeBuilder; + this.name = name; + this.attributes = attributes; + this.eventtype = typeBuilder.ModuleBuilder.GetTypeTokenForMemberRef(eventtype); + } + + public void SetAddOnMethod(MethodBuilder mdBuilder) + { + addOnMethod = mdBuilder; + Accessor acc; + acc.Semantics = MethodSemanticsTable.AddOn; + acc.Method = mdBuilder; + accessors.Add(acc); + } + + public void SetRemoveOnMethod(MethodBuilder mdBuilder) + { + removeOnMethod = mdBuilder; + Accessor acc; + acc.Semantics = MethodSemanticsTable.RemoveOn; + acc.Method = mdBuilder; + accessors.Add(acc); + } + + public void SetRaiseMethod(MethodBuilder mdBuilder) + { + fireMethod = mdBuilder; + Accessor acc; + acc.Semantics = MethodSemanticsTable.Fire; + acc.Method = mdBuilder; + accessors.Add(acc); + } + + public void AddOtherMethod(MethodBuilder mdBuilder) + { + Accessor acc; + acc.Semantics = MethodSemanticsTable.Other; + acc.Method = mdBuilder; + accessors.Add(acc); + } + + public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) + { + SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute)); + } + + public void SetCustomAttribute(CustomAttributeBuilder customBuilder) + { + if (customBuilder.KnownCA == KnownCA.SpecialNameAttribute) + { + attributes |= EventAttributes.SpecialName; + } + else + { + if (lazyPseudoToken == 0) + { + lazyPseudoToken = typeBuilder.ModuleBuilder.AllocPseudoToken(); + } + typeBuilder.ModuleBuilder.SetCustomAttribute(lazyPseudoToken, customBuilder); + } + } + + public override EventAttributes Attributes + { + get { return attributes; } + } + + public override MethodInfo GetAddMethod(bool nonPublic) + { + return nonPublic || (addOnMethod != null && addOnMethod.IsPublic) ? addOnMethod : null; + } + + public override MethodInfo GetRemoveMethod(bool nonPublic) + { + return nonPublic || (removeOnMethod != null && removeOnMethod.IsPublic) ? removeOnMethod : null; + } + + public override MethodInfo GetRaiseMethod(bool nonPublic) + { + return nonPublic || (fireMethod != null && fireMethod.IsPublic) ? fireMethod : null; + } + + public override MethodInfo[] GetOtherMethods(bool nonPublic) + { + List list = new List(); + foreach (Accessor acc in accessors) + { + if (acc.Semantics == MethodSemanticsTable.Other && (nonPublic || acc.Method.IsPublic)) + { + list.Add(acc.Method); + } + } + return list.ToArray(); + } + + public override MethodInfo[] __GetMethods() + { + List list = new List(); + foreach (Accessor acc in accessors) + { + list.Add(acc.Method); + } + return list.ToArray(); + } + + public override Type DeclaringType + { + get { return typeBuilder; } + } + + public override string Name + { + get { return name; } + } + + public override Module Module + { + get { return typeBuilder.ModuleBuilder; } + } + + public EventToken GetEventToken() + { + if (lazyPseudoToken == 0) + { + lazyPseudoToken = typeBuilder.ModuleBuilder.AllocPseudoToken(); + } + return new EventToken(lazyPseudoToken); + } + + public override Type EventHandlerType + { + get { return typeBuilder.ModuleBuilder.ResolveType(eventtype); } + } + + internal void Bake() + { + EventTable.Record rec = new EventTable.Record(); + rec.EventFlags = (short)attributes; + rec.Name = typeBuilder.ModuleBuilder.Strings.Add(name); + rec.EventType = eventtype; + int token = 0x14000000 | typeBuilder.ModuleBuilder.Event.AddRecord(rec); + + if (lazyPseudoToken == 0) + { + lazyPseudoToken = token; + } + else + { + typeBuilder.ModuleBuilder.RegisterTokenFixup(lazyPseudoToken, token); + } + + foreach (Accessor acc in accessors) + { + AddMethodSemantics(acc.Semantics, acc.Method.MetadataToken, token); + } + } + + private void AddMethodSemantics(short semantics, int methodToken, int propertyToken) + { + MethodSemanticsTable.Record rec = new MethodSemanticsTable.Record(); + rec.Semantics = semantics; + rec.Method = methodToken; + rec.Association = propertyToken; + typeBuilder.ModuleBuilder.MethodSemantics.AddRecord(rec); + } + + internal override bool IsPublic + { + get + { + foreach (Accessor acc in accessors) + { + if (acc.Method.IsPublic) + { + return true; + } + } + return false; + } + } + + internal override bool IsNonPrivate + { + get + { + foreach (Accessor acc in accessors) + { + if ((acc.Method.Attributes & MethodAttributes.MemberAccessMask) > MethodAttributes.Private) + { + return true; + } + } + return false; + } + } + + internal override bool IsStatic + { + get + { + foreach (Accessor acc in accessors) + { + if (acc.Method.IsStatic) + { + return true; + } + } + return false; + } + } + + internal override bool IsBaked + { + get { return typeBuilder.IsBaked; } + } + + internal override int GetCurrentToken() + { + if (typeBuilder.ModuleBuilder.IsSaved && ModuleBuilder.IsPseudoToken(lazyPseudoToken)) + { + return typeBuilder.ModuleBuilder.ResolvePseudoToken(lazyPseudoToken); + } + else + { + return lazyPseudoToken; + } + } + } +} diff --git a/reflect/Emit/ExceptionHandler.cs b/reflect/Emit/ExceptionHandler.cs new file mode 100644 index 0000000..013f925 --- /dev/null +++ b/reflect/Emit/ExceptionHandler.cs @@ -0,0 +1,121 @@ +/* + Copyright (C) 2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; + +namespace IKVM.Reflection.Emit +{ + public struct ExceptionHandler : IEquatable + { + private readonly int tryOffset; + private readonly int tryLength; + private readonly int filterOffset; + private readonly int handlerOffset; + private readonly int handlerLength; + private readonly ExceptionHandlingClauseOptions kind; + private readonly int exceptionTypeToken; + + public ExceptionHandler(int tryOffset, int tryLength, int filterOffset, int handlerOffset, int handlerLength, ExceptionHandlingClauseOptions kind, int exceptionTypeToken) + { + if (tryOffset < 0 || tryLength < 0 || filterOffset < 0 || handlerOffset < 0 || handlerLength < 0) + { + throw new ArgumentOutOfRangeException(); + } + this.tryOffset = tryOffset; + this.tryLength = tryLength; + this.filterOffset = filterOffset; + this.handlerOffset = handlerOffset; + this.handlerLength = handlerLength; + this.kind = kind; + this.exceptionTypeToken = exceptionTypeToken; + } + + public int TryOffset + { + get { return tryOffset; } + } + + public int TryLength + { + get { return tryLength; } + } + + public int FilterOffset + { + get { return filterOffset; } + } + + public int HandlerOffset + { + get { return handlerOffset; } + } + + public int HandlerLength + { + get { return handlerLength; } + } + + public ExceptionHandlingClauseOptions Kind + { + get { return kind; } + } + + public int ExceptionTypeToken + { + get { return exceptionTypeToken; } + } + + public bool Equals(ExceptionHandler other) + { + return tryOffset == other.tryOffset + && tryLength == other.tryLength + && filterOffset == other.filterOffset + && handlerOffset == other.handlerOffset + && handlerLength == other.handlerLength + && kind == other.kind + && exceptionTypeToken == other.exceptionTypeToken; + } + + public override bool Equals(object obj) + { + ExceptionHandler? other = obj as ExceptionHandler?; + return other != null && Equals(other.Value); + } + + public override int GetHashCode() + { + return tryOffset ^ tryLength * 33 ^ filterOffset * 333 ^ handlerOffset * 3333 ^ handlerLength * 33333; + } + + public static bool operator ==(ExceptionHandler left, ExceptionHandler right) + { + return left.Equals(right); + } + + public static bool operator !=(ExceptionHandler left, ExceptionHandler right) + { + return !left.Equals(right); + } + } +} diff --git a/reflect/Emit/FieldBuilder.cs b/reflect/Emit/FieldBuilder.cs new file mode 100644 index 0000000..0ac911d --- /dev/null +++ b/reflect/Emit/FieldBuilder.cs @@ -0,0 +1,225 @@ +/* + Copyright (C) 2008-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using IKVM.Reflection.Metadata; +using IKVM.Reflection.Writer; + +namespace IKVM.Reflection.Emit +{ + public sealed class FieldBuilder : FieldInfo + { + private readonly TypeBuilder typeBuilder; + private readonly string name; + private readonly int pseudoToken; + private FieldAttributes attribs; + private readonly int nameIndex; + private readonly int signature; + private readonly FieldSignature fieldSig; + + internal FieldBuilder(TypeBuilder type, string name, Type fieldType, CustomModifiers customModifiers, FieldAttributes attribs) + { + this.typeBuilder = type; + this.name = name; + this.pseudoToken = type.ModuleBuilder.AllocPseudoToken(); + this.nameIndex = type.ModuleBuilder.Strings.Add(name); + this.fieldSig = FieldSignature.Create(fieldType, customModifiers); + ByteBuffer sig = new ByteBuffer(5); + fieldSig.WriteSig(this.typeBuilder.ModuleBuilder, sig); + this.signature = this.typeBuilder.ModuleBuilder.Blobs.Add(sig); + this.attribs = attribs; + this.typeBuilder.ModuleBuilder.Field.AddVirtualRecord(); + } + + public void SetConstant(object defaultValue) + { + attribs |= FieldAttributes.HasDefault; + typeBuilder.ModuleBuilder.AddConstant(pseudoToken, defaultValue); + } + + public override object GetRawConstantValue() + { + if (!typeBuilder.IsCreated()) + { + // the .NET FieldBuilder doesn't support this method + // (since we dont' have a different FieldInfo object after baking, we will support it once we're baked) + throw new NotSupportedException(); + } + return typeBuilder.Module.Constant.GetRawConstantValue(typeBuilder.Module, GetCurrentToken()); + } + + public void __SetDataAndRVA(byte[] data) + { + SetDataAndRvaImpl(data, typeBuilder.ModuleBuilder.initializedData, 0); + } + + public void __SetReadOnlyDataAndRVA(byte[] data) + { + SetDataAndRvaImpl(data, typeBuilder.ModuleBuilder.methodBodies, unchecked((int)0x80000000)); + } + + private void SetDataAndRvaImpl(byte[] data, ByteBuffer bb, int readonlyMarker) + { + attribs |= FieldAttributes.HasFieldRVA; + FieldRVATable.Record rec = new FieldRVATable.Record(); + bb.Align(8); + rec.RVA = bb.Position + readonlyMarker; + rec.Field = pseudoToken; + typeBuilder.ModuleBuilder.FieldRVA.AddRecord(rec); + bb.Write(data); + } + + public override void __GetDataFromRVA(byte[] data, int offset, int length) + { + throw new NotImplementedException(); + } + + public override int __FieldRVA + { + get { throw new NotImplementedException(); } + } + + public override bool __TryGetFieldOffset(out int offset) + { + int pseudoTokenOrIndex = pseudoToken; + if (typeBuilder.ModuleBuilder.IsSaved) + { + pseudoTokenOrIndex = typeBuilder.ModuleBuilder.ResolvePseudoToken(pseudoToken) & 0xFFFFFF; + } + foreach (int i in this.Module.FieldLayout.Filter(pseudoTokenOrIndex)) + { + offset = this.Module.FieldLayout.records[i].Offset; + return true; + } + offset = 0; + return false; + } + + public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) + { + SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute)); + } + + public void SetCustomAttribute(CustomAttributeBuilder customBuilder) + { + switch (customBuilder.KnownCA) + { + case KnownCA.FieldOffsetAttribute: + SetOffset((int)customBuilder.DecodeBlob(this.Module.Assembly).GetConstructorArgument(0)); + break; + case KnownCA.MarshalAsAttribute: + FieldMarshal.SetMarshalAsAttribute(typeBuilder.ModuleBuilder, pseudoToken, customBuilder); + attribs |= FieldAttributes.HasFieldMarshal; + break; + case KnownCA.NonSerializedAttribute: + attribs |= FieldAttributes.NotSerialized; + break; + case KnownCA.SpecialNameAttribute: + attribs |= FieldAttributes.SpecialName; + break; + default: + typeBuilder.ModuleBuilder.SetCustomAttribute(pseudoToken, customBuilder); + break; + } + } + + public void SetOffset(int iOffset) + { + FieldLayoutTable.Record rec = new FieldLayoutTable.Record(); + rec.Offset = iOffset; + rec.Field = pseudoToken; + typeBuilder.ModuleBuilder.FieldLayout.AddRecord(rec); + } + + public override FieldAttributes Attributes + { + get { return attribs; } + } + + public override Type DeclaringType + { + get { return typeBuilder.IsModulePseudoType ? null : typeBuilder; } + } + + public override string Name + { + get { return name; } + } + + public override int MetadataToken + { + get { return pseudoToken; } + } + + public override Module Module + { + get { return typeBuilder.Module; } + } + + public FieldToken GetToken() + { + return new FieldToken(pseudoToken); + } + + internal void WriteFieldRecords(MetadataWriter mw) + { + mw.Write((short)attribs); + mw.WriteStringIndex(nameIndex); + mw.WriteBlobIndex(signature); + } + + internal void FixupToken(int token) + { + typeBuilder.ModuleBuilder.RegisterTokenFixup(this.pseudoToken, token); + } + + internal override FieldSignature FieldSignature + { + get { return fieldSig; } + } + + internal override int ImportTo(ModuleBuilder other) + { + return other.ImportMethodOrField(typeBuilder, name, fieldSig); + } + + internal override int GetCurrentToken() + { + if (typeBuilder.ModuleBuilder.IsSaved) + { + return typeBuilder.ModuleBuilder.ResolvePseudoToken(pseudoToken); + } + else + { + return pseudoToken; + } + } + + internal override bool IsBaked + { + get { return typeBuilder.IsBaked; } + } + } +} diff --git a/reflect/Emit/ILGenerator.cs b/reflect/Emit/ILGenerator.cs new file mode 100644 index 0000000..18db09b --- /dev/null +++ b/reflect/Emit/ILGenerator.cs @@ -0,0 +1,1150 @@ +/* + Copyright (C) 2008-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Runtime.InteropServices; +using System.Collections.Generic; +#if !NO_SYMBOL_WRITER +using System.Diagnostics.SymbolStore; +#endif +using System.Diagnostics; +using IKVM.Reflection.Writer; + +namespace IKVM.Reflection.Emit +{ + public struct Label + { + // 1-based here, to make sure that an uninitialized Label isn't valid + private readonly int index1; + + internal Label(int index) + { + this.index1 = index + 1; + } + + internal int Index + { + get { return index1 - 1; } + } + + public bool Equals(Label other) + { + return other.index1 == index1; + } + + public override bool Equals(object obj) + { + return this == obj as Label?; + } + + public override int GetHashCode() + { + return index1; + } + + public static bool operator ==(Label arg1, Label arg2) + { + return arg1.index1 == arg2.index1; + } + + public static bool operator !=(Label arg1, Label arg2) + { + return !(arg1 == arg2); + } + } + + public sealed class LocalBuilder : LocalVariableInfo + { + internal string name; + internal int startOffset; + internal int endOffset; + + internal LocalBuilder(Type localType, int index, bool pinned) + : base(index, localType, pinned) + { + } + + internal LocalBuilder(Type localType, int index, bool pinned, CustomModifiers customModifiers) + : base(index, localType, pinned, customModifiers) + { + } + + public void SetLocalSymInfo(string name) + { + this.name = name; + } + + public void SetLocalSymInfo(string name, int startOffset, int endOffset) + { + this.name = name; + this.startOffset = startOffset; + this.endOffset = endOffset; + } + } + + public sealed class ILGenerator + { + private readonly ModuleBuilder moduleBuilder; + private readonly ByteBuffer code; + private readonly SignatureHelper locals; + private int localsCount; + private readonly List tokenFixups = new List(); + private readonly List labels = new List(); + private readonly List labelStackHeight = new List(); + private readonly List labelFixups = new List(); + private readonly List sequencePoints = new List(); + private readonly List exceptions = new List(); + private readonly Stack exceptionStack = new Stack(); + private ushort maxStack; + private bool fatHeader; + private int stackHeight; + private Scope scope; + private byte exceptionBlockAssistanceMode = EBAM_COMPAT; + private const byte EBAM_COMPAT = 0; + private const byte EBAM_DISABLE = 1; + private const byte EBAM_CLEVER = 2; + + private struct LabelFixup + { + internal int label; + internal int offset; + } + + internal sealed class ExceptionBlock : IComparer + { + internal readonly int ordinal; + internal Label labelEnd; + internal int tryOffset; + internal int tryLength; + internal int handlerOffset; + internal int handlerLength; + internal int filterOffsetOrExceptionTypeToken; + internal ExceptionHandlingClauseOptions kind; + + internal ExceptionBlock(int ordinal) + { + this.ordinal = ordinal; + } + + internal ExceptionBlock(ExceptionHandler h) + { + this.ordinal = -1; + this.tryOffset = h.TryOffset; + this.tryLength = h.TryLength; + this.handlerOffset = h.HandlerOffset; + this.handlerLength = h.HandlerLength; + this.kind = h.Kind; + this.filterOffsetOrExceptionTypeToken = kind == ExceptionHandlingClauseOptions.Filter ? h.FilterOffset : h.ExceptionTypeToken; + } + + int IComparer.Compare(ExceptionBlock x, ExceptionBlock y) + { + // Mono's sort insists on doing unnecessary comparisons + if (x == y) + { + return 0; + } + else if (x.tryOffset == y.tryOffset && x.tryLength == y.tryLength) + { + return x.ordinal < y.ordinal ? -1 : 1; + } + else if (x.tryOffset >= y.tryOffset && x.handlerOffset + x.handlerLength <= y.handlerOffset + y.handlerLength) + { + return -1; + } + else if (y.tryOffset >= x.tryOffset && y.handlerOffset + y.handlerLength <= x.handlerOffset + x.handlerLength) + { + return 1; + } + else + { + return x.ordinal < y.ordinal ? -1 : 1; + } + } + } + + private struct SequencePoint + { +#if !NO_SYMBOL_WRITER + internal ISymbolDocumentWriter document; + internal int offset; + internal int startLine; + internal int startColumn; + internal int endLine; + internal int endColumn; +#endif + } + + private sealed class Scope + { + internal readonly Scope parent; + internal readonly List children = new List(); + internal readonly List locals = new List(); + internal int startOffset; + internal int endOffset; + + internal Scope(Scope parent) + { + this.parent = parent; + } + } + + internal ILGenerator(ModuleBuilder moduleBuilder, int initialCapacity) + { + this.code = new ByteBuffer(initialCapacity); + this.moduleBuilder = moduleBuilder; + this.locals = SignatureHelper.GetLocalVarSigHelper(moduleBuilder); + if (moduleBuilder.symbolWriter != null) + { + scope = new Scope(null); + } + } + + // non-standard API + public void __DisableExceptionBlockAssistance() + { + exceptionBlockAssistanceMode = EBAM_DISABLE; + } + + // non-standard API + public void __CleverExceptionBlockAssistance() + { + exceptionBlockAssistanceMode = EBAM_CLEVER; + } + + // non-standard API + public int __MaxStackSize + { + get { return maxStack; } + set + { + maxStack = (ushort)value; + fatHeader = true; + } + } + + // non-standard API + // returns -1 if the current position is currently unreachable + public int __StackHeight + { + get { return stackHeight; } + } + + // new in .NET 4.0 + public int ILOffset + { + get { return code.Position; } + } + + public void BeginCatchBlock(Type exceptionType) + { + if (exceptionType == null) + { + // this must be a catch block after a filter + ExceptionBlock block = exceptionStack.Peek(); + if (block.kind != ExceptionHandlingClauseOptions.Filter || block.handlerOffset != 0) + { + throw new ArgumentNullException("exceptionType"); + } + if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1)) + { + Emit(OpCodes.Endfilter); + } + stackHeight = 0; + UpdateStack(1); + block.handlerOffset = code.Position; + } + else + { + ExceptionBlock block = BeginCatchOrFilterBlock(); + block.kind = ExceptionHandlingClauseOptions.Clause; + block.filterOffsetOrExceptionTypeToken = moduleBuilder.GetTypeTokenForMemberRef(exceptionType); + block.handlerOffset = code.Position; + } + } + + private ExceptionBlock BeginCatchOrFilterBlock() + { + ExceptionBlock block = exceptionStack.Peek(); + if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1)) + { + Emit(OpCodes.Leave, block.labelEnd); + } + stackHeight = 0; + UpdateStack(1); + if (block.tryLength == 0) + { + block.tryLength = code.Position - block.tryOffset; + } + else + { + block.handlerLength = code.Position - block.handlerOffset; + exceptionStack.Pop(); + ExceptionBlock newBlock = new ExceptionBlock(exceptions.Count); + newBlock.labelEnd = block.labelEnd; + newBlock.tryOffset = block.tryOffset; + newBlock.tryLength = block.tryLength; + block = newBlock; + exceptions.Add(block); + exceptionStack.Push(block); + } + return block; + } + + public Label BeginExceptionBlock() + { + ExceptionBlock block = new ExceptionBlock(exceptions.Count); + block.labelEnd = DefineLabel(); + block.tryOffset = code.Position; + exceptionStack.Push(block); + exceptions.Add(block); + stackHeight = 0; + return block.labelEnd; + } + + public void BeginExceptFilterBlock() + { + ExceptionBlock block = BeginCatchOrFilterBlock(); + block.kind = ExceptionHandlingClauseOptions.Filter; + block.filterOffsetOrExceptionTypeToken = code.Position; + } + + public void BeginFaultBlock() + { + BeginFinallyFaultBlock(ExceptionHandlingClauseOptions.Fault); + } + + public void BeginFinallyBlock() + { + BeginFinallyFaultBlock(ExceptionHandlingClauseOptions.Finally); + } + + private void BeginFinallyFaultBlock(ExceptionHandlingClauseOptions kind) + { + ExceptionBlock block = exceptionStack.Peek(); + if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1)) + { + Emit(OpCodes.Leave, block.labelEnd); + } + if (block.handlerOffset == 0) + { + block.tryLength = code.Position - block.tryOffset; + } + else + { + block.handlerLength = code.Position - block.handlerOffset; + Label labelEnd; + if (exceptionBlockAssistanceMode != EBAM_COMPAT) + { + labelEnd = block.labelEnd; + } + else + { + MarkLabel(block.labelEnd); + labelEnd = DefineLabel(); + Emit(OpCodes.Leave, labelEnd); + } + exceptionStack.Pop(); + ExceptionBlock newBlock = new ExceptionBlock(exceptions.Count); + newBlock.labelEnd = labelEnd; + newBlock.tryOffset = block.tryOffset; + newBlock.tryLength = code.Position - block.tryOffset; + block = newBlock; + exceptions.Add(block); + exceptionStack.Push(block); + } + block.handlerOffset = code.Position; + block.kind = kind; + stackHeight = 0; + } + + public void EndExceptionBlock() + { + ExceptionBlock block = exceptionStack.Pop(); + if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1)) + { + if (block.kind != ExceptionHandlingClauseOptions.Finally && block.kind != ExceptionHandlingClauseOptions.Fault) + { + Emit(OpCodes.Leave, block.labelEnd); + } + else + { + Emit(OpCodes.Endfinally); + } + } + MarkLabel(block.labelEnd); + block.handlerLength = code.Position - block.handlerOffset; + } + + public void BeginScope() + { + Scope newScope = new Scope(scope); + scope.children.Add(newScope); + scope = newScope; + scope.startOffset = code.Position; + } + + public void UsingNamespace(string usingNamespace) + { +#if !NO_SYMBOL_WRITER + if (moduleBuilder.symbolWriter != null) + { + moduleBuilder.symbolWriter.UsingNamespace(usingNamespace); + } +#endif + } + + public LocalBuilder DeclareLocal(Type localType) + { + return DeclareLocal(localType, false); + } + + public LocalBuilder DeclareLocal(Type localType, bool pinned) + { + LocalBuilder local = new LocalBuilder(localType, localsCount++, pinned); + locals.AddArgument(localType, pinned); + if (scope != null) + { + scope.locals.Add(local); + } + return local; + } + + public LocalBuilder __DeclareLocal(Type localType, bool pinned, CustomModifiers customModifiers) + { + LocalBuilder local = new LocalBuilder(localType, localsCount++, pinned, customModifiers); + locals.__AddArgument(localType, pinned, customModifiers); + if (scope != null) + { + scope.locals.Add(local); + } + return local; + } + + public Label DefineLabel() + { + Label label = new Label(labels.Count); + labels.Add(-1); + labelStackHeight.Add(-1); + return label; + } + + public void Emit(OpCode opc) + { + Debug.Assert(opc != OpCodes.Ret || (opc == OpCodes.Ret && stackHeight <= 1)); + if (opc.Value < 0) + { + code.Write((byte)(opc.Value >> 8)); + } + code.Write((byte)opc.Value); + switch (opc.FlowControl) + { + case FlowControl.Branch: + case FlowControl.Break: + case FlowControl.Return: + case FlowControl.Throw: + stackHeight = -1; + break; + default: + UpdateStack(opc.StackDiff); + break; + } + } + + private void UpdateStack(int stackdiff) + { + if (stackHeight == -1) + { + // we're about to emit code that is either unreachable or reachable only via a backward branch + stackHeight = 0; + } + Debug.Assert(stackHeight >= 0 && stackHeight <= ushort.MaxValue); + stackHeight += stackdiff; + Debug.Assert(stackHeight >= 0 && stackHeight <= ushort.MaxValue); + maxStack = Math.Max(maxStack, (ushort)stackHeight); + } + + public void Emit(OpCode opc, byte arg) + { + Emit(opc); + code.Write(arg); + } + + public void Emit(OpCode opc, double arg) + { + Emit(opc); + code.Write(arg); + } + + public void Emit(OpCode opc, FieldInfo field) + { + Emit(opc); + WriteToken(moduleBuilder.GetFieldToken(field).Token); + } + + public void Emit(OpCode opc, short arg) + { + Emit(opc); + code.Write(arg); + } + + public void Emit(OpCode opc, int arg) + { + Emit(opc); + code.Write(arg); + } + + public void Emit(OpCode opc, long arg) + { + Emit(opc); + code.Write(arg); + } + + public void Emit(OpCode opc, Label label) + { + // We need special stackHeight handling for unconditional branches, + // because the branch and next flows have differing stack heights. + // Note that this assumes that unconditional branches do not push/pop. + int flowStackHeight = this.stackHeight; + Emit(opc); + if (opc == OpCodes.Leave || opc == OpCodes.Leave_S) + { + flowStackHeight = 0; + } + else if (opc.FlowControl != FlowControl.Branch) + { + flowStackHeight = this.stackHeight; + } + // if the label has already been marked, we can emit the branch offset directly + if (labels[label.Index] != -1) + { + if (labelStackHeight[label.Index] != flowStackHeight && (labelStackHeight[label.Index] != 0 || flowStackHeight != -1)) + { + // the "backward branch constraint" prohibits this, so we don't need to support it + throw new NotSupportedException("'Backward branch constraints' violated"); + } + if (opc.OperandType == OperandType.ShortInlineBrTarget) + { + WriteByteBranchOffset(labels[label.Index] - (code.Position + 1)); + } + else + { + code.Write(labels[label.Index] - (code.Position + 4)); + } + } + else + { + Debug.Assert(labelStackHeight[label.Index] == -1 || labelStackHeight[label.Index] == flowStackHeight || (flowStackHeight == -1 && labelStackHeight[label.Index] == 0)); + labelStackHeight[label.Index] = flowStackHeight; + LabelFixup fix = new LabelFixup(); + fix.label = label.Index; + fix.offset = code.Position; + labelFixups.Add(fix); + if (opc.OperandType == OperandType.ShortInlineBrTarget) + { + code.Write((byte)1); + } + else + { + code.Write(4); + } + } + } + + private void WriteByteBranchOffset(int offset) + { + if (offset < -128 || offset > 127) + { + throw new NotSupportedException("Branch offset of " + offset + " does not fit in one-byte branch target at position " + code.Position); + } + code.Write((byte)offset); + } + + public void Emit(OpCode opc, Label[] labels) + { + Emit(opc); + LabelFixup fix = new LabelFixup(); + fix.label = -1; + fix.offset = code.Position; + labelFixups.Add(fix); + code.Write(labels.Length); + foreach (Label label in labels) + { + code.Write(label.Index); + if (this.labels[label.Index] != -1) + { + if (labelStackHeight[label.Index] != stackHeight) + { + // the "backward branch constraint" prohibits this, so we don't need to support it + throw new NotSupportedException(); + } + } + else + { + Debug.Assert(labelStackHeight[label.Index] == -1 || labelStackHeight[label.Index] == stackHeight); + labelStackHeight[label.Index] = stackHeight; + } + } + } + + public void Emit(OpCode opc, LocalBuilder local) + { + if ((opc == OpCodes.Ldloc || opc == OpCodes.Ldloca || opc == OpCodes.Stloc) && local.LocalIndex < 256) + { + if (opc == OpCodes.Ldloc) + { + switch (local.LocalIndex) + { + case 0: + Emit(OpCodes.Ldloc_0); + break; + case 1: + Emit(OpCodes.Ldloc_1); + break; + case 2: + Emit(OpCodes.Ldloc_2); + break; + case 3: + Emit(OpCodes.Ldloc_3); + break; + default: + Emit(OpCodes.Ldloc_S); + code.Write((byte)local.LocalIndex); + break; + } + } + else if (opc == OpCodes.Ldloca) + { + Emit(OpCodes.Ldloca_S); + code.Write((byte)local.LocalIndex); + } + else if (opc == OpCodes.Stloc) + { + switch (local.LocalIndex) + { + case 0: + Emit(OpCodes.Stloc_0); + break; + case 1: + Emit(OpCodes.Stloc_1); + break; + case 2: + Emit(OpCodes.Stloc_2); + break; + case 3: + Emit(OpCodes.Stloc_3); + break; + default: + Emit(OpCodes.Stloc_S); + code.Write((byte)local.LocalIndex); + break; + } + } + } + else + { + Emit(opc); + switch (opc.OperandType) + { + case OperandType.InlineVar: + code.Write((ushort)local.LocalIndex); + break; + case OperandType.ShortInlineVar: + code.Write((byte)local.LocalIndex); + break; + } + } + } + + private void WriteToken(int token) + { + if (ModuleBuilder.IsPseudoToken(token)) + { + tokenFixups.Add(code.Position); + } + code.Write(token); + } + + private void UpdateStack(OpCode opc, bool hasthis, Type returnType, int parameterCount) + { + if (opc == OpCodes.Jmp) + { + stackHeight = -1; + } + else if (opc.FlowControl == FlowControl.Call) + { + int stackdiff = 0; + if ((hasthis && opc != OpCodes.Newobj) || opc == OpCodes.Calli) + { + // pop this + stackdiff--; + } + // pop parameters + stackdiff -= parameterCount; + if (returnType != moduleBuilder.universe.System_Void) + { + // push return value + stackdiff++; + } + UpdateStack(stackdiff); + } + } + + public void Emit(OpCode opc, MethodInfo method) + { + UpdateStack(opc, method.HasThis, method.ReturnType, method.ParameterCount); + Emit(opc); + WriteToken(moduleBuilder.GetMethodTokenForIL(method).Token); + } + + public void Emit(OpCode opc, ConstructorInfo constructor) + { + Emit(opc, constructor.GetMethodInfo()); + } + + public void Emit(OpCode opc, sbyte arg) + { + Emit(opc); + code.Write(arg); + } + + public void Emit(OpCode opc, float arg) + { + Emit(opc); + code.Write(arg); + } + + public void Emit(OpCode opc, string str) + { + Emit(opc); + code.Write(moduleBuilder.GetStringConstant(str).Token); + } + + public void Emit(OpCode opc, Type type) + { + Emit(opc); + if (opc == OpCodes.Ldtoken) + { + code.Write(moduleBuilder.GetTypeToken(type).Token); + } + else + { + code.Write(moduleBuilder.GetTypeTokenForMemberRef(type)); + } + } + + public void Emit(OpCode opcode, SignatureHelper signature) + { + Emit(opcode); + UpdateStack(opcode, signature.HasThis, signature.ReturnType, signature.ParameterCount); + code.Write(moduleBuilder.GetSignatureToken(signature).Token); + } + + public void EmitCall(OpCode opc, MethodInfo method, Type[] optionalParameterTypes) + { + __EmitCall(opc, method, optionalParameterTypes, null); + } + + public void __EmitCall(OpCode opc, MethodInfo method, Type[] optionalParameterTypes, CustomModifiers[] customModifiers) + { + if (optionalParameterTypes == null || optionalParameterTypes.Length == 0) + { + Emit(opc, method); + } + else + { + Emit(opc); + UpdateStack(opc, method.HasThis, method.ReturnType, method.ParameterCount + optionalParameterTypes.Length); + code.Write(moduleBuilder.__GetMethodToken(method, optionalParameterTypes, customModifiers).Token); + } + } + + public void __EmitCall(OpCode opc, ConstructorInfo constructor, Type[] optionalParameterTypes) + { + EmitCall(opc, constructor.GetMethodInfo(), optionalParameterTypes); + } + + public void __EmitCall(OpCode opc, ConstructorInfo constructor, Type[] optionalParameterTypes, CustomModifiers[] customModifiers) + { + __EmitCall(opc, constructor.GetMethodInfo(), optionalParameterTypes, customModifiers); + } + + public void EmitCalli(OpCode opc, CallingConvention callingConvention, Type returnType, Type[] parameterTypes) + { + SignatureHelper sig = SignatureHelper.GetMethodSigHelper(moduleBuilder, callingConvention, returnType); + sig.AddArguments(parameterTypes, null, null); + Emit(opc, sig); + } + + public void EmitCalli(OpCode opc, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes) + { + SignatureHelper sig = SignatureHelper.GetMethodSigHelper(moduleBuilder, callingConvention, returnType); + sig.AddArguments(parameterTypes, null, null); + if (optionalParameterTypes != null && optionalParameterTypes.Length != 0) + { + sig.AddSentinel(); + sig.AddArguments(optionalParameterTypes, null, null); + } + Emit(opc, sig); + } + + public void __EmitCalli(OpCode opc, __StandAloneMethodSig sig) + { + Emit(opc); + if (sig.IsUnmanaged) + { + UpdateStack(opc, false, sig.ReturnType, sig.ParameterCount); + } + else + { + CallingConventions callingConvention = sig.CallingConvention; + UpdateStack(opc, (callingConvention & CallingConventions.HasThis | CallingConventions.ExplicitThis) == CallingConventions.HasThis, sig.ReturnType, sig.ParameterCount); + } + ByteBuffer bb = new ByteBuffer(16); + Signature.WriteStandAloneMethodSig(moduleBuilder, bb, sig); + code.Write(0x11000000 | moduleBuilder.StandAloneSig.FindOrAddRecord(moduleBuilder.Blobs.Add(bb))); + } + + public void EmitWriteLine(string text) + { + Universe u = moduleBuilder.universe; + Emit(OpCodes.Ldstr, text); + Emit(OpCodes.Call, u.Import(typeof(Console)).GetMethod("WriteLine", new Type[] { u.System_String })); + } + + public void EmitWriteLine(FieldInfo field) + { + Universe u = moduleBuilder.universe; + Emit(OpCodes.Call, u.Import(typeof(Console)).GetMethod("get_Out")); + if (field.IsStatic) + { + Emit(OpCodes.Ldsfld, field); + } + else + { + Emit(OpCodes.Ldarg_0); + Emit(OpCodes.Ldfld, field); + } + Emit(OpCodes.Callvirt, u.Import(typeof(System.IO.TextWriter)).GetMethod("WriteLine", new Type[] { field.FieldType })); + } + + public void EmitWriteLine(LocalBuilder local) + { + Universe u = moduleBuilder.universe; + Emit(OpCodes.Call, u.Import(typeof(Console)).GetMethod("get_Out")); + Emit(OpCodes.Ldloc, local); + Emit(OpCodes.Callvirt, u.Import(typeof(System.IO.TextWriter)).GetMethod("WriteLine", new Type[] { local.LocalType })); + } + + public void EndScope() + { + scope.endOffset = code.Position; + scope = scope.parent; + } + + public void MarkLabel(Label loc) + { + Debug.Assert(stackHeight == -1 || labelStackHeight[loc.Index] == -1 || stackHeight == labelStackHeight[loc.Index]); + labels[loc.Index] = code.Position; + if (labelStackHeight[loc.Index] == -1) + { + if (stackHeight == -1) + { + // We're at a location that can only be reached by a backward branch, + // so according to the "backward branch constraint" that must mean the stack is empty, + // but note that this may be an unused label followed by another label that is used and + // that does have a non-zero stack height, so we don't yet set stackHeight here. + labelStackHeight[loc.Index] = 0; + } + else + { + labelStackHeight[loc.Index] = stackHeight; + } + } + else + { + Debug.Assert(stackHeight == -1 || stackHeight == labelStackHeight[loc.Index]); + stackHeight = labelStackHeight[loc.Index]; + } + } + +#if !NO_SYMBOL_WRITER + public void MarkSequencePoint(ISymbolDocumentWriter document, int startLine, int startColumn, int endLine, int endColumn) + { + SequencePoint sp = new SequencePoint(); + sp.document = document; + sp.offset = code.Position; + sp.startLine = startLine; + sp.startColumn = startColumn; + sp.endLine = endLine; + sp.endColumn = endColumn; + sequencePoints.Add(sp); + } +#endif + + public void ThrowException(Type excType) + { + Emit(OpCodes.Newobj, excType.GetConstructor(Type.EmptyTypes)); + Emit(OpCodes.Throw); + } + + internal int WriteBody(bool initLocals) + { + if (moduleBuilder.symbolWriter != null) + { + Debug.Assert(scope != null && scope.parent == null); + scope.endOffset = code.Position; + } + + ResolveBranches(); + + ByteBuffer bb = moduleBuilder.methodBodies; + + int localVarSigTok = 0; + + int rva; + if (localsCount == 0 && exceptions.Count == 0 && maxStack <= 8 && code.Length < 64 && !fatHeader) + { + rva = WriteTinyHeaderAndCode(bb); + } + else + { + if (localsCount != 0) + { + localVarSigTok = moduleBuilder.GetSignatureToken(locals).Token; + } + rva = WriteFatHeaderAndCode(bb, localVarSigTok, initLocals); + } + +#if !NO_SYMBOL_WRITER + if (moduleBuilder.symbolWriter != null) + { + if (sequencePoints.Count != 0) + { + ISymbolDocumentWriter document = sequencePoints[0].document; + int[] offsets = new int[sequencePoints.Count]; + int[] lines = new int[sequencePoints.Count]; + int[] columns = new int[sequencePoints.Count]; + int[] endLines = new int[sequencePoints.Count]; + int[] endColumns = new int[sequencePoints.Count]; + for (int i = 0; i < sequencePoints.Count; i++) + { + if (sequencePoints[i].document != document) + { + throw new NotImplementedException(); + } + offsets[i] = sequencePoints[i].offset; + lines[i] = sequencePoints[i].startLine; + columns[i] = sequencePoints[i].startColumn; + endLines[i] = sequencePoints[i].endLine; + endColumns[i] = sequencePoints[i].endColumn; + } + moduleBuilder.symbolWriter.DefineSequencePoints(document, offsets, lines, columns, endLines, endColumns); + } + + WriteScope(scope, localVarSigTok); + } +#endif + return rva; + } + + private void ResolveBranches() + { + foreach (LabelFixup fixup in labelFixups) + { + // is it a switch? + if (fixup.label == -1) + { + code.Position = fixup.offset; + int count = code.GetInt32AtCurrentPosition(); + int offset = fixup.offset + 4 + 4 * count; + code.Position += 4; + for (int i = 0; i < count; i++) + { + int index = code.GetInt32AtCurrentPosition(); + code.Write(labels[index] - offset); + } + } + else + { + code.Position = fixup.offset; + byte size = code.GetByteAtCurrentPosition(); + int branchOffset = labels[fixup.label] - (code.Position + size); + if (size == 1) + { + WriteByteBranchOffset(branchOffset); + } + else + { + code.Write(branchOffset); + } + } + } + } + + internal static void WriteTinyHeader(ByteBuffer bb, int length) + { + const byte CorILMethod_TinyFormat = 0x2; + bb.Write((byte)(CorILMethod_TinyFormat | (length << 2))); + } + + private int WriteTinyHeaderAndCode(ByteBuffer bb) + { + int rva = bb.Position; + WriteTinyHeader(bb, code.Length); + AddTokenFixups(bb.Position, moduleBuilder.tokenFixupOffsets, tokenFixups); + bb.Write(code); + return rva; + } + + internal static void WriteFatHeader(ByteBuffer bb, bool initLocals, bool exceptions, ushort maxStack, int codeLength, int localVarSigTok) + { + const byte CorILMethod_FatFormat = 0x03; + const byte CorILMethod_MoreSects = 0x08; + const byte CorILMethod_InitLocals = 0x10; + + short flagsAndSize = (short)(CorILMethod_FatFormat | (3 << 12)); + if (initLocals) + { + flagsAndSize |= CorILMethod_InitLocals; + } + + if (exceptions) + { + flagsAndSize |= CorILMethod_MoreSects; + } + + bb.Write(flagsAndSize); + bb.Write(maxStack); + bb.Write(codeLength); + bb.Write(localVarSigTok); + } + + private int WriteFatHeaderAndCode(ByteBuffer bb, int localVarSigTok, bool initLocals) + { + // fat headers require 4-byte alignment + bb.Align(4); + int rva = bb.Position; + WriteFatHeader(bb, initLocals, exceptions.Count > 0, maxStack, code.Length, localVarSigTok); + AddTokenFixups(bb.Position, moduleBuilder.tokenFixupOffsets, tokenFixups); + bb.Write(code); + if (exceptions.Count > 0) + { + exceptions.Sort(exceptions[0]); + WriteExceptionHandlers(bb, exceptions); + } + return rva; + } + + internal static void WriteExceptionHandlers(ByteBuffer bb, List exceptions) + { + bb.Align(4); + + bool fat = false; + if (exceptions.Count * 12 + 4 > 255) + { + fat = true; + } + else + { + foreach (ExceptionBlock block in exceptions) + { + if (block.tryOffset > 65535 || block.tryLength > 255 || block.handlerOffset > 65535 || block.handlerLength > 255) + { + fat = true; + break; + } + } + } + + const byte CorILMethod_Sect_EHTable = 0x1; + const byte CorILMethod_Sect_FatFormat = 0x40; + + if (fat) + { + bb.Write((byte)(CorILMethod_Sect_EHTable | CorILMethod_Sect_FatFormat)); + int dataSize = exceptions.Count * 24 + 4; + bb.Write((byte)dataSize); + bb.Write((short)(dataSize >> 8)); + foreach (ExceptionBlock block in exceptions) + { + bb.Write((int)block.kind); + bb.Write(block.tryOffset); + bb.Write(block.tryLength); + bb.Write(block.handlerOffset); + bb.Write(block.handlerLength); + bb.Write(block.filterOffsetOrExceptionTypeToken); + } + } + else + { + bb.Write(CorILMethod_Sect_EHTable); + bb.Write((byte)(exceptions.Count * 12 + 4)); + bb.Write((short)0); + foreach (ExceptionBlock block in exceptions) + { + bb.Write((short)block.kind); + bb.Write((short)block.tryOffset); + bb.Write((byte)block.tryLength); + bb.Write((short)block.handlerOffset); + bb.Write((byte)block.handlerLength); + bb.Write(block.filterOffsetOrExceptionTypeToken); + } + } + } + + internal static void AddTokenFixups(int codeOffset, List tokenFixupOffsets, IEnumerable tokenFixups) + { + foreach (int fixup in tokenFixups) + { + tokenFixupOffsets.Add(fixup + codeOffset); + } + } + +#if !NO_SYMBOL_WRITER + private void WriteScope(Scope scope, int localVarSigTok) + { + moduleBuilder.symbolWriter.OpenScope(scope.startOffset); + foreach (LocalBuilder local in scope.locals) + { + if (local.name != null) + { + int startOffset = local.startOffset; + int endOffset = local.endOffset; + if (startOffset == 0 && endOffset == 0) + { + startOffset = scope.startOffset; + endOffset = scope.endOffset; + } + moduleBuilder.symbolWriter.DefineLocalVariable2(local.name, 0, localVarSigTok, SymAddressKind.ILOffset, local.LocalIndex, 0, 0, startOffset, endOffset); + } + } + foreach (Scope child in scope.children) + { + WriteScope(child, localVarSigTok); + } + moduleBuilder.symbolWriter.CloseScope(scope.endOffset); + } +#endif + } +} diff --git a/reflect/Emit/MethodBuilder.cs b/reflect/Emit/MethodBuilder.cs new file mode 100644 index 0000000..a7f724d --- /dev/null +++ b/reflect/Emit/MethodBuilder.cs @@ -0,0 +1,782 @@ +/* + Copyright (C) 2008-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.IO; +using System.Diagnostics; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +#if !NO_SYMBOL_WRITER +using System.Diagnostics.SymbolStore; +#endif +using IKVM.Reflection.Metadata; +using IKVM.Reflection.Writer; + +namespace IKVM.Reflection.Emit +{ + public sealed class MethodBuilder : MethodInfo + { + private readonly TypeBuilder typeBuilder; + private readonly string name; + private readonly int pseudoToken; + private int nameIndex; + private int signature; + private Type returnType; + private Type[] parameterTypes; + private PackedCustomModifiers customModifiers; + private MethodAttributes attributes; + private MethodImplAttributes implFlags; + private ILGenerator ilgen; + private int rva = -1; + private CallingConventions callingConvention; + private List parameters; + private GenericTypeParameterBuilder[] gtpb; + private List declarativeSecurity; + private MethodSignature methodSignature; + private bool initLocals = true; + + internal MethodBuilder(TypeBuilder typeBuilder, string name, MethodAttributes attributes, CallingConventions callingConvention) + { + this.typeBuilder = typeBuilder; + this.name = name; + this.pseudoToken = typeBuilder.ModuleBuilder.AllocPseudoToken(); + this.attributes = attributes; + if ((attributes & MethodAttributes.Static) == 0) + { + callingConvention |= CallingConventions.HasThis; + } + this.callingConvention = callingConvention; + } + + public ILGenerator GetILGenerator() + { + return GetILGenerator(16); + } + + public ILGenerator GetILGenerator(int streamSize) + { + if (rva != -1) + { + throw new InvalidOperationException(); + } + if (ilgen == null) + { + ilgen = new ILGenerator(typeBuilder.ModuleBuilder, streamSize); + } + return ilgen; + } + + public void __ReleaseILGenerator() + { + if (ilgen != null) + { +#if !NO_SYMBOL_WRITER + if (this.ModuleBuilder.symbolWriter != null) + { + this.ModuleBuilder.symbolWriter.OpenMethod(new SymbolToken(-pseudoToken | 0x06000000), this); + } +#endif + rva = ilgen.WriteBody(initLocals); +#if !NO_SYMBOL_WRITER + if (this.ModuleBuilder.symbolWriter != null) + { + this.ModuleBuilder.symbolWriter.CloseMethod(); + } +#endif + ilgen = null; + } + } + + public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) + { + SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute)); + } + + private void SetDllImportPseudoCustomAttribute(CustomAttributeBuilder customBuilder) + { + CallingConvention? callingConvention = customBuilder.GetFieldValue("CallingConvention"); + CharSet? charSet = customBuilder.GetFieldValue("CharSet"); + SetDllImportPseudoCustomAttribute((string)customBuilder.GetConstructorArgument(0), + (string)customBuilder.GetFieldValue("EntryPoint"), + callingConvention, + charSet, + (bool?)customBuilder.GetFieldValue("BestFitMapping"), + (bool?)customBuilder.GetFieldValue("ThrowOnUnmappableChar"), + (bool?)customBuilder.GetFieldValue("SetLastError"), + (bool?)customBuilder.GetFieldValue("PreserveSig"), + (bool?)customBuilder.GetFieldValue("ExactSpelling")); + } + + internal void SetDllImportPseudoCustomAttribute(string dllName, string entryName, CallingConvention? nativeCallConv, CharSet? nativeCharSet, + bool? bestFitMapping, bool? throwOnUnmappableChar, bool? setLastError, bool? preserveSig, bool? exactSpelling) + { + const short NoMangle = 0x0001; + const short CharSetMask = 0x0006; + const short CharSetNotSpec = 0x0000; + const short CharSetAnsi = 0x0002; + const short CharSetUnicode = 0x0004; + const short CharSetAuto = 0x0006; + const short SupportsLastError = 0x0040; + const short CallConvMask = 0x0700; + const short CallConvWinapi = 0x0100; + const short CallConvCdecl = 0x0200; + const short CallConvStdcall = 0x0300; + const short CallConvThiscall = 0x0400; + const short CallConvFastcall = 0x0500; + // non-standard flags + const short BestFitOn = 0x0010; + const short BestFitOff = 0x0020; + const short CharMapErrorOn = 0x1000; + const short CharMapErrorOff = 0x2000; + short flags = CharSetNotSpec | CallConvWinapi; + if (bestFitMapping.HasValue) + { + flags |= bestFitMapping.Value ? BestFitOn : BestFitOff; + } + if (throwOnUnmappableChar.HasValue) + { + flags |= throwOnUnmappableChar.Value ? CharMapErrorOn : CharMapErrorOff; + } + if (nativeCallConv.HasValue) + { + flags &= ~CallConvMask; + switch (nativeCallConv.Value) + { + case System.Runtime.InteropServices.CallingConvention.Cdecl: + flags |= CallConvCdecl; + break; + case System.Runtime.InteropServices.CallingConvention.FastCall: + flags |= CallConvFastcall; + break; + case System.Runtime.InteropServices.CallingConvention.StdCall: + flags |= CallConvStdcall; + break; + case System.Runtime.InteropServices.CallingConvention.ThisCall: + flags |= CallConvThiscall; + break; + case System.Runtime.InteropServices.CallingConvention.Winapi: + flags |= CallConvWinapi; + break; + } + } + if (nativeCharSet.HasValue) + { + flags &= ~CharSetMask; + switch (nativeCharSet.Value) + { + case CharSet.Ansi: + case CharSet.None: + flags |= CharSetAnsi; + break; + case CharSet.Auto: + flags |= CharSetAuto; + break; + case CharSet.Unicode: + flags |= CharSetUnicode; + break; + } + } + if (exactSpelling.HasValue && exactSpelling.Value) + { + flags |= NoMangle; + } + if (!preserveSig.HasValue || preserveSig.Value) + { + implFlags |= MethodImplAttributes.PreserveSig; + } + if (setLastError.HasValue && setLastError.Value) + { + flags |= SupportsLastError; + } + ImplMapTable.Record rec = new ImplMapTable.Record(); + rec.MappingFlags = flags; + rec.MemberForwarded = pseudoToken; + rec.ImportName = this.ModuleBuilder.Strings.Add(entryName ?? name); + rec.ImportScope = this.ModuleBuilder.ModuleRef.FindOrAddRecord(dllName == null ? 0 : this.ModuleBuilder.Strings.Add(dllName)); + this.ModuleBuilder.ImplMap.AddRecord(rec); + } + + private void SetMethodImplAttribute(CustomAttributeBuilder customBuilder) + { + MethodImplOptions opt; + switch (customBuilder.Constructor.ParameterCount) + { + case 0: + opt = 0; + break; + case 1: + { + object val = customBuilder.GetConstructorArgument(0); + if (val is short) + { + opt = (MethodImplOptions)(short)val; + } + else if (val is int) + { + opt = (MethodImplOptions)(int)val; + } + else + { + opt = (MethodImplOptions)val; + } + break; + } + default: + throw new NotSupportedException(); + } + MethodCodeType? type = customBuilder.GetFieldValue("MethodCodeType"); + implFlags = (MethodImplAttributes)opt; + if (type.HasValue) + { + implFlags |= (MethodImplAttributes)type; + } + } + + public void SetCustomAttribute(CustomAttributeBuilder customBuilder) + { + switch (customBuilder.KnownCA) + { + case KnownCA.DllImportAttribute: + SetDllImportPseudoCustomAttribute(customBuilder.DecodeBlob(this.Module.Assembly)); + attributes |= MethodAttributes.PinvokeImpl; + break; + case KnownCA.MethodImplAttribute: + SetMethodImplAttribute(customBuilder.DecodeBlob(this.Module.Assembly)); + break; + case KnownCA.PreserveSigAttribute: + implFlags |= MethodImplAttributes.PreserveSig; + break; + case KnownCA.SpecialNameAttribute: + attributes |= MethodAttributes.SpecialName; + break; + case KnownCA.SuppressUnmanagedCodeSecurityAttribute: + attributes |= MethodAttributes.HasSecurity; + goto default; + default: + this.ModuleBuilder.SetCustomAttribute(pseudoToken, customBuilder); + break; + } + } + + public void __AddDeclarativeSecurity(CustomAttributeBuilder customBuilder) + { + attributes |= MethodAttributes.HasSecurity; + if (declarativeSecurity == null) + { + declarativeSecurity = new List(); + } + declarativeSecurity.Add(customBuilder); + } + +#if !CORECLR + public void AddDeclarativeSecurity(System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet) + { + this.ModuleBuilder.AddDeclarativeSecurity(pseudoToken, securityAction, permissionSet); + this.attributes |= MethodAttributes.HasSecurity; + } +#endif + + public void SetImplementationFlags(MethodImplAttributes attributes) + { + implFlags = attributes; + } + + public ParameterBuilder DefineParameter(int position, ParameterAttributes attributes, string strParamName) + { + if (parameters == null) + { + parameters = new List(); + } + this.ModuleBuilder.Param.AddVirtualRecord(); + ParameterBuilder pb = new ParameterBuilder(this.ModuleBuilder, position, attributes, strParamName); + if (parameters.Count == 0 || position >= parameters[parameters.Count - 1].Position) + { + parameters.Add(pb); + } + else + { + for (int i = 0; i < parameters.Count; i++) + { + if (parameters[i].Position > position) + { + parameters.Insert(i, pb); + break; + } + } + } + return pb; + } + + private void CheckSig() + { + if (methodSignature != null) + { + throw new InvalidOperationException("The method signature can not be modified after it has been used."); + } + } + + public void SetParameters(params Type[] parameterTypes) + { + CheckSig(); + this.parameterTypes = Util.Copy(parameterTypes); + } + + public void SetReturnType(Type returnType) + { + CheckSig(); + this.returnType = returnType ?? this.Module.universe.System_Void; + } + + public void SetSignature(Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers) + { + SetSignature(returnType, parameterTypes, PackedCustomModifiers.CreateFromExternal(returnTypeOptionalCustomModifiers, returnTypeRequiredCustomModifiers, + parameterTypeOptionalCustomModifiers, parameterTypeRequiredCustomModifiers, Util.NullSafeLength(parameterTypes))); + } + + public void __SetSignature(Type returnType, CustomModifiers returnTypeCustomModifiers, Type[] parameterTypes, CustomModifiers[] parameterTypeCustomModifiers) + { + SetSignature(returnType, parameterTypes, PackedCustomModifiers.CreateFromExternal(returnTypeCustomModifiers, parameterTypeCustomModifiers, Util.NullSafeLength(parameterTypes))); + } + + private void SetSignature(Type returnType, Type[] parameterTypes, PackedCustomModifiers customModifiers) + { + CheckSig(); + this.returnType = returnType ?? this.Module.universe.System_Void; + this.parameterTypes = Util.Copy(parameterTypes); + this.customModifiers = customModifiers; + } + + public GenericTypeParameterBuilder[] DefineGenericParameters(params string[] names) + { + CheckSig(); + if (gtpb != null) + { + throw new InvalidOperationException("Generic parameters already defined."); + } + gtpb = new GenericTypeParameterBuilder[names.Length]; + for (int i = 0; i < names.Length; i++) + { + gtpb[i] = new GenericTypeParameterBuilder(names[i], this, i); + } + return (GenericTypeParameterBuilder[])gtpb.Clone(); + } + + public override MethodInfo MakeGenericMethod(params Type[] typeArguments) + { + return new GenericMethodInstance(typeBuilder, this, typeArguments); + } + + public override MethodInfo GetGenericMethodDefinition() + { + if (gtpb == null) + { + throw new InvalidOperationException(); + } + return this; + } + + public override Type[] GetGenericArguments() + { + return Util.Copy(gtpb); + } + + internal override Type GetGenericMethodArgument(int index) + { + return gtpb[index]; + } + + internal override int GetGenericMethodArgumentCount() + { + return gtpb == null ? 0 : gtpb.Length; + } + + public override Type ReturnType + { + get { return returnType; } + } + + public override ParameterInfo ReturnParameter + { + get { return new ParameterInfoImpl(this, -1); } + } + + public override MethodAttributes Attributes + { + get { return attributes; } + } + + public void __SetAttributes(MethodAttributes attributes) + { + this.attributes = attributes; + } + + public void __SetCallingConvention(CallingConventions callingConvention) + { + this.callingConvention = callingConvention; + this.methodSignature = null; + } + + public override MethodImplAttributes GetMethodImplementationFlags() + { + return implFlags; + } + + private sealed class ParameterInfoImpl : ParameterInfo + { + private readonly MethodBuilder method; + private readonly int parameter; + + internal ParameterInfoImpl(MethodBuilder method, int parameter) + { + this.method = method; + this.parameter = parameter; + } + + private ParameterBuilder ParameterBuilder + { + get + { + if (method.parameters != null) + { + foreach (ParameterBuilder pb in method.parameters) + { + // ParameterBuilder.Position is 1-based + if (pb.Position - 1 == parameter) + { + return pb; + } + } + } + return null; + } + } + + public override string Name + { + get + { + ParameterBuilder pb = this.ParameterBuilder; + return pb != null ? pb.Name : null; + } + } + + public override Type ParameterType + { + get { return parameter == -1 ? method.returnType : method.parameterTypes[parameter]; } + } + + public override ParameterAttributes Attributes + { + get + { + ParameterBuilder pb = this.ParameterBuilder; + return pb != null ? (ParameterAttributes)pb.Attributes : ParameterAttributes.None; + } + } + + public override int Position + { + get { return parameter; } + } + + public override object RawDefaultValue + { + get + { + ParameterBuilder pb = this.ParameterBuilder; + if (pb != null && (pb.Attributes & (int)ParameterAttributes.HasDefault) != 0) + { + return method.ModuleBuilder.Constant.GetRawConstantValue(method.ModuleBuilder, pb.PseudoToken); + } + if (pb != null && (pb.Attributes & (int)ParameterAttributes.Optional) != 0) + { + return Missing.Value; + } + return null; + } + } + + public override CustomModifiers __GetCustomModifiers() + { + return method.customModifiers.GetParameterCustomModifiers(parameter); + } + + public override bool __TryGetFieldMarshal(out FieldMarshal fieldMarshal) + { + fieldMarshal = new FieldMarshal(); + return false; + } + + public override MemberInfo Member + { + get { return method; } + } + + public override int MetadataToken + { + get + { + ParameterBuilder pb = this.ParameterBuilder; + return pb != null ? pb.PseudoToken : 0x08000000; + } + } + + internal override Module Module + { + get { return method.Module; } + } + } + + public override ParameterInfo[] GetParameters() + { + ParameterInfo[] parameters = new ParameterInfo[parameterTypes.Length]; + for (int i = 0; i < parameters.Length; i++) + { + parameters[i] = new ParameterInfoImpl(this, i); + } + return parameters; + } + + internal override int ParameterCount + { + get { return parameterTypes.Length; } + } + + public override Type DeclaringType + { + get { return typeBuilder.IsModulePseudoType ? null : typeBuilder; } + } + + public override string Name + { + get { return name; } + } + + public override CallingConventions CallingConvention + { + get { return callingConvention; } + } + + public override int MetadataToken + { + get { return pseudoToken; } + } + + public override bool IsGenericMethod + { + get { return gtpb != null; } + } + + public override bool IsGenericMethodDefinition + { + get { return gtpb != null; } + } + + public override Module Module + { + get { return typeBuilder.Module; } + } + + public Module GetModule() + { + return typeBuilder.Module; + } + + public MethodToken GetToken() + { + return new MethodToken(pseudoToken); + } + + public override MethodBody GetMethodBody() + { + throw new NotSupportedException(); + } + + public override int __MethodRVA + { + get { throw new NotImplementedException(); } + } + + public bool InitLocals + { + get { return initLocals; } + set { initLocals = value; } + } + + public void __AddUnmanagedExport(string name, int ordinal) + { + this.ModuleBuilder.AddUnmanagedExport(name, ordinal, this, new RelativeVirtualAddress(0xFFFFFFFF)); + } + + public void CreateMethodBody(byte[] il, int count) + { + if (il == null) + { + throw new NotSupportedException(); + } + if (il.Length != count) + { + Array.Resize(ref il, count); + } + SetMethodBody(il, 16, null, null, null); + } + + public void SetMethodBody(byte[] il, int maxStack, byte[] localSignature, IEnumerable exceptionHandlers, IEnumerable tokenFixups) + { + ByteBuffer bb = this.ModuleBuilder.methodBodies; + + if (localSignature == null && exceptionHandlers == null && maxStack <= 8 && il.Length < 64) + { + rva = bb.Position; + ILGenerator.WriteTinyHeader(bb, il.Length); + } + else + { + // fat headers require 4-byte alignment + bb.Align(4); + rva = bb.Position; + ILGenerator.WriteFatHeader(bb, initLocals, exceptionHandlers != null, (ushort)maxStack, il.Length, + localSignature == null ? 0 : this.ModuleBuilder.GetSignatureToken(localSignature, localSignature.Length).Token); + } + + if (tokenFixups != null) + { + ILGenerator.AddTokenFixups(bb.Position, this.ModuleBuilder.tokenFixupOffsets, tokenFixups); + } + bb.Write(il); + + if (exceptionHandlers != null) + { + List exceptions = new List(); + foreach (ExceptionHandler block in exceptionHandlers) + { + exceptions.Add(new ILGenerator.ExceptionBlock(block)); + } + ILGenerator.WriteExceptionHandlers(bb, exceptions); + } + } + + internal void Bake() + { + this.nameIndex = this.ModuleBuilder.Strings.Add(name); + this.signature = this.ModuleBuilder.GetSignatureBlobIndex(this.MethodSignature); + + __ReleaseILGenerator(); + + if (declarativeSecurity != null) + { + this.ModuleBuilder.AddDeclarativeSecurity(pseudoToken, declarativeSecurity); + } + } + + internal ModuleBuilder ModuleBuilder + { + get { return typeBuilder.ModuleBuilder; } + } + + internal void WriteMethodDefRecord(int baseRVA, MetadataWriter mw, ref int paramList) + { + if (rva != -1) + { + mw.Write(rva + baseRVA); + } + else + { + mw.Write(0); + } + mw.Write((short)implFlags); + mw.Write((short)attributes); + mw.WriteStringIndex(nameIndex); + mw.WriteBlobIndex(signature); + mw.WriteParam(paramList); + if (parameters != null) + { + paramList += parameters.Count; + } + } + + internal void WriteParamRecords(MetadataWriter mw) + { + if (parameters != null) + { + foreach (ParameterBuilder pb in parameters) + { + pb.WriteParamRecord(mw); + } + } + } + + internal void FixupToken(int token, ref int parameterToken) + { + typeBuilder.ModuleBuilder.RegisterTokenFixup(this.pseudoToken, token); + if (parameters != null) + { + foreach (ParameterBuilder pb in parameters) + { + pb.FixupToken(parameterToken++); + } + } + } + + internal override MethodSignature MethodSignature + { + get + { + if (methodSignature == null) + { + methodSignature = MethodSignature.MakeFromBuilder(returnType ?? typeBuilder.Universe.System_Void, parameterTypes ?? Type.EmptyTypes, + customModifiers, callingConvention, gtpb == null ? 0 : gtpb.Length); + } + return methodSignature; + } + } + + internal override int ImportTo(ModuleBuilder other) + { + return other.ImportMethodOrField(typeBuilder, name, this.MethodSignature); + } + + internal void CheckBaked() + { + typeBuilder.CheckBaked(); + } + + internal override int GetCurrentToken() + { + if (typeBuilder.ModuleBuilder.IsSaved) + { + return typeBuilder.ModuleBuilder.ResolvePseudoToken(pseudoToken); + } + else + { + return pseudoToken; + } + } + + internal override bool IsBaked + { + get { return typeBuilder.IsBaked; } + } + } +} diff --git a/reflect/Emit/ModuleBuilder.cs b/reflect/Emit/ModuleBuilder.cs new file mode 100644 index 0000000..8ceea42 --- /dev/null +++ b/reflect/Emit/ModuleBuilder.cs @@ -0,0 +1,2019 @@ +/* + Copyright (C) 2008-2015 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.IO; +using System.Diagnostics; +#if !NO_SYMBOL_WRITER +using System.Diagnostics.SymbolStore; +#endif +using System.Security.Cryptography; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using IKVM.Reflection.Impl; +using IKVM.Reflection.Metadata; +using IKVM.Reflection.Writer; + +namespace IKVM.Reflection.Emit +{ + public sealed class ModuleBuilder : Module, ITypeOwner + { + private static readonly bool usePublicKeyAssemblyReference = false; + private Guid mvid; + private uint timestamp; + private long imageBaseAddress = 0x00400000; + private long stackReserve = -1; + private int fileAlignment = 0x200; + private DllCharacteristics dllCharacteristics = DllCharacteristics.DynamicBase | DllCharacteristics.NoSEH | DllCharacteristics.NXCompat | DllCharacteristics.TerminalServerAware; + private readonly AssemblyBuilder asm; + internal readonly string moduleName; + internal readonly string fileName; + internal readonly ISymbolWriterImpl symbolWriter; + private readonly TypeBuilder moduleType; + private readonly List types = new List(); + private readonly Dictionary typeTokens = new Dictionary(); + private readonly Dictionary memberRefTypeTokens = new Dictionary(); + internal readonly ByteBuffer methodBodies = new ByteBuffer(128 * 1024); + internal readonly List tokenFixupOffsets = new List(); + internal readonly ByteBuffer initializedData = new ByteBuffer(512); + internal ResourceSection unmanagedResources; + private readonly Dictionary importedMemberRefs = new Dictionary(); + private readonly Dictionary importedMethodSpecs = new Dictionary(); + private readonly Dictionary referencedAssemblies = new Dictionary(); + private List referencedAssemblyNames; + private int nextPseudoToken = -1; + private readonly List resolvedTokens = new List(); + internal readonly TableHeap Tables = new TableHeap(); + internal readonly StringHeap Strings = new StringHeap(); + internal readonly UserStringHeap UserStrings = new UserStringHeap(); + internal readonly GuidHeap Guids = new GuidHeap(); + internal readonly BlobHeap Blobs = new BlobHeap(); + internal readonly List vtablefixups = new List(); + internal readonly List unmanagedExports = new List(); + private List interfaceImplCustomAttributes; + private readonly List resourceWriters = new List(); + private bool saved; + + private struct ResourceWriterRecord + { + private readonly string name; +#if !CORECLR + private readonly ResourceWriter rw; +#endif + private readonly Stream stream; + private readonly ResourceAttributes attributes; + +#if CORECLR + internal ResourceWriterRecord(string name, Stream stream, ResourceAttributes attributes) + { + this.name = name; + this.stream = stream; + this.attributes = attributes; + } +#else + internal ResourceWriterRecord(string name, Stream stream, ResourceAttributes attributes) + : this(name, null, stream, attributes) + { + } + + internal ResourceWriterRecord(string name, ResourceWriter rw, Stream stream, ResourceAttributes attributes) + { + this.name = name; + this.rw = rw; + this.stream = stream; + this.attributes = attributes; + } +#endif + + internal void Emit(ModuleBuilder mb, int offset) + { +#if !CORECLR + if (rw != null) + { + rw.Generate(); + } +#endif + ManifestResourceTable.Record rec = new ManifestResourceTable.Record(); + rec.Offset = offset; + rec.Flags = (int)attributes; + rec.Name = mb.Strings.Add(name); + rec.Implementation = 0; + mb.ManifestResource.AddRecord(rec); + } + + internal int GetLength() + { + return 4 + (int)stream.Length; + } + + internal void Write(MetadataWriter mw) + { + mw.Write((int)stream.Length); + stream.Position = 0; + byte[] buffer = new byte[8192]; + int length; + while ((length = stream.Read(buffer, 0, buffer.Length)) != 0) + { + mw.Write(buffer, 0, length); + } + } + + internal void Close() + { +#if !CORECLR + if (rw != null) + { + rw.Close(); + } +#endif + } + } + + internal struct VTableFixups + { + internal uint initializedDataOffset; + internal ushort count; + internal ushort type; + + internal int SlotWidth + { + get { return (type & 0x02) == 0 ? 4 : 8; } + } + } + + struct InterfaceImplCustomAttribute + { + internal int type; + internal int interfaceType; + internal int pseudoToken; + } + + struct MemberRefKey : IEquatable + { + private readonly Type type; + private readonly string name; + private readonly Signature signature; + + internal MemberRefKey(Type type, string name, Signature signature) + { + this.type = type; + this.name = name; + this.signature = signature; + } + + public bool Equals(MemberRefKey other) + { + return other.type.Equals(type) + && other.name == name + && other.signature.Equals(signature); + } + + public override bool Equals(object obj) + { + MemberRefKey? other = obj as MemberRefKey?; + return other != null && Equals(other.Value); + } + + public override int GetHashCode() + { + return type.GetHashCode() + name.GetHashCode() + signature.GetHashCode(); + } + + internal MethodBase LookupMethod() + { + return type.FindMethod(name, (MethodSignature)signature); + } + } + + struct MethodSpecKey : IEquatable + { + private readonly Type type; + private readonly string name; + private readonly MethodSignature signature; + private readonly Type[] genericParameters; + + internal MethodSpecKey(Type type, string name, MethodSignature signature, Type[] genericParameters) + { + this.type = type; + this.name = name; + this.signature = signature; + this.genericParameters = genericParameters; + } + + public bool Equals(MethodSpecKey other) + { + return other.type.Equals(type) + && other.name == name + && other.signature.Equals(signature) + && Util.ArrayEquals(other.genericParameters, genericParameters); + } + + public override bool Equals(object obj) + { + MethodSpecKey? other = obj as MethodSpecKey?; + return other != null && Equals(other.Value); + } + + public override int GetHashCode() + { + return type.GetHashCode() + name.GetHashCode() + signature.GetHashCode() + Util.GetHashCode(genericParameters); + } + } + + internal ModuleBuilder(AssemblyBuilder asm, string moduleName, string fileName, bool emitSymbolInfo) + : base(asm.universe) + { + this.asm = asm; + this.moduleName = moduleName; + this.fileName = fileName; + if (emitSymbolInfo) + { + symbolWriter = SymbolSupport.CreateSymbolWriterFor(this); + if (universe.Deterministic && !symbolWriter.IsDeterministic) + { + throw new NotSupportedException(); + } + } + if (!universe.Deterministic) + { + __PEHeaderTimeDateStamp = DateTime.UtcNow; + mvid = Guid.NewGuid(); + } + // must be the first record in the TypeDef table + moduleType = new TypeBuilder(this, null, ""); + types.Add(moduleType); + } + + internal void PopulatePropertyAndEventTables() + { + // LAMESPEC the PropertyMap and EventMap tables are not required to be sorted by the CLI spec, + // but .NET sorts them and Mono requires them to be sorted, so we have to populate the + // tables in the right order + foreach (TypeBuilder type in types) + { + type.PopulatePropertyAndEventTables(); + } + } + + internal void WriteTypeDefTable(MetadataWriter mw) + { + int fieldList = 1; + int methodList = 1; + foreach (TypeBuilder type in types) + { + type.WriteTypeDefRecord(mw, ref fieldList, ref methodList); + } + } + + internal void WriteMethodDefTable(int baseRVA, MetadataWriter mw) + { + int paramList = 1; + foreach (TypeBuilder type in types) + { + type.WriteMethodDefRecords(baseRVA, mw, ref paramList); + } + } + + internal void WriteParamTable(MetadataWriter mw) + { + foreach (TypeBuilder type in types) + { + type.WriteParamRecords(mw); + } + } + + internal void WriteFieldTable(MetadataWriter mw) + { + foreach (TypeBuilder type in types) + { + type.WriteFieldRecords(mw); + } + } + + internal int AllocPseudoToken() + { + return nextPseudoToken--; + } + + public TypeBuilder DefineType(string name) + { + return DefineType(name, TypeAttributes.Class); + } + + public TypeBuilder DefineType(string name, TypeAttributes attr) + { + return DefineType(name, attr, null); + } + + public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent) + { + return DefineType(name, attr, parent, PackingSize.Unspecified, 0); + } + + public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, int typesize) + { + return DefineType(name, attr, parent, PackingSize.Unspecified, typesize); + } + + public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, PackingSize packsize) + { + return DefineType(name, attr, parent, packsize, 0); + } + + public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, Type[] interfaces) + { + TypeBuilder tb = DefineType(name, attr, parent); + foreach (Type iface in interfaces) + { + tb.AddInterfaceImplementation(iface); + } + return tb; + } + + public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize) + { + string ns = null; + int lastdot = name.LastIndexOf('.'); + if (lastdot > 0) + { + ns = name.Substring(0, lastdot); + name = name.Substring(lastdot + 1); + } + TypeBuilder typeBuilder = __DefineType(ns, name); + typeBuilder.__SetAttributes(attr); + typeBuilder.SetParent(parent); + if (packingSize != PackingSize.Unspecified || typesize != 0) + { + typeBuilder.__SetLayout((int)packingSize, typesize); + } + return typeBuilder; + } + + public TypeBuilder __DefineType(string ns, string name) + { + return DefineType(this, ns, name); + } + + internal TypeBuilder DefineType(ITypeOwner owner, string ns, string name) + { + TypeBuilder typeBuilder = new TypeBuilder(owner, ns, name); + types.Add(typeBuilder); + return typeBuilder; + } + + public EnumBuilder DefineEnum(string name, TypeAttributes visibility, Type underlyingType) + { + TypeBuilder tb = DefineType(name, (visibility & TypeAttributes.VisibilityMask) | TypeAttributes.Sealed, universe.System_Enum); + FieldBuilder fb = tb.DefineField("value__", underlyingType, FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName); + return new EnumBuilder(tb, fb); + } + + public FieldBuilder __DefineField(string name, Type type, CustomModifiers customModifiers, FieldAttributes attributes) + { + return moduleType.__DefineField(name, type, customModifiers, attributes); + } + + [Obsolete("Please use __DefineField(string, Type, CustomModifiers, FieldAttributes) instead.")] + public FieldBuilder __DefineField(string name, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes) + { + return moduleType.DefineField(name, type, requiredCustomModifiers, optionalCustomModifiers, attributes); + } + + public ConstructorBuilder __DefineModuleInitializer(MethodAttributes visibility) + { + return moduleType.DefineConstructor(visibility | MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, Type.EmptyTypes); + } + + public FieldBuilder DefineUninitializedData(string name, int size, FieldAttributes attributes) + { + return moduleType.DefineUninitializedData(name, size, attributes); + } + + public FieldBuilder DefineInitializedData(string name, byte[] data, FieldAttributes attributes) + { + return moduleType.DefineInitializedData(name, data, attributes); + } + + public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes) + { + return moduleType.DefineMethod(name, attributes, returnType, parameterTypes); + } + + public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes) + { + return moduleType.DefineMethod(name, attributes, callingConvention, returnType, parameterTypes); + } + + public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers) + { + return moduleType.DefineMethod(name, attributes, callingConvention, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers); + } + + public MethodBuilder DefinePInvokeMethod(string name, string dllName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet) + { + return moduleType.DefinePInvokeMethod(name, dllName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet); + } + + public MethodBuilder DefinePInvokeMethod(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet) + { + return moduleType.DefinePInvokeMethod(name, dllName, entryName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet); + } + + public void CreateGlobalFunctions() + { + moduleType.CreateType(); + } + + internal void AddTypeForwarder(Type type, bool includeNested) + { + ExportType(type); + if (includeNested && !type.__IsMissing) + { + foreach (Type nested in type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic)) + { + // we export all nested types (i.e. even the private ones) + // (this behavior is the same as the C# compiler) + AddTypeForwarder(nested, true); + } + } + } + + private int ExportType(Type type) + { + ExportedTypeTable.Record rec = new ExportedTypeTable.Record(); + if (asm.ImageRuntimeVersion == "v2.0.50727") + { + // HACK we should *not* set the TypeDefId in this case, but 2.0 and 3.5 peverify gives a warning if it is missing (4.5 doesn't) + rec.TypeDefId = type.MetadataToken; + } + SetTypeNameAndTypeNamespace(type.TypeName, out rec.TypeName, out rec.TypeNamespace); + if (type.IsNested) + { + rec.Flags = 0; + rec.Implementation = ExportType(type.DeclaringType); + } + else + { + rec.Flags = 0x00200000; // CorTypeAttr.tdForwarder + rec.Implementation = ImportAssemblyRef(type.Assembly); + } + return 0x27000000 | this.ExportedType.FindOrAddRecord(rec); + } + + private void SetTypeNameAndTypeNamespace(TypeName name, out int typeName, out int typeNamespace) + { + typeName = this.Strings.Add(name.Name); + typeNamespace = name.Namespace == null ? 0 : this.Strings.Add(name.Namespace); + } + + public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) + { + SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute)); + } + + public void SetCustomAttribute(CustomAttributeBuilder customBuilder) + { + SetCustomAttribute(0x00000001, customBuilder); + } + + internal void SetCustomAttribute(int token, CustomAttributeBuilder customBuilder) + { + CustomAttributeTable.Record rec = new CustomAttributeTable.Record(); + rec.Parent = token; + rec.Type = asm.IsWindowsRuntime ? customBuilder.Constructor.ImportTo(this) : GetConstructorToken(customBuilder.Constructor).Token; + rec.Value = customBuilder.WriteBlob(this); + this.CustomAttribute.AddRecord(rec); + } + + private void AddDeclSecurityRecord(int token, int action, int blob) + { + DeclSecurityTable.Record rec = new DeclSecurityTable.Record(); + rec.Action = (short)action; + rec.Parent = token; + rec.PermissionSet = blob; + this.DeclSecurity.AddRecord(rec); + } + +#if !CORECLR + internal void AddDeclarativeSecurity(int token, System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet) + { + // like Ref.Emit, we're using the .NET 1.x xml format + AddDeclSecurityRecord(token, (int)securityAction, this.Blobs.Add(ByteBuffer.Wrap(System.Text.Encoding.Unicode.GetBytes(permissionSet.ToXml().ToString())))); + } +#endif + + internal void AddDeclarativeSecurity(int token, List declarativeSecurity) + { + Dictionary> ordered = new Dictionary>(); + foreach (CustomAttributeBuilder cab in declarativeSecurity) + { + int action; + // check for HostProtectionAttribute without SecurityAction + if (cab.ConstructorArgumentCount == 0) + { + action = (int)System.Security.Permissions.SecurityAction.LinkDemand; + } + else + { + action = (int)cab.GetConstructorArgument(0); + } + if (cab.IsLegacyDeclSecurity) + { + AddDeclSecurityRecord(token, action, cab.WriteLegacyDeclSecurityBlob(this)); + continue; + } + List list; + if (!ordered.TryGetValue(action, out list)) + { + list = new List(); + ordered.Add(action, list); + } + list.Add(cab); + } + foreach (KeyValuePair> kv in ordered) + { + AddDeclSecurityRecord(token, kv.Key, WriteDeclSecurityBlob(kv.Value)); + } + } + + private int WriteDeclSecurityBlob(List list) + { + ByteBuffer namedArgs = new ByteBuffer(100); + ByteBuffer bb = new ByteBuffer(list.Count * 100); + bb.Write((byte)'.'); + bb.WriteCompressedUInt(list.Count); + foreach (CustomAttributeBuilder cab in list) + { + bb.Write(cab.Constructor.DeclaringType.AssemblyQualifiedName); + namedArgs.Clear(); + cab.WriteNamedArgumentsForDeclSecurity(this, namedArgs); + bb.WriteCompressedUInt(namedArgs.Length); + bb.Write(namedArgs); + } + return this.Blobs.Add(bb); + } + + public void DefineManifestResource(string name, Stream stream, ResourceAttributes attribute) + { + resourceWriters.Add(new ResourceWriterRecord(name, stream, attribute)); + } + +#if !CORECLR + public IResourceWriter DefineResource(string name, string description) + { + return DefineResource(name, description, ResourceAttributes.Public); + } + + public IResourceWriter DefineResource(string name, string description, ResourceAttributes attribute) + { + // FXBUG we ignore the description, because there is no such thing + + MemoryStream mem = new MemoryStream(); + ResourceWriter rw = new ResourceWriter(mem); + resourceWriters.Add(new ResourceWriterRecord(name, rw, mem, attribute)); + return rw; + } +#endif + + internal void EmitResources() + { + int offset = 0; + foreach (ResourceWriterRecord rwr in resourceWriters) + { + // resources must be 8-byte aligned + offset = (offset + 7) & ~7; + rwr.Emit(this, offset); + offset += rwr.GetLength(); + } + } + + internal void WriteResources(MetadataWriter mw) + { + int offset = 0; + foreach (ResourceWriterRecord rwr in resourceWriters) + { + // resources must be 8-byte aligned + int alignment = ((offset + 7) & ~7) - offset; + for (int i = 0; i < alignment; i++) + { + mw.Write((byte)0); + } + rwr.Write(mw); + offset += rwr.GetLength() + alignment; + } + } + + internal void CloseResources() + { + foreach (ResourceWriterRecord rwr in resourceWriters) + { + rwr.Close(); + } + } + + internal int GetManifestResourcesLength() + { + int length = 0; + foreach (ResourceWriterRecord rwr in resourceWriters) + { + // resources must be 8-byte aligned + length = (length + 7) & ~7; + length += rwr.GetLength(); + } + return length; + } + + public override Assembly Assembly + { + get { return asm; } + } + + internal override Type FindType(TypeName name) + { + foreach (Type type in types) + { + if (type.TypeName == name) + { + return type; + } + } + return null; + } + + internal override Type FindTypeIgnoreCase(TypeName lowerCaseName) + { + foreach (Type type in types) + { + if (type.TypeName.ToLowerInvariant() == lowerCaseName) + { + return type; + } + } + return null; + } + + internal override void GetTypesImpl(List list) + { + foreach (Type type in types) + { + if (type != moduleType) + { + list.Add(type); + } + } + } + +#if !NO_SYMBOL_WRITER + public ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType) + { + return symbolWriter.DefineDocument(url, language, languageVendor, documentType); + } +#endif + + public int __GetAssemblyToken(Assembly assembly) + { + return ImportAssemblyRef(assembly); + } + + public TypeToken GetTypeToken(string name) + { + return new TypeToken(GetType(name, true, false).MetadataToken); + } + + public TypeToken GetTypeToken(Type type) + { + if (type.Module == this && !asm.IsWindowsRuntime) + { + return new TypeToken(type.GetModuleBuilderToken()); + } + else + { + return new TypeToken(ImportType(type)); + } + } + + internal int GetTypeTokenForMemberRef(Type type) + { + if (type.__IsMissing) + { + return ImportType(type); + } + else if (type.IsGenericTypeDefinition) + { + int token; + if (!memberRefTypeTokens.TryGetValue(type, out token)) + { + ByteBuffer spec = new ByteBuffer(5); + Signature.WriteTypeSpec(this, spec, type); + token = 0x1B000000 | this.TypeSpec.AddRecord(this.Blobs.Add(spec)); + memberRefTypeTokens.Add(type, token); + } + return token; + } + else if (type.IsModulePseudoType) + { + return 0x1A000000 | this.ModuleRef.FindOrAddRecord(this.Strings.Add(type.Module.ScopeName)); + } + else + { + return GetTypeToken(type).Token; + } + } + + private static bool IsFromGenericTypeDefinition(MemberInfo member) + { + Type decl = member.DeclaringType; + return decl != null && !decl.__IsMissing && decl.IsGenericTypeDefinition; + } + + public FieldToken GetFieldToken(FieldInfo field) + { + // NOTE for some reason, when TypeBuilder.GetFieldToken() is used on a field in a generic type definition, + // a memberref token is returned (confirmed on .NET) unlike for Get(Method|Constructor)Token which always + // simply returns the MethodDef token (if the method is from the same module). + FieldBuilder fb = field as FieldBuilder; + if (fb != null && fb.Module == this && !IsFromGenericTypeDefinition(fb)) + { + return new FieldToken(fb.MetadataToken); + } + else + { + return new FieldToken(field.ImportTo(this)); + } + } + + public MethodToken GetMethodToken(MethodInfo method) + { + MethodBuilder mb = method as MethodBuilder; + if (mb != null && mb.ModuleBuilder == this) + { + return new MethodToken(mb.MetadataToken); + } + else + { + return new MethodToken(method.ImportTo(this)); + } + } + + // new in .NET 4.5 + public MethodToken GetMethodToken(MethodInfo method, IEnumerable optionalParameterTypes) + { + return __GetMethodToken(method, Util.ToArray(optionalParameterTypes), null); + } + + public MethodToken __GetMethodToken(MethodInfo method, Type[] optionalParameterTypes, CustomModifiers[] customModifiers) + { + ByteBuffer sig = new ByteBuffer(16); + method.MethodSignature.WriteMethodRefSig(this, sig, optionalParameterTypes, customModifiers); + MemberRefTable.Record record = new MemberRefTable.Record(); + if (method.Module == this) + { + record.Class = method.MetadataToken; + } + else + { + record.Class = GetTypeTokenForMemberRef(method.DeclaringType ?? method.Module.GetModuleType()); + } + record.Name = Strings.Add(method.Name); + record.Signature = Blobs.Add(sig); + return new MethodToken(0x0A000000 | MemberRef.FindOrAddRecord(record)); + } + + // when we refer to a method on a generic type definition in the IL stream, + // we need to use a MemberRef (even if the method is in the same module) + internal MethodToken GetMethodTokenForIL(MethodInfo method) + { + if (method.IsGenericMethodDefinition) + { + method = method.MakeGenericMethod(method.GetGenericArguments()); + } + if (IsFromGenericTypeDefinition(method)) + { + return new MethodToken(method.ImportTo(this)); + } + else + { + return GetMethodToken(method); + } + } + + internal int GetMethodTokenWinRT(MethodInfo method) + { + return asm.IsWindowsRuntime ? method.ImportTo(this) : GetMethodToken(method).Token; + } + + public MethodToken GetConstructorToken(ConstructorInfo constructor) + { + return GetMethodToken(constructor.GetMethodInfo()); + } + + // new in .NET 4.5 + public MethodToken GetConstructorToken(ConstructorInfo constructor, IEnumerable optionalParameterTypes) + { + return GetMethodToken(constructor.GetMethodInfo(), optionalParameterTypes); + } + + public MethodToken __GetConstructorToken(ConstructorInfo constructor, Type[] optionalParameterTypes, CustomModifiers[] customModifiers) + { + return __GetMethodToken(constructor.GetMethodInfo(), optionalParameterTypes, customModifiers); + } + + internal int ImportMethodOrField(Type declaringType, string name, Signature sig) + { + int token; + MemberRefKey key = new MemberRefKey(declaringType, name, sig); + if (!importedMemberRefs.TryGetValue(key, out token)) + { + MemberRefTable.Record rec = new MemberRefTable.Record(); + rec.Class = GetTypeTokenForMemberRef(declaringType); + rec.Name = this.Strings.Add(name); + ByteBuffer bb = new ByteBuffer(16); + sig.WriteSig(this, bb); + rec.Signature = this.Blobs.Add(bb); + token = 0x0A000000 | this.MemberRef.AddRecord(rec); + importedMemberRefs.Add(key, token); + } + return token; + } + + internal int ImportMethodSpec(Type declaringType, MethodInfo method, Type[] genericParameters) + { + Debug.Assert(method.__IsMissing || method.GetMethodOnTypeDefinition() == method); + int token; + MethodSpecKey key = new MethodSpecKey(declaringType, method.Name, method.MethodSignature, genericParameters); + if (!importedMethodSpecs.TryGetValue(key, out token)) + { + MethodSpecTable.Record rec = new MethodSpecTable.Record(); + MethodBuilder mb = method as MethodBuilder; + if (mb != null && mb.ModuleBuilder == this && !declaringType.IsGenericType) + { + rec.Method = mb.MetadataToken; + } + else + { + // we're calling ImportMethodOrField directly here, because 'method' may be a MethodDef on a generic TypeDef and 'declaringType' the type instance + // (in order words the method and type have already been decoupled by the caller) + rec.Method = ImportMethodOrField(declaringType, method.Name, method.MethodSignature); + } + Writer.ByteBuffer spec = new Writer.ByteBuffer(10); + Signature.WriteMethodSpec(this, spec, genericParameters); + rec.Instantiation = this.Blobs.Add(spec); + token = 0x2B000000 | this.MethodSpec.FindOrAddRecord(rec); + importedMethodSpecs.Add(key, token); + } + return token; + } + + internal int ImportType(Type type) + { + int token; + if (!typeTokens.TryGetValue(type, out token)) + { + if (type.HasElementType || type.IsConstructedGenericType || type.__IsFunctionPointer) + { + ByteBuffer spec = new ByteBuffer(5); + Signature.WriteTypeSpec(this, spec, type); + token = 0x1B000000 | this.TypeSpec.AddRecord(this.Blobs.Add(spec)); + } + else + { + TypeRefTable.Record rec = new TypeRefTable.Record(); + if (type.IsNested) + { + rec.ResolutionScope = GetTypeToken(type.DeclaringType).Token; + } + else if (type.Module == this) + { + rec.ResolutionScope = 1; + } + else + { + rec.ResolutionScope = ImportAssemblyRef(type.Assembly); + } + SetTypeNameAndTypeNamespace(type.TypeName, out rec.TypeName, out rec.TypeNamespace); + token = 0x01000000 | this.TypeRef.AddRecord(rec); + } + typeTokens.Add(type, token); + } + return token; + } + + private int ImportAssemblyRef(Assembly asm) + { + int token; + if (!referencedAssemblies.TryGetValue(asm, out token)) + { + // We can't write the AssemblyRef record here yet, because the identity of the assembly can still change + // (if it's an AssemblyBuilder). + token = AllocPseudoToken(); + referencedAssemblies.Add(asm, token); + } + return token; + } + + internal void FillAssemblyRefTable() + { + foreach (KeyValuePair kv in referencedAssemblies) + { + if (IsPseudoToken(kv.Value)) + { + RegisterTokenFixup(kv.Value, FindOrAddAssemblyRef(kv.Key.GetName(), false)); + } + } + } + + private int FindOrAddAssemblyRef(AssemblyName name, bool alwaysAdd) + { + AssemblyRefTable.Record rec = new AssemblyRefTable.Record(); + Version ver = name.Version ?? new Version(0, 0, 0, 0); + rec.MajorVersion = (ushort)ver.Major; + rec.MinorVersion = (ushort)ver.Minor; + rec.BuildNumber = (ushort)ver.Build; + rec.RevisionNumber = (ushort)ver.Revision; + rec.Flags = (int)(name.Flags & ~AssemblyNameFlags.PublicKey); + const AssemblyNameFlags afPA_Specified = (AssemblyNameFlags)0x0080; + const AssemblyNameFlags afPA_Mask = (AssemblyNameFlags)0x0070; + if ((name.RawFlags & afPA_Specified) != 0) + { + rec.Flags |= (int)(name.RawFlags & afPA_Mask); + } + if (name.ContentType == AssemblyContentType.WindowsRuntime) + { + rec.Flags |= 0x0200; + } + byte[] publicKeyOrToken = null; + if (usePublicKeyAssemblyReference) + { + publicKeyOrToken = name.GetPublicKey(); + } + if (publicKeyOrToken == null || publicKeyOrToken.Length == 0) + { + publicKeyOrToken = name.GetPublicKeyToken() ?? Empty.Array; + } + else + { + const int PublicKey = 0x0001; + rec.Flags |= PublicKey; + } + rec.PublicKeyOrToken = this.Blobs.Add(ByteBuffer.Wrap(publicKeyOrToken)); + rec.Name = this.Strings.Add(name.Name); + rec.Culture = name.Culture == null ? 0 : this.Strings.Add(name.Culture); + if (name.hash != null) + { + rec.HashValue = this.Blobs.Add(ByteBuffer.Wrap(name.hash)); + } + else + { + rec.HashValue = 0; + } + return 0x23000000 | (alwaysAdd ? this.AssemblyRef.AddRecord(rec) : this.AssemblyRef.FindOrAddRecord(rec)); + } + + internal void WriteSymbolTokenMap() + { + for (int i = 0; i < resolvedTokens.Count; i++) + { + int newToken = resolvedTokens[i]; + // The symbol API doesn't support remapping arbitrary integers, the types have to be the same, + // so we copy the type from the newToken, because our pseudo tokens don't have a type. + // (see MethodToken.SymbolToken) + int oldToken = (i + 1) | (newToken & ~0xFFFFFF); + SymbolSupport.RemapToken(symbolWriter, oldToken, newToken); + } + } + + internal void RegisterTokenFixup(int pseudoToken, int realToken) + { + int index = -(pseudoToken + 1); + while (resolvedTokens.Count <= index) + { + resolvedTokens.Add(0); + } + resolvedTokens[index] = realToken; + } + + internal static bool IsPseudoToken(int token) + { + return token < 0; + } + + internal int ResolvePseudoToken(int pseudoToken) + { + int index = -(pseudoToken + 1); + return resolvedTokens[index]; + } + + internal void ApplyUnmanagedExports(ImageFileMachine imageFileMachine) + { + if (unmanagedExports.Count != 0) + { + int type; + int size; + switch (imageFileMachine) + { + case ImageFileMachine.I386: + case ImageFileMachine.ARM: + type = 0x05; + size = 4; + break; + case ImageFileMachine.AMD64: + type = 0x06; + size = 8; + break; + default: + throw new NotSupportedException(); + } + List methods = new List(); + for (int i = 0; i < unmanagedExports.Count; i++) + { + if (unmanagedExports[i].mb != null) + { + methods.Add(unmanagedExports[i].mb); + } + } + if (methods.Count != 0) + { + RelativeVirtualAddress rva = __AddVTableFixups(methods.ToArray(), type); + for (int i = 0; i < unmanagedExports.Count; i++) + { + if (unmanagedExports[i].mb != null) + { + UnmanagedExport exp = unmanagedExports[i]; + exp.rva = new RelativeVirtualAddress(rva.initializedDataOffset + (uint)(methods.IndexOf(unmanagedExports[i].mb) * size)); + unmanagedExports[i] = exp; + } + } + } + } + } + + internal void FixupMethodBodyTokens() + { + int methodToken = 0x06000001; + int fieldToken = 0x04000001; + int parameterToken = 0x08000001; + foreach (TypeBuilder type in types) + { + type.ResolveMethodAndFieldTokens(ref methodToken, ref fieldToken, ref parameterToken); + } + foreach (int offset in tokenFixupOffsets) + { + methodBodies.Position = offset; + int pseudoToken = methodBodies.GetInt32AtCurrentPosition(); + methodBodies.Write(ResolvePseudoToken(pseudoToken)); + } + foreach (VTableFixups fixup in vtablefixups) + { + for (int i = 0; i < fixup.count; i++) + { + initializedData.Position = (int)fixup.initializedDataOffset + i * fixup.SlotWidth; + initializedData.Write(ResolvePseudoToken(initializedData.GetInt32AtCurrentPosition())); + } + } + } + + private int GetHeaderLength() + { + return + 4 + // Signature + 2 + // MajorVersion + 2 + // MinorVersion + 4 + // Reserved + 4 + // ImageRuntimeVersion Length + StringToPaddedUTF8Length(asm.ImageRuntimeVersion) + + 2 + // Flags + 2 + // Streams + 4 + // #~ Offset + 4 + // #~ Size + 4 + // StringToPaddedUTF8Length("#~") + 4 + // #Strings Offset + 4 + // #Strings Size + 12 + // StringToPaddedUTF8Length("#Strings") + 4 + // #US Offset + 4 + // #US Size + 4 + // StringToPaddedUTF8Length("#US") + 4 + // #GUID Offset + 4 + // #GUID Size + 8 + // StringToPaddedUTF8Length("#GUID") + (Blobs.IsEmpty ? 0 : + ( + 4 + // #Blob Offset + 4 + // #Blob Size + 8 // StringToPaddedUTF8Length("#Blob") + )); + } + + internal int MetadataLength + { + get + { + return GetHeaderLength() + (Blobs.IsEmpty ? 0 : Blobs.Length) + Tables.Length + Strings.Length + UserStrings.Length + Guids.Length; + } + } + + internal void WriteMetadata(MetadataWriter mw, out int guidHeapOffset) + { + mw.Write(0x424A5342); // Signature ("BSJB") + mw.Write((ushort)1); // MajorVersion + mw.Write((ushort)1); // MinorVersion + mw.Write(0); // Reserved + byte[] version = StringToPaddedUTF8(asm.ImageRuntimeVersion); + mw.Write(version.Length); // Length + mw.Write(version); + mw.Write((ushort)0); // Flags + // #Blob is the only optional heap + if (Blobs.IsEmpty) + { + mw.Write((ushort)4); // Streams + } + else + { + mw.Write((ushort)5); // Streams + } + + int offset = GetHeaderLength(); + + // Streams + mw.Write(offset); // Offset + mw.Write(Tables.Length); // Size + mw.Write(StringToPaddedUTF8("#~")); + offset += Tables.Length; + + mw.Write(offset); // Offset + mw.Write(Strings.Length); // Size + mw.Write(StringToPaddedUTF8("#Strings")); + offset += Strings.Length; + + mw.Write(offset); // Offset + mw.Write(UserStrings.Length); // Size + mw.Write(StringToPaddedUTF8("#US")); + offset += UserStrings.Length; + + mw.Write(offset); // Offset + mw.Write(Guids.Length); // Size + mw.Write(StringToPaddedUTF8("#GUID")); + offset += Guids.Length; + + if (!Blobs.IsEmpty) + { + mw.Write(offset); // Offset + mw.Write(Blobs.Length); // Size + mw.Write(StringToPaddedUTF8("#Blob")); + } + + Tables.Write(mw); + Strings.Write(mw); + UserStrings.Write(mw); + guidHeapOffset = mw.Position; + Guids.Write(mw); + if (!Blobs.IsEmpty) + { + Blobs.Write(mw); + } + } + + private static int StringToPaddedUTF8Length(string str) + { + return (System.Text.Encoding.UTF8.GetByteCount(str) + 4) & ~3; + } + + private static byte[] StringToPaddedUTF8(string str) + { + byte[] buf = new byte[(System.Text.Encoding.UTF8.GetByteCount(str) + 4) & ~3]; + System.Text.Encoding.UTF8.GetBytes(str, 0, str.Length, buf, 0); + return buf; + } + + internal override void ExportTypes(int fileToken, ModuleBuilder manifestModule) + { + manifestModule.ExportTypes(types.ToArray(), fileToken); + } + + internal void ExportTypes(Type[] types, int fileToken) + { + Dictionary declaringTypes = new Dictionary(); + foreach (Type type in types) + { + if (!type.IsModulePseudoType && IsVisible(type)) + { + ExportedTypeTable.Record rec = new ExportedTypeTable.Record(); + rec.Flags = (int)type.Attributes; + // LAMESPEC ECMA says that TypeDefId is a row index, but it should be a token + rec.TypeDefId = type.MetadataToken; + SetTypeNameAndTypeNamespace(type.TypeName, out rec.TypeName, out rec.TypeNamespace); + if (type.IsNested) + { + rec.Implementation = declaringTypes[type.DeclaringType]; + } + else + { + rec.Implementation = fileToken; + } + int exportTypeToken = 0x27000000 | this.ExportedType.AddRecord(rec); + declaringTypes.Add(type, exportTypeToken); + } + } + } + + private static bool IsVisible(Type type) + { + // NOTE this is not the same as Type.IsVisible, because that doesn't take into account family access + return type.IsPublic || ((type.IsNestedFamily || type.IsNestedFamORAssem || type.IsNestedPublic) && IsVisible(type.DeclaringType)); + } + + internal void AddConstant(int parentToken, object defaultValue) + { + ConstantTable.Record rec = new ConstantTable.Record(); + rec.Parent = parentToken; + ByteBuffer val = new ByteBuffer(16); + if (defaultValue == null) + { + rec.Type = Signature.ELEMENT_TYPE_CLASS; + val.Write((int)0); + } + else if (defaultValue is bool) + { + rec.Type = Signature.ELEMENT_TYPE_BOOLEAN; + val.Write((bool)defaultValue ? (byte)1 : (byte)0); + } + else if (defaultValue is char) + { + rec.Type = Signature.ELEMENT_TYPE_CHAR; + val.Write((char)defaultValue); + } + else if (defaultValue is sbyte) + { + rec.Type = Signature.ELEMENT_TYPE_I1; + val.Write((sbyte)defaultValue); + } + else if (defaultValue is byte) + { + rec.Type = Signature.ELEMENT_TYPE_U1; + val.Write((byte)defaultValue); + } + else if (defaultValue is short) + { + rec.Type = Signature.ELEMENT_TYPE_I2; + val.Write((short)defaultValue); + } + else if (defaultValue is ushort) + { + rec.Type = Signature.ELEMENT_TYPE_U2; + val.Write((ushort)defaultValue); + } + else if (defaultValue is int) + { + rec.Type = Signature.ELEMENT_TYPE_I4; + val.Write((int)defaultValue); + } + else if (defaultValue is uint) + { + rec.Type = Signature.ELEMENT_TYPE_U4; + val.Write((uint)defaultValue); + } + else if (defaultValue is long) + { + rec.Type = Signature.ELEMENT_TYPE_I8; + val.Write((long)defaultValue); + } + else if (defaultValue is ulong) + { + rec.Type = Signature.ELEMENT_TYPE_U8; + val.Write((ulong)defaultValue); + } + else if (defaultValue is float) + { + rec.Type = Signature.ELEMENT_TYPE_R4; + val.Write((float)defaultValue); + } + else if (defaultValue is double) + { + rec.Type = Signature.ELEMENT_TYPE_R8; + val.Write((double)defaultValue); + } + else if (defaultValue is string) + { + rec.Type = Signature.ELEMENT_TYPE_STRING; + foreach (char c in (string)defaultValue) + { + val.Write(c); + } + } + else if (defaultValue is DateTime) + { + rec.Type = Signature.ELEMENT_TYPE_I8; + val.Write(((DateTime)defaultValue).Ticks); + } + else + { + throw new ArgumentException(); + } + rec.Value = this.Blobs.Add(val); + this.Constant.AddRecord(rec); + } + + ModuleBuilder ITypeOwner.ModuleBuilder + { + get { return this; } + } + + internal override Type ResolveType(int metadataToken, IGenericContext context) + { + if (metadataToken >> 24 != TypeDefTable.Index) + { + throw new NotImplementedException(); + } + return types[(metadataToken & 0xFFFFFF) - 1]; + } + + public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) + { + if (genericTypeArguments != null || genericMethodArguments != null) + { + throw new NotImplementedException(); + } + // this method is inefficient, but since it isn't used we don't care + if ((metadataToken >> 24) == MemberRefTable.Index) + { + foreach (KeyValuePair kv in importedMemberRefs) + { + if (kv.Value == metadataToken) + { + return kv.Key.LookupMethod(); + } + } + } + // HACK if we're given a SymbolToken, we need to convert back + if ((metadataToken & 0xFF000000) == 0x06000000) + { + metadataToken = -(metadataToken & 0x00FFFFFF); + } + foreach (Type type in types) + { + MethodBase method = ((TypeBuilder)type).LookupMethod(metadataToken); + if (method != null) + { + return method; + } + } + return ((TypeBuilder)moduleType).LookupMethod(metadataToken); + } + + public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) + { + throw new NotImplementedException(); + } + + public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) + { + throw new NotImplementedException(); + } + + public override string ResolveString(int metadataToken) + { + throw new NotImplementedException(); + } + + public override string FullyQualifiedName + { + get { return Path.GetFullPath(Path.Combine(asm.dir, fileName)); } + } + + public override string Name + { + get { return fileName; } + } + + internal Guid GetModuleVersionIdOrEmpty() + { + return mvid; + } + + public override Guid ModuleVersionId + { + get + { + if (mvid == Guid.Empty && universe.Deterministic) + { + // if a deterministic GUID is used, it can't be queried before the assembly has been written + throw new InvalidOperationException(); + } + return mvid; + } + } + + public void __SetModuleVersionId(Guid guid) + { + if (guid == Guid.Empty && universe.Deterministic) + { + // if you want to use Guid.Empty, don't set UniverseOptions.DeterministicOutput + throw new ArgumentOutOfRangeException(); + } + mvid = guid; + } + + internal uint GetTimeDateStamp() + { + return timestamp; + } + + public DateTime __PEHeaderTimeDateStamp + { + get { return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(timestamp); } + set + { + if (value < new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc) || value > new DateTime(2106, 2, 7, 6, 28, 15, DateTimeKind.Utc)) + { + throw new ArgumentOutOfRangeException(); + } + timestamp = (uint)(value - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; + } + } + + public override Type[] __ResolveOptionalParameterTypes(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments, out CustomModifiers[] customModifiers) + { + throw new NotImplementedException(); + } + + public override string ScopeName + { + get { return moduleName; } + } + +#if !NO_SYMBOL_WRITER + public ISymbolWriter GetSymWriter() + { + return symbolWriter; + } +#endif + + public void DefineUnmanagedResource(string resourceFileName) + { + // This method reads the specified resource file (Win32 .res file) and converts it into the appropriate format and embeds it in the .rsrc section, + // also setting the Resource Directory entry. + unmanagedResources = new ResourceSection(); + unmanagedResources.ExtractResources(System.IO.File.ReadAllBytes(resourceFileName)); + } + + public bool IsTransient() + { + return false; + } + + public void SetUserEntryPoint(MethodInfo entryPoint) + { + int token = entryPoint.MetadataToken; + if (token < 0) + { + token = -token | 0x06000000; + } +#if !NO_SYMBOL_WRITER + if (symbolWriter != null) + { + symbolWriter.SetUserEntryPoint(new SymbolToken(token)); + } +#endif + } + + public StringToken GetStringConstant(string str) + { + return new StringToken(this.UserStrings.Add(str) | (0x70 << 24)); + } + + public SignatureToken GetSignatureToken(SignatureHelper sigHelper) + { + return new SignatureToken(this.StandAloneSig.FindOrAddRecord(this.Blobs.Add(sigHelper.GetSignature(this))) | (StandAloneSigTable.Index << 24)); + } + + public SignatureToken GetSignatureToken(byte[] sigBytes, int sigLength) + { + return new SignatureToken(this.StandAloneSig.FindOrAddRecord(this.Blobs.Add(ByteBuffer.Wrap(sigBytes, sigLength))) | (StandAloneSigTable.Index << 24)); + } + + public MethodInfo GetArrayMethod(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes) + { + return new ArrayMethod(this, arrayClass, methodName, callingConvention, returnType, parameterTypes); + } + + public MethodToken GetArrayMethodToken(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes) + { + return GetMethodToken(GetArrayMethod(arrayClass, methodName, callingConvention, returnType, parameterTypes)); + } + + internal override Type GetModuleType() + { + return moduleType; + } + + internal override IKVM.Reflection.Reader.ByteReader GetBlob(int blobIndex) + { + return Blobs.GetBlob(blobIndex); + } + + internal int GetSignatureBlobIndex(Signature sig) + { + ByteBuffer bb = new ByteBuffer(16); + sig.WriteSig(this, bb); + return this.Blobs.Add(bb); + } + + // non-standard API + public new long __ImageBase + { + get { return imageBaseAddress; } + set { imageBaseAddress = value; } + } + + protected override long GetImageBaseImpl() + { + return imageBaseAddress; + } + + public new long __StackReserve + { + get { return stackReserve; } + set { stackReserve = value; } + } + + protected override long GetStackReserveImpl() + { + return stackReserve; + } + + [Obsolete("Use __StackReserve property.")] + public void __SetStackReserve(long stackReserve) + { + __StackReserve = stackReserve; + } + + internal ulong GetStackReserve(ulong defaultValue) + { + return stackReserve == -1 ? defaultValue : (ulong)stackReserve; + } + + public new int __FileAlignment + { + get { return fileAlignment; } + set { fileAlignment = value; } + } + + protected override int GetFileAlignmentImpl() + { + return fileAlignment; + } + + public new DllCharacteristics __DllCharacteristics + { + get { return dllCharacteristics; } + set { dllCharacteristics = value; } + } + + protected override DllCharacteristics GetDllCharacteristicsImpl() + { + return dllCharacteristics; + } + + public override int MDStreamVersion + { + get { return asm.mdStreamVersion; } + } + + private int AddTypeRefByName(int resolutionScope, string ns, string name) + { + TypeRefTable.Record rec = new TypeRefTable.Record(); + rec.ResolutionScope = resolutionScope; + SetTypeNameAndTypeNamespace(new TypeName(ns, name), out rec.TypeName, out rec.TypeNamespace); + return 0x01000000 | this.TypeRef.AddRecord(rec); + } + + public void __Save(PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine) + { + SaveImpl(null, portableExecutableKind, imageFileMachine); + } + + public void __Save(Stream stream, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine) + { + if (!stream.CanRead || !stream.CanWrite || !stream.CanSeek || stream.Position != 0) + { + throw new ArgumentException("Stream must support read/write/seek and current position must be zero.", "stream"); + } + SaveImpl(stream, portableExecutableKind, imageFileMachine); + } + + private void SaveImpl(Stream streamOrNull, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine) + { + SetIsSaved(); + PopulatePropertyAndEventTables(); + IList attributes = asm.GetCustomAttributesData(null); + if (attributes.Count > 0) + { + int mscorlib = ImportAssemblyRef(universe.Mscorlib); + int[] placeholderTokens = new int[4]; + string[] placeholderTypeNames = new string[] { "AssemblyAttributesGoHere", "AssemblyAttributesGoHereM", "AssemblyAttributesGoHereS", "AssemblyAttributesGoHereSM" }; + foreach (CustomAttributeData cad in attributes) + { + int index; + if (cad.Constructor.DeclaringType.BaseType == universe.System_Security_Permissions_CodeAccessSecurityAttribute) + { + if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute) + { + index = 3; + } + else + { + index = 2; + } + } + else if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute) + { + index = 1; + } + else + { + index = 0; + } + if (placeholderTokens[index] == 0) + { + // we manually add a TypeRef without looking it up in mscorlib, because Mono and Silverlight's mscorlib don't have these types + placeholderTokens[index] = AddTypeRefByName(mscorlib, "System.Runtime.CompilerServices", placeholderTypeNames[index]); + } + SetCustomAttribute(placeholderTokens[index], cad.__ToBuilder()); + } + } + FillAssemblyRefTable(); + EmitResources(); + ModuleWriter.WriteModule(null, null, this, PEFileKinds.Dll, portableExecutableKind, imageFileMachine, unmanagedResources, 0, streamOrNull); + CloseResources(); + } + + public void __AddAssemblyReference(AssemblyName assemblyName) + { + __AddAssemblyReference(assemblyName, null); + } + + public void __AddAssemblyReference(AssemblyName assemblyName, Assembly assembly) + { + if (referencedAssemblyNames == null) + { + referencedAssemblyNames = new List(); + } + referencedAssemblyNames.Add((AssemblyName)assemblyName.Clone()); + int token = FindOrAddAssemblyRef(assemblyName, true); + if (assembly != null) + { + referencedAssemblies.Add(assembly, token); + } + } + + public override AssemblyName[] __GetReferencedAssemblies() + { + List list = new List(); + if (referencedAssemblyNames != null) + { + foreach (AssemblyName name in referencedAssemblyNames) + { + if (!list.Contains(name)) + { + list.Add(name); + } + } + } + foreach (Assembly asm in referencedAssemblies.Keys) + { + AssemblyName name = asm.GetName(); + if (!list.Contains(name)) + { + list.Add(name); + } + } + return list.ToArray(); + } + + public void __AddModuleReference(string module) + { + this.ModuleRef.FindOrAddRecord(module == null ? 0 : this.Strings.Add(module)); + } + + public override string[] __GetReferencedModules() + { + string[] arr = new string[this.ModuleRef.RowCount]; + for (int i = 0; i < arr.Length; i++) + { + arr[i] = this.Strings.Find(this.ModuleRef.records[i]); + } + return arr; + } + + public override Type[] __GetReferencedTypes() + { + List list = new List(); + foreach (KeyValuePair kv in typeTokens) + { + if (kv.Value >> 24 == TypeRefTable.Index) + { + list.Add(kv.Key); + } + } + return list.ToArray(); + } + + public override Type[] __GetExportedTypes() + { + throw new NotImplementedException(); + } + + public int __AddModule(int flags, string name, byte[] hash) + { + FileTable.Record file = new FileTable.Record(); + file.Flags = flags; + file.Name = this.Strings.Add(name); + file.HashValue = this.Blobs.Add(ByteBuffer.Wrap(hash)); + return 0x26000000 + this.File.AddRecord(file); + } + + public int __AddManifestResource(int offset, ResourceAttributes flags, string name, int implementation) + { + ManifestResourceTable.Record res = new ManifestResourceTable.Record(); + res.Offset = offset; + res.Flags = (int)flags; + res.Name = this.Strings.Add(name); + res.Implementation = implementation; + return 0x28000000 + this.ManifestResource.AddRecord(res); + } + + public void __SetCustomAttributeFor(int token, CustomAttributeBuilder customBuilder) + { + SetCustomAttribute(token, customBuilder); + } + + public RelativeVirtualAddress __AddVTableFixups(MethodBuilder[] methods, int type) + { + initializedData.Align(8); + VTableFixups fixups; + fixups.initializedDataOffset = (uint)initializedData.Position; + fixups.count = (ushort)methods.Length; + fixups.type = (ushort)type; + foreach (MethodBuilder mb in methods) + { + initializedData.Write(mb.MetadataToken); + if (fixups.SlotWidth == 8) + { + initializedData.Write(0); + } + } + vtablefixups.Add(fixups); + return new RelativeVirtualAddress(fixups.initializedDataOffset); + } + + public void __AddUnmanagedExportStub(string name, int ordinal, RelativeVirtualAddress rva) + { + AddUnmanagedExport(name, ordinal, null, rva); + } + + internal void AddUnmanagedExport(string name, int ordinal, MethodBuilder methodBuilder, RelativeVirtualAddress rva) + { + UnmanagedExport export; + export.name = name; + export.ordinal = ordinal; + export.mb = methodBuilder; + export.rva = rva; + unmanagedExports.Add(export); + } + + internal void SetInterfaceImplementationCustomAttribute(TypeBuilder typeBuilder, Type interfaceType, CustomAttributeBuilder cab) + { + // NOTE since interfaceimpls are extremely common and custom attributes on them are extremely rare, + // we store (and resolve) the custom attributes in such away as to avoid impacting the common case performance + if (interfaceImplCustomAttributes == null) + { + interfaceImplCustomAttributes = new List(); + } + InterfaceImplCustomAttribute rec; + rec.type = typeBuilder.MetadataToken; + int token = GetTypeToken(interfaceType).Token; + switch (token >> 24) + { + case TypeDefTable.Index: + token = (token & 0xFFFFFF) << 2 | 0; + break; + case TypeRefTable.Index: + token = (token & 0xFFFFFF) << 2 | 1; + break; + case TypeSpecTable.Index: + token = (token & 0xFFFFFF) << 2 | 2; + break; + default: + throw new InvalidOperationException(); + } + rec.interfaceType = token; + rec.pseudoToken = AllocPseudoToken(); + interfaceImplCustomAttributes.Add(rec); + SetCustomAttribute(rec.pseudoToken, cab); + } + + internal void ResolveInterfaceImplPseudoTokens() + { + if (interfaceImplCustomAttributes != null) + { + foreach (InterfaceImplCustomAttribute rec in interfaceImplCustomAttributes) + { + for (int i = 0; i < InterfaceImpl.records.Length; i++) + { + if (InterfaceImpl.records[i].Class == rec.type && InterfaceImpl.records[i].Interface == rec.interfaceType) + { + RegisterTokenFixup(rec.pseudoToken, (InterfaceImplTable.Index << 24) | (i + 1)); + break; + } + } + } + } + } + + internal void FixupPseudoToken(ref int token) + { + if (IsPseudoToken(token)) + { + token = ResolvePseudoToken(token); + } + } + + internal void SetIsSaved() + { + if (saved) + { + throw new InvalidOperationException(); + } + saved = true; + } + + internal bool IsSaved + { + get { return saved; } + } + + internal override string GetString(int index) + { + return this.Strings.Find(index); + } + } + + struct UnmanagedExport + { + internal string name; + internal int ordinal; + internal RelativeVirtualAddress rva; + internal MethodBuilder mb; + } + + public struct RelativeVirtualAddress + { + internal readonly uint initializedDataOffset; + + internal RelativeVirtualAddress(uint initializedDataOffset) + { + this.initializedDataOffset = initializedDataOffset; + } + + public static RelativeVirtualAddress operator +(RelativeVirtualAddress rva, int offset) + { + return new RelativeVirtualAddress(rva.initializedDataOffset + (uint)offset); + } + } + + class ArrayMethod : MethodInfo + { + private readonly Module module; + private readonly Type arrayClass; + private readonly string methodName; + private readonly CallingConventions callingConvention; + private readonly Type returnType; + protected readonly Type[] parameterTypes; + private MethodSignature methodSignature; + + internal ArrayMethod(Module module, Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes) + { + this.module = module; + this.arrayClass = arrayClass; + this.methodName = methodName; + this.callingConvention = callingConvention; + this.returnType = returnType ?? module.universe.System_Void; + this.parameterTypes = Util.Copy(parameterTypes); + } + + public override MethodBody GetMethodBody() + { + throw new InvalidOperationException(); + } + + public override int __MethodRVA + { + get { throw new InvalidOperationException(); } + } + + public override MethodImplAttributes GetMethodImplementationFlags() + { + throw new NotSupportedException(); + } + + public override ParameterInfo[] GetParameters() + { + throw new NotSupportedException(); + } + + internal override int ImportTo(ModuleBuilder module) + { + return module.ImportMethodOrField(arrayClass, methodName, MethodSignature); + } + + public override MethodAttributes Attributes + { + get { throw new NotSupportedException(); } + } + + public override CallingConventions CallingConvention + { + get { return callingConvention; } + } + + public override Type DeclaringType + { + get { return arrayClass; } + } + + internal override MethodSignature MethodSignature + { + get + { + if (methodSignature == null) + { + methodSignature = MethodSignature.MakeFromBuilder(returnType, parameterTypes, new PackedCustomModifiers(), callingConvention, 0); + } + return methodSignature; + } + } + + public override Module Module + { + // FXBUG like .NET, we return the module that GetArrayMethod was called on, not the module associated with the array type + get { return module; } + } + + public override string Name + { + get { return methodName; } + } + + internal override int ParameterCount + { + get { return parameterTypes.Length; } + } + + public override ParameterInfo ReturnParameter + { + // FXBUG like .NET, we throw NotImplementedException + get { throw new NotImplementedException(); } + } + + public override Type ReturnType + { + get { return returnType; } + } + + internal override bool HasThis + { + get { return (callingConvention & (CallingConventions.HasThis | CallingConventions.ExplicitThis)) == CallingConventions.HasThis; } + } + + internal override int GetCurrentToken() + { + return this.MetadataToken; + } + + internal override bool IsBaked + { + get { return arrayClass.IsBaked; } + } + } +} diff --git a/reflect/Emit/OpCode.cs b/reflect/Emit/OpCode.cs new file mode 100644 index 0000000..1d75a0a --- /dev/null +++ b/reflect/Emit/OpCode.cs @@ -0,0 +1,288 @@ +/* + Copyright (C) 2008, 2010 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Diagnostics; + +namespace IKVM.Reflection.Emit +{ + public struct OpCode + { + private const int ValueCount = 1024; + private const int OperandTypeCount = 19; + private const int FlowControlCount = 9; + private const int StackDiffCount = 5; + private const int OpCodeTypeCount = 6; + private const int StackBehaviourPopCount = 20; + private const int StackBehaviourPushCount = 9; + private static readonly StackBehaviour[] pop = { + StackBehaviour.Pop0, + StackBehaviour.Pop1, + StackBehaviour.Pop1_pop1, + StackBehaviour.Popi, + StackBehaviour.Popi_pop1, + StackBehaviour.Popi_popi, + StackBehaviour.Popi_popi8, + StackBehaviour.Popi_popi_popi, + StackBehaviour.Popi_popr4, + StackBehaviour.Popi_popr8, + StackBehaviour.Popref, + StackBehaviour.Popref_pop1, + StackBehaviour.Popref_popi, + StackBehaviour.Popref_popi_popi, + StackBehaviour.Popref_popi_popi8, + StackBehaviour.Popref_popi_popr4, + StackBehaviour.Popref_popi_popr8, + StackBehaviour.Popref_popi_popref, + StackBehaviour.Varpop, + StackBehaviour.Popref_popi_pop1 + }; + private static readonly StackBehaviour[] push = { + StackBehaviour.Push0, + StackBehaviour.Push1, + StackBehaviour.Push1_push1, + StackBehaviour.Pushi, + StackBehaviour.Pushi8, + StackBehaviour.Pushr4, + StackBehaviour.Pushr8, + StackBehaviour.Pushref, + StackBehaviour.Varpush + }; + private readonly int value; + + internal OpCode(int value) + { + this.value = value; + } + + public override bool Equals(object obj) + { + return this == obj as OpCode?; + } + + public override int GetHashCode() + { + return value; + } + + public bool Equals(OpCode other) + { + return this == other; + } + + public static bool operator ==(OpCode a, OpCode b) + { + return a.value == b.value; + } + + public static bool operator !=(OpCode a, OpCode b) + { + return !(a == b); + } + + public short Value + { + get { return (short)(value >> 22); } + } + + public int Size + { + get { return value < 0 ? 2 : 1; } + } + +#if !GENERATOR + public string Name + { + get { return OpCodes.GetName(this.Value); } + } +#endif + + public OperandType OperandType + { + get { return (OperandType)((value & 0x3FFFFF) % OperandTypeCount); } + } + + public FlowControl FlowControl + { + get { return (FlowControl)(((value & 0x3FFFFF) / OperandTypeCount) % FlowControlCount); } + } + + internal int StackDiff + { + get { return ((((value & 0x3FFFFF) / (OperandTypeCount * FlowControlCount)) % StackDiffCount) - 3); } + } + + public OpCodeType OpCodeType + { + get { return (OpCodeType)(((value & 0x3FFFFF) / (OperandTypeCount * FlowControlCount * StackDiffCount)) % OpCodeTypeCount); } + } + + public StackBehaviour StackBehaviourPop + { + get { return pop[(((value & 0x3FFFFF) / (OperandTypeCount * FlowControlCount * StackDiffCount * OpCodeTypeCount)) % StackBehaviourPopCount)]; } + } + + public StackBehaviour StackBehaviourPush + { + get { return push[(((value & 0x3FFFFF) / (OperandTypeCount * FlowControlCount * StackDiffCount * OpCodeTypeCount * StackBehaviourPopCount)) % StackBehaviourPushCount)]; } + } + +#if GENERATOR + static void Main(string[] args) + { + Debug.Assert(pop.Length == StackBehaviourPopCount); + Debug.Assert(push.Length == StackBehaviourPushCount); + CheckEnumRange(typeof(FlowControl), FlowControlCount); + CheckEnumRange(typeof(OpCodeType), OpCodeTypeCount); + CheckEnumRange(typeof(OperandType), OperandTypeCount); + foreach (var field in typeof(System.Reflection.Emit.OpCodes).GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static)) + { + System.Reflection.Emit.OpCode opc1 = (System.Reflection.Emit.OpCode)field.GetValue(null); + IKVM.Reflection.Emit.OpCode opc2 = new IKVM.Reflection.Emit.OpCode(Pack(opc1)); + Debug.Assert(opc1.Value == opc2.Value); + Debug.Assert(opc1.Size == opc2.Size); + Debug.Assert((int)opc1.FlowControl == (int)opc2.FlowControl); + Debug.Assert((int)opc1.OpCodeType == (int)opc2.OpCodeType); + Debug.Assert((int)opc1.OperandType == (int)opc2.OperandType); + Debug.Assert((int)opc1.StackBehaviourPop == (int)opc2.StackBehaviourPop); + Debug.Assert((int)opc1.StackBehaviourPush == (int)opc2.StackBehaviourPush); + Console.WriteLine("\t\tpublic static readonly OpCode {0} = new OpCode({1});", field.Name, Pack(opc1)); + } + Console.WriteLine(); + Console.WriteLine("\t\tinternal static string GetName(int value)"); + Console.WriteLine("\t\t{"); + Console.WriteLine("\t\t\tswitch (value)"); + Console.WriteLine("\t\t\t{"); + foreach (var field in typeof(System.Reflection.Emit.OpCodes).GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static)) + { + System.Reflection.Emit.OpCode opc1 = (System.Reflection.Emit.OpCode)field.GetValue(null); + Console.WriteLine("\t\t\t\tcase {0}:", opc1.Value); + Console.WriteLine("\t\t\t\t\treturn \"{0}\";", opc1.Name); + } + Console.WriteLine("\t\t\t}"); + Console.WriteLine("\t\t\tthrow new ArgumentOutOfRangeException();"); + Console.WriteLine("\t\t}"); + Console.WriteLine(); + Console.WriteLine("\t\tpublic static bool TakesSingleByteArgument(OpCode inst)"); + Console.WriteLine("\t\t{"); + Console.WriteLine("\t\t\tswitch (inst.Value)"); + Console.WriteLine("\t\t\t{"); + foreach (var field in typeof(System.Reflection.Emit.OpCodes).GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static)) + { + System.Reflection.Emit.OpCode opc1 = (System.Reflection.Emit.OpCode)field.GetValue(null); + if (System.Reflection.Emit.OpCodes.TakesSingleByteArgument(opc1)) + { + Console.WriteLine("\t\t\t\tcase {0}:", opc1.Value); + } + } + Console.WriteLine("\t\t\t\t\treturn true;"); + Console.WriteLine("\t\t\t\tdefault:"); + Console.WriteLine("\t\t\t\t\treturn false;"); + Console.WriteLine("\t\t\t}"); + Console.WriteLine("\t\t}"); + } + + private static void CheckEnumRange(System.Type type, int count) + { + foreach (var field in type.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static)) + { + int value = (int)field.GetValue(null); + Debug.Assert(value >= 0 && value < count); + } + } + + static int Pack(System.Reflection.Emit.OpCode opcode) + { + int value = 0; + value *= StackBehaviourPushCount; + value += Map(push, opcode.StackBehaviourPush); + value *= StackBehaviourPopCount; + value += Map(pop, opcode.StackBehaviourPop); + value *= OpCodeTypeCount; + value += (int)opcode.OpCodeType; + value *= StackDiffCount; + value += 3 + GetStackDiff(opcode.StackBehaviourPush) + GetStackDiff(opcode.StackBehaviourPop); + value *= FlowControlCount; + value += (int)opcode.FlowControl; + value *= OperandTypeCount; + value += (int)opcode.OperandType; + return (opcode.Value << 22) | value; + } + + private static int Map(StackBehaviour[] array, System.Reflection.Emit.StackBehaviour stackBehaviour) + { + for (int i = 0; i < array.Length; i++) + { + if ((int)array[i] == (int)stackBehaviour) + { + return i; + } + } + throw new InvalidOperationException(); + } + + static int GetStackDiff(System.Reflection.Emit.StackBehaviour sb) + { + switch (sb) + { + case System.Reflection.Emit.StackBehaviour.Pop0: + case System.Reflection.Emit.StackBehaviour.Push0: + case System.Reflection.Emit.StackBehaviour.Varpop: + case System.Reflection.Emit.StackBehaviour.Varpush: + return 0; + case System.Reflection.Emit.StackBehaviour.Pop1: + case System.Reflection.Emit.StackBehaviour.Popi: + case System.Reflection.Emit.StackBehaviour.Popref: + return -1; + case System.Reflection.Emit.StackBehaviour.Pop1_pop1: + case System.Reflection.Emit.StackBehaviour.Popi_pop1: + case System.Reflection.Emit.StackBehaviour.Popi_popi: + case System.Reflection.Emit.StackBehaviour.Popi_popi8: + case System.Reflection.Emit.StackBehaviour.Popi_popr4: + case System.Reflection.Emit.StackBehaviour.Popi_popr8: + case System.Reflection.Emit.StackBehaviour.Popref_pop1: + case System.Reflection.Emit.StackBehaviour.Popref_popi: + return -2; + case System.Reflection.Emit.StackBehaviour.Popi_popi_popi: + case System.Reflection.Emit.StackBehaviour.Popref_popi_pop1: + case System.Reflection.Emit.StackBehaviour.Popref_popi_popi: + case System.Reflection.Emit.StackBehaviour.Popref_popi_popi8: + case System.Reflection.Emit.StackBehaviour.Popref_popi_popr4: + case System.Reflection.Emit.StackBehaviour.Popref_popi_popr8: + case System.Reflection.Emit.StackBehaviour.Popref_popi_popref: + return -3; + case System.Reflection.Emit.StackBehaviour.Push1: + case System.Reflection.Emit.StackBehaviour.Pushi: + case System.Reflection.Emit.StackBehaviour.Pushi8: + case System.Reflection.Emit.StackBehaviour.Pushr4: + case System.Reflection.Emit.StackBehaviour.Pushr8: + case System.Reflection.Emit.StackBehaviour.Pushref: + return 1; + case System.Reflection.Emit.StackBehaviour.Push1_push1: + return 2; + } + throw new InvalidOperationException(); + } +#endif // GENERATOR + } +} diff --git a/reflect/Emit/OpCodes.cs b/reflect/Emit/OpCodes.cs new file mode 100644 index 0000000..bb2ddd8 --- /dev/null +++ b/reflect/Emit/OpCodes.cs @@ -0,0 +1,749 @@ +/* + Copyright (C) 2008 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; + +namespace IKVM.Reflection.Emit +{ + public sealed class OpCodes + { + public static readonly OpCode Nop = new OpCode(4888); + public static readonly OpCode Break = new OpCode(4199116); + public static readonly OpCode Ldarg_0 = new OpCode(8492847); + public static readonly OpCode Ldarg_1 = new OpCode(12687151); + public static readonly OpCode Ldarg_2 = new OpCode(16881455); + public static readonly OpCode Ldarg_3 = new OpCode(21075759); + public static readonly OpCode Ldloc_0 = new OpCode(25270063); + public static readonly OpCode Ldloc_1 = new OpCode(29464367); + public static readonly OpCode Ldloc_2 = new OpCode(33658671); + public static readonly OpCode Ldloc_3 = new OpCode(37852975); + public static readonly OpCode Stloc_0 = new OpCode(41949467); + public static readonly OpCode Stloc_1 = new OpCode(46143771); + public static readonly OpCode Stloc_2 = new OpCode(50338075); + public static readonly OpCode Stloc_3 = new OpCode(54532379); + public static readonly OpCode Ldarg_S = new OpCode(58824508); + public static readonly OpCode Ldarga_S = new OpCode(63224012); + public static readonly OpCode Starg_S = new OpCode(67115304); + public static readonly OpCode Ldloc_S = new OpCode(71407420); + public static readonly OpCode Ldloca_S = new OpCode(75806924); + public static readonly OpCode Stloc_S = new OpCode(79698216); + public static readonly OpCode Ldnull = new OpCode(84609339); + public static readonly OpCode Ldc_I4_M1 = new OpCode(88389823); + public static readonly OpCode Ldc_I4_0 = new OpCode(92584127); + public static readonly OpCode Ldc_I4_1 = new OpCode(96778431); + public static readonly OpCode Ldc_I4_2 = new OpCode(100972735); + public static readonly OpCode Ldc_I4_3 = new OpCode(105167039); + public static readonly OpCode Ldc_I4_4 = new OpCode(109361343); + public static readonly OpCode Ldc_I4_5 = new OpCode(113555647); + public static readonly OpCode Ldc_I4_6 = new OpCode(117749951); + public static readonly OpCode Ldc_I4_7 = new OpCode(121944255); + public static readonly OpCode Ldc_I4_8 = new OpCode(126138559); + public static readonly OpCode Ldc_I4_S = new OpCode(130332874); + public static readonly OpCode Ldc_I4 = new OpCode(134530584); + public static readonly OpCode Ldc_I8 = new OpCode(138827489); + public static readonly OpCode Ldc_R4 = new OpCode(143124407); + public static readonly OpCode Ldc_R8 = new OpCode(147421301); + public static readonly OpCode Dup = new OpCode(155404637); + public static readonly OpCode Pop = new OpCode(159393399); + public static readonly OpCode Jmp = new OpCode(163582686); + public static readonly OpCode Call = new OpCode(168690130); + public static readonly OpCode Calli = new OpCode(172884439); + public static readonly OpCode Ret = new OpCode(176258034); + public static readonly OpCode Br_S = new OpCode(180356455); + public static readonly OpCode Brfalse_S = new OpCode(184566035); + public static readonly OpCode Brtrue_S = new OpCode(188760339); + public static readonly OpCode Beq_S = new OpCode(192949342); + public static readonly OpCode Bge_S = new OpCode(197143646); + public static readonly OpCode Bgt_S = new OpCode(201337950); + public static readonly OpCode Ble_S = new OpCode(205532254); + public static readonly OpCode Blt_S = new OpCode(209726558); + public static readonly OpCode Bne_Un_S = new OpCode(213920862); + public static readonly OpCode Bge_Un_S = new OpCode(218115166); + public static readonly OpCode Bgt_Un_S = new OpCode(222309470); + public static readonly OpCode Ble_Un_S = new OpCode(226503774); + public static readonly OpCode Blt_Un_S = new OpCode(230698078); + public static readonly OpCode Br = new OpCode(234885812); + public static readonly OpCode Brfalse = new OpCode(239095392); + public static readonly OpCode Brtrue = new OpCode(243289696); + public static readonly OpCode Beq = new OpCode(247475279); + public static readonly OpCode Bge = new OpCode(251669583); + public static readonly OpCode Bgt = new OpCode(255863887); + public static readonly OpCode Ble = new OpCode(260058191); + public static readonly OpCode Blt = new OpCode(264252495); + public static readonly OpCode Bne_Un = new OpCode(268446799); + public static readonly OpCode Bge_Un = new OpCode(272641103); + public static readonly OpCode Bgt_Un = new OpCode(276835407); + public static readonly OpCode Ble_Un = new OpCode(281029711); + public static readonly OpCode Blt_Un = new OpCode(285224015); + public static readonly OpCode Switch = new OpCode(289427051); + public static readonly OpCode Ldind_I1 = new OpCode(293929358); + public static readonly OpCode Ldind_U1 = new OpCode(298123662); + public static readonly OpCode Ldind_I2 = new OpCode(302317966); + public static readonly OpCode Ldind_U2 = new OpCode(306512270); + public static readonly OpCode Ldind_I4 = new OpCode(310706574); + public static readonly OpCode Ldind_U4 = new OpCode(314900878); + public static readonly OpCode Ldind_I8 = new OpCode(319197782); + public static readonly OpCode Ldind_I = new OpCode(323289486); + public static readonly OpCode Ldind_R4 = new OpCode(327688990); + public static readonly OpCode Ldind_R8 = new OpCode(331985894); + public static readonly OpCode Ldind_Ref = new OpCode(336282798); + public static readonly OpCode Stind_Ref = new OpCode(339768820); + public static readonly OpCode Stind_I1 = new OpCode(343963124); + public static readonly OpCode Stind_I2 = new OpCode(348157428); + public static readonly OpCode Stind_I4 = new OpCode(352351732); + public static readonly OpCode Stind_I8 = new OpCode(356551166); + public static readonly OpCode Stind_R4 = new OpCode(360755730); + public static readonly OpCode Stind_R8 = new OpCode(364955164); + public static readonly OpCode Add = new OpCode(369216329); + public static readonly OpCode Sub = new OpCode(373410633); + public static readonly OpCode Mul = new OpCode(377604937); + public static readonly OpCode Div = new OpCode(381799241); + public static readonly OpCode Div_Un = new OpCode(385993545); + public static readonly OpCode Rem = new OpCode(390187849); + public static readonly OpCode Rem_Un = new OpCode(394382153); + public static readonly OpCode And = new OpCode(398576457); + public static readonly OpCode Or = new OpCode(402770761); + public static readonly OpCode Xor = new OpCode(406965065); + public static readonly OpCode Shl = new OpCode(411159369); + public static readonly OpCode Shr = new OpCode(415353673); + public static readonly OpCode Shr_Un = new OpCode(419547977); + public static readonly OpCode Neg = new OpCode(423737322); + public static readonly OpCode Not = new OpCode(427931626); + public static readonly OpCode Conv_I1 = new OpCode(432331130); + public static readonly OpCode Conv_I2 = new OpCode(436525434); + public static readonly OpCode Conv_I4 = new OpCode(440719738); + public static readonly OpCode Conv_I8 = new OpCode(445016642); + public static readonly OpCode Conv_R4 = new OpCode(449313546); + public static readonly OpCode Conv_R8 = new OpCode(453610450); + public static readonly OpCode Conv_U4 = new OpCode(457496954); + public static readonly OpCode Conv_U8 = new OpCode(461793858); + public static readonly OpCode Callvirt = new OpCode(466484004); + public static readonly OpCode Cpobj = new OpCode(469790542); + public static readonly OpCode Ldobj = new OpCode(474077528); + public static readonly OpCode Ldstr = new OpCode(478872210); + public static readonly OpCode Newobj = new OpCode(483158791); + public static readonly OpCode Castclass = new OpCode(487311950); + public static readonly OpCode Isinst = new OpCode(491095854); + public static readonly OpCode Conv_R_Un = new OpCode(495553490); + public static readonly OpCode Unbox = new OpCode(507874780); + public static readonly OpCode Throw = new OpCode(511759452); + public static readonly OpCode Ldfld = new OpCode(516056466); + public static readonly OpCode Ldflda = new OpCode(520455970); + public static readonly OpCode Stfld = new OpCode(524347262); + public static readonly OpCode Ldsfld = new OpCode(528588249); + public static readonly OpCode Ldsflda = new OpCode(532987753); + public static readonly OpCode Stsfld = new OpCode(536879045); + public static readonly OpCode Stobj = new OpCode(541090290); + public static readonly OpCode Conv_Ovf_I1_Un = new OpCode(545577338); + public static readonly OpCode Conv_Ovf_I2_Un = new OpCode(549771642); + public static readonly OpCode Conv_Ovf_I4_Un = new OpCode(553965946); + public static readonly OpCode Conv_Ovf_I8_Un = new OpCode(558262850); + public static readonly OpCode Conv_Ovf_U1_Un = new OpCode(562354554); + public static readonly OpCode Conv_Ovf_U2_Un = new OpCode(566548858); + public static readonly OpCode Conv_Ovf_U4_Un = new OpCode(570743162); + public static readonly OpCode Conv_Ovf_U8_Un = new OpCode(575040066); + public static readonly OpCode Conv_Ovf_I_Un = new OpCode(579131770); + public static readonly OpCode Conv_Ovf_U_Un = new OpCode(583326074); + public static readonly OpCode Box = new OpCode(587930786); + public static readonly OpCode Newarr = new OpCode(592133640); + public static readonly OpCode Ldlen = new OpCode(595953446); + public static readonly OpCode Ldelema = new OpCode(600157847); + public static readonly OpCode Ldelem_I1 = new OpCode(604352143); + public static readonly OpCode Ldelem_U1 = new OpCode(608546447); + public static readonly OpCode Ldelem_I2 = new OpCode(612740751); + public static readonly OpCode Ldelem_U2 = new OpCode(616935055); + public static readonly OpCode Ldelem_I4 = new OpCode(621129359); + public static readonly OpCode Ldelem_U4 = new OpCode(625323663); + public static readonly OpCode Ldelem_I8 = new OpCode(629620567); + public static readonly OpCode Ldelem_I = new OpCode(633712271); + public static readonly OpCode Ldelem_R4 = new OpCode(638111775); + public static readonly OpCode Ldelem_R8 = new OpCode(642408679); + public static readonly OpCode Ldelem_Ref = new OpCode(646705583); + public static readonly OpCode Stelem_I = new OpCode(650186475); + public static readonly OpCode Stelem_I1 = new OpCode(654380779); + public static readonly OpCode Stelem_I2 = new OpCode(658575083); + public static readonly OpCode Stelem_I4 = new OpCode(662769387); + public static readonly OpCode Stelem_I8 = new OpCode(666968821); + public static readonly OpCode Stelem_R4 = new OpCode(671168255); + public static readonly OpCode Stelem_R8 = new OpCode(675367689); + public static readonly OpCode Stelem_Ref = new OpCode(679567123); + public static readonly OpCode Ldelem = new OpCode(683838727); + public static readonly OpCode Stelem = new OpCode(687965999); + public static readonly OpCode Unbox_Any = new OpCode(692217246); + public static readonly OpCode Conv_Ovf_I1 = new OpCode(751098234); + public static readonly OpCode Conv_Ovf_U1 = new OpCode(755292538); + public static readonly OpCode Conv_Ovf_I2 = new OpCode(759486842); + public static readonly OpCode Conv_Ovf_U2 = new OpCode(763681146); + public static readonly OpCode Conv_Ovf_I4 = new OpCode(767875450); + public static readonly OpCode Conv_Ovf_U4 = new OpCode(772069754); + public static readonly OpCode Conv_Ovf_I8 = new OpCode(776366658); + public static readonly OpCode Conv_Ovf_U8 = new OpCode(780560962); + public static readonly OpCode Refanyval = new OpCode(814012802); + public static readonly OpCode Ckfinite = new OpCode(818514898); + public static readonly OpCode Mkrefany = new OpCode(830595078); + public static readonly OpCode Ldtoken = new OpCode(872728098); + public static readonly OpCode Conv_U2 = new OpCode(876927354); + public static readonly OpCode Conv_U1 = new OpCode(881121658); + public static readonly OpCode Conv_I = new OpCode(885315962); + public static readonly OpCode Conv_Ovf_I = new OpCode(889510266); + public static readonly OpCode Conv_Ovf_U = new OpCode(893704570); + public static readonly OpCode Add_Ovf = new OpCode(897698633); + public static readonly OpCode Add_Ovf_Un = new OpCode(901892937); + public static readonly OpCode Mul_Ovf = new OpCode(906087241); + public static readonly OpCode Mul_Ovf_Un = new OpCode(910281545); + public static readonly OpCode Sub_Ovf = new OpCode(914475849); + public static readonly OpCode Sub_Ovf_Un = new OpCode(918670153); + public static readonly OpCode Endfinally = new OpCode(922751806); + public static readonly OpCode Leave = new OpCode(926945972); + public static readonly OpCode Leave_S = new OpCode(931140291); + public static readonly OpCode Stind_I = new OpCode(935359988); + public static readonly OpCode Conv_U = new OpCode(939841914); + public static readonly OpCode Prefix7 = new OpCode(1040189696); + public static readonly OpCode Prefix6 = new OpCode(1044384000); + public static readonly OpCode Prefix5 = new OpCode(1048578304); + public static readonly OpCode Prefix4 = new OpCode(1052772608); + public static readonly OpCode Prefix3 = new OpCode(1056966912); + public static readonly OpCode Prefix2 = new OpCode(1061161216); + public static readonly OpCode Prefix1 = new OpCode(1065355520); + public static readonly OpCode Prefixref = new OpCode(1069549824); + public static readonly OpCode Arglist = new OpCode(-2147170789); + public static readonly OpCode Ceq = new OpCode(-2142966567); + public static readonly OpCode Cgt = new OpCode(-2138772263); + public static readonly OpCode Cgt_Un = new OpCode(-2134577959); + public static readonly OpCode Clt = new OpCode(-2130383655); + public static readonly OpCode Clt_Un = new OpCode(-2126189351); + public static readonly OpCode Ldftn = new OpCode(-2122004966); + public static readonly OpCode Ldvirtftn = new OpCode(-2117759533); + public static readonly OpCode Ldarg = new OpCode(-2109627244); + public static readonly OpCode Ldarga = new OpCode(-2105227740); + public static readonly OpCode Starg = new OpCode(-2101336448); + public static readonly OpCode Ldloc = new OpCode(-2097044332); + public static readonly OpCode Ldloca = new OpCode(-2092644828); + public static readonly OpCode Stloc = new OpCode(-2088753536); + public static readonly OpCode Localloc = new OpCode(-2084241010); + public static readonly OpCode Endfilter = new OpCode(-2076160335); + public static readonly OpCode Unaligned = new OpCode(-2071982151); + public static readonly OpCode Volatile = new OpCode(-2067787858); + public static readonly OpCode Tailcall = new OpCode(-2063593554); + public static readonly OpCode Initobj = new OpCode(-2059384859); + public static readonly OpCode Constrained = new OpCode(-2055204938); + public static readonly OpCode Cpblk = new OpCode(-2050974371); + public static readonly OpCode Initblk = new OpCode(-2046780067); + public static readonly OpCode Rethrow = new OpCode(-2038428509); + public static readonly OpCode Sizeof = new OpCode(-2029730269); + public static readonly OpCode Refanytype = new OpCode(-2025531014); + public static readonly OpCode Readonly = new OpCode(-2021650514); + + internal static string GetName(int value) + { + switch (value) + { + case 0: + return "nop"; + case 1: + return "break"; + case 2: + return "ldarg.0"; + case 3: + return "ldarg.1"; + case 4: + return "ldarg.2"; + case 5: + return "ldarg.3"; + case 6: + return "ldloc.0"; + case 7: + return "ldloc.1"; + case 8: + return "ldloc.2"; + case 9: + return "ldloc.3"; + case 10: + return "stloc.0"; + case 11: + return "stloc.1"; + case 12: + return "stloc.2"; + case 13: + return "stloc.3"; + case 14: + return "ldarg.s"; + case 15: + return "ldarga.s"; + case 16: + return "starg.s"; + case 17: + return "ldloc.s"; + case 18: + return "ldloca.s"; + case 19: + return "stloc.s"; + case 20: + return "ldnull"; + case 21: + return "ldc.i4.m1"; + case 22: + return "ldc.i4.0"; + case 23: + return "ldc.i4.1"; + case 24: + return "ldc.i4.2"; + case 25: + return "ldc.i4.3"; + case 26: + return "ldc.i4.4"; + case 27: + return "ldc.i4.5"; + case 28: + return "ldc.i4.6"; + case 29: + return "ldc.i4.7"; + case 30: + return "ldc.i4.8"; + case 31: + return "ldc.i4.s"; + case 32: + return "ldc.i4"; + case 33: + return "ldc.i8"; + case 34: + return "ldc.r4"; + case 35: + return "ldc.r8"; + case 37: + return "dup"; + case 38: + return "pop"; + case 39: + return "jmp"; + case 40: + return "call"; + case 41: + return "calli"; + case 42: + return "ret"; + case 43: + return "br.s"; + case 44: + return "brfalse.s"; + case 45: + return "brtrue.s"; + case 46: + return "beq.s"; + case 47: + return "bge.s"; + case 48: + return "bgt.s"; + case 49: + return "ble.s"; + case 50: + return "blt.s"; + case 51: + return "bne.un.s"; + case 52: + return "bge.un.s"; + case 53: + return "bgt.un.s"; + case 54: + return "ble.un.s"; + case 55: + return "blt.un.s"; + case 56: + return "br"; + case 57: + return "brfalse"; + case 58: + return "brtrue"; + case 59: + return "beq"; + case 60: + return "bge"; + case 61: + return "bgt"; + case 62: + return "ble"; + case 63: + return "blt"; + case 64: + return "bne.un"; + case 65: + return "bge.un"; + case 66: + return "bgt.un"; + case 67: + return "ble.un"; + case 68: + return "blt.un"; + case 69: + return "switch"; + case 70: + return "ldind.i1"; + case 71: + return "ldind.u1"; + case 72: + return "ldind.i2"; + case 73: + return "ldind.u2"; + case 74: + return "ldind.i4"; + case 75: + return "ldind.u4"; + case 76: + return "ldind.i8"; + case 77: + return "ldind.i"; + case 78: + return "ldind.r4"; + case 79: + return "ldind.r8"; + case 80: + return "ldind.ref"; + case 81: + return "stind.ref"; + case 82: + return "stind.i1"; + case 83: + return "stind.i2"; + case 84: + return "stind.i4"; + case 85: + return "stind.i8"; + case 86: + return "stind.r4"; + case 87: + return "stind.r8"; + case 88: + return "add"; + case 89: + return "sub"; + case 90: + return "mul"; + case 91: + return "div"; + case 92: + return "div.un"; + case 93: + return "rem"; + case 94: + return "rem.un"; + case 95: + return "and"; + case 96: + return "or"; + case 97: + return "xor"; + case 98: + return "shl"; + case 99: + return "shr"; + case 100: + return "shr.un"; + case 101: + return "neg"; + case 102: + return "not"; + case 103: + return "conv.i1"; + case 104: + return "conv.i2"; + case 105: + return "conv.i4"; + case 106: + return "conv.i8"; + case 107: + return "conv.r4"; + case 108: + return "conv.r8"; + case 109: + return "conv.u4"; + case 110: + return "conv.u8"; + case 111: + return "callvirt"; + case 112: + return "cpobj"; + case 113: + return "ldobj"; + case 114: + return "ldstr"; + case 115: + return "newobj"; + case 116: + return "castclass"; + case 117: + return "isinst"; + case 118: + return "conv.r.un"; + case 121: + return "unbox"; + case 122: + return "throw"; + case 123: + return "ldfld"; + case 124: + return "ldflda"; + case 125: + return "stfld"; + case 126: + return "ldsfld"; + case 127: + return "ldsflda"; + case 128: + return "stsfld"; + case 129: + return "stobj"; + case 130: + return "conv.ovf.i1.un"; + case 131: + return "conv.ovf.i2.un"; + case 132: + return "conv.ovf.i4.un"; + case 133: + return "conv.ovf.i8.un"; + case 134: + return "conv.ovf.u1.un"; + case 135: + return "conv.ovf.u2.un"; + case 136: + return "conv.ovf.u4.un"; + case 137: + return "conv.ovf.u8.un"; + case 138: + return "conv.ovf.i.un"; + case 139: + return "conv.ovf.u.un"; + case 140: + return "box"; + case 141: + return "newarr"; + case 142: + return "ldlen"; + case 143: + return "ldelema"; + case 144: + return "ldelem.i1"; + case 145: + return "ldelem.u1"; + case 146: + return "ldelem.i2"; + case 147: + return "ldelem.u2"; + case 148: + return "ldelem.i4"; + case 149: + return "ldelem.u4"; + case 150: + return "ldelem.i8"; + case 151: + return "ldelem.i"; + case 152: + return "ldelem.r4"; + case 153: + return "ldelem.r8"; + case 154: + return "ldelem.ref"; + case 155: + return "stelem.i"; + case 156: + return "stelem.i1"; + case 157: + return "stelem.i2"; + case 158: + return "stelem.i4"; + case 159: + return "stelem.i8"; + case 160: + return "stelem.r4"; + case 161: + return "stelem.r8"; + case 162: + return "stelem.ref"; + case 163: + return "ldelem"; + case 164: + return "stelem"; + case 165: + return "unbox.any"; + case 179: + return "conv.ovf.i1"; + case 180: + return "conv.ovf.u1"; + case 181: + return "conv.ovf.i2"; + case 182: + return "conv.ovf.u2"; + case 183: + return "conv.ovf.i4"; + case 184: + return "conv.ovf.u4"; + case 185: + return "conv.ovf.i8"; + case 186: + return "conv.ovf.u8"; + case 194: + return "refanyval"; + case 195: + return "ckfinite"; + case 198: + return "mkrefany"; + case 208: + return "ldtoken"; + case 209: + return "conv.u2"; + case 210: + return "conv.u1"; + case 211: + return "conv.i"; + case 212: + return "conv.ovf.i"; + case 213: + return "conv.ovf.u"; + case 214: + return "add.ovf"; + case 215: + return "add.ovf.un"; + case 216: + return "mul.ovf"; + case 217: + return "mul.ovf.un"; + case 218: + return "sub.ovf"; + case 219: + return "sub.ovf.un"; + case 220: + return "endfinally"; + case 221: + return "leave"; + case 222: + return "leave.s"; + case 223: + return "stind.i"; + case 224: + return "conv.u"; + case 248: + return "prefix7"; + case 249: + return "prefix6"; + case 250: + return "prefix5"; + case 251: + return "prefix4"; + case 252: + return "prefix3"; + case 253: + return "prefix2"; + case 254: + return "prefix1"; + case 255: + return "prefixref"; + case -512: + return "arglist"; + case -511: + return "ceq"; + case -510: + return "cgt"; + case -509: + return "cgt.un"; + case -508: + return "clt"; + case -507: + return "clt.un"; + case -506: + return "ldftn"; + case -505: + return "ldvirtftn"; + case -503: + return "ldarg"; + case -502: + return "ldarga"; + case -501: + return "starg"; + case -500: + return "ldloc"; + case -499: + return "ldloca"; + case -498: + return "stloc"; + case -497: + return "localloc"; + case -495: + return "endfilter"; + case -494: + return "unaligned."; + case -493: + return "volatile."; + case -492: + return "tail."; + case -491: + return "initobj"; + case -490: + return "constrained."; + case -489: + return "cpblk"; + case -488: + return "initblk"; + case -486: + return "rethrow"; + case -484: + return "sizeof"; + case -483: + return "refanytype"; + case -482: + return "readonly."; + } + throw new ArgumentOutOfRangeException(); + } + + public static bool TakesSingleByteArgument(OpCode inst) + { + switch (inst.Value) + { + case 14: + case 15: + case 16: + case 17: + case 18: + case 19: + case 31: + case 43: + case 44: + case 45: + case 46: + case 47: + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + case 222: + case -494: + return true; + default: + return false; + } + } + } +} diff --git a/reflect/Emit/ParameterBuilder.cs b/reflect/Emit/ParameterBuilder.cs new file mode 100644 index 0000000..4626496 --- /dev/null +++ b/reflect/Emit/ParameterBuilder.cs @@ -0,0 +1,141 @@ +/* + Copyright (C) 2008 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using IKVM.Reflection.Writer; +using IKVM.Reflection.Metadata; + +namespace IKVM.Reflection.Emit +{ + public sealed class ParameterBuilder + { + private readonly ModuleBuilder moduleBuilder; + private short flags; + private readonly short sequence; + private readonly int nameIndex; + private readonly string name; + private int lazyPseudoToken; + + internal ParameterBuilder(ModuleBuilder moduleBuilder, int sequence, ParameterAttributes attribs, string name) + { + this.moduleBuilder = moduleBuilder; + this.flags = (short)attribs; + this.sequence = (short)sequence; + this.nameIndex = name == null ? 0 : moduleBuilder.Strings.Add(name); + this.name = name; + } + + internal int PseudoToken + { + get + { + if (lazyPseudoToken == 0) + { + // we lazily create the token, because if we don't need it we don't want the token fixup cost + lazyPseudoToken = moduleBuilder.AllocPseudoToken(); + } + return lazyPseudoToken; + } + } + + public string Name + { + get { return name; } + } + + public int Position + { + // note that this differs from ParameterInfo.Position, which is zero based + get { return sequence; } + } + + public int Attributes + { + get { return flags; } + } + + public bool IsIn + { + get { return (flags & (short)ParameterAttributes.In) != 0; } + } + + public bool IsOut + { + get { return (flags & (short)ParameterAttributes.Out) != 0; } + } + + public bool IsOptional + { + get { return (flags & (short)ParameterAttributes.Optional) != 0; } + } + + public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) + { + SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute)); + } + + public void SetCustomAttribute(CustomAttributeBuilder customAttributeBuilder) + { + switch (customAttributeBuilder.KnownCA) + { + case KnownCA.InAttribute: + flags |= (short)ParameterAttributes.In; + break; + case KnownCA.OutAttribute: + flags |= (short)ParameterAttributes.Out; + break; + case KnownCA.OptionalAttribute: + flags |= (short)ParameterAttributes.Optional; + break; + case KnownCA.MarshalAsAttribute: + FieldMarshal.SetMarshalAsAttribute(moduleBuilder, PseudoToken, customAttributeBuilder); + flags |= (short)ParameterAttributes.HasFieldMarshal; + break; + default: + moduleBuilder.SetCustomAttribute(PseudoToken, customAttributeBuilder); + break; + } + } + + public void SetConstant(object defaultValue) + { + flags |= (short)ParameterAttributes.HasDefault; + moduleBuilder.AddConstant(PseudoToken, defaultValue); + } + + internal void WriteParamRecord(MetadataWriter mw) + { + mw.Write(flags); + mw.Write(sequence); + mw.WriteStringIndex(nameIndex); + } + + internal void FixupToken(int parameterToken) + { + if (lazyPseudoToken != 0) + { + moduleBuilder.RegisterTokenFixup(lazyPseudoToken, parameterToken); + } + } + } +} diff --git a/reflect/Emit/PropertyBuilder.cs b/reflect/Emit/PropertyBuilder.cs new file mode 100644 index 0000000..76661d0 --- /dev/null +++ b/reflect/Emit/PropertyBuilder.cs @@ -0,0 +1,287 @@ +/* + Copyright (C) 2008-2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using IKVM.Reflection.Writer; +using IKVM.Reflection.Metadata; + +namespace IKVM.Reflection.Emit +{ + public sealed class PropertyBuilder : PropertyInfo + { + private readonly TypeBuilder typeBuilder; + private readonly string name; + private PropertyAttributes attributes; + private PropertySignature sig; + private MethodBuilder getter; + private MethodBuilder setter; + private readonly List accessors = new List(); + private int lazyPseudoToken; + private bool patchCallingConvention; + + private struct Accessor + { + internal short Semantics; + internal MethodBuilder Method; + } + + internal PropertyBuilder(TypeBuilder typeBuilder, string name, PropertyAttributes attributes, PropertySignature sig, bool patchCallingConvention) + { + this.typeBuilder = typeBuilder; + this.name = name; + this.attributes = attributes; + this.sig = sig; + this.patchCallingConvention = patchCallingConvention; + } + + internal override PropertySignature PropertySignature + { + get { return sig; } + } + + public void SetGetMethod(MethodBuilder mdBuilder) + { + getter = mdBuilder; + Accessor acc; + acc.Semantics = MethodSemanticsTable.Getter; + acc.Method = mdBuilder; + accessors.Add(acc); + } + + public void SetSetMethod(MethodBuilder mdBuilder) + { + setter = mdBuilder; + Accessor acc; + acc.Semantics = MethodSemanticsTable.Setter; + acc.Method = mdBuilder; + accessors.Add(acc); + } + + public void AddOtherMethod(MethodBuilder mdBuilder) + { + Accessor acc; + acc.Semantics = MethodSemanticsTable.Other; + acc.Method = mdBuilder; + accessors.Add(acc); + } + + public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) + { + SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute)); + } + + public void SetCustomAttribute(CustomAttributeBuilder customBuilder) + { + if (customBuilder.KnownCA == KnownCA.SpecialNameAttribute) + { + attributes |= PropertyAttributes.SpecialName; + } + else + { + if (lazyPseudoToken == 0) + { + lazyPseudoToken = typeBuilder.ModuleBuilder.AllocPseudoToken(); + } + typeBuilder.ModuleBuilder.SetCustomAttribute(lazyPseudoToken, customBuilder); + } + } + + public override object GetRawConstantValue() + { + if (lazyPseudoToken != 0) + { + return typeBuilder.ModuleBuilder.Constant.GetRawConstantValue(typeBuilder.ModuleBuilder, lazyPseudoToken); + } + throw new InvalidOperationException(); + } + + public override PropertyAttributes Attributes + { + get { return attributes; } + } + + public override bool CanRead + { + get { return getter != null; } + } + + public override bool CanWrite + { + get { return setter != null; } + } + + public override MethodInfo GetGetMethod(bool nonPublic) + { + return nonPublic || (getter != null && getter.IsPublic) ? getter : null; + } + + public override MethodInfo GetSetMethod(bool nonPublic) + { + return nonPublic || (setter != null && setter.IsPublic) ? setter : null; + } + + public override MethodInfo[] GetAccessors(bool nonPublic) + { + List list = new List(); + foreach (Accessor acc in accessors) + { + AddAccessor(list, nonPublic, acc.Method); + } + return list.ToArray(); + } + + private static void AddAccessor(List list, bool nonPublic, MethodInfo method) + { + if (method != null && (nonPublic || method.IsPublic)) + { + list.Add(method); + } + } + + public override Type DeclaringType + { + get { return typeBuilder; } + } + + public override string Name + { + get { return name; } + } + + public override Module Module + { + get { return typeBuilder.Module; } + } + + public void SetConstant(object defaultValue) + { + if (lazyPseudoToken == 0) + { + lazyPseudoToken = typeBuilder.ModuleBuilder.AllocPseudoToken(); + } + attributes |= PropertyAttributes.HasDefault; + typeBuilder.ModuleBuilder.AddConstant(lazyPseudoToken, defaultValue); + } + + internal void Bake() + { + if (patchCallingConvention) + { + sig.HasThis = !this.IsStatic; + } + + PropertyTable.Record rec = new PropertyTable.Record(); + rec.Flags = (short)attributes; + rec.Name = typeBuilder.ModuleBuilder.Strings.Add(name); + rec.Type = typeBuilder.ModuleBuilder.GetSignatureBlobIndex(sig); + int token = 0x17000000 | typeBuilder.ModuleBuilder.Property.AddRecord(rec); + + if (lazyPseudoToken == 0) + { + lazyPseudoToken = token; + } + else + { + typeBuilder.ModuleBuilder.RegisterTokenFixup(lazyPseudoToken, token); + } + + foreach (Accessor acc in accessors) + { + AddMethodSemantics(acc.Semantics, acc.Method.MetadataToken, token); + } + } + + private void AddMethodSemantics(short semantics, int methodToken, int propertyToken) + { + MethodSemanticsTable.Record rec = new MethodSemanticsTable.Record(); + rec.Semantics = semantics; + rec.Method = methodToken; + rec.Association = propertyToken; + typeBuilder.ModuleBuilder.MethodSemantics.AddRecord(rec); + } + + internal override bool IsPublic + { + get + { + foreach (Accessor acc in accessors) + { + if (acc.Method.IsPublic) + { + return true; + } + } + return false; + } + } + + internal override bool IsNonPrivate + { + get + { + foreach (Accessor acc in accessors) + { + if ((acc.Method.Attributes & MethodAttributes.MemberAccessMask) > MethodAttributes.Private) + { + return true; + } + } + return false; + } + } + + internal override bool IsStatic + { + get + { + foreach (Accessor acc in accessors) + { + if (acc.Method.IsStatic) + { + return true; + } + } + return false; + } + } + + internal override bool IsBaked + { + get { return typeBuilder.IsBaked; } + } + + internal override int GetCurrentToken() + { + if (typeBuilder.ModuleBuilder.IsSaved && ModuleBuilder.IsPseudoToken(lazyPseudoToken)) + { + return typeBuilder.ModuleBuilder.ResolvePseudoToken(lazyPseudoToken); + } + else + { + return lazyPseudoToken; + } + } + } +} diff --git a/reflect/Emit/SignatureHelper.cs b/reflect/Emit/SignatureHelper.cs new file mode 100644 index 0000000..64dc18d --- /dev/null +++ b/reflect/Emit/SignatureHelper.cs @@ -0,0 +1,317 @@ +/* + Copyright (C) 2008-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using IKVM.Reflection; +using IKVM.Reflection.Writer; + +namespace IKVM.Reflection.Emit +{ + public abstract class SignatureHelper + { + protected readonly byte type; + protected ushort paramCount; + + sealed class Lazy : SignatureHelper + { + private readonly List args = new List(); + + internal Lazy(byte type) + : base(type) + { + } + + internal override Type ReturnType + { + get { return args[0]; } + } + + public override byte[] GetSignature() + { + throw new NotSupportedException(); + } + + internal override ByteBuffer GetSignature(ModuleBuilder module) + { + ByteBuffer bb = new ByteBuffer(16); + Signature.WriteSignatureHelper(module, bb, type, paramCount, args); + return bb; + } + + public override void AddSentinel() + { + args.Add(MarkerType.Sentinel); + } + + public override void __AddArgument(Type argument, bool pinned, CustomModifiers customModifiers) + { + if (pinned) + { + args.Add(MarkerType.Pinned); + } + foreach (CustomModifiers.Entry mod in customModifiers) + { + args.Add(mod.IsRequired ? MarkerType.ModReq : MarkerType.ModOpt); + args.Add(mod.Type); + } + args.Add(argument); + paramCount++; + } + } + + sealed class Eager : SignatureHelper + { + private readonly ModuleBuilder module; + private readonly ByteBuffer bb = new ByteBuffer(16); + private readonly Type returnType; + + internal Eager(ModuleBuilder module, byte type, Type returnType) + : base(type) + { + this.module = module; + this.returnType = returnType; + bb.Write(type); + if (type != Signature.FIELD) + { + // space for parameterCount + bb.Write((byte)0); + } + } + + internal override Type ReturnType + { + get { return returnType; } + } + + public override byte[] GetSignature() + { + return GetSignature(null).ToArray(); + } + + internal override ByteBuffer GetSignature(ModuleBuilder module) + { + if (type != Signature.FIELD) + { + bb.Position = 1; + bb.Insert(MetadataWriter.GetCompressedUIntLength(paramCount) - bb.GetCompressedUIntLength()); + bb.WriteCompressedUInt(paramCount); + } + return bb; + } + + public override void AddSentinel() + { + bb.Write(Signature.SENTINEL); + } + + public override void __AddArgument(Type argument, bool pinned, CustomModifiers customModifiers) + { + if (pinned) + { + bb.Write(Signature.ELEMENT_TYPE_PINNED); + } + foreach (CustomModifiers.Entry mod in customModifiers) + { + bb.Write(mod.IsRequired ? Signature.ELEMENT_TYPE_CMOD_REQD : Signature.ELEMENT_TYPE_CMOD_OPT); + Signature.WriteTypeSpec(module, bb, mod.Type); + } + Signature.WriteTypeSpec(module, bb, argument ?? module.universe.System_Void); + paramCount++; + } + } + + private SignatureHelper(byte type) + { + this.type = type; + } + + internal bool HasThis + { + get { return (type & Signature.HASTHIS) != 0; } + } + + internal abstract Type ReturnType + { + get; + } + + internal int ParameterCount + { + get { return paramCount; } + } + + private static SignatureHelper Create(Module mod, byte type, Type returnType) + { + ModuleBuilder mb = mod as ModuleBuilder; + return mb == null + ? (SignatureHelper)new Lazy(type) + : new Eager(mb, type, returnType); + } + + public static SignatureHelper GetFieldSigHelper(Module mod) + { + return Create(mod, Signature.FIELD, null); + } + + public static SignatureHelper GetLocalVarSigHelper() + { + return new Lazy(Signature.LOCAL_SIG); + } + + public static SignatureHelper GetLocalVarSigHelper(Module mod) + { + return Create(mod, Signature.LOCAL_SIG, null); + } + + public static SignatureHelper GetPropertySigHelper(Module mod, Type returnType, Type[] parameterTypes) + { + SignatureHelper sig = Create(mod, Signature.PROPERTY, returnType); + sig.AddArgument(returnType); + sig.paramCount = 0; + sig.AddArguments(parameterTypes, null, null); + return sig; + } + + public static SignatureHelper GetPropertySigHelper(Module mod, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers) + { + return GetPropertySigHelper(mod, CallingConventions.Standard, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers); + } + + public static SignatureHelper GetPropertySigHelper(Module mod, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers) + { + byte type = Signature.PROPERTY; + if ((callingConvention & CallingConventions.HasThis) != 0) + { + type |= Signature.HASTHIS; + } + SignatureHelper sig = Create(mod, type, returnType); + sig.AddArgument(returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers); + sig.paramCount = 0; + sig.AddArguments(parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers); + return sig; + } + + public static SignatureHelper GetMethodSigHelper(CallingConvention unmanagedCallingConvention, Type returnType) + { + return GetMethodSigHelper(null, unmanagedCallingConvention, returnType); + } + + public static SignatureHelper GetMethodSigHelper(CallingConventions callingConvention, Type returnType) + { + return GetMethodSigHelper(null, callingConvention, returnType); + } + + public static SignatureHelper GetMethodSigHelper(Module mod, CallingConvention unmanagedCallConv, Type returnType) + { + byte type; + switch (unmanagedCallConv) + { + case CallingConvention.Cdecl: + type = 0x01; // C + break; + case CallingConvention.StdCall: + case CallingConvention.Winapi: + type = 0x02; // STDCALL + break; + case CallingConvention.ThisCall: + type = 0x03; // THISCALL + break; + case CallingConvention.FastCall: + type = 0x04; // FASTCALL + break; + default: + throw new ArgumentOutOfRangeException("unmanagedCallConv"); + } + SignatureHelper sig = Create(mod, type, returnType); + sig.AddArgument(returnType); + sig.paramCount = 0; + return sig; + } + + public static SignatureHelper GetMethodSigHelper(Module mod, CallingConventions callingConvention, Type returnType) + { + byte type = 0; + if ((callingConvention & CallingConventions.HasThis) != 0) + { + type |= Signature.HASTHIS; + } + if ((callingConvention & CallingConventions.ExplicitThis) != 0) + { + type |= Signature.EXPLICITTHIS; + } + if ((callingConvention & CallingConventions.VarArgs) != 0) + { + type |= Signature.VARARG; + } + SignatureHelper sig = Create(mod, type, returnType); + sig.AddArgument(returnType); + sig.paramCount = 0; + return sig; + } + + public static SignatureHelper GetMethodSigHelper(Module mod, Type returnType, Type[] parameterTypes) + { + SignatureHelper sig = Create(mod, 0, returnType); + sig.AddArgument(returnType); + sig.paramCount = 0; + sig.AddArguments(parameterTypes, null, null); + return sig; + } + + public abstract byte[] GetSignature(); + + internal abstract ByteBuffer GetSignature(ModuleBuilder module); + + public abstract void AddSentinel(); + + public void AddArgument(Type clsArgument) + { + AddArgument(clsArgument, false); + } + + public void AddArgument(Type argument, bool pinned) + { + __AddArgument(argument, pinned, new CustomModifiers()); + } + + public void AddArgument(Type argument, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers) + { + __AddArgument(argument, false, CustomModifiers.FromReqOpt(requiredCustomModifiers, optionalCustomModifiers)); + } + + public abstract void __AddArgument(Type argument, bool pinned, CustomModifiers customModifiers); + + public void AddArguments(Type[] arguments, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers) + { + if (arguments != null) + { + for (int i = 0; i < arguments.Length; i++) + { + __AddArgument(arguments[i], false, CustomModifiers.FromReqOpt(Util.NullSafeElementAt(requiredCustomModifiers, i), Util.NullSafeElementAt(optionalCustomModifiers, i))); + } + } + } + } +} diff --git a/reflect/Emit/Tokens.cs b/reflect/Emit/Tokens.cs new file mode 100644 index 0000000..9b39f29 --- /dev/null +++ b/reflect/Emit/Tokens.cs @@ -0,0 +1,271 @@ +/* + Copyright (C) 2008 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +namespace IKVM.Reflection.Emit +{ + public struct EventToken + { + public static readonly EventToken Empty; + private readonly int token; + + internal EventToken(int token) + { + this.token = token; + } + + public int Token + { + get { return token; } + } + + public override bool Equals(object obj) + { + return obj as EventToken? == this; + } + + public override int GetHashCode() + { + return token; + } + + public bool Equals(EventToken other) + { + return this == other; + } + + public static bool operator ==(EventToken et1, EventToken et2) + { + return et1.token == et2.token; + } + + public static bool operator !=(EventToken et1, EventToken et2) + { + return et1.token != et2.token; + } + } + + public struct FieldToken + { + public static readonly FieldToken Empty; + private readonly int token; + + internal FieldToken(int token) + { + this.token = token; + } + + public int Token + { + get { return token; } + } + + public override bool Equals(object obj) + { + return obj as FieldToken? == this; + } + + public override int GetHashCode() + { + return token; + } + + public bool Equals(FieldToken other) + { + return this == other; + } + + public static bool operator ==(FieldToken ft1, FieldToken ft2) + { + return ft1.token == ft2.token; + } + + public static bool operator !=(FieldToken ft1, FieldToken ft2) + { + return ft1.token != ft2.token; + } + } + + public struct MethodToken + { + public static readonly MethodToken Empty; + private readonly int token; + + internal MethodToken(int token) + { + this.token = token; + } + + public int Token + { + get { return token; } + } + + public override bool Equals(object obj) + { + return obj as MethodToken? == this; + } + + public override int GetHashCode() + { + return token; + } + + public bool Equals(MethodToken other) + { + return this == other; + } + + public static bool operator ==(MethodToken mt1, MethodToken mt2) + { + return mt1.token == mt2.token; + } + + public static bool operator !=(MethodToken mt1, MethodToken mt2) + { + return mt1.token != mt2.token; + } + } + + public struct SignatureToken + { + public static readonly SignatureToken Empty; + private readonly int token; + + internal SignatureToken(int token) + { + this.token = token; + } + + public int Token + { + get { return token; } + } + + public override bool Equals(object obj) + { + return obj as SignatureToken? == this; + } + + public override int GetHashCode() + { + return token; + } + + public bool Equals(SignatureToken other) + { + return this == other; + } + + public static bool operator ==(SignatureToken st1, SignatureToken st2) + { + return st1.token == st2.token; + } + + public static bool operator !=(SignatureToken st1, SignatureToken st2) + { + return st1.token != st2.token; + } + } + + public struct StringToken + { + private readonly int token; + + internal StringToken(int token) + { + this.token = token; + } + + public int Token + { + get { return token; } + } + + public override bool Equals(object obj) + { + return obj as StringToken? == this; + } + + public override int GetHashCode() + { + return token; + } + + public bool Equals(StringToken other) + { + return this == other; + } + + public static bool operator ==(StringToken st1, StringToken st2) + { + return st1.token == st2.token; + } + + public static bool operator !=(StringToken st1, StringToken st2) + { + return st1.token != st2.token; + } + } + + public struct TypeToken + { + public static readonly TypeToken Empty; + private readonly int token; + + internal TypeToken(int token) + { + this.token = token; + } + + public int Token + { + get { return token; } + } + + public override bool Equals(object obj) + { + return obj as TypeToken? == this; + } + + public override int GetHashCode() + { + return token; + } + + public bool Equals(TypeToken other) + { + return this == other; + } + + public static bool operator ==(TypeToken tt1, TypeToken tt2) + { + return tt1.token == tt2.token; + } + + public static bool operator !=(TypeToken tt1, TypeToken tt2) + { + return tt1.token != tt2.token; + } + } +} diff --git a/reflect/Emit/TypeBuilder.cs b/reflect/Emit/TypeBuilder.cs new file mode 100644 index 0000000..9916ee6 --- /dev/null +++ b/reflect/Emit/TypeBuilder.cs @@ -0,0 +1,1208 @@ +/* + Copyright (C) 2008-2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.InteropServices; +using IKVM.Reflection.Impl; +using IKVM.Reflection.Metadata; +using IKVM.Reflection.Writer; + +namespace IKVM.Reflection.Emit +{ + public sealed class GenericTypeParameterBuilder : TypeInfo + { + private readonly string name; + private readonly TypeBuilder type; + private readonly MethodBuilder method; + private readonly int paramPseudoIndex; + private readonly int position; + private int typeToken; + private Type baseType; + private GenericParameterAttributes attr; + + internal GenericTypeParameterBuilder(string name, TypeBuilder type, int position) + : this(name, type, null, position, Signature.ELEMENT_TYPE_VAR) + { + } + + internal GenericTypeParameterBuilder(string name, MethodBuilder method, int position) + : this(name, null, method, position, Signature.ELEMENT_TYPE_MVAR) + { + } + + private GenericTypeParameterBuilder(string name, TypeBuilder type, MethodBuilder method, int position, byte sigElementType) + : base(sigElementType) + { + this.name = name; + this.type = type; + this.method = method; + this.position = position; + GenericParamTable.Record rec = new GenericParamTable.Record(); + rec.Number = (short)position; + rec.Flags = 0; + rec.Owner = type != null ? type.MetadataToken : method.MetadataToken; + rec.Name = this.ModuleBuilder.Strings.Add(name); + this.paramPseudoIndex = this.ModuleBuilder.GenericParam.AddRecord(rec); + } + + public override string AssemblyQualifiedName + { + get { return null; } + } + + public override bool IsValueType + { + get { return (this.GenericParameterAttributes & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0; } + } + + public override Type BaseType + { + get { return baseType; } + } + + public override Type[] __GetDeclaredInterfaces() + { + throw new NotImplementedException(); + } + + public override TypeAttributes Attributes + { + get { return TypeAttributes.Public; } + } + + public override string Namespace + { + get { return DeclaringType.Namespace; } + } + + public override string Name + { + get { return name; } + } + + public override string FullName + { + get { return null; } + } + + public override string ToString() + { + return this.Name; + } + + private ModuleBuilder ModuleBuilder + { + get { return type != null ? type.ModuleBuilder : method.ModuleBuilder; } + } + + public override Module Module + { + get { return ModuleBuilder; } + } + + public override int GenericParameterPosition + { + get { return position; } + } + + public override Type DeclaringType + { + get { return type; } + } + + public override MethodBase DeclaringMethod + { + get { return method; } + } + + public override Type[] GetGenericParameterConstraints() + { + throw new NotImplementedException(); + } + + public override CustomModifiers[] __GetGenericParameterConstraintCustomModifiers() + { + throw new NotImplementedException(); + } + + public override GenericParameterAttributes GenericParameterAttributes + { + get + { + CheckBaked(); + return attr; + } + } + + internal override void CheckBaked() + { + if (type != null) + { + type.CheckBaked(); + } + else + { + method.CheckBaked(); + } + } + + private void AddConstraint(Type type) + { + GenericParamConstraintTable.Record rec = new GenericParamConstraintTable.Record(); + rec.Owner = paramPseudoIndex; + rec.Constraint = this.ModuleBuilder.GetTypeTokenForMemberRef(type); + this.ModuleBuilder.GenericParamConstraint.AddRecord(rec); + } + + public void SetBaseTypeConstraint(Type baseTypeConstraint) + { + this.baseType = baseTypeConstraint; + AddConstraint(baseTypeConstraint); + } + + public void SetInterfaceConstraints(params Type[] interfaceConstraints) + { + foreach (Type type in interfaceConstraints) + { + AddConstraint(type); + } + } + + public void SetGenericParameterAttributes(GenericParameterAttributes genericParameterAttributes) + { + this.attr = genericParameterAttributes; + // for now we'll back patch the table + this.ModuleBuilder.GenericParam.PatchAttribute(paramPseudoIndex, genericParameterAttributes); + } + + public void SetCustomAttribute(CustomAttributeBuilder customBuilder) + { + this.ModuleBuilder.SetCustomAttribute((GenericParamTable.Index << 24) | paramPseudoIndex, customBuilder); + } + + public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) + { + SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute)); + } + + public override int MetadataToken + { + get + { + CheckBaked(); + return (GenericParamTable.Index << 24) | paramPseudoIndex; + } + } + + internal override int GetModuleBuilderToken() + { + if (typeToken == 0) + { + ByteBuffer spec = new ByteBuffer(5); + Signature.WriteTypeSpec(this.ModuleBuilder, spec, this); + typeToken = 0x1B000000 | this.ModuleBuilder.TypeSpec.AddRecord(this.ModuleBuilder.Blobs.Add(spec)); + } + return typeToken; + } + + internal override Type BindTypeParameters(IGenericBinder binder) + { + if (type != null) + { + return binder.BindTypeParameter(this); + } + else + { + return binder.BindMethodParameter(this); + } + } + + internal override int GetCurrentToken() + { + if (this.ModuleBuilder.IsSaved) + { + return (GenericParamTable.Index << 24) | this.Module.GenericParam.GetIndexFixup()[paramPseudoIndex - 1] + 1; + } + else + { + return (GenericParamTable.Index << 24) | paramPseudoIndex; + } + } + + internal override bool IsBaked + { + get { return ((MemberInfo)type ?? method).IsBaked; } + } + } + + public sealed class TypeBuilder : TypeInfo, ITypeOwner + { + public const int UnspecifiedTypeSize = 0; + private readonly ITypeOwner owner; + private readonly int token; + private int extends; + private Type lazyBaseType; // (lazyBaseType == null && attribs & TypeAttributes.Interface) == 0) => BaseType == System.Object + private readonly int typeName; + private readonly int typeNameSpace; + private readonly string ns; + private readonly string name; + private readonly List methods = new List(); + private readonly List fields = new List(); + private List properties; + private List events; + private TypeAttributes attribs; + private GenericTypeParameterBuilder[] gtpb; + private List declarativeSecurity; + private List interfaces; + private int size; + private short pack; + private bool hasLayout; + + internal TypeBuilder(ITypeOwner owner, string ns, string name) + { + this.owner = owner; + this.token = this.ModuleBuilder.TypeDef.AllocToken(); + this.ns = ns; + this.name = name; + this.typeNameSpace = ns == null ? 0 : this.ModuleBuilder.Strings.Add(ns); + this.typeName = this.ModuleBuilder.Strings.Add(name); + MarkKnownType(ns, name); + } + + public ConstructorBuilder DefineDefaultConstructor(MethodAttributes attributes) + { + ConstructorBuilder cb = DefineConstructor(attributes, CallingConventions.Standard, Type.EmptyTypes); + ILGenerator ilgen = cb.GetILGenerator(); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Call, BaseType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null)); + ilgen.Emit(OpCodes.Ret); + return cb; + } + + public ConstructorBuilder DefineConstructor(MethodAttributes attribs, CallingConventions callConv, Type[] parameterTypes) + { + return DefineConstructor(attribs, callConv, parameterTypes, null, null); + } + + public ConstructorBuilder DefineConstructor(MethodAttributes attribs, CallingConventions callingConvention, Type[] parameterTypes, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers) + { + attribs |= MethodAttributes.RTSpecialName | MethodAttributes.SpecialName; + string name = (attribs & MethodAttributes.Static) == 0 ? ConstructorInfo.ConstructorName : ConstructorInfo.TypeConstructorName; + MethodBuilder mb = DefineMethod(name, attribs, callingConvention, null, null, null, parameterTypes, requiredCustomModifiers, optionalCustomModifiers); + return new ConstructorBuilder(mb); + } + + public ConstructorBuilder DefineTypeInitializer() + { + MethodBuilder mb = DefineMethod(ConstructorInfo.TypeConstructorName, MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName, null, Type.EmptyTypes); + return new ConstructorBuilder(mb); + } + + private MethodBuilder CreateMethodBuilder(string name, MethodAttributes attributes, CallingConventions callingConvention) + { + this.ModuleBuilder.MethodDef.AddVirtualRecord(); + MethodBuilder mb = new MethodBuilder(this, name, attributes, callingConvention); + methods.Add(mb); + return mb; + } + + public MethodBuilder DefineMethod(string name, MethodAttributes attribs) + { + return DefineMethod(name, attribs, CallingConventions.Standard); + } + + public MethodBuilder DefineMethod(string name, MethodAttributes attribs, CallingConventions callingConvention) + { + return CreateMethodBuilder(name, attribs, callingConvention); + } + + public MethodBuilder DefineMethod(string name, MethodAttributes attribs, Type returnType, Type[] parameterTypes) + { + return DefineMethod(name, attribs, CallingConventions.Standard, returnType, null, null, parameterTypes, null, null); + } + + public MethodBuilder DefineMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes) + { + return DefineMethod(name, attributes, callingConvention, returnType, null, null, parameterTypes, null, null); + } + + public MethodBuilder DefineMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers) + { + MethodBuilder mb = CreateMethodBuilder(name, attributes, callingConvention); + mb.SetSignature(returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers); + return mb; + } + + public MethodBuilder DefinePInvokeMethod(string name, string dllName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet) + { + return DefinePInvokeMethod(name, dllName, null, attributes, callingConvention, returnType, null, null, parameterTypes, null, null, nativeCallConv, nativeCharSet); + } + + public MethodBuilder DefinePInvokeMethod(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet) + { + return DefinePInvokeMethod(name, dllName, entryName, attributes, callingConvention, returnType, null, null, parameterTypes, null, null, nativeCallConv, nativeCharSet); + } + + public MethodBuilder DefinePInvokeMethod(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, + Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, + Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers, + CallingConvention nativeCallConv, CharSet nativeCharSet) + { + MethodBuilder mb = DefineMethod(name, attributes | MethodAttributes.PinvokeImpl, callingConvention, + returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, + parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers); + mb.SetDllImportPseudoCustomAttribute(dllName, entryName, nativeCallConv, nativeCharSet, null, null, null, null, null); + return mb; + } + + public void DefineMethodOverride(MethodInfo methodInfoBody, MethodInfo methodInfoDeclaration) + { + MethodImplTable.Record rec = new MethodImplTable.Record(); + rec.Class = token; + rec.MethodBody = this.ModuleBuilder.GetMethodToken(methodInfoBody).Token; + rec.MethodDeclaration = this.ModuleBuilder.GetMethodTokenWinRT(methodInfoDeclaration); + this.ModuleBuilder.MethodImpl.AddRecord(rec); + } + + public FieldBuilder DefineField(string name, Type fieldType, FieldAttributes attribs) + { + return DefineField(name, fieldType, null, null, attribs); + } + + public FieldBuilder DefineField(string fieldName, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes) + { + return __DefineField(fieldName, type, CustomModifiers.FromReqOpt(requiredCustomModifiers, optionalCustomModifiers), attributes); + } + + public FieldBuilder __DefineField(string fieldName, Type type, CustomModifiers customModifiers, FieldAttributes attributes) + { + FieldBuilder fb = new FieldBuilder(this, fieldName, type, customModifiers, attributes); + fields.Add(fb); + return fb; + } + + public PropertyBuilder DefineProperty(string name, PropertyAttributes attributes, Type returnType, Type[] parameterTypes) + { + return DefineProperty(name, attributes, returnType, null, null, parameterTypes, null, null); + } + + public PropertyBuilder DefineProperty(string name, PropertyAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes) + { + return DefineProperty(name, attributes, callingConvention, returnType, null, null, parameterTypes, null, null); + } + + public PropertyBuilder DefineProperty(string name, PropertyAttributes attributes, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, + Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers) + { + return DefinePropertyImpl(name, attributes, CallingConventions.Standard, true, returnType, parameterTypes, + PackedCustomModifiers.CreateFromExternal(returnTypeOptionalCustomModifiers, returnTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers, parameterTypeRequiredCustomModifiers, Util.NullSafeLength(parameterTypes))); + } + + public PropertyBuilder DefineProperty(string name, PropertyAttributes attributes, CallingConventions callingConvention, + Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, + Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers) + { + return DefinePropertyImpl(name, attributes, callingConvention, false, returnType, parameterTypes, + PackedCustomModifiers.CreateFromExternal(returnTypeOptionalCustomModifiers, returnTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers, parameterTypeRequiredCustomModifiers, Util.NullSafeLength(parameterTypes))); + } + + public PropertyBuilder __DefineProperty(string name, PropertyAttributes attributes, CallingConventions callingConvention, + Type returnType, CustomModifiers returnTypeCustomModifiers, Type[] parameterTypes, CustomModifiers[] parameterTypeCustomModifiers) + { + return DefinePropertyImpl(name, attributes, callingConvention, false, returnType, parameterTypes, + PackedCustomModifiers.CreateFromExternal(returnTypeCustomModifiers, parameterTypeCustomModifiers, Util.NullSafeLength(parameterTypes))); + } + + private PropertyBuilder DefinePropertyImpl(string name, PropertyAttributes attributes, CallingConventions callingConvention, bool patchCallingConvention, + Type returnType, Type[] parameterTypes, PackedCustomModifiers customModifiers) + { + if (properties == null) + { + properties = new List(); + } + PropertySignature sig = PropertySignature.Create(callingConvention, returnType, parameterTypes, customModifiers); + PropertyBuilder pb = new PropertyBuilder(this, name, attributes, sig, patchCallingConvention); + properties.Add(pb); + return pb; + } + + public EventBuilder DefineEvent(string name, EventAttributes attributes, Type eventtype) + { + if (events == null) + { + events = new List(); + } + EventBuilder eb = new EventBuilder(this, name, attributes, eventtype); + events.Add(eb); + return eb; + } + + public TypeBuilder DefineNestedType(string name) + { + return DefineNestedType(name, TypeAttributes.Class | TypeAttributes.NestedPrivate); + } + + public TypeBuilder DefineNestedType(string name, TypeAttributes attribs) + { + return DefineNestedType(name, attribs, null); + } + + public TypeBuilder DefineNestedType(string name, TypeAttributes attr, Type parent, Type[] interfaces) + { + TypeBuilder tb = DefineNestedType(name, attr, parent); + if (interfaces != null) + { + foreach (Type iface in interfaces) + { + tb.AddInterfaceImplementation(iface); + } + } + return tb; + } + + public TypeBuilder DefineNestedType(string name, TypeAttributes attr, Type parent) + { + return DefineNestedType(name, attr, parent, 0); + } + + public TypeBuilder DefineNestedType(string name, TypeAttributes attr, Type parent, int typeSize) + { + return DefineNestedType(name, attr, parent, PackingSize.Unspecified, typeSize); + } + + public TypeBuilder DefineNestedType(string name, TypeAttributes attr, Type parent, PackingSize packSize) + { + return DefineNestedType(name, attr, parent, packSize, 0); + } + + public TypeBuilder DefineNestedType(string name, TypeAttributes attr, Type parent, PackingSize packSize, int typeSize) + { + string ns = null; + int lastdot = name.LastIndexOf('.'); + if (lastdot > 0) + { + ns = name.Substring(0, lastdot); + name = name.Substring(lastdot + 1); + } + TypeBuilder typeBuilder = __DefineNestedType(ns, name); + typeBuilder.__SetAttributes(attr); + typeBuilder.SetParent(parent); + if (packSize != PackingSize.Unspecified || typeSize != 0) + { + typeBuilder.__SetLayout((int)packSize, typeSize); + } + return typeBuilder; + } + + public TypeBuilder __DefineNestedType(string ns, string name) + { + this.typeFlags |= TypeFlags.HasNestedTypes; + TypeBuilder typeBuilder = this.ModuleBuilder.DefineType(this, ns, name); + NestedClassTable.Record rec = new NestedClassTable.Record(); + rec.NestedClass = typeBuilder.MetadataToken; + rec.EnclosingClass = this.MetadataToken; + this.ModuleBuilder.NestedClass.AddRecord(rec); + return typeBuilder; + } + + public void SetParent(Type parent) + { + lazyBaseType = parent; + } + + public void AddInterfaceImplementation(Type interfaceType) + { + if (interfaces == null) + { + interfaces = new List(); + } + interfaces.Add(interfaceType); + } + + public void __SetInterfaceImplementationCustomAttribute(Type interfaceType, CustomAttributeBuilder cab) + { + this.ModuleBuilder.SetInterfaceImplementationCustomAttribute(this, interfaceType, cab); + } + + public int Size + { + get { return size; } + } + + public PackingSize PackingSize + { + get { return (PackingSize)pack; } + } + + public override bool __GetLayout(out int packingSize, out int typeSize) + { + packingSize = this.pack; + typeSize = this.size; + return hasLayout; + } + + public void __SetLayout(int packingSize, int typesize) + { + this.pack = (short)packingSize; + this.size = typesize; + this.hasLayout = true; + } + + private void SetStructLayoutPseudoCustomAttribute(CustomAttributeBuilder customBuilder) + { + object val = customBuilder.GetConstructorArgument(0); + LayoutKind layout; + if (val is short) + { + layout = (LayoutKind)(short)val; + } + else + { + layout = (LayoutKind)val; + } + pack = (short)((int?)customBuilder.GetFieldValue("Pack") ?? 0); + size = (int?)customBuilder.GetFieldValue("Size") ?? 0; + CharSet charSet = customBuilder.GetFieldValue("CharSet") ?? CharSet.None; + attribs &= ~TypeAttributes.LayoutMask; + switch (layout) + { + case LayoutKind.Auto: + attribs |= TypeAttributes.AutoLayout; + break; + case LayoutKind.Explicit: + attribs |= TypeAttributes.ExplicitLayout; + break; + case LayoutKind.Sequential: + attribs |= TypeAttributes.SequentialLayout; + break; + } + attribs &= ~TypeAttributes.StringFormatMask; + switch (charSet) + { + case CharSet.None: + case CharSet.Ansi: + attribs |= TypeAttributes.AnsiClass; + break; + case CharSet.Auto: + attribs |= TypeAttributes.AutoClass; + break; + case CharSet.Unicode: + attribs |= TypeAttributes.UnicodeClass; + break; + } + hasLayout = pack != 0 || size != 0; + } + + public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) + { + SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute)); + } + + public void SetCustomAttribute(CustomAttributeBuilder customBuilder) + { + switch (customBuilder.KnownCA) + { + case KnownCA.StructLayoutAttribute: + SetStructLayoutPseudoCustomAttribute(customBuilder.DecodeBlob(this.Assembly)); + break; + case KnownCA.SerializableAttribute: + attribs |= TypeAttributes.Serializable; + break; + case KnownCA.ComImportAttribute: + attribs |= TypeAttributes.Import; + break; + case KnownCA.SpecialNameAttribute: + attribs |= TypeAttributes.SpecialName; + break; + case KnownCA.SuppressUnmanagedCodeSecurityAttribute: + attribs |= TypeAttributes.HasSecurity; + goto default; + default: + this.ModuleBuilder.SetCustomAttribute(token, customBuilder); + break; + } + } + + public void __AddDeclarativeSecurity(CustomAttributeBuilder customBuilder) + { + attribs |= TypeAttributes.HasSecurity; + if (declarativeSecurity == null) + { + declarativeSecurity = new List(); + } + declarativeSecurity.Add(customBuilder); + } + +#if !CORECLR + public void AddDeclarativeSecurity(System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet) + { + this.ModuleBuilder.AddDeclarativeSecurity(token, securityAction, permissionSet); + this.attribs |= TypeAttributes.HasSecurity; + } +#endif + + public GenericTypeParameterBuilder[] DefineGenericParameters(params string[] names) + { + typeFlags |= TypeFlags.IsGenericTypeDefinition; + gtpb = new GenericTypeParameterBuilder[names.Length]; + for (int i = 0; i < names.Length; i++) + { + gtpb[i] = new GenericTypeParameterBuilder(names[i], this, i); + } + return (GenericTypeParameterBuilder[])gtpb.Clone(); + } + + public override Type[] GetGenericArguments() + { + return Util.Copy(gtpb); + } + + public override CustomModifiers[] __GetGenericArgumentsCustomModifiers() + { + return gtpb == null ? Empty.Array : new CustomModifiers[gtpb.Length]; + } + + internal override Type GetGenericTypeArgument(int index) + { + return gtpb[index]; + } + + public override bool ContainsGenericParameters + { + get { return gtpb != null; } + } + + public override Type GetGenericTypeDefinition() + { + return this; + } + + public TypeInfo CreateTypeInfo() + { + if ((typeFlags & TypeFlags.Baked) != 0) + { + // .NET allows multiple invocations (subsequent invocations return the same baked type) + throw new NotImplementedException(); + } + typeFlags |= TypeFlags.Baked; + if (hasLayout) + { + ClassLayoutTable.Record rec = new ClassLayoutTable.Record(); + rec.PackingSize = pack; + rec.ClassSize = size; + rec.Parent = token; + this.ModuleBuilder.ClassLayout.AddRecord(rec); + } + bool hasConstructor = false; + foreach (MethodBuilder mb in methods) + { + hasConstructor |= mb.IsSpecialName && mb.Name == ConstructorInfo.ConstructorName; + mb.Bake(); + } + if (!hasConstructor && !IsModulePseudoType && !IsInterface && !IsValueType && !(IsAbstract && IsSealed) && Universe.AutomaticallyProvideDefaultConstructor) + { + ((MethodBuilder)DefineDefaultConstructor(MethodAttributes.Public).GetMethodInfo()).Bake(); + } + if (declarativeSecurity != null) + { + this.ModuleBuilder.AddDeclarativeSecurity(token, declarativeSecurity); + } + if (!IsModulePseudoType) + { + Type baseType = this.BaseType; + if (baseType != null) + { + extends = this.ModuleBuilder.GetTypeToken(baseType).Token; + } + } + if (interfaces != null) + { + foreach (Type interfaceType in interfaces) + { + InterfaceImplTable.Record rec = new InterfaceImplTable.Record(); + rec.Class = token; + rec.Interface = this.ModuleBuilder.GetTypeToken(interfaceType).Token; + this.ModuleBuilder.InterfaceImpl.AddRecord(rec); + } + } + return new BakedType(this); + } + + public Type CreateType() + { + return CreateTypeInfo(); + } + + internal void PopulatePropertyAndEventTables() + { + if (properties != null) + { + PropertyMapTable.Record rec = new PropertyMapTable.Record(); + rec.Parent = token; + rec.PropertyList = this.ModuleBuilder.Property.RowCount + 1; + this.ModuleBuilder.PropertyMap.AddRecord(rec); + foreach (PropertyBuilder pb in properties) + { + pb.Bake(); + } + } + if (events != null) + { + EventMapTable.Record rec = new EventMapTable.Record(); + rec.Parent = token; + rec.EventList = this.ModuleBuilder.Event.RowCount + 1; + this.ModuleBuilder.EventMap.AddRecord(rec); + foreach (EventBuilder eb in events) + { + eb.Bake(); + } + } + } + + public override Type BaseType + { + get + { + if (lazyBaseType == null && !IsInterface) + { + Type obj = Module.universe.System_Object; + if (this != obj) + { + lazyBaseType = obj; + } + } + return lazyBaseType; + } + } + + public override string FullName + { + get + { + if (this.IsNested) + { + return this.DeclaringType.FullName + "+" + TypeNameParser.Escape(name); + } + if (ns == null) + { + return TypeNameParser.Escape(name); + } + else + { + return TypeNameParser.Escape(ns) + "." + TypeNameParser.Escape(name); + } + } + } + + internal override TypeName TypeName + { + get { return new TypeName(ns, name); } + } + + public override string Name + { + // FXBUG for a TypeBuilder the name is not escaped + get { return name; } + } + + public override string Namespace + { + get + { + // for some reason, TypeBuilder doesn't return null (and mcs depends on this) + // note also that we don't return the declaring type namespace for nested types + return ns ?? ""; + } + } + + public override TypeAttributes Attributes + { + get { return attribs; } + } + + public void __SetAttributes(TypeAttributes attributes) + { + this.attribs = attributes; + } + + public override Type[] __GetDeclaredInterfaces() + { + return Util.ToArray(interfaces, Type.EmptyTypes); + } + + public override MethodBase[] __GetDeclaredMethods() + { + MethodBase[] methods = new MethodBase[this.methods.Count]; + for (int i = 0; i < methods.Length; i++) + { + MethodBuilder mb = this.methods[i]; + if (mb.IsConstructor) + { + methods[i] = new ConstructorInfoImpl(mb); + } + else + { + methods[i] = mb; + } + } + return methods; + } + + public override Type DeclaringType + { + get { return owner as TypeBuilder; } + } + + public override bool IsGenericType + { + get { return IsGenericTypeDefinition; } + } + + public override bool IsGenericTypeDefinition + { + get { return (typeFlags & TypeFlags.IsGenericTypeDefinition) != 0; } + } + + public override int MetadataToken + { + get { return token; } + } + + public FieldBuilder DefineUninitializedData(string name, int size, FieldAttributes attributes) + { + return DefineInitializedData(name, new byte[size], attributes); + } + + public FieldBuilder DefineInitializedData(string name, byte[] data, FieldAttributes attributes) + { + Type fieldType = this.ModuleBuilder.GetType("$ArrayType$" + data.Length); + if (fieldType == null) + { + TypeBuilder tb = this.ModuleBuilder.DefineType("$ArrayType$" + data.Length, TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.ExplicitLayout, this.Module.universe.System_ValueType, PackingSize.Size1, data.Length); + tb.CreateType(); + fieldType = tb; + } + FieldBuilder fb = DefineField(name, fieldType, attributes | FieldAttributes.Static); + fb.__SetDataAndRVA(data); + return fb; + } + + public static MethodInfo GetMethod(Type type, MethodInfo method) + { + return new GenericMethodInstance(type, method, null); + } + + public static ConstructorInfo GetConstructor(Type type, ConstructorInfo constructor) + { + return new ConstructorInfoImpl(GetMethod(type, constructor.GetMethodInfo())); + } + + public static FieldInfo GetField(Type type, FieldInfo field) + { + return new GenericFieldInstance(type, field); + } + + public override Module Module + { + get { return owner.ModuleBuilder; } + } + + public TypeToken TypeToken + { + get { return new TypeToken(token); } + } + + internal void WriteTypeDefRecord(MetadataWriter mw, ref int fieldList, ref int methodList) + { + mw.Write((int)attribs); + mw.WriteStringIndex(typeName); + mw.WriteStringIndex(typeNameSpace); + mw.WriteTypeDefOrRef(extends); + mw.WriteField(fieldList); + mw.WriteMethodDef(methodList); + methodList += methods.Count; + fieldList += fields.Count; + } + + internal void WriteMethodDefRecords(int baseRVA, MetadataWriter mw, ref int paramList) + { + foreach (MethodBuilder mb in methods) + { + mb.WriteMethodDefRecord(baseRVA, mw, ref paramList); + } + } + + internal void ResolveMethodAndFieldTokens(ref int methodToken, ref int fieldToken, ref int parameterToken) + { + foreach (MethodBuilder method in methods) + { + method.FixupToken(methodToken++, ref parameterToken); + } + foreach (FieldBuilder field in fields) + { + field.FixupToken(fieldToken++); + } + } + + internal void WriteParamRecords(MetadataWriter mw) + { + foreach (MethodBuilder mb in methods) + { + mb.WriteParamRecords(mw); + } + } + + internal void WriteFieldRecords(MetadataWriter mw) + { + foreach (FieldBuilder fb in fields) + { + fb.WriteFieldRecords(mw); + } + } + + internal ModuleBuilder ModuleBuilder + { + get { return owner.ModuleBuilder; } + } + + ModuleBuilder ITypeOwner.ModuleBuilder + { + get { return owner.ModuleBuilder; } + } + + internal override int GetModuleBuilderToken() + { + return token; + } + + internal bool HasNestedTypes + { + get { return (typeFlags & TypeFlags.HasNestedTypes) != 0; } + } + + // helper for ModuleBuilder.ResolveMethod() + internal MethodBase LookupMethod(int token) + { + foreach (MethodBuilder method in methods) + { + if (method.MetadataToken == token) + { + return method; + } + } + return null; + } + + public bool IsCreated() + { + return (typeFlags & TypeFlags.Baked) != 0; + } + + internal override void CheckBaked() + { + if ((typeFlags & TypeFlags.Baked) == 0) + { + throw new NotSupportedException(); + } + } + + public override Type[] __GetDeclaredTypes() + { + if (this.HasNestedTypes) + { + List types = new List(); + List classes = this.ModuleBuilder.NestedClass.GetNestedClasses(token); + foreach (int nestedClass in classes) + { + types.Add(this.ModuleBuilder.ResolveType(nestedClass)); + } + return types.ToArray(); + } + else + { + return Type.EmptyTypes; + } + } + + public override FieldInfo[] __GetDeclaredFields() + { + return Util.ToArray(fields, Empty.Array); + } + + public override EventInfo[] __GetDeclaredEvents() + { + return Util.ToArray(events, Empty.Array); + } + + public override PropertyInfo[] __GetDeclaredProperties() + { + return Util.ToArray(properties, Empty.Array); + } + + internal override bool IsModulePseudoType + { + get { return token == 0x02000001; } + } + + internal override bool IsBaked + { + get { return IsCreated(); } + } + } + + sealed class BakedType : TypeInfo + { + internal BakedType(TypeBuilder typeBuilder) + : base(typeBuilder) + { + } + + public override string AssemblyQualifiedName + { + get { return underlyingType.AssemblyQualifiedName; } + } + + public override Type BaseType + { + get { return underlyingType.BaseType; } + } + + internal override TypeName TypeName + { + get { return underlyingType.TypeName; } + } + + public override string Name + { + // we need to escape here, because TypeBuilder.Name does not escape + get { return TypeNameParser.Escape(underlyingType.__Name); } + } + + public override string FullName + { + get { return GetFullName(); } + } + + public override TypeAttributes Attributes + { + get { return underlyingType.Attributes; } + } + + public override Type[] __GetDeclaredInterfaces() + { + return underlyingType.__GetDeclaredInterfaces(); + } + + public override MethodBase[] __GetDeclaredMethods() + { + return underlyingType.__GetDeclaredMethods(); + } + + public override __MethodImplMap __GetMethodImplMap() + { + return underlyingType.__GetMethodImplMap(); + } + + public override FieldInfo[] __GetDeclaredFields() + { + return underlyingType.__GetDeclaredFields(); + } + + public override EventInfo[] __GetDeclaredEvents() + { + return underlyingType.__GetDeclaredEvents(); + } + + public override PropertyInfo[] __GetDeclaredProperties() + { + return underlyingType.__GetDeclaredProperties(); + } + + public override Type[] __GetDeclaredTypes() + { + return underlyingType.__GetDeclaredTypes(); + } + + public override Type DeclaringType + { + get { return underlyingType.DeclaringType; } + } + + public override bool __GetLayout(out int packingSize, out int typeSize) + { + return underlyingType.__GetLayout(out packingSize, out typeSize); + } + + public override Type[] GetGenericArguments() + { + return underlyingType.GetGenericArguments(); + } + + internal override Type GetGenericTypeArgument(int index) + { + return underlyingType.GetGenericTypeArgument(index); + } + + public override CustomModifiers[] __GetGenericArgumentsCustomModifiers() + { + return underlyingType.__GetGenericArgumentsCustomModifiers(); + } + + public override bool IsGenericType + { + get { return underlyingType.IsGenericType; } + } + + public override bool IsGenericTypeDefinition + { + get { return underlyingType.IsGenericTypeDefinition; } + } + + public override bool ContainsGenericParameters + { + get { return underlyingType.ContainsGenericParameters; } + } + + public override int MetadataToken + { + get { return underlyingType.MetadataToken; } + } + + public override Module Module + { + get { return underlyingType.Module; } + } + + internal override int GetModuleBuilderToken() + { + return underlyingType.GetModuleBuilderToken(); + } + + internal override bool IsBaked + { + get { return true; } + } + } +} diff --git a/reflect/Enums.cs b/reflect/Enums.cs new file mode 100644 index 0000000..9fcbb6d --- /dev/null +++ b/reflect/Enums.cs @@ -0,0 +1,325 @@ +/* + Copyright (C) 2009-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; + +namespace IKVM.Reflection +{ + [Flags] + public enum AssemblyNameFlags + { + None = 0, + PublicKey = 1, + Retargetable = 256, + EnableJITcompileOptimizer = 16384, + EnableJITcompileTracking = 32768, + } + + public enum AssemblyContentType + { + Default = 0, + WindowsRuntime = 1, + } + + [Flags] + public enum BindingFlags + { + Default = 0, + IgnoreCase = 1, + DeclaredOnly = 2, + Instance = 4, + Static = 8, + Public = 16, + NonPublic = 32, + FlattenHierarchy = 64, + } + + [Flags] + public enum CallingConventions + { + Standard = 1, + VarArgs = 2, + Any = 3, + HasThis = 32, + ExplicitThis = 64, + } + + [Flags] + public enum EventAttributes + { + None = 0, + SpecialName = 512, + RTSpecialName = 1024, + ReservedMask = 1024, + } + + [Flags] + public enum FieldAttributes + { + PrivateScope = 0, + Private = 1, + FamANDAssem = 2, + Assembly = 3, + Family = 4, + FamORAssem = 5, + Public = 6, + FieldAccessMask = 7, + Static = 16, + InitOnly = 32, + Literal = 64, + NotSerialized = 128, + HasFieldRVA = 256, + SpecialName = 512, + RTSpecialName = 1024, + HasFieldMarshal = 4096, + PinvokeImpl = 8192, + HasDefault = 32768, + ReservedMask = 38144, + } + + [Flags] + public enum GenericParameterAttributes + { + None = 0, + Covariant = 1, + Contravariant = 2, + VarianceMask = 3, + ReferenceTypeConstraint = 4, + NotNullableValueTypeConstraint = 8, + DefaultConstructorConstraint = 16, + SpecialConstraintMask = 28, + } + + public enum ImageFileMachine + { + I386 = 332, + ARM = 452, + IA64 = 512, + AMD64 = 34404, + } + + [FlagsAttribute] + public enum MemberTypes + { + Constructor = 0x01, + Event = 0x02, + Field = 0x04, + Method = 0x08, + Property = 0x10, + TypeInfo = 0x20, + Custom = 0x40, + NestedType = 0x80, + All = Constructor | Event | Field | Method | Property | TypeInfo | NestedType + } + + [Flags] + public enum MethodAttributes + { + MemberAccessMask = 0x0007, + PrivateScope = 0x0000, + Private = 0x0001, + FamANDAssem = 0x0002, + Assembly = 0x0003, + Family = 0x0004, + FamORAssem = 0x0005, + Public = 0x0006, + Static = 0x0010, + Final = 0x0020, + Virtual = 0x0040, + HideBySig = 0x0080, + VtableLayoutMask = 0x0100, + ReuseSlot = 0x0000, + NewSlot = 0x0100, + CheckAccessOnOverride = 0x0200, + Abstract = 0x0400, + SpecialName = 0x0800, + + PinvokeImpl = 0x2000, + UnmanagedExport = 0x0008, + + RTSpecialName = 0x1000, + HasSecurity = 0x4000, + RequireSecObject = 0x8000, + + ReservedMask = 0xd000, + } + + [Flags] + public enum MethodImplAttributes + { + CodeTypeMask = 0x0003, + IL = 0x0000, + Native = 0x0001, + OPTIL = 0x0002, + Runtime = 0x0003, + ManagedMask = 0x0004, + Unmanaged = 0x0004, + Managed = 0x0000, + + ForwardRef = 0x0010, + PreserveSig = 0x0080, + InternalCall = 0x1000, + Synchronized = 0x0020, + NoInlining = 0x0008, + NoOptimization = 0x0040, + AggressiveInlining = 0x0100, + + MaxMethodImplVal = 0xffff, + } + + [Flags] + public enum ParameterAttributes + { + None = 0, + In = 1, + Out = 2, + Lcid = 4, + Retval = 8, + Optional = 16, + HasDefault = 4096, + HasFieldMarshal = 8192, + Reserved3 = 16384, + Reserved4 = 32768, + ReservedMask = 61440, + } + + [Flags] + public enum PortableExecutableKinds + { + NotAPortableExecutableImage = 0, + ILOnly = 1, + Required32Bit = 2, + PE32Plus = 4, + Unmanaged32Bit = 8, + Preferred32Bit = 16, + } + + public enum ProcessorArchitecture + { + None = 0, + MSIL = 1, + X86 = 2, + IA64 = 3, + Amd64 = 4, + Arm = 5, + // if an item is added here, make sure to update AssemblyName.ProcessorArchitecture, + // AssemblyReader.GetNameImpl() and Fusion.ParseAssemblyName as well + } + + [Flags] + public enum PropertyAttributes + { + None = 0, + SpecialName = 512, + RTSpecialName = 1024, + HasDefault = 4096, + } + + [Flags] + public enum ResourceAttributes + { + Public = 1, + Private = 2, + } + + [Flags] + public enum ResourceLocation + { + Embedded = 1, + ContainedInAnotherAssembly = 2, + ContainedInManifestFile = 4, + } + + [Flags] + public enum TypeAttributes + { + AnsiClass = 0, + Class = 0, + AutoLayout = 0, + NotPublic = 0, + Public = 1, + NestedPublic = 2, + NestedPrivate = 3, + NestedFamily = 4, + NestedAssembly = 5, + NestedFamANDAssem = 6, + VisibilityMask = 7, + NestedFamORAssem = 7, + SequentialLayout = 8, + ExplicitLayout = 16, + LayoutMask = 24, + ClassSemanticsMask = 32, + Interface = 32, + Abstract = 128, + Sealed = 256, + SpecialName = 1024, + RTSpecialName = 2048, + Import = 4096, + Serializable = 8192, + WindowsRuntime = 16384, + UnicodeClass = 65536, + AutoClass = 131072, + CustomFormatClass = 196608, + StringFormatMask = 196608, + HasSecurity = 262144, + ReservedMask = 264192, + BeforeFieldInit = 1048576, + CustomFormatMask = 12582912, + } + + // IKVM.Reflection specific type + [Flags] + public enum DllCharacteristics + { + HighEntropyVA = 0x0020, // IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA + DynamicBase = 0x0040, // IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE + NoSEH = 0x0400, // IMAGE_DLLCHARACTERISTICS_NO_SEH + NXCompat = 0x0100, // IMAGE_DLLCHARACTERISTICS_NX_COMPAT + AppContainer = 0x1000, // IMAGE_DLLCHARACTERISTICS_APPCONTAINER + TerminalServerAware = 0x8000, // IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE + } + + // IKVM.Reflection specific type + [Flags] + public enum ImplMapFlags + { + NoMangle = 0x0001, + CharSetMask = 0x0006, + CharSetNotSpec = 0x0000, + CharSetAnsi = 0x0002, + CharSetUnicode = 0x0004, + CharSetAuto = 0x0006, + SupportsLastError = 0x0040, + CallConvMask = 0x0700, + CallConvWinapi = 0x0100, + CallConvCdecl = 0x0200, + CallConvStdcall = 0x0300, + CallConvThiscall = 0x0400, + CallConvFastcall = 0x0500, + // non-standard flags (i.e. CLR specific) + BestFitOn = 0x0010, + BestFitOff = 0x0020, + CharMapErrorOn = 0x1000, + CharMapErrorOff = 0x2000, + } +} diff --git a/reflect/EventInfo.cs b/reflect/EventInfo.cs new file mode 100644 index 0000000..d8f3c03 --- /dev/null +++ b/reflect/EventInfo.cs @@ -0,0 +1,252 @@ +/* + Copyright (C) 2009-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System.Collections.Generic; +using System.Diagnostics; + +namespace IKVM.Reflection +{ + public abstract class EventInfo : MemberInfo + { + // prevent external subclasses + internal EventInfo() + { + } + + public sealed override MemberTypes MemberType + { + get { return MemberTypes.Event; } + } + + public abstract EventAttributes Attributes { get; } + public abstract MethodInfo GetAddMethod(bool nonPublic); + public abstract MethodInfo GetRaiseMethod(bool nonPublic); + public abstract MethodInfo GetRemoveMethod(bool nonPublic); + public abstract MethodInfo[] GetOtherMethods(bool nonPublic); + public abstract MethodInfo[] __GetMethods(); + public abstract Type EventHandlerType { get; } + internal abstract bool IsPublic { get; } + internal abstract bool IsNonPrivate { get; } + internal abstract bool IsStatic { get; } + + public bool IsSpecialName + { + get { return (Attributes & EventAttributes.SpecialName) != 0; } + } + + public MethodInfo GetAddMethod() + { + return GetAddMethod(false); + } + + public MethodInfo GetRaiseMethod() + { + return GetRaiseMethod(false); + } + + public MethodInfo GetRemoveMethod() + { + return GetRemoveMethod(false); + } + + public MethodInfo[] GetOtherMethods() + { + return GetOtherMethods(false); + } + + public MethodInfo AddMethod + { + get { return GetAddMethod(true); } + } + + public MethodInfo RaiseMethod + { + get { return GetRaiseMethod(true); } + } + + public MethodInfo RemoveMethod + { + get { return GetRemoveMethod(true); } + } + + internal virtual EventInfo BindTypeParameters(Type type) + { + return new GenericEventInfo(this.DeclaringType.BindTypeParameters(type), this); + } + + public override string ToString() + { + return this.DeclaringType.ToString() + " " + Name; + } + + internal sealed override bool BindingFlagsMatch(BindingFlags flags) + { + return BindingFlagsMatch(IsPublic, flags, BindingFlags.Public, BindingFlags.NonPublic) + && BindingFlagsMatch(IsStatic, flags, BindingFlags.Static, BindingFlags.Instance); + } + + internal sealed override bool BindingFlagsMatchInherited(BindingFlags flags) + { + return IsNonPrivate + && BindingFlagsMatch(IsPublic, flags, BindingFlags.Public, BindingFlags.NonPublic) + && BindingFlagsMatch(IsStatic, flags, BindingFlags.Static | BindingFlags.FlattenHierarchy, BindingFlags.Instance); + } + + internal sealed override MemberInfo SetReflectedType(Type type) + { + return new EventInfoWithReflectedType(type, this); + } + + internal sealed override List GetPseudoCustomAttributes(Type attributeType) + { + // events don't have pseudo custom attributes + return null; + } + } + + sealed class EventInfoWithReflectedType : EventInfo + { + private readonly Type reflectedType; + private readonly EventInfo eventInfo; + + internal EventInfoWithReflectedType(Type reflectedType, EventInfo eventInfo) + { + Debug.Assert(reflectedType != eventInfo.DeclaringType); + this.reflectedType = reflectedType; + this.eventInfo = eventInfo; + } + + public override EventAttributes Attributes + { + get { return eventInfo.Attributes; } + } + + public override MethodInfo GetAddMethod(bool nonPublic) + { + return SetReflectedType(eventInfo.GetAddMethod(nonPublic), reflectedType); + } + + public override MethodInfo GetRaiseMethod(bool nonPublic) + { + return SetReflectedType(eventInfo.GetRaiseMethod(nonPublic), reflectedType); + } + + public override MethodInfo GetRemoveMethod(bool nonPublic) + { + return SetReflectedType(eventInfo.GetRemoveMethod(nonPublic), reflectedType); + } + + public override MethodInfo[] GetOtherMethods(bool nonPublic) + { + return SetReflectedType(eventInfo.GetOtherMethods(nonPublic), reflectedType); + } + + public override MethodInfo[] __GetMethods() + { + return SetReflectedType(eventInfo.__GetMethods(), reflectedType); + } + + public override Type EventHandlerType + { + get { return eventInfo.EventHandlerType; } + } + + internal override bool IsPublic + { + get { return eventInfo.IsPublic; } + } + + internal override bool IsNonPrivate + { + get { return eventInfo.IsNonPrivate; } + } + + internal override bool IsStatic + { + get { return eventInfo.IsStatic; } + } + + internal override EventInfo BindTypeParameters(Type type) + { + return eventInfo.BindTypeParameters(type); + } + + public override string ToString() + { + return eventInfo.ToString(); + } + + public override bool __IsMissing + { + get { return eventInfo.__IsMissing; } + } + + public override Type DeclaringType + { + get { return eventInfo.DeclaringType; } + } + + public override Type ReflectedType + { + get { return reflectedType; } + } + + public override bool Equals(object obj) + { + EventInfoWithReflectedType other = obj as EventInfoWithReflectedType; + return other != null + && other.reflectedType == reflectedType + && other.eventInfo == eventInfo; + } + + public override int GetHashCode() + { + return reflectedType.GetHashCode() ^ eventInfo.GetHashCode(); + } + + public override int MetadataToken + { + get { return eventInfo.MetadataToken; } + } + + public override Module Module + { + get { return eventInfo.Module; } + } + + public override string Name + { + get { return eventInfo.Name; } + } + + internal override bool IsBaked + { + get { return eventInfo.IsBaked; } + } + + internal override int GetCurrentToken() + { + return eventInfo.GetCurrentToken(); + } + } +} diff --git a/reflect/ExceptionHandlingClause.cs b/reflect/ExceptionHandlingClause.cs new file mode 100644 index 0000000..3553f90 --- /dev/null +++ b/reflect/ExceptionHandlingClause.cs @@ -0,0 +1,94 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using IKVM.Reflection.Reader; + +namespace IKVM.Reflection +{ + [Flags] + public enum ExceptionHandlingClauseOptions + { + Clause = 0x0000, + Filter = 0x0001, + Finally = 0x0002, + Fault = 0x0004, + } + + public sealed class ExceptionHandlingClause + { + private readonly int flags; + private readonly int tryOffset; + private readonly int tryLength; + private readonly int handlerOffset; + private readonly int handlerLength; + private readonly Type catchType; + private readonly int filterOffset; + + internal ExceptionHandlingClause(ModuleReader module, int flags, int tryOffset, int tryLength, int handlerOffset, int handlerLength, int classTokenOrfilterOffset, IGenericContext context) + { + this.flags = flags; + this.tryOffset = tryOffset; + this.tryLength = tryLength; + this.handlerOffset = handlerOffset; + this.handlerLength = handlerLength; + this.catchType = flags == (int)ExceptionHandlingClauseOptions.Clause && classTokenOrfilterOffset != 0 ? module.ResolveType(classTokenOrfilterOffset, context) : null; + this.filterOffset = flags == (int)ExceptionHandlingClauseOptions.Filter ? classTokenOrfilterOffset : 0; + } + + public Type CatchType + { + get { return catchType; } + } + + public int FilterOffset + { + get { return filterOffset; } + } + + public ExceptionHandlingClauseOptions Flags + { + get { return (ExceptionHandlingClauseOptions)flags; } + } + + public int HandlerLength + { + get { return handlerLength; } + } + + public int HandlerOffset + { + get { return handlerOffset; } + } + + public int TryLength + { + get { return tryLength; } + } + + public int TryOffset + { + get { return tryOffset; } + } + } +} diff --git a/reflect/FieldInfo.cs b/reflect/FieldInfo.cs new file mode 100644 index 0000000..92f8909 --- /dev/null +++ b/reflect/FieldInfo.cs @@ -0,0 +1,304 @@ +/* + Copyright (C) 2009-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace IKVM.Reflection +{ + public abstract class FieldInfo : MemberInfo + { + // prevent external subclasses + internal FieldInfo() + { + } + + public sealed override MemberTypes MemberType + { + get { return MemberTypes.Field; } + } + + public abstract FieldAttributes Attributes { get; } + public abstract void __GetDataFromRVA(byte[] data, int offset, int length); + public abstract int __FieldRVA { get; } + public abstract Object GetRawConstantValue(); + internal abstract FieldSignature FieldSignature { get; } + + public Type FieldType + { + get { return this.FieldSignature.FieldType; } + } + + public CustomModifiers __GetCustomModifiers() + { + return this.FieldSignature.GetCustomModifiers(); + } + + public Type[] GetOptionalCustomModifiers() + { + return __GetCustomModifiers().GetOptional(); + } + + public Type[] GetRequiredCustomModifiers() + { + return __GetCustomModifiers().GetRequired(); + } + + public bool IsStatic + { + get { return (Attributes & FieldAttributes.Static) != 0; } + } + + public bool IsLiteral + { + get { return (Attributes & FieldAttributes.Literal) != 0; } + } + + public bool IsInitOnly + { + get { return (Attributes & FieldAttributes.InitOnly) != 0; } + } + + public bool IsNotSerialized + { + get { return (Attributes & FieldAttributes.NotSerialized) != 0; } + } + + public bool IsSpecialName + { + get { return (Attributes & FieldAttributes.SpecialName) != 0; } + } + + public bool IsPublic + { + get { return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Public; } + } + + public bool IsPrivate + { + get { return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Private; } + } + + public bool IsFamily + { + get { return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Family; } + } + + public bool IsFamilyOrAssembly + { + get { return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.FamORAssem; } + } + + public bool IsAssembly + { + get { return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Assembly; } + } + + public bool IsFamilyAndAssembly + { + get { return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.FamANDAssem; } + } + + public bool IsPinvokeImpl + { + get { return (Attributes & FieldAttributes.PinvokeImpl) != 0; } + } + + public virtual FieldInfo __GetFieldOnTypeDefinition() + { + return this; + } + + public abstract bool __TryGetFieldOffset(out int offset); + + public bool __TryGetFieldMarshal(out FieldMarshal fieldMarshal) + { + return FieldMarshal.ReadFieldMarshal(this.Module, GetCurrentToken(), out fieldMarshal); + } + + internal abstract int ImportTo(Emit.ModuleBuilder module); + + internal virtual FieldInfo BindTypeParameters(Type type) + { + return new GenericFieldInstance(this.DeclaringType.BindTypeParameters(type), this); + } + + internal sealed override bool BindingFlagsMatch(BindingFlags flags) + { + return BindingFlagsMatch(IsPublic, flags, BindingFlags.Public, BindingFlags.NonPublic) + && BindingFlagsMatch(IsStatic, flags, BindingFlags.Static, BindingFlags.Instance); + } + + internal sealed override bool BindingFlagsMatchInherited(BindingFlags flags) + { + return (Attributes & FieldAttributes.FieldAccessMask) > FieldAttributes.Private + && BindingFlagsMatch(IsPublic, flags, BindingFlags.Public, BindingFlags.NonPublic) + && BindingFlagsMatch(IsStatic, flags, BindingFlags.Static | BindingFlags.FlattenHierarchy, BindingFlags.Instance); + } + + internal sealed override MemberInfo SetReflectedType(Type type) + { + return new FieldInfoWithReflectedType(type, this); + } + + internal sealed override List GetPseudoCustomAttributes(Type attributeType) + { + Module module = this.Module; + List list = new List(); + if (attributeType == null || attributeType.IsAssignableFrom(module.universe.System_Runtime_InteropServices_MarshalAsAttribute)) + { + FieldMarshal spec; + if (__TryGetFieldMarshal(out spec)) + { + list.Add(CustomAttributeData.CreateMarshalAsPseudoCustomAttribute(module, spec)); + } + } + if (attributeType == null || attributeType.IsAssignableFrom(module.universe.System_Runtime_InteropServices_FieldOffsetAttribute)) + { + int offset; + if (__TryGetFieldOffset(out offset)) + { + list.Add(CustomAttributeData.CreateFieldOffsetPseudoCustomAttribute(module, offset)); + } + } + return list; + } + } + + sealed class FieldInfoWithReflectedType : FieldInfo + { + private readonly Type reflectedType; + private readonly FieldInfo field; + + internal FieldInfoWithReflectedType(Type reflectedType, FieldInfo field) + { + Debug.Assert(reflectedType != field.DeclaringType); + this.reflectedType = reflectedType; + this.field = field; + } + + public override FieldAttributes Attributes + { + get { return field.Attributes; } + } + + public override void __GetDataFromRVA(byte[] data, int offset, int length) + { + field.__GetDataFromRVA(data, offset, length); + } + + public override int __FieldRVA + { + get { return field.__FieldRVA; } + } + + public override bool __TryGetFieldOffset(out int offset) + { + return field.__TryGetFieldOffset(out offset); + } + + public override Object GetRawConstantValue() + { + return field.GetRawConstantValue(); + } + + internal override FieldSignature FieldSignature + { + get { return field.FieldSignature; } + } + + public override FieldInfo __GetFieldOnTypeDefinition() + { + return field.__GetFieldOnTypeDefinition(); + } + + internal override int ImportTo(Emit.ModuleBuilder module) + { + return field.ImportTo(module); + } + + internal override FieldInfo BindTypeParameters(Type type) + { + return field.BindTypeParameters(type); + } + + public override bool __IsMissing + { + get { return field.__IsMissing; } + } + + public override Type DeclaringType + { + get { return field.DeclaringType; } + } + + public override Type ReflectedType + { + get { return reflectedType; } + } + + public override bool Equals(object obj) + { + FieldInfoWithReflectedType other = obj as FieldInfoWithReflectedType; + return other != null + && other.reflectedType == reflectedType + && other.field == field; + } + + public override int GetHashCode() + { + return reflectedType.GetHashCode() ^ field.GetHashCode(); + } + + public override int MetadataToken + { + get { return field.MetadataToken; } + } + + public override Module Module + { + get { return field.Module; } + } + + public override string Name + { + get { return field.Name; } + } + + public override string ToString() + { + return field.ToString(); + } + + internal override int GetCurrentToken() + { + return field.GetCurrentToken(); + } + + internal override bool IsBaked + { + get { return field.IsBaked; } + } + } +} diff --git a/reflect/FieldSignature.cs b/reflect/FieldSignature.cs new file mode 100644 index 0000000..481fc61 --- /dev/null +++ b/reflect/FieldSignature.cs @@ -0,0 +1,98 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using IKVM.Reflection.Emit; +using IKVM.Reflection.Writer; +using IKVM.Reflection.Reader; + +namespace IKVM.Reflection +{ + sealed class FieldSignature : Signature + { + private readonly Type fieldType; + private readonly CustomModifiers mods; + + internal static FieldSignature Create(Type fieldType, CustomModifiers customModifiers) + { + return new FieldSignature(fieldType, customModifiers); + } + + private FieldSignature(Type fieldType, CustomModifiers mods) + { + this.fieldType = fieldType; + this.mods = mods; + } + + public override bool Equals(object obj) + { + FieldSignature other = obj as FieldSignature; + return other != null + && other.fieldType.Equals(fieldType) + && other.mods.Equals(mods); + } + + public override int GetHashCode() + { + return fieldType.GetHashCode() ^ mods.GetHashCode(); + } + + internal Type FieldType + { + get { return fieldType; } + } + + internal CustomModifiers GetCustomModifiers() + { + return mods; + } + + internal FieldSignature ExpandTypeParameters(Type declaringType) + { + return new FieldSignature( + fieldType.BindTypeParameters(declaringType), + mods.Bind(declaringType)); + } + + internal static FieldSignature ReadSig(ModuleReader module, ByteReader br, IGenericContext context) + { + if (br.ReadByte() != FIELD) + { + throw new BadImageFormatException(); + } + CustomModifiers mods = CustomModifiers.Read(module, br, context); + Type fieldType = ReadType(module, br, context); + return new FieldSignature(fieldType, mods); + } + + internal override void WriteSig(ModuleBuilder module, ByteBuffer bb) + { + bb.Write(FIELD); + WriteCustomModifiers(module, bb, mods); + WriteType(module, bb, fieldType); + } + } +} diff --git a/reflect/Fusion.cs b/reflect/Fusion.cs new file mode 100644 index 0000000..bc08323 --- /dev/null +++ b/reflect/Fusion.cs @@ -0,0 +1,810 @@ +/* + Copyright (C) 2010-2013 Jeroen Frijters + Copyright (C) 2011 Marek Safar + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace IKVM.Reflection +{ + struct ParsedAssemblyName + { + internal string Name; + internal string Version; + internal string Culture; + internal string PublicKeyToken; + internal bool? Retargetable; + internal ProcessorArchitecture ProcessorArchitecture; + internal bool HasPublicKey; + internal bool WindowsRuntime; + } + + enum ParseAssemblyResult + { + OK, + GenericError, + DuplicateKey, + } + + static class Fusion + { + static readonly Version FrameworkVersion = new Version(4, 0, 0, 0); + static readonly Version FrameworkVersionNext = new Version(4, 1, 0, 0); + static readonly Version SilverlightVersion = new Version(2, 0, 5, 0); + static readonly Version SilverlightVersionMinimum = new Version(2, 0, 0, 0); + static readonly Version SilverlightVersionMaximum = new Version(5, 9, 0, 0); + const string PublicKeyTokenEcma = "b77a5c561934e089"; + const string PublicKeyTokenMicrosoft = "b03f5f7f11d50a3a"; + const string PublicKeyTokenSilverlight = "7cec85d7bea7798e"; + const string PublicKeyTokenWinFX = "31bf3856ad364e35"; + +#if !CORECLR + internal static bool CompareAssemblyIdentityNative(string assemblyIdentity1, bool unified1, string assemblyIdentity2, bool unified2, out AssemblyComparisonResult result) + { + bool equivalent; + Marshal.ThrowExceptionForHR(CompareAssemblyIdentity(assemblyIdentity1, unified1, assemblyIdentity2, unified2, out equivalent, out result)); + return equivalent; + } + + [DllImport("fusion", CharSet = CharSet.Unicode)] + private static extern int CompareAssemblyIdentity(string pwzAssemblyIdentity1, bool fUnified1, string pwzAssemblyIdentity2, bool fUnified2, out bool pfEquivalent, out AssemblyComparisonResult pResult); +#endif + + // internal for use by mcs + internal static bool CompareAssemblyIdentityPure(string assemblyIdentity1, bool unified1, string assemblyIdentity2, bool unified2, out AssemblyComparisonResult result) + { + ParsedAssemblyName name1; + ParsedAssemblyName name2; + + ParseAssemblyResult r1 = ParseAssemblyName(assemblyIdentity1, out name1); + ParseAssemblyResult r2 = ParseAssemblyName(assemblyIdentity2, out name2); + + Version version1; + if (unified1) + { + if (name1.Name == null || !ParseVersion(name1.Version, out version1) || version1 == null || version1.Revision == -1 + || name1.Culture == null || name1.PublicKeyToken == null || name1.PublicKeyToken.Length < 2) + { + result = AssemblyComparisonResult.NonEquivalent; + throw new ArgumentException(); + } + } + + Version version2 = null; + if (!ParseVersion(name2.Version, out version2) || version2 == null || version2.Revision == -1 + || name2.Culture == null || name2.PublicKeyToken == null || name2.PublicKeyToken.Length < 2) + { + result = AssemblyComparisonResult.NonEquivalent; + throw new ArgumentException(); + } + + if (name2.Name != null && name2.Name.Equals("mscorlib", StringComparison.OrdinalIgnoreCase)) + { + if (name1.Name != null && name1.Name.Equals(name2.Name, StringComparison.OrdinalIgnoreCase)) + { + result = AssemblyComparisonResult.EquivalentFullMatch; + return true; + } + else + { + result = AssemblyComparisonResult.NonEquivalent; + return false; + } + } + + if (r1 != ParseAssemblyResult.OK) + { + result = AssemblyComparisonResult.NonEquivalent; + switch (r1) + { + case ParseAssemblyResult.DuplicateKey: + throw new System.IO.FileLoadException(); + case ParseAssemblyResult.GenericError: + default: + throw new ArgumentException(); + } + } + + if (r2 != ParseAssemblyResult.OK) + { + result = AssemblyComparisonResult.NonEquivalent; + switch (r2) + { + case ParseAssemblyResult.DuplicateKey: + throw new System.IO.FileLoadException(); + case ParseAssemblyResult.GenericError: + default: + throw new ArgumentException(); + } + } + + if (!ParseVersion(name1.Version, out version1)) + { + result = AssemblyComparisonResult.NonEquivalent; + throw new ArgumentException(); + } + + bool partial = IsPartial(name1, version1); + + if (partial && name1.Retargetable.HasValue) + { + result = AssemblyComparisonResult.NonEquivalent; + throw new System.IO.FileLoadException(); + } + if ((partial && unified1) || IsPartial(name2, version2)) + { + result = AssemblyComparisonResult.NonEquivalent; + throw new ArgumentException(); + } + if (!name1.Name.Equals(name2.Name, StringComparison.OrdinalIgnoreCase)) + { + result = AssemblyComparisonResult.NonEquivalent; + return false; + } + if (partial && name1.Culture == null) + { + } + else if (!name1.Culture.Equals(name2.Culture, StringComparison.OrdinalIgnoreCase)) + { + result = AssemblyComparisonResult.NonEquivalent; + return false; + } + + if (!name1.Retargetable.GetValueOrDefault() && name2.Retargetable.GetValueOrDefault()) + { + result = AssemblyComparisonResult.NonEquivalent; + return false; + } + + // HACK handle the case "System.Net, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes" + // compared with "System.Net, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=No" + if (name1.PublicKeyToken == name2.PublicKeyToken + && version1 != null + && name1.Retargetable.GetValueOrDefault() + && !name2.Retargetable.GetValueOrDefault() + && GetRemappedPublicKeyToken(ref name1, version1) != null) + { + name1.Retargetable = false; + } + + string remappedPublicKeyToken1 = null; + string remappedPublicKeyToken2 = null; + if (version1 != null && (remappedPublicKeyToken1 = GetRemappedPublicKeyToken(ref name1, version1)) != null) + { + name1.PublicKeyToken = remappedPublicKeyToken1; + version1 = FrameworkVersion; + } + if ((remappedPublicKeyToken2 = GetRemappedPublicKeyToken(ref name2, version2)) != null) + { + name2.PublicKeyToken = remappedPublicKeyToken2; + version2 = FrameworkVersion; + } + if (name1.Retargetable.GetValueOrDefault()) + { + if (name2.Retargetable.GetValueOrDefault()) + { + if (remappedPublicKeyToken1 != null ^ remappedPublicKeyToken2 != null) + { + result = AssemblyComparisonResult.NonEquivalent; + return false; + } + } + else if (remappedPublicKeyToken1 == null || remappedPublicKeyToken2 != null) + { + result = AssemblyComparisonResult.Unknown; + return false; + } + } + + bool fxUnified = false; + bool versionMatch = version1 == version2; + if (IsFrameworkAssembly(name1)) + { + fxUnified |= !versionMatch; + version1 = FrameworkVersion; + } + if (IsFrameworkAssembly(name2) && version2 < FrameworkVersionNext) + { + fxUnified |= !versionMatch; + version2 = FrameworkVersion; + } + + if (IsStrongNamed(name2)) + { + if (name1.PublicKeyToken != null && name1.PublicKeyToken != name2.PublicKeyToken) + { + result = AssemblyComparisonResult.NonEquivalent; + return false; + } + else if (version1 == null) + { + result = AssemblyComparisonResult.EquivalentPartialMatch; + return true; + } + else if (version1.Revision == -1 || version2.Revision == -1) + { + result = AssemblyComparisonResult.NonEquivalent; + throw new ArgumentException(); + } + else if (version1 < version2) + { + if (unified2) + { + result = partial ? AssemblyComparisonResult.EquivalentPartialUnified : AssemblyComparisonResult.EquivalentUnified; + return true; + } + else + { + result = partial ? AssemblyComparisonResult.NonEquivalentPartialVersion : AssemblyComparisonResult.NonEquivalentVersion; + return false; + } + } + else if (version1 > version2) + { + if (unified1) + { + result = partial ? AssemblyComparisonResult.EquivalentPartialUnified : AssemblyComparisonResult.EquivalentUnified; + return true; + } + else + { + result = partial ? AssemblyComparisonResult.NonEquivalentPartialVersion : AssemblyComparisonResult.NonEquivalentVersion; + return false; + } + } + else if (!versionMatch || fxUnified) + { + result = partial ? AssemblyComparisonResult.EquivalentPartialFXUnified : AssemblyComparisonResult.EquivalentFXUnified; + return true; + } + else + { + result = partial ? AssemblyComparisonResult.EquivalentPartialMatch : AssemblyComparisonResult.EquivalentFullMatch; + return true; + } + } + else if (IsStrongNamed(name1)) + { + result = AssemblyComparisonResult.NonEquivalent; + return false; + } + else + { + result = partial ? AssemblyComparisonResult.EquivalentPartialWeakNamed : AssemblyComparisonResult.EquivalentWeakNamed; + return true; + } + } + + static bool IsFrameworkAssembly(ParsedAssemblyName name) + { + // Framework assemblies use different unification rules, so when + // a new framework is released the new assemblies need to be added. + switch (name.Name) + { + case "System": + case "System.Core": + case "System.Data": + case "System.Data.DataSetExtensions": + case "System.Data.Linq": + case "System.Data.OracleClient": + case "System.Data.Services": + case "System.Data.Services.Client": + case "System.IdentityModel": + case "System.IdentityModel.Selectors": + case "System.IO.Compression": + case "System.Numerics": + case "System.Reflection.Context": + case "System.Runtime.Remoting": + case "System.Runtime.Serialization": + case "System.Runtime.WindowsRuntime": + case "System.Runtime.WindowsRuntime.UI.Xaml": + case "System.ServiceModel": + case "System.Transactions": + case "System.Windows.Forms": + case "System.Xml": + case "System.Xml.Linq": + case "System.Xml.Serialization": + return name.PublicKeyToken == PublicKeyTokenEcma; + + case "Microsoft.CSharp": + case "Microsoft.VisualBasic": + case "System.Collections": + case "System.Collections.Concurrent": + case "System.ComponentModel": + case "System.ComponentModel.Annotations": + case "System.ComponentModel.EventBasedAsync": + case "System.Configuration": + case "System.Configuration.Install": + case "System.Design": + case "System.Diagnostics.Contracts": + case "System.Diagnostics.Debug": + case "System.Diagnostics.Tools": + case "System.Diagnostics.Tracing": + case "System.DirectoryServices": + case "System.Drawing": + case "System.Drawing.Design": + case "System.Dynamic.Runtime": + case "System.EnterpriseServices": + case "System.Globalization": + case "System.IO": + case "System.Linq": + case "System.Linq.Expressions": + case "System.Linq.Parallel": + case "System.Linq.Queryable": + case "System.Management": + case "System.Messaging": + case "System.Net": + case "System.Net.Http": + case "System.Net.Http.Rtc": + case "System.Net.NetworkInformation": + case "System.Net.Primitives": + case "System.Net.Requests": + case "System.ObjectModel": + case "System.Reflection": + case "System.Reflection.Extensions": + case "System.Reflection.Primitives": + case "System.Resources.ResourceManager": + case "System.Runtime": + case "System.Runtime.Extensions": + case "System.Runtime.InteropServices": + case "System.Runtime.InteropServices.WindowsRuntime": + case "System.Runtime.Numerics": + case "System.Runtime.Serialization.Formatters.Soap": + case "System.Runtime.Serialization.Json": + case "System.Runtime.Serialization.Primitives": + case "System.Runtime.Serialization.Xml": + case "System.Security": + case "System.Security.Principal": + case "System.ServiceModel.Duplex": + case "System.ServiceModel.Http": + case "System.ServiceModel.NetTcp": + case "System.ServiceModel.Primitives": + case "System.ServiceModel.Security": + case "System.ServiceProcess": + case "System.Text.Encoding": + case "System.Text.Encoding.Extensions": + case "System.Text.RegularExpressions": + case "System.Threading": + case "System.Threading.Tasks": + case "System.Threading.Tasks.Parallel": + case "System.Web": + case "System.Web.Mobile": + case "System.Web.Services": + case "System.Windows": + case "System.Xml.ReaderWriter": + case "System.Xml.XDocument": + case "System.Xml.XmlSerializer": + return name.PublicKeyToken == PublicKeyTokenMicrosoft; + + case "System.ComponentModel.DataAnnotations": + case "System.ServiceModel.Web": + case "System.Web.Abstractions": + case "System.Web.Extensions": + case "System.Web.Extensions.Design": + case "System.Web.DynamicData": + case "System.Web.Routing": + return name.PublicKeyToken == PublicKeyTokenWinFX; + } + + return false; + } + + static string GetRemappedPublicKeyToken(ref ParsedAssemblyName name, Version version) + { + if (name.Retargetable.GetValueOrDefault() && version < SilverlightVersion) + { + return null; + } + if (name.PublicKeyToken == "ddd0da4d3e678217" && name.Name == "System.ComponentModel.DataAnnotations" && name.Retargetable.GetValueOrDefault()) + { + return PublicKeyTokenWinFX; + } + if (SilverlightVersionMinimum <= version && version <= SilverlightVersionMaximum) + { + switch (name.PublicKeyToken) + { + case PublicKeyTokenSilverlight: + switch (name.Name) + { + case "System": + case "System.Core": + return PublicKeyTokenEcma; + } + if (name.Retargetable.GetValueOrDefault()) + { + switch (name.Name) + { + case "System.Runtime.Serialization": + case "System.Xml": + return PublicKeyTokenEcma; + case "System.Net": + case "System.Windows": + return PublicKeyTokenMicrosoft; + case "System.ServiceModel.Web": + return PublicKeyTokenWinFX; + } + } + break; + case PublicKeyTokenWinFX: + switch (name.Name) + { + case "System.ComponentModel.Composition": + return PublicKeyTokenEcma; + } + if (name.Retargetable.GetValueOrDefault()) + { + switch (name.Name) + { + case "Microsoft.CSharp": + return PublicKeyTokenMicrosoft; + case "System.Numerics": + case "System.ServiceModel": + case "System.Xml.Serialization": + case "System.Xml.Linq": + return PublicKeyTokenEcma; + } + } + break; + } + } + return null; + } + + internal static ParseAssemblyResult ParseAssemblySimpleName(string fullName, out int pos, out string simpleName) + { + pos = 0; + if (!TryParse(fullName, ref pos, out simpleName) || simpleName.Length == 0) + { + return ParseAssemblyResult.GenericError; + } + if (pos == fullName.Length && fullName[fullName.Length - 1] == ',') + { + return ParseAssemblyResult.GenericError; + } + return ParseAssemblyResult.OK; + } + + private static bool TryParse(string fullName, ref int pos, out string value) + { + value = null; + StringBuilder sb = new StringBuilder(); + while (pos < fullName.Length && char.IsWhiteSpace(fullName[pos])) + { + pos++; + } + int quote = -1; + if (pos < fullName.Length && (fullName[pos] == '"' || fullName[pos] == '\'')) + { + quote = fullName[pos++]; + } + for (; pos < fullName.Length; pos++) + { + char ch = fullName[pos]; + if (ch == '\\') + { + if (++pos == fullName.Length) + { + return false; + } + ch = fullName[pos]; + if (ch == '\\') + { + return false; + } + } + else if (ch == quote) + { + for (pos++; pos != fullName.Length; pos++) + { + ch = fullName[pos]; + if (ch == ',' || ch == '=') + { + break; + } + if (!char.IsWhiteSpace(ch)) + { + return false; + } + } + break; + } + else if (quote == -1 && (ch == '"' || ch == '\'')) + { + return false; + } + else if (quote == -1 && (ch == ',' || ch == '=')) + { + break; + } + sb.Append(ch); + } + value = sb.ToString().Trim(); + return value.Length != 0 || quote != -1; + } + + private static bool TryConsume(string fullName, char ch, ref int pos) + { + if (pos < fullName.Length && fullName[pos] == ch) + { + pos++; + return true; + } + return false; + } + + private static bool TryParseAssemblyAttribute(string fullName, ref int pos, ref string key, ref string value) + { + return TryConsume(fullName, ',', ref pos) + && TryParse(fullName, ref pos, out key) + && TryConsume(fullName, '=', ref pos) + && TryParse(fullName, ref pos, out value); + } + + internal static ParseAssemblyResult ParseAssemblyName(string fullName, out ParsedAssemblyName parsedName) + { + parsedName = new ParsedAssemblyName(); + int pos; + ParseAssemblyResult res = ParseAssemblySimpleName(fullName, out pos, out parsedName.Name); + if (res != ParseAssemblyResult.OK) + { + return res; + } + else + { + const int ERROR_SXS_IDENTITIES_DIFFERENT = unchecked((int)0x80073716); + System.Collections.Generic.Dictionary unknownAttributes = null; + bool hasProcessorArchitecture = false; + bool hasContentType = false; + bool hasPublicKeyToken = false; + string publicKeyToken; + while (pos != fullName.Length) + { + string key = null; + string value = null; + if (!TryParseAssemblyAttribute(fullName, ref pos, ref key, ref value)) + { + return ParseAssemblyResult.GenericError; + } + key = key.ToLowerInvariant(); + switch (key) + { + case "version": + if (parsedName.Version != null) + { + return ParseAssemblyResult.DuplicateKey; + } + parsedName.Version = value; + break; + case "culture": + if (parsedName.Culture != null) + { + return ParseAssemblyResult.DuplicateKey; + } + if (!ParseCulture(value, out parsedName.Culture)) + { + return ParseAssemblyResult.GenericError; + } + break; + case "publickeytoken": + if (hasPublicKeyToken) + { + return ParseAssemblyResult.DuplicateKey; + } + if (!ParsePublicKeyToken(value, out publicKeyToken)) + { + return ParseAssemblyResult.GenericError; + } + if (parsedName.HasPublicKey && parsedName.PublicKeyToken != publicKeyToken) + { + Marshal.ThrowExceptionForHR(ERROR_SXS_IDENTITIES_DIFFERENT); + } + parsedName.PublicKeyToken = publicKeyToken; + hasPublicKeyToken = true; + break; + case "publickey": + if (parsedName.HasPublicKey) + { + return ParseAssemblyResult.DuplicateKey; + } + if (!ParsePublicKey(value, out publicKeyToken)) + { + return ParseAssemblyResult.GenericError; + } + if (hasPublicKeyToken && parsedName.PublicKeyToken != publicKeyToken) + { + Marshal.ThrowExceptionForHR(ERROR_SXS_IDENTITIES_DIFFERENT); + } + parsedName.PublicKeyToken = publicKeyToken; + parsedName.HasPublicKey = true; + break; + case "retargetable": + if (parsedName.Retargetable.HasValue) + { + return ParseAssemblyResult.DuplicateKey; + } + switch (value.ToLowerInvariant()) + { + case "yes": + parsedName.Retargetable = true; + break; + case "no": + parsedName.Retargetable = false; + break; + default: + return ParseAssemblyResult.GenericError; + } + break; + case "processorarchitecture": + if (hasProcessorArchitecture) + { + return ParseAssemblyResult.DuplicateKey; + } + hasProcessorArchitecture = true; + switch (value.ToLowerInvariant()) + { + case "none": + parsedName.ProcessorArchitecture = ProcessorArchitecture.None; + break; + case "msil": + parsedName.ProcessorArchitecture = ProcessorArchitecture.MSIL; + break; + case "x86": + parsedName.ProcessorArchitecture = ProcessorArchitecture.X86; + break; + case "ia64": + parsedName.ProcessorArchitecture = ProcessorArchitecture.IA64; + break; + case "amd64": + parsedName.ProcessorArchitecture = ProcessorArchitecture.Amd64; + break; + case "arm": + parsedName.ProcessorArchitecture = ProcessorArchitecture.Arm; + break; + default: + return ParseAssemblyResult.GenericError; + } + break; + case "contenttype": + if (hasContentType) + { + return ParseAssemblyResult.DuplicateKey; + } + hasContentType = true; + if (!value.Equals("windowsruntime", StringComparison.OrdinalIgnoreCase)) + { + return ParseAssemblyResult.GenericError; + } + parsedName.WindowsRuntime = true; + break; + default: + if (key.Length == 0) + { + return ParseAssemblyResult.GenericError; + } + if (unknownAttributes == null) + { + unknownAttributes = new System.Collections.Generic.Dictionary(); + } + if (unknownAttributes.ContainsKey(key)) + { + return ParseAssemblyResult.DuplicateKey; + } + unknownAttributes.Add(key, null); + break; + } + } + return ParseAssemblyResult.OK; + } + } + + private static bool ParseVersion(string str, out Version version) + { + if (str == null) + { + version = null; + return true; + } + string[] parts = str.Split('.'); + if (parts.Length < 2 || parts.Length > 4) + { + version = null; + ushort dummy; + // if the version consists of a single integer, it is invalid, but not invalid enough to fail the parse of the whole assembly name + return parts.Length == 1 && ushort.TryParse(parts[0], System.Globalization.NumberStyles.Integer, null, out dummy); + } + if (parts[0] == "" || parts[1] == "") + { + // this is a strange scenario, the version is invalid, but not invalid enough to fail the parse of the whole assembly name + version = null; + return true; + } + ushort major, minor, build = 65535, revision = 65535; + if (ushort.TryParse(parts[0], System.Globalization.NumberStyles.Integer, null, out major) + && ushort.TryParse(parts[1], System.Globalization.NumberStyles.Integer, null, out minor) + && (parts.Length <= 2 || parts[2] == "" || ushort.TryParse(parts[2], System.Globalization.NumberStyles.Integer, null, out build)) + && (parts.Length <= 3 || parts[3] == "" || (parts[2] != "" && ushort.TryParse(parts[3], System.Globalization.NumberStyles.Integer, null, out revision)))) + { + if (parts.Length == 4 && parts[3] != "" && parts[2] != "") + { + version = new Version(major, minor, build, revision); + } + else if (parts.Length == 3 && parts[2] != "") + { + version = new Version(major, minor, build); + } + else + { + version = new Version(major, minor); + } + return true; + } + version = null; + return false; + } + + private static bool ParseCulture(string str, out string culture) + { + if (str == null) + { + culture = null; + return false; + } + culture = str; + return true; + } + + private static bool ParsePublicKeyToken(string str, out string publicKeyToken) + { + if (str == null) + { + publicKeyToken = null; + return false; + } + publicKeyToken = str.ToLowerInvariant(); + return true; + } + + private static bool ParsePublicKey(string str, out string publicKeyToken) + { + if (str == null) + { + publicKeyToken = null; + return false; + } + publicKeyToken = AssemblyName.ComputePublicKeyToken(str); + return true; + } + + private static bool IsPartial(ParsedAssemblyName name, Version version) + { + return version == null || name.Culture == null || name.PublicKeyToken == null; + } + + private static bool IsStrongNamed(ParsedAssemblyName name) + { + return name.PublicKeyToken != null && name.PublicKeyToken != "null"; + } + } +} diff --git a/reflect/GenericWrappers.cs b/reflect/GenericWrappers.cs new file mode 100644 index 0000000..1122ff2 --- /dev/null +++ b/reflect/GenericWrappers.cs @@ -0,0 +1,694 @@ +/* + Copyright (C) 2009, 2010 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; + +namespace IKVM.Reflection +{ + // this represents both generic method instantiations and non-generic methods on generic type instantations + // (this means that it can be a generic method declaration as well as a generic method instance) + sealed class GenericMethodInstance : MethodInfo + { + private readonly Type declaringType; + private readonly MethodInfo method; + private readonly Type[] methodArgs; + private MethodSignature lazyMethodSignature; + + internal GenericMethodInstance(Type declaringType, MethodInfo method, Type[] methodArgs) + { + System.Diagnostics.Debug.Assert(!(method is GenericMethodInstance)); + this.declaringType = declaringType; + this.method = method; + this.methodArgs = methodArgs; + } + + public override bool Equals(object obj) + { + GenericMethodInstance other = obj as GenericMethodInstance; + return other != null + && other.method.Equals(method) + && other.declaringType.Equals(declaringType) + && Util.ArrayEquals(other.methodArgs, methodArgs); + } + + public override int GetHashCode() + { + return declaringType.GetHashCode() * 33 ^ method.GetHashCode() ^ Util.GetHashCode(methodArgs); + } + + public override Type ReturnType + { + get { return method.ReturnType.BindTypeParameters(this); } + } + + public override ParameterInfo ReturnParameter + { + get { return new GenericParameterInfoImpl(this, method.ReturnParameter); } + } + + public override ParameterInfo[] GetParameters() + { + ParameterInfo[] parameters = method.GetParameters(); + for (int i = 0; i < parameters.Length; i++) + { + parameters[i] = new GenericParameterInfoImpl(this, parameters[i]); + } + return parameters; + } + + internal override int ParameterCount + { + get { return method.ParameterCount; } + } + + public override CallingConventions CallingConvention + { + get { return method.CallingConvention; } + } + + public override MethodAttributes Attributes + { + get { return method.Attributes; } + } + + public override MethodImplAttributes GetMethodImplementationFlags() + { + return method.GetMethodImplementationFlags(); + } + + public override string Name + { + get { return method.Name; } + } + + public override Type DeclaringType + { + get { return declaringType.IsModulePseudoType ? null : declaringType; } + } + + public override Module Module + { + get { return method.Module; } + } + + public override int MetadataToken + { + get { return method.MetadataToken; } + } + + public override MethodBody GetMethodBody() + { + IKVM.Reflection.Reader.MethodDefImpl md = method as IKVM.Reflection.Reader.MethodDefImpl; + if (md != null) + { + return md.GetMethodBody(this); + } + throw new NotSupportedException(); + } + + public override int __MethodRVA + { + get { return method.__MethodRVA; } + } + + public override MethodInfo MakeGenericMethod(params Type[] typeArguments) + { + return new GenericMethodInstance(declaringType, method, typeArguments); + } + + public override bool IsGenericMethod + { + get { return method.IsGenericMethod; } + } + + public override bool IsGenericMethodDefinition + { + get { return method.IsGenericMethodDefinition && methodArgs == null; } + } + + public override bool ContainsGenericParameters + { + get + { + if (declaringType.ContainsGenericParameters) + { + return true; + } + if (methodArgs != null) + { + foreach (Type type in methodArgs) + { + if (type.ContainsGenericParameters) + { + return true; + } + } + } + return false; + } + } + + public override MethodInfo GetGenericMethodDefinition() + { + if (this.IsGenericMethod) + { + if (this.IsGenericMethodDefinition) + { + return this; + } + else if (declaringType.IsConstructedGenericType) + { + return new GenericMethodInstance(declaringType, method, null); + } + else + { + return method; + } + } + throw new InvalidOperationException(); + } + + public override MethodBase __GetMethodOnTypeDefinition() + { + return method; + } + + public override Type[] GetGenericArguments() + { + if (methodArgs == null) + { + return method.GetGenericArguments(); + } + else + { + return (Type[])methodArgs.Clone(); + } + } + + internal override Type GetGenericMethodArgument(int index) + { + if (methodArgs == null) + { + return method.GetGenericMethodArgument(index); + } + else + { + return methodArgs[index]; + } + } + + internal override int GetGenericMethodArgumentCount() + { + return method.GetGenericMethodArgumentCount(); + } + + internal override MethodInfo GetMethodOnTypeDefinition() + { + return method.GetMethodOnTypeDefinition(); + } + + internal override int ImportTo(Emit.ModuleBuilder module) + { + if (methodArgs == null) + { + return module.ImportMethodOrField(declaringType, method.Name, method.MethodSignature); + } + else + { + return module.ImportMethodSpec(declaringType, method, methodArgs); + } + } + + internal override MethodSignature MethodSignature + { + get { return lazyMethodSignature ?? (lazyMethodSignature = method.MethodSignature.Bind(declaringType, methodArgs)); } + } + + internal override MethodBase BindTypeParameters(Type type) + { + System.Diagnostics.Debug.Assert(methodArgs == null); + return new GenericMethodInstance(declaringType.BindTypeParameters(type), method, null); + } + + internal override bool HasThis + { + get { return method.HasThis; } + } + + public override MethodInfo[] __GetMethodImpls() + { + MethodInfo[] methods = method.__GetMethodImpls(); + for (int i = 0; i < methods.Length; i++) + { + methods[i] = (MethodInfo)methods[i].BindTypeParameters(declaringType); + } + return methods; + } + + internal override int GetCurrentToken() + { + return method.GetCurrentToken(); + } + + internal override bool IsBaked + { + get { return method.IsBaked; } + } + } + + sealed class GenericFieldInstance : FieldInfo + { + private readonly Type declaringType; + private readonly FieldInfo field; + + internal GenericFieldInstance(Type declaringType, FieldInfo field) + { + this.declaringType = declaringType; + this.field = field; + } + + public override bool Equals(object obj) + { + GenericFieldInstance other = obj as GenericFieldInstance; + return other != null && other.declaringType.Equals(declaringType) && other.field.Equals(field); + } + + public override int GetHashCode() + { + return declaringType.GetHashCode() * 3 ^ field.GetHashCode(); + } + + public override FieldAttributes Attributes + { + get { return field.Attributes; } + } + + public override string Name + { + get { return field.Name; } + } + + public override Type DeclaringType + { + get { return declaringType; } + } + + public override Module Module + { + get { return declaringType.Module; } + } + + public override int MetadataToken + { + get { return field.MetadataToken; } + } + + public override object GetRawConstantValue() + { + return field.GetRawConstantValue(); + } + + public override void __GetDataFromRVA(byte[] data, int offset, int length) + { + field.__GetDataFromRVA(data, offset, length); + } + + public override int __FieldRVA + { + get { return field.__FieldRVA; } + } + + public override bool __TryGetFieldOffset(out int offset) + { + return field.__TryGetFieldOffset(out offset); + } + + public override FieldInfo __GetFieldOnTypeDefinition() + { + return field; + } + + internal override FieldSignature FieldSignature + { + get { return field.FieldSignature.ExpandTypeParameters(declaringType); } + } + + internal override int ImportTo(Emit.ModuleBuilder module) + { + return module.ImportMethodOrField(declaringType, field.Name, field.FieldSignature); + } + + internal override FieldInfo BindTypeParameters(Type type) + { + return new GenericFieldInstance(declaringType.BindTypeParameters(type), field); + } + + internal override int GetCurrentToken() + { + return field.GetCurrentToken(); + } + + internal override bool IsBaked + { + get { return field.IsBaked; } + } + } + + sealed class GenericParameterInfoImpl : ParameterInfo + { + private readonly GenericMethodInstance method; + private readonly ParameterInfo parameterInfo; + + internal GenericParameterInfoImpl(GenericMethodInstance method, ParameterInfo parameterInfo) + { + this.method = method; + this.parameterInfo = parameterInfo; + } + + public override string Name + { + get { return parameterInfo.Name; } + } + + public override Type ParameterType + { + get { return parameterInfo.ParameterType.BindTypeParameters(method); } + } + + public override ParameterAttributes Attributes + { + get { return parameterInfo.Attributes; } + } + + public override int Position + { + get { return parameterInfo.Position; } + } + + public override object RawDefaultValue + { + get { return parameterInfo.RawDefaultValue; } + } + + public override CustomModifiers __GetCustomModifiers() + { + return parameterInfo.__GetCustomModifiers().Bind(method); + } + + public override bool __TryGetFieldMarshal(out FieldMarshal fieldMarshal) + { + return parameterInfo.__TryGetFieldMarshal(out fieldMarshal); + } + + public override MemberInfo Member + { + get { return method; } + } + + public override int MetadataToken + { + get { return parameterInfo.MetadataToken; } + } + + internal override Module Module + { + get { return method.Module; } + } + } + + sealed class GenericPropertyInfo : PropertyInfo + { + private readonly Type typeInstance; + private readonly PropertyInfo property; + + internal GenericPropertyInfo(Type typeInstance, PropertyInfo property) + { + this.typeInstance = typeInstance; + this.property = property; + } + + public override bool Equals(object obj) + { + GenericPropertyInfo other = obj as GenericPropertyInfo; + return other != null && other.typeInstance == typeInstance && other.property == property; + } + + public override int GetHashCode() + { + return typeInstance.GetHashCode() * 537 + property.GetHashCode(); + } + + public override PropertyAttributes Attributes + { + get { return property.Attributes; } + } + + public override bool CanRead + { + get { return property.CanRead; } + } + + public override bool CanWrite + { + get { return property.CanWrite; } + } + + private MethodInfo Wrap(MethodInfo method) + { + if (method == null) + { + return null; + } + return new GenericMethodInstance(typeInstance, method, null); + } + + public override MethodInfo GetGetMethod(bool nonPublic) + { + return Wrap(property.GetGetMethod(nonPublic)); + } + + public override MethodInfo GetSetMethod(bool nonPublic) + { + return Wrap(property.GetSetMethod(nonPublic)); + } + + public override MethodInfo[] GetAccessors(bool nonPublic) + { + MethodInfo[] accessors = property.GetAccessors(nonPublic); + for (int i = 0; i < accessors.Length; i++) + { + accessors[i] = Wrap(accessors[i]); + } + return accessors; + } + + public override object GetRawConstantValue() + { + return property.GetRawConstantValue(); + } + + internal override bool IsPublic + { + get { return property.IsPublic; } + } + + internal override bool IsNonPrivate + { + get { return property.IsNonPrivate; } + } + + internal override bool IsStatic + { + get { return property.IsStatic; } + } + + internal override PropertySignature PropertySignature + { + get { return property.PropertySignature.ExpandTypeParameters(typeInstance); } + } + + public override string Name + { + get { return property.Name; } + } + + public override Type DeclaringType + { + get { return typeInstance; } + } + + public override Module Module + { + get { return typeInstance.Module; } + } + + public override int MetadataToken + { + get { return property.MetadataToken; } + } + + internal override PropertyInfo BindTypeParameters(Type type) + { + return new GenericPropertyInfo(typeInstance.BindTypeParameters(type), property); + } + + internal override bool IsBaked + { + get { return property.IsBaked; } + } + + internal override int GetCurrentToken() + { + return property.GetCurrentToken(); + } + } + + sealed class GenericEventInfo : EventInfo + { + private readonly Type typeInstance; + private readonly EventInfo eventInfo; + + internal GenericEventInfo(Type typeInstance, EventInfo eventInfo) + { + this.typeInstance = typeInstance; + this.eventInfo = eventInfo; + } + + public override bool Equals(object obj) + { + GenericEventInfo other = obj as GenericEventInfo; + return other != null && other.typeInstance == typeInstance && other.eventInfo == eventInfo; + } + + public override int GetHashCode() + { + return typeInstance.GetHashCode() * 777 + eventInfo.GetHashCode(); + } + + public override EventAttributes Attributes + { + get { return eventInfo.Attributes; } + } + + private MethodInfo Wrap(MethodInfo method) + { + if (method == null) + { + return null; + } + return new GenericMethodInstance(typeInstance, method, null); + } + + public override MethodInfo GetAddMethod(bool nonPublic) + { + return Wrap(eventInfo.GetAddMethod(nonPublic)); + } + + public override MethodInfo GetRaiseMethod(bool nonPublic) + { + return Wrap(eventInfo.GetRaiseMethod(nonPublic)); + } + + public override MethodInfo GetRemoveMethod(bool nonPublic) + { + return Wrap(eventInfo.GetRemoveMethod(nonPublic)); + } + + public override MethodInfo[] GetOtherMethods(bool nonPublic) + { + MethodInfo[] others = eventInfo.GetOtherMethods(nonPublic); + for (int i = 0; i < others.Length; i++) + { + others[i] = Wrap(others[i]); + } + return others; + } + + public override MethodInfo[] __GetMethods() + { + MethodInfo[] others = eventInfo.__GetMethods(); + for (int i = 0; i < others.Length; i++) + { + others[i] = Wrap(others[i]); + } + return others; + } + + public override Type EventHandlerType + { + get { return eventInfo.EventHandlerType.BindTypeParameters(typeInstance); } + } + + public override string Name + { + get { return eventInfo.Name; } + } + + public override Type DeclaringType + { + get { return typeInstance; } + } + + public override Module Module + { + get { return eventInfo.Module; } + } + + public override int MetadataToken + { + get { return eventInfo.MetadataToken; } + } + + internal override EventInfo BindTypeParameters(Type type) + { + return new GenericEventInfo(typeInstance.BindTypeParameters(type), eventInfo); + } + + internal override bool IsPublic + { + get { return eventInfo.IsPublic; } + } + + internal override bool IsNonPrivate + { + get { return eventInfo.IsNonPrivate; } + } + + internal override bool IsStatic + { + get { return eventInfo.IsStatic; } + } + + internal override bool IsBaked + { + get { return eventInfo.IsBaked; } + } + + internal override int GetCurrentToken() + { + return eventInfo.GetCurrentToken(); + } + } +} diff --git a/reflect/IKVM.Reflection.csproj b/reflect/IKVM.Reflection.csproj new file mode 100644 index 0000000..7081a19 --- /dev/null +++ b/reflect/IKVM.Reflection.csproj @@ -0,0 +1,148 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {4CB170EF-DFE6-4A56-9E1B-A85449E827A7} + Library + Properties + IKVM.Reflection + IKVM.Reflection + v2.0 + 512 + + + + + + + + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/reflect/Impl/ITypeOwner.cs b/reflect/Impl/ITypeOwner.cs new file mode 100644 index 0000000..10050f7 --- /dev/null +++ b/reflect/Impl/ITypeOwner.cs @@ -0,0 +1,32 @@ +/* + Copyright (C) 2008 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using IKVM.Reflection.Emit; + +namespace IKVM.Reflection.Impl +{ + interface ITypeOwner + { + ModuleBuilder ModuleBuilder { get; } + } +} diff --git a/reflect/Impl/MdbWriter.cs b/reflect/Impl/MdbWriter.cs new file mode 100644 index 0000000..4d1e2cd --- /dev/null +++ b/reflect/Impl/MdbWriter.cs @@ -0,0 +1,238 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +#if MONO +using System; +using System.Collections.Generic; +using Mono.CompilerServices.SymbolWriter; +using IKVM.Reflection.Emit; + +namespace IKVM.Reflection.Impl +{ + sealed class Method : IMethodDef + { + internal int token; + internal string name; + internal SymbolDocumentWriter document; + internal int[] offsets; + internal int[] lines; + internal int[] columns; + internal List variables = new List(); + + public string Name + { + get { return name; } + } + + public int Token + { + get { return token; } + } + } + + sealed class SymbolDocumentWriter : System.Diagnostics.SymbolStore.ISymbolDocumentWriter + { + internal readonly string url; + internal SourceFileEntry source; + + internal SymbolDocumentWriter(string url) + { + this.url = url; + } + + public void SetCheckSum(Guid algorithmId, byte[] checkSum) + { + } + + public void SetSource(byte[] source) + { + } + } + + sealed class MdbWriter : ISymbolWriterImpl + { + private readonly ModuleBuilder moduleBuilder; + private readonly Dictionary methods = new Dictionary(); + private readonly Dictionary documents = new Dictionary(); + private Method currentMethod; + + internal MdbWriter(ModuleBuilder moduleBuilder) + { + this.moduleBuilder = moduleBuilder; + } + + public byte[] GetDebugInfo(ref IMAGE_DEBUG_DIRECTORY idd) + { + return Empty.Array; + } + + public void RemapToken(int oldToken, int newToken) + { + if (methods.ContainsKey(oldToken)) + { + methods[oldToken].token = newToken; + } + } + + public void Close() + { + MonoSymbolWriter writer = new MonoSymbolWriter(moduleBuilder.FullyQualifiedName); + + foreach (Method method in methods.Values) + { + if (method.document != null) + { + if (method.document.source == null) + { + method.document.source = new SourceFileEntry(writer.SymbolFile, method.document.url); + } + ICompileUnit file = new CompileUnitEntry(writer.SymbolFile, method.document.source); + SourceMethodBuilder smb = writer.OpenMethod(file, 0, method); + for (int i = 0; i < method.offsets.Length; i++) + { + smb.MarkSequencePoint(method.offsets[i], method.document.source, method.lines[i], method.columns[i], false); + } + for (int i = 0; i < method.variables.Count; i++) + { + writer.DefineLocalVariable(i, method.variables[i]); + } + writer.CloseMethod(); + } + } + + writer.WriteSymbolFile(moduleBuilder.ModuleVersionId); + } + + public System.Diagnostics.SymbolStore.ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType) + { + SymbolDocumentWriter writer; + if (!documents.TryGetValue(url, out writer)) + { + writer = new SymbolDocumentWriter(url); + documents.Add(url, writer); + } + return writer; + } + + public void OpenMethod(System.Diagnostics.SymbolStore.SymbolToken method) + { + throw new NotImplementedException(); + } + + public void OpenMethod(System.Diagnostics.SymbolStore.SymbolToken token, MethodBase mb) + { + Method method = new Method(); + method.token = token.GetToken(); + method.name = mb.Name; + methods.Add(token.GetToken(), method); + currentMethod = method; + } + + public void CloseMethod() + { + currentMethod = null; + } + + public void DefineLocalVariable(string name, System.Reflection.FieldAttributes attributes, byte[] signature, System.Diagnostics.SymbolStore.SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset) + { + } + + public void DefineLocalVariable2(string name, FieldAttributes attributes, int signature, System.Diagnostics.SymbolStore.SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset) + { + currentMethod.variables.Add(name); + } + + public void DefineSequencePoints(System.Diagnostics.SymbolStore.ISymbolDocumentWriter document, int[] offsets, int[] lines, int[] columns, int[] endLines, int[] endColumns) + { + currentMethod.document = (SymbolDocumentWriter)document; + currentMethod.offsets = offsets; + currentMethod.lines = lines; + currentMethod.columns = columns; + } + + public void DefineParameter(string name, System.Reflection.ParameterAttributes attributes, int sequence, System.Diagnostics.SymbolStore.SymAddressKind addrKind, int addr1, int addr2, int addr3) + { + } + + public void DefineField(System.Diagnostics.SymbolStore.SymbolToken parent, string name, System.Reflection.FieldAttributes attributes, byte[] signature, System.Diagnostics.SymbolStore.SymAddressKind addrKind, int addr1, int addr2, int addr3) + { + } + + public void DefineGlobalVariable(string name, System.Reflection.FieldAttributes attributes, byte[] signature, System.Diagnostics.SymbolStore.SymAddressKind addrKind, int addr1, int addr2, int addr3) + { + } + + public void OpenNamespace(string name) + { + } + + public void CloseNamespace() + { + } + + public void UsingNamespace(string fullName) + { + } + + public int OpenScope(int startOffset) + { + return 0; + } + + public void CloseScope(int endOffset) + { + } + + public void SetMethodSourceRange(System.Diagnostics.SymbolStore.ISymbolDocumentWriter startDoc, int startLine, int startColumn, System.Diagnostics.SymbolStore.ISymbolDocumentWriter endDoc, int endLine, int endColumn) + { + } + + public void SetScopeRange(int scopeID, int startOffset, int endOffset) + { + } + + public void SetSymAttribute(System.Diagnostics.SymbolStore.SymbolToken parent, string name, byte[] data) + { + } + + public void SetUserEntryPoint(System.Diagnostics.SymbolStore.SymbolToken entryMethod) + { + } + + public void SetUnderlyingWriter(IntPtr underlyingWriter) + { + throw new InvalidOperationException(); + } + + public void Initialize(IntPtr emitter, string filename, bool fFullBuild) + { + throw new InvalidOperationException(); + } + + public bool IsDeterministic + { + get { return true; } + } + } +} +#endif // MONO diff --git a/reflect/Impl/PdbWriter.cs b/reflect/Impl/PdbWriter.cs new file mode 100644 index 0000000..4d8fc1d --- /dev/null +++ b/reflect/Impl/PdbWriter.cs @@ -0,0 +1,1193 @@ +/* + Copyright (C) 2008-2010 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Diagnostics.SymbolStore; +using IKVM.Reflection.Emit; + +namespace IKVM.Reflection.Impl +{ + [Guid("7dac8207-d3ae-4c75-9b67-92801a497d44")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + interface IMetaDataImport + { + void PlaceHolder_CloseEnum(); + void PlaceHolder_CountEnum(); + void PlaceHolder_ResetEnum(); + void PlaceHolder_EnumTypeDefs(); + void PlaceHolder_EnumInterfaceImpls(); + void PlaceHolder_EnumTypeRefs(); + void PlaceHolder_FindTypeDefByName(); + void PlaceHolder_GetScopeProps(); + void PlaceHolder_GetModuleFromScope(); + + void GetTypeDefProps( + int td, // [IN] TypeDef token for inquiry. + IntPtr szTypeDef, // [OUT] Put name here. + int cchTypeDef, // [IN] size of name buffer in wide chars. + IntPtr pchTypeDef, // [OUT] put size of name (wide chars) here. + IntPtr pdwTypeDefFlags, // [OUT] Put flags here. + IntPtr ptkExtends); // [OUT] Put base class TypeDef/TypeRef here. + + void PlaceHolder_GetInterfaceImplProps(); + void PlaceHolder_GetTypeRefProps(); + void PlaceHolder_ResolveTypeRef(); + void PlaceHolder_EnumMembers(); + void PlaceHolder_EnumMembersWithName(); + void PlaceHolder_EnumMethods(); + void PlaceHolder_EnumMethodsWithName(); + void PlaceHolder_EnumFields(); + void PlaceHolder_EnumFieldsWithName(); + void PlaceHolder_EnumParams(); + void PlaceHolder_EnumMemberRefs(); + void PlaceHolder_EnumMethodImpls(); + void PlaceHolder_EnumPermissionSets(); + void PlaceHolder_FindMember(); + void PlaceHolder_FindMethod(); + void PlaceHolder_FindField(); + void PlaceHolder_FindMemberRef(); + + void GetMethodProps( + int mb, // The method for which to get props. + IntPtr pClass, // Put method's class here. + IntPtr szMethod, // Put method's name here. + int cchMethod, // Size of szMethod buffer in wide chars. + IntPtr pchMethod, // Put actual size here + IntPtr pdwAttr, // Put flags here. + IntPtr ppvSigBlob, // [OUT] point to the blob value of meta data + IntPtr pcbSigBlob, // [OUT] actual size of signature blob + IntPtr pulCodeRVA, // [OUT] codeRVA + IntPtr pdwImplFlags); // [OUT] Impl. Flags + + void PlaceHolder_GetMemberRefProps(); + void PlaceHolder_EnumProperties(); + void PlaceHolder_EnumEvents(); + void PlaceHolder_GetEventProps(); + void PlaceHolder_EnumMethodSemantics(); + void PlaceHolder_GetMethodSemantics(); + void PlaceHolder_GetClassLayout(); + void PlaceHolder_GetFieldMarshal(); + void PlaceHolder_GetRVA(); + void PlaceHolder_GetPermissionSetProps(); + void PlaceHolder_GetSigFromToken(); + void PlaceHolder_GetModuleRefProps(); + void PlaceHolder_EnumModuleRefs(); + void PlaceHolder_GetTypeSpecFromToken(); + void PlaceHolder_GetNameFromToken(); + void PlaceHolder_EnumUnresolvedMethods(); + void PlaceHolder_GetUserString(); + void PlaceHolder_GetPinvokeMap(); + void PlaceHolder_EnumSignatures(); + void PlaceHolder_EnumTypeSpecs(); + void PlaceHolder_EnumUserStrings(); + void PlaceHolder_GetParamForMethodIndex(); + void PlaceHolder_EnumCustomAttributes(); + void PlaceHolder_GetCustomAttributeProps(); + void PlaceHolder_FindTypeRef(); + void PlaceHolder_GetMemberProps(); + void PlaceHolder_GetFieldProps(); + void PlaceHolder_GetPropertyProps(); + void PlaceHolder_GetParamProps(); + void PlaceHolder_GetCustomAttributeByName(); + void PlaceHolder_IsValidToken(); + + void GetNestedClassProps( + int tdNestedClass, // [IN] NestedClass token. + IntPtr ptdEnclosingClass); // [OUT] EnclosingClass token. + + void PlaceHolder_GetNativeCallConvFromSig(); + void PlaceHolder_IsGlobal(); + } + + [Guid("ba3fee4c-ecb9-4e41-83b7-183fa41cd859")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + interface IMetaDataEmit + { + void PlaceHolder_SetModuleProps(); + void PlaceHolder_Save(); + void PlaceHolder_SaveToStream(); + void PlaceHolder_GetSaveSize(); + void PlaceHolder_DefineTypeDef(); + void PlaceHolder_DefineNestedType(); + void PlaceHolder_SetHandler(); + void PlaceHolder_DefineMethod(); + void PlaceHolder_DefineMethodImpl(); + void PlaceHolder_DefineTypeRefByName(); + void PlaceHolder_DefineImportType(); + void PlaceHolder_DefineMemberRef(); + void PlaceHolder_DefineImportMember(); + void PlaceHolder_DefineEvent(); + void PlaceHolder_SetClassLayout(); + void PlaceHolder_DeleteClassLayout(); + void PlaceHolder_SetFieldMarshal(); + void PlaceHolder_DeleteFieldMarshal(); + void PlaceHolder_DefinePermissionSet(); + void PlaceHolder_SetRVA(); + void PlaceHolder_GetTokenFromSig(); + void PlaceHolder_DefineModuleRef(); + void PlaceHolder_SetParent(); + void PlaceHolder_GetTokenFromTypeSpec(); + void PlaceHolder_SaveToMemory(); + void PlaceHolder_DefineUserString(); + void PlaceHolder_DeleteToken(); + void PlaceHolder_SetMethodProps(); + void PlaceHolder_SetTypeDefProps(); + void PlaceHolder_SetEventProps(); + void PlaceHolder_SetPermissionSetProps(); + void PlaceHolder_DefinePinvokeMap(); + void PlaceHolder_SetPinvokeMap(); + void PlaceHolder_DeletePinvokeMap(); + void PlaceHolder_DefineCustomAttribute(); + void PlaceHolder_SetCustomAttributeValue(); + void PlaceHolder_DefineField(); + void PlaceHolder_DefineProperty(); + void PlaceHolder_DefineParam(); + void PlaceHolder_SetFieldProps(); + void PlaceHolder_SetPropertyProps(); + void PlaceHolder_SetParamProps(); + void PlaceHolder_DefineSecurityAttributeSet(); + void PlaceHolder_ApplyEditAndContinue(); + void PlaceHolder_TranslateSigWithScope(); + void PlaceHolder_SetMethodImplFlags(); + void PlaceHolder_SetFieldRVA(); + void PlaceHolder_Merge(); + void PlaceHolder_MergeEnd(); + } + + [Guid("B01FAFEB-C450-3A4D-BEEC-B4CEEC01E006")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + internal interface ISymUnmanagedDocumentWriter { } + + [Guid("0b97726e-9e6d-4f05-9a26-424022093caa")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + [CoClass(typeof(CorSymWriterClass))] + interface ISymUnmanagedWriter2 + { + ISymUnmanagedDocumentWriter DefineDocument(string url, ref Guid language, ref Guid languageVendor, ref Guid documentType); + void PlaceHolder_SetUserEntryPoint(); + void OpenMethod(int method); + void CloseMethod(); + int OpenScope(int startOffset); + void CloseScope(int endOffset); + void PlaceHolder_SetScopeRange(); + void DefineLocalVariable(string name, int attributes, int cSig, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] signature, int addrKind, int addr1, int addr2, int startOffset, int endOffset); + void PlaceHolder_DefineParameter(); + void PlaceHolder_DefineField(); + void PlaceHolder_DefineGlobalVariable(); + void Close(); + void PlaceHolder_SetSymAttribute(); + void PlaceHolder_OpenNamespace(); + void PlaceHolder_CloseNamespace(); + void PlaceHolder_UsingNamespace(); + void PlaceHolder_SetMethodSourceRange(); + void Initialize([MarshalAs(UnmanagedType.IUnknown)] object emitter, string filename, [MarshalAs(UnmanagedType.IUnknown)] object pIStream, bool fFullBuild); + + void GetDebugInfo( + [In, Out] ref IMAGE_DEBUG_DIRECTORY pIDD, + [In] uint cData, + [Out] out uint pcData, + [Out, MarshalAs(UnmanagedType.LPArray)] byte[] data); + + void DefineSequencePoints(ISymUnmanagedDocumentWriter document, int spCount, + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] offsets, + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] lines, + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] columns, + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] endLines, + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] endColumns); + + void RemapToken( + [In] int oldToken, + [In] int newToken); + + void PlaceHolder_Initialize2(); + void PlaceHolder_DefineConstant(); + void PlaceHolder_Abort(); + + void DefineLocalVariable2(string name, int attributes, int token, int addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset); + + void PlaceHolder_DefineGlobalVariable2(); + void PlaceHolder_DefineConstant2(); + } + + [Guid("108296c1-281e-11d3-bd22-0000f80849bd")] + [ComImport] + class CorSymWriterClass { } + + sealed class PdbWriter : ISymbolWriterImpl, IMetaDataEmit, IMetaDataImport + { + private readonly ModuleBuilder moduleBuilder; + private ISymUnmanagedWriter2 symUnmanagedWriter; + private readonly Dictionary documents = new Dictionary(); + private readonly List methods = new List(); + private readonly Dictionary remap = new Dictionary(); + private readonly Dictionary reversemap = new Dictionary(); + private readonly Dictionary methodMap = new Dictionary(); + private Method currentMethod; + + internal PdbWriter(ModuleBuilder moduleBuilder) + { + this.moduleBuilder = moduleBuilder; + } + + private sealed class Document : ISymbolDocumentWriter + { + internal readonly string url; + private Guid language; + private Guid languageVendor; + private Guid documentType; + private ISymUnmanagedDocumentWriter unmanagedDocument; + + internal Document(string url, Guid language, Guid languageVendor, Guid documentType) + { + this.url = url; + this.language = language; + this.languageVendor = languageVendor; + this.documentType = documentType; + } + + public void SetCheckSum(Guid algorithmId, byte[] checkSum) + { + throw new NotImplementedException(); + } + + public void SetSource(byte[] source) + { + throw new NotImplementedException(); + } + + internal ISymUnmanagedDocumentWriter GetUnmanagedDocument(ISymUnmanagedWriter2 symUnmanagedWriter) + { + if (unmanagedDocument == null) + { + unmanagedDocument = symUnmanagedWriter.DefineDocument(url, ref language, ref languageVendor, ref documentType); + } + return unmanagedDocument; + } + + internal void Release() + { + if (unmanagedDocument != null) + { + Marshal.ReleaseComObject(unmanagedDocument); + unmanagedDocument = null; + } + } + } + + private sealed class LocalVar + { + internal readonly FieldAttributes attributes; + internal readonly int signature; + internal readonly SymAddressKind addrKind; + internal readonly int addr1; + internal readonly int addr2; + internal readonly int addr3; + internal readonly int startOffset; + internal readonly int endOffset; + + internal LocalVar(FieldAttributes attributes, int signature, SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset) + { + this.attributes = attributes; + this.signature = signature; + this.addrKind = addrKind; + this.addr1 = addr1; + this.addr2 = addr2; + this.addr3 = addr3; + this.startOffset = startOffset; + this.endOffset = endOffset; + } + } + + private sealed class Scope + { + internal readonly int startOffset; + internal int endOffset; + internal readonly List scopes = new List(); + internal readonly Dictionary locals = new Dictionary(); + + internal Scope(int startOffset) + { + this.startOffset = startOffset; + } + + internal void Do(ISymUnmanagedWriter2 symUnmanagedWriter) + { + symUnmanagedWriter.OpenScope(startOffset); + foreach (KeyValuePair kv in locals) + { + symUnmanagedWriter.DefineLocalVariable2(kv.Key, (int)kv.Value.attributes, kv.Value.signature, (int)kv.Value.addrKind, kv.Value.addr1, kv.Value.addr2, kv.Value.addr3, kv.Value.startOffset, kv.Value.endOffset); + } + foreach (Scope scope in scopes) + { + scope.Do(symUnmanagedWriter); + } + symUnmanagedWriter.CloseScope(endOffset); + } + } + + private sealed class Method + { + internal readonly int token; + internal Document document; + internal int[] offsets; + internal int[] lines; + internal int[] columns; + internal int[] endLines; + internal int[] endColumns; + internal readonly List scopes = new List(); + internal readonly Stack scopeStack = new Stack(); + + internal Method(int token) + { + this.token = token; + } + } + + public ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType) + { + Document doc; + if (!documents.TryGetValue(url, out doc)) + { + doc = new Document(url, language, languageVendor, documentType); + documents.Add(url, doc); + } + return doc; + } + + public void OpenMethod(SymbolToken method) + { + throw new NotImplementedException(); + } + + public void OpenMethod(SymbolToken method, MethodBase mb) + { + int token = method.GetToken(); + currentMethod = new Method(token); + methodMap.Add(token, mb); + } + + public void CloseMethod() + { + methods.Add(currentMethod); + currentMethod = null; + } + + public void DefineSequencePoints(ISymbolDocumentWriter document, int[] offsets, int[] lines, int[] columns, int[] endLines, int[] endColumns) + { + currentMethod.document = (Document)document; + currentMethod.offsets = offsets; + currentMethod.lines = lines; + currentMethod.columns = columns; + currentMethod.endLines = endLines; + currentMethod.endColumns = endColumns; + } + + public int OpenScope(int startOffset) + { + Scope scope = new Scope(startOffset); + if (currentMethod.scopeStack.Count == 0) + { + currentMethod.scopes.Add(scope); + } + else + { + currentMethod.scopeStack.Peek().scopes.Add(scope); + } + currentMethod.scopeStack.Push(scope); + return 0; + } + + public void CloseScope(int endOffset) + { + currentMethod.scopeStack.Pop().endOffset = endOffset; + } + + public void DefineLocalVariable2(string name, FieldAttributes attributes, int signature, SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset) + { + currentMethod.scopeStack.Peek().locals[name] = new LocalVar(attributes, signature, addrKind, addr1, addr2, addr3, startOffset, endOffset); + } + + private void InitWriter() + { + if (symUnmanagedWriter == null) + { + string fileName = System.IO.Path.ChangeExtension(moduleBuilder.FullyQualifiedName, ".pdb"); + // pro-actively delete the .pdb to get a meaningful IOException, instead of COMInteropException if the file can't be overwritten (or is corrupt, or who knows what) + System.IO.File.Delete(fileName); + symUnmanagedWriter = new ISymUnmanagedWriter2(); + symUnmanagedWriter.Initialize(this, fileName, null, true); + } + } + + public byte[] GetDebugInfo(ref IMAGE_DEBUG_DIRECTORY idd) + { + InitWriter(); + uint cData; + symUnmanagedWriter.GetDebugInfo(ref idd, 0, out cData, null); + byte[] buf = new byte[cData]; + symUnmanagedWriter.GetDebugInfo(ref idd, (uint)buf.Length, out cData, buf); + return buf; + } + + public void RemapToken(int oldToken, int newToken) + { + remap.Add(oldToken, newToken); + reversemap.Add(newToken, oldToken); + } + + public void Close() + { + InitWriter(); + + foreach (Method method in methods) + { + int remappedToken = method.token; + remap.TryGetValue(remappedToken, out remappedToken); + symUnmanagedWriter.OpenMethod(remappedToken); + if (method.document != null) + { + ISymUnmanagedDocumentWriter doc = method.document.GetUnmanagedDocument(symUnmanagedWriter); + symUnmanagedWriter.DefineSequencePoints(doc, method.offsets.Length, method.offsets, method.lines, method.columns, method.endLines, method.endColumns); + } + foreach (Scope scope in method.scopes) + { + scope.Do(symUnmanagedWriter); + } + symUnmanagedWriter.CloseMethod(); + } + + foreach (Document doc in documents.Values) + { + doc.Release(); + } + + symUnmanagedWriter.Close(); + Marshal.ReleaseComObject(symUnmanagedWriter); + symUnmanagedWriter = null; + documents.Clear(); + methods.Clear(); + remap.Clear(); + reversemap.Clear(); + } + + public void DefineLocalVariable(string name, System.Reflection.FieldAttributes attributes, byte[] signature, SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset) + { + throw new NotImplementedException(); + } + + public void CloseNamespace() + { + throw new NotImplementedException(); + } + + public void DefineField(SymbolToken parent, string name, System.Reflection.FieldAttributes attributes, byte[] signature, SymAddressKind addrKind, int addr1, int addr2, int addr3) + { + throw new NotImplementedException(); + } + + public void DefineGlobalVariable(string name, System.Reflection.FieldAttributes attributes, byte[] signature, SymAddressKind addrKind, int addr1, int addr2, int addr3) + { + throw new NotImplementedException(); + } + + public void DefineParameter(string name, System.Reflection.ParameterAttributes attributes, int sequence, SymAddressKind addrKind, int addr1, int addr2, int addr3) + { + throw new NotImplementedException(); + } + + public void Initialize(IntPtr emitter, string filename, bool fFullBuild) + { + throw new NotImplementedException(); + } + + public void OpenNamespace(string name) + { + throw new NotImplementedException(); + } + + public void SetMethodSourceRange(ISymbolDocumentWriter startDoc, int startLine, int startColumn, ISymbolDocumentWriter endDoc, int endLine, int endColumn) + { + throw new NotImplementedException(); + } + + public void SetScopeRange(int scopeID, int startOffset, int endOffset) + { + throw new NotImplementedException(); + } + + public void SetSymAttribute(SymbolToken parent, string name, byte[] data) + { + throw new NotImplementedException(); + } + + public void SetUnderlyingWriter(IntPtr underlyingWriter) + { + throw new NotImplementedException(); + } + + public void SetUserEntryPoint(SymbolToken entryMethod) + { + throw new NotImplementedException(); + } + + public void UsingNamespace(string fullName) + { + throw new NotImplementedException(); + } + + public void PlaceHolder_CloseEnum() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_CountEnum() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_ResetEnum() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumTypeDefs() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumInterfaceImpls() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumTypeRefs() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_FindTypeDefByName() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetScopeProps() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetModuleFromScope() + { + throw new NotImplementedException(); + } + + private static void WriteString(IntPtr ptrString, IntPtr ptrLength, string str, int length) + { + if (ptrString != IntPtr.Zero) + { + for (int i = 0; i < Math.Min(length, str.Length); i++) + { + Marshal.WriteInt16(ptrString, i, str[i]); + } + } + if (ptrLength != IntPtr.Zero) + { + Marshal.WriteInt32(ptrLength, str.Length); + } + } + + private static void WriteToken(IntPtr ptr, MemberInfo member) + { + if (ptr != IntPtr.Zero) + { + Marshal.WriteInt32(ptr, member == null ? 0 : member.MetadataToken); + } + } + + private static void WriteInt32(IntPtr ptr, int value) + { + if (ptr != IntPtr.Zero) + { + Marshal.WriteInt32(ptr, value); + } + } + + public void GetTypeDefProps( + int td, // [IN] TypeDef token for inquiry. + IntPtr szTypeDef, // [OUT] Put name here. + int cchTypeDef, // [IN] size of name buffer in wide chars. + IntPtr pchTypeDef, // [OUT] put size of name (wide chars) here. + IntPtr pdwTypeDefFlags, // [OUT] Put flags here. + IntPtr ptkExtends) // [OUT] Put base class TypeDef/TypeRef here. + { + if (td == 0) + { + // why are we being called with an invalid token? + WriteString(szTypeDef, pchTypeDef, "", cchTypeDef); + WriteInt32(pdwTypeDefFlags, 0); + WriteToken(ptkExtends, null); + } + else + { + Type type = moduleBuilder.ResolveType(td); + WriteString(szTypeDef, pchTypeDef, type.FullName, cchTypeDef); + WriteInt32(pdwTypeDefFlags, (int)type.Attributes); + WriteToken(ptkExtends, type.BaseType); + } + } + + public void PlaceHolder_GetInterfaceImplProps() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetTypeRefProps() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_ResolveTypeRef() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumMembers() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumMembersWithName() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumMethods() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumMethodsWithName() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumFields() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumFieldsWithName() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumParams() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumMemberRefs() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumMethodImpls() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumPermissionSets() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_FindMember() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_FindMethod() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_FindField() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_FindMemberRef() + { + throw new NotImplementedException(); + } + + public void GetMethodProps( + int mb, // The method for which to get props. + IntPtr pClass, // [OUT] Put method's class here. + IntPtr szMethod, // [OUT] Put method's name here. + int cchMethod, // Size of szMethod buffer in wide chars. + IntPtr pchMethod, // [OUT] Put actual size here + IntPtr pdwAttr, // [OUT] Put flags here. + IntPtr ppvSigBlob, // [OUT] point to the blob value of meta data + IntPtr pcbSigBlob, // [OUT] actual size of signature blob + IntPtr pulCodeRVA, // [OUT] codeRVA + IntPtr pdwImplFlags) // [OUT] Impl. Flags + { + if (pdwAttr != IntPtr.Zero || ppvSigBlob != IntPtr.Zero || pcbSigBlob != IntPtr.Zero || pulCodeRVA != IntPtr.Zero || pdwImplFlags != IntPtr.Zero) + { + throw new NotImplementedException(); + } + MethodBase method = methodMap[reversemap[mb]]; + WriteToken(pClass, method.DeclaringType); + WriteString(szMethod, pchMethod, method.Name, cchMethod); + } + + public void PlaceHolder_GetMemberRefProps() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumProperties() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumEvents() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetEventProps() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumMethodSemantics() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetMethodSemantics() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetClassLayout() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetFieldMarshal() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetRVA() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetPermissionSetProps() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetSigFromToken() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetModuleRefProps() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumModuleRefs() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetTypeSpecFromToken() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetNameFromToken() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumUnresolvedMethods() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetUserString() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetPinvokeMap() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumSignatures() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumTypeSpecs() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumUserStrings() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetParamForMethodIndex() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_EnumCustomAttributes() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetCustomAttributeProps() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_FindTypeRef() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetMemberProps() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetFieldProps() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetPropertyProps() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetParamProps() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetCustomAttributeByName() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_IsValidToken() + { + throw new NotImplementedException(); + } + + public void GetNestedClassProps( + int tdNestedClass, // [IN] NestedClass token. + IntPtr ptdEnclosingClass) // [OUT] EnclosingClass token. + { + Type type = moduleBuilder.ResolveType(tdNestedClass); + WriteToken(ptdEnclosingClass, type.DeclaringType); + } + + public void PlaceHolder_GetNativeCallConvFromSig() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_IsGlobal() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_SetModuleProps() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_Save() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_SaveToStream() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetSaveSize() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DefineTypeDef() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DefineNestedType() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_SetHandler() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DefineMethod() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DefineMethodImpl() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DefineTypeRefByName() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DefineImportType() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DefineMemberRef() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DefineImportMember() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DefineEvent() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_SetClassLayout() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DeleteClassLayout() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_SetFieldMarshal() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DeleteFieldMarshal() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DefinePermissionSet() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_SetRVA() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetTokenFromSig() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DefineModuleRef() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_SetParent() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_GetTokenFromTypeSpec() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_SaveToMemory() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DefineUserString() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DeleteToken() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_SetMethodProps() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_SetTypeDefProps() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_SetEventProps() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_SetPermissionSetProps() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DefinePinvokeMap() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_SetPinvokeMap() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DeletePinvokeMap() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DefineCustomAttribute() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_SetCustomAttributeValue() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DefineField() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DefineProperty() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DefineParam() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_SetFieldProps() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_SetPropertyProps() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_SetParamProps() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_DefineSecurityAttributeSet() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_ApplyEditAndContinue() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_TranslateSigWithScope() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_SetMethodImplFlags() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_SetFieldRVA() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_Merge() + { + throw new NotImplementedException(); + } + + public void PlaceHolder_MergeEnd() + { + throw new NotImplementedException(); + } + + public bool IsDeterministic + { + get { return false; } + } + } +} diff --git a/reflect/Impl/SymbolSupport.cs b/reflect/Impl/SymbolSupport.cs new file mode 100644 index 0000000..7b4e890 --- /dev/null +++ b/reflect/Impl/SymbolSupport.cs @@ -0,0 +1,103 @@ +/* + Copyright (C) 2008, 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Runtime.InteropServices; +#if !NO_SYMBOL_WRITER +using System.Diagnostics.SymbolStore; +#endif +using IKVM.Reflection.Emit; + +namespace IKVM.Reflection.Impl +{ + [StructLayout(LayoutKind.Sequential)] + struct IMAGE_DEBUG_DIRECTORY + { + public uint Characteristics; + public uint TimeDateStamp; + public ushort MajorVersion; + public ushort MinorVersion; + public uint Type; + public uint SizeOfData; + public uint AddressOfRawData; + public uint PointerToRawData; + } + +#if NO_SYMBOL_WRITER + struct SymbolToken + { + internal SymbolToken(int value) { } + } + + interface ISymbolWriterImpl + { + byte[] GetDebugInfo(ref IMAGE_DEBUG_DIRECTORY idd); + void RemapToken(int oldToken, int newToken); + void DefineLocalVariable2(string name, FieldAttributes attributes, int signature, int addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset); + void OpenMethod(SymbolToken symbolToken, MethodBase mb); + bool IsDeterministic { get; } + } +#else + interface ISymbolWriterImpl : ISymbolWriter + { + byte[] GetDebugInfo(ref IMAGE_DEBUG_DIRECTORY idd); + void RemapToken(int oldToken, int newToken); + void DefineLocalVariable2(string name, FieldAttributes attributes, int signature, SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset); + void OpenMethod(SymbolToken symbolToken, MethodBase mb); + bool IsDeterministic { get; } + } +#endif + + static class SymbolSupport + { + internal static ISymbolWriterImpl CreateSymbolWriterFor(ModuleBuilder moduleBuilder) + { +#if NO_SYMBOL_WRITER + throw new NotSupportedException("IKVM.Reflection compiled with NO_SYMBOL_WRITER does not support writing debugging symbols."); +#else + if (Universe.MonoRuntime) + { +#if MONO + return new MdbWriter(moduleBuilder); +#else + throw new NotSupportedException("IKVM.Reflection must be compiled with MONO defined to support writing Mono debugging symbols."); +#endif + } + else + { + return new PdbWriter(moduleBuilder); + } +#endif + } + + internal static byte[] GetDebugInfo(ISymbolWriterImpl writer, ref IMAGE_DEBUG_DIRECTORY idd) + { + return writer.GetDebugInfo(ref idd); + } + + internal static void RemapToken(ISymbolWriterImpl writer, int oldToken, int newToken) + { + writer.RemapToken(oldToken, newToken); + } + } +} diff --git a/reflect/InterfaceMapping.cs b/reflect/InterfaceMapping.cs new file mode 100644 index 0000000..f589cfe --- /dev/null +++ b/reflect/InterfaceMapping.cs @@ -0,0 +1,35 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; + +namespace IKVM.Reflection +{ + public struct InterfaceMapping + { + public MethodInfo[] InterfaceMethods; + public Type InterfaceType; + public MethodInfo[] TargetMethods; + public Type TargetType; + } +} diff --git a/reflect/LocalVariableInfo.cs b/reflect/LocalVariableInfo.cs new file mode 100644 index 0000000..9d565aa --- /dev/null +++ b/reflect/LocalVariableInfo.cs @@ -0,0 +1,73 @@ +/* + Copyright (C) 2009-2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; + +namespace IKVM.Reflection +{ + public class LocalVariableInfo + { + private readonly int index; + private readonly Type type; + private readonly bool pinned; + private readonly CustomModifiers customModifiers; + + internal LocalVariableInfo(int index, Type type, bool pinned) + { + this.index = index; + this.type = type; + this.pinned = pinned; + } + + internal LocalVariableInfo(int index, Type type, bool pinned, CustomModifiers customModifiers) + : this(index, type, pinned) + { + this.customModifiers = customModifiers; + } + + public bool IsPinned + { + get { return pinned; } + } + + public int LocalIndex + { + get { return index; } + } + + public Type LocalType + { + get { return type; } + } + + public CustomModifiers __GetCustomModifiers() + { + return customModifiers; + } + + public override string ToString() + { + return String.Format(pinned ? "{0} ({1}) (pinned)" : "{0} ({1})", type, index); + } + } +} diff --git a/reflect/ManifestResourceInfo.cs b/reflect/ManifestResourceInfo.cs new file mode 100644 index 0000000..04a2a30 --- /dev/null +++ b/reflect/ManifestResourceInfo.cs @@ -0,0 +1,113 @@ +/* + Copyright (C) 2009-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using IKVM.Reflection.Reader; +using IKVM.Reflection.Metadata; + +namespace IKVM.Reflection +{ + public sealed class ManifestResourceInfo + { + private readonly ModuleReader module; + private readonly int index; + + internal ManifestResourceInfo(ModuleReader module, int index) + { + this.module = module; + this.index = index; + } + + public ResourceAttributes __ResourceAttributes + { + get { return (ResourceAttributes)module.ManifestResource.records[index].Flags; } + } + + public int __Offset + { + get { return module.ManifestResource.records[index].Offset; } + } + + public ResourceLocation ResourceLocation + { + get + { + int implementation = module.ManifestResource.records[index].Implementation; + if ((implementation >> 24) == AssemblyRefTable.Index) + { + Assembly asm = ReferencedAssembly; + if (asm == null || asm.__IsMissing) + { + return ResourceLocation.ContainedInAnotherAssembly; + } + return asm.GetManifestResourceInfo(module.GetString(module.ManifestResource.records[index].Name)).ResourceLocation | ResourceLocation.ContainedInAnotherAssembly; + } + else if ((implementation >> 24) == FileTable.Index) + { + if ((implementation & 0xFFFFFF) == 0) + { + return ResourceLocation.ContainedInManifestFile | ResourceLocation.Embedded; + } + return 0; + } + else + { + throw new BadImageFormatException(); + } + } + } + + public Assembly ReferencedAssembly + { + get + { + int implementation = module.ManifestResource.records[index].Implementation; + if ((implementation >> 24) == AssemblyRefTable.Index) + { + return module.ResolveAssemblyRef((implementation & 0xFFFFFF) - 1); + } + return null; + } + } + + public string FileName + { + get + { + int implementation = module.ManifestResource.records[index].Implementation; + if ((implementation >> 24) == FileTable.Index) + { + if ((implementation & 0xFFFFFF) == 0) + { + return null; + } + else + { + return module.GetString(module.File.records[(implementation & 0xFFFFFF) - 1].Name); + } + } + return null; + } + } + } +} diff --git a/reflect/MarshalSpec.cs b/reflect/MarshalSpec.cs new file mode 100644 index 0000000..0370ada --- /dev/null +++ b/reflect/MarshalSpec.cs @@ -0,0 +1,259 @@ +/* + Copyright (C) 2008-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; +using IKVM.Reflection.Emit; +using IKVM.Reflection.Reader; +using IKVM.Reflection.Writer; +using IKVM.Reflection.Metadata; + +namespace IKVM.Reflection +{ + public struct FieldMarshal + { + private const UnmanagedType NATIVE_TYPE_MAX = (UnmanagedType)0x50; + public UnmanagedType UnmanagedType; + public UnmanagedType? ArraySubType; + public short? SizeParamIndex; + public int? SizeConst; + public VarEnum? SafeArraySubType; + public Type SafeArrayUserDefinedSubType; + public int? IidParameterIndex; + public string MarshalType; + public string MarshalCookie; + public Type MarshalTypeRef; + + internal static bool ReadFieldMarshal(Module module, int token, out FieldMarshal fm) + { + fm = new FieldMarshal(); + foreach (int i in module.FieldMarshal.Filter(token)) + { + ByteReader blob = module.GetBlob(module.FieldMarshal.records[i].NativeType); + fm.UnmanagedType = (UnmanagedType)blob.ReadCompressedUInt(); + if (fm.UnmanagedType == UnmanagedType.LPArray) + { + fm.ArraySubType = (UnmanagedType)blob.ReadCompressedUInt(); + if (fm.ArraySubType == NATIVE_TYPE_MAX) + { + fm.ArraySubType = null; + } + if (blob.Length != 0) + { + fm.SizeParamIndex = (short)blob.ReadCompressedUInt(); + if (blob.Length != 0) + { + fm.SizeConst = blob.ReadCompressedUInt(); + if (blob.Length != 0 && blob.ReadCompressedUInt() == 0) + { + fm.SizeParamIndex = null; + } + } + } + } + else if (fm.UnmanagedType == UnmanagedType.SafeArray) + { + if (blob.Length != 0) + { + fm.SafeArraySubType = (VarEnum)blob.ReadCompressedUInt(); + if (blob.Length != 0) + { + fm.SafeArrayUserDefinedSubType = ReadType(module, blob); + } + } + } + else if (fm.UnmanagedType == UnmanagedType.ByValArray) + { + fm.SizeConst = blob.ReadCompressedUInt(); + if (blob.Length != 0) + { + fm.ArraySubType = (UnmanagedType)blob.ReadCompressedUInt(); + } + } + else if (fm.UnmanagedType == UnmanagedType.ByValTStr) + { + fm.SizeConst = blob.ReadCompressedUInt(); + } + else if (fm.UnmanagedType == UnmanagedType.Interface + || fm.UnmanagedType == UnmanagedType.IDispatch + || fm.UnmanagedType == UnmanagedType.IUnknown) + { + if (blob.Length != 0) + { + fm.IidParameterIndex = blob.ReadCompressedUInt(); + } + } + else if (fm.UnmanagedType == UnmanagedType.CustomMarshaler) + { + blob.ReadCompressedUInt(); + blob.ReadCompressedUInt(); + fm.MarshalType = ReadString(blob); + fm.MarshalCookie = ReadString(blob); + + TypeNameParser parser = TypeNameParser.Parse(fm.MarshalType, false); + if (!parser.Error) + { + fm.MarshalTypeRef = parser.GetType(module.universe, module, false, fm.MarshalType, false, false); + } + } + return true; + } + return false; + } + + internal static void SetMarshalAsAttribute(ModuleBuilder module, int token, CustomAttributeBuilder attribute) + { + attribute = attribute.DecodeBlob(module.Assembly); + FieldMarshalTable.Record rec = new FieldMarshalTable.Record(); + rec.Parent = token; + rec.NativeType = WriteMarshallingDescriptor(module, attribute); + module.FieldMarshal.AddRecord(rec); + } + + private static int WriteMarshallingDescriptor(ModuleBuilder module, CustomAttributeBuilder attribute) + { + UnmanagedType unmanagedType; + object val = attribute.GetConstructorArgument(0); + if (val is short) + { + unmanagedType = (UnmanagedType)(short)val; + } + else if (val is int) + { + unmanagedType = (UnmanagedType)(int)val; + } + else + { + unmanagedType = (UnmanagedType)val; + } + + ByteBuffer bb = new ByteBuffer(5); + bb.WriteCompressedUInt((int)unmanagedType); + + if (unmanagedType == UnmanagedType.LPArray) + { + UnmanagedType arraySubType = attribute.GetFieldValue("ArraySubType") ?? NATIVE_TYPE_MAX; + bb.WriteCompressedUInt((int)arraySubType); + int? sizeParamIndex = attribute.GetFieldValue("SizeParamIndex"); + int? sizeConst = attribute.GetFieldValue("SizeConst"); + if (sizeParamIndex != null) + { + bb.WriteCompressedUInt(sizeParamIndex.Value); + if (sizeConst != null) + { + bb.WriteCompressedUInt(sizeConst.Value); + bb.WriteCompressedUInt(1); // flag that says that SizeParamIndex was specified + } + } + else if (sizeConst != null) + { + bb.WriteCompressedUInt(0); // SizeParamIndex + bb.WriteCompressedUInt(sizeConst.Value); + bb.WriteCompressedUInt(0); // flag that says that SizeParamIndex was not specified + } + } + else if (unmanagedType == UnmanagedType.SafeArray) + { + VarEnum? safeArraySubType = attribute.GetFieldValue("SafeArraySubType"); + if (safeArraySubType != null) + { + bb.WriteCompressedUInt((int)safeArraySubType); + Type safeArrayUserDefinedSubType = (Type)attribute.GetFieldValue("SafeArrayUserDefinedSubType"); + if (safeArrayUserDefinedSubType != null) + { + WriteType(module, bb, safeArrayUserDefinedSubType); + } + } + } + else if (unmanagedType == UnmanagedType.ByValArray) + { + bb.WriteCompressedUInt(attribute.GetFieldValue("SizeConst") ?? 1); + UnmanagedType? arraySubType = attribute.GetFieldValue("ArraySubType"); + if (arraySubType != null) + { + bb.WriteCompressedUInt((int)arraySubType); + } + } + else if (unmanagedType == UnmanagedType.ByValTStr) + { + bb.WriteCompressedUInt(attribute.GetFieldValue("SizeConst").Value); + } + else if (unmanagedType == UnmanagedType.Interface + || unmanagedType == UnmanagedType.IDispatch + || unmanagedType == UnmanagedType.IUnknown) + { + int? iidParameterIndex = attribute.GetFieldValue("IidParameterIndex"); + if (iidParameterIndex != null) + { + bb.WriteCompressedUInt(iidParameterIndex.Value); + } + } + else if (unmanagedType == UnmanagedType.CustomMarshaler) + { + bb.WriteCompressedUInt(0); + bb.WriteCompressedUInt(0); + string marshalType = (string)attribute.GetFieldValue("MarshalType"); + if (marshalType != null) + { + WriteString(bb, marshalType); + } + else + { + WriteType(module, bb, (Type)attribute.GetFieldValue("MarshalTypeRef")); + } + WriteString(bb, (string)attribute.GetFieldValue("MarshalCookie") ?? ""); + } + + return module.Blobs.Add(bb); + } + + private static Type ReadType(Module module, ByteReader br) + { + string str = ReadString(br); + if (str == "") + { + return null; + } + return module.Assembly.GetType(str) ?? module.universe.GetType(str, true); + } + + private static void WriteType(Module module, ByteBuffer bb, Type type) + { + WriteString(bb, type.Assembly == module.Assembly ? type.FullName : type.AssemblyQualifiedName); + } + + private static string ReadString(ByteReader br) + { + return Encoding.UTF8.GetString(br.ReadBytes(br.ReadCompressedUInt())); + } + + private static void WriteString(ByteBuffer bb, string str) + { + byte[] buf = Encoding.UTF8.GetBytes(str); + bb.WriteCompressedUInt(buf.Length); + bb.Write(buf); + } + } +} diff --git a/reflect/MemberInfo.cs b/reflect/MemberInfo.cs new file mode 100644 index 0000000..1a8173b --- /dev/null +++ b/reflect/MemberInfo.cs @@ -0,0 +1,135 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace IKVM.Reflection +{ +// disable warnings that complain about us having == and != operators without also overriding Equals/GetHashCode, +// this is intentional because most subtypes use reference equality +#pragma warning disable 660, 661 + public abstract class MemberInfo : ICustomAttributeProvider + { + // prevent external subclasses + internal MemberInfo() + { + } + + public abstract string Name { get; } + public abstract Type DeclaringType { get; } + public abstract MemberTypes MemberType { get; } + + public virtual Type ReflectedType + { + get { return DeclaringType; } + } + + internal abstract MemberInfo SetReflectedType(Type type); + + public virtual int MetadataToken + { + get { throw new NotSupportedException(); } + } + + public abstract Module Module + { + get; + } + + public virtual bool __IsMissing + { + get { return false; } + } + + public bool IsDefined(Type attributeType, bool inherit) + { + return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit).Count != 0; + } + + public IList __GetCustomAttributes(Type attributeType, bool inherit) + { + return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit); + } + + public IList GetCustomAttributesData() + { + return CustomAttributeData.GetCustomAttributes(this); + } + + public IEnumerable CustomAttributes + { + get { return GetCustomAttributesData(); } + } + + public static bool operator ==(MemberInfo m1, MemberInfo m2) + { + return ReferenceEquals(m1, m2) || (!ReferenceEquals(m1, null) && m1.Equals(m2)); + } + + public static bool operator !=(MemberInfo m1, MemberInfo m2) + { + return !(m1 == m2); + } + + internal abstract int GetCurrentToken(); + + internal abstract List GetPseudoCustomAttributes(Type attributeType); + + internal abstract bool IsBaked { get; } + + internal virtual bool BindingFlagsMatch(BindingFlags flags) + { + throw new InvalidOperationException(); + } + + internal virtual bool BindingFlagsMatchInherited(BindingFlags flags) + { + throw new InvalidOperationException(); + } + + protected static bool BindingFlagsMatch(bool state, BindingFlags flags, BindingFlags trueFlag, BindingFlags falseFlag) + { + return (state && (flags & trueFlag) == trueFlag) + || (!state && (flags & falseFlag) == falseFlag); + } + + protected static T SetReflectedType(T member, Type type) + where T : MemberInfo + { + return member == null ? null : (T)member.SetReflectedType(type); + } + + protected static T[] SetReflectedType(T[] members, Type type) + where T : MemberInfo + { + for (int i = 0; i < members.Length; i++) + { + members[i] = SetReflectedType(members[i], type); + } + return members; + } + } +} diff --git a/reflect/Metadata/CliHeader.cs b/reflect/Metadata/CliHeader.cs new file mode 100644 index 0000000..cb2574b --- /dev/null +++ b/reflect/Metadata/CliHeader.cs @@ -0,0 +1,99 @@ +/* + Copyright (C) 2008 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System.IO; + +namespace IKVM.Reflection.Metadata +{ + struct RvaSize + { + internal uint VirtualAddress; + internal uint Size; + + internal void Read(BinaryReader br) + { + VirtualAddress = br.ReadUInt32(); + Size = br.ReadUInt32(); + } + + internal void Write(IKVM.Reflection.Writer.MetadataWriter mw) + { + mw.Write(VirtualAddress); + mw.Write(Size); + } + } + + sealed class CliHeader + { + internal const uint COMIMAGE_FLAGS_ILONLY = 0x00000001; + internal const uint COMIMAGE_FLAGS_32BITREQUIRED = 0x00000002; + internal const uint COMIMAGE_FLAGS_STRONGNAMESIGNED = 0x00000008; + internal const uint COMIMAGE_FLAGS_NATIVE_ENTRYPOINT = 0x00000010; + internal const uint COMIMAGE_FLAGS_32BITPREFERRED = 0x00020000; + + internal uint Cb = 0x48; + internal ushort MajorRuntimeVersion; + internal ushort MinorRuntimeVersion; + internal RvaSize MetaData; + internal uint Flags; + internal uint EntryPointToken; + internal RvaSize Resources; + internal RvaSize StrongNameSignature; + internal RvaSize CodeManagerTable; + internal RvaSize VTableFixups; + internal RvaSize ExportAddressTableJumps; + internal RvaSize ManagedNativeHeader; + + internal void Read(BinaryReader br) + { + Cb = br.ReadUInt32(); + MajorRuntimeVersion = br.ReadUInt16(); + MinorRuntimeVersion = br.ReadUInt16(); + MetaData.Read(br); + Flags = br.ReadUInt32(); + EntryPointToken = br.ReadUInt32(); + Resources.Read(br); + StrongNameSignature.Read(br); + CodeManagerTable.Read(br); + VTableFixups.Read(br); + ExportAddressTableJumps.Read(br); + ManagedNativeHeader.Read(br); + } + + internal void Write(IKVM.Reflection.Writer.MetadataWriter mw) + { + mw.Write(Cb); + mw.Write(MajorRuntimeVersion); + mw.Write(MinorRuntimeVersion); + MetaData.Write(mw); + mw.Write(Flags); + mw.Write(EntryPointToken); + Resources.Write(mw); + StrongNameSignature.Write(mw); + CodeManagerTable.Write(mw); + VTableFixups.Write(mw); + ExportAddressTableJumps.Write(mw); + ManagedNativeHeader.Write(mw); + } + } +} diff --git a/reflect/Metadata/MetadataRW.cs b/reflect/Metadata/MetadataRW.cs new file mode 100644 index 0000000..d03c8d6 --- /dev/null +++ b/reflect/Metadata/MetadataRW.cs @@ -0,0 +1,101 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; + +namespace IKVM.Reflection.Metadata +{ + // base class for MetadataReader and MetadataWriter + abstract class MetadataRW + { + internal readonly bool bigStrings; + internal readonly bool bigGuids; + internal readonly bool bigBlobs; + internal readonly bool bigResolutionScope; + internal readonly bool bigTypeDefOrRef; + internal readonly bool bigMemberRefParent; + internal readonly bool bigHasCustomAttribute; + internal readonly bool bigCustomAttributeType; + internal readonly bool bigMethodDefOrRef; + internal readonly bool bigHasConstant; + internal readonly bool bigHasSemantics; + internal readonly bool bigHasFieldMarshal; + internal readonly bool bigHasDeclSecurity; + internal readonly bool bigTypeOrMethodDef; + internal readonly bool bigMemberForwarded; + internal readonly bool bigImplementation; + internal readonly bool bigField; + internal readonly bool bigMethodDef; + internal readonly bool bigParam; + internal readonly bool bigTypeDef; + internal readonly bool bigProperty; + internal readonly bool bigEvent; + internal readonly bool bigGenericParam; + internal readonly bool bigModuleRef; + + protected MetadataRW(Module module, bool bigStrings, bool bigGuids, bool bigBlobs) + { + this.bigStrings = bigStrings; + this.bigGuids = bigGuids; + this.bigBlobs = bigBlobs; + this.bigField = module.Field.IsBig; + this.bigMethodDef = module.MethodDef.IsBig; + this.bigParam = module.Param.IsBig; + this.bigTypeDef = module.TypeDef.IsBig; + this.bigProperty = module.Property.IsBig; + this.bigEvent = module.Event.IsBig; + this.bigGenericParam = module.GenericParam.IsBig; + this.bigModuleRef = module.ModuleRef.IsBig; + this.bigResolutionScope = IsBig(2, module.ModuleTable, module.ModuleRef, module.AssemblyRef, module.TypeRef); + this.bigTypeDefOrRef = IsBig(2, module.TypeDef, module.TypeRef, module.TypeSpec); + this.bigMemberRefParent = IsBig(3, module.TypeDef, module.TypeRef, module.ModuleRef, module.MethodDef, module.TypeSpec); + this.bigMethodDefOrRef = IsBig(1, module.MethodDef, module.MemberRef); + this.bigHasCustomAttribute = IsBig(5, module.MethodDef, module.Field, module.TypeRef, module.TypeDef, module.Param, module.InterfaceImpl, module.MemberRef, + module.ModuleTable, /*module.Permission,*/ module.Property, module.Event, module.StandAloneSig, module.ModuleRef, module.TypeSpec, module.AssemblyTable, + module.AssemblyRef, module.File, module.ExportedType, module.ManifestResource); + this.bigCustomAttributeType = IsBig(3, module.MethodDef, module.MemberRef); + this.bigHasConstant = IsBig(2, module.Field, module.Param, module.Property); + this.bigHasSemantics = IsBig(1, module.Event, module.Property); + this.bigHasFieldMarshal = IsBig(1, module.Field, module.Param); + this.bigHasDeclSecurity = IsBig(2, module.TypeDef, module.MethodDef, module.AssemblyTable); + this.bigTypeOrMethodDef = IsBig(1, module.TypeDef, module.MethodDef); + this.bigMemberForwarded = IsBig(1, module.Field, module.MethodDef); + this.bigImplementation = IsBig(2, module.File, module.AssemblyRef, module.ExportedType); + } + + private static bool IsBig(int bitsUsed, params Table[] tables) + { + int limit = 1 << (16 - bitsUsed); + foreach (Table table in tables) + { + if (table.RowCount >= limit) + { + return true; + } + } + return false; + } + } +} diff --git a/reflect/Metadata/Tables.cs b/reflect/Metadata/Tables.cs new file mode 100644 index 0000000..b8734c2 --- /dev/null +++ b/reflect/Metadata/Tables.cs @@ -0,0 +1,2722 @@ +/* + Copyright (C) 2009-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; +using IKVM.Reflection.Emit; +using IKVM.Reflection.Writer; +using IKVM.Reflection.Reader; + +namespace IKVM.Reflection.Metadata +{ + internal abstract class Table + { + internal bool Sorted; + + internal bool IsBig + { + get { return RowCount > 65535; } + } + + internal abstract int RowCount { get; set; } + + internal abstract void Write(MetadataWriter mw); + internal abstract void Read(MetadataReader mr); + + internal int GetLength(MetadataWriter md) + { + return RowCount * GetRowSize(new RowSizeCalc(md)); + } + + protected abstract int GetRowSize(RowSizeCalc rsc); + + protected sealed class RowSizeCalc + { + private readonly MetadataWriter mw; + private int size; + + internal RowSizeCalc(MetadataWriter mw) + { + this.mw = mw; + } + + internal RowSizeCalc AddFixed(int size) + { + this.size += size; + return this; + } + + internal RowSizeCalc WriteStringIndex() + { + if (mw.bigStrings) + { + this.size += 4; + } + else + { + this.size += 2; + } + return this; + } + + internal RowSizeCalc WriteGuidIndex() + { + if (mw.bigGuids) + { + this.size += 4; + } + else + { + this.size += 2; + } + return this; + } + + internal RowSizeCalc WriteBlobIndex() + { + if (mw.bigBlobs) + { + this.size += 4; + } + else + { + this.size += 2; + } + return this; + } + + internal RowSizeCalc WriteTypeDefOrRef() + { + if (mw.bigTypeDefOrRef) + { + this.size += 4; + } + else + { + this.size += 2; + } + return this; + } + + internal RowSizeCalc WriteField() + { + if (mw.bigField) + { + size += 4; + } + else + { + size += 2; + } + return this; + } + + internal RowSizeCalc WriteMethodDef() + { + if (mw.bigMethodDef) + { + this.size += 4; + } + else + { + this.size += 2; + } + return this; + } + + internal RowSizeCalc WriteParam() + { + if (mw.bigParam) + { + this.size += 4; + } + else + { + this.size += 2; + } + return this; + } + + internal RowSizeCalc WriteResolutionScope() + { + if (mw.bigResolutionScope) + { + this.size += 4; + } + else + { + this.size += 2; + } + return this; + } + + internal RowSizeCalc WriteMemberRefParent() + { + if (mw.bigMemberRefParent) + { + this.size += 4; + } + else + { + this.size += 2; + } + return this; + } + + internal RowSizeCalc WriteHasCustomAttribute() + { + if (mw.bigHasCustomAttribute) + { + size += 4; + } + else + { + size += 2; + } + return this; + } + + internal RowSizeCalc WriteCustomAttributeType() + { + if (mw.bigCustomAttributeType) + { + this.size += 4; + } + else + { + this.size += 2; + } + return this; + } + + internal RowSizeCalc WriteHasConstant() + { + if (mw.bigHasConstant) + { + size += 4; + } + else + { + size += 2; + } + return this; + } + + internal RowSizeCalc WriteTypeDef() + { + if (mw.bigTypeDef) + { + this.size += 4; + } + else + { + this.size += 2; + } + return this; + } + + internal RowSizeCalc WriteMethodDefOrRef() + { + if (mw.bigMethodDefOrRef) + { + this.size += 4; + } + else + { + this.size += 2; + } + return this; + } + + internal RowSizeCalc WriteEvent() + { + if (mw.bigEvent) + { + this.size += 4; + } + else + { + this.size += 2; + } + return this; + } + + internal RowSizeCalc WriteProperty() + { + if (mw.bigProperty) + { + this.size += 4; + } + else + { + this.size += 2; + } + return this; + } + + internal RowSizeCalc WriteHasSemantics() + { + if (mw.bigHasSemantics) + { + this.size += 4; + } + else + { + this.size += 2; + } + return this; + } + + internal RowSizeCalc WriteImplementation() + { + if (mw.bigImplementation) + { + this.size += 4; + } + else + { + this.size += 2; + } + return this; + } + + internal RowSizeCalc WriteTypeOrMethodDef() + { + if (mw.bigTypeOrMethodDef) + { + this.size += 4; + } + else + { + this.size += 2; + } + return this; + } + + internal RowSizeCalc WriteGenericParam() + { + if (mw.bigGenericParam) + { + this.size += 4; + } + else + { + this.size += 2; + } + return this; + } + + internal RowSizeCalc WriteHasDeclSecurity() + { + if (mw.bigHasDeclSecurity) + { + this.size += 4; + } + else + { + this.size += 2; + } + return this; + } + + internal RowSizeCalc WriteMemberForwarded() + { + if (mw.bigMemberForwarded) + { + this.size += 4; + } + else + { + this.size += 2; + } + return this; + } + + internal RowSizeCalc WriteModuleRef() + { + if (mw.bigModuleRef) + { + this.size += 4; + } + else + { + this.size += 2; + } + return this; + } + + internal RowSizeCalc WriteHasFieldMarshal() + { + if (mw.bigHasFieldMarshal) + { + this.size += 4; + } + else + { + this.size += 2; + } + return this; + } + + internal int Value + { + get { return size; } + } + } + } + + abstract class Table : Table + { + internal T[] records = Empty.Array; + protected int rowCount; + + internal sealed override int RowCount + { + get { return rowCount; } + set { rowCount = value; records = new T[value]; } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + throw new InvalidOperationException(); + } + + internal int AddRecord(T newRecord) + { + if (rowCount == records.Length) + { + Array.Resize(ref records, Math.Max(16, records.Length * 2)); + } + records[rowCount++] = newRecord; + return rowCount; + } + + internal int AddVirtualRecord() + { + return ++rowCount; + } + + internal override void Write(MetadataWriter mw) + { + throw new InvalidOperationException(); + } + } + + abstract class SortedTable : Table + where T : SortedTable.IRecord + { + internal interface IRecord + { + int SortKey { get; } + int FilterKey { get; } + } + + internal struct Enumerable + { + private readonly SortedTable table; + private readonly int token; + + internal Enumerable(SortedTable table, int token) + { + this.table = table; + this.token = token; + } + + public Enumerator GetEnumerator() + { + T[] records = table.records; + if (!table.Sorted) + { + return new Enumerator(records, table.RowCount - 1, -1, token); + } + int index = BinarySearch(records, table.RowCount, token & 0xFFFFFF); + if (index < 0) + { + return new Enumerator(null, 0, 1, -1); + } + int start = index; + while (start > 0 && (records[start - 1].FilterKey & 0xFFFFFF) == (token & 0xFFFFFF)) + { + start--; + } + int end = index; + int max = table.RowCount - 1; + while (end < max && (records[end + 1].FilterKey & 0xFFFFFF) == (token & 0xFFFFFF)) + { + end++; + } + return new Enumerator(records, end, start - 1, token); + } + + private static int BinarySearch(T[] records, int length, int maskedToken) + { + int min = 0; + int max = length - 1; + while (min <= max) + { + int mid = min + ((max - min) / 2); + int maskedValue = records[mid].FilterKey & 0xFFFFFF; + if (maskedToken == maskedValue) + { + return mid; + } + else if (maskedToken < maskedValue) + { + max = mid - 1; + } + else + { + min = mid + 1; + } + } + return -1; + } + } + + internal struct Enumerator + { + private readonly T[] records; + private readonly int token; + private readonly int max; + private int index; + + internal Enumerator(T[] records, int max, int index, int token) + { + this.records = records; + this.token = token; + this.max = max; + this.index = index; + } + + public int Current + { + get { return index; } + } + + public bool MoveNext() + { + while (index < max) + { + index++; + if (records[index].FilterKey == token) + { + return true; + } + } + return false; + } + } + + internal Enumerable Filter(int token) + { + return new Enumerable(this, token); + } + + protected void Sort() + { + ulong[] map = new ulong[rowCount]; + for (uint i = 0; i < map.Length; i++) + { + map[i] = ((ulong)records[i].SortKey << 32) | i; + } + Array.Sort(map); + T[] newRecords = new T[rowCount]; + for (int i = 0; i < map.Length; i++) + { + newRecords[i] = records[(int)map[i]]; + } + records = newRecords; + } + } + + sealed class ModuleTable : Table + { + internal const int Index = 0x00; + + internal struct Record + { + internal short Generation; + internal int Name; // -> StringHeap + internal int Mvid; // -> GuidHeap + internal int EncId; // -> GuidHeap + internal int EncBaseId; // -> GuidHeap + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Generation = mr.ReadInt16(); + records[i].Name = mr.ReadStringIndex(); + records[i].Mvid = mr.ReadGuidIndex(); + records[i].EncId = mr.ReadGuidIndex(); + records[i].EncBaseId = mr.ReadGuidIndex(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.Write(records[i].Generation); + mw.WriteStringIndex(records[i].Name); + mw.WriteGuidIndex(records[i].Mvid); + mw.WriteGuidIndex(records[i].EncId); + mw.WriteGuidIndex(records[i].EncBaseId); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .AddFixed(2) + .WriteStringIndex() + .WriteGuidIndex() + .WriteGuidIndex() + .WriteGuidIndex() + .Value; + } + + internal void Add(short generation, int name, int mvid, int encid, int encbaseid) + { + Record record = new Record(); + record.Generation = generation; + record.Name = name; + record.Mvid = mvid; + record.EncId = encid; + record.EncBaseId = encbaseid; + AddRecord(record); + } + } + + sealed class TypeRefTable : Table + { + internal const int Index = 0x01; + + internal struct Record + { + internal int ResolutionScope; + internal int TypeName; + internal int TypeNamespace; + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].ResolutionScope = mr.ReadResolutionScope(); + records[i].TypeName = mr.ReadStringIndex(); + records[i].TypeNamespace = mr.ReadStringIndex(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.WriteResolutionScope(records[i].ResolutionScope); + mw.WriteStringIndex(records[i].TypeName); + mw.WriteStringIndex(records[i].TypeNamespace); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .WriteResolutionScope() + .WriteStringIndex() + .WriteStringIndex() + .Value; + } + + internal void Fixup(ModuleBuilder moduleBuilder) + { + for (int i = 0; i < rowCount; i++) + { + moduleBuilder.FixupPseudoToken(ref records[i].ResolutionScope); + } + } + } + + sealed class TypeDefTable : Table + { + internal const int Index = 0x02; + + internal struct Record + { + internal int Flags; + internal int TypeName; + internal int TypeNamespace; + internal int Extends; + internal int FieldList; + internal int MethodList; + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Flags = mr.ReadInt32(); + records[i].TypeName = mr.ReadStringIndex(); + records[i].TypeNamespace = mr.ReadStringIndex(); + records[i].Extends = mr.ReadTypeDefOrRef(); + records[i].FieldList = mr.ReadField(); + records[i].MethodList = mr.ReadMethodDef(); + } + } + + internal override void Write(MetadataWriter mw) + { + mw.ModuleBuilder.WriteTypeDefTable(mw); + } + + internal int AllocToken() + { + return 0x02000000 + AddVirtualRecord(); + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .AddFixed(4) + .WriteStringIndex() + .WriteStringIndex() + .WriteTypeDefOrRef() + .WriteField() + .WriteMethodDef() + .Value; + } + } + + sealed class FieldPtrTable : Table + { + internal const int Index = 0x03; + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i] = mr.ReadField(); + } + } + } + + sealed class FieldTable : Table + { + internal const int Index = 0x04; + + internal struct Record + { + internal short Flags; + internal int Name; + internal int Signature; + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Flags = mr.ReadInt16(); + records[i].Name = mr.ReadStringIndex(); + records[i].Signature = mr.ReadBlobIndex(); + } + } + + internal override void Write(MetadataWriter mw) + { + mw.ModuleBuilder.WriteFieldTable(mw); + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .AddFixed(2) + .WriteStringIndex() + .WriteBlobIndex() + .Value; + } + } + + sealed class MethodPtrTable : Table + { + internal const int Index = 0x05; + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i] = mr.ReadMethodDef(); + } + } + } + + sealed class MethodDefTable : Table + { + internal const int Index = 0x06; + private int baseRVA; + + internal struct Record + { + internal int RVA; + internal short ImplFlags; + internal short Flags; + internal int Name; + internal int Signature; + internal int ParamList; + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].RVA = mr.ReadInt32(); + records[i].ImplFlags = mr.ReadInt16(); + records[i].Flags = mr.ReadInt16(); + records[i].Name = mr.ReadStringIndex(); + records[i].Signature = mr.ReadBlobIndex(); + records[i].ParamList = mr.ReadParam(); + } + } + + internal override void Write(MetadataWriter mw) + { + mw.ModuleBuilder.WriteMethodDefTable(baseRVA, mw); + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .AddFixed(8) + .WriteStringIndex() + .WriteBlobIndex() + .WriteParam() + .Value; + } + + internal void Fixup(TextSection code) + { + baseRVA = (int)code.MethodBodiesRVA; + } + } + + sealed class ParamPtrTable : Table + { + internal const int Index = 0x07; + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i] = mr.ReadParam(); + } + } + } + + sealed class ParamTable : Table + { + internal const int Index = 0x08; + + internal struct Record + { + internal short Flags; + internal short Sequence; + internal int Name; + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Flags = mr.ReadInt16(); + records[i].Sequence = mr.ReadInt16(); + records[i].Name = mr.ReadStringIndex(); + } + } + + internal override void Write(MetadataWriter mw) + { + mw.ModuleBuilder.WriteParamTable(mw); + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .AddFixed(4) + .WriteStringIndex() + .Value; + } + } + + sealed class InterfaceImplTable : SortedTable + { + internal const int Index = 0x09; + + internal struct Record : IRecord + { + internal int Class; + internal int Interface; + + int IRecord.SortKey + { + get { return Class; } + } + + int IRecord.FilterKey + { + get { return Class; } + } + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Class = mr.ReadTypeDef(); + records[i].Interface = mr.ReadTypeDefOrRef(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.WriteTypeDef(records[i].Class); + mw.WriteEncodedTypeDefOrRef(records[i].Interface); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .WriteTypeDef() + .WriteTypeDefOrRef() + .Value; + } + + internal void Fixup() + { + for (int i = 0; i < rowCount; i++) + { + int token = records[i].Interface; + switch (token >> 24) + { + case 0: + break; + case TypeDefTable.Index: + token = (token & 0xFFFFFF) << 2 | 0; + break; + case TypeRefTable.Index: + token = (token & 0xFFFFFF) << 2 | 1; + break; + case TypeSpecTable.Index: + token = (token & 0xFFFFFF) << 2 | 2; + break; + default: + throw new InvalidOperationException(); + } + records[i].Interface = token; + } + // LAMESPEC the CLI spec says that InterfaceImpl should be sorted by { Class, Interface }, + // but it appears to only be necessary to sort by Class (and csc emits InterfaceImpl records in + // source file order, so to be able to support round tripping, we need to retain ordering as well). + Sort(); + } + } + + sealed class MemberRefTable : Table + { + internal const int Index = 0x0A; + + internal struct Record + { + internal int Class; + internal int Name; + internal int Signature; + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Class = mr.ReadMemberRefParent(); + records[i].Name = mr.ReadStringIndex(); + records[i].Signature = mr.ReadBlobIndex(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.WriteMemberRefParent(records[i].Class); + mw.WriteStringIndex(records[i].Name); + mw.WriteBlobIndex(records[i].Signature); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .WriteMemberRefParent() + .WriteStringIndex() + .WriteBlobIndex() + .Value; + } + + internal int FindOrAddRecord(Record record) + { + for (int i = 0; i < rowCount; i++) + { + if (records[i].Class == record.Class + && records[i].Name == record.Name + && records[i].Signature == record.Signature) + { + return i + 1; + } + } + return AddRecord(record); + } + + internal void Fixup(ModuleBuilder moduleBuilder) + { + for (int i = 0; i < rowCount; i++) + { + moduleBuilder.FixupPseudoToken(ref records[i].Class); + } + } + } + + sealed class ConstantTable : SortedTable + { + internal const int Index = 0x0B; + + internal struct Record : IRecord + { + internal short Type; + internal int Parent; + internal int Value; + + int IRecord.SortKey + { + get { return EncodeHasConstant(Parent); } + } + + int IRecord.FilterKey + { + get { return Parent; } + } + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Type = mr.ReadInt16(); + records[i].Parent = mr.ReadHasConstant(); + records[i].Value = mr.ReadBlobIndex(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.Write(records[i].Type); + mw.WriteHasConstant(records[i].Parent); + mw.WriteBlobIndex(records[i].Value); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .AddFixed(2) + .WriteHasConstant() + .WriteBlobIndex() + .Value; + } + + internal void Fixup(ModuleBuilder moduleBuilder) + { + for (int i = 0; i < rowCount; i++) + { + moduleBuilder.FixupPseudoToken(ref records[i].Parent); + } + Sort(); + } + + internal static int EncodeHasConstant(int token) + { + switch (token >> 24) + { + case FieldTable.Index: + return (token & 0xFFFFFF) << 2 | 0; + case ParamTable.Index: + return (token & 0xFFFFFF) << 2 | 1; + case PropertyTable.Index: + return (token & 0xFFFFFF) << 2 | 2; + default: + throw new InvalidOperationException(); + } + } + + internal object GetRawConstantValue(Module module, int parent) + { + foreach (int i in Filter(parent)) + { + ByteReader br = module.GetBlob(module.Constant.records[i].Value); + switch (module.Constant.records[i].Type) + { + // see ModuleBuilder.AddConstant for the encodings + case Signature.ELEMENT_TYPE_BOOLEAN: + return br.ReadByte() != 0; + case Signature.ELEMENT_TYPE_I1: + return br.ReadSByte(); + case Signature.ELEMENT_TYPE_I2: + return br.ReadInt16(); + case Signature.ELEMENT_TYPE_I4: + return br.ReadInt32(); + case Signature.ELEMENT_TYPE_I8: + return br.ReadInt64(); + case Signature.ELEMENT_TYPE_U1: + return br.ReadByte(); + case Signature.ELEMENT_TYPE_U2: + return br.ReadUInt16(); + case Signature.ELEMENT_TYPE_U4: + return br.ReadUInt32(); + case Signature.ELEMENT_TYPE_U8: + return br.ReadUInt64(); + case Signature.ELEMENT_TYPE_R4: + return br.ReadSingle(); + case Signature.ELEMENT_TYPE_R8: + return br.ReadDouble(); + case Signature.ELEMENT_TYPE_CHAR: + return br.ReadChar(); + case Signature.ELEMENT_TYPE_STRING: + { + char[] chars = new char[br.Length / 2]; + for (int j = 0; j < chars.Length; j++) + { + chars[j] = br.ReadChar(); + } + return new String(chars); + } + case Signature.ELEMENT_TYPE_CLASS: + if (br.ReadInt32() != 0) + { + throw new BadImageFormatException(); + } + return null; + default: + throw new BadImageFormatException(); + } + } + throw new InvalidOperationException(); + } + } + + sealed class CustomAttributeTable : SortedTable + { + internal const int Index = 0x0C; + + internal struct Record : IRecord + { + internal int Parent; + internal int Type; + internal int Value; + + int IRecord.SortKey + { + get { return EncodeHasCustomAttribute(Parent); } + } + + int IRecord.FilterKey + { + get { return Parent; } + } + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Parent = mr.ReadHasCustomAttribute(); + records[i].Type = mr.ReadCustomAttributeType(); + records[i].Value = mr.ReadBlobIndex(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.WriteHasCustomAttribute(records[i].Parent); + mw.WriteCustomAttributeType(records[i].Type); + mw.WriteBlobIndex(records[i].Value); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .WriteHasCustomAttribute() + .WriteCustomAttributeType() + .WriteBlobIndex() + .Value; + } + + internal void Fixup(ModuleBuilder moduleBuilder) + { + int[] genericParamFixup = moduleBuilder.GenericParam.GetIndexFixup(); + for (int i = 0; i < rowCount; i++) + { + moduleBuilder.FixupPseudoToken(ref records[i].Type); + moduleBuilder.FixupPseudoToken(ref records[i].Parent); + if (records[i].Parent >> 24 == GenericParamTable.Index) + { + records[i].Parent = (GenericParamTable.Index << 24) + genericParamFixup[(records[i].Parent & 0xFFFFFF) - 1] + 1; + } + } + Sort(); + } + + internal static int EncodeHasCustomAttribute(int token) + { + switch (token >> 24) + { + case MethodDefTable.Index: + return (token & 0xFFFFFF) << 5 | 0; + case FieldTable.Index: + return (token & 0xFFFFFF) << 5 | 1; + case TypeRefTable.Index: + return (token & 0xFFFFFF) << 5 | 2; + case TypeDefTable.Index: + return (token & 0xFFFFFF) << 5 | 3; + case ParamTable.Index: + return (token & 0xFFFFFF) << 5 | 4; + case InterfaceImplTable.Index: + return (token & 0xFFFFFF) << 5 | 5; + case MemberRefTable.Index: + return (token & 0xFFFFFF) << 5 | 6; + case ModuleTable.Index: + return (token & 0xFFFFFF) << 5 | 7; + // Permission (8) table doesn't exist in the spec + case PropertyTable.Index: + return (token & 0xFFFFFF) << 5 | 9; + case EventTable.Index: + return (token & 0xFFFFFF) << 5 | 10; + case StandAloneSigTable.Index: + return (token & 0xFFFFFF) << 5 | 11; + case ModuleRefTable.Index: + return (token & 0xFFFFFF) << 5 | 12; + case TypeSpecTable.Index: + return (token & 0xFFFFFF) << 5 | 13; + case AssemblyTable.Index: + return (token & 0xFFFFFF) << 5 | 14; + case AssemblyRefTable.Index: + return (token & 0xFFFFFF) << 5 | 15; + case FileTable.Index: + return (token & 0xFFFFFF) << 5 | 16; + case ExportedTypeTable.Index: + return (token & 0xFFFFFF) << 5 | 17; + case ManifestResourceTable.Index: + return (token & 0xFFFFFF) << 5 | 18; + case GenericParamTable.Index: + return (token & 0xFFFFFF) << 5 | 19; + default: + throw new InvalidOperationException(); + } + } + } + + sealed class FieldMarshalTable : SortedTable + { + internal const int Index = 0x0D; + + internal struct Record : IRecord + { + internal int Parent; + internal int NativeType; + + int IRecord.SortKey + { + get { return EncodeHasFieldMarshal(Parent); } + } + + int IRecord.FilterKey + { + get { return Parent; } + } + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Parent = mr.ReadHasFieldMarshal(); + records[i].NativeType = mr.ReadBlobIndex(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.WriteHasFieldMarshal(records[i].Parent); + mw.WriteBlobIndex(records[i].NativeType); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .WriteHasFieldMarshal() + .WriteBlobIndex() + .Value; + } + + internal void Fixup(ModuleBuilder moduleBuilder) + { + for (int i = 0; i < rowCount; i++) + { + records[i].Parent = moduleBuilder.ResolvePseudoToken(records[i].Parent); + } + Sort(); + } + + internal static int EncodeHasFieldMarshal(int token) + { + switch (token >> 24) + { + case FieldTable.Index: + return (token & 0xFFFFFF) << 1 | 0; + case ParamTable.Index: + return (token & 0xFFFFFF) << 1 | 1; + default: + throw new InvalidOperationException(); + } + } + } + + sealed class DeclSecurityTable : SortedTable + { + internal const int Index = 0x0E; + + internal struct Record : IRecord + { + internal short Action; + internal int Parent; + internal int PermissionSet; + + int IRecord.SortKey + { + get { return Parent; } + } + + int IRecord.FilterKey + { + get { return Parent; } + } + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Action = mr.ReadInt16(); + records[i].Parent = mr.ReadHasDeclSecurity(); + records[i].PermissionSet = mr.ReadBlobIndex(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.Write(records[i].Action); + mw.WriteHasDeclSecurity(records[i].Parent); + mw.WriteBlobIndex(records[i].PermissionSet); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .AddFixed(2) + .WriteHasDeclSecurity() + .WriteBlobIndex() + .Value; + } + + internal void Fixup(ModuleBuilder moduleBuilder) + { + for (int i = 0; i < rowCount; i++) + { + int token = records[i].Parent; + moduleBuilder.FixupPseudoToken(ref token); + // do the HasDeclSecurity encoding, so that we can sort the table + switch (token >> 24) + { + case TypeDefTable.Index: + token = (token & 0xFFFFFF) << 2 | 0; + break; + case MethodDefTable.Index: + token = (token & 0xFFFFFF) << 2 | 1; + break; + case AssemblyTable.Index: + token = (token & 0xFFFFFF) << 2 | 2; + break; + default: + throw new InvalidOperationException(); + } + records[i].Parent = token; + } + Sort(); + } + } + + sealed class ClassLayoutTable : SortedTable + { + internal const int Index = 0x0f; + + internal struct Record : IRecord + { + internal short PackingSize; + internal int ClassSize; + internal int Parent; + + int IRecord.SortKey + { + get { return Parent; } + } + + int IRecord.FilterKey + { + get { return Parent; } + } + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].PackingSize = mr.ReadInt16(); + records[i].ClassSize = mr.ReadInt32(); + records[i].Parent = mr.ReadTypeDef(); + } + } + + internal override void Write(MetadataWriter mw) + { + Sort(); + for (int i = 0; i < rowCount; i++) + { + mw.Write(records[i].PackingSize); + mw.Write(records[i].ClassSize); + mw.WriteTypeDef(records[i].Parent); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .AddFixed(6) + .WriteTypeDef() + .Value; + } + } + + sealed class FieldLayoutTable : SortedTable + { + internal const int Index = 0x10; + + internal struct Record : IRecord + { + internal int Offset; + internal int Field; + + int IRecord.SortKey + { + get { return Field; } + } + + int IRecord.FilterKey + { + get { return Field; } + } + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Offset = mr.ReadInt32(); + records[i].Field = mr.ReadField(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.Write(records[i].Offset); + mw.WriteField(records[i].Field); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .AddFixed(4) + .WriteField() + .Value; + } + + internal void Fixup(ModuleBuilder moduleBuilder) + { + for (int i = 0; i < rowCount; i++) + { + records[i].Field = moduleBuilder.ResolvePseudoToken(records[i].Field) & 0xFFFFFF; + } + Sort(); + } + } + + sealed class StandAloneSigTable : Table + { + internal const int Index = 0x11; + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i] = mr.ReadBlobIndex(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.WriteBlobIndex(records[i]); + } + } + + protected override int GetRowSize(Table.RowSizeCalc rsc) + { + return rsc.WriteBlobIndex().Value; + } + + internal int FindOrAddRecord(int blob) + { + for (int i = 0; i < rowCount; i++) + { + if (records[i] == blob) + { + return i + 1; + } + } + return AddRecord(blob); + } + } + + sealed class EventMapTable : SortedTable + { + internal const int Index = 0x12; + + internal struct Record : IRecord + { + internal int Parent; + internal int EventList; + + int IRecord.SortKey + { + get { return Parent; } + } + + int IRecord.FilterKey + { + get { return Parent; } + } + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Parent = mr.ReadTypeDef(); + records[i].EventList = mr.ReadEvent(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.WriteTypeDef(records[i].Parent); + mw.WriteEvent(records[i].EventList); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .WriteTypeDef() + .WriteEvent() + .Value; + } + } + + sealed class EventPtrTable : Table + { + internal const int Index = 0x13; + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i] = mr.ReadEvent(); + } + } + } + + sealed class EventTable : Table + { + internal const int Index = 0x14; + + internal struct Record + { + internal short EventFlags; + internal int Name; + internal int EventType; + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].EventFlags = mr.ReadInt16(); + records[i].Name = mr.ReadStringIndex(); + records[i].EventType = mr.ReadTypeDefOrRef(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.Write(records[i].EventFlags); + mw.WriteStringIndex(records[i].Name); + mw.WriteTypeDefOrRef(records[i].EventType); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .AddFixed(2) + .WriteStringIndex() + .WriteTypeDefOrRef() + .Value; + } + } + + sealed class PropertyMapTable : SortedTable + { + internal const int Index = 0x15; + + internal struct Record : IRecord + { + internal int Parent; + internal int PropertyList; + + int IRecord.SortKey + { + get { return Parent; } + } + + int IRecord.FilterKey + { + get { return Parent; } + } + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Parent = mr.ReadTypeDef(); + records[i].PropertyList = mr.ReadProperty(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.WriteTypeDef(records[i].Parent); + mw.WriteProperty(records[i].PropertyList); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .WriteTypeDef() + .WriteProperty() + .Value; + } + } + + sealed class PropertyPtrTable : Table + { + internal const int Index = 0x16; + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i] = mr.ReadProperty(); + } + } + } + + sealed class PropertyTable : Table + { + internal const int Index = 0x17; + + internal struct Record + { + internal short Flags; + internal int Name; + internal int Type; + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Flags = mr.ReadInt16(); + records[i].Name = mr.ReadStringIndex(); + records[i].Type = mr.ReadBlobIndex(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.Write(records[i].Flags); + mw.WriteStringIndex(records[i].Name); + mw.WriteBlobIndex(records[i].Type); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .AddFixed(2) + .WriteStringIndex() + .WriteBlobIndex() + .Value; + } + } + + sealed class MethodSemanticsTable : SortedTable + { + internal const int Index = 0x18; + + // semantics + internal const short Setter = 0x0001; + internal const short Getter = 0x0002; + internal const short Other = 0x0004; + internal const short AddOn = 0x0008; + internal const short RemoveOn = 0x0010; + internal const short Fire = 0x0020; + + internal struct Record : IRecord + { + internal short Semantics; + internal int Method; + internal int Association; + + int IRecord.SortKey + { + get { return Association; } + } + + int IRecord.FilterKey + { + get { return Association; } + } + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Semantics = mr.ReadInt16(); + records[i].Method = mr.ReadMethodDef(); + records[i].Association = mr.ReadHasSemantics(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.Write(records[i].Semantics); + mw.WriteMethodDef(records[i].Method); + mw.WriteHasSemantics(records[i].Association); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .AddFixed(2) + .WriteMethodDef() + .WriteHasSemantics() + .Value; + } + + internal void Fixup(ModuleBuilder moduleBuilder) + { + for (int i = 0; i < rowCount; i++) + { + moduleBuilder.FixupPseudoToken(ref records[i].Method); + int token = records[i].Association; + // do the HasSemantics encoding, so that we can sort the table + switch (token >> 24) + { + case EventTable.Index: + token = (token & 0xFFFFFF) << 1 | 0; + break; + case PropertyTable.Index: + token = (token & 0xFFFFFF) << 1 | 1; + break; + default: + throw new InvalidOperationException(); + } + records[i].Association = token; + } + Sort(); + } + + internal MethodInfo GetMethod(Module module, int token, bool nonPublic, short semantics) + { + foreach (int i in Filter(token)) + { + if ((records[i].Semantics & semantics) != 0) + { + MethodBase method = module.ResolveMethod((MethodDefTable.Index << 24) + records[i].Method); + if (nonPublic || method.IsPublic) + { + return (MethodInfo)method; + } + } + } + return null; + } + + internal MethodInfo[] GetMethods(Module module, int token, bool nonPublic, short semantics) + { + List methods = new List(); + foreach (int i in Filter(token)) + { + if ((records[i].Semantics & semantics) != 0) + { + MethodInfo method = (MethodInfo)module.ResolveMethod((MethodDefTable.Index << 24) + records[i].Method); + if (nonPublic || method.IsPublic) + { + methods.Add(method); + } + } + } + return methods.ToArray(); + } + + internal void ComputeFlags(Module module, int token, out bool isPublic, out bool isNonPrivate, out bool isStatic) + { + isPublic = false; + isNonPrivate = false; + isStatic = false; + foreach (int i in Filter(token)) + { + MethodBase method = module.ResolveMethod((MethodDefTable.Index << 24) + records[i].Method); + isPublic |= method.IsPublic; + isNonPrivate |= (method.Attributes & MethodAttributes.MemberAccessMask) > MethodAttributes.Private; + isStatic |= method.IsStatic; + } + } + } + + sealed class MethodImplTable : SortedTable + { + internal const int Index = 0x19; + + internal struct Record : IRecord + { + internal int Class; + internal int MethodBody; + internal int MethodDeclaration; + + int IRecord.SortKey + { + get { return Class; } + } + + int IRecord.FilterKey + { + get { return Class; } + } + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Class = mr.ReadTypeDef(); + records[i].MethodBody = mr.ReadMethodDefOrRef(); + records[i].MethodDeclaration = mr.ReadMethodDefOrRef(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.WriteTypeDef(records[i].Class); + mw.WriteMethodDefOrRef(records[i].MethodBody); + mw.WriteMethodDefOrRef(records[i].MethodDeclaration); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .WriteTypeDef() + .WriteMethodDefOrRef() + .WriteMethodDefOrRef() + .Value; + } + + internal void Fixup(ModuleBuilder moduleBuilder) + { + for (int i = 0; i < rowCount; i++) + { + moduleBuilder.FixupPseudoToken(ref records[i].MethodBody); + moduleBuilder.FixupPseudoToken(ref records[i].MethodDeclaration); + } + Sort(); + } + } + + sealed class ModuleRefTable : Table + { + internal const int Index = 0x1A; + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i] = mr.ReadStringIndex(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.WriteStringIndex(records[i]); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .WriteStringIndex() + .Value; + } + + internal int FindOrAddRecord(int str) + { + for (int i = 0; i < rowCount; i++) + { + if (records[i] == str) + { + return i + 1; + } + } + return AddRecord(str); + } + } + + sealed class TypeSpecTable : Table + { + internal const int Index = 0x1B; + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i] = mr.ReadBlobIndex(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.WriteBlobIndex(records[i]); + } + } + + protected override int GetRowSize(Table.RowSizeCalc rsc) + { + return rsc.WriteBlobIndex().Value; + } + } + + sealed class ImplMapTable : SortedTable + { + internal const int Index = 0x1C; + + internal struct Record : IRecord + { + internal short MappingFlags; + internal int MemberForwarded; + internal int ImportName; + internal int ImportScope; + + int IRecord.SortKey + { + get { return MemberForwarded; } + } + + int IRecord.FilterKey + { + get { return MemberForwarded; } + } + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].MappingFlags = mr.ReadInt16(); + records[i].MemberForwarded = mr.ReadMemberForwarded(); + records[i].ImportName = mr.ReadStringIndex(); + records[i].ImportScope = mr.ReadModuleRef(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.Write(records[i].MappingFlags); + mw.WriteMemberForwarded(records[i].MemberForwarded); + mw.WriteStringIndex(records[i].ImportName); + mw.WriteModuleRef(records[i].ImportScope); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .AddFixed(2) + .WriteMemberForwarded() + .WriteStringIndex() + .WriteModuleRef() + .Value; + } + + internal void Fixup(ModuleBuilder moduleBuilder) + { + for (int i = 0; i < rowCount; i++) + { + moduleBuilder.FixupPseudoToken(ref records[i].MemberForwarded); + } + Sort(); + } + } + + sealed class FieldRVATable : SortedTable + { + internal const int Index = 0x1D; + + internal struct Record : IRecord + { + internal int RVA; // we set the high bit to signify that the RVA is in the CIL stream (instead of .sdata) + internal int Field; + + int IRecord.SortKey + { + get { return Field; } + } + + int IRecord.FilterKey + { + get { return Field; } + } + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].RVA = mr.ReadInt32(); + records[i].Field = mr.ReadField(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.Write(records[i].RVA); + mw.WriteField(records[i].Field); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .AddFixed(4) + .WriteField() + .Value; + } + + internal void Fixup(ModuleBuilder moduleBuilder, int sdataRVA, int cilRVA) + { + for (int i = 0; i < rowCount; i++) + { + if (records[i].RVA < 0) + { + records[i].RVA = (records[i].RVA & 0x7fffffff) + cilRVA; + } + else + { + records[i].RVA += sdataRVA; + } + moduleBuilder.FixupPseudoToken(ref records[i].Field); + } + Sort(); + } + } + + sealed class AssemblyTable : Table + { + internal const int Index = 0x20; + + internal struct Record + { + internal int HashAlgId; + internal ushort MajorVersion; + internal ushort MinorVersion; + internal ushort BuildNumber; + internal ushort RevisionNumber; + internal int Flags; + internal int PublicKey; + internal int Name; + internal int Culture; + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].HashAlgId = mr.ReadInt32(); + records[i].MajorVersion = mr.ReadUInt16(); + records[i].MinorVersion = mr.ReadUInt16(); + records[i].BuildNumber = mr.ReadUInt16(); + records[i].RevisionNumber = mr.ReadUInt16(); + records[i].Flags = mr.ReadInt32(); + records[i].PublicKey = mr.ReadBlobIndex(); + records[i].Name = mr.ReadStringIndex(); + records[i].Culture = mr.ReadStringIndex(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.Write(records[i].HashAlgId); + mw.Write(records[i].MajorVersion); + mw.Write(records[i].MinorVersion); + mw.Write(records[i].BuildNumber); + mw.Write(records[i].RevisionNumber); + mw.Write(records[i].Flags); + mw.WriteBlobIndex(records[i].PublicKey); + mw.WriteStringIndex(records[i].Name); + mw.WriteStringIndex(records[i].Culture); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .AddFixed(16) + .WriteBlobIndex() + .WriteStringIndex() + .WriteStringIndex() + .Value; + } + } + + sealed class AssemblyRefTable : Table + { + internal const int Index = 0x23; + + internal struct Record + { + internal ushort MajorVersion; + internal ushort MinorVersion; + internal ushort BuildNumber; + internal ushort RevisionNumber; + internal int Flags; + internal int PublicKeyOrToken; + internal int Name; + internal int Culture; + internal int HashValue; + } + + internal int FindOrAddRecord(Record rec) + { + for (int i = 0; i < rowCount; i++) + { + // note that we ignore HashValue here! + if (records[i].Name == rec.Name + && records[i].MajorVersion == rec.MajorVersion + && records[i].MinorVersion == rec.MinorVersion + && records[i].BuildNumber == rec.BuildNumber + && records[i].RevisionNumber == rec.RevisionNumber + && records[i].Flags == rec.Flags + && records[i].PublicKeyOrToken == rec.PublicKeyOrToken + && records[i].Culture == rec.Culture + ) + { + return i + 1; + } + } + return AddRecord(rec); + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].MajorVersion = mr.ReadUInt16(); + records[i].MinorVersion = mr.ReadUInt16(); + records[i].BuildNumber = mr.ReadUInt16(); + records[i].RevisionNumber = mr.ReadUInt16(); + records[i].Flags = mr.ReadInt32(); + records[i].PublicKeyOrToken = mr.ReadBlobIndex(); + records[i].Name = mr.ReadStringIndex(); + records[i].Culture = mr.ReadStringIndex(); + records[i].HashValue = mr.ReadBlobIndex(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.Write(records[i].MajorVersion); + mw.Write(records[i].MinorVersion); + mw.Write(records[i].BuildNumber); + mw.Write(records[i].RevisionNumber); + mw.Write(records[i].Flags); + mw.WriteBlobIndex(records[i].PublicKeyOrToken); + mw.WriteStringIndex(records[i].Name); + mw.WriteStringIndex(records[i].Culture); + mw.WriteBlobIndex(records[i].HashValue); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .AddFixed(12) + .WriteBlobIndex() + .WriteStringIndex() + .WriteStringIndex() + .WriteBlobIndex() + .Value; + } + } + + sealed class FileTable : Table + { + internal const int Index = 0x26; + + internal struct Record + { + internal int Flags; + internal int Name; + internal int HashValue; + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Flags = mr.ReadInt32(); + records[i].Name = mr.ReadStringIndex(); + records[i].HashValue = mr.ReadBlobIndex(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.Write(records[i].Flags); + mw.WriteStringIndex(records[i].Name); + mw.WriteBlobIndex(records[i].HashValue); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .AddFixed(4) + .WriteStringIndex() + .WriteBlobIndex() + .Value; + } + } + + sealed class ExportedTypeTable : Table + { + internal const int Index = 0x27; + + internal struct Record + { + internal int Flags; + internal int TypeDefId; + internal int TypeName; + internal int TypeNamespace; + internal int Implementation; + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Flags = mr.ReadInt32(); + records[i].TypeDefId = mr.ReadInt32(); + records[i].TypeName = mr.ReadStringIndex(); + records[i].TypeNamespace = mr.ReadStringIndex(); + records[i].Implementation = mr.ReadImplementation(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.Write(records[i].Flags); + mw.Write(records[i].TypeDefId); + mw.WriteStringIndex(records[i].TypeName); + mw.WriteStringIndex(records[i].TypeNamespace); + mw.WriteImplementation(records[i].Implementation); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .AddFixed(8) + .WriteStringIndex() + .WriteStringIndex() + .WriteImplementation() + .Value; + } + + internal int FindOrAddRecord(Record rec) + { + for (int i = 0; i < rowCount; i++) + { + if (records[i].Implementation == rec.Implementation + && records[i].TypeName == rec.TypeName + && records[i].TypeNamespace == rec.TypeNamespace) + { + return i + 1; + } + } + return AddRecord(rec); + } + + internal void Fixup(ModuleBuilder moduleBuilder) + { + for (int i = 0; i < rowCount; i++) + { + moduleBuilder.FixupPseudoToken(ref records[i].Implementation); + } + } + } + + sealed class ManifestResourceTable : Table + { + internal const int Index = 0x28; + + internal struct Record + { + internal int Offset; + internal int Flags; + internal int Name; + internal int Implementation; + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Offset = mr.ReadInt32(); + records[i].Flags = mr.ReadInt32(); + records[i].Name = mr.ReadStringIndex(); + records[i].Implementation = mr.ReadImplementation(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.Write(records[i].Offset); + mw.Write(records[i].Flags); + mw.WriteStringIndex(records[i].Name); + mw.WriteImplementation(records[i].Implementation); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .AddFixed(8) + .WriteStringIndex() + .WriteImplementation() + .Value; + } + + internal void Fixup(ModuleBuilder moduleBuilder) + { + for (int i = 0; i < rowCount; i++) + { + moduleBuilder.FixupPseudoToken(ref records[i].Implementation); + } + } + } + + sealed class NestedClassTable : SortedTable + { + internal const int Index = 0x29; + + internal struct Record : IRecord + { + internal int NestedClass; + internal int EnclosingClass; + + int IRecord.SortKey + { + get { return NestedClass; } + } + + int IRecord.FilterKey + { + get { return NestedClass; } + } + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].NestedClass = mr.ReadTypeDef(); + records[i].EnclosingClass = mr.ReadTypeDef(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.WriteTypeDef(records[i].NestedClass); + mw.WriteTypeDef(records[i].EnclosingClass); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .WriteTypeDef() + .WriteTypeDef() + .Value; + } + + internal List GetNestedClasses(int enclosingClass) + { + List nestedClasses = new List(); + for (int i = 0; i < rowCount; i++) + { + if (records[i].EnclosingClass == enclosingClass) + { + nestedClasses.Add(records[i].NestedClass); + } + } + return nestedClasses; + } + } + + sealed class GenericParamTable : SortedTable, IComparer + { + internal const int Index = 0x2A; + + internal struct Record : IRecord + { + internal short Number; + internal short Flags; + internal int Owner; + internal int Name; + // not part of the table, we use it to be able to fixup the GenericParamConstraint table + internal int unsortedIndex; + + int IRecord.SortKey + { + get { return Owner; } + } + + int IRecord.FilterKey + { + get { return Owner; } + } + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Number = mr.ReadInt16(); + records[i].Flags = mr.ReadInt16(); + records[i].Owner = mr.ReadTypeOrMethodDef(); + records[i].Name = mr.ReadStringIndex(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.Write(records[i].Number); + mw.Write(records[i].Flags); + mw.WriteTypeOrMethodDef(records[i].Owner); + mw.WriteStringIndex(records[i].Name); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .AddFixed(4) + .WriteTypeOrMethodDef() + .WriteStringIndex() + .Value; + } + + internal void Fixup(ModuleBuilder moduleBuilder) + { + for (int i = 0; i < rowCount; i++) + { + int token = records[i].Owner; + moduleBuilder.FixupPseudoToken(ref token); + // do the TypeOrMethodDef encoding, so that we can sort the table + switch (token >> 24) + { + case TypeDefTable.Index: + records[i].Owner = (token & 0xFFFFFF) << 1 | 0; + break; + case MethodDefTable.Index: + records[i].Owner = (token & 0xFFFFFF) << 1 | 1; + break; + default: + throw new InvalidOperationException(); + } + records[i].unsortedIndex = i; + } + // FXBUG the unnecessary (IComparer) cast is a workaround for a .NET 2.0 C# compiler bug + Array.Sort(records, 0, rowCount, (IComparer)this); + } + + int IComparer.Compare(Record x, Record y) + { + if (x.Owner == y.Owner) + { + return x.Number == y.Number ? 0 : (x.Number > y.Number ? 1 : -1); + } + return x.Owner > y.Owner ? 1 : -1; + } + + internal void PatchAttribute(int token, GenericParameterAttributes genericParameterAttributes) + { + records[(token & 0xFFFFFF) - 1].Flags = (short)genericParameterAttributes; + } + + internal int[] GetIndexFixup() + { + int[] array = new int[rowCount]; + for (int i = 0; i < rowCount; i++) + { + array[records[i].unsortedIndex] = i; + } + return array; + } + + internal int FindFirstByOwner(int token) + { + foreach (int i in Filter(token)) + { + return i; + } + return -1; + } + } + + sealed class MethodSpecTable : Table + { + internal const int Index = 0x2B; + + internal struct Record + { + internal int Method; + internal int Instantiation; + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Method = mr.ReadMethodDefOrRef(); + records[i].Instantiation = mr.ReadBlobIndex(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.WriteMethodDefOrRef(records[i].Method); + mw.WriteBlobIndex(records[i].Instantiation); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .WriteMethodDefOrRef() + .WriteBlobIndex() + .Value; + } + + internal int FindOrAddRecord(Record record) + { + for (int i = 0; i < rowCount; i++) + { + if (records[i].Method == record.Method + && records[i].Instantiation == record.Instantiation) + { + return i + 1; + } + } + return AddRecord(record); + } + + internal void Fixup(ModuleBuilder moduleBuilder) + { + for (int i = 0; i < rowCount; i++) + { + moduleBuilder.FixupPseudoToken(ref records[i].Method); + } + } + } + + sealed class GenericParamConstraintTable : SortedTable + { + internal const int Index = 0x2C; + + internal struct Record : IRecord + { + internal int Owner; + internal int Constraint; + + int IRecord.SortKey + { + get { return Owner; } + } + + int IRecord.FilterKey + { + get { return Owner; } + } + } + + internal override void Read(MetadataReader mr) + { + for (int i = 0; i < records.Length; i++) + { + records[i].Owner = mr.ReadGenericParam(); + records[i].Constraint = mr.ReadTypeDefOrRef(); + } + } + + internal override void Write(MetadataWriter mw) + { + for (int i = 0; i < rowCount; i++) + { + mw.WriteGenericParam(records[i].Owner); + mw.WriteTypeDefOrRef(records[i].Constraint); + } + } + + protected override int GetRowSize(RowSizeCalc rsc) + { + return rsc + .WriteGenericParam() + .WriteTypeDefOrRef() + .Value; + } + + internal void Fixup(ModuleBuilder moduleBuilder) + { + int[] fixups = moduleBuilder.GenericParam.GetIndexFixup(); + for (int i = 0; i < rowCount; i++) + { + records[i].Owner = fixups[records[i].Owner - 1] + 1; + } + Sort(); + } + } +} diff --git a/reflect/MethodBase.cs b/reflect/MethodBase.cs new file mode 100644 index 0000000..f3810ec --- /dev/null +++ b/reflect/MethodBase.cs @@ -0,0 +1,168 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; + +namespace IKVM.Reflection +{ + public abstract class MethodBase : MemberInfo + { + // prevent external subclasses + internal MethodBase() + { + } + + internal abstract MethodSignature MethodSignature { get; } + internal abstract int ParameterCount { get; } + public abstract ParameterInfo[] GetParameters(); + public abstract MethodAttributes Attributes { get; } + public abstract MethodImplAttributes GetMethodImplementationFlags(); + public abstract MethodBody GetMethodBody(); + public abstract CallingConventions CallingConvention { get; } + public abstract int __MethodRVA { get; } + + public bool IsConstructor + { + get + { + if ((this.Attributes & MethodAttributes.RTSpecialName) != 0) + { + string name = this.Name; + return name == ConstructorInfo.ConstructorName || name == ConstructorInfo.TypeConstructorName; + } + return false; + } + } + + public bool IsStatic + { + get { return (Attributes & MethodAttributes.Static) != 0; } + } + + public bool IsVirtual + { + get { return (Attributes & MethodAttributes.Virtual) != 0; } + } + + public bool IsAbstract + { + get { return (Attributes & MethodAttributes.Abstract) != 0; } + } + + public bool IsFinal + { + get { return (Attributes & MethodAttributes.Final) != 0; } + } + + public bool IsPublic + { + get { return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public; } + } + + public bool IsFamily + { + get { return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Family; } + } + + public bool IsFamilyOrAssembly + { + get { return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem; } + } + + public bool IsAssembly + { + get { return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Assembly; } + } + + public bool IsFamilyAndAssembly + { + get { return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamANDAssem; } + } + + public bool IsPrivate + { + get { return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private; } + } + + public bool IsSpecialName + { + get { return (Attributes & MethodAttributes.SpecialName) != 0; } + } + + public bool IsHideBySig + { + get { return (Attributes & MethodAttributes.HideBySig) != 0; } + } + + public MethodImplAttributes MethodImplementationFlags + { + get { return GetMethodImplementationFlags(); } + } + + public virtual Type[] GetGenericArguments() + { + return Type.EmptyTypes; + } + + public virtual bool IsGenericMethod + { + get { return false; } + } + + public virtual bool IsGenericMethodDefinition + { + get { return false; } + } + + public virtual bool ContainsGenericParameters + { + get { return IsGenericMethodDefinition; } + } + + public virtual MethodBase __GetMethodOnTypeDefinition() + { + return this; + } + + // This goes to the (uninstantiated) MethodInfo on the (uninstantiated) Type. For constructors + // it also has the effect of removing the ConstructorInfo wrapper and returning the underlying MethodInfo. + internal abstract MethodInfo GetMethodOnTypeDefinition(); + + internal abstract int ImportTo(Emit.ModuleBuilder module); + + internal abstract MethodBase BindTypeParameters(Type type); + + internal sealed override bool BindingFlagsMatch(BindingFlags flags) + { + return BindingFlagsMatch(IsPublic, flags, BindingFlags.Public, BindingFlags.NonPublic) + && BindingFlagsMatch(IsStatic, flags, BindingFlags.Static, BindingFlags.Instance); + } + + internal sealed override bool BindingFlagsMatchInherited(BindingFlags flags) + { + return (Attributes & MethodAttributes.MemberAccessMask) > MethodAttributes.Private + && BindingFlagsMatch(IsPublic, flags, BindingFlags.Public, BindingFlags.NonPublic) + && BindingFlagsMatch(IsStatic, flags, BindingFlags.Static | BindingFlags.FlattenHierarchy, BindingFlags.Instance); + } + } +} diff --git a/reflect/MethodBody.cs b/reflect/MethodBody.cs new file mode 100644 index 0000000..b39571e --- /dev/null +++ b/reflect/MethodBody.cs @@ -0,0 +1,163 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using IKVM.Reflection.Reader; +using System.IO; + +namespace IKVM.Reflection +{ + public sealed class MethodBody + { + private readonly IList exceptionClauses; + private readonly IList locals; + private readonly bool initLocals; + private readonly int maxStack; + private readonly int localVarSigTok; + private byte[] body; + + internal MethodBody(ModuleReader module, int rva, IGenericContext context) + { + const byte CorILMethod_TinyFormat = 0x02; + const byte CorILMethod_FatFormat = 0x03; + const byte CorILMethod_MoreSects = 0x08; + const byte CorILMethod_InitLocals = 0x10; + const byte CorILMethod_Sect_EHTable = 0x01; + const byte CorILMethod_Sect_FatFormat = 0x40; + const byte CorILMethod_Sect_MoreSects = 0x80; + + List exceptionClauses = new List(); + List locals = new List(); + Stream stream = module.GetStream(); + module.SeekRVA(rva); + BinaryReader br = new BinaryReader(stream); + byte b = br.ReadByte(); + if ((b & 3) == CorILMethod_TinyFormat) + { + initLocals = true; + body = br.ReadBytes(b >> 2); + maxStack = 8; + } + else if ((b & 3) == CorILMethod_FatFormat) + { + initLocals = (b & CorILMethod_InitLocals) != 0; + short flagsAndSize = (short)(b | (br.ReadByte() << 8)); + if ((flagsAndSize >> 12) != 3) + { + throw new BadImageFormatException("Fat format method header size should be 3"); + } + maxStack = br.ReadUInt16(); + int codeLength = br.ReadInt32(); + localVarSigTok = br.ReadInt32(); + body = br.ReadBytes(codeLength); + if ((b & CorILMethod_MoreSects) != 0) + { + stream.Position = (stream.Position + 3) & ~3; + int hdr = br.ReadInt32(); + if ((hdr & CorILMethod_Sect_MoreSects) != 0 || (hdr & CorILMethod_Sect_EHTable) == 0) + { + throw new NotImplementedException(); + } + else if ((hdr & CorILMethod_Sect_FatFormat) != 0) + { + int count = ComputeExceptionCount((hdr >> 8) & 0xFFFFFF, 24); + for (int i = 0; i < count; i++) + { + int flags = br.ReadInt32(); + int tryOffset = br.ReadInt32(); + int tryLength = br.ReadInt32(); + int handlerOffset = br.ReadInt32(); + int handlerLength = br.ReadInt32(); + int classTokenOrFilterOffset = br.ReadInt32(); + exceptionClauses.Add(new ExceptionHandlingClause(module, flags, tryOffset, tryLength, handlerOffset, handlerLength, classTokenOrFilterOffset, context)); + } + } + else + { + int count = ComputeExceptionCount((hdr >> 8) & 0xFF, 12); + for (int i = 0; i < count; i++) + { + int flags = br.ReadUInt16(); + int tryOffset = br.ReadUInt16(); + int tryLength = br.ReadByte(); + int handlerOffset = br.ReadUInt16(); + int handlerLength = br.ReadByte(); + int classTokenOrFilterOffset = br.ReadInt32(); + exceptionClauses.Add(new ExceptionHandlingClause(module, flags, tryOffset, tryLength, handlerOffset, handlerLength, classTokenOrFilterOffset, context)); + } + } + } + if (localVarSigTok != 0) + { + ByteReader sig = module.GetStandAloneSig((localVarSigTok & 0xFFFFFF) - 1); + Signature.ReadLocalVarSig(module, sig, context, locals); + } + } + else + { + throw new BadImageFormatException(); + } + this.exceptionClauses = exceptionClauses.AsReadOnly(); + this.locals = locals.AsReadOnly(); + } + + private static int ComputeExceptionCount(int size, int itemLength) + { + // LAMESPEC according to the spec, the count should be calculated as "(size - 4) / itemLength", + // FXBUG but to workaround a VB compiler bug that specifies the size incorrectly, + // we do a truncating division instead. + return size / itemLength; + } + + public IList ExceptionHandlingClauses + { + get { return exceptionClauses; } + } + + public bool InitLocals + { + get { return initLocals; } + } + + public IList LocalVariables + { + get { return locals; } + } + + public byte[] GetILAsByteArray() + { + return body; + } + + public int LocalSignatureMetadataToken + { + get { return localVarSigTok; } + } + + public int MaxStackSize + { + get { return maxStack; } + } + } +} diff --git a/reflect/MethodImplMap.cs b/reflect/MethodImplMap.cs new file mode 100644 index 0000000..bab829f --- /dev/null +++ b/reflect/MethodImplMap.cs @@ -0,0 +1,36 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; + +namespace IKVM.Reflection +{ + public struct __MethodImplMap + { + public Type TargetType; + public MethodInfo[] MethodBodies; + public MethodInfo[][] MethodDeclarations; + } +} diff --git a/reflect/MethodInfo.cs b/reflect/MethodInfo.cs new file mode 100644 index 0000000..6bbdb5f --- /dev/null +++ b/reflect/MethodInfo.cs @@ -0,0 +1,392 @@ +/* + Copyright (C) 2009-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; + +namespace IKVM.Reflection +{ + public abstract class MethodInfo : MethodBase, IGenericContext, IGenericBinder + { + // prevent external subclasses + internal MethodInfo() + { + } + + public sealed override MemberTypes MemberType + { + get { return MemberTypes.Method; } + } + + public abstract Type ReturnType { get; } + public abstract ParameterInfo ReturnParameter { get; } + + public virtual MethodInfo MakeGenericMethod(params Type[] typeArguments) + { + throw new NotSupportedException(this.GetType().FullName); + } + + public virtual MethodInfo GetGenericMethodDefinition() + { + throw new NotSupportedException(this.GetType().FullName); + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append(this.ReturnType.Name).Append(' ').Append(this.Name); + string sep; + if (this.IsGenericMethod) + { + sb.Append('['); + sep = ""; + foreach (Type arg in GetGenericArguments()) + { + sb.Append(sep).Append(arg); + sep = ", "; + } + sb.Append(']'); + } + sb.Append('('); + sep = ""; + foreach (ParameterInfo arg in GetParameters()) + { + sb.Append(sep).Append(arg.ParameterType); + sep = ", "; + } + sb.Append(')'); + return sb.ToString(); + } + + internal bool IsNewSlot + { + get { return (this.Attributes & MethodAttributes.NewSlot) != 0; } + } + + public MethodInfo GetBaseDefinition() + { + MethodInfo match = this; + if (match.IsVirtual) + { + for (Type type = this.DeclaringType.BaseType; type != null && !match.IsNewSlot; type = type.BaseType) + { + MethodInfo method = type.FindMethod(this.Name, this.MethodSignature) as MethodInfo; + if (method != null && method.IsVirtual) + { + match = method; + } + } + } + return match; + } + + public virtual MethodInfo[] __GetMethodImpls() + { + throw new NotSupportedException(); + } + + public bool __TryGetImplMap(out ImplMapFlags mappingFlags, out string importName, out string importScope) + { + return Module.__TryGetImplMap(GetCurrentToken(), out mappingFlags, out importName, out importScope); + } + + public ConstructorInfo __AsConstructorInfo() + { + return new ConstructorInfoImpl(this); + } + + Type IGenericContext.GetGenericTypeArgument(int index) + { + return this.DeclaringType.GetGenericTypeArgument(index); + } + + Type IGenericContext.GetGenericMethodArgument(int index) + { + return GetGenericMethodArgument(index); + } + + internal virtual Type GetGenericMethodArgument(int index) + { + throw new InvalidOperationException(); + } + + internal virtual int GetGenericMethodArgumentCount() + { + throw new InvalidOperationException(); + } + + internal override MethodInfo GetMethodOnTypeDefinition() + { + return this; + } + + Type IGenericBinder.BindTypeParameter(Type type) + { + return this.DeclaringType.GetGenericTypeArgument(type.GenericParameterPosition); + } + + Type IGenericBinder.BindMethodParameter(Type type) + { + return GetGenericMethodArgument(type.GenericParameterPosition); + } + + internal override MethodBase BindTypeParameters(Type type) + { + return new GenericMethodInstance(this.DeclaringType.BindTypeParameters(type), this, null); + } + + // This method is used by ILGenerator and exists to allow ArrayMethod to override it, + // because ArrayMethod doesn't have a working MethodAttributes property, so it needs + // to base the result of this on the CallingConvention. + internal virtual bool HasThis + { + get { return !IsStatic; } + } + + internal sealed override MemberInfo SetReflectedType(Type type) + { + return new MethodInfoWithReflectedType(type, this); + } + + internal sealed override List GetPseudoCustomAttributes(Type attributeType) + { + Module module = this.Module; + List list = new List(); + if ((this.Attributes & MethodAttributes.PinvokeImpl) != 0 + && (attributeType == null || attributeType.IsAssignableFrom(module.universe.System_Runtime_InteropServices_DllImportAttribute))) + { + ImplMapFlags flags; + string importName; + string importScope; + if (__TryGetImplMap(out flags, out importName, out importScope)) + { + list.Add(CustomAttributeData.CreateDllImportPseudoCustomAttribute(module, flags, importName, importScope, GetMethodImplementationFlags())); + } + } + if ((GetMethodImplementationFlags() & MethodImplAttributes.PreserveSig) != 0 + && (attributeType == null || attributeType.IsAssignableFrom(module.universe.System_Runtime_InteropServices_PreserveSigAttribute))) + { + list.Add(CustomAttributeData.CreatePreserveSigPseudoCustomAttribute(module)); + } + return list; + } + } + + sealed class MethodInfoWithReflectedType : MethodInfo + { + private readonly Type reflectedType; + private readonly MethodInfo method; + + internal MethodInfoWithReflectedType(Type reflectedType, MethodInfo method) + { + Debug.Assert(reflectedType != method.DeclaringType); + this.reflectedType = reflectedType; + this.method = method; + } + + public override bool Equals(object obj) + { + MethodInfoWithReflectedType other = obj as MethodInfoWithReflectedType; + return other != null + && other.reflectedType == reflectedType + && other.method == method; + } + + public override int GetHashCode() + { + return reflectedType.GetHashCode() ^ method.GetHashCode(); + } + + internal override MethodSignature MethodSignature + { + get { return method.MethodSignature; } + } + + internal override int ParameterCount + { + get { return method.ParameterCount; } + } + + public override ParameterInfo[] GetParameters() + { + ParameterInfo[] parameters = method.GetParameters(); + for (int i = 0; i < parameters.Length; i++) + { + parameters[i] = new ParameterInfoWrapper(this, parameters[i]); + } + return parameters; + } + + public override MethodAttributes Attributes + { + get { return method.Attributes; } + } + + public override MethodImplAttributes GetMethodImplementationFlags() + { + return method.GetMethodImplementationFlags(); + } + + public override MethodBody GetMethodBody() + { + return method.GetMethodBody(); + } + + public override CallingConventions CallingConvention + { + get { return method.CallingConvention; } + } + + public override int __MethodRVA + { + get { return method.__MethodRVA; } + } + + public override Type ReturnType + { + get { return method.ReturnType; } + } + + public override ParameterInfo ReturnParameter + { + get { return new ParameterInfoWrapper(this, method.ReturnParameter); } + } + + public override MethodInfo MakeGenericMethod(params Type[] typeArguments) + { + return SetReflectedType(method.MakeGenericMethod(typeArguments), reflectedType); + } + + public override MethodInfo GetGenericMethodDefinition() + { + return method.GetGenericMethodDefinition(); + } + + public override string ToString() + { + return method.ToString(); + } + + public override MethodInfo[] __GetMethodImpls() + { + return method.__GetMethodImpls(); + } + + internal override Type GetGenericMethodArgument(int index) + { + return method.GetGenericMethodArgument(index); + } + + internal override int GetGenericMethodArgumentCount() + { + return method.GetGenericMethodArgumentCount(); + } + + internal override MethodInfo GetMethodOnTypeDefinition() + { + return method.GetMethodOnTypeDefinition(); + } + + internal override bool HasThis + { + get { return method.HasThis; } + } + + public override Module Module + { + get { return method.Module; } + } + + public override Type DeclaringType + { + get { return method.DeclaringType; } + } + + public override Type ReflectedType + { + get { return reflectedType; } + } + + public override string Name + { + get { return method.Name; } + } + + internal override int ImportTo(IKVM.Reflection.Emit.ModuleBuilder module) + { + return method.ImportTo(module); + } + + public override MethodBase __GetMethodOnTypeDefinition() + { + return method.__GetMethodOnTypeDefinition(); + } + + public override bool __IsMissing + { + get { return method.__IsMissing; } + } + + internal override MethodBase BindTypeParameters(Type type) + { + return method.BindTypeParameters(type); + } + + public override bool ContainsGenericParameters + { + get { return method.ContainsGenericParameters; } + } + + public override Type[] GetGenericArguments() + { + return method.GetGenericArguments(); + } + + public override bool IsGenericMethod + { + get { return method.IsGenericMethod; } + } + + public override bool IsGenericMethodDefinition + { + get { return method.IsGenericMethodDefinition; } + } + + public override int MetadataToken + { + get { return method.MetadataToken; } + } + + internal override int GetCurrentToken() + { + return method.GetCurrentToken(); + } + + internal override bool IsBaked + { + get { return method.IsBaked; } + } + } +} diff --git a/reflect/MethodSignature.cs b/reflect/MethodSignature.cs new file mode 100644 index 0000000..189f13b --- /dev/null +++ b/reflect/MethodSignature.cs @@ -0,0 +1,505 @@ +/* + Copyright (C) 2009-2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using IKVM.Reflection.Reader; +using IKVM.Reflection.Writer; +using IKVM.Reflection.Emit; + +namespace IKVM.Reflection +{ + sealed class MethodSignature : Signature + { + private readonly Type returnType; + private readonly Type[] parameterTypes; + private readonly PackedCustomModifiers modifiers; + private readonly CallingConventions callingConvention; + private readonly int genericParamCount; + + internal MethodSignature(Type returnType, Type[] parameterTypes, PackedCustomModifiers modifiers, CallingConventions callingConvention, int genericParamCount) + { + this.returnType = returnType; + this.parameterTypes = parameterTypes; + this.modifiers = modifiers; + this.callingConvention = callingConvention; + this.genericParamCount = genericParamCount; + } + + public override bool Equals(object obj) + { + MethodSignature other = obj as MethodSignature; + return other != null + && other.callingConvention == callingConvention + && other.genericParamCount == genericParamCount + && other.returnType.Equals(returnType) + && Util.ArrayEquals(other.parameterTypes, parameterTypes) + && other.modifiers.Equals(modifiers); + } + + public override int GetHashCode() + { + return genericParamCount ^ 77 * (int)callingConvention + ^ 3 * returnType.GetHashCode() + ^ Util.GetHashCode(parameterTypes) * 5 + ^ modifiers.GetHashCode() * 55; + } + + private sealed class UnboundGenericMethodContext : IGenericContext + { + private readonly IGenericContext original; + + internal UnboundGenericMethodContext(IGenericContext original) + { + this.original = original; + } + + public Type GetGenericTypeArgument(int index) + { + return original.GetGenericTypeArgument(index); + } + + public Type GetGenericMethodArgument(int index) + { + return UnboundGenericMethodParameter.Make(index); + } + } + + internal static MethodSignature ReadSig(ModuleReader module, ByteReader br, IGenericContext context) + { + CallingConventions callingConvention; + int genericParamCount; + Type returnType; + Type[] parameterTypes; + byte flags = br.ReadByte(); + switch (flags & 7) + { + case DEFAULT: + callingConvention = CallingConventions.Standard; + break; + case VARARG: + callingConvention = CallingConventions.VarArgs; + break; + default: + throw new BadImageFormatException(); + } + if ((flags & HASTHIS) != 0) + { + callingConvention |= CallingConventions.HasThis; + } + if ((flags & EXPLICITTHIS) != 0) + { + callingConvention |= CallingConventions.ExplicitThis; + } + genericParamCount = 0; + if ((flags & GENERIC) != 0) + { + genericParamCount = br.ReadCompressedUInt(); + context = new UnboundGenericMethodContext(context); + } + int paramCount = br.ReadCompressedUInt(); + CustomModifiers[] modifiers = null; + PackedCustomModifiers.Pack(ref modifiers, 0, CustomModifiers.Read(module, br, context), paramCount + 1); + returnType = ReadRetType(module, br, context); + parameterTypes = new Type[paramCount]; + for (int i = 0; i < parameterTypes.Length; i++) + { + if ((callingConvention & CallingConventions.VarArgs) != 0 && br.PeekByte() == SENTINEL) + { + Array.Resize(ref parameterTypes, i); + if (modifiers != null) + { + Array.Resize(ref modifiers, i + 1); + } + break; + } + PackedCustomModifiers.Pack(ref modifiers, i + 1, CustomModifiers.Read(module, br, context), paramCount + 1); + parameterTypes[i] = ReadParam(module, br, context); + } + return new MethodSignature(returnType, parameterTypes, PackedCustomModifiers.Wrap(modifiers), callingConvention, genericParamCount); + } + + internal static __StandAloneMethodSig ReadStandAloneMethodSig(ModuleReader module, ByteReader br, IGenericContext context) + { + CallingConventions callingConvention = 0; + System.Runtime.InteropServices.CallingConvention unmanagedCallingConvention = 0; + bool unmanaged; + byte flags = br.ReadByte(); + switch (flags & 7) + { + case DEFAULT: + callingConvention = CallingConventions.Standard; + unmanaged = false; + break; + case 0x01: // C + unmanagedCallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl; + unmanaged = true; + break; + case 0x02: // STDCALL + unmanagedCallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall; + unmanaged = true; + break; + case 0x03: // THISCALL + unmanagedCallingConvention = System.Runtime.InteropServices.CallingConvention.ThisCall; + unmanaged = true; + break; + case 0x04: // FASTCALL + unmanagedCallingConvention = System.Runtime.InteropServices.CallingConvention.FastCall; + unmanaged = true; + break; + case VARARG: + callingConvention = CallingConventions.VarArgs; + unmanaged = false; + break; + default: + throw new BadImageFormatException(); + } + if ((flags & HASTHIS) != 0) + { + callingConvention |= CallingConventions.HasThis; + } + if ((flags & EXPLICITTHIS) != 0) + { + callingConvention |= CallingConventions.ExplicitThis; + } + if ((flags & GENERIC) != 0) + { + throw new BadImageFormatException(); + } + int paramCount = br.ReadCompressedUInt(); + CustomModifiers[] customModifiers = null; + PackedCustomModifiers.Pack(ref customModifiers, 0, CustomModifiers.Read(module, br, context), paramCount + 1); + Type returnType = ReadRetType(module, br, context); + List parameterTypes = new List(); + List optionalParameterTypes = new List(); + List curr = parameterTypes; + for (int i = 0; i < paramCount; i++) + { + if (br.PeekByte() == SENTINEL) + { + br.ReadByte(); + curr = optionalParameterTypes; + } + PackedCustomModifiers.Pack(ref customModifiers, i + 1, CustomModifiers.Read(module, br, context), paramCount + 1); + curr.Add(ReadParam(module, br, context)); + } + return new __StandAloneMethodSig(unmanaged, unmanagedCallingConvention, callingConvention, returnType, parameterTypes.ToArray(), optionalParameterTypes.ToArray(), PackedCustomModifiers.Wrap(customModifiers)); + } + + internal int GetParameterCount() + { + return parameterTypes.Length; + } + + internal Type GetParameterType(int index) + { + return parameterTypes[index]; + } + + internal Type GetReturnType(IGenericBinder binder) + { + return returnType.BindTypeParameters(binder); + } + + internal CustomModifiers GetReturnTypeCustomModifiers(IGenericBinder binder) + { + return modifiers.GetReturnTypeCustomModifiers().Bind(binder); + } + + internal Type GetParameterType(IGenericBinder binder, int index) + { + return parameterTypes[index].BindTypeParameters(binder); + } + + internal CustomModifiers GetParameterCustomModifiers(IGenericBinder binder, int index) + { + return modifiers.GetParameterCustomModifiers(index).Bind(binder); + } + + internal CallingConventions CallingConvention + { + get { return callingConvention; } + } + + internal int GenericParameterCount + { + get { return genericParamCount; } + } + + private sealed class Binder : IGenericBinder + { + private readonly Type declaringType; + private readonly Type[] methodArgs; + + internal Binder(Type declaringType, Type[] methodArgs) + { + this.declaringType = declaringType; + this.methodArgs = methodArgs; + } + + public Type BindTypeParameter(Type type) + { + return declaringType.GetGenericTypeArgument(type.GenericParameterPosition); + } + + public Type BindMethodParameter(Type type) + { + if (methodArgs == null) + { + return type; + } + return methodArgs[type.GenericParameterPosition]; + } + } + + internal MethodSignature Bind(Type type, Type[] methodArgs) + { + Binder binder = new Binder(type, methodArgs); + return new MethodSignature(returnType.BindTypeParameters(binder), + BindTypeParameters(binder, parameterTypes), + modifiers.Bind(binder), + callingConvention, genericParamCount); + } + + private sealed class Unbinder : IGenericBinder + { + internal static readonly Unbinder Instance = new Unbinder(); + + private Unbinder() + { + } + + public Type BindTypeParameter(Type type) + { + return type; + } + + public Type BindMethodParameter(Type type) + { + return UnboundGenericMethodParameter.Make(type.GenericParameterPosition); + } + } + + internal static MethodSignature MakeFromBuilder(Type returnType, Type[] parameterTypes, PackedCustomModifiers modifiers, CallingConventions callingConvention, int genericParamCount) + { + if (genericParamCount > 0) + { + returnType = returnType.BindTypeParameters(Unbinder.Instance); + parameterTypes = BindTypeParameters(Unbinder.Instance, parameterTypes); + modifiers = modifiers.Bind(Unbinder.Instance); + } + return new MethodSignature(returnType, parameterTypes, modifiers, callingConvention, genericParamCount); + } + + internal bool MatchParameterTypes(MethodSignature other) + { + return Util.ArrayEquals(other.parameterTypes, parameterTypes); + } + + internal bool MatchParameterTypes(Type[] types) + { + return Util.ArrayEquals(types, parameterTypes); + } + + internal override void WriteSig(ModuleBuilder module, ByteBuffer bb) + { + WriteSigImpl(module, bb, parameterTypes.Length); + } + + internal void WriteMethodRefSig(ModuleBuilder module, ByteBuffer bb, Type[] optionalParameterTypes, CustomModifiers[] customModifiers) + { + WriteSigImpl(module, bb, parameterTypes.Length + optionalParameterTypes.Length); + if (optionalParameterTypes.Length > 0) + { + bb.Write(SENTINEL); + for (int i = 0; i < optionalParameterTypes.Length; i++) + { + WriteCustomModifiers(module, bb, Util.NullSafeElementAt(customModifiers, i)); + WriteType(module, bb, optionalParameterTypes[i]); + } + } + } + + private void WriteSigImpl(ModuleBuilder module, ByteBuffer bb, int parameterCount) + { + byte first; + if ((callingConvention & CallingConventions.Any) == CallingConventions.VarArgs) + { + Debug.Assert(genericParamCount == 0); + first = VARARG; + } + else if (genericParamCount > 0) + { + first = GENERIC; + } + else + { + first = DEFAULT; + } + if ((callingConvention & CallingConventions.HasThis) != 0) + { + first |= HASTHIS; + } + if ((callingConvention & CallingConventions.ExplicitThis) != 0) + { + first |= EXPLICITTHIS; + } + bb.Write(first); + if (genericParamCount > 0) + { + bb.WriteCompressedUInt(genericParamCount); + } + bb.WriteCompressedUInt(parameterCount); + // RetType + WriteCustomModifiers(module, bb, modifiers.GetReturnTypeCustomModifiers()); + WriteType(module, bb, returnType); + // Param + for (int i = 0; i < parameterTypes.Length; i++) + { + WriteCustomModifiers(module, bb, modifiers.GetParameterCustomModifiers(i)); + WriteType(module, bb, parameterTypes[i]); + } + } + } + + struct PackedCustomModifiers + { + // element 0 is the return type, the rest are the parameters + private readonly CustomModifiers[] customModifiers; + + private PackedCustomModifiers(CustomModifiers[] customModifiers) + { + this.customModifiers = customModifiers; + } + + public override int GetHashCode() + { + return Util.GetHashCode(customModifiers); + } + + public override bool Equals(object obj) + { + PackedCustomModifiers? other = obj as PackedCustomModifiers?; + return other != null && Equals(other.Value); + } + + internal bool Equals(PackedCustomModifiers other) + { + return Util.ArrayEquals(customModifiers, other.customModifiers); + } + + internal CustomModifiers GetReturnTypeCustomModifiers() + { + if (customModifiers == null) + { + return new CustomModifiers(); + } + return customModifiers[0]; + } + + internal CustomModifiers GetParameterCustomModifiers(int index) + { + if (customModifiers == null) + { + return new CustomModifiers(); + } + return customModifiers[index + 1]; + } + + internal PackedCustomModifiers Bind(IGenericBinder binder) + { + if (customModifiers == null) + { + return new PackedCustomModifiers(); + } + CustomModifiers[] expanded = new CustomModifiers[customModifiers.Length]; + for (int i = 0; i < customModifiers.Length; i++) + { + expanded[i] = customModifiers[i].Bind(binder); + } + return new PackedCustomModifiers(expanded); + } + + internal bool ContainsMissingType + { + get + { + if (customModifiers != null) + { + for (int i = 0; i < customModifiers.Length; i++) + { + if (customModifiers[i].ContainsMissingType) + { + return true; + } + } + } + return false; + } + } + + // this method make a copy of the incoming arrays (where necessary) and returns a normalized modifiers array + internal static PackedCustomModifiers CreateFromExternal(Type[] returnOptional, Type[] returnRequired, Type[][] parameterOptional, Type[][] parameterRequired, int parameterCount) + { + CustomModifiers[] modifiers = null; + Pack(ref modifiers, 0, CustomModifiers.FromReqOpt(returnRequired, returnOptional), parameterCount + 1); + for (int i = 0; i < parameterCount; i++) + { + Pack(ref modifiers, i + 1, CustomModifiers.FromReqOpt(Util.NullSafeElementAt(parameterRequired, i), Util.NullSafeElementAt(parameterOptional, i)), parameterCount + 1); + } + return new PackedCustomModifiers(modifiers); + } + + internal static PackedCustomModifiers CreateFromExternal(CustomModifiers returnTypeCustomModifiers, CustomModifiers[] parameterTypeCustomModifiers, int parameterCount) + { + CustomModifiers[] customModifiers = null; + Pack(ref customModifiers, 0, returnTypeCustomModifiers, parameterCount + 1); + if (parameterTypeCustomModifiers != null) + { + for (int i = 0; i < parameterCount; i++) + { + Pack(ref customModifiers, i + 1, parameterTypeCustomModifiers[i], parameterCount + 1); + } + } + return new PackedCustomModifiers(customModifiers); + } + + internal static PackedCustomModifiers Wrap(CustomModifiers[] modifiers) + { + return new PackedCustomModifiers(modifiers); + } + + internal static void Pack(ref CustomModifiers[] array, int index, CustomModifiers mods, int count) + { + if (!mods.IsEmpty) + { + if (array == null) + { + array = new CustomModifiers[count]; + } + array[index] = mods; + } + } + } +} diff --git a/reflect/Missing.cs b/reflect/Missing.cs new file mode 100644 index 0000000..9510ded --- /dev/null +++ b/reflect/Missing.cs @@ -0,0 +1,1254 @@ +/* + Copyright (C) 2011-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace IKVM.Reflection +{ +#if !CORECLR + [Serializable] +#endif + public sealed class MissingAssemblyException : InvalidOperationException + { +#if !CORECLR + [NonSerialized] +#endif + private readonly MissingAssembly assembly; + + internal MissingAssemblyException(MissingAssembly assembly) + : base("Assembly '" + assembly.FullName + "' is a missing assembly and does not support the requested operation.") + { + this.assembly = assembly; + } + +#if !CORECLR + private MissingAssemblyException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) + : base(info, context) + { + } +#endif + + public Assembly Assembly + { + get { return assembly; } + } + } + +#if !CORECLR + [Serializable] +#endif + public sealed class MissingModuleException : InvalidOperationException + { +#if !CORECLR + [NonSerialized] +#endif + private readonly MissingModule module; + + internal MissingModuleException(MissingModule module) + : base("Module from missing assembly '" + module.Assembly.FullName + "' does not support the requested operation.") + { + this.module = module; + } + +#if !CORECLR + private MissingModuleException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) + : base(info, context) + { + } +#endif + + public Module Module + { + get { return module; } + } + } + +#if !CORECLR + [Serializable] +#endif + public sealed class MissingMemberException : InvalidOperationException + { +#if !CORECLR + [NonSerialized] +#endif + private readonly MemberInfo member; + + internal MissingMemberException(MemberInfo member) + : base("Member '" + member + "' is a missing member and does not support the requested operation.") + { + this.member = member; + } + +#if !CORECLR + private MissingMemberException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) + : base(info, context) + { + } +#endif + + public MemberInfo MemberInfo + { + get { return member; } + } + } + + public struct MissingGenericMethodBuilder + { + private readonly MissingMethod method; + + public MissingGenericMethodBuilder(Type declaringType, CallingConventions callingConvention, string name, int genericParameterCount) + { + method = new MissingMethod(declaringType, name, new MethodSignature(null, null, new PackedCustomModifiers(), callingConvention, genericParameterCount)); + } + + public Type[] GetGenericArguments() + { + return method.GetGenericArguments(); + } + + public void SetSignature(Type returnType, CustomModifiers returnTypeCustomModifiers, Type[] parameterTypes, CustomModifiers[] parameterTypeCustomModifiers) + { + method.signature = new MethodSignature( + returnType ?? method.Module.universe.System_Void, + Util.Copy(parameterTypes), + PackedCustomModifiers.CreateFromExternal(returnTypeCustomModifiers, parameterTypeCustomModifiers, parameterTypes.Length), + method.signature.CallingConvention, + method.signature.GenericParameterCount); + } + + [Obsolete("Please use SetSignature(Type, CustomModifiers, Type[], CustomModifiers[]) instead.")] + public void SetSignature(Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers) + { + method.signature = new MethodSignature( + returnType ?? method.Module.universe.System_Void, + Util.Copy(parameterTypes), + PackedCustomModifiers.CreateFromExternal(returnTypeOptionalCustomModifiers, returnTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers, parameterTypeRequiredCustomModifiers, parameterTypes.Length), + method.signature.CallingConvention, + method.signature.GenericParameterCount); + } + + public MethodInfo Finish() + { + return method; + } + } + + sealed class MissingAssembly : Assembly + { + private readonly MissingModule module; + + internal MissingAssembly(Universe universe, string name) + : base(universe) + { + module = new MissingModule(this, -1); + this.fullName = name; + } + + public override Type[] GetTypes() + { + throw new MissingAssemblyException(this); + } + + public override AssemblyName GetName() + { + return new AssemblyName(fullName); + } + + public override string ImageRuntimeVersion + { + get { throw new MissingAssemblyException(this); } + } + + public override Module ManifestModule + { + get { return module; } + } + + public override MethodInfo EntryPoint + { + get { throw new MissingAssemblyException(this); } + } + + public override string Location + { + get { throw new MissingAssemblyException(this); } + } + + public override AssemblyName[] GetReferencedAssemblies() + { + throw new MissingAssemblyException(this); + } + + public override Module[] GetModules(bool getResourceModules) + { + throw new MissingAssemblyException(this); + } + + public override Module[] GetLoadedModules(bool getResourceModules) + { + throw new MissingAssemblyException(this); + } + + public override Module GetModule(string name) + { + throw new MissingAssemblyException(this); + } + + public override string[] GetManifestResourceNames() + { + throw new MissingAssemblyException(this); + } + + public override ManifestResourceInfo GetManifestResourceInfo(string resourceName) + { + throw new MissingAssemblyException(this); + } + + public override System.IO.Stream GetManifestResourceStream(string resourceName) + { + throw new MissingAssemblyException(this); + } + + public override bool __IsMissing + { + get { return true; } + } + + internal override Type FindType(TypeName typeName) + { + return null; + } + + internal override Type FindTypeIgnoreCase(TypeName lowerCaseName) + { + return null; + } + + internal override IList GetCustomAttributesData(Type attributeType) + { + throw new MissingAssemblyException(this); + } + } + + sealed class MissingModule : NonPEModule + { + private readonly Assembly assembly; + private readonly int index; + + internal MissingModule(Assembly assembly, int index) + : base(assembly.universe) + { + this.assembly = assembly; + this.index = index; + } + + public override int MDStreamVersion + { + get { throw new MissingModuleException(this); } + } + + public override Assembly Assembly + { + get { return assembly; } + } + + public override string FullyQualifiedName + { + get { throw new MissingModuleException(this); } + } + + public override string Name + { + get + { + if (index == -1) + { + throw new MissingModuleException(this); + } + return assembly.ManifestModule.GetString(assembly.ManifestModule.File.records[index].Name); + } + } + + public override Guid ModuleVersionId + { + get { throw new MissingModuleException(this); } + } + + public override string ScopeName + { + get { throw new MissingModuleException(this); } + } + + internal override Type FindType(TypeName typeName) + { + return null; + } + + internal override Type FindTypeIgnoreCase(TypeName lowerCaseName) + { + return null; + } + + internal override void GetTypesImpl(System.Collections.Generic.List list) + { + throw new MissingModuleException(this); + } + + public override void __GetDataDirectoryEntry(int index, out int rva, out int length) + { + throw new MissingModuleException(this); + } + + public override IList __GetPlaceholderAssemblyCustomAttributes(bool multiple, bool security) + { + throw new MissingModuleException(this); + } + + public override long __RelativeVirtualAddressToFileOffset(int rva) + { + throw new MissingModuleException(this); + } + + public override __StandAloneMethodSig __ResolveStandAloneMethodSig(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) + { + throw new MissingModuleException(this); + } + + public override int __Subsystem + { + get { throw new MissingModuleException(this); } + } + + internal override void ExportTypes(int fileToken, IKVM.Reflection.Emit.ModuleBuilder manifestModule) + { + throw new MissingModuleException(this); + } + + public override void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine) + { + throw new MissingModuleException(this); + } + + public override bool __IsMissing + { + get { return true; } + } + + protected override Exception InvalidOperationException() + { + return new MissingModuleException(this); + } + + protected override Exception NotSupportedException() + { + return new MissingModuleException(this); + } + + protected override Exception ArgumentOutOfRangeException() + { + return new MissingModuleException(this); + } + + public override byte[] __ModuleHash + { + get + { + if (index == -1) + { + throw new MissingModuleException(this); + } + if (assembly.ManifestModule.File.records[index].HashValue == 0) + { + return null; + } + IKVM.Reflection.Reader.ByteReader br = assembly.ManifestModule.GetBlob(assembly.ManifestModule.File.records[index].HashValue); + return br.ReadBytes(br.Length); + } + } + } + + sealed class MissingType : Type + { + private readonly Module module; + private readonly Type declaringType; + private readonly string ns; + private readonly string name; + private Type[] typeArgs; + private int token; + private int flags; + private bool cyclicTypeForwarder; + + internal MissingType(Module module, Type declaringType, string ns, string name) + { + this.module = module; + this.declaringType = declaringType; + this.ns = ns; + this.name = name; + MarkKnownType(ns, name); + + // HACK we need to handle the Windows Runtime projected types that change from ValueType to Class or v.v. + if (WindowsRuntimeProjection.IsProjectedValueType(ns, name, module)) + { + typeFlags |= TypeFlags.ValueType; + } + else if (WindowsRuntimeProjection.IsProjectedReferenceType(ns, name, module)) + { + typeFlags |= TypeFlags.NotValueType; + } + } + + internal override MethodBase FindMethod(string name, MethodSignature signature) + { + MethodInfo method = new MissingMethod(this, name, signature); + if (name == ".ctor") + { + return new ConstructorInfoImpl(method); + } + return method; + } + + internal override FieldInfo FindField(string name, FieldSignature signature) + { + return new MissingField(this, name, signature); + } + + internal override Type FindNestedType(TypeName name) + { + return null; + } + + internal override Type FindNestedTypeIgnoreCase(TypeName lowerCaseName) + { + return null; + } + + public override bool __IsMissing + { + get { return true; } + } + + public override Type DeclaringType + { + get { return declaringType; } + } + + internal override TypeName TypeName + { + get { return new TypeName(ns, name); } + } + + public override string Name + { + get { return TypeNameParser.Escape(name); } + } + + public override string FullName + { + get { return GetFullName(); } + } + + public override Module Module + { + get { return module; } + } + + public override int MetadataToken + { + get { return token; } + } + + public override bool IsValueType + { + get + { + switch (typeFlags & (TypeFlags.ValueType | TypeFlags.NotValueType)) + { + case TypeFlags.ValueType: + return true; + case TypeFlags.NotValueType: + return false; + case TypeFlags.ValueType | TypeFlags.NotValueType: + if (WindowsRuntimeProjection.IsProjectedValueType(ns, name, module)) + { + typeFlags &= ~TypeFlags.NotValueType; + return true; + } + if (WindowsRuntimeProjection.IsProjectedReferenceType(ns, name, module)) + { + typeFlags &= ~TypeFlags.ValueType; + return false; + } + goto default; + default: + if (module.universe.ResolveMissingTypeIsValueType(this)) + { + typeFlags |= TypeFlags.ValueType; + } + else + { + typeFlags |= TypeFlags.NotValueType; + } + return (typeFlags & TypeFlags.ValueType) != 0; + } + } + } + + public override Type BaseType + { + get { throw new MissingMemberException(this); } + } + + public override TypeAttributes Attributes + { + get { throw new MissingMemberException(this); } + } + + public override Type[] __GetDeclaredTypes() + { + throw new MissingMemberException(this); + } + + public override Type[] __GetDeclaredInterfaces() + { + throw new MissingMemberException(this); + } + + public override MethodBase[] __GetDeclaredMethods() + { + throw new MissingMemberException(this); + } + + public override __MethodImplMap __GetMethodImplMap() + { + throw new MissingMemberException(this); + } + + public override FieldInfo[] __GetDeclaredFields() + { + throw new MissingMemberException(this); + } + + public override EventInfo[] __GetDeclaredEvents() + { + throw new MissingMemberException(this); + } + + public override PropertyInfo[] __GetDeclaredProperties() + { + throw new MissingMemberException(this); + } + + public override CustomModifiers __GetCustomModifiers() + { + throw new MissingMemberException(this); + } + + public override Type[] GetGenericArguments() + { + throw new MissingMemberException(this); + } + + public override CustomModifiers[] __GetGenericArgumentsCustomModifiers() + { + throw new MissingMemberException(this); + } + + public override bool __GetLayout(out int packingSize, out int typeSize) + { + throw new MissingMemberException(this); + } + + public override bool IsGenericType + { + get { throw new MissingMemberException(this); } + } + + public override bool IsGenericTypeDefinition + { + get { throw new MissingMemberException(this); } + } + + internal override Type GetGenericTypeArgument(int index) + { + if (typeArgs == null) + { + typeArgs = new Type[index + 1]; + } + else if (typeArgs.Length <= index) + { + Array.Resize(ref typeArgs, index + 1); + } + return typeArgs[index] ?? (typeArgs[index] = new MissingTypeParameter(this, index)); + } + + internal override Type BindTypeParameters(IGenericBinder binder) + { + return this; + } + + internal override Type SetMetadataTokenForMissing(int token, int flags) + { + this.token = token; + this.flags = flags; + return this; + } + + internal override Type SetCyclicTypeForwarder() + { + this.cyclicTypeForwarder = true; + return this; + } + + internal override bool IsBaked + { + get { throw new MissingMemberException(this); } + } + + public override bool __IsTypeForwarder + { + // CorTypeAttr.tdForwarder + get { return (flags & 0x00200000) != 0; } + } + + public override bool __IsCyclicTypeForwarder + { + get { return cyclicTypeForwarder; } + } + } + + sealed class MissingTypeParameter : IKVM.Reflection.Reader.TypeParameterType + { + private readonly MemberInfo owner; + private readonly int index; + + internal MissingTypeParameter(Type owner, int index) + : this(owner, index, Signature.ELEMENT_TYPE_VAR) + { + } + + internal MissingTypeParameter(MethodInfo owner, int index) + : this(owner, index, Signature.ELEMENT_TYPE_MVAR) + { + } + + private MissingTypeParameter(MemberInfo owner, int index, byte sigElementType) + : base(sigElementType) + { + this.owner = owner; + this.index = index; + } + + public override Module Module + { + get { return owner.Module; } + } + + public override string Name + { + get { return null; } + } + + public override int GenericParameterPosition + { + get { return index; } + } + + public override MethodBase DeclaringMethod + { + get { return owner as MethodBase; } + } + + public override Type DeclaringType + { + get { return owner as Type; } + } + + internal override Type BindTypeParameters(IGenericBinder binder) + { + if (owner is MethodBase) + { + return binder.BindMethodParameter(this); + } + else + { + return binder.BindTypeParameter(this); + } + } + + internal override bool IsBaked + { + get { return owner.IsBaked; } + } + } + + sealed class MissingMethod : MethodInfo + { + private readonly Type declaringType; + private readonly string name; + internal MethodSignature signature; + private MethodInfo forwarder; + private Type[] typeArgs; + + internal MissingMethod(Type declaringType, string name, MethodSignature signature) + { + this.declaringType = declaringType; + this.name = name; + this.signature = signature; + } + + private MethodInfo Forwarder + { + get + { + MethodInfo method = TryGetForwarder(); + if (method == null) + { + throw new MissingMemberException(this); + } + return method; + } + } + + private MethodInfo TryGetForwarder() + { + if (forwarder == null && !declaringType.__IsMissing) + { + MethodBase mb = declaringType.FindMethod(name, signature); + ConstructorInfo ci = mb as ConstructorInfo; + if (ci != null) + { + forwarder = ci.GetMethodInfo(); + } + else + { + forwarder = (MethodInfo)mb; + } + } + return forwarder; + } + + public override bool __IsMissing + { + get { return TryGetForwarder() == null; } + } + + public override Type ReturnType + { + get { return signature.GetReturnType(this); } + } + + public override ParameterInfo ReturnParameter + { + get { return new ParameterInfoImpl(this, -1); } + } + + internal override MethodSignature MethodSignature + { + get { return signature; } + } + + internal override int ParameterCount + { + get { return signature.GetParameterCount(); } + } + + private sealed class ParameterInfoImpl : ParameterInfo + { + private readonly MissingMethod method; + private readonly int index; + + internal ParameterInfoImpl(MissingMethod method, int index) + { + this.method = method; + this.index = index; + } + + private ParameterInfo Forwarder + { + get { return index == -1 ? method.Forwarder.ReturnParameter : method.Forwarder.GetParameters()[index]; } + } + + public override string Name + { + get { return Forwarder.Name; } + } + + public override Type ParameterType + { + get { return index == -1 ? method.signature.GetReturnType(method) : method.signature.GetParameterType(method, index); } + } + + public override ParameterAttributes Attributes + { + get { return Forwarder.Attributes; } + } + + public override int Position + { + get { return index; } + } + + public override object RawDefaultValue + { + get { return Forwarder.RawDefaultValue; } + } + + public override CustomModifiers __GetCustomModifiers() + { + return index == -1 + ? method.signature.GetReturnTypeCustomModifiers(method) + : method.signature.GetParameterCustomModifiers(method, index); + } + + public override bool __TryGetFieldMarshal(out FieldMarshal fieldMarshal) + { + return Forwarder.__TryGetFieldMarshal(out fieldMarshal); + } + + public override MemberInfo Member + { + get { return method; } + } + + public override int MetadataToken + { + get { return Forwarder.MetadataToken; } + } + + internal override Module Module + { + get { return method.Module; } + } + + public override string ToString() + { + return Forwarder.ToString(); + } + } + + public override ParameterInfo[] GetParameters() + { + ParameterInfo[] parameters = new ParameterInfo[signature.GetParameterCount()]; + for (int i = 0; i < parameters.Length; i++) + { + parameters[i] = new ParameterInfoImpl(this, i); + } + return parameters; + } + + public override MethodAttributes Attributes + { + get { return Forwarder.Attributes; } + } + + public override MethodImplAttributes GetMethodImplementationFlags() + { + return Forwarder.GetMethodImplementationFlags(); + } + + public override MethodBody GetMethodBody() + { + return Forwarder.GetMethodBody(); + } + + public override int __MethodRVA + { + get { return Forwarder.__MethodRVA; } + } + + public override CallingConventions CallingConvention + { + get { return signature.CallingConvention; } + } + + internal override int ImportTo(IKVM.Reflection.Emit.ModuleBuilder module) + { + MethodInfo method = TryGetForwarder(); + if (method != null) + { + return method.ImportTo(module); + } + return module.ImportMethodOrField(declaringType, this.Name, this.MethodSignature); + } + + public override string Name + { + get { return name; } + } + + public override Type DeclaringType + { + get { return declaringType.IsModulePseudoType ? null : declaringType; } + } + + public override Module Module + { + get { return declaringType.Module; } + } + + public override bool Equals(object obj) + { + MissingMethod other = obj as MissingMethod; + return other != null + && other.declaringType == declaringType + && other.name == name + && other.signature.Equals(signature); + } + + public override int GetHashCode() + { + return declaringType.GetHashCode() ^ name.GetHashCode() ^ signature.GetHashCode(); + } + + internal override MethodBase BindTypeParameters(Type type) + { + MethodInfo forwarder = TryGetForwarder(); + if (forwarder != null) + { + return forwarder.BindTypeParameters(type); + } + return new GenericMethodInstance(type, this, null); + } + + public override bool ContainsGenericParameters + { + get { return Forwarder.ContainsGenericParameters; } + } + + public override Type[] GetGenericArguments() + { + MethodInfo method = TryGetForwarder(); + if (method != null) + { + return Forwarder.GetGenericArguments(); + } + if (typeArgs == null) + { + typeArgs = new Type[signature.GenericParameterCount]; + for (int i = 0; i < typeArgs.Length; i++) + { + typeArgs[i] = new MissingTypeParameter(this, i); + } + } + return Util.Copy(typeArgs); + } + + internal override Type GetGenericMethodArgument(int index) + { + return GetGenericArguments()[index]; + } + + internal override int GetGenericMethodArgumentCount() + { + return Forwarder.GetGenericMethodArgumentCount(); + } + + public override MethodInfo GetGenericMethodDefinition() + { + return Forwarder.GetGenericMethodDefinition(); + } + + internal override MethodInfo GetMethodOnTypeDefinition() + { + return Forwarder.GetMethodOnTypeDefinition(); + } + + internal override bool HasThis + { + get { return (signature.CallingConvention & (CallingConventions.HasThis | CallingConventions.ExplicitThis)) == CallingConventions.HasThis; } + } + + public override bool IsGenericMethod + { + get { return IsGenericMethodDefinition; } + } + + public override bool IsGenericMethodDefinition + { + get { return signature.GenericParameterCount != 0; } + } + + public override MethodInfo MakeGenericMethod(params Type[] typeArguments) + { + MethodInfo method = TryGetForwarder(); + if (method != null) + { + return method.MakeGenericMethod(typeArguments); + } + return new GenericMethodInstance(declaringType, this, typeArguments); + } + + public override int MetadataToken + { + get { return Forwarder.MetadataToken; } + } + + internal override int GetCurrentToken() + { + return Forwarder.GetCurrentToken(); + } + + internal override bool IsBaked + { + get { return Forwarder.IsBaked; } + } + } + + sealed class MissingField : FieldInfo + { + private readonly Type declaringType; + private readonly string name; + private readonly FieldSignature signature; + private FieldInfo forwarder; + + internal MissingField(Type declaringType, string name, FieldSignature signature) + { + this.declaringType = declaringType; + this.name = name; + this.signature = signature; + } + + private FieldInfo Forwarder + { + get + { + FieldInfo field = TryGetForwarder(); + if (field == null) + { + throw new MissingMemberException(this); + } + return field; + } + } + + private FieldInfo TryGetForwarder() + { + if (forwarder == null && !declaringType.__IsMissing) + { + forwarder = declaringType.FindField(name, signature); + } + return forwarder; + } + + public override bool __IsMissing + { + get { return TryGetForwarder() == null; } + } + + public override FieldAttributes Attributes + { + get { return Forwarder.Attributes; } + } + + public override void __GetDataFromRVA(byte[] data, int offset, int length) + { + Forwarder.__GetDataFromRVA(data, offset, length); + } + + public override int __FieldRVA + { + get { return Forwarder.__FieldRVA; } + } + + public override bool __TryGetFieldOffset(out int offset) + { + return Forwarder.__TryGetFieldOffset(out offset); + } + + public override object GetRawConstantValue() + { + return Forwarder.GetRawConstantValue(); + } + + internal override FieldSignature FieldSignature + { + get { return signature; } + } + + internal override int ImportTo(IKVM.Reflection.Emit.ModuleBuilder module) + { + FieldInfo field = TryGetForwarder(); + if (field != null) + { + return field.ImportTo(module); + } + return module.ImportMethodOrField(declaringType, this.Name, this.FieldSignature); + } + + public override string Name + { + get { return name; } + } + + public override Type DeclaringType + { + get { return declaringType.IsModulePseudoType ? null : declaringType; } + } + + public override Module Module + { + get { return declaringType.Module; } + } + + internal override FieldInfo BindTypeParameters(Type type) + { + FieldInfo forwarder = TryGetForwarder(); + if (forwarder != null) + { + return forwarder.BindTypeParameters(type); + } + return new GenericFieldInstance(type, this); + } + + public override int MetadataToken + { + get { return Forwarder.MetadataToken; } + } + + public override bool Equals(object obj) + { + MissingField other = obj as MissingField; + return other != null + && other.declaringType == declaringType + && other.name == name + && other.signature.Equals(signature); + } + + public override int GetHashCode() + { + return declaringType.GetHashCode() ^ name.GetHashCode() ^ signature.GetHashCode(); + } + + public override string ToString() + { + return this.FieldType.Name + " " + this.Name; + } + + internal override int GetCurrentToken() + { + return Forwarder.GetCurrentToken(); + } + + internal override bool IsBaked + { + get { return Forwarder.IsBaked; } + } + } + + // NOTE this is currently only used by CustomAttributeData (because there is no other way to refer to a property) + sealed class MissingProperty : PropertyInfo + { + private readonly Type declaringType; + private readonly string name; + private readonly PropertySignature signature; + + internal MissingProperty(Type declaringType, string name, PropertySignature signature) + { + this.declaringType = declaringType; + this.name = name; + this.signature = signature; + } + + public override PropertyAttributes Attributes + { + get { throw new MissingMemberException(this); } + } + + public override bool CanRead + { + get { throw new MissingMemberException(this); } + } + + public override bool CanWrite + { + get { throw new MissingMemberException(this); } + } + + public override MethodInfo GetGetMethod(bool nonPublic) + { + throw new MissingMemberException(this); + } + + public override MethodInfo GetSetMethod(bool nonPublic) + { + throw new MissingMemberException(this); + } + + public override MethodInfo[] GetAccessors(bool nonPublic) + { + throw new MissingMemberException(this); + } + + public override object GetRawConstantValue() + { + throw new MissingMemberException(this); + } + + internal override bool IsPublic + { + get { throw new MissingMemberException(this); } + } + + internal override bool IsNonPrivate + { + get { throw new MissingMemberException(this); } + } + + internal override bool IsStatic + { + get { throw new MissingMemberException(this); } + } + + internal override PropertySignature PropertySignature + { + get { return signature; } + } + + public override string Name + { + get { return name; } + } + + public override Type DeclaringType + { + get { return declaringType; } + } + + public override Module Module + { + get { return declaringType.Module; } + } + + internal override bool IsBaked + { + get { return declaringType.IsBaked; } + } + + internal override int GetCurrentToken() + { + throw new MissingMemberException(this); + } + } +} diff --git a/reflect/Module.cs b/reflect/Module.cs new file mode 100644 index 0000000..d93dba5 --- /dev/null +++ b/reflect/Module.cs @@ -0,0 +1,726 @@ +/* + Copyright (C) 2009-2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using IKVM.Reflection.Metadata; +using IKVM.Reflection.Reader; + +namespace IKVM.Reflection +{ + public sealed class RawModule : IDisposable + { + private readonly ModuleReader module; + private readonly bool isManifestModule; + private bool imported; + + internal RawModule(ModuleReader module) + { + this.module = module; + this.isManifestModule = module.Assembly != null; + } + + public string Location + { + get { return module.FullyQualifiedName; } + } + + public bool IsManifestModule + { + get { return isManifestModule; } + } + + public Guid ModuleVersionId + { + get { return module.ModuleVersionId; } + } + + public string ImageRuntimeVersion + { + get { return module.__ImageRuntimeVersion; } + } + + public int MDStreamVersion + { + get { return module.MDStreamVersion; } + } + + private void CheckManifestModule() + { + if (!IsManifestModule) + { + throw new BadImageFormatException("Module does not contain a manifest"); + } + } + + public AssemblyName GetAssemblyName() + { + CheckManifestModule(); + return module.Assembly.GetName(); + } + + public AssemblyName[] GetReferencedAssemblies() + { + return module.__GetReferencedAssemblies(); + } + + public void Dispose() + { + if (!imported) + { + module.Dispose(); + } + } + + internal AssemblyReader ToAssembly() + { + if (imported) + { + throw new InvalidOperationException(); + } + imported = true; + return (AssemblyReader)module.Assembly; + } + + internal Module ToModule(Assembly assembly) + { + if (module.Assembly != null) + { + throw new InvalidOperationException(); + } + imported = true; + module.SetAssembly(assembly); + return module; + } + } + + public abstract class Module : ICustomAttributeProvider + { + internal readonly Universe universe; + internal readonly ModuleTable ModuleTable = new ModuleTable(); + internal readonly TypeRefTable TypeRef = new TypeRefTable(); + internal readonly TypeDefTable TypeDef = new TypeDefTable(); + internal readonly FieldPtrTable FieldPtr = new FieldPtrTable(); + internal readonly FieldTable Field = new FieldTable(); + internal readonly MemberRefTable MemberRef = new MemberRefTable(); + internal readonly ConstantTable Constant = new ConstantTable(); + internal readonly CustomAttributeTable CustomAttribute = new CustomAttributeTable(); + internal readonly FieldMarshalTable FieldMarshal = new FieldMarshalTable(); + internal readonly DeclSecurityTable DeclSecurity = new DeclSecurityTable(); + internal readonly ClassLayoutTable ClassLayout = new ClassLayoutTable(); + internal readonly FieldLayoutTable FieldLayout = new FieldLayoutTable(); + internal readonly ParamPtrTable ParamPtr = new ParamPtrTable(); + internal readonly ParamTable Param = new ParamTable(); + internal readonly InterfaceImplTable InterfaceImpl = new InterfaceImplTable(); + internal readonly StandAloneSigTable StandAloneSig = new StandAloneSigTable(); + internal readonly EventMapTable EventMap = new EventMapTable(); + internal readonly EventPtrTable EventPtr = new EventPtrTable(); + internal readonly EventTable Event = new EventTable(); + internal readonly PropertyMapTable PropertyMap = new PropertyMapTable(); + internal readonly PropertyPtrTable PropertyPtr = new PropertyPtrTable(); + internal readonly PropertyTable Property = new PropertyTable(); + internal readonly MethodSemanticsTable MethodSemantics = new MethodSemanticsTable(); + internal readonly MethodImplTable MethodImpl = new MethodImplTable(); + internal readonly ModuleRefTable ModuleRef = new ModuleRefTable(); + internal readonly TypeSpecTable TypeSpec = new TypeSpecTable(); + internal readonly ImplMapTable ImplMap = new ImplMapTable(); + internal readonly FieldRVATable FieldRVA = new FieldRVATable(); + internal readonly AssemblyTable AssemblyTable = new AssemblyTable(); + internal readonly AssemblyRefTable AssemblyRef = new AssemblyRefTable(); + internal readonly MethodPtrTable MethodPtr = new MethodPtrTable(); + internal readonly MethodDefTable MethodDef = new MethodDefTable(); + internal readonly NestedClassTable NestedClass = new NestedClassTable(); + internal readonly FileTable File = new FileTable(); + internal readonly ExportedTypeTable ExportedType = new ExportedTypeTable(); + internal readonly ManifestResourceTable ManifestResource = new ManifestResourceTable(); + internal readonly GenericParamTable GenericParam = new GenericParamTable(); + internal readonly MethodSpecTable MethodSpec = new MethodSpecTable(); + internal readonly GenericParamConstraintTable GenericParamConstraint = new GenericParamConstraintTable(); + + protected Module(Universe universe) + { + this.universe = universe; + } + + internal Table[] GetTables() + { + Table[] tables = new Table[64]; + tables[ModuleTable.Index] = ModuleTable; + tables[TypeRefTable.Index] = TypeRef; + tables[TypeDefTable.Index] = TypeDef; + tables[FieldPtrTable.Index] = FieldPtr; + tables[FieldTable.Index] = Field; + tables[MemberRefTable.Index] = MemberRef; + tables[ConstantTable.Index] = Constant; + tables[CustomAttributeTable.Index] = CustomAttribute; + tables[FieldMarshalTable.Index] = FieldMarshal; + tables[DeclSecurityTable.Index] = DeclSecurity; + tables[ClassLayoutTable.Index] = ClassLayout; + tables[FieldLayoutTable.Index] = FieldLayout; + tables[ParamPtrTable.Index] = ParamPtr; + tables[ParamTable.Index] = Param; + tables[InterfaceImplTable.Index] = InterfaceImpl; + tables[StandAloneSigTable.Index] = StandAloneSig; + tables[EventMapTable.Index] = EventMap; + tables[EventPtrTable.Index] = EventPtr; + tables[EventTable.Index] = Event; + tables[PropertyMapTable.Index] = PropertyMap; + tables[PropertyPtrTable.Index] = PropertyPtr; + tables[PropertyTable.Index] = Property; + tables[MethodSemanticsTable.Index] = MethodSemantics; + tables[MethodImplTable.Index] = MethodImpl; + tables[ModuleRefTable.Index] = ModuleRef; + tables[TypeSpecTable.Index] = TypeSpec; + tables[ImplMapTable.Index] = ImplMap; + tables[FieldRVATable.Index] = FieldRVA; + tables[AssemblyTable.Index] = AssemblyTable; + tables[AssemblyRefTable.Index] = AssemblyRef; + tables[MethodPtrTable.Index] = MethodPtr; + tables[MethodDefTable.Index] = MethodDef; + tables[NestedClassTable.Index] = NestedClass; + tables[FileTable.Index] = File; + tables[ExportedTypeTable.Index] = ExportedType; + tables[ManifestResourceTable.Index] = ManifestResource; + tables[GenericParamTable.Index] = GenericParam; + tables[MethodSpecTable.Index] = MethodSpec; + tables[GenericParamConstraintTable.Index] = GenericParamConstraint; + return tables; + } + + public virtual void __GetDataDirectoryEntry(int index, out int rva, out int length) + { + throw new NotSupportedException(); + } + + public virtual long __RelativeVirtualAddressToFileOffset(int rva) + { + throw new NotSupportedException(); + } + + public bool __GetSectionInfo(int rva, out string name, out int characteristics) + { + int virtualAddress; + int virtualSize; + int pointerToRawData; + int sizeOfRawData; + return __GetSectionInfo(rva, out name, out characteristics, out virtualAddress, out virtualSize, out pointerToRawData, out sizeOfRawData); + } + + public virtual bool __GetSectionInfo(int rva, out string name, out int characteristics, out int virtualAddress, out int virtualSize, out int pointerToRawData, out int sizeOfRawData) + { + throw new NotSupportedException(); + } + + public virtual int __ReadDataFromRVA(int rva, byte[] data, int offset, int length) + { + throw new NotSupportedException(); + } + + public virtual void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine) + { + throw new NotSupportedException(); + } + + public virtual int __Subsystem + { + get { throw new NotSupportedException(); } + } + + public FieldInfo GetField(string name) + { + return GetField(name, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly); + } + + public FieldInfo GetField(string name, BindingFlags bindingFlags) + { + return IsResource() ? null : GetModuleType().GetField(name, bindingFlags | BindingFlags.DeclaredOnly); + } + + public FieldInfo[] GetFields() + { + return GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly); + } + + public FieldInfo[] GetFields(BindingFlags bindingFlags) + { + return IsResource() ? Empty.Array : GetModuleType().GetFields(bindingFlags | BindingFlags.DeclaredOnly); + } + + public MethodInfo GetMethod(string name) + { + return IsResource() ? null : GetModuleType().GetMethod(name, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly); + } + + public MethodInfo GetMethod(string name, Type[] types) + { + return IsResource() ? null : GetModuleType().GetMethod(name, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly, null, types, null); + } + + public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConv, Type[] types, ParameterModifier[] modifiers) + { + return IsResource() ? null : GetModuleType().GetMethod(name, bindingAttr | BindingFlags.DeclaredOnly, binder, callConv, types, modifiers); + } + + public MethodInfo[] GetMethods() + { + return GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly); + } + + public MethodInfo[] GetMethods(BindingFlags bindingFlags) + { + return IsResource() ? Empty.Array : GetModuleType().GetMethods(bindingFlags | BindingFlags.DeclaredOnly); + } + + public ConstructorInfo __ModuleInitializer + { + get { return IsResource() ? null : GetModuleType().TypeInitializer; } + } + + public virtual byte[] ResolveSignature(int metadataToken) + { + throw new NotSupportedException(); + } + + public virtual __StandAloneMethodSig __ResolveStandAloneMethodSig(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) + { + throw new NotSupportedException(); + } + + public virtual CustomModifiers __ResolveTypeSpecCustomModifiers(int typeSpecToken, Type[] genericTypeArguments, Type[] genericMethodArguments) + { + throw new NotSupportedException(); + } + + public int MetadataToken + { + get { return IsResource() ? 0 : 1; } + } + + public abstract int MDStreamVersion { get ;} + public abstract Assembly Assembly { get; } + public abstract string FullyQualifiedName { get; } + public abstract string Name { get; } + public abstract Guid ModuleVersionId { get; } + public abstract MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments); + public abstract FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments); + public abstract MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments); + + public abstract string ResolveString(int metadataToken); + public abstract Type[] __ResolveOptionalParameterTypes(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments, out CustomModifiers[] customModifiers); + public abstract string ScopeName { get; } + + internal abstract void GetTypesImpl(List list); + + internal abstract Type FindType(TypeName name); + internal abstract Type FindTypeIgnoreCase(TypeName lowerCaseName); + + [Obsolete("Please use __ResolveOptionalParameterTypes(int, Type[], Type[], out CustomModifiers[]) instead.")] + public Type[] __ResolveOptionalParameterTypes(int metadataToken) + { + CustomModifiers[] dummy; + return __ResolveOptionalParameterTypes(metadataToken, null, null, out dummy); + } + + public Type GetType(string className) + { + return GetType(className, false, false); + } + + public Type GetType(string className, bool ignoreCase) + { + return GetType(className, false, ignoreCase); + } + + public Type GetType(string className, bool throwOnError, bool ignoreCase) + { + TypeNameParser parser = TypeNameParser.Parse(className, throwOnError); + if (parser.Error) + { + return null; + } + if (parser.AssemblyName != null) + { + if (throwOnError) + { + throw new ArgumentException("Type names passed to Module.GetType() must not specify an assembly."); + } + else + { + return null; + } + } + TypeName typeName = TypeName.Split(TypeNameParser.Unescape(parser.FirstNamePart)); + Type type = ignoreCase + ? FindTypeIgnoreCase(typeName.ToLowerInvariant()) + : FindType(typeName); + if (type == null && __IsMissing) + { + throw new MissingModuleException((MissingModule)this); + } + return parser.Expand(type, this, throwOnError, className, false, ignoreCase); + } + + public Type[] GetTypes() + { + List list = new List(); + GetTypesImpl(list); + return list.ToArray(); + } + + public Type[] FindTypes(TypeFilter filter, object filterCriteria) + { + List list = new List(); + foreach (Type type in GetTypes()) + { + if (filter(type, filterCriteria)) + { + list.Add(type); + } + } + return list.ToArray(); + } + + public virtual bool IsResource() + { + return false; + } + + public Type ResolveType(int metadataToken) + { + return ResolveType(metadataToken, null, null); + } + + internal sealed class GenericContext : IGenericContext + { + private readonly Type[] genericTypeArguments; + private readonly Type[] genericMethodArguments; + + internal GenericContext(Type[] genericTypeArguments, Type[] genericMethodArguments) + { + this.genericTypeArguments = genericTypeArguments; + this.genericMethodArguments = genericMethodArguments; + } + + public Type GetGenericTypeArgument(int index) + { + return genericTypeArguments[index]; + } + + public Type GetGenericMethodArgument(int index) + { + return genericMethodArguments[index]; + } + } + + public Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) + { + if ((metadataToken >> 24) == TypeSpecTable.Index) + { + return ResolveType(metadataToken, new GenericContext(genericTypeArguments, genericMethodArguments)); + } + else + { + return ResolveType(metadataToken, null); + } + } + + internal abstract Type ResolveType(int metadataToken, IGenericContext context); + + public MethodBase ResolveMethod(int metadataToken) + { + return ResolveMethod(metadataToken, null, null); + } + + public FieldInfo ResolveField(int metadataToken) + { + return ResolveField(metadataToken, null, null); + } + + public MemberInfo ResolveMember(int metadataToken) + { + return ResolveMember(metadataToken, null, null); + } + + public bool IsDefined(Type attributeType, bool inherit) + { + return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit).Count != 0; + } + + public IList __GetCustomAttributes(Type attributeType, bool inherit) + { + return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit); + } + + public IList GetCustomAttributesData() + { + return CustomAttributeData.GetCustomAttributes(this); + } + + public IEnumerable CustomAttributes + { + get { return GetCustomAttributesData(); } + } + + public virtual IList __GetPlaceholderAssemblyCustomAttributes(bool multiple, bool security) + { + return Empty.Array; + } + + public abstract AssemblyName[] __GetReferencedAssemblies(); + + public virtual void __ResolveReferencedAssemblies(Assembly[] assemblies) + { + throw new NotSupportedException(); + } + + public abstract string[] __GetReferencedModules(); + + public abstract Type[] __GetReferencedTypes(); + + public abstract Type[] __GetExportedTypes(); + + public virtual bool __IsMissing + { + get { return false; } + } + + public long __ImageBase + { + get { return GetImageBaseImpl(); } + } + + protected abstract long GetImageBaseImpl(); + + public long __StackReserve + { + get { return GetStackReserveImpl(); } + } + + protected abstract long GetStackReserveImpl(); + + public int __FileAlignment + { + get { return GetFileAlignmentImpl(); } + } + + protected abstract int GetFileAlignmentImpl(); + + public DllCharacteristics __DllCharacteristics + { + get { return GetDllCharacteristicsImpl(); } + } + + protected abstract DllCharacteristics GetDllCharacteristicsImpl(); + + public virtual byte[] __ModuleHash + { + get { throw new NotSupportedException(); } + } + + public virtual int __EntryPointRVA + { + get { throw new NotSupportedException(); } + } + + public virtual int __EntryPointToken + { + get { throw new NotSupportedException(); } + } + + public virtual string __ImageRuntimeVersion + { + get { throw new NotSupportedException(); } + } + + public IEnumerable __EnumerateCustomAttributeTable() + { + List list = new List(CustomAttribute.RowCount); + for (int i = 0; i < CustomAttribute.RowCount; i++) + { + list.Add(new CustomAttributeData(this, i)); + } + return list; + } + + [Obsolete] + public List __GetCustomAttributesFor(int token) + { + return CustomAttributeData.GetCustomAttributesImpl(new List(), this, token, null); + } + + public bool __TryGetImplMap(int token, out ImplMapFlags mappingFlags, out string importName, out string importScope) + { + foreach (int i in ImplMap.Filter(token)) + { + mappingFlags = (ImplMapFlags)(ushort)ImplMap.records[i].MappingFlags; + importName = GetString(ImplMap.records[i].ImportName); + importScope = GetString(ModuleRef.records[(ImplMap.records[i].ImportScope & 0xFFFFFF) - 1]); + return true; + } + mappingFlags = 0; + importName = null; + importScope = null; + return false; + } + +#if !NO_AUTHENTICODE + public virtual System.Security.Cryptography.X509Certificates.X509Certificate GetSignerCertificate() + { + return null; + } +#endif // !NO_AUTHENTICODE + + internal abstract Type GetModuleType(); + + internal abstract ByteReader GetBlob(int blobIndex); + + internal IList GetDeclarativeSecurity(int metadataToken) + { + List list = new List(); + foreach (int i in DeclSecurity.Filter(metadataToken)) + { + CustomAttributeData.ReadDeclarativeSecurity(this, i, list); + } + return list; + } + + internal virtual void Dispose() + { + } + + internal virtual void ExportTypes(int fileToken, IKVM.Reflection.Emit.ModuleBuilder manifestModule) + { + } + + internal virtual string GetString(int index) + { + throw new NotSupportedException(); + } + } + + abstract class NonPEModule : Module + { + protected NonPEModule(Universe universe) + : base(universe) + { + } + + protected virtual Exception InvalidOperationException() + { + return new InvalidOperationException(); + } + + protected virtual Exception NotSupportedException() + { + return new NotSupportedException(); + } + + protected virtual Exception ArgumentOutOfRangeException() + { + return new ArgumentOutOfRangeException(); + } + + internal sealed override Type GetModuleType() + { + throw InvalidOperationException(); + } + + internal sealed override ByteReader GetBlob(int blobIndex) + { + throw InvalidOperationException(); + } + + public sealed override AssemblyName[] __GetReferencedAssemblies() + { + throw NotSupportedException(); + } + + public sealed override string[] __GetReferencedModules() + { + throw NotSupportedException(); + } + + public override Type[] __GetReferencedTypes() + { + throw NotSupportedException(); + } + + public override Type[] __GetExportedTypes() + { + throw NotSupportedException(); + } + + protected sealed override long GetImageBaseImpl() + { + throw NotSupportedException(); + } + + protected sealed override long GetStackReserveImpl() + { + throw NotSupportedException(); + } + + protected sealed override int GetFileAlignmentImpl() + { + throw NotSupportedException(); + } + + protected override DllCharacteristics GetDllCharacteristicsImpl() + { + throw NotSupportedException(); + } + + internal sealed override Type ResolveType(int metadataToken, IGenericContext context) + { + throw ArgumentOutOfRangeException(); + } + + public sealed override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) + { + throw ArgumentOutOfRangeException(); + } + + public sealed override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) + { + throw ArgumentOutOfRangeException(); + } + + public sealed override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) + { + throw ArgumentOutOfRangeException(); + } + + public sealed override string ResolveString(int metadataToken) + { + throw ArgumentOutOfRangeException(); + } + + public sealed override Type[] __ResolveOptionalParameterTypes(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments, out CustomModifiers[] customModifiers) + { + throw ArgumentOutOfRangeException(); + } + } + + public delegate bool TypeFilter(Type m, object filterCriteria); + public delegate bool MemberFilter(MemberInfo m, object filterCriteria); +} diff --git a/reflect/ParameterInfo.cs b/reflect/ParameterInfo.cs new file mode 100644 index 0000000..ca70d33 --- /dev/null +++ b/reflect/ParameterInfo.cs @@ -0,0 +1,189 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System.Collections.Generic; + +namespace IKVM.Reflection +{ + public abstract class ParameterInfo : ICustomAttributeProvider + { + // prevent external subclasses + internal ParameterInfo() + { + } + + public sealed override bool Equals(object obj) + { + ParameterInfo other = obj as ParameterInfo; + return other != null && other.Member == this.Member && other.Position == this.Position; + } + + public sealed override int GetHashCode() + { + return this.Member.GetHashCode() * 1777 + this.Position; + } + + public static bool operator ==(ParameterInfo p1, ParameterInfo p2) + { + return ReferenceEquals(p1, p2) || (!ReferenceEquals(p1, null) && p1.Equals(p2)); + } + + public static bool operator !=(ParameterInfo p1, ParameterInfo p2) + { + return !(p1 == p2); + } + + public abstract string Name { get; } + public abstract Type ParameterType { get; } + public abstract ParameterAttributes Attributes { get; } + public abstract int Position { get; } + public abstract object RawDefaultValue { get; } + public abstract CustomModifiers __GetCustomModifiers(); + public abstract bool __TryGetFieldMarshal(out FieldMarshal fieldMarshal); + public abstract MemberInfo Member { get; } + public abstract int MetadataToken { get; } + internal abstract Module Module { get; } + + public Type[] GetOptionalCustomModifiers() + { + return __GetCustomModifiers().GetOptional(); + } + + public Type[] GetRequiredCustomModifiers() + { + return __GetCustomModifiers().GetRequired(); + } + + public bool IsIn + { + get { return (Attributes & ParameterAttributes.In) != 0; } + } + + public bool IsOut + { + get { return (Attributes & ParameterAttributes.Out) != 0; } + } + + public bool IsLcid + { + get { return (Attributes & ParameterAttributes.Lcid) != 0; } + } + + public bool IsRetval + { + get { return (Attributes & ParameterAttributes.Retval) != 0; } + } + + public bool IsOptional + { + get { return (Attributes & ParameterAttributes.Optional) != 0; } + } + + public bool HasDefaultValue + { + get { return (Attributes & ParameterAttributes.HasDefault) != 0; } + } + + public bool IsDefined(Type attributeType, bool inherit) + { + return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit).Count != 0; + } + + public IList __GetCustomAttributes(Type attributeType, bool inherit) + { + return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit); + } + + public IList GetCustomAttributesData() + { + return CustomAttributeData.GetCustomAttributes(this); + } + + public IEnumerable CustomAttributes + { + get { return GetCustomAttributesData(); } + } + } + + sealed class ParameterInfoWrapper : ParameterInfo + { + private readonly MemberInfo member; + private readonly ParameterInfo forward; + + internal ParameterInfoWrapper(MemberInfo member, ParameterInfo forward) + { + this.member = member; + this.forward = forward; + } + + public override string Name + { + get { return forward.Name; } + } + + public override Type ParameterType + { + get { return forward.ParameterType; } + } + + public override ParameterAttributes Attributes + { + get { return forward.Attributes; } + } + + public override int Position + { + get { return forward.Position; } + } + + public override object RawDefaultValue + { + get { return forward.RawDefaultValue; } + } + + public override CustomModifiers __GetCustomModifiers() + { + return forward.__GetCustomModifiers(); + } + + public override bool __TryGetFieldMarshal(out FieldMarshal fieldMarshal) + { + return forward.__TryGetFieldMarshal(out fieldMarshal); + } + + public override MemberInfo Member + { + get { return member; } + } + + public override int MetadataToken + { + get { return forward.MetadataToken; } + } + + internal override Module Module + { + get { return member.Module; } + } + } +} diff --git a/reflect/ParameterModifier.cs b/reflect/ParameterModifier.cs new file mode 100644 index 0000000..605cca4 --- /dev/null +++ b/reflect/ParameterModifier.cs @@ -0,0 +1,45 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; + +namespace IKVM.Reflection +{ + public struct ParameterModifier + { + private readonly bool[] values; + + public ParameterModifier(int parameterCount) + { + values = new bool[parameterCount]; + } + + public bool this[int index] + { + get { return values[index]; } + set { values[index] = value; } + } + } +} diff --git a/reflect/Projection.cs b/reflect/Projection.cs new file mode 100644 index 0000000..d38f9e2 --- /dev/null +++ b/reflect/Projection.cs @@ -0,0 +1,602 @@ +/* + Copyright (C) 2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; +using IKVM.Reflection.Metadata; +using IKVM.Reflection.Reader; + +namespace IKVM.Reflection +{ + sealed class WindowsRuntimeProjection + { + private static readonly Dictionary projections = new Dictionary(); + private readonly ModuleReader module; + private readonly Dictionary strings; + private readonly Dictionary added = new Dictionary(); + private readonly int[] assemblyRefTokens = new int[(int)ProjectionAssembly.Count]; + private int typeofSystemAttribute = -1; + private int typeofSystemAttributeUsageAttribute = -1; + private int typeofSystemEnum = -1; + private int typeofSystemIDisposable = -1; + private int typeofSystemMulticastDelegate = -1; + private int typeofWindowsFoundationMetadataAllowMultipleAttribute = -1; + private bool[] projectedTypeRefs; + + enum ProjectionAssembly + { + System_Runtime, + System_Runtime_InteropServices_WindowsRuntime, + System_ObjectModel, + System_Runtime_WindowsRuntime, + System_Runtime_WindowsRuntime_UI_Xaml, + + Count + } + + sealed class Mapping + { + internal readonly ProjectionAssembly Assembly; + internal readonly string TypeNamespace; + internal readonly string TypeName; + + internal Mapping(ProjectionAssembly assembly, string typeNamespace, string typeName) + { + this.Assembly = assembly; + this.TypeNamespace = typeNamespace; + this.TypeName = typeName; + } + } + + static WindowsRuntimeProjection() + { + projections.Add(new TypeName("System", "Attribute"), new Mapping(ProjectionAssembly.System_Runtime, "System", "Attribute")); + projections.Add(new TypeName("System", "MulticastDelegate"), new Mapping(ProjectionAssembly.System_Runtime, "System", "MulticastDelegate")); + projections.Add(new TypeName("Windows.Foundation", "DateTime"), new Mapping(ProjectionAssembly.System_Runtime, "System", "DateTimeOffset")); + projections.Add(new TypeName("Windows.Foundation", "EventHandler`1"), new Mapping(ProjectionAssembly.System_Runtime, "System", "EventHandler`1")); + projections.Add(new TypeName("Windows.Foundation", "EventRegistrationToken"), new Mapping(ProjectionAssembly.System_Runtime_InteropServices_WindowsRuntime, "System.Runtime.InteropServices.WindowsRuntime", "EventRegistrationToken")); + projections.Add(new TypeName("Windows.Foundation", "HResult"), new Mapping(ProjectionAssembly.System_Runtime, "System", "Exception")); + projections.Add(new TypeName("Windows.Foundation", "IClosable"), new Mapping(ProjectionAssembly.System_Runtime, "System", "IDisposable")); + projections.Add(new TypeName("Windows.Foundation", "IReference`1"), new Mapping(ProjectionAssembly.System_Runtime, "System", "Nullable`1")); + projections.Add(new TypeName("Windows.Foundation", "Point"), new Mapping(ProjectionAssembly.System_Runtime_WindowsRuntime, "Windows.Foundation", "Point")); + projections.Add(new TypeName("Windows.Foundation", "Rect"), new Mapping(ProjectionAssembly.System_Runtime_WindowsRuntime, "Windows.Foundation", "Rect")); + projections.Add(new TypeName("Windows.Foundation", "Size"), new Mapping(ProjectionAssembly.System_Runtime_WindowsRuntime, "Windows.Foundation", "Size")); + projections.Add(new TypeName("Windows.Foundation", "TimeSpan"), new Mapping(ProjectionAssembly.System_Runtime, "System", "TimeSpan")); + projections.Add(new TypeName("Windows.Foundation", "Uri"), new Mapping(ProjectionAssembly.System_Runtime, "System", "Uri")); + projections.Add(new TypeName("Windows.Foundation.Collections", "IIterable`1"), new Mapping(ProjectionAssembly.System_Runtime, "System.Collections.Generic", "IEnumerable`1")); + projections.Add(new TypeName("Windows.Foundation.Collections", "IKeyValuePair`2"), new Mapping(ProjectionAssembly.System_Runtime, "System.Collections.Generic", "KeyValuePair`2")); + projections.Add(new TypeName("Windows.Foundation.Collections", "IMap`2"), new Mapping(ProjectionAssembly.System_Runtime, "System.Collections.Generic", "IDictionary`2")); + projections.Add(new TypeName("Windows.Foundation.Collections", "IMapView`2"), new Mapping(ProjectionAssembly.System_Runtime, "System.Collections.Generic", "IReadOnlyDictionary`2")); + projections.Add(new TypeName("Windows.Foundation.Collections", "IVector`1"), new Mapping(ProjectionAssembly.System_Runtime, "System.Collections.Generic", "IList`1")); + projections.Add(new TypeName("Windows.Foundation.Collections", "IVectorView`1"), new Mapping(ProjectionAssembly.System_Runtime, "System.Collections.Generic", "IReadOnlyList`1")); + projections.Add(new TypeName("Windows.Foundation.Metadata", "AttributeTargets"), new Mapping(ProjectionAssembly.System_Runtime, "System", "AttributeTargets")); + projections.Add(new TypeName("Windows.Foundation.Metadata", "AttributeUsageAttribute"), new Mapping(ProjectionAssembly.System_Runtime, "System", "AttributeUsageAttribute")); + projections.Add(new TypeName("Windows.UI", "Color"), new Mapping(ProjectionAssembly.System_Runtime_WindowsRuntime, "Windows.UI", "Color")); + projections.Add(new TypeName("Windows.UI.Xaml", "CornerRadius"), new Mapping(ProjectionAssembly.System_Runtime_WindowsRuntime_UI_Xaml, "Windows.UI.Xaml", "CornerRadius")); + projections.Add(new TypeName("Windows.UI.Xaml", "Duration"), new Mapping(ProjectionAssembly.System_Runtime_WindowsRuntime_UI_Xaml, "Windows.UI.Xaml", "Duration")); + projections.Add(new TypeName("Windows.UI.Xaml", "DurationType"), new Mapping(ProjectionAssembly.System_Runtime_WindowsRuntime_UI_Xaml, "Windows.UI.Xaml", "DurationType")); + projections.Add(new TypeName("Windows.UI.Xaml", "GridLength"), new Mapping(ProjectionAssembly.System_Runtime_WindowsRuntime_UI_Xaml, "Windows.UI.Xaml", "GridLength")); + projections.Add(new TypeName("Windows.UI.Xaml", "GridUnitType"), new Mapping(ProjectionAssembly.System_Runtime_WindowsRuntime_UI_Xaml, "Windows.UI.Xaml", "GridUnitType")); + projections.Add(new TypeName("Windows.UI.Xaml", "Thickness"), new Mapping(ProjectionAssembly.System_Runtime_WindowsRuntime_UI_Xaml, "Windows.UI.Xaml", "Thickness")); + projections.Add(new TypeName("Windows.UI.Xaml.Controls.Primitives", "GeneratorPosition"), new Mapping(ProjectionAssembly.System_Runtime_WindowsRuntime_UI_Xaml, "Windows.UI.Xaml.Controls.Primitives", "GeneratorPosition")); + projections.Add(new TypeName("Windows.UI.Xaml.Data", "INotifyPropertyChanged"), new Mapping(ProjectionAssembly.System_ObjectModel, "System.ComponentModel", "INotifyPropertyChanged")); + projections.Add(new TypeName("Windows.UI.Xaml.Data", "PropertyChangedEventArgs"), new Mapping(ProjectionAssembly.System_ObjectModel, "System.ComponentModel", "PropertyChangedEventArgs")); + projections.Add(new TypeName("Windows.UI.Xaml.Data", "PropertyChangedEventHandler"), new Mapping(ProjectionAssembly.System_ObjectModel, "System.ComponentModel", "PropertyChangedEventHandler")); + projections.Add(new TypeName("Windows.UI.Xaml.Input", "ICommand"), new Mapping(ProjectionAssembly.System_ObjectModel, "System.Windows.Input", "ICommand")); + projections.Add(new TypeName("Windows.UI.Xaml.Interop", "IBindableIterable"), new Mapping(ProjectionAssembly.System_Runtime, "System.Collections", "IEnumerable")); + projections.Add(new TypeName("Windows.UI.Xaml.Interop", "IBindableVector"), new Mapping(ProjectionAssembly.System_Runtime, "System.Collections", "IList")); + projections.Add(new TypeName("Windows.UI.Xaml.Interop", "NotifyCollectionChangedAction"), new Mapping(ProjectionAssembly.System_ObjectModel, "System.Collections.Specialized", "NotifyCollectionChangedAction")); + projections.Add(new TypeName("Windows.UI.Xaml.Interop", "NotifyCollectionChangedEventArgs"), new Mapping(ProjectionAssembly.System_ObjectModel, "System.Collections.Specialized", "NotifyCollectionChangedEventArgs")); + projections.Add(new TypeName("Windows.UI.Xaml.Interop", "NotifyCollectionChangedEventHandler"), new Mapping(ProjectionAssembly.System_ObjectModel, "System.Collections.Specialized", "NotifyCollectionChangedEventHandler")); + projections.Add(new TypeName("Windows.UI.Xaml.Interop", "TypeName"), new Mapping(ProjectionAssembly.System_Runtime, "System", "Type")); + projections.Add(new TypeName("Windows.UI.Xaml.Media", "Matrix"), new Mapping(ProjectionAssembly.System_Runtime_WindowsRuntime_UI_Xaml, "Windows.UI.Xaml.Media", "Matrix")); + projections.Add(new TypeName("Windows.UI.Xaml.Media.Animation", "KeyTime"), new Mapping(ProjectionAssembly.System_Runtime_WindowsRuntime_UI_Xaml, "Windows.UI.Xaml.Media.Animation", "KeyTime")); + projections.Add(new TypeName("Windows.UI.Xaml.Media.Animation", "RepeatBehavior"), new Mapping(ProjectionAssembly.System_Runtime_WindowsRuntime_UI_Xaml, "Windows.UI.Xaml.Media.Animation", "RepeatBehavior")); + projections.Add(new TypeName("Windows.UI.Xaml.Media.Animation", "RepeatBehaviorType"), new Mapping(ProjectionAssembly.System_Runtime_WindowsRuntime_UI_Xaml, "Windows.UI.Xaml.Media.Animation", "RepeatBehaviorType")); + projections.Add(new TypeName("Windows.UI.Xaml.Media.Media3D", "Matrix3D"), new Mapping(ProjectionAssembly.System_Runtime_WindowsRuntime_UI_Xaml, "Windows.UI.Xaml.Media.Media3D", "Matrix3D")); + + // hidden types + projections.Add(new TypeName("Windows.Foundation", "IPropertyValue"), null); + projections.Add(new TypeName("Windows.Foundation", "IReferenceArray`1"), null); + projections.Add(new TypeName("Windows.Foundation.Metadata", "GCPressureAmount"), null); + projections.Add(new TypeName("Windows.Foundation.Metadata", "GCPressureAttribute"), null); + projections.Add(new TypeName("Windows.UI.Xaml", "CornerRadiusHelper"), null); + projections.Add(new TypeName("Windows.UI.Xaml", "DurationHelper"), null); + projections.Add(new TypeName("Windows.UI.Xaml", "GridLengthHelper"), null); + projections.Add(new TypeName("Windows.UI.Xaml", "ThicknessHelper"), null); + projections.Add(new TypeName("Windows.UI.Xaml.Controls.Primitives", "GeneratorPositionHelper"), null); + projections.Add(new TypeName("Windows.UI.Xaml.Interop", "INotifyCollectionChanged"), null); + projections.Add(new TypeName("Windows.UI.Xaml.Media", "MatrixHelper"), null); + projections.Add(new TypeName("Windows.UI.Xaml.Media.Animation", "KeyTimeHelper"), null); + projections.Add(new TypeName("Windows.UI.Xaml.Media.Animation", "RepeatBehaviorHelper"), null); + projections.Add(new TypeName("Windows.UI.Xaml.Media.Media3D", "Matrix3DHelper"), null); + } + + private WindowsRuntimeProjection(ModuleReader module, Dictionary strings) + { + this.module = module; + this.strings = strings; + } + + internal static void Patch(ModuleReader module, Dictionary strings, ref string imageRuntimeVersion, ref byte[] blobHeap) + { + if (!module.CustomAttribute.Sorted) + { + // HasAllowMultipleAttribute requires this + throw new NotImplementedException("CustomAttribute table must be sorted"); + } + + bool clr = imageRuntimeVersion.Contains(";"); + if (clr) + { + imageRuntimeVersion = imageRuntimeVersion.Substring(imageRuntimeVersion.IndexOf(';') + 1); + if (imageRuntimeVersion.StartsWith("CLR", StringComparison.OrdinalIgnoreCase)) + { + imageRuntimeVersion = imageRuntimeVersion.Substring(3); + } + imageRuntimeVersion = imageRuntimeVersion.TrimStart(' '); + } + else + { + Assembly mscorlib = module.universe.Mscorlib; + imageRuntimeVersion = mscorlib.__IsMissing ? "v4.0.30319" : mscorlib.ImageRuntimeVersion; + } + + WindowsRuntimeProjection obj = new WindowsRuntimeProjection(module, strings); + obj.PatchAssemblyRef(ref blobHeap); + obj.PatchTypeRef(); + obj.PatchTypes(clr); + obj.PatchMethodImpl(); + obj.PatchCustomAttribute(ref blobHeap); + } + + private void PatchAssemblyRef(ref byte[] blobHeap) + { + AssemblyRefTable assemblyRefs = module.AssemblyRef; + for (int i = 0; i < assemblyRefs.records.Length; i++) + { + if (module.GetString(assemblyRefs.records[i].Name) == "mscorlib") + { + Version ver = GetMscorlibVersion(); + assemblyRefs.records[i].MajorVersion = (ushort)ver.Major; + assemblyRefs.records[i].MinorVersion = (ushort)ver.Minor; + assemblyRefs.records[i].BuildNumber = (ushort)ver.Build; + assemblyRefs.records[i].RevisionNumber = (ushort)ver.Revision; + break; + } + } + + int publicKeyTokenMicrosoft = AddBlob(ref blobHeap, new byte[] { 0xB0, 0x3F, 0x5F, 0x7F, 0x11, 0xD5, 0x0A, 0x3A }); + int publicKeyTokenEcma = AddBlob(ref blobHeap, new byte[] { 0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89 }); + assemblyRefTokens[(int)ProjectionAssembly.System_Runtime] = AddAssemblyReference("System.Runtime", publicKeyTokenMicrosoft); + assemblyRefTokens[(int)ProjectionAssembly.System_Runtime_InteropServices_WindowsRuntime] = AddAssemblyReference("System.Runtime.InteropServices.WindowsRuntime", publicKeyTokenMicrosoft); + assemblyRefTokens[(int)ProjectionAssembly.System_ObjectModel] = AddAssemblyReference("System.ObjectModel", publicKeyTokenMicrosoft); + assemblyRefTokens[(int)ProjectionAssembly.System_Runtime_WindowsRuntime] = AddAssemblyReference("System.Runtime.WindowsRuntime", publicKeyTokenEcma); + assemblyRefTokens[(int)ProjectionAssembly.System_Runtime_WindowsRuntime_UI_Xaml] = AddAssemblyReference("System.Runtime.WindowsRuntime.UI.Xaml", publicKeyTokenEcma); + } + + private void PatchTypeRef() + { + TypeRefTable.Record[] typeRefs = module.TypeRef.records; + projectedTypeRefs = new bool[typeRefs.Length]; + for (int i = 0; i < typeRefs.Length; i++) + { + Mapping mapping; + TypeName typeName = GetTypeRefName(i); + projections.TryGetValue(typeName, out mapping); + if (mapping != null) + { + typeRefs[i].ResolutionScope = assemblyRefTokens[(int)mapping.Assembly]; + typeRefs[i].TypeNamespace = GetString(mapping.TypeNamespace); + typeRefs[i].TypeName = GetString(mapping.TypeName); + projectedTypeRefs[i] = true; + } + switch (typeName.Namespace) + { + case "System": + switch (typeName.Name) + { + case "Attribute": + typeofSystemAttribute = (TypeRefTable.Index << 24) + i + 1; + break; + case "Enum": + typeofSystemEnum = (TypeRefTable.Index << 24) + i + 1; + break; + case "MulticastDelegate": + typeofSystemMulticastDelegate = (TypeRefTable.Index << 24) + i + 1; + break; + } + break; + case "Windows.Foundation": + switch (typeName.Name) + { + case "IClosable": + typeofSystemIDisposable = (TypeRefTable.Index << 24) + i + 1; + break; + } + break; + case "Windows.Foundation.Metadata": + switch (typeName.Name) + { + case "AllowMultipleAttribute": + typeofWindowsFoundationMetadataAllowMultipleAttribute = (TypeRefTable.Index << 24) + i + 1; + break; + case "AttributeUsageAttribute": + typeofSystemAttributeUsageAttribute = (TypeRefTable.Index << 24) + i + 1; + break; + } + break; + } + } + } + + private void PatchTypes(bool clr) + { + TypeDefTable.Record[] types = module.TypeDef.records; + MethodDefTable.Record[] methods = module.MethodDef.records; + FieldTable.Record[] fields = module.Field.records; + for (int i = 0; i < types.Length; i++) + { + TypeAttributes attr = (TypeAttributes)types[i].Flags; + if ((attr & TypeAttributes.WindowsRuntime) != 0) + { + if (clr && (attr & (TypeAttributes.VisibilityMask | TypeAttributes.WindowsRuntime | TypeAttributes.Interface)) == (TypeAttributes.Public | TypeAttributes.WindowsRuntime)) + { + types[i].TypeName = GetString("" + module.GetString(types[i].TypeName)); + types[i].Flags &= (int)~TypeAttributes.Public; + } + + if (types[i].Extends != typeofSystemAttribute && (!clr || (attr & TypeAttributes.Interface) == 0)) + { + types[i].Flags |= (int)TypeAttributes.Import; + } + if (projections.ContainsKey(GetTypeDefName(i))) + { + types[i].Flags &= (int)~TypeAttributes.Public; + } + + int endOfMethodList = i == types.Length - 1 ? methods.Length : types[i + 1].MethodList - 1; + for (int j = types[i].MethodList - 1; j < endOfMethodList; j++) + { + if (types[i].Extends == typeofSystemMulticastDelegate) + { + if (module.GetString(methods[j].Name) == ".ctor") + { + methods[j].Flags &= (int)~MethodAttributes.MemberAccessMask; + methods[j].Flags |= (int)MethodAttributes.Public; + } + } + else if (methods[j].RVA == 0) + { + methods[j].ImplFlags = (int)(MethodImplAttributes.Runtime | MethodImplAttributes.Managed | MethodImplAttributes.InternalCall); + } + } + + if (types[i].Extends == typeofSystemEnum) + { + int endOfFieldList = i == types.Length - 1 ? fields.Length : types[i + 1].FieldList - 1; + for (int j = types[i].FieldList - 1; j < endOfFieldList; j++) + { + fields[j].Flags &= (int)~FieldAttributes.FieldAccessMask; + fields[j].Flags |= (int)FieldAttributes.Public; + } + } + } + else if (clr && (attr & (TypeAttributes.VisibilityMask | TypeAttributes.SpecialName)) == (TypeAttributes.NotPublic | TypeAttributes.SpecialName)) + { + string name = module.GetString(types[i].TypeName); + if (name.StartsWith("", StringComparison.Ordinal)) + { + types[i].TypeName = GetString(name.Substring(5)); + types[i].Flags |= (int)TypeAttributes.Public; + types[i].Flags &= (int)~TypeAttributes.SpecialName; + } + } + } + } + + private void PatchMethodImpl() + { + MethodImplTable.Record[] methodImpls = module.MethodImpl.records; + MemberRefTable.Record[] memberRefs = module.MemberRef.records; + MethodDefTable.Record[] methods = module.MethodDef.records; + int[] typeSpecs = module.TypeSpec.records; + for (int i = 0; i < methodImpls.Length; i++) + { + int methodDefOrMemberRef = methodImpls[i].MethodDeclaration; + if ((methodDefOrMemberRef >> 24) == MemberRefTable.Index) + { + int typeDefOrRef = memberRefs[(methodDefOrMemberRef & 0xFFFFFF) - 1].Class; + if ((typeDefOrRef >> 24) == TypeSpecTable.Index) + { + typeDefOrRef = ReadTypeSpec(module.GetBlob(typeSpecs[(typeDefOrRef & 0xFFFFFF) - 1])); + } + if ((typeDefOrRef >> 24) == TypeRefTable.Index) + { + if (typeDefOrRef == typeofSystemIDisposable) + { + int dispose = GetString("Dispose"); + methods[(methodImpls[i].MethodBody & 0xFFFFFF) - 1].Name = dispose; + memberRefs[(methodImpls[i].MethodDeclaration & 0xFFFFFF) - 1].Name = dispose; + } + else if (projectedTypeRefs[(typeDefOrRef & 0xFFFFFF) - 1]) + { + methods[(methodImpls[i].MethodBody & 0xFFFFFF) - 1].Flags &= (int)~MethodAttributes.MemberAccessMask; + methods[(methodImpls[i].MethodBody & 0xFFFFFF) - 1].Flags |= (int)MethodAttributes.Private; + methodImpls[i].MethodBody = 0; + methodImpls[i].MethodDeclaration = 0; + } + } + else if ((typeDefOrRef >> 24) == TypeDefTable.Index) + { + } + else if ((typeDefOrRef >> 24) == TypeSpecTable.Index) + { + throw new NotImplementedException(); + } + else + { + throw new BadImageFormatException(); + } + } + } + } + + private void PatchCustomAttribute(ref byte[] blobHeap) + { + MemberRefTable.Record[] memberRefs = module.MemberRef.records; + int ctorSystemAttributeUsageAttribute = -1; + int ctorWindowsFoundationMetadataAllowMultipleAttribute = -1; + for (int i = 0; i < memberRefs.Length; i++) + { + if (memberRefs[i].Class == typeofSystemAttributeUsageAttribute + && module.GetString(memberRefs[i].Name) == ".ctor") + { + ctorSystemAttributeUsageAttribute = (MemberRefTable.Index << 24) + i + 1; + } + else if (memberRefs[i].Class == typeofWindowsFoundationMetadataAllowMultipleAttribute + && module.GetString(memberRefs[i].Name) == ".ctor") + { + ctorWindowsFoundationMetadataAllowMultipleAttribute = (MemberRefTable.Index << 24) + i + 1; + } + } + + if (ctorSystemAttributeUsageAttribute != -1) + { + CustomAttributeTable.Record[] customAttributes = module.CustomAttribute.records; + Dictionary map = new Dictionary(); + for (int i = 0; i < customAttributes.Length; i++) + { + if (customAttributes[i].Type == ctorSystemAttributeUsageAttribute) + { + ByteReader br = module.GetBlob(customAttributes[i].Value); + br.ReadInt16(); + AttributeTargets targets = MapAttributeTargets(br.ReadInt32()); + if ((targets & AttributeTargets.Method) != 0) + { + // apart from the two types special cased below, Method implies Constructor + targets |= AttributeTargets.Constructor; + if (customAttributes[i].Parent >> 24 == TypeDefTable.Index) + { + TypeName typeName = GetTypeDefName((customAttributes[i].Parent & 0xFFFFFF) - 1); + if (typeName.Namespace == "Windows.Foundation.Metadata" && (typeName.Name == "OverloadAttribute" || typeName.Name == "DefaultOverloadAttribute")) + { + targets &= ~AttributeTargets.Constructor; + } + } + } + customAttributes[i].Value = GetAttributeUsageAttributeBlob(ref blobHeap, map, targets, HasAllowMultipleAttribute(customAttributes, i, ctorWindowsFoundationMetadataAllowMultipleAttribute)); + } + } + } + } + + private int AddAssemblyReference(string name, int publicKeyToken) + { + AssemblyRefTable.Record rec; + Version ver = GetMscorlibVersion(); + rec.MajorVersion = (ushort)ver.Major; + rec.MinorVersion = (ushort)ver.Minor; + rec.BuildNumber = (ushort)ver.Build; + rec.RevisionNumber = (ushort)ver.Revision; + rec.Flags = 0; + rec.PublicKeyOrToken = publicKeyToken; + rec.Name = GetString(name); + rec.Culture = 0; + rec.HashValue = 0; + int token = 0x23000000 | module.AssemblyRef.FindOrAddRecord(rec); + Array.Resize(ref module.AssemblyRef.records, module.AssemblyRef.RowCount); + return token; + } + + private TypeName GetTypeRefName(int index) + { + return new TypeName(module.GetString(module.TypeRef.records[index].TypeNamespace), module.GetString(module.TypeRef.records[index].TypeName)); + } + + private TypeName GetTypeDefName(int index) + { + return new TypeName(module.GetString(module.TypeDef.records[index].TypeNamespace), module.GetString(module.TypeDef.records[index].TypeName)); + } + + private int GetString(string str) + { + int index; + if (!added.TryGetValue(str, out index)) + { + index = -(added.Count + 1); + added.Add(str, index); + strings.Add(index, str); + } + return index; + } + + private Version GetMscorlibVersion() + { + Assembly mscorlib = module.universe.Mscorlib; + return mscorlib.__IsMissing ? new Version(4, 0, 0, 0) : mscorlib.GetName().Version; + } + + private static bool HasAllowMultipleAttribute(CustomAttributeTable.Record[] customAttributes, int i, int ctorWindowsFoundationMetadataAllowMultipleAttribute) + { + // we can assume that the CustomAttribute table is sorted, because we've checked the Sorted flag earlier + int owner = customAttributes[i].Parent; + while (i > 0 && customAttributes[i - 1].Parent == owner) + { + i--; + } + while (i < customAttributes.Length && customAttributes[i].Parent == owner) + { + if (customAttributes[i].Type == ctorWindowsFoundationMetadataAllowMultipleAttribute) + { + return true; + } + i++; + } + return false; + } + + private static AttributeTargets MapAttributeTargets(int targets) + { + if (targets == -1) + { + return AttributeTargets.All; + } + AttributeTargets result = 0; + if ((targets & 1) != 0) + { + result |= AttributeTargets.Delegate; + } + if ((targets & 2) != 0) + { + result |= AttributeTargets.Enum; + } + if ((targets & 4) != 0) + { + result |= AttributeTargets.Event; + } + if ((targets & 8) != 0) + { + result |= AttributeTargets.Field; + } + if ((targets & 16) != 0) + { + result |= AttributeTargets.Interface; + } + if ((targets & 64) != 0) + { + result |= AttributeTargets.Method; + } + if ((targets & 128) != 0) + { + result |= AttributeTargets.Parameter; + } + if ((targets & 256) != 0) + { + result |= AttributeTargets.Property; + } + if ((targets & 512) != 0) + { + result |= AttributeTargets.Class; + } + if ((targets & 1024) != 0) + { + result |= AttributeTargets.Struct; + } + return result; + } + + private static int GetAttributeUsageAttributeBlob(ref byte[] blobHeap, Dictionary map, AttributeTargets targets, bool allowMultiple) + { + int key = (int)targets; + if (allowMultiple) + { + key |= unchecked((int)0x80000000); + } + int blob; + if (!map.TryGetValue(key, out blob)) + { + blob = AddBlob(ref blobHeap, new byte[] { 0x01, 0x00, (byte)targets, (byte)((int)targets >> 8), (byte)((int)targets >> 16), (byte)((int)targets >> 24), + 0x01, 0x00, 0x54, 0x02, 0x0D, 0x41, 0x6C, 0x6C, 0x6F, 0x77, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x70, 0x6C, 0x65, allowMultiple ? (byte)0x01 : (byte)0x00 }); + map.Add(key, blob); + } + return blob; + } + + private static int ReadTypeSpec(ByteReader br) + { + if (br.ReadByte() != Signature.ELEMENT_TYPE_GENERICINST) + { + throw new NotImplementedException("Expected ELEMENT_TYPE_GENERICINST"); + } + switch (br.ReadByte()) + { + case Signature.ELEMENT_TYPE_CLASS: + case Signature.ELEMENT_TYPE_VALUETYPE: + break; + default: + throw new NotImplementedException("Expected ELEMENT_TYPE_CLASS or ELEMENT_TYPE_VALUETYPE"); + } + int encoded = br.ReadCompressedUInt(); + switch (encoded & 3) + { + case 0: + return (TypeDefTable.Index << 24) + (encoded >> 2); + case 1: + return (TypeRefTable.Index << 24) + (encoded >> 2); + case 2: + return (TypeSpecTable.Index << 24) + (encoded >> 2); + default: + throw new BadImageFormatException(); + } + } + + private static int AddBlob(ref byte[] blobHeap, byte[] blob) + { + if (blob.Length > 127) + { + throw new NotImplementedException(); + } + int offset = blobHeap.Length; + Array.Resize(ref blobHeap, offset + blob.Length + 1); + blobHeap[offset] = (byte)blob.Length; + Buffer.BlockCopy(blob, 0, blobHeap, offset + 1, blob.Length); + return offset; + } + + internal static bool IsProjectedValueType(string ns, string name, Module module) + { + return ((ns == "System.Collections.Generic" && name == "KeyValuePair`2") + || (ns == "System" && name == "Nullable`1")) + && module.Assembly.GetName().Name == "System.Runtime"; + } + + internal static bool IsProjectedReferenceType(string ns, string name, Module module) + { + return ((ns == "System" && name == "Exception") + || (ns == "System" && name == "Type")) + && module.Assembly.GetName().Name == "System.Runtime"; + } + } +} diff --git a/reflect/Properties/AssemblyInfo.cs b/reflect/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..f453241 --- /dev/null +++ b/reflect/Properties/AssemblyInfo.cs @@ -0,0 +1,27 @@ +/* + Copyright (C) 2008 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System.Reflection; + +[assembly: AssemblyTitle("IKVM.Reflection")] +[assembly: AssemblyDescription("Alternative implementation of System.Reflection[.Emit]")] diff --git a/reflect/PropertyInfo.cs b/reflect/PropertyInfo.cs new file mode 100644 index 0000000..4d5ce9f --- /dev/null +++ b/reflect/PropertyInfo.cs @@ -0,0 +1,355 @@ +/* + Copyright (C) 2009-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; + +namespace IKVM.Reflection +{ + public abstract class PropertyInfo : MemberInfo + { + // prevent external subclasses + internal PropertyInfo() + { + } + + public sealed override MemberTypes MemberType + { + get { return MemberTypes.Property; } + } + + public abstract PropertyAttributes Attributes { get; } + public abstract bool CanRead { get; } + public abstract bool CanWrite { get; } + public abstract MethodInfo GetGetMethod(bool nonPublic); + public abstract MethodInfo GetSetMethod(bool nonPublic); + public abstract MethodInfo[] GetAccessors(bool nonPublic); + public abstract object GetRawConstantValue(); + internal abstract bool IsPublic { get; } + internal abstract bool IsNonPrivate { get; } + internal abstract bool IsStatic { get; } + internal abstract PropertySignature PropertySignature { get; } + + private sealed class ParameterInfoImpl : ParameterInfo + { + private readonly PropertyInfo property; + private readonly int parameter; + + internal ParameterInfoImpl(PropertyInfo property, int parameter) + { + this.property = property; + this.parameter = parameter; + } + + public override string Name + { + get { return null; } + } + + public override Type ParameterType + { + get { return property.PropertySignature.GetParameter(parameter); } + } + + public override ParameterAttributes Attributes + { + get { return ParameterAttributes.None; } + } + + public override int Position + { + get { return parameter; } + } + + public override object RawDefaultValue + { + get { throw new InvalidOperationException(); } + } + + public override CustomModifiers __GetCustomModifiers() + { + return property.PropertySignature.GetParameterCustomModifiers(parameter); + } + + public override bool __TryGetFieldMarshal(out FieldMarshal fieldMarshal) + { + fieldMarshal = new FieldMarshal(); + return false; + } + + public override MemberInfo Member + { + get { return property; } + } + + public override int MetadataToken + { + get { return 0x08000000; } + } + + internal override Module Module + { + get { return property.Module; } + } + } + + public virtual ParameterInfo[] GetIndexParameters() + { + ParameterInfo[] parameters = new ParameterInfo[this.PropertySignature.ParameterCount]; + for (int i = 0; i < parameters.Length; i++) + { + parameters[i] = new ParameterInfoImpl(this, i); + } + return parameters; + } + + public Type PropertyType + { + get { return this.PropertySignature.PropertyType; } + } + + public CustomModifiers __GetCustomModifiers() + { + return this.PropertySignature.GetCustomModifiers(); + } + + public Type[] GetRequiredCustomModifiers() + { + return __GetCustomModifiers().GetRequired(); + } + + public Type[] GetOptionalCustomModifiers() + { + return __GetCustomModifiers().GetOptional(); + } + + public bool IsSpecialName + { + get { return (Attributes & PropertyAttributes.SpecialName) != 0; } + } + + public MethodInfo GetMethod + { + get { return GetGetMethod(true); } + } + + public MethodInfo SetMethod + { + get { return GetSetMethod(true); } + } + + public MethodInfo GetGetMethod() + { + return GetGetMethod(false); + } + + public MethodInfo GetSetMethod() + { + return GetSetMethod(false); + } + + public MethodInfo[] GetAccessors() + { + return GetAccessors(false); + } + + public CallingConventions __CallingConvention + { + get { return this.PropertySignature.CallingConvention; } + } + + internal virtual PropertyInfo BindTypeParameters(Type type) + { + return new GenericPropertyInfo(this.DeclaringType.BindTypeParameters(type), this); + } + + public override string ToString() + { + return this.DeclaringType.ToString() + " " + Name; + } + + internal sealed override bool BindingFlagsMatch(BindingFlags flags) + { + return BindingFlagsMatch(IsPublic, flags, BindingFlags.Public, BindingFlags.NonPublic) + && BindingFlagsMatch(IsStatic, flags, BindingFlags.Static, BindingFlags.Instance); + } + + internal sealed override bool BindingFlagsMatchInherited(BindingFlags flags) + { + return IsNonPrivate + && BindingFlagsMatch(IsPublic, flags, BindingFlags.Public, BindingFlags.NonPublic) + && BindingFlagsMatch(IsStatic, flags, BindingFlags.Static | BindingFlags.FlattenHierarchy, BindingFlags.Instance); + } + + internal sealed override MemberInfo SetReflectedType(Type type) + { + return new PropertyInfoWithReflectedType(type, this); + } + + internal sealed override List GetPseudoCustomAttributes(Type attributeType) + { + // properties don't have pseudo custom attributes + return null; + } + } + + sealed class PropertyInfoWithReflectedType : PropertyInfo + { + private readonly Type reflectedType; + private readonly PropertyInfo property; + + internal PropertyInfoWithReflectedType(Type reflectedType, PropertyInfo property) + { + this.reflectedType = reflectedType; + this.property = property; + } + + public override PropertyAttributes Attributes + { + get { return property.Attributes; } + } + + public override bool CanRead + { + get { return property.CanRead; } + } + + public override bool CanWrite + { + get { return property.CanWrite; } + } + + public override MethodInfo GetGetMethod(bool nonPublic) + { + return SetReflectedType(property.GetGetMethod(nonPublic), reflectedType); + } + + public override MethodInfo GetSetMethod(bool nonPublic) + { + return SetReflectedType(property.GetSetMethod(nonPublic), reflectedType); + } + + public override MethodInfo[] GetAccessors(bool nonPublic) + { + return SetReflectedType(property.GetAccessors(nonPublic), reflectedType); + } + + public override object GetRawConstantValue() + { + return property.GetRawConstantValue(); + } + + internal override bool IsPublic + { + get { return property.IsPublic; } + } + + internal override bool IsNonPrivate + { + get { return property.IsNonPrivate; } + } + + internal override bool IsStatic + { + get { return property.IsStatic; } + } + + internal override PropertySignature PropertySignature + { + get { return property.PropertySignature; } + } + + public override ParameterInfo[] GetIndexParameters() + { + ParameterInfo[] parameters = property.GetIndexParameters(); + for (int i = 0; i < parameters.Length; i++) + { + parameters[i] = new ParameterInfoWrapper(this, parameters[i]); + } + return parameters; + } + + internal override PropertyInfo BindTypeParameters(Type type) + { + return property.BindTypeParameters(type); + } + + public override string ToString() + { + return property.ToString(); + } + + public override bool __IsMissing + { + get { return property.__IsMissing; } + } + + public override Type DeclaringType + { + get { return property.DeclaringType; } + } + + public override Type ReflectedType + { + get { return reflectedType; } + } + + public override bool Equals(object obj) + { + PropertyInfoWithReflectedType other = obj as PropertyInfoWithReflectedType; + return other != null + && other.reflectedType == reflectedType + && other.property == property; + } + + public override int GetHashCode() + { + return reflectedType.GetHashCode() ^ property.GetHashCode(); + } + + public override int MetadataToken + { + get { return property.MetadataToken; } + } + + public override Module Module + { + get { return property.Module; } + } + + public override string Name + { + get { return property.Name; } + } + + internal override bool IsBaked + { + get { return property.IsBaked; } + } + + internal override int GetCurrentToken() + { + return property.GetCurrentToken(); + } + } +} diff --git a/reflect/PropertySignature.cs b/reflect/PropertySignature.cs new file mode 100644 index 0000000..e6e0fee --- /dev/null +++ b/reflect/PropertySignature.cs @@ -0,0 +1,186 @@ +/* + Copyright (C) 2009-2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using IKVM.Reflection.Emit; +using IKVM.Reflection.Writer; +using IKVM.Reflection.Reader; + +namespace IKVM.Reflection +{ + sealed class PropertySignature : Signature + { + private CallingConventions callingConvention; + private readonly Type propertyType; + private readonly Type[] parameterTypes; + private readonly PackedCustomModifiers customModifiers; + + internal static PropertySignature Create(CallingConventions callingConvention, Type propertyType, Type[] parameterTypes, PackedCustomModifiers customModifiers) + { + return new PropertySignature(callingConvention, propertyType, Util.Copy(parameterTypes), customModifiers); + } + + private PropertySignature(CallingConventions callingConvention, Type propertyType, Type[] parameterTypes, PackedCustomModifiers customModifiers) + { + this.callingConvention = callingConvention; + this.propertyType = propertyType; + this.parameterTypes = parameterTypes; + this.customModifiers = customModifiers; + } + + public override bool Equals(object obj) + { + PropertySignature other = obj as PropertySignature; + return other != null + && other.propertyType.Equals(propertyType) + && other.customModifiers.Equals(customModifiers); + } + + public override int GetHashCode() + { + return propertyType.GetHashCode() ^ customModifiers.GetHashCode(); + } + + internal int ParameterCount + { + get { return parameterTypes.Length; } + } + + internal bool HasThis + { + set + { + if (value) + { + callingConvention |= CallingConventions.HasThis; + } + else + { + callingConvention &= ~CallingConventions.HasThis; + } + } + } + + internal Type PropertyType + { + get { return propertyType; } + } + + internal CustomModifiers GetCustomModifiers() + { + return customModifiers.GetReturnTypeCustomModifiers(); + } + + internal PropertySignature ExpandTypeParameters(Type declaringType) + { + return new PropertySignature( + callingConvention, + propertyType.BindTypeParameters(declaringType), + BindTypeParameters(declaringType, parameterTypes), + customModifiers.Bind(declaringType)); + } + + internal override void WriteSig(ModuleBuilder module, ByteBuffer bb) + { + byte flags = PROPERTY; + if ((callingConvention & CallingConventions.HasThis) != 0) + { + flags |= HASTHIS; + } + if ((callingConvention & CallingConventions.ExplicitThis) != 0) + { + flags |= EXPLICITTHIS; + } + if ((callingConvention & CallingConventions.VarArgs) != 0) + { + flags |= VARARG; + } + bb.Write(flags); + bb.WriteCompressedUInt(parameterTypes == null ? 0 : parameterTypes.Length); + WriteCustomModifiers(module, bb, customModifiers.GetReturnTypeCustomModifiers()); + WriteType(module, bb, propertyType); + if (parameterTypes != null) + { + for (int i = 0; i < parameterTypes.Length; i++) + { + WriteCustomModifiers(module, bb, customModifiers.GetParameterCustomModifiers(i)); + WriteType(module, bb, parameterTypes[i]); + } + } + } + + internal Type GetParameter(int parameter) + { + return parameterTypes[parameter]; + } + + internal CustomModifiers GetParameterCustomModifiers(int parameter) + { + return customModifiers.GetParameterCustomModifiers(parameter); + } + + internal CallingConventions CallingConvention + { + get { return callingConvention; } + } + + internal bool MatchParameterTypes(Type[] types) + { + return Util.ArrayEquals(types, parameterTypes); + } + + internal static PropertySignature ReadSig(ModuleReader module, ByteReader br, IGenericContext context) + { + byte flags = br.ReadByte(); + if ((flags & PROPERTY) == 0) + { + throw new BadImageFormatException(); + } + CallingConventions callingConvention = CallingConventions.Standard; + if ((flags & HASTHIS) != 0) + { + callingConvention |= CallingConventions.HasThis; + } + if ((flags & EXPLICITTHIS) != 0) + { + callingConvention |= CallingConventions.ExplicitThis; + } + Type returnType; + Type[] parameterTypes; + int paramCount = br.ReadCompressedUInt(); + CustomModifiers[] mods = null; + PackedCustomModifiers.Pack(ref mods, 0, CustomModifiers.Read(module, br, context), paramCount + 1); + returnType = ReadRetType(module, br, context); + parameterTypes = new Type[paramCount]; + for (int i = 0; i < parameterTypes.Length; i++) + { + PackedCustomModifiers.Pack(ref mods, i + 1, CustomModifiers.Read(module, br, context), paramCount + 1); + parameterTypes[i] = ReadParam(module, br, context); + } + return new PropertySignature(callingConvention, returnType, parameterTypes, PackedCustomModifiers.Wrap(mods)); + } + } +} diff --git a/reflect/Reader/AssemblyReader.cs b/reflect/Reader/AssemblyReader.cs new file mode 100644 index 0000000..868ec2c --- /dev/null +++ b/reflect/Reader/AssemblyReader.cs @@ -0,0 +1,330 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Configuration.Assemblies; +using System.IO; +using IKVM.Reflection.Metadata; + +namespace IKVM.Reflection.Reader +{ + sealed class AssemblyReader : Assembly + { + private const int ContainsNoMetaData = 0x0001; + private readonly string location; + private readonly ModuleReader manifestModule; + private readonly Module[] externalModules; + + internal AssemblyReader(string location, ModuleReader manifestModule) + : base(manifestModule.universe) + { + this.location = location; + this.manifestModule = manifestModule; + externalModules = new Module[manifestModule.File.records.Length]; + } + + public override string Location + { + get { return location ?? ""; } + } + + public override AssemblyName GetName() + { + return GetNameImpl(ref manifestModule.AssemblyTable.records[0]); + } + + private AssemblyName GetNameImpl(ref AssemblyTable.Record rec) + { + AssemblyName name = new AssemblyName(); + name.Name = manifestModule.GetString(rec.Name); + name.Version = new Version(rec.MajorVersion, rec.MinorVersion, rec.BuildNumber, rec.RevisionNumber); + if (rec.PublicKey != 0) + { + name.SetPublicKey(manifestModule.GetBlobCopy(rec.PublicKey)); + } + else + { + name.SetPublicKey(Empty.Array); + } + if (rec.Culture != 0) + { + name.Culture = manifestModule.GetString(rec.Culture); + } + else + { + name.Culture = ""; + } + name.HashAlgorithm = (AssemblyHashAlgorithm)rec.HashAlgId; + name.CodeBase = this.CodeBase; + PortableExecutableKinds peKind; + ImageFileMachine machine; + manifestModule.GetPEKind(out peKind, out machine); + switch (machine) + { + case ImageFileMachine.I386: + // FXBUG we copy the .NET bug that Preferred32Bit implies x86 + if ((peKind & (PortableExecutableKinds.Required32Bit | PortableExecutableKinds.Preferred32Bit)) != 0) + { + name.ProcessorArchitecture = ProcessorArchitecture.X86; + } + else if ((rec.Flags & 0x70) == 0x70) + { + // it's a reference assembly + name.ProcessorArchitecture = ProcessorArchitecture.None; + } + else + { + name.ProcessorArchitecture = ProcessorArchitecture.MSIL; + } + break; + case ImageFileMachine.IA64: + name.ProcessorArchitecture = ProcessorArchitecture.IA64; + break; + case ImageFileMachine.AMD64: + name.ProcessorArchitecture = ProcessorArchitecture.Amd64; + break; + case ImageFileMachine.ARM: + name.ProcessorArchitecture = ProcessorArchitecture.Arm; + break; + } + name.RawFlags = (AssemblyNameFlags)rec.Flags; + return name; + } + + public override Type[] GetTypes() + { + if (externalModules.Length == 0) + { + return manifestModule.GetTypes(); + } + + List list = new List(); + foreach (Module module in GetModules(false)) + { + list.AddRange(module.GetTypes()); + } + return list.ToArray(); + } + + internal override Type FindType(TypeName typeName) + { + Type type = manifestModule.FindType(typeName); + for (int i = 0; type == null && i < externalModules.Length; i++) + { + if ((manifestModule.File.records[i].Flags & ContainsNoMetaData) == 0) + { + type = GetModule(i).FindType(typeName); + } + } + return type; + } + + internal override Type FindTypeIgnoreCase(TypeName lowerCaseName) + { + Type type = manifestModule.FindTypeIgnoreCase(lowerCaseName); + for (int i = 0; type == null && i < externalModules.Length; i++) + { + if ((manifestModule.File.records[i].Flags & ContainsNoMetaData) == 0) + { + type = GetModule(i).FindTypeIgnoreCase(lowerCaseName); + } + } + return type; + } + + public override string ImageRuntimeVersion + { + get { return manifestModule.__ImageRuntimeVersion; } + } + + public override Module ManifestModule + { + get { return manifestModule; } + } + + public override Module[] GetLoadedModules(bool getResourceModules) + { + List list = new List(); + list.Add(manifestModule); + foreach (Module m in externalModules) + { + if (m != null) + { + list.Add(m); + } + } + return list.ToArray(); + } + + public override Module[] GetModules(bool getResourceModules) + { + if (externalModules.Length == 0) + { + return new Module[] { manifestModule }; + } + else + { + List list = new List(); + list.Add(manifestModule); + for (int i = 0; i < manifestModule.File.records.Length; i++) + { + if (getResourceModules || (manifestModule.File.records[i].Flags & ContainsNoMetaData) == 0) + { + list.Add(GetModule(i)); + } + } + return list.ToArray(); + } + } + + public override Module GetModule(string name) + { + if (name.Equals(manifestModule.ScopeName, StringComparison.OrdinalIgnoreCase)) + { + return manifestModule; + } + int index = GetModuleIndex(name); + if (index != -1) + { + return GetModule(index); + } + return null; + } + + private int GetModuleIndex(string name) + { + for (int i = 0; i < manifestModule.File.records.Length; i++) + { + if (name.Equals(manifestModule.GetString(manifestModule.File.records[i].Name), StringComparison.OrdinalIgnoreCase)) + { + return i; + } + } + return -1; + } + + private Module GetModule(int index) + { + if (externalModules[index] != null) + { + return externalModules[index]; + } + return LoadModule(index, null, manifestModule.GetString(manifestModule.File.records[index].Name)); + } + + private Module LoadModule(int index, byte[] rawModule, string name) + { + string location = name == null ? null : Path.Combine(Path.GetDirectoryName(this.location), name); + if ((manifestModule.File.records[index].Flags & ContainsNoMetaData) != 0) + { + return externalModules[index] = new ResourceModule(manifestModule, index, location); + } + else + { + if (rawModule == null) + { + try + { + rawModule = File.ReadAllBytes(location); + } + catch (FileNotFoundException) + { + if (resolvers != null) + { + ResolveEventArgs arg = new ResolveEventArgs(name, this); + foreach (ModuleResolveEventHandler resolver in resolvers) + { + Module module = resolver(this, arg); + if (module != null) + { + return module; + } + } + } + if (universe.MissingMemberResolution) + { + return externalModules[index] = new MissingModule(this, index); + } + throw; + } + } + return externalModules[index] = new ModuleReader(this, manifestModule.universe, new MemoryStream(rawModule), location, false); + } + } + + public override Module LoadModule(string moduleName, byte[] rawModule) + { + int index = GetModuleIndex(moduleName); + if (index == -1) + { + throw new ArgumentException(); + } + if (externalModules[index] != null) + { + return externalModules[index]; + } + return LoadModule(index, rawModule, null); + } + + public override MethodInfo EntryPoint + { + get { return manifestModule.GetEntryPoint(); } + } + + public override string[] GetManifestResourceNames() + { + return manifestModule.GetManifestResourceNames(); + } + + public override ManifestResourceInfo GetManifestResourceInfo(string resourceName) + { + return manifestModule.GetManifestResourceInfo(resourceName); + } + + public override Stream GetManifestResourceStream(string resourceName) + { + return manifestModule.GetManifestResourceStream(resourceName); + } + + public override AssemblyName[] GetReferencedAssemblies() + { + return manifestModule.__GetReferencedAssemblies(); + } + + protected override AssemblyNameFlags GetAssemblyFlags() + { + return (AssemblyNameFlags)manifestModule.AssemblyTable.records[0].Flags; + } + + internal string Name + { + get { return manifestModule.GetString(manifestModule.AssemblyTable.records[0].Name); } + } + + internal override IList GetCustomAttributesData(Type attributeType) + { + return CustomAttributeData.GetCustomAttributesImpl(null, manifestModule, 0x20000001, attributeType) ?? CustomAttributeData.EmptyList; + } + } +} diff --git a/reflect/Reader/Authenticode.cs b/reflect/Reader/Authenticode.cs new file mode 100644 index 0000000..5dff8cf --- /dev/null +++ b/reflect/Reader/Authenticode.cs @@ -0,0 +1,185 @@ +/* + Copyright (C) 2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +#if !NO_AUTHENTICODE +using System; +using System.IO; +using System.Security.Cryptography; +using System.Security.Cryptography.Pkcs; +using System.Security.Cryptography.X509Certificates; + +namespace IKVM.Reflection.Reader +{ + // This code is based on trial-and-error and some inspiration from the Mono.Security library. + // It almost certainly has bugs and/or design flaws. + static class Authenticode + { + private const ushort IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b; + private const ushort IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b; + private const int WIN_CERT_REVISION_2_0 = 0x0200; + private const int WIN_CERT_TYPE_PKCS_SIGNED_DATA = 0x0002; + + internal static X509Certificate GetSignerCertificate(Stream stream) + { + stream.Seek(60, SeekOrigin.Begin); + BinaryReader br = new BinaryReader(stream); + int peSignatureOffset = br.ReadInt32(); + int checksumOffset = peSignatureOffset + 24 + 64; + // seek to the IMAGE_OPTIONAL_HEADER + stream.Seek(peSignatureOffset + 24, SeekOrigin.Begin); + int certificateTableDataDirectoryOffset; + switch (br.ReadUInt16()) + { + case IMAGE_NT_OPTIONAL_HDR32_MAGIC: + certificateTableDataDirectoryOffset = peSignatureOffset + 24 + (64 + 4 * 8) + 8 * 4; + break; + case IMAGE_NT_OPTIONAL_HDR64_MAGIC: + certificateTableDataDirectoryOffset = peSignatureOffset + 24 + (64 + 4 * 8 + 16) + 8 * 4; + break; + default: + throw new BadImageFormatException(); + } + stream.Seek(certificateTableDataDirectoryOffset, SeekOrigin.Begin); + int certificateTableOffset = br.ReadInt32(); + int certificateTableLength = br.ReadInt32(); + + stream.Seek(certificateTableOffset, SeekOrigin.Begin); + int dwLength = br.ReadInt32(); + short wRevision = br.ReadInt16(); + short wCertificateType = br.ReadInt16(); + if (wRevision != WIN_CERT_REVISION_2_0) + { + return null; + } + if (wCertificateType != WIN_CERT_TYPE_PKCS_SIGNED_DATA) + { + return null; + } + byte[] buf = new byte[certificateTableLength - 8]; + stream.Read(buf, 0, buf.Length); + + SignedCms cms = new SignedCms(); + try + { + cms.Decode(buf); + cms.CheckSignature(false); + } + catch (CryptographicException) + { + return null; + } + SignerInfo signerInfo = cms.SignerInfos[0]; + + int[] offsets = new int[] { checksumOffset, certificateTableDataDirectoryOffset, certificateTableOffset }; + int[] lengths = new int[] { 4, 8, certificateTableLength }; + byte[] actualHash = ComputeHashWithSkip(stream, signerInfo.DigestAlgorithm.FriendlyName, offsets, lengths); + byte[] requiredHash = DecodeASN1(cms.ContentInfo.Content, 0, 1, 1); + + if (requiredHash == null || actualHash.Length != requiredHash.Length) + { + return null; + } + + for (int i = 0; i < actualHash.Length; i++) + { + if (actualHash[i] != requiredHash[i]) + { + return null; + } + } + + return signerInfo.Certificate; + } + + private static byte[] ComputeHashWithSkip(Stream stream, string hashAlgorithm, int[] skipOffsets, int[] skipLengths) + { + using (HashAlgorithm hash = HashAlgorithm.Create(hashAlgorithm)) + { + using (CryptoStream cs = new CryptoStream(Stream.Null, hash, CryptoStreamMode.Write)) + { + stream.Seek(0, SeekOrigin.Begin); + byte[] buf = new byte[8192]; + HashChunk(stream, cs, buf, skipOffsets[0]); + stream.Seek(skipLengths[0], SeekOrigin.Current); + for (int i = 1; i < skipOffsets.Length; i++) + { + HashChunk(stream, cs, buf, skipOffsets[i] - (skipOffsets[i - 1] + skipLengths[i - 1])); + stream.Seek(skipLengths[i], SeekOrigin.Current); + } + HashChunk(stream, cs, buf, (int)stream.Length - (skipOffsets[skipOffsets.Length - 1] + skipLengths[skipLengths.Length - 1])); + } + return hash.Hash; + } + } + + private static void HashChunk(Stream stream, CryptoStream cs, byte[] buf, int length) + { + while (length > 0) + { + int read = stream.Read(buf, 0, Math.Min(buf.Length, length)); + cs.Write(buf, 0, read); + length -= read; + } + } + + private static byte[] DecodeASN1(byte[] buf, params int[] indexes) + { + return DecodeASN1(buf, 0, buf.Length, 0, indexes); + } + + private static byte[] DecodeASN1(byte[] buf, int pos, int end, int depth, int[] indexes) + { + for (int index = 0; pos < end; index++) + { + int tag = buf[pos++]; + int length = buf[pos++]; + if (length > 128) + { + int lenlen = length & 0x7F; + length = 0; + for (int i = 0; i < lenlen; i++) + { + length = length * 256 + buf[pos++]; + } + } + if (indexes[depth] == index) + { + if (depth == indexes.Length - 1) + { + byte[] data = new byte[length]; + Buffer.BlockCopy(buf, pos, data, 0, length); + return data; + } + if ((tag & 0x20) == 0) + { + return null; + } + return DecodeASN1(buf, pos, pos + length, depth + 1, indexes); + } + pos += length; + } + return null; + } + } +} +#endif // !NO_AUTHENTICODE diff --git a/reflect/Reader/ByteReader.cs b/reflect/Reader/ByteReader.cs new file mode 100644 index 0000000..e85328b --- /dev/null +++ b/reflect/Reader/ByteReader.cs @@ -0,0 +1,217 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; + +namespace IKVM.Reflection.Reader +{ + sealed class ByteReader + { + private byte[] buffer; + private int pos; + private int end; + + internal ByteReader(byte[] buffer, int offset, int length) + { + this.buffer = buffer; + this.pos = offset; + this.end = pos + length; + } + + internal static ByteReader FromBlob(byte[] blobHeap, int blob) + { + ByteReader br = new ByteReader(blobHeap, blob, 4); + int length = br.ReadCompressedUInt(); + br.end = br.pos + length; + return br; + } + + internal int Length + { + get { return end - pos; } + } + + internal byte PeekByte() + { + if (pos == end) + throw new BadImageFormatException(); + return buffer[pos]; + } + + internal byte ReadByte() + { + if (pos == end) + throw new BadImageFormatException(); + return buffer[pos++]; + } + + internal byte[] ReadBytes(int count) + { + if (count < 0) + throw new BadImageFormatException(); + if (end - pos < count) + throw new BadImageFormatException(); + byte[] buf = new byte[count]; + Buffer.BlockCopy(buffer, pos, buf, 0, count); + pos += count; + return buf; + } + + internal int ReadCompressedUInt() + { + byte b1 = ReadByte(); + if (b1 <= 0x7F) + { + return b1; + } + else if ((b1 & 0xC0) == 0x80) + { + byte b2 = ReadByte(); + return ((b1 & 0x3F) << 8) | b2; + } + else + { + byte b2 = ReadByte(); + byte b3 = ReadByte(); + byte b4 = ReadByte(); + return ((b1 & 0x3F) << 24) + (b2 << 16) + (b3 << 8) + b4; + } + } + + internal int ReadCompressedInt() + { + byte b1 = PeekByte(); + int value = ReadCompressedUInt(); + if ((value & 1) == 0) + { + return value >> 1; + } + else + { + switch (b1 & 0xC0) + { + case 0: + case 0x40: + return (value >> 1) - 0x40; + case 0x80: + return (value >> 1) - 0x2000; + default: + return (value >> 1) - 0x10000000; + } + } + } + + internal string ReadString() + { + if (PeekByte() == 0xFF) + { + pos++; + return null; + } + int length = ReadCompressedUInt(); + string str = Encoding.UTF8.GetString(buffer, pos, length); + pos += length; + return str; + } + + internal char ReadChar() + { + return (char)ReadInt16(); + } + + internal sbyte ReadSByte() + { + return (sbyte)ReadByte(); + } + + internal short ReadInt16() + { + if (end - pos < 2) + throw new BadImageFormatException(); + byte b1 = buffer[pos++]; + byte b2 = buffer[pos++]; + return (short)(b1 | (b2 << 8)); + } + + internal ushort ReadUInt16() + { + return (ushort)ReadInt16(); + } + + internal int ReadInt32() + { + if (end - pos < 4) + throw new BadImageFormatException(); + byte b1 = buffer[pos++]; + byte b2 = buffer[pos++]; + byte b3 = buffer[pos++]; + byte b4 = buffer[pos++]; + return (int)(b1 | (b2 << 8) | (b3 << 16) | (b4 << 24)); + } + + internal uint ReadUInt32() + { + return (uint)ReadInt32(); + } + + internal long ReadInt64() + { + ulong lo = ReadUInt32(); + ulong hi = ReadUInt32(); + return (long)(lo | (hi << 32)); + } + + internal ulong ReadUInt64() + { + return (ulong)ReadInt64(); + } + + internal float ReadSingle() + { + return SingleConverter.Int32BitsToSingle(ReadInt32()); + } + + internal double ReadDouble() + { + return BitConverter.Int64BitsToDouble(ReadInt64()); + } + + internal ByteReader Slice(int length) + { + if (end - pos < length) + throw new BadImageFormatException(); + ByteReader br = new ByteReader(buffer, pos, length); + pos += length; + return br; + } + + // NOTE this method only works if the original offset was aligned and for alignments that are a power of 2 + internal void Align(int alignment) + { + alignment--; + pos = (pos + alignment) & ~alignment; + } + } +} diff --git a/reflect/Reader/EventInfoImpl.cs b/reflect/Reader/EventInfoImpl.cs new file mode 100644 index 0000000..68d0bc0 --- /dev/null +++ b/reflect/Reader/EventInfoImpl.cs @@ -0,0 +1,166 @@ +/* + Copyright (C) 2009-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; +using IKVM.Reflection.Metadata; + +namespace IKVM.Reflection.Reader +{ + sealed class EventInfoImpl : EventInfo + { + private readonly ModuleReader module; + private readonly Type declaringType; + private readonly int index; + private bool isPublic; + private bool isNonPrivate; + private bool isStatic; + private bool flagsCached; + + internal EventInfoImpl(ModuleReader module, Type declaringType, int index) + { + this.module = module; + this.declaringType = declaringType; + this.index = index; + } + + public override bool Equals(object obj) + { + EventInfoImpl other = obj as EventInfoImpl; + return other != null && other.declaringType == declaringType && other.index == index; + } + + public override int GetHashCode() + { + return declaringType.GetHashCode() * 123 + index; + } + + public override EventAttributes Attributes + { + get { return (EventAttributes)module.Event.records[index].EventFlags; } + } + + public override MethodInfo GetAddMethod(bool nonPublic) + { + return module.MethodSemantics.GetMethod(module, this.MetadataToken, nonPublic, MethodSemanticsTable.AddOn); + } + + public override MethodInfo GetRaiseMethod(bool nonPublic) + { + return module.MethodSemantics.GetMethod(module, this.MetadataToken, nonPublic, MethodSemanticsTable.Fire); + } + + public override MethodInfo GetRemoveMethod(bool nonPublic) + { + return module.MethodSemantics.GetMethod(module, this.MetadataToken, nonPublic, MethodSemanticsTable.RemoveOn); + } + + public override MethodInfo[] GetOtherMethods(bool nonPublic) + { + return module.MethodSemantics.GetMethods(module, this.MetadataToken, nonPublic, MethodSemanticsTable.Other); + } + + public override MethodInfo[] __GetMethods() + { + return module.MethodSemantics.GetMethods(module, this.MetadataToken, true, -1); + } + + public override Type EventHandlerType + { + get { return module.ResolveType(module.Event.records[index].EventType, declaringType); } + } + + public override string Name + { + get { return module.GetString(module.Event.records[index].Name); } + } + + public override Type DeclaringType + { + get { return declaringType; } + } + + public override Module Module + { + get { return module; } + } + + public override int MetadataToken + { + get { return (EventTable.Index << 24) + index + 1; } + } + + internal override bool IsPublic + { + get + { + if (!flagsCached) + { + ComputeFlags(); + } + return isPublic; + } + } + + internal override bool IsNonPrivate + { + get + { + if (!flagsCached) + { + ComputeFlags(); + } + return isNonPrivate; + } + } + + internal override bool IsStatic + { + get + { + if (!flagsCached) + { + ComputeFlags(); + } + return isStatic; + } + } + + private void ComputeFlags() + { + module.MethodSemantics.ComputeFlags(module, this.MetadataToken, out isPublic, out isNonPrivate, out isStatic); + flagsCached = true; + } + + internal override bool IsBaked + { + get { return true; } + } + + internal override int GetCurrentToken() + { + return this.MetadataToken; + } + } +} diff --git a/reflect/Reader/Field.cs b/reflect/Reader/Field.cs new file mode 100644 index 0000000..2aba292 --- /dev/null +++ b/reflect/Reader/Field.cs @@ -0,0 +1,136 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; +using IKVM.Reflection.Metadata; + +namespace IKVM.Reflection.Reader +{ + sealed class FieldDefImpl : FieldInfo + { + private readonly ModuleReader module; + private readonly TypeDefImpl declaringType; + private readonly int index; + private FieldSignature lazyFieldSig; + + internal FieldDefImpl(ModuleReader module, TypeDefImpl declaringType, int index) + { + this.module = module; + this.declaringType = declaringType; + this.index = index; + } + + public override FieldAttributes Attributes + { + get { return (FieldAttributes)module.Field.records[index].Flags; } + } + + public override Type DeclaringType + { + get { return declaringType.IsModulePseudoType ? null : declaringType; } + } + + public override string Name + { + get { return module.GetString(module.Field.records[index].Name); } + } + + public override string ToString() + { + return this.FieldType.Name + " " + this.Name; + } + + public override Module Module + { + get { return module; } + } + + public override int MetadataToken + { + get { return (FieldTable.Index << 24) + index + 1; } + } + + public override object GetRawConstantValue() + { + return module.Constant.GetRawConstantValue(module, this.MetadataToken); + } + + public override void __GetDataFromRVA(byte[] data, int offset, int length) + { + int rva = this.__FieldRVA; + if (rva == 0) + { + // C++ assemblies can have fields that have an RVA that is zero + Array.Clear(data, offset, length); + return; + } + module.__ReadDataFromRVA(rva, data, offset, length); + } + + public override int __FieldRVA + { + get + { + foreach (int i in module.FieldRVA.Filter(index + 1)) + { + return module.FieldRVA.records[i].RVA; + } + throw new InvalidOperationException(); + } + } + + public override bool __TryGetFieldOffset(out int offset) + { + foreach (int i in this.Module.FieldLayout.Filter(index + 1)) + { + offset = this.Module.FieldLayout.records[i].Offset; + return true; + } + offset = 0; + return false; + } + + internal override FieldSignature FieldSignature + { + get { return lazyFieldSig ?? (lazyFieldSig = FieldSignature.ReadSig(module, module.GetBlob(module.Field.records[index].Signature), declaringType)); } + } + + internal override int ImportTo(Emit.ModuleBuilder module) + { + return module.ImportMethodOrField(declaringType, this.Name, this.FieldSignature); + } + + internal override int GetCurrentToken() + { + return this.MetadataToken; + } + + internal override bool IsBaked + { + get { return true; } + } + } +} diff --git a/reflect/Reader/GenericTypeParameter.cs b/reflect/Reader/GenericTypeParameter.cs new file mode 100644 index 0000000..e030566 --- /dev/null +++ b/reflect/Reader/GenericTypeParameter.cs @@ -0,0 +1,380 @@ +/* + Copyright (C) 2009-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; +using IKVM.Reflection.Metadata; + +namespace IKVM.Reflection.Reader +{ + abstract class TypeParameterType : TypeInfo + { + protected TypeParameterType(byte sigElementType) + : base(sigElementType) + { + } + + public sealed override string AssemblyQualifiedName + { + get { return null; } + } + + public sealed override bool IsValueType + { + get { return (this.GenericParameterAttributes & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0; } + } + + public sealed override Type BaseType + { + get + { + foreach (Type type in GetGenericParameterConstraints()) + { + if (!type.IsInterface && !type.IsGenericParameter) + { + return type; + } + } + return this.IsValueType ? this.Module.universe.System_ValueType : this.Module.universe.System_Object; + } + } + + public override Type[] __GetDeclaredInterfaces() + { + List list = new List(); + foreach (Type type in GetGenericParameterConstraints()) + { + if (type.IsInterface) + { + list.Add(type); + } + } + return list.ToArray(); + } + + public sealed override TypeAttributes Attributes + { + get { return TypeAttributes.Public; } + } + + public sealed override string FullName + { + get { return null; } + } + + public sealed override string ToString() + { + return this.Name; + } + + protected sealed override bool ContainsMissingTypeImpl + { + get { return ContainsMissingType(GetGenericParameterConstraints()); } + } + } + + sealed class UnboundGenericMethodParameter : TypeParameterType + { + private static readonly DummyModule module = new DummyModule(); + private readonly int position; + + private sealed class DummyModule : NonPEModule + { + internal DummyModule() + : base(new Universe()) + { + } + + protected override Exception NotSupportedException() + { + return new InvalidOperationException(); + } + + protected override Exception ArgumentOutOfRangeException() + { + return new InvalidOperationException(); + } + + public override bool Equals(object obj) + { + throw new InvalidOperationException(); + } + + public override int GetHashCode() + { + throw new InvalidOperationException(); + } + + public override string ToString() + { + throw new InvalidOperationException(); + } + + public override int MDStreamVersion + { + get { throw new InvalidOperationException(); } + } + + public override Assembly Assembly + { + get { throw new InvalidOperationException(); } + } + + internal override Type FindType(TypeName typeName) + { + throw new InvalidOperationException(); + } + + internal override Type FindTypeIgnoreCase(TypeName lowerCaseName) + { + throw new InvalidOperationException(); + } + + internal override void GetTypesImpl(List list) + { + throw new InvalidOperationException(); + } + + public override string FullyQualifiedName + { + get { throw new InvalidOperationException(); } + } + + public override string Name + { + get { throw new InvalidOperationException(); } + } + + public override Guid ModuleVersionId + { + get { throw new InvalidOperationException(); } + } + + public override string ScopeName + { + get { throw new InvalidOperationException(); } + } + } + + internal static Type Make(int position) + { + return module.universe.CanonicalizeType(new UnboundGenericMethodParameter(position)); + } + + private UnboundGenericMethodParameter(int position) + : base(Signature.ELEMENT_TYPE_MVAR) + { + this.position = position; + } + + public override bool Equals(object obj) + { + UnboundGenericMethodParameter other = obj as UnboundGenericMethodParameter; + return other != null && other.position == position; + } + + public override int GetHashCode() + { + return position; + } + + public override string Namespace + { + get { throw new InvalidOperationException(); } + } + + public override string Name + { + get { throw new InvalidOperationException(); } + } + + public override int MetadataToken + { + get { throw new InvalidOperationException(); } + } + + public override Module Module + { + get { return module; } + } + + public override int GenericParameterPosition + { + get { return position; } + } + + public override Type DeclaringType + { + get { return null; } + } + + public override MethodBase DeclaringMethod + { + get { throw new InvalidOperationException(); } + } + + public override Type[] GetGenericParameterConstraints() + { + throw new InvalidOperationException(); + } + + public override CustomModifiers[] __GetGenericParameterConstraintCustomModifiers() + { + throw new InvalidOperationException(); + } + + public override GenericParameterAttributes GenericParameterAttributes + { + get { throw new InvalidOperationException(); } + } + + internal override Type BindTypeParameters(IGenericBinder binder) + { + return binder.BindMethodParameter(this); + } + + internal override bool IsBaked + { + get { throw new InvalidOperationException(); } + } + } + + sealed class GenericTypeParameter : TypeParameterType + { + private readonly ModuleReader module; + private readonly int index; + + internal GenericTypeParameter(ModuleReader module, int index, byte sigElementType) + : base(sigElementType) + { + this.module = module; + this.index = index; + } + + public override bool Equals(object obj) + { + return base.Equals(obj); + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + + public override string Namespace + { + get { return DeclaringType.Namespace; } + } + + public override string Name + { + get { return module.GetString(module.GenericParam.records[index].Name); } + } + + public override Module Module + { + get { return module; } + } + + public override int MetadataToken + { + get { return (GenericParamTable.Index << 24) + index + 1; } + } + + public override int GenericParameterPosition + { + get { return module.GenericParam.records[index].Number; } + } + + public override Type DeclaringType + { + get + { + int owner = module.GenericParam.records[index].Owner; + return (owner >> 24) == TypeDefTable.Index ? module.ResolveType(owner) : null; + } + } + + public override MethodBase DeclaringMethod + { + get + { + int owner = module.GenericParam.records[index].Owner; + return (owner >> 24) == MethodDefTable.Index ? module.ResolveMethod(owner) : null; + } + } + + public override Type[] GetGenericParameterConstraints() + { + IGenericContext context = (this.DeclaringMethod as IGenericContext) ?? this.DeclaringType; + List list = new List(); + foreach (int i in module.GenericParamConstraint.Filter(this.MetadataToken)) + { + list.Add(module.ResolveType(module.GenericParamConstraint.records[i].Constraint, context)); + } + return list.ToArray(); + } + + public override CustomModifiers[] __GetGenericParameterConstraintCustomModifiers() + { + IGenericContext context = (this.DeclaringMethod as IGenericContext) ?? this.DeclaringType; + List list = new List(); + foreach (int i in module.GenericParamConstraint.Filter(this.MetadataToken)) + { + CustomModifiers mods = new CustomModifiers(); + int metadataToken = module.GenericParamConstraint.records[i].Constraint; + if ((metadataToken >> 24) == TypeSpecTable.Index) + { + int index = (metadataToken & 0xFFFFFF) - 1; + mods = CustomModifiers.Read(module, module.GetBlob(module.TypeSpec.records[index]), context); + } + list.Add(mods); + } + return list.ToArray(); + } + + public override GenericParameterAttributes GenericParameterAttributes + { + get { return (GenericParameterAttributes)module.GenericParam.records[index].Flags; } + } + + internal override Type BindTypeParameters(IGenericBinder binder) + { + int owner = module.GenericParam.records[index].Owner; + if ((owner >> 24) == MethodDefTable.Index) + { + return binder.BindMethodParameter(this); + } + else + { + return binder.BindTypeParameter(this); + } + } + + internal override bool IsBaked + { + get { return true; } + } + } +} diff --git a/reflect/Reader/MetadataReader.cs b/reflect/Reader/MetadataReader.cs new file mode 100644 index 0000000..28a4720 --- /dev/null +++ b/reflect/Reader/MetadataReader.cs @@ -0,0 +1,406 @@ +/* + Copyright (C) 2009-2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; +using IKVM.Reflection.Metadata; + +namespace IKVM.Reflection.Reader +{ + sealed class MetadataReader : MetadataRW + { + private readonly Stream stream; + private const int bufferLength = 2048; + private readonly byte[] buffer = new byte[bufferLength]; + private int pos = bufferLength; + + internal MetadataReader(ModuleReader module, Stream stream, byte heapSizes) + : base(module, (heapSizes & 0x01) != 0, (heapSizes & 0x02) != 0, (heapSizes & 0x04) != 0) + { + this.stream = stream; + } + + private void FillBuffer(int needed) + { + int count = bufferLength - pos; + if (count != 0) + { + // move remaining bytes to the front of the buffer + Buffer.BlockCopy(buffer, pos, buffer, 0, count); + } + pos = 0; + + while (count < needed) + { + int len = stream.Read(buffer, count, bufferLength - count); + if (len == 0) + { + throw new BadImageFormatException(); + } + count += len; + } + + if (count != bufferLength) + { + // we didn't fill the buffer completely, so have to restore the invariant + // that all data from pos up until the end of the buffer is valid + Buffer.BlockCopy(buffer, 0, buffer, bufferLength - count, count); + pos = bufferLength - count; + } + } + + internal ushort ReadUInt16() + { + return (ushort)ReadInt16(); + } + + internal short ReadInt16() + { + if (pos > bufferLength - 2) + { + FillBuffer(2); + } + byte b1 = buffer[pos++]; + byte b2 = buffer[pos++]; + return (short)(b1 | (b2 << 8)); + } + + internal int ReadInt32() + { + if (pos > bufferLength - 4) + { + FillBuffer(4); + } + byte b1 = buffer[pos++]; + byte b2 = buffer[pos++]; + byte b3 = buffer[pos++]; + byte b4 = buffer[pos++]; + return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24); + } + + private int ReadIndex(bool big) + { + if (big) + { + return ReadInt32(); + } + else + { + return ReadUInt16(); + } + } + + internal int ReadStringIndex() + { + return ReadIndex(bigStrings); + } + + internal int ReadGuidIndex() + { + return ReadIndex(bigGuids); + } + + internal int ReadBlobIndex() + { + return ReadIndex(bigBlobs); + } + + internal int ReadResolutionScope() + { + int codedIndex = ReadIndex(bigResolutionScope); + switch (codedIndex & 3) + { + case 0: + return (ModuleTable.Index << 24) + (codedIndex >> 2); + case 1: + return (ModuleRefTable.Index << 24) + (codedIndex >> 2); + case 2: + return (AssemblyRefTable.Index << 24) + (codedIndex >> 2); + case 3: + return (TypeRefTable.Index << 24) + (codedIndex >> 2); + default: + throw new BadImageFormatException(); + } + } + + internal int ReadTypeDefOrRef() + { + int codedIndex = ReadIndex(bigTypeDefOrRef); + switch (codedIndex & 3) + { + case 0: + return (TypeDefTable.Index << 24) + (codedIndex >> 2); + case 1: + return (TypeRefTable.Index << 24) + (codedIndex >> 2); + case 2: + return (TypeSpecTable.Index << 24) + (codedIndex >> 2); + default: + throw new BadImageFormatException(); + } + } + + internal int ReadMemberRefParent() + { + int codedIndex = ReadIndex(bigMemberRefParent); + switch (codedIndex & 7) + { + case 0: + return (TypeDefTable.Index << 24) + (codedIndex >> 3); + case 1: + return (TypeRefTable.Index << 24) + (codedIndex >> 3); + case 2: + return (ModuleRefTable.Index << 24) + (codedIndex >> 3); + case 3: + return (MethodDefTable.Index << 24) + (codedIndex >> 3); + case 4: + return (TypeSpecTable.Index << 24) + (codedIndex >> 3); + default: + throw new BadImageFormatException(); + } + } + + internal int ReadHasCustomAttribute() + { + int codedIndex = ReadIndex(bigHasCustomAttribute); + switch (codedIndex & 31) + { + case 0: + return (MethodDefTable.Index << 24) + (codedIndex >> 5); + case 1: + return (FieldTable.Index << 24) + (codedIndex >> 5); + case 2: + return (TypeRefTable.Index << 24) + (codedIndex >> 5); + case 3: + return (TypeDefTable.Index << 24) + (codedIndex >> 5); + case 4: + return (ParamTable.Index << 24) + (codedIndex >> 5); + case 5: + return (InterfaceImplTable.Index << 24) + (codedIndex >> 5); + case 6: + return (MemberRefTable.Index << 24) + (codedIndex >> 5); + case 7: + return (ModuleTable.Index << 24) + (codedIndex >> 5); + case 8: + throw new BadImageFormatException(); + case 9: + return (PropertyTable.Index << 24) + (codedIndex >> 5); + case 10: + return (EventTable.Index << 24) + (codedIndex >> 5); + case 11: + return (StandAloneSigTable.Index << 24) + (codedIndex >> 5); + case 12: + return (ModuleRefTable.Index << 24) + (codedIndex >> 5); + case 13: + return (TypeSpecTable.Index << 24) + (codedIndex >> 5); + case 14: + return (AssemblyTable.Index << 24) + (codedIndex >> 5); + case 15: + return (AssemblyRefTable.Index << 24) + (codedIndex >> 5); + case 16: + return (FileTable.Index << 24) + (codedIndex >> 5); + case 17: + return (ExportedTypeTable.Index << 24) + (codedIndex >> 5); + case 18: + return (ManifestResourceTable.Index << 24) + (codedIndex >> 5); + case 19: + return (GenericParamTable.Index << 24) + (codedIndex >> 5); + default: + throw new BadImageFormatException(); + } + } + + internal int ReadCustomAttributeType() + { + int codedIndex = ReadIndex(bigCustomAttributeType); + switch (codedIndex & 7) + { + case 2: + return (MethodDefTable.Index << 24) + (codedIndex >> 3); + case 3: + return (MemberRefTable.Index << 24) + (codedIndex >> 3); + default: + throw new BadImageFormatException(); + } + } + + internal int ReadMethodDefOrRef() + { + int codedIndex = ReadIndex(bigMethodDefOrRef); + switch (codedIndex & 1) + { + case 0: + return (MethodDefTable.Index << 24) + (codedIndex >> 1); + case 1: + return (MemberRefTable.Index << 24) + (codedIndex >> 1); + default: + throw new BadImageFormatException(); + } + } + + internal int ReadHasConstant() + { + int codedIndex = ReadIndex(bigHasConstant); + switch (codedIndex & 3) + { + case 0: + return (FieldTable.Index << 24) + (codedIndex >> 2); + case 1: + return (ParamTable.Index << 24) + (codedIndex >> 2); + case 2: + return (PropertyTable.Index << 24) + (codedIndex >> 2); + default: + throw new BadImageFormatException(); + } + } + + internal int ReadHasSemantics() + { + int codedIndex = ReadIndex(bigHasSemantics); + switch (codedIndex & 1) + { + case 0: + return (EventTable.Index << 24) + (codedIndex >> 1); + case 1: + return (PropertyTable.Index << 24) + (codedIndex >> 1); + default: + throw new BadImageFormatException(); + } + } + + internal int ReadHasFieldMarshal() + { + int codedIndex = ReadIndex(bigHasFieldMarshal); + switch (codedIndex & 1) + { + case 0: + return (FieldTable.Index << 24) + (codedIndex >> 1); + case 1: + return (ParamTable.Index << 24) + (codedIndex >> 1); + default: + throw new BadImageFormatException(); + } + } + + internal int ReadHasDeclSecurity() + { + int codedIndex = ReadIndex(bigHasDeclSecurity); + switch (codedIndex & 3) + { + case 0: + return (TypeDefTable.Index << 24) + (codedIndex >> 2); + case 1: + return (MethodDefTable.Index << 24) + (codedIndex >> 2); + case 2: + return (AssemblyTable.Index << 24) + (codedIndex >> 2); + default: + throw new BadImageFormatException(); + } + } + + internal int ReadTypeOrMethodDef() + { + int codedIndex = ReadIndex(bigTypeOrMethodDef); + switch (codedIndex & 1) + { + case 0: + return (TypeDefTable.Index << 24) + (codedIndex >> 1); + case 1: + return (MethodDefTable.Index << 24) + (codedIndex >> 1); + default: + throw new BadImageFormatException(); + } + } + + internal int ReadMemberForwarded() + { + int codedIndex = ReadIndex(bigMemberForwarded); + switch (codedIndex & 1) + { + case 0: + return (FieldTable.Index << 24) + (codedIndex >> 1); + case 1: + return (MethodDefTable.Index << 24) + (codedIndex >> 1); + default: + throw new BadImageFormatException(); + } + } + + internal int ReadImplementation() + { + int codedIndex = ReadIndex(bigImplementation); + switch (codedIndex & 3) + { + case 0: + return (FileTable.Index << 24) + (codedIndex >> 2); + case 1: + return (AssemblyRefTable.Index << 24) + (codedIndex >> 2); + case 2: + return (ExportedTypeTable.Index << 24) + (codedIndex >> 2); + default: + throw new BadImageFormatException(); + } + } + + internal int ReadField() + { + return ReadIndex(bigField); + } + + internal int ReadMethodDef() + { + return ReadIndex(bigMethodDef); + } + + internal int ReadParam() + { + return ReadIndex(bigParam); + } + + internal int ReadProperty() + { + return ReadIndex(bigProperty); + } + + internal int ReadEvent() + { + return ReadIndex(bigEvent); + } + + internal int ReadTypeDef() + { + return ReadIndex(bigTypeDef) | (TypeDefTable.Index << 24); + } + + internal int ReadGenericParam() + { + return ReadIndex(bigGenericParam) | (GenericParamTable.Index << 24); + } + + internal int ReadModuleRef() + { + return ReadIndex(bigModuleRef) | (ModuleRefTable.Index << 24); + } + } +} diff --git a/reflect/Reader/Method.cs b/reflect/Reader/Method.cs new file mode 100644 index 0000000..d94f019 --- /dev/null +++ b/reflect/Reader/Method.cs @@ -0,0 +1,394 @@ +/* + Copyright (C) 2009-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; +using IKVM.Reflection.Metadata; + +namespace IKVM.Reflection.Reader +{ + sealed class MethodDefImpl : MethodInfo + { + private readonly ModuleReader module; + private readonly int index; + private readonly TypeDefImpl declaringType; + private MethodSignature lazyMethodSignature; + private ParameterInfo returnParameter; + private ParameterInfo[] parameters; + private Type[] typeArgs; + + internal MethodDefImpl(ModuleReader module, TypeDefImpl declaringType, int index) + { + this.module = module; + this.index = index; + this.declaringType = declaringType; + } + + public override MethodBody GetMethodBody() + { + return GetMethodBody(this); + } + + internal MethodBody GetMethodBody(IGenericContext context) + { + if ((GetMethodImplementationFlags() & MethodImplAttributes.CodeTypeMask) != MethodImplAttributes.IL) + { + // method is not IL + return null; + } + int rva = module.MethodDef.records[index].RVA; + return rva == 0 ? null : new MethodBody(module, rva, context); + } + + public override int __MethodRVA + { + get { return module.MethodDef.records[index].RVA; } + } + + public override CallingConventions CallingConvention + { + get { return this.MethodSignature.CallingConvention; } + } + + public override MethodAttributes Attributes + { + get { return (MethodAttributes)module.MethodDef.records[index].Flags; } + } + + public override MethodImplAttributes GetMethodImplementationFlags() + { + return (MethodImplAttributes)module.MethodDef.records[index].ImplFlags; + } + + public override ParameterInfo[] GetParameters() + { + PopulateParameters(); + return (ParameterInfo[])parameters.Clone(); + } + + private void PopulateParameters() + { + if (parameters == null) + { + MethodSignature methodSignature = this.MethodSignature; + parameters = new ParameterInfo[methodSignature.GetParameterCount()]; + int parameter = module.MethodDef.records[index].ParamList - 1; + int end = module.MethodDef.records.Length > index + 1 ? module.MethodDef.records[index + 1].ParamList - 1 : module.Param.records.Length; + for (; parameter < end; parameter++) + { + int seq = module.Param.records[parameter].Sequence - 1; + if (seq == -1) + { + returnParameter = new ParameterInfoImpl(this, seq, parameter); + } + else + { + parameters[seq] = new ParameterInfoImpl(this, seq, parameter); + } + } + for (int i = 0; i < parameters.Length; i++) + { + if (parameters[i] == null) + { + parameters[i] = new ParameterInfoImpl(this, i, -1); + } + } + if (returnParameter == null) + { + returnParameter = new ParameterInfoImpl(this, -1, -1); + } + } + } + + internal override int ParameterCount + { + get { return this.MethodSignature.GetParameterCount(); } + } + + public override ParameterInfo ReturnParameter + { + get + { + PopulateParameters(); + return returnParameter; + } + } + + public override Type ReturnType + { + get + { + return this.ReturnParameter.ParameterType; + } + } + + public override Type DeclaringType + { + get { return declaringType.IsModulePseudoType ? null : declaringType; } + } + + public override string Name + { + get { return module.GetString(module.MethodDef.records[index].Name); } + } + + public override int MetadataToken + { + get { return (MethodDefTable.Index << 24) + index + 1; } + } + + public override bool IsGenericMethodDefinition + { + get + { + PopulateGenericArguments(); + return typeArgs.Length > 0; + } + } + + public override bool IsGenericMethod + { + get { return IsGenericMethodDefinition; } + } + + public override Type[] GetGenericArguments() + { + PopulateGenericArguments(); + return Util.Copy(typeArgs); + } + + private void PopulateGenericArguments() + { + if (typeArgs == null) + { + int token = this.MetadataToken; + int first = module.GenericParam.FindFirstByOwner(token); + if (first == -1) + { + typeArgs = Type.EmptyTypes; + } + else + { + List list = new List(); + int len = module.GenericParam.records.Length; + for (int i = first; i < len && module.GenericParam.records[i].Owner == token; i++) + { + list.Add(new GenericTypeParameter(module, i, Signature.ELEMENT_TYPE_MVAR)); + } + typeArgs = list.ToArray(); + } + } + } + + internal override Type GetGenericMethodArgument(int index) + { + PopulateGenericArguments(); + return typeArgs[index]; + } + + internal override int GetGenericMethodArgumentCount() + { + PopulateGenericArguments(); + return typeArgs.Length; + } + + public override MethodInfo GetGenericMethodDefinition() + { + if (this.IsGenericMethodDefinition) + { + return this; + } + throw new InvalidOperationException(); + } + + public override MethodInfo MakeGenericMethod(params Type[] typeArguments) + { + return new GenericMethodInstance(declaringType, this, typeArguments); + } + + public override Module Module + { + get { return module; } + } + + internal override MethodSignature MethodSignature + { + get { return lazyMethodSignature ?? (lazyMethodSignature = MethodSignature.ReadSig(module, module.GetBlob(module.MethodDef.records[index].Signature), this)); } + } + + internal override int ImportTo(Emit.ModuleBuilder module) + { + return module.ImportMethodOrField(declaringType, this.Name, this.MethodSignature); + } + + public override MethodInfo[] __GetMethodImpls() + { + Type[] typeArgs = null; + List list = null; + foreach (int i in module.MethodImpl.Filter(declaringType.MetadataToken)) + { + if (module.MethodImpl.records[i].MethodBody == this.MetadataToken) + { + if (typeArgs == null) + { + typeArgs = declaringType.GetGenericArguments(); + } + if (list == null) + { + list = new List(); + } + list.Add((MethodInfo)module.ResolveMethod(module.MethodImpl.records[i].MethodDeclaration, typeArgs, null)); + } + } + return Util.ToArray(list, Empty.Array); + } + + internal override int GetCurrentToken() + { + return this.MetadataToken; + } + + internal override bool IsBaked + { + get { return true; } + } + } + + sealed class ParameterInfoImpl : ParameterInfo + { + private readonly MethodDefImpl method; + private readonly int position; + private readonly int index; + + internal ParameterInfoImpl(MethodDefImpl method, int position, int index) + { + this.method = method; + this.position = position; + this.index = index; + } + + public override string Name + { + get { return index == -1 ? null : ((ModuleReader)this.Module).GetString(this.Module.Param.records[index].Name); } + } + + public override Type ParameterType + { + get { return position == -1 ? method.MethodSignature.GetReturnType(method) : method.MethodSignature.GetParameterType(method, position); } + } + + public override ParameterAttributes Attributes + { + get { return index == -1 ? ParameterAttributes.None : (ParameterAttributes)this.Module.Param.records[index].Flags; } + } + + public override int Position + { + get { return position; } + } + + public override object RawDefaultValue + { + get + { + if ((this.Attributes & ParameterAttributes.HasDefault) != 0) + { + return this.Module.Constant.GetRawConstantValue(this.Module, this.MetadataToken); + } + Universe universe = this.Module.universe; + if (this.ParameterType == universe.System_Decimal) + { + Type attr = universe.System_Runtime_CompilerServices_DecimalConstantAttribute; + if (attr != null) + { + foreach (CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(this, attr, false)) + { + IList args = cad.ConstructorArguments; + if (args.Count == 5) + { + if (args[0].ArgumentType == universe.System_Byte + && args[1].ArgumentType == universe.System_Byte + && args[2].ArgumentType == universe.System_Int32 + && args[3].ArgumentType == universe.System_Int32 + && args[4].ArgumentType == universe.System_Int32) + { + return new Decimal((int)args[4].Value, (int)args[3].Value, (int)args[2].Value, (byte)args[1].Value != 0, (byte)args[0].Value); + } + else if (args[0].ArgumentType == universe.System_Byte + && args[1].ArgumentType == universe.System_Byte + && args[2].ArgumentType == universe.System_UInt32 + && args[3].ArgumentType == universe.System_UInt32 + && args[4].ArgumentType == universe.System_UInt32) + { + return new Decimal(unchecked((int)(uint)args[4].Value), unchecked((int)(uint)args[3].Value), unchecked((int)(uint)args[2].Value), (byte)args[1].Value != 0, (byte)args[0].Value); + } + } + } + } + } + if ((this.Attributes & ParameterAttributes.Optional) != 0) + { + return Missing.Value; + } + return null; + } + } + + public override CustomModifiers __GetCustomModifiers() + { + return position == -1 + ? method.MethodSignature.GetReturnTypeCustomModifiers(method) + : method.MethodSignature.GetParameterCustomModifiers(method, position); + } + + public override bool __TryGetFieldMarshal(out FieldMarshal fieldMarshal) + { + return FieldMarshal.ReadFieldMarshal(this.Module, this.MetadataToken, out fieldMarshal); + } + + public override MemberInfo Member + { + get + { + // return the right ConstructorInfo wrapper + return method.Module.ResolveMethod(method.MetadataToken); + } + } + + public override int MetadataToken + { + get + { + // for parameters that don't have a row in the Param table, we return 0x08000000 (because index is -1 in that case), + // just like .NET + return (ParamTable.Index << 24) + index + 1; + } + } + + internal override Module Module + { + get { return method.Module; } + } + } +} diff --git a/reflect/Reader/ModuleReader.cs b/reflect/Reader/ModuleReader.cs new file mode 100644 index 0000000..4daa535 --- /dev/null +++ b/reflect/Reader/ModuleReader.cs @@ -0,0 +1,1304 @@ +/* + Copyright (C) 2009-2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.IO; +using System.Text; +using System.Collections.Generic; +using IKVM.Reflection.Metadata; + +namespace IKVM.Reflection.Reader +{ + sealed class StreamHeader + { + internal uint Offset; + internal uint Size; + internal string Name; + + internal void Read(BinaryReader br) + { + Offset = br.ReadUInt32(); + Size = br.ReadUInt32(); + byte[] buf = new byte[32]; + byte b; + int len = 0; + while ((b = br.ReadByte()) != 0) + { + buf[len++] = b; + } + Name = Encoding.UTF8.GetString(buf, 0, len); ; + int padding = -1 + ((len + 4) & ~3) - len; + br.BaseStream.Seek(padding, SeekOrigin.Current); + } + } + + sealed class ModuleReader : Module + { + private readonly Stream stream; + private readonly string location; + private Assembly assembly; + private readonly PEReader peFile = new PEReader(); + private readonly CliHeader cliHeader = new CliHeader(); + private string imageRuntimeVersion; + private int metadataStreamVersion; + private byte[] stringHeap; + private byte[] blobHeap; + private byte[] guidHeap; + private uint userStringHeapOffset; + private uint userStringHeapSize; + private byte[] lazyUserStringHeap; + private TypeDefImpl[] typeDefs; + private TypeDefImpl moduleType; + private Assembly[] assemblyRefs; + private Type[] typeRefs; + private Type[] typeSpecs; + private FieldInfo[] fields; + private MethodBase[] methods; + private MemberInfo[] memberRefs; + private Dictionary strings = new Dictionary(); + private Dictionary types = new Dictionary(); + private Dictionary forwardedTypes = new Dictionary(); + + private sealed class LazyForwardedType + { + private readonly int index; + private Type type; + + internal LazyForwardedType(int index) + { + this.index = index; + } + + internal Type GetType(ModuleReader module) + { + // guard against circular type forwarding + if (type == MarkerType.Pinned) + { + TypeName typeName = module.GetTypeName(module.ExportedType.records[index].TypeNamespace, module.ExportedType.records[index].TypeName); + return module.universe.GetMissingTypeOrThrow(module, module, null, typeName).SetCyclicTypeForwarder(); + } + else if (type == null) + { + type = MarkerType.Pinned; + type = module.ResolveExportedType(index); + } + return type; + } + } + + internal ModuleReader(AssemblyReader assembly, Universe universe, Stream stream, string location, bool mapped) + : base(universe) + { + this.stream = universe != null && universe.MetadataOnly ? null : stream; + this.location = location; + Read(stream, mapped); + if (universe != null && universe.WindowsRuntimeProjection && imageRuntimeVersion.StartsWith("WindowsRuntime ", StringComparison.Ordinal)) + { + WindowsRuntimeProjection.Patch(this, strings, ref imageRuntimeVersion, ref blobHeap); + } + if (assembly == null && AssemblyTable.records.Length != 0) + { + assembly = new AssemblyReader(location, this); + } + this.assembly = assembly; + } + + private void Read(Stream stream, bool mapped) + { + BinaryReader br = new BinaryReader(stream); + peFile.Read(br, mapped); + stream.Seek(peFile.RvaToFileOffset(peFile.GetComDescriptorVirtualAddress()), SeekOrigin.Begin); + cliHeader.Read(br); + stream.Seek(peFile.RvaToFileOffset(cliHeader.MetaData.VirtualAddress), SeekOrigin.Begin); + foreach (StreamHeader sh in ReadStreamHeaders(br, out imageRuntimeVersion)) + { + switch (sh.Name) + { + case "#Strings": + stringHeap = ReadHeap(stream, sh.Offset, sh.Size); + break; + case "#Blob": + blobHeap = ReadHeap(stream, sh.Offset, sh.Size); + break; + case "#US": + userStringHeapOffset = sh.Offset; + userStringHeapSize = sh.Size; + break; + case "#GUID": + guidHeap = ReadHeap(stream, sh.Offset, sh.Size); + break; + case "#~": + case "#-": + stream.Seek(peFile.RvaToFileOffset(cliHeader.MetaData.VirtualAddress + sh.Offset), SeekOrigin.Begin); + ReadTables(br); + break; + default: + // we ignore unknown streams, because the CLR does so too + // (and some obfuscators add bogus streams) + break; + } + } + } + + internal void SetAssembly(Assembly assembly) + { + this.assembly = assembly; + } + + private static StreamHeader[] ReadStreamHeaders(BinaryReader br, out string Version) + { + uint Signature = br.ReadUInt32(); + if (Signature != 0x424A5342) + { + throw new BadImageFormatException("Invalid metadata signature"); + } + /*ushort MajorVersion =*/ br.ReadUInt16(); + /*ushort MinorVersion =*/ br.ReadUInt16(); + /*uint Reserved =*/ br.ReadUInt32(); + uint Length = br.ReadUInt32(); + byte[] buf = br.ReadBytes((int)Length); + Version = Encoding.UTF8.GetString(buf).TrimEnd('\u0000'); + /*ushort Flags =*/ br.ReadUInt16(); + ushort Streams = br.ReadUInt16(); + StreamHeader[] streamHeaders = new StreamHeader[Streams]; + for (int i = 0; i < streamHeaders.Length; i++) + { + streamHeaders[i] = new StreamHeader(); + streamHeaders[i].Read(br); + } + return streamHeaders; + } + + private void ReadTables(BinaryReader br) + { + Table[] tables = GetTables(); + /*uint Reserved0 =*/ br.ReadUInt32(); + byte MajorVersion = br.ReadByte(); + byte MinorVersion = br.ReadByte(); + metadataStreamVersion = MajorVersion << 16 | MinorVersion; + byte HeapSizes = br.ReadByte(); + /*byte Reserved7 =*/ br.ReadByte(); + ulong Valid = br.ReadUInt64(); + ulong Sorted = br.ReadUInt64(); + for (int i = 0; i < 64; i++) + { + if ((Valid & (1UL << i)) != 0) + { + tables[i].Sorted = (Sorted & (1UL << i)) != 0; + tables[i].RowCount = br.ReadInt32(); + } + } + MetadataReader mr = new MetadataReader(this, br.BaseStream, HeapSizes); + for (int i = 0; i < 64; i++) + { + if ((Valid & (1UL << i)) != 0) + { + tables[i].Read(mr); + } + } + if (ParamPtr.RowCount != 0) + { + throw new NotImplementedException("ParamPtr table support has not yet been implemented."); + } + } + + private byte[] ReadHeap(Stream stream, uint offset, uint size) + { + byte[] buf = new byte[size]; + stream.Seek(peFile.RvaToFileOffset(cliHeader.MetaData.VirtualAddress + offset), SeekOrigin.Begin); + for (int pos = 0; pos < buf.Length; ) + { + int read = stream.Read(buf, pos, buf.Length - pos); + if (read == 0) + { + throw new BadImageFormatException(); + } + pos += read; + } + return buf; + } + + internal void SeekRVA(int rva) + { + GetStream().Seek(peFile.RvaToFileOffset((uint)rva), SeekOrigin.Begin); + } + + internal Stream GetStream() + { + if (stream == null) + { + throw new InvalidOperationException("Operation not available when UniverseOptions.MetadataOnly is enabled."); + } + return stream; + } + + internal override void GetTypesImpl(List list) + { + PopulateTypeDef(); + foreach (TypeDefImpl type in typeDefs) + { + if (type != moduleType) + { + list.Add(type); + } + } + } + + private void PopulateTypeDef() + { + if (typeDefs == null) + { + typeDefs = new TypeDefImpl[TypeDef.records.Length]; + for (int i = 0; i < typeDefs.Length; i++) + { + TypeDefImpl type = new TypeDefImpl(this, i); + typeDefs[i] = type; + if (type.IsModulePseudoType) + { + moduleType = type; + } + else if (!type.IsNestedByFlags) + { + types.Add(type.TypeName, type); + } + } + // add forwarded types to forwardedTypes dictionary (because Module.GetType(string) should return them) + for (int i = 0; i < ExportedType.records.Length; i++) + { + int implementation = ExportedType.records[i].Implementation; + if (implementation >> 24 == AssemblyRefTable.Index) + { + TypeName typeName = GetTypeName(ExportedType.records[i].TypeNamespace, ExportedType.records[i].TypeName); + forwardedTypes.Add(typeName, new LazyForwardedType(i)); + } + } + } + } + + internal override string GetString(int index) + { + if (index == 0) + { + return null; + } + string str; + if (!strings.TryGetValue(index, out str)) + { + int len = 0; + while (stringHeap[index + len] != 0) + { + len++; + } + str = Encoding.UTF8.GetString(stringHeap, index, len); + strings.Add(index, str); + } + return str; + } + + private static int ReadCompressedUInt(byte[] buffer, ref int offset) + { + byte b1 = buffer[offset++]; + if (b1 <= 0x7F) + { + return b1; + } + else if ((b1 & 0xC0) == 0x80) + { + byte b2 = buffer[offset++]; + return ((b1 & 0x3F) << 8) | b2; + } + else + { + byte b2 = buffer[offset++]; + byte b3 = buffer[offset++]; + byte b4 = buffer[offset++]; + return ((b1 & 0x3F) << 24) + (b2 << 16) + (b3 << 8) + b4; + } + } + + internal byte[] GetBlobCopy(int blobIndex) + { + int len = ReadCompressedUInt(blobHeap, ref blobIndex); + byte[] buf = new byte[len]; + Buffer.BlockCopy(blobHeap, blobIndex, buf, 0, len); + return buf; + } + + internal override ByteReader GetBlob(int blobIndex) + { + return ByteReader.FromBlob(blobHeap, blobIndex); + } + + public override string ResolveString(int metadataToken) + { + string str; + if (!strings.TryGetValue(metadataToken, out str)) + { + if ((metadataToken >> 24) != 0x70) + { + throw TokenOutOfRangeException(metadataToken); + } + if (lazyUserStringHeap == null) + { + lazyUserStringHeap = ReadHeap(GetStream(), userStringHeapOffset, userStringHeapSize); + } + int index = metadataToken & 0xFFFFFF; + int len = ReadCompressedUInt(lazyUserStringHeap, ref index) & ~1; + StringBuilder sb = new StringBuilder(len / 2); + for (int i = 0; i < len; i += 2) + { + char ch = (char)(lazyUserStringHeap[index + i] | lazyUserStringHeap[index + i + 1] << 8); + sb.Append(ch); + } + str = sb.ToString(); + strings.Add(metadataToken, str); + } + return str; + } + + internal override Type ResolveType(int metadataToken, IGenericContext context) + { + int index = (metadataToken & 0xFFFFFF) - 1; + if (index < 0) + { + throw TokenOutOfRangeException(metadataToken); + } + else if ((metadataToken >> 24) == TypeDefTable.Index && index < TypeDef.RowCount) + { + PopulateTypeDef(); + return typeDefs[index]; + } + else if ((metadataToken >> 24) == TypeRefTable.Index && index < TypeRef.RowCount) + { + if (typeRefs == null) + { + typeRefs = new Type[TypeRef.records.Length]; + } + if (typeRefs[index] == null) + { + int scope = TypeRef.records[index].ResolutionScope; + switch (scope >> 24) + { + case AssemblyRefTable.Index: + { + Assembly assembly = ResolveAssemblyRef((scope & 0xFFFFFF) - 1); + TypeName typeName = GetTypeName(TypeRef.records[index].TypeNamespace, TypeRef.records[index].TypeName); + typeRefs[index] = assembly.ResolveType(this, typeName); + break; + } + case TypeRefTable.Index: + { + Type outer = ResolveType(scope, null); + TypeName typeName = GetTypeName(TypeRef.records[index].TypeNamespace, TypeRef.records[index].TypeName); + typeRefs[index] = outer.ResolveNestedType(this, typeName); + break; + } + case ModuleTable.Index: + case ModuleRefTable.Index: + { + Module module; + if (scope >> 24 == ModuleTable.Index) + { + if (scope == 0 || scope == 1) + { + module = this; + } + else + { + throw new NotImplementedException("self reference scope?"); + } + } + else + { + module = ResolveModuleRef(ModuleRef.records[(scope & 0xFFFFFF) - 1]); + } + TypeName typeName = GetTypeName(TypeRef.records[index].TypeNamespace, TypeRef.records[index].TypeName); + typeRefs[index] = module.FindType(typeName) ?? module.universe.GetMissingTypeOrThrow(this, module, null, typeName); + break; + } + default: + throw new NotImplementedException("ResolutionScope = " + scope.ToString("X")); + } + } + return typeRefs[index]; + } + else if ((metadataToken >> 24) == TypeSpecTable.Index && index < TypeSpec.RowCount) + { + if (typeSpecs == null) + { + typeSpecs = new Type[TypeSpec.records.Length]; + } + Type type = typeSpecs[index]; + if (type == null) + { + TrackingGenericContext tc = context == null ? null : new TrackingGenericContext(context); + type = Signature.ReadTypeSpec(this, ByteReader.FromBlob(blobHeap, TypeSpec.records[index]), tc); + if (tc == null || !tc.IsUsed) + { + typeSpecs[index] = type; + } + } + return type; + } + else + { + throw TokenOutOfRangeException(metadataToken); + } + } + + private Module ResolveModuleRef(int moduleNameIndex) + { + string moduleName = GetString(moduleNameIndex); + Module module = assembly.GetModule(moduleName); + if (module == null) + { + throw new FileNotFoundException(moduleName); + } + return module; + } + + private sealed class TrackingGenericContext : IGenericContext + { + private readonly IGenericContext context; + private bool used; + + internal TrackingGenericContext(IGenericContext context) + { + this.context = context; + } + + internal bool IsUsed + { + get { return used; } + } + + public Type GetGenericTypeArgument(int index) + { + used = true; + return context.GetGenericTypeArgument(index); + } + + public Type GetGenericMethodArgument(int index) + { + used = true; + return context.GetGenericMethodArgument(index); + } + } + + private TypeName GetTypeName(int typeNamespace, int typeName) + { + return new TypeName(GetString(typeNamespace), GetString(typeName)); + } + + internal Assembly ResolveAssemblyRef(int index) + { + if (assemblyRefs == null) + { + assemblyRefs = new Assembly[AssemblyRef.RowCount]; + } + if (assemblyRefs[index] == null) + { + assemblyRefs[index] = ResolveAssemblyRefImpl(ref AssemblyRef.records[index]); + } + return assemblyRefs[index]; + } + + private Assembly ResolveAssemblyRefImpl(ref AssemblyRefTable.Record rec) + { + const int PublicKey = 0x0001; + string name = AssemblyName.GetFullName( + GetString(rec.Name), + rec.MajorVersion, + rec.MinorVersion, + rec.BuildNumber, + rec.RevisionNumber, + rec.Culture == 0 ? "neutral" : GetString(rec.Culture), + rec.PublicKeyOrToken == 0 ? Empty.Array : (rec.Flags & PublicKey) == 0 ? GetBlobCopy(rec.PublicKeyOrToken) : AssemblyName.ComputePublicKeyToken(GetBlobCopy(rec.PublicKeyOrToken)), + rec.Flags); + return universe.Load(name, this, true); + } + + public override Guid ModuleVersionId + { + get + { + byte[] buf = new byte[16]; + Buffer.BlockCopy(guidHeap, 16 * (ModuleTable.records[0].Mvid - 1), buf, 0, 16); + return new Guid(buf); + } + } + + public override string FullyQualifiedName + { + get { return location ?? ""; } + } + + public override string Name + { + get { return location == null ? "" : System.IO.Path.GetFileName(location); } + } + + public override Assembly Assembly + { + get { return assembly; } + } + + internal override Type FindType(TypeName typeName) + { + PopulateTypeDef(); + Type type; + if (!types.TryGetValue(typeName, out type)) + { + LazyForwardedType fw; + if (forwardedTypes.TryGetValue(typeName, out fw)) + { + return fw.GetType(this); + } + } + return type; + } + + internal override Type FindTypeIgnoreCase(TypeName lowerCaseName) + { + PopulateTypeDef(); + foreach (Type type in types.Values) + { + if (type.TypeName.ToLowerInvariant() == lowerCaseName) + { + return type; + } + } + foreach (TypeName name in forwardedTypes.Keys) + { + if (name.ToLowerInvariant() == lowerCaseName) + { + return forwardedTypes[name].GetType(this); + } + } + return null; + } + + private Exception TokenOutOfRangeException(int metadataToken) + { + return new ArgumentOutOfRangeException("metadataToken", String.Format("Token 0x{0:x8} is not valid in the scope of module {1}.", metadataToken, this.Name)); + } + + public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) + { + switch (metadataToken >> 24) + { + case FieldTable.Index: + return ResolveField(metadataToken, genericTypeArguments, genericMethodArguments); + case MemberRefTable.Index: + int index = (metadataToken & 0xFFFFFF) - 1; + if (index < 0 || index >= MemberRef.RowCount) + { + goto default; + } + return GetMemberRef(index, genericTypeArguments, genericMethodArguments); + case MethodDefTable.Index: + case MethodSpecTable.Index: + return ResolveMethod(metadataToken, genericTypeArguments, genericMethodArguments); + case TypeRefTable.Index: + case TypeDefTable.Index: + case TypeSpecTable.Index: + return ResolveType(metadataToken, genericTypeArguments, genericMethodArguments); + default: + throw TokenOutOfRangeException(metadataToken); + } + } + + internal FieldInfo GetFieldAt(TypeDefImpl owner, int index) + { + if (fields == null) + { + fields = new FieldInfo[Field.records.Length]; + } + if (fields[index] == null) + { + fields[index] = new FieldDefImpl(this, owner ?? FindFieldOwner(index), index); + } + return fields[index]; + } + + public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) + { + int index = (metadataToken & 0xFFFFFF) - 1; + if (index < 0) + { + throw TokenOutOfRangeException(metadataToken); + } + else if ((metadataToken >> 24) == FieldTable.Index && index < Field.RowCount) + { + return GetFieldAt(null, index); + } + else if ((metadataToken >> 24) == MemberRefTable.Index && index < MemberRef.RowCount) + { + FieldInfo field = GetMemberRef(index, genericTypeArguments, genericMethodArguments) as FieldInfo; + if (field != null) + { + return field; + } + throw new ArgumentException(String.Format("Token 0x{0:x8} is not a valid FieldInfo token in the scope of module {1}.", metadataToken, this.Name), "metadataToken"); + } + else + { + throw TokenOutOfRangeException(metadataToken); + } + } + + private TypeDefImpl FindFieldOwner(int fieldIndex) + { + // TODO use binary search? + for (int i = 0; i < TypeDef.records.Length; i++) + { + int field = TypeDef.records[i].FieldList - 1; + int end = TypeDef.records.Length > i + 1 ? TypeDef.records[i + 1].FieldList - 1 : Field.records.Length; + if (field <= fieldIndex && fieldIndex < end) + { + PopulateTypeDef(); + return typeDefs[i]; + } + } + throw new InvalidOperationException(); + } + + internal MethodBase GetMethodAt(TypeDefImpl owner, int index) + { + if (methods == null) + { + methods = new MethodBase[MethodDef.records.Length]; + } + if (methods[index] == null) + { + MethodDefImpl method = new MethodDefImpl(this, owner ?? FindMethodOwner(index), index); + methods[index] = method.IsConstructor ? new ConstructorInfoImpl(method) : (MethodBase)method; + } + return methods[index]; + } + + public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) + { + int index = (metadataToken & 0xFFFFFF) - 1; + if (index < 0) + { + throw TokenOutOfRangeException(metadataToken); + } + else if ((metadataToken >> 24) == MethodDefTable.Index && index < MethodDef.RowCount) + { + return GetMethodAt(null, index); + } + else if ((metadataToken >> 24) == MemberRefTable.Index && index < MemberRef.RowCount) + { + MethodBase method = GetMemberRef(index, genericTypeArguments, genericMethodArguments) as MethodBase; + if (method != null) + { + return method; + } + throw new ArgumentException(String.Format("Token 0x{0:x8} is not a valid MethodBase token in the scope of module {1}.", metadataToken, this.Name), "metadataToken"); + } + else if ((metadataToken >> 24) == MethodSpecTable.Index && index < MethodSpec.RowCount) + { + MethodInfo method = (MethodInfo)ResolveMethod(MethodSpec.records[index].Method, genericTypeArguments, genericMethodArguments); + ByteReader instantiation = ByteReader.FromBlob(blobHeap, MethodSpec.records[index].Instantiation); + return method.MakeGenericMethod(Signature.ReadMethodSpec(this, instantiation, new GenericContext(genericTypeArguments, genericMethodArguments))); + } + else + { + throw TokenOutOfRangeException(metadataToken); + } + } + + public override Type[] __ResolveOptionalParameterTypes(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments, out CustomModifiers[] customModifiers) + { + int index = (metadataToken & 0xFFFFFF) - 1; + if (index < 0) + { + throw TokenOutOfRangeException(metadataToken); + } + else if ((metadataToken >> 24) == MemberRefTable.Index && index < MemberRef.RowCount) + { + int sig = MemberRef.records[index].Signature; + return Signature.ReadOptionalParameterTypes(this, GetBlob(sig), new GenericContext(genericTypeArguments, genericMethodArguments), out customModifiers); + } + else if ((metadataToken >> 24) == MethodDefTable.Index && index < MethodDef.RowCount) + { + // for convenience, we support passing a MethodDef token as well, because in some places + // it makes sense to have a vararg method that is referred to by its methoddef (e.g. ldftn). + // Note that MethodSpec doesn't make sense, because generic methods cannot be vararg. + customModifiers = Empty.Array; + return Type.EmptyTypes; + } + else + { + throw TokenOutOfRangeException(metadataToken); + } + } + + public override CustomModifiers __ResolveTypeSpecCustomModifiers(int typeSpecToken, Type[] genericTypeArguments, Type[] genericMethodArguments) + { + int index = (typeSpecToken & 0xFFFFFF) - 1; + if (typeSpecToken >> 24 != TypeSpecTable.Index || index < 0 || index >= TypeSpec.RowCount) + { + throw TokenOutOfRangeException(typeSpecToken); + } + return CustomModifiers.Read(this, ByteReader.FromBlob(blobHeap, TypeSpec.records[index]), new GenericContext(genericTypeArguments, genericMethodArguments)); + } + + public override string ScopeName + { + get { return GetString(ModuleTable.records[0].Name); } + } + + private TypeDefImpl FindMethodOwner(int methodIndex) + { + // TODO use binary search? + for (int i = 0; i < TypeDef.records.Length; i++) + { + int method = TypeDef.records[i].MethodList - 1; + int end = TypeDef.records.Length > i + 1 ? TypeDef.records[i + 1].MethodList - 1 : MethodDef.records.Length; + if (method <= methodIndex && methodIndex < end) + { + PopulateTypeDef(); + return typeDefs[i]; + } + } + throw new InvalidOperationException(); + } + + private MemberInfo GetMemberRef(int index, Type[] genericTypeArguments, Type[] genericMethodArguments) + { + if (memberRefs == null) + { + memberRefs = new MemberInfo[MemberRef.records.Length]; + } + if (memberRefs[index] == null) + { + int owner = MemberRef.records[index].Class; + int sig = MemberRef.records[index].Signature; + string name = GetString(MemberRef.records[index].Name); + switch (owner >> 24) + { + case MethodDefTable.Index: + return GetMethodAt(null, (owner & 0xFFFFFF) - 1); + case ModuleRefTable.Index: + memberRefs[index] = ResolveTypeMemberRef(ResolveModuleType(owner), name, ByteReader.FromBlob(blobHeap, sig)); + break; + case TypeDefTable.Index: + case TypeRefTable.Index: + memberRefs[index] = ResolveTypeMemberRef(ResolveType(owner), name, ByteReader.FromBlob(blobHeap, sig)); + break; + case TypeSpecTable.Index: + { + Type type = ResolveType(owner, genericTypeArguments, genericMethodArguments); + if (type.IsArray) + { + MethodSignature methodSig = MethodSignature.ReadSig(this, ByteReader.FromBlob(blobHeap, sig), new GenericContext(genericTypeArguments, genericMethodArguments)); + return type.FindMethod(name, methodSig) + ?? universe.GetMissingMethodOrThrow(this, type, name, methodSig); + } + else if (type.IsConstructedGenericType) + { + MemberInfo member = ResolveTypeMemberRef(type.GetGenericTypeDefinition(), name, ByteReader.FromBlob(blobHeap, sig)); + MethodBase mb = member as MethodBase; + if (mb != null) + { + member = mb.BindTypeParameters(type); + } + FieldInfo fi = member as FieldInfo; + if (fi != null) + { + member = fi.BindTypeParameters(type); + } + return member; + } + else + { + return ResolveTypeMemberRef(type, name, ByteReader.FromBlob(blobHeap, sig)); + } + } + default: + throw new BadImageFormatException(); + } + } + return memberRefs[index]; + } + + private Type ResolveModuleType(int token) + { + int index = (token & 0xFFFFFF) - 1; + string name = GetString(ModuleRef.records[index]); + Module module = assembly.GetModule(name); + if (module == null || module.IsResource()) + { + throw new BadImageFormatException(); + } + return module.GetModuleType(); + } + + private MemberInfo ResolveTypeMemberRef(Type type, string name, ByteReader sig) + { + if (sig.PeekByte() == Signature.FIELD) + { + Type org = type; + FieldSignature fieldSig = FieldSignature.ReadSig(this, sig, type); + FieldInfo field = type.FindField(name, fieldSig); + if (field == null && universe.MissingMemberResolution) + { + return universe.GetMissingFieldOrThrow(this, type, name, fieldSig); + } + while (field == null && (type = type.BaseType) != null) + { + field = type.FindField(name, fieldSig); + } + if (field != null) + { + return field; + } +#if CORECLR + throw new MissingFieldException(org.ToString() + "." + name); +#else + throw new MissingFieldException(org.ToString(), name); +#endif + } + else + { + Type org = type; + MethodSignature methodSig = MethodSignature.ReadSig(this, sig, type); + MethodBase method = type.FindMethod(name, methodSig); + if (method == null && universe.MissingMemberResolution) + { + return universe.GetMissingMethodOrThrow(this, type, name, methodSig); + } + while (method == null && (type = type.BaseType) != null) + { + method = type.FindMethod(name, methodSig); + } + if (method != null) + { + return method; + } +#if CORECLR + throw new MissingMethodException(org.ToString() + "." + name); +#else + throw new MissingMethodException(org.ToString(), name); +#endif + } + } + + internal ByteReader GetStandAloneSig(int index) + { + return ByteReader.FromBlob(blobHeap, StandAloneSig.records[index]); + } + + public override byte[] ResolveSignature(int metadataToken) + { + int index = (metadataToken & 0xFFFFFF) - 1; + if ((metadataToken >> 24) == StandAloneSigTable.Index && index >= 0 && index < StandAloneSig.RowCount) + { + ByteReader br = GetStandAloneSig(index); + return br.ReadBytes(br.Length); + } + else + { + throw TokenOutOfRangeException(metadataToken); + } + } + + public override __StandAloneMethodSig __ResolveStandAloneMethodSig(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) + { + int index = (metadataToken & 0xFFFFFF) - 1; + if ((metadataToken >> 24) == StandAloneSigTable.Index && index >= 0 && index < StandAloneSig.RowCount) + { + return MethodSignature.ReadStandAloneMethodSig(this, GetStandAloneSig(index), new GenericContext(genericTypeArguments, genericMethodArguments)); + } + else + { + throw TokenOutOfRangeException(metadataToken); + } + } + + internal MethodInfo GetEntryPoint() + { + if (cliHeader.EntryPointToken != 0 && (cliHeader.Flags & CliHeader.COMIMAGE_FLAGS_NATIVE_ENTRYPOINT) == 0) + { + return (MethodInfo)ResolveMethod((int)cliHeader.EntryPointToken); + } + return null; + } + + internal string[] GetManifestResourceNames() + { + string[] names = new string[ManifestResource.records.Length]; + for (int i = 0; i < ManifestResource.records.Length; i++) + { + names[i] = GetString(ManifestResource.records[i].Name); + } + return names; + } + + internal ManifestResourceInfo GetManifestResourceInfo(string resourceName) + { + for (int i = 0; i < ManifestResource.records.Length; i++) + { + if (resourceName == GetString(ManifestResource.records[i].Name)) + { + ManifestResourceInfo info = new ManifestResourceInfo(this, i); + Assembly asm = info.ReferencedAssembly; + if (asm != null && !asm.__IsMissing && asm.GetManifestResourceInfo(resourceName) == null) + { + return null; + } + return info; + } + } + return null; + } + + internal Stream GetManifestResourceStream(string resourceName) + { + for (int i = 0; i < ManifestResource.records.Length; i++) + { + if (resourceName == GetString(ManifestResource.records[i].Name)) + { + if (ManifestResource.records[i].Implementation != 0x26000000) + { + ManifestResourceInfo info = new ManifestResourceInfo(this, i); + switch (ManifestResource.records[i].Implementation >> 24) + { + case FileTable.Index: + string fileName = Path.Combine(Path.GetDirectoryName(location), info.FileName); + if (System.IO.File.Exists(fileName)) + { + // note that, like System.Reflection, we return null for zero length files and + // ManifestResource.Offset is ignored + FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete); + if (fs.Length == 0) + { + fs.Close(); + return null; + } + return fs; + } + return null; + case AssemblyRefTable.Index: + Assembly asm = info.ReferencedAssembly; + if (asm.__IsMissing) + { + return null; + } + return asm.GetManifestResourceStream(resourceName); + default: + throw new BadImageFormatException(); + } + } + SeekRVA((int)cliHeader.Resources.VirtualAddress + ManifestResource.records[i].Offset); + BinaryReader br = new BinaryReader(stream); + int length = br.ReadInt32(); + return new MemoryStream(br.ReadBytes(length)); + } + } + return null; + } + + public override AssemblyName[] __GetReferencedAssemblies() + { + List list = new List(); + for (int i = 0; i < AssemblyRef.records.Length; i++) + { + AssemblyName name = new AssemblyName(); + name.Name = GetString(AssemblyRef.records[i].Name); + name.Version = new Version( + AssemblyRef.records[i].MajorVersion, + AssemblyRef.records[i].MinorVersion, + AssemblyRef.records[i].BuildNumber, + AssemblyRef.records[i].RevisionNumber); + if (AssemblyRef.records[i].PublicKeyOrToken != 0) + { + byte[] keyOrToken = GetBlobCopy(AssemblyRef.records[i].PublicKeyOrToken); + const int PublicKey = 0x0001; + if ((AssemblyRef.records[i].Flags & PublicKey) != 0) + { + name.SetPublicKey(keyOrToken); + } + else + { + name.SetPublicKeyToken(keyOrToken); + } + } + else + { + name.SetPublicKeyToken(Empty.Array); + } + if (AssemblyRef.records[i].Culture != 0) + { + name.Culture = GetString(AssemblyRef.records[i].Culture); + } + else + { + name.Culture = ""; + } + if (AssemblyRef.records[i].HashValue != 0) + { + name.hash = GetBlobCopy(AssemblyRef.records[i].HashValue); + } + name.RawFlags = (AssemblyNameFlags)AssemblyRef.records[i].Flags; + list.Add(name); + } + return list.ToArray(); + } + + public override void __ResolveReferencedAssemblies(Assembly[] assemblies) + { + if (assemblyRefs == null) + { + assemblyRefs = new Assembly[AssemblyRef.RowCount]; + } + for (int i = 0; i < assemblies.Length; i++) + { + if (assemblyRefs[i] == null) + { + assemblyRefs[i] = assemblies[i]; + } + } + } + + public override string[] __GetReferencedModules() + { + string[] arr = new string[this.ModuleRef.RowCount]; + for (int i = 0; i < arr.Length; i++) + { + arr[i] = GetString(this.ModuleRef.records[i]); + } + return arr; + } + + public override Type[] __GetReferencedTypes() + { + Type[] arr = new Type[this.TypeRef.RowCount]; + for (int i = 0; i < arr.Length; i++) + { + arr[i] = ResolveType((TypeRefTable.Index << 24) + i + 1); + } + return arr; + } + + public override Type[] __GetExportedTypes() + { + Type[] arr = new Type[this.ExportedType.RowCount]; + for (int i = 0; i < arr.Length; i++) + { + arr[i] = ResolveExportedType(i); + } + return arr; + } + + private Type ResolveExportedType(int index) + { + TypeName typeName = GetTypeName(ExportedType.records[index].TypeNamespace, ExportedType.records[index].TypeName); + int implementation = ExportedType.records[index].Implementation; + int token = ExportedType.records[index].TypeDefId; + int flags = ExportedType.records[index].Flags; + switch (implementation >> 24) + { + case AssemblyRefTable.Index: + return ResolveAssemblyRef((implementation & 0xFFFFFF) - 1).ResolveType(this, typeName).SetMetadataTokenForMissing(token, flags); + case ExportedTypeTable.Index: + return ResolveExportedType((implementation & 0xFFFFFF) - 1).ResolveNestedType(this, typeName).SetMetadataTokenForMissing(token, flags); + case FileTable.Index: + Module module = assembly.GetModule(GetString(File.records[(implementation & 0xFFFFFF) - 1].Name)); + return module.FindType(typeName) ?? module.universe.GetMissingTypeOrThrow(this, module, null, typeName).SetMetadataTokenForMissing(token, flags); + default: + throw new BadImageFormatException(); + } + } + + internal override Type GetModuleType() + { + PopulateTypeDef(); + return moduleType; + } + + public override string __ImageRuntimeVersion + { + get { return imageRuntimeVersion; } + } + + public override int MDStreamVersion + { + get { return metadataStreamVersion; } + } + + public override void __GetDataDirectoryEntry(int index, out int rva, out int length) + { + peFile.GetDataDirectoryEntry(index, out rva, out length); + } + + public override long __RelativeVirtualAddressToFileOffset(int rva) + { + return peFile.RvaToFileOffset((uint)rva); + } + + public override bool __GetSectionInfo(int rva, out string name, out int characteristics, out int virtualAddress, out int virtualSize, out int pointerToRawData, out int sizeOfRawData) + { + return peFile.GetSectionInfo(rva, out name, out characteristics, out virtualAddress, out virtualSize, out pointerToRawData, out sizeOfRawData); + } + + public override int __ReadDataFromRVA(int rva, byte[] data, int offset, int length) + { + SeekRVA(rva); + int totalBytesRead = 0; + while (length > 0) + { + int read = stream.Read(data, offset, length); + if (read == 0) + { + // C++ assemblies can have fields that have an RVA that lies outside of the file + break; + } + offset += read; + length -= read; + totalBytesRead += read; + } + return totalBytesRead; + } + + public override void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine) + { + peKind = 0; + if ((cliHeader.Flags & CliHeader.COMIMAGE_FLAGS_ILONLY) != 0) + { + peKind |= PortableExecutableKinds.ILOnly; + } + switch (cliHeader.Flags & (CliHeader.COMIMAGE_FLAGS_32BITREQUIRED | CliHeader.COMIMAGE_FLAGS_32BITPREFERRED)) + { + case CliHeader.COMIMAGE_FLAGS_32BITREQUIRED: + peKind |= PortableExecutableKinds.Required32Bit; + break; + case CliHeader.COMIMAGE_FLAGS_32BITREQUIRED | CliHeader.COMIMAGE_FLAGS_32BITPREFERRED: + peKind |= PortableExecutableKinds.Preferred32Bit; + break; + default: + // COMIMAGE_FLAGS_32BITPREFERRED by itself is illegal, so we ignore it + // (not setting any flag is ok) + break; + } + if (peFile.OptionalHeader.Magic == IMAGE_OPTIONAL_HEADER.IMAGE_NT_OPTIONAL_HDR64_MAGIC) + { + peKind |= PortableExecutableKinds.PE32Plus; + } + + machine = (ImageFileMachine)peFile.FileHeader.Machine; + } + + public override int __Subsystem + { + get { return peFile.OptionalHeader.Subsystem; } + } + + public override IList __GetPlaceholderAssemblyCustomAttributes(bool multiple, bool security) + { + TypeName typeName; + switch ((multiple ? 1 : 0) + (security ? 2 : 0)) + { + case 0: + typeName = new TypeName("System.Runtime.CompilerServices", "AssemblyAttributesGoHere"); + break; + case 1: + typeName = new TypeName("System.Runtime.CompilerServices", "AssemblyAttributesGoHereM"); + break; + case 2: + typeName = new TypeName("System.Runtime.CompilerServices", "AssemblyAttributesGoHereS"); + break; + case 3: + default: + typeName = new TypeName("System.Runtime.CompilerServices", "AssemblyAttributesGoHereSM"); + break; + } + List list = new List(); + for (int i = 0; i < CustomAttribute.records.Length; i++) + { + if ((CustomAttribute.records[i].Parent >> 24) == TypeRefTable.Index) + { + int index = (CustomAttribute.records[i].Parent & 0xFFFFFF) - 1; + if (typeName == GetTypeName(TypeRef.records[index].TypeNamespace, TypeRef.records[index].TypeName)) + { + list.Add(new CustomAttributeData(this, i)); + } + } + } + return list; + } + + internal override void Dispose() + { + if (stream != null) + { + stream.Close(); + } + } + + internal override void ExportTypes(int fileToken, IKVM.Reflection.Emit.ModuleBuilder manifestModule) + { + PopulateTypeDef(); + manifestModule.ExportTypes(typeDefs, fileToken); + } + + protected override long GetImageBaseImpl() + { + return (long)peFile.OptionalHeader.ImageBase; + } + + protected override long GetStackReserveImpl() + { + return (long)peFile.OptionalHeader.SizeOfStackReserve; + } + + protected override int GetFileAlignmentImpl() + { + return (int)peFile.OptionalHeader.FileAlignment; + } + + protected override DllCharacteristics GetDllCharacteristicsImpl() + { + return (DllCharacteristics)peFile.OptionalHeader.DllCharacteristics; + } + + public override int __EntryPointRVA + { + get { return (cliHeader.Flags & CliHeader.COMIMAGE_FLAGS_NATIVE_ENTRYPOINT) != 0 ? (int)cliHeader.EntryPointToken : 0; } + } + + public override int __EntryPointToken + { + get { return (cliHeader.Flags & CliHeader.COMIMAGE_FLAGS_NATIVE_ENTRYPOINT) == 0 ? (int)cliHeader.EntryPointToken : 0; } + } + +#if !NO_AUTHENTICODE + public override System.Security.Cryptography.X509Certificates.X509Certificate GetSignerCertificate() + { + return Authenticode.GetSignerCertificate(GetStream()); + } +#endif // !NO_AUTHENTICODE + } +} diff --git a/reflect/Reader/PEReader.cs b/reflect/Reader/PEReader.cs new file mode 100644 index 0000000..7d2b4eb --- /dev/null +++ b/reflect/Reader/PEReader.cs @@ -0,0 +1,349 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using BYTE = System.Byte; +using WORD = System.UInt16; +using DWORD = System.UInt32; +using ULONGLONG = System.UInt64; +using System.IO; + +namespace IKVM.Reflection.Reader +{ + sealed class MSDOS_HEADER + { + internal const WORD MAGIC_MZ = 0x5A4D; + + internal WORD signature; // 'MZ' + // skip 58 bytes + internal DWORD peSignatureOffset; + } + + sealed class IMAGE_NT_HEADERS + { + public const DWORD MAGIC_SIGNATURE = 0x00004550; // "PE\0\0" + + public DWORD Signature; + public IMAGE_FILE_HEADER FileHeader = new IMAGE_FILE_HEADER(); + public IMAGE_OPTIONAL_HEADER OptionalHeader = new IMAGE_OPTIONAL_HEADER(); + + internal void Read(BinaryReader br) + { + Signature = br.ReadUInt32(); + if (Signature != IMAGE_NT_HEADERS.MAGIC_SIGNATURE) + { + throw new BadImageFormatException(); + } + FileHeader.Read(br); + long optionalHeaderPosition = br.BaseStream.Position; + OptionalHeader.Read(br); + if (br.BaseStream.Position > optionalHeaderPosition + FileHeader.SizeOfOptionalHeader) + { + throw new BadImageFormatException(); + } + br.BaseStream.Seek(optionalHeaderPosition + FileHeader.SizeOfOptionalHeader, SeekOrigin.Begin); + } + } + + sealed class IMAGE_FILE_HEADER + { + public const WORD IMAGE_FILE_MACHINE_I386 = 0x014c; + public const WORD IMAGE_FILE_MACHINE_IA64 = 0x0200; + public const WORD IMAGE_FILE_MACHINE_AMD64 = 0x8664; + + public const WORD IMAGE_FILE_32BIT_MACHINE = 0x0100; + public const WORD IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002; + public const WORD IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020; + public const WORD IMAGE_FILE_DLL = 0x2000; + + public WORD Machine; + public WORD NumberOfSections; + public DWORD TimeDateStamp; + public DWORD PointerToSymbolTable; + public DWORD NumberOfSymbols; + public WORD SizeOfOptionalHeader; + public WORD Characteristics; + + internal void Read(BinaryReader br) + { + Machine = br.ReadUInt16(); + NumberOfSections = br.ReadUInt16(); + TimeDateStamp = br.ReadUInt32(); + PointerToSymbolTable = br.ReadUInt32(); + NumberOfSymbols = br.ReadUInt32(); + SizeOfOptionalHeader = br.ReadUInt16(); + Characteristics = br.ReadUInt16(); + } + } + + sealed class IMAGE_OPTIONAL_HEADER + { + public const WORD IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b; + public const WORD IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b; + + public const WORD IMAGE_SUBSYSTEM_WINDOWS_GUI = 2; + public const WORD IMAGE_SUBSYSTEM_WINDOWS_CUI = 3; + + public WORD Magic; + public BYTE MajorLinkerVersion; + public BYTE MinorLinkerVersion; + public DWORD SizeOfCode; + public DWORD SizeOfInitializedData; + public DWORD SizeOfUninitializedData; + public DWORD AddressOfEntryPoint; + public DWORD BaseOfCode; + public DWORD BaseOfData; + public ULONGLONG ImageBase; + public DWORD SectionAlignment; + public DWORD FileAlignment; + public WORD MajorOperatingSystemVersion; + public WORD MinorOperatingSystemVersion; + public WORD MajorImageVersion; + public WORD MinorImageVersion; + public WORD MajorSubsystemVersion; + public WORD MinorSubsystemVersion; + public DWORD Win32VersionValue; + public DWORD SizeOfImage; + public DWORD SizeOfHeaders; + public DWORD CheckSum; + public WORD Subsystem; + public WORD DllCharacteristics; + public ULONGLONG SizeOfStackReserve; + public ULONGLONG SizeOfStackCommit; + public ULONGLONG SizeOfHeapReserve; + public ULONGLONG SizeOfHeapCommit; + public DWORD LoaderFlags; + public DWORD NumberOfRvaAndSizes; + public IMAGE_DATA_DIRECTORY[] DataDirectory; + + internal void Read(BinaryReader br) + { + Magic = br.ReadUInt16(); + if (Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC && Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) + { + throw new BadImageFormatException(); + } + MajorLinkerVersion = br.ReadByte(); + MinorLinkerVersion = br.ReadByte(); + SizeOfCode = br.ReadUInt32(); + SizeOfInitializedData = br.ReadUInt32(); + SizeOfUninitializedData = br.ReadUInt32(); + AddressOfEntryPoint = br.ReadUInt32(); + BaseOfCode = br.ReadUInt32(); + if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) + { + BaseOfData = br.ReadUInt32(); + ImageBase = br.ReadUInt32(); + } + else + { + ImageBase = br.ReadUInt64(); + } + SectionAlignment = br.ReadUInt32(); + FileAlignment = br.ReadUInt32(); + MajorOperatingSystemVersion = br.ReadUInt16(); + MinorOperatingSystemVersion = br.ReadUInt16(); + MajorImageVersion = br.ReadUInt16(); + MinorImageVersion = br.ReadUInt16(); + MajorSubsystemVersion = br.ReadUInt16(); + MinorSubsystemVersion = br.ReadUInt16(); + Win32VersionValue = br.ReadUInt32(); + SizeOfImage = br.ReadUInt32(); + SizeOfHeaders = br.ReadUInt32(); + CheckSum = br.ReadUInt32(); + Subsystem = br.ReadUInt16(); + DllCharacteristics = br.ReadUInt16(); + if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) + { + SizeOfStackReserve = br.ReadUInt32(); + SizeOfStackCommit = br.ReadUInt32(); + SizeOfHeapReserve = br.ReadUInt32(); + SizeOfHeapCommit = br.ReadUInt32(); + } + else + { + SizeOfStackReserve = br.ReadUInt64(); + SizeOfStackCommit = br.ReadUInt64(); + SizeOfHeapReserve = br.ReadUInt64(); + SizeOfHeapCommit = br.ReadUInt64(); + } + LoaderFlags = br.ReadUInt32(); + NumberOfRvaAndSizes = br.ReadUInt32(); + DataDirectory = new IMAGE_DATA_DIRECTORY[NumberOfRvaAndSizes]; + for (uint i = 0; i < NumberOfRvaAndSizes; i++) + { + DataDirectory[i] = new IMAGE_DATA_DIRECTORY(); + DataDirectory[i].Read(br); + } + } + } + + struct IMAGE_DATA_DIRECTORY + { + public DWORD VirtualAddress; + public DWORD Size; + + internal void Read(BinaryReader br) + { + VirtualAddress = br.ReadUInt32(); + Size = br.ReadUInt32(); + } + } + + class SectionHeader + { + public const DWORD IMAGE_SCN_CNT_CODE = 0x00000020; + public const DWORD IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040; + public const DWORD IMAGE_SCN_MEM_DISCARDABLE = 0x02000000; + public const DWORD IMAGE_SCN_MEM_EXECUTE = 0x20000000; + public const DWORD IMAGE_SCN_MEM_READ = 0x40000000; + public const DWORD IMAGE_SCN_MEM_WRITE = 0x80000000; + + public string Name; // 8 byte UTF8 encoded 0-padded + public DWORD VirtualSize; + public DWORD VirtualAddress; + public DWORD SizeOfRawData; + public DWORD PointerToRawData; + public DWORD PointerToRelocations; + public DWORD PointerToLinenumbers; + public WORD NumberOfRelocations; + public WORD NumberOfLinenumbers; + public DWORD Characteristics; + + internal void Read(BinaryReader br) + { + char[] name = new char[8]; + int len = 8; + for (int i = 0; i < 8; i++) + { + byte b = br.ReadByte(); + name[i] = (char)b; + if (b == 0 && len == 8) + { + len = i; + } + } + Name = new String(name, 0, len); + VirtualSize = br.ReadUInt32(); + VirtualAddress = br.ReadUInt32(); + SizeOfRawData = br.ReadUInt32(); + PointerToRawData = br.ReadUInt32(); + PointerToRelocations = br.ReadUInt32(); + PointerToLinenumbers = br.ReadUInt32(); + NumberOfRelocations = br.ReadUInt16(); + NumberOfLinenumbers = br.ReadUInt16(); + Characteristics = br.ReadUInt32(); + } + } + + sealed class PEReader + { + private MSDOS_HEADER msdos = new MSDOS_HEADER(); + private IMAGE_NT_HEADERS headers = new IMAGE_NT_HEADERS(); + private SectionHeader[] sections; + private bool mapped; + + internal void Read(BinaryReader br, bool mapped) + { + this.mapped = mapped; + msdos.signature = br.ReadUInt16(); + br.BaseStream.Seek(58, SeekOrigin.Current); + msdos.peSignatureOffset = br.ReadUInt32(); + + if (msdos.signature != MSDOS_HEADER.MAGIC_MZ) + { + throw new BadImageFormatException(); + } + + br.BaseStream.Seek(msdos.peSignatureOffset, SeekOrigin.Begin); + headers.Read(br); + sections = new SectionHeader[headers.FileHeader.NumberOfSections]; + for (int i = 0; i < sections.Length; i++) + { + sections[i] = new SectionHeader(); + sections[i].Read(br); + } + } + + internal IMAGE_FILE_HEADER FileHeader + { + get { return headers.FileHeader; } + } + + internal IMAGE_OPTIONAL_HEADER OptionalHeader + { + get { return headers.OptionalHeader; } + } + + internal DWORD GetComDescriptorVirtualAddress() + { + return headers.OptionalHeader.DataDirectory[14].VirtualAddress; + } + + internal void GetDataDirectoryEntry(int index, out int rva, out int length) + { + rva = (int)headers.OptionalHeader.DataDirectory[index].VirtualAddress; + length = (int)headers.OptionalHeader.DataDirectory[index].Size; + } + + internal long RvaToFileOffset(DWORD rva) + { + if (mapped) + { + return rva; + } + for (int i = 0; i < sections.Length; i++) + { + if (rva >= sections[i].VirtualAddress && rva < sections[i].VirtualAddress + sections[i].VirtualSize) + { + return sections[i].PointerToRawData + rva - sections[i].VirtualAddress; + } + } + throw new BadImageFormatException(); + } + + internal bool GetSectionInfo(int rva, out string name, out int characteristics, out int virtualAddress, out int virtualSize, out int pointerToRawData, out int sizeOfRawData) + { + for (int i = 0; i < sections.Length; i++) + { + if (rva >= sections[i].VirtualAddress && rva < sections[i].VirtualAddress + sections[i].VirtualSize) + { + name = sections[i].Name; + characteristics = (int)sections[i].Characteristics; + virtualAddress = (int)sections[i].VirtualAddress; + virtualSize = (int)sections[i].VirtualSize; + pointerToRawData = (int)sections[i].PointerToRawData; + sizeOfRawData = (int)sections[i].SizeOfRawData; + return true; + } + } + name = null; + characteristics = 0; + virtualAddress = 0; + virtualSize = 0; + pointerToRawData = 0; + sizeOfRawData = 0; + return false; + } + } +} diff --git a/reflect/Reader/PropertyInfoImpl.cs b/reflect/Reader/PropertyInfoImpl.cs new file mode 100644 index 0000000..120b839 --- /dev/null +++ b/reflect/Reader/PropertyInfoImpl.cs @@ -0,0 +1,179 @@ +/* + Copyright (C) 2009-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; +using IKVM.Reflection.Metadata; + +namespace IKVM.Reflection.Reader +{ + sealed class PropertyInfoImpl : PropertyInfo + { + private readonly ModuleReader module; + private readonly Type declaringType; + private readonly int index; + private PropertySignature sig; + private bool isPublic; + private bool isNonPrivate; + private bool isStatic; + private bool flagsCached; + + internal PropertyInfoImpl(ModuleReader module, Type declaringType, int index) + { + this.module = module; + this.declaringType = declaringType; + this.index = index; + } + + public override bool Equals(object obj) + { + PropertyInfoImpl other = obj as PropertyInfoImpl; + return other != null && other.DeclaringType == declaringType && other.index == index; + } + + public override int GetHashCode() + { + return declaringType.GetHashCode() * 77 + index; + } + + internal override PropertySignature PropertySignature + { + get + { + if (sig == null) + { + sig = PropertySignature.ReadSig(module, module.GetBlob(module.Property.records[index].Type), declaringType); + } + return sig; + } + } + + public override PropertyAttributes Attributes + { + get { return (PropertyAttributes)module.Property.records[index].Flags; } + } + + public override object GetRawConstantValue() + { + return module.Constant.GetRawConstantValue(module, this.MetadataToken); + } + + public override bool CanRead + { + get { return GetGetMethod(true) != null; } + } + + public override bool CanWrite + { + get { return GetSetMethod(true) != null; } + } + + public override MethodInfo GetGetMethod(bool nonPublic) + { + return module.MethodSemantics.GetMethod(module, this.MetadataToken, nonPublic, MethodSemanticsTable.Getter); + } + + public override MethodInfo GetSetMethod(bool nonPublic) + { + return module.MethodSemantics.GetMethod(module, this.MetadataToken, nonPublic, MethodSemanticsTable.Setter); + } + + public override MethodInfo[] GetAccessors(bool nonPublic) + { + return module.MethodSemantics.GetMethods(module, this.MetadataToken, nonPublic, MethodSemanticsTable.Getter | MethodSemanticsTable.Setter | MethodSemanticsTable.Other); + } + + public override Type DeclaringType + { + get { return declaringType; } + } + + public override Module Module + { + get { return module; } + } + + public override int MetadataToken + { + get { return (PropertyTable.Index << 24) + index + 1; } + } + + public override string Name + { + get { return module.GetString(module.Property.records[index].Name); } + } + + internal override bool IsPublic + { + get + { + if (!flagsCached) + { + ComputeFlags(); + } + return isPublic; + } + } + + internal override bool IsNonPrivate + { + get + { + if (!flagsCached) + { + ComputeFlags(); + } + return isNonPrivate; + } + } + + internal override bool IsStatic + { + get + { + if (!flagsCached) + { + ComputeFlags(); + } + return isStatic; + } + } + + private void ComputeFlags() + { + module.MethodSemantics.ComputeFlags(module, this.MetadataToken, out isPublic, out isNonPrivate, out isStatic); + flagsCached = true; + } + + internal override bool IsBaked + { + get { return true; } + } + + internal override int GetCurrentToken() + { + return this.MetadataToken; + } + } +} diff --git a/reflect/Reader/ResourceModule.cs b/reflect/Reader/ResourceModule.cs new file mode 100644 index 0000000..0113e47 --- /dev/null +++ b/reflect/Reader/ResourceModule.cs @@ -0,0 +1,107 @@ +/* + Copyright (C) 2009-2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using IKVM.Reflection.Metadata; + +namespace IKVM.Reflection.Reader +{ + sealed class ResourceModule : NonPEModule + { + private readonly ModuleReader manifest; + private readonly int index; + private readonly string location; + + internal ResourceModule(ModuleReader manifest, int index, string location) + : base(manifest.universe) + { + this.manifest = manifest; + this.index = index; + this.location = location; + } + + public override int MDStreamVersion + { + get { throw new NotSupportedException(); } + } + + public override bool IsResource() + { + return true; + } + + public override Assembly Assembly + { + get { return manifest.Assembly; } + } + + public override string FullyQualifiedName + { + get { return location ?? ""; } + } + + public override string Name + { + get { return location == null ? "" : System.IO.Path.GetFileName(location); } + } + + public override string ScopeName + { + get { return manifest.GetString(manifest.File.records[index].Name); } + } + + public override Guid ModuleVersionId + { + get { throw new NotSupportedException(); } + } + + public override byte[] __ModuleHash + { + get + { + int blob = manifest.File.records[index].HashValue; + return blob == 0 ? Empty.Array : manifest.GetBlobCopy(blob); + } + } + + internal override Type FindType(TypeName typeName) + { + return null; + } + + internal override Type FindTypeIgnoreCase(TypeName lowerCaseName) + { + return null; + } + + internal override void GetTypesImpl(List list) + { + } + + protected override Exception ArgumentOutOfRangeException() + { + return new NotSupportedException(); + } + } +} diff --git a/reflect/Reader/TypeDefImpl.cs b/reflect/Reader/TypeDefImpl.cs new file mode 100644 index 0000000..4dc8030 --- /dev/null +++ b/reflect/Reader/TypeDefImpl.cs @@ -0,0 +1,377 @@ +/* + Copyright (C) 2009-2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.InteropServices; +using IKVM.Reflection.Metadata; + +namespace IKVM.Reflection.Reader +{ + sealed class TypeDefImpl : TypeInfo + { + private readonly ModuleReader module; + private readonly int index; + private readonly string typeName; + private readonly string typeNamespace; + private Type[] typeArgs; + + internal TypeDefImpl(ModuleReader module, int index) + { + this.module = module; + this.index = index; + this.typeName = module.GetString(module.TypeDef.records[index].TypeName); + this.typeNamespace = module.GetString(module.TypeDef.records[index].TypeNamespace); + MarkKnownType(typeNamespace, typeName); + } + + public override Type BaseType + { + get + { + int extends = module.TypeDef.records[index].Extends; + if ((extends & 0xFFFFFF) == 0) + { + return null; + } + return module.ResolveType(extends, this); + } + } + + public override TypeAttributes Attributes + { + get { return (TypeAttributes)module.TypeDef.records[index].Flags; } + } + + public override EventInfo[] __GetDeclaredEvents() + { + foreach (int i in module.EventMap.Filter(this.MetadataToken)) + { + int evt = module.EventMap.records[i].EventList - 1; + int end = module.EventMap.records.Length > i + 1 ? module.EventMap.records[i + 1].EventList - 1 : module.Event.records.Length; + EventInfo[] events = new EventInfo[end - evt]; + if (module.EventPtr.RowCount == 0) + { + for (int j = 0; evt < end; evt++, j++) + { + events[j] = new EventInfoImpl(module, this, evt); + } + } + else + { + for (int j = 0; evt < end; evt++, j++) + { + events[j] = new EventInfoImpl(module, this, module.EventPtr.records[evt] - 1); + } + } + return events; + } + return Empty.Array; + } + + public override FieldInfo[] __GetDeclaredFields() + { + int field = module.TypeDef.records[index].FieldList - 1; + int end = module.TypeDef.records.Length > index + 1 ? module.TypeDef.records[index + 1].FieldList - 1 : module.Field.records.Length; + FieldInfo[] fields = new FieldInfo[end - field]; + if (module.FieldPtr.RowCount == 0) + { + for (int i = 0; field < end; i++, field++) + { + fields[i] = module.GetFieldAt(this, field); + } + } + else + { + for (int i = 0; field < end; i++, field++) + { + fields[i] = module.GetFieldAt(this, module.FieldPtr.records[field] - 1); + } + } + return fields; + } + + public override Type[] __GetDeclaredInterfaces() + { + List list = null; + foreach (int i in module.InterfaceImpl.Filter(this.MetadataToken)) + { + if (list == null) + { + list = new List(); + } + list.Add(module.ResolveType(module.InterfaceImpl.records[i].Interface, this)); + } + return Util.ToArray(list, Type.EmptyTypes); + } + + public override MethodBase[] __GetDeclaredMethods() + { + int method = module.TypeDef.records[index].MethodList - 1; + int end = module.TypeDef.records.Length > index + 1 ? module.TypeDef.records[index + 1].MethodList - 1 : module.MethodDef.records.Length; + MethodBase[] methods = new MethodBase[end - method]; + if (module.MethodPtr.RowCount == 0) + { + for (int i = 0; method < end; method++, i++) + { + methods[i] = module.GetMethodAt(this, method); + } + } + else + { + for (int i = 0; method < end; method++, i++) + { + methods[i] = module.GetMethodAt(this, module.MethodPtr.records[method] - 1); + } + } + return methods; + } + + public override __MethodImplMap __GetMethodImplMap() + { + PopulateGenericArguments(); + List bodies = new List(); + List> declarations = new List>(); + foreach (int i in module.MethodImpl.Filter(this.MetadataToken)) + { + MethodInfo body = (MethodInfo)module.ResolveMethod(module.MethodImpl.records[i].MethodBody, typeArgs, null); + int index = bodies.IndexOf(body); + if (index == -1) + { + index = bodies.Count; + bodies.Add(body); + declarations.Add(new List()); + } + MethodInfo declaration = (MethodInfo)module.ResolveMethod(module.MethodImpl.records[i].MethodDeclaration, typeArgs, null); + declarations[index].Add(declaration); + } + __MethodImplMap map = new __MethodImplMap(); + map.TargetType = this; + map.MethodBodies = bodies.ToArray(); + map.MethodDeclarations = new MethodInfo[declarations.Count][]; + for (int i = 0; i < map.MethodDeclarations.Length; i++) + { + map.MethodDeclarations[i] = declarations[i].ToArray(); + } + return map; + } + + public override Type[] __GetDeclaredTypes() + { + int token = this.MetadataToken; + List list = new List(); + // note that the NestedClass table is sorted on NestedClass, so we can't use binary search + for (int i = 0; i < module.NestedClass.records.Length; i++) + { + if (module.NestedClass.records[i].EnclosingClass == token) + { + list.Add(module.ResolveType(module.NestedClass.records[i].NestedClass)); + } + } + return list.ToArray(); + } + + public override PropertyInfo[] __GetDeclaredProperties() + { + foreach (int i in module.PropertyMap.Filter(this.MetadataToken)) + { + int property = module.PropertyMap.records[i].PropertyList - 1; + int end = module.PropertyMap.records.Length > i + 1 ? module.PropertyMap.records[i + 1].PropertyList - 1 : module.Property.records.Length; + PropertyInfo[] properties = new PropertyInfo[end - property]; + if (module.PropertyPtr.RowCount == 0) + { + for (int j = 0; property < end; property++, j++) + { + properties[j] = new PropertyInfoImpl(module, this, property); + } + } + else + { + for (int j = 0; property < end; property++, j++) + { + properties[j] = new PropertyInfoImpl(module, this, module.PropertyPtr.records[property] - 1); + } + } + return properties; + } + return Empty.Array; + } + + internal override TypeName TypeName + { + get { return new TypeName(typeNamespace, typeName); } + } + + public override string Name + { + get { return TypeNameParser.Escape(typeName); } + } + + public override string FullName + { + get { return GetFullName(); } + } + + public override int MetadataToken + { + get { return (TypeDefTable.Index << 24) + index + 1; } + } + + public override Type[] GetGenericArguments() + { + PopulateGenericArguments(); + return Util.Copy(typeArgs); + } + + private void PopulateGenericArguments() + { + if (typeArgs == null) + { + int token = this.MetadataToken; + int first = module.GenericParam.FindFirstByOwner(token); + if (first == -1) + { + typeArgs = Type.EmptyTypes; + } + else + { + List list = new List(); + int len = module.GenericParam.records.Length; + for (int i = first; i < len && module.GenericParam.records[i].Owner == token; i++) + { + list.Add(new GenericTypeParameter(module, i, Signature.ELEMENT_TYPE_VAR)); + } + typeArgs = list.ToArray(); + } + } + } + + internal override Type GetGenericTypeArgument(int index) + { + PopulateGenericArguments(); + return typeArgs[index]; + } + + public override CustomModifiers[] __GetGenericArgumentsCustomModifiers() + { + PopulateGenericArguments(); + return new CustomModifiers[typeArgs.Length]; + } + + public override bool IsGenericType + { + get { return IsGenericTypeDefinition; } + } + + public override bool IsGenericTypeDefinition + { + get + { + if ((typeFlags & (TypeFlags.IsGenericTypeDefinition | TypeFlags.NotGenericTypeDefinition)) == 0) + { + typeFlags |= module.GenericParam.FindFirstByOwner(this.MetadataToken) == -1 + ? TypeFlags.NotGenericTypeDefinition + : TypeFlags.IsGenericTypeDefinition; + } + return (typeFlags & TypeFlags.IsGenericTypeDefinition) != 0; + } + } + + public override Type GetGenericTypeDefinition() + { + if (IsGenericTypeDefinition) + { + return this; + } + throw new InvalidOperationException(); + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(this.FullName); + string sep = "["; + foreach (Type arg in GetGenericArguments()) + { + sb.Append(sep); + sb.Append(arg); + sep = ","; + } + if (sep != "[") + { + sb.Append(']'); + } + return sb.ToString(); + } + + internal bool IsNestedByFlags + { + get { return (this.Attributes & TypeAttributes.VisibilityMask & ~TypeAttributes.Public) != 0; } + } + + public override Type DeclaringType + { + get + { + // note that we cannot use Type.IsNested for this, because that calls DeclaringType + if (!IsNestedByFlags) + { + return null; + } + foreach (int i in module.NestedClass.Filter(this.MetadataToken)) + { + return module.ResolveType(module.NestedClass.records[i].EnclosingClass, null, null); + } + throw new InvalidOperationException(); + } + } + + public override bool __GetLayout(out int packingSize, out int typeSize) + { + foreach (int i in module.ClassLayout.Filter(this.MetadataToken)) + { + packingSize = module.ClassLayout.records[i].PackingSize; + typeSize = module.ClassLayout.records[i].ClassSize; + return true; + } + packingSize = 0; + typeSize = 0; + return false; + } + + public override Module Module + { + get { return module; } + } + + internal override bool IsModulePseudoType + { + get { return index == 0; } + } + + internal override bool IsBaked + { + get { return true; } + } + } +} diff --git a/reflect/Signature.cs b/reflect/Signature.cs new file mode 100644 index 0000000..cb2d9f0 --- /dev/null +++ b/reflect/Signature.cs @@ -0,0 +1,596 @@ +/* + Copyright (C) 2009-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Text; +using CallingConvention = System.Runtime.InteropServices.CallingConvention; +using IKVM.Reflection.Reader; +using IKVM.Reflection.Emit; +using IKVM.Reflection.Writer; +using IKVM.Reflection.Metadata; + +namespace IKVM.Reflection +{ + abstract class Signature + { + internal const byte DEFAULT = 0x00; + internal const byte VARARG = 0x05; + internal const byte GENERIC = 0x10; + internal const byte HASTHIS = 0x20; + internal const byte EXPLICITTHIS = 0x40; + internal const byte FIELD = 0x06; + internal const byte LOCAL_SIG = 0x07; + internal const byte PROPERTY = 0x08; + internal const byte GENERICINST = 0x0A; + internal const byte SENTINEL = 0x41; + internal const byte ELEMENT_TYPE_VOID = 0x01; + internal const byte ELEMENT_TYPE_BOOLEAN = 0x02; + internal const byte ELEMENT_TYPE_CHAR = 0x03; + internal const byte ELEMENT_TYPE_I1 = 0x04; + internal const byte ELEMENT_TYPE_U1 = 0x05; + internal const byte ELEMENT_TYPE_I2 = 0x06; + internal const byte ELEMENT_TYPE_U2 = 0x07; + internal const byte ELEMENT_TYPE_I4 = 0x08; + internal const byte ELEMENT_TYPE_U4 = 0x09; + internal const byte ELEMENT_TYPE_I8 = 0x0a; + internal const byte ELEMENT_TYPE_U8 = 0x0b; + internal const byte ELEMENT_TYPE_R4 = 0x0c; + internal const byte ELEMENT_TYPE_R8 = 0x0d; + internal const byte ELEMENT_TYPE_STRING = 0x0e; + internal const byte ELEMENT_TYPE_PTR = 0x0f; + internal const byte ELEMENT_TYPE_BYREF = 0x10; + internal const byte ELEMENT_TYPE_VALUETYPE = 0x11; + internal const byte ELEMENT_TYPE_CLASS = 0x12; + internal const byte ELEMENT_TYPE_VAR = 0x13; + internal const byte ELEMENT_TYPE_ARRAY = 0x14; + internal const byte ELEMENT_TYPE_GENERICINST = 0x15; + internal const byte ELEMENT_TYPE_TYPEDBYREF = 0x16; + internal const byte ELEMENT_TYPE_I = 0x18; + internal const byte ELEMENT_TYPE_U = 0x19; + internal const byte ELEMENT_TYPE_FNPTR = 0x1b; + internal const byte ELEMENT_TYPE_OBJECT = 0x1c; + internal const byte ELEMENT_TYPE_SZARRAY = 0x1d; + internal const byte ELEMENT_TYPE_MVAR = 0x1e; + internal const byte ELEMENT_TYPE_CMOD_REQD = 0x1f; + internal const byte ELEMENT_TYPE_CMOD_OPT = 0x20; + internal const byte ELEMENT_TYPE_PINNED = 0x45; + + internal abstract void WriteSig(ModuleBuilder module, ByteBuffer bb); + + private static Type ReadGenericInst(ModuleReader module, ByteReader br, IGenericContext context) + { + Type type; + switch (br.ReadByte()) + { + case ELEMENT_TYPE_CLASS: + type = ReadTypeDefOrRefEncoded(module, br, context).MarkNotValueType(); + break; + case ELEMENT_TYPE_VALUETYPE: + type = ReadTypeDefOrRefEncoded(module, br, context).MarkValueType(); + break; + default: + throw new BadImageFormatException(); + } + if (!type.__IsMissing && !type.IsGenericTypeDefinition) + { + throw new BadImageFormatException(); + } + int genArgCount = br.ReadCompressedUInt(); + Type[] args = new Type[genArgCount]; + CustomModifiers[] mods = null; + for (int i = 0; i < genArgCount; i++) + { + // LAMESPEC the Type production (23.2.12) doesn't include CustomMod* for genericinst, but C++ uses it, the verifier allows it and ildasm also supports it + CustomModifiers cm = CustomModifiers.Read(module, br, context); + if (!cm.IsEmpty) + { + if (mods == null) + { + mods = new CustomModifiers[genArgCount]; + } + mods[i] = cm; + } + args[i] = ReadType(module, br, context); + } + return GenericTypeInstance.Make(type, args, mods); + } + + internal static Type ReadTypeSpec(ModuleReader module, ByteReader br, IGenericContext context) + { + // LAMESPEC a TypeSpec can contain custom modifiers (C++/CLI generates "newarr (TypeSpec with custom modifiers)") + CustomModifiers.Skip(br); + // LAMESPEC anything can be adorned by (useless) custom modifiers + // also, VAR and MVAR are also used in TypeSpec (contrary to what the spec says) + return ReadType(module, br, context); + } + + private static Type ReadFunctionPointer(ModuleReader module, ByteReader br, IGenericContext context) + { + __StandAloneMethodSig sig = MethodSignature.ReadStandAloneMethodSig(module, br, context); + if (module.universe.EnableFunctionPointers) + { + return FunctionPointerType.Make(module.universe, sig); + } + else + { + // by default, like .NET we return System.IntPtr here + return module.universe.System_IntPtr; + } + } + + internal static Type[] ReadMethodSpec(ModuleReader module, ByteReader br, IGenericContext context) + { + if (br.ReadByte() != GENERICINST) + { + throw new BadImageFormatException(); + } + Type[] args = new Type[br.ReadCompressedUInt()]; + for (int i = 0; i < args.Length; i++) + { + args[i] = ReadType(module, br, context); + } + return args; + } + + private static int[] ReadArraySizes(ByteReader br) + { + int num = br.ReadCompressedUInt(); + if (num == 0) + { + return null; + } + int[] arr = new int[num]; + for (int i = 0; i < num; i++) + { + arr[i] = br.ReadCompressedUInt(); + } + return arr; + } + + private static int[] ReadArrayBounds(ByteReader br) + { + int num = br.ReadCompressedUInt(); + if (num == 0) + { + return null; + } + int[] arr = new int[num]; + for (int i = 0; i < num; i++) + { + arr[i] = br.ReadCompressedInt(); + } + return arr; + } + + private static Type ReadTypeOrVoid(ModuleReader module, ByteReader br, IGenericContext context) + { + if (br.PeekByte() == ELEMENT_TYPE_VOID) + { + br.ReadByte(); + return module.universe.System_Void; + } + else + { + return ReadType(module, br, context); + } + } + + // see ECMA 335 CLI spec June 2006 section 23.2.12 for this production + protected static Type ReadType(ModuleReader module, ByteReader br, IGenericContext context) + { + CustomModifiers mods; + switch (br.ReadByte()) + { + case ELEMENT_TYPE_CLASS: + return ReadTypeDefOrRefEncoded(module, br, context).MarkNotValueType(); + case ELEMENT_TYPE_VALUETYPE: + return ReadTypeDefOrRefEncoded(module, br, context).MarkValueType(); + case ELEMENT_TYPE_BOOLEAN: + return module.universe.System_Boolean; + case ELEMENT_TYPE_CHAR: + return module.universe.System_Char; + case ELEMENT_TYPE_I1: + return module.universe.System_SByte; + case ELEMENT_TYPE_U1: + return module.universe.System_Byte; + case ELEMENT_TYPE_I2: + return module.universe.System_Int16; + case ELEMENT_TYPE_U2: + return module.universe.System_UInt16; + case ELEMENT_TYPE_I4: + return module.universe.System_Int32; + case ELEMENT_TYPE_U4: + return module.universe.System_UInt32; + case ELEMENT_TYPE_I8: + return module.universe.System_Int64; + case ELEMENT_TYPE_U8: + return module.universe.System_UInt64; + case ELEMENT_TYPE_R4: + return module.universe.System_Single; + case ELEMENT_TYPE_R8: + return module.universe.System_Double; + case ELEMENT_TYPE_I: + return module.universe.System_IntPtr; + case ELEMENT_TYPE_U: + return module.universe.System_UIntPtr; + case ELEMENT_TYPE_STRING: + return module.universe.System_String; + case ELEMENT_TYPE_OBJECT: + return module.universe.System_Object; + case ELEMENT_TYPE_VAR: + return context.GetGenericTypeArgument(br.ReadCompressedUInt()); + case ELEMENT_TYPE_MVAR: + return context.GetGenericMethodArgument(br.ReadCompressedUInt()); + case ELEMENT_TYPE_GENERICINST: + return ReadGenericInst(module, br, context); + case ELEMENT_TYPE_SZARRAY: + mods = CustomModifiers.Read(module, br, context); + return ReadType(module, br, context).__MakeArrayType(mods); + case ELEMENT_TYPE_ARRAY: + mods = CustomModifiers.Read(module, br, context); + return ReadType(module, br, context).__MakeArrayType(br.ReadCompressedUInt(), ReadArraySizes(br), ReadArrayBounds(br), mods); + case ELEMENT_TYPE_PTR: + mods = CustomModifiers.Read(module, br, context); + return ReadTypeOrVoid(module, br, context).__MakePointerType(mods); + case ELEMENT_TYPE_FNPTR: + return ReadFunctionPointer(module, br, context); + default: + throw new BadImageFormatException(); + } + } + + internal static void ReadLocalVarSig(ModuleReader module, ByteReader br, IGenericContext context, List list) + { + if (br.Length < 2 || br.ReadByte() != LOCAL_SIG) + { + throw new BadImageFormatException("Invalid local variable signature"); + } + int count = br.ReadCompressedUInt(); + for (int i = 0; i < count; i++) + { + if (br.PeekByte() == ELEMENT_TYPE_TYPEDBYREF) + { + br.ReadByte(); + list.Add(new LocalVariableInfo(i, module.universe.System_TypedReference, false, new CustomModifiers())); + } + else + { + CustomModifiers mods1 = CustomModifiers.Read(module, br, context); + bool pinned = false; + if (br.PeekByte() == ELEMENT_TYPE_PINNED) + { + br.ReadByte(); + pinned = true; + } + CustomModifiers mods2 = CustomModifiers.Read(module, br, context); + Type type = ReadTypeOrByRef(module, br, context); + list.Add(new LocalVariableInfo(i, type, pinned, CustomModifiers.Combine(mods1, mods2))); + } + } + } + + private static Type ReadTypeOrByRef(ModuleReader module, ByteReader br, IGenericContext context) + { + if (br.PeekByte() == ELEMENT_TYPE_BYREF) + { + br.ReadByte(); + // LAMESPEC it is allowed (by C++/CLI, ilasm and peverify) to have custom modifiers after the BYREF + // (which makes sense, as it is analogous to pointers) + CustomModifiers mods = CustomModifiers.Read(module, br, context); + // C++/CLI generates void& local variables, so we need to use ReadTypeOrVoid here + return ReadTypeOrVoid(module, br, context).__MakeByRefType(mods); + } + else + { + return ReadType(module, br, context); + } + } + + protected static Type ReadRetType(ModuleReader module, ByteReader br, IGenericContext context) + { + switch (br.PeekByte()) + { + case ELEMENT_TYPE_VOID: + br.ReadByte(); + return module.universe.System_Void; + case ELEMENT_TYPE_TYPEDBYREF: + br.ReadByte(); + return module.universe.System_TypedReference; + default: + return ReadTypeOrByRef(module, br, context); + } + } + + protected static Type ReadParam(ModuleReader module, ByteReader br, IGenericContext context) + { + switch (br.PeekByte()) + { + case ELEMENT_TYPE_TYPEDBYREF: + br.ReadByte(); + return module.universe.System_TypedReference; + default: + return ReadTypeOrByRef(module, br, context); + } + } + + protected static void WriteType(ModuleBuilder module, ByteBuffer bb, Type type) + { + while (type.HasElementType) + { + byte sigElementType = type.SigElementType; + bb.Write(sigElementType); + if (sigElementType == ELEMENT_TYPE_ARRAY) + { + // LAMESPEC the Type production (23.2.12) doesn't include CustomMod* for arrays, but the verifier allows it and ildasm also supports it + WriteCustomModifiers(module, bb, type.__GetCustomModifiers()); + WriteType(module, bb, type.GetElementType()); + bb.WriteCompressedUInt(type.GetArrayRank()); + int[] sizes = type.__GetArraySizes(); + bb.WriteCompressedUInt(sizes.Length); + for (int i = 0; i < sizes.Length; i++) + { + bb.WriteCompressedUInt(sizes[i]); + } + int[] lobounds = type.__GetArrayLowerBounds(); + bb.WriteCompressedUInt(lobounds.Length); + for (int i = 0; i < lobounds.Length; i++) + { + bb.WriteCompressedInt(lobounds[i]); + } + return; + } + WriteCustomModifiers(module, bb, type.__GetCustomModifiers()); + type = type.GetElementType(); + } + if (type.__IsBuiltIn) + { + bb.Write(type.SigElementType); + } + else if (type.IsGenericParameter) + { + bb.Write(type.SigElementType); + bb.WriteCompressedUInt(type.GenericParameterPosition); + } + else if (!type.__IsMissing && type.IsGenericType) + { + WriteGenericSignature(module, bb, type); + } + else if (type.__IsFunctionPointer) + { + bb.Write(ELEMENT_TYPE_FNPTR); + WriteStandAloneMethodSig(module, bb, type.__MethodSignature); + } + else + { + if (type.IsValueType) + { + bb.Write(ELEMENT_TYPE_VALUETYPE); + } + else + { + bb.Write(ELEMENT_TYPE_CLASS); + } + bb.WriteTypeDefOrRefEncoded(module.GetTypeToken(type).Token); + } + } + + private static void WriteGenericSignature(ModuleBuilder module, ByteBuffer bb, Type type) + { + Type[] typeArguments = type.GetGenericArguments(); + CustomModifiers[] customModifiers = type.__GetGenericArgumentsCustomModifiers(); + if (!type.IsGenericTypeDefinition) + { + type = type.GetGenericTypeDefinition(); + } + bb.Write(ELEMENT_TYPE_GENERICINST); + if (type.IsValueType) + { + bb.Write(ELEMENT_TYPE_VALUETYPE); + } + else + { + bb.Write(ELEMENT_TYPE_CLASS); + } + bb.WriteTypeDefOrRefEncoded(module.GetTypeToken(type).Token); + bb.WriteCompressedUInt(typeArguments.Length); + for (int i = 0; i < typeArguments.Length; i++) + { + WriteCustomModifiers(module, bb, customModifiers[i]); + WriteType(module, bb, typeArguments[i]); + } + } + + protected static void WriteCustomModifiers(ModuleBuilder module, ByteBuffer bb, CustomModifiers modifiers) + { + foreach (CustomModifiers.Entry entry in modifiers) + { + bb.Write(entry.IsRequired ? ELEMENT_TYPE_CMOD_REQD : ELEMENT_TYPE_CMOD_OPT); + bb.WriteTypeDefOrRefEncoded(module.GetTypeTokenForMemberRef(entry.Type)); + } + } + + internal static Type ReadTypeDefOrRefEncoded(ModuleReader module, ByteReader br, IGenericContext context) + { + int encoded = br.ReadCompressedUInt(); + switch (encoded & 3) + { + case 0: + return module.ResolveType((TypeDefTable.Index << 24) + (encoded >> 2), null, null); + case 1: + return module.ResolveType((TypeRefTable.Index << 24) + (encoded >> 2), null, null); + case 2: + return module.ResolveType((TypeSpecTable.Index << 24) + (encoded >> 2), context); + default: + throw new BadImageFormatException(); + } + } + + internal static void WriteStandAloneMethodSig(ModuleBuilder module, ByteBuffer bb, __StandAloneMethodSig sig) + { + if (sig.IsUnmanaged) + { + switch (sig.UnmanagedCallingConvention) + { + case CallingConvention.Cdecl: + bb.Write((byte)0x01); // C + break; + case CallingConvention.StdCall: + case CallingConvention.Winapi: + bb.Write((byte)0x02); // STDCALL + break; + case CallingConvention.ThisCall: + bb.Write((byte)0x03); // THISCALL + break; + case CallingConvention.FastCall: + bb.Write((byte)0x04); // FASTCALL + break; + default: + throw new ArgumentOutOfRangeException("callingConvention"); + } + } + else + { + CallingConventions callingConvention = sig.CallingConvention; + byte flags = 0; + if ((callingConvention & CallingConventions.HasThis) != 0) + { + flags |= HASTHIS; + } + if ((callingConvention & CallingConventions.ExplicitThis) != 0) + { + flags |= EXPLICITTHIS; + } + if ((callingConvention & CallingConventions.VarArgs) != 0) + { + flags |= VARARG; + } + bb.Write(flags); + } + Type[] parameterTypes = sig.ParameterTypes; + Type[] optionalParameterTypes = sig.OptionalParameterTypes; + bb.WriteCompressedUInt(parameterTypes.Length + optionalParameterTypes.Length); + WriteCustomModifiers(module, bb, sig.GetReturnTypeCustomModifiers()); + WriteType(module, bb, sig.ReturnType); + int index = 0; + foreach (Type t in parameterTypes) + { + WriteCustomModifiers(module, bb, sig.GetParameterCustomModifiers(index++)); + WriteType(module, bb, t); + } + // note that optional parameters are only allowed for managed signatures (but we don't enforce that) + if (optionalParameterTypes.Length > 0) + { + bb.Write(SENTINEL); + foreach (Type t in optionalParameterTypes) + { + WriteCustomModifiers(module, bb, sig.GetParameterCustomModifiers(index++)); + WriteType(module, bb, t); + } + } + } + + internal static void WriteTypeSpec(ModuleBuilder module, ByteBuffer bb, Type type) + { + WriteType(module, bb, type); + } + + internal static void WriteMethodSpec(ModuleBuilder module, ByteBuffer bb, Type[] genArgs) + { + bb.Write(GENERICINST); + bb.WriteCompressedUInt(genArgs.Length); + foreach (Type arg in genArgs) + { + WriteType(module, bb, arg); + } + } + + // this reads just the optional parameter types, from a MethodRefSig + internal static Type[] ReadOptionalParameterTypes(ModuleReader module, ByteReader br, IGenericContext context, out CustomModifiers[] customModifiers) + { + br.ReadByte(); + int paramCount = br.ReadCompressedUInt(); + CustomModifiers.Skip(br); + ReadRetType(module, br, context); + for (int i = 0; i < paramCount; i++) + { + if (br.PeekByte() == SENTINEL) + { + br.ReadByte(); + Type[] types = new Type[paramCount - i]; + customModifiers = new CustomModifiers[types.Length]; + for (int j = 0; j < types.Length; j++) + { + customModifiers[j] = CustomModifiers.Read(module, br, context); + types[j] = ReadType(module, br, context); + } + return types; + } + CustomModifiers.Skip(br); + ReadType(module, br, context); + } + customModifiers = Empty.Array; + return Type.EmptyTypes; + } + + protected static Type[] BindTypeParameters(IGenericBinder binder, Type[] types) + { + if (types == null || types.Length == 0) + { + return Type.EmptyTypes; + } + Type[] expanded = new Type[types.Length]; + for (int i = 0; i < types.Length; i++) + { + expanded[i] = types[i].BindTypeParameters(binder); + } + return expanded; + } + + internal static void WriteSignatureHelper(ModuleBuilder module, ByteBuffer bb, byte flags, ushort paramCount, List args) + { + bb.Write(flags); + if (flags != FIELD) + { + bb.WriteCompressedUInt(paramCount); + } + foreach (Type type in args) + { + if (type == null) + { + bb.Write(ELEMENT_TYPE_VOID); + } + else if (type is MarkerType) + { + bb.Write(type.SigElementType); + } + else + { + WriteType(module, bb, type); + } + } + } + } +} diff --git a/reflect/StandAloneMethodSig.cs b/reflect/StandAloneMethodSig.cs new file mode 100644 index 0000000..bbeee90 --- /dev/null +++ b/reflect/StandAloneMethodSig.cs @@ -0,0 +1,130 @@ +/* + Copyright (C) 2010 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Runtime.InteropServices; +using IKVM.Reflection.Reader; + +namespace IKVM.Reflection +{ + public sealed class __StandAloneMethodSig + { + private readonly bool unmanaged; + private readonly CallingConvention unmanagedCallingConvention; + private readonly CallingConventions callingConvention; + private readonly Type returnType; + private readonly Type[] parameterTypes; + private readonly Type[] optionalParameterTypes; + private readonly PackedCustomModifiers customModifiers; + + internal __StandAloneMethodSig(bool unmanaged, CallingConvention unmanagedCallingConvention, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes, PackedCustomModifiers customModifiers) + { + this.unmanaged = unmanaged; + this.unmanagedCallingConvention = unmanagedCallingConvention; + this.callingConvention = callingConvention; + this.returnType = returnType; + this.parameterTypes = parameterTypes; + this.optionalParameterTypes = optionalParameterTypes; + this.customModifiers = customModifiers; + } + + public bool Equals(__StandAloneMethodSig other) + { + return other != null + && other.unmanaged == unmanaged + && other.unmanagedCallingConvention == unmanagedCallingConvention + && other.callingConvention == callingConvention + && other.returnType == returnType + && Util.ArrayEquals(other.parameterTypes, parameterTypes) + && Util.ArrayEquals(other.optionalParameterTypes, optionalParameterTypes) + && other.customModifiers.Equals(customModifiers); + } + + public override bool Equals(object obj) + { + return Equals(obj as __StandAloneMethodSig); + } + + public override int GetHashCode() + { + return returnType.GetHashCode() + ^ Util.GetHashCode(parameterTypes); + } + + public bool IsUnmanaged + { + get { return unmanaged; } + } + + public CallingConventions CallingConvention + { + get { return callingConvention; } + } + + public CallingConvention UnmanagedCallingConvention + { + get { return unmanagedCallingConvention; } + } + + public Type ReturnType + { + get { return returnType; } + } + + public CustomModifiers GetReturnTypeCustomModifiers() + { + return customModifiers.GetReturnTypeCustomModifiers(); + } + + public Type[] ParameterTypes + { + get { return Util.Copy(parameterTypes); } + } + + public Type[] OptionalParameterTypes + { + get { return Util.Copy(optionalParameterTypes); } + } + + public CustomModifiers GetParameterCustomModifiers(int index) + { + return customModifiers.GetParameterCustomModifiers(index); + } + + public bool ContainsMissingType + { + get + { + return returnType.__ContainsMissingType + || Type.ContainsMissingType(parameterTypes) + || Type.ContainsMissingType(optionalParameterTypes) + || customModifiers.ContainsMissingType; + } + } + + internal int ParameterCount + { + get { return parameterTypes.Length + optionalParameterTypes.Length; } + } + } +} diff --git a/reflect/StrongNameKeyPair.cs b/reflect/StrongNameKeyPair.cs new file mode 100644 index 0000000..1e17bc4 --- /dev/null +++ b/reflect/StrongNameKeyPair.cs @@ -0,0 +1,140 @@ +/* + Copyright (C) 2009-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.IO; +using System.Security.Cryptography; + +namespace IKVM.Reflection +{ + public sealed class StrongNameKeyPair + { + private readonly byte[] keyPairArray; + private readonly string keyPairContainer; + + public StrongNameKeyPair(string keyPairContainer) + { + if (keyPairContainer == null) + { + throw new ArgumentNullException("keyPairContainer"); + } + if (Universe.MonoRuntime && Environment.OSVersion.Platform == PlatformID.Win32NT) + { + throw new NotSupportedException("IKVM.Reflection does not support key containers when running on Mono"); + } + this.keyPairContainer = keyPairContainer; + } + + public StrongNameKeyPair(byte[] keyPairArray) + { + if (keyPairArray == null) + { + throw new ArgumentNullException("keyPairArray"); + } + this.keyPairArray = (byte[])keyPairArray.Clone(); + } + + public StrongNameKeyPair(FileStream keyPairFile) + : this(ReadAllBytes(keyPairFile)) + { + } + + private static byte[] ReadAllBytes(FileStream keyPairFile) + { + if (keyPairFile == null) + { + throw new ArgumentNullException("keyPairFile"); + } + byte[] buf = new byte[keyPairFile.Length - keyPairFile.Position]; + keyPairFile.Read(buf, 0, buf.Length); + return buf; + } + + public byte[] PublicKey + { + get + { +#if !CORECLR + if (Universe.MonoRuntime) + { + // MONOBUG workaround for https://bugzilla.xamarin.com/show_bug.cgi?id=5299 + return MonoGetPublicKey(); + } +#endif + using (RSACryptoServiceProvider rsa = CreateRSA()) + { + byte[] cspBlob = rsa.ExportCspBlob(false); + byte[] publicKey = new byte[12 + cspBlob.Length]; + Buffer.BlockCopy(cspBlob, 0, publicKey, 12, cspBlob.Length); + publicKey[1] = 36; + publicKey[4] = 4; + publicKey[5] = 128; + publicKey[8] = (byte)(cspBlob.Length >> 0); + publicKey[9] = (byte)(cspBlob.Length >> 8); + publicKey[10] = (byte)(cspBlob.Length >> 16); + publicKey[11] = (byte)(cspBlob.Length >> 24); + return publicKey; + } + } + } + + internal RSACryptoServiceProvider CreateRSA() + { + try + { + if (keyPairArray != null) + { + RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); + rsa.ImportCspBlob(keyPairArray); + return rsa; + } + else + { + CspParameters parm = new CspParameters(); + parm.KeyContainerName = keyPairContainer; + // MONOBUG Mono doesn't like it when Flags or KeyNumber are set + if (!Universe.MonoRuntime) + { + parm.Flags = CspProviderFlags.UseMachineKeyStore | CspProviderFlags.UseExistingKey; + parm.KeyNumber = 2; // Signature + } + return new RSACryptoServiceProvider(parm); + } + } + catch + { + throw new ArgumentException("Unable to obtain public key for StrongNameKeyPair."); + } + } + +#if !CORECLR + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] + private byte[] MonoGetPublicKey() + { + return keyPairArray != null + ? new System.Reflection.StrongNameKeyPair(keyPairArray).PublicKey + : new System.Reflection.StrongNameKeyPair(keyPairContainer).PublicKey; + } +#endif + } +} diff --git a/reflect/Type.cs b/reflect/Type.cs new file mode 100644 index 0000000..1550b02 --- /dev/null +++ b/reflect/Type.cs @@ -0,0 +1,3266 @@ +/* + Copyright (C) 2009-2015 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Runtime.InteropServices; +using System.Text; +using System.Collections.Generic; +using IKVM.Reflection.Emit; + +namespace IKVM.Reflection +{ + interface IGenericContext + { + Type GetGenericTypeArgument(int index); + Type GetGenericMethodArgument(int index); + } + + interface IGenericBinder + { + Type BindTypeParameter(Type type); + Type BindMethodParameter(Type type); + } + + public abstract class Type : MemberInfo, IGenericContext, IGenericBinder + { + public static readonly Type[] EmptyTypes = Empty.Array; + protected readonly Type underlyingType; + protected TypeFlags typeFlags; + private byte sigElementType; // only used if (__IsBuiltIn || HasElementType || __IsFunctionPointer || IsGenericParameter) + + [Flags] + protected enum TypeFlags : ushort + { + // for use by TypeBuilder or TypeDefImpl + IsGenericTypeDefinition = 1, + + // for use by TypeBuilder + HasNestedTypes = 2, + Baked = 4, + + // for use by MissingType + ValueType = 8, + NotValueType = 16, + + // for use by TypeDefImpl, TypeBuilder or MissingType + PotentialEnumOrValueType = 32, + EnumOrValueType = 64, + + // for use by TypeDefImpl + NotGenericTypeDefinition = 128, + + // used to cache __ContainsMissingType + ContainsMissingType_Unknown = 0, + ContainsMissingType_Pending = 256, + ContainsMissingType_Yes = 512, + ContainsMissingType_No = 256 | 512, + ContainsMissingType_Mask = 256 | 512, + + // built-in type support + PotentialBuiltIn = 1024, + BuiltIn = 2048, + } + + // prevent subclassing by outsiders + internal Type() + { + this.underlyingType = this; + } + + internal Type(Type underlyingType) + { + System.Diagnostics.Debug.Assert(underlyingType.underlyingType == underlyingType); + this.underlyingType = underlyingType; + this.typeFlags = underlyingType.typeFlags; + } + + internal Type(byte sigElementType) + : this() + { + this.sigElementType = sigElementType; + } + + public static Binder DefaultBinder + { + get { return new DefaultBinder(); } + } + + public sealed override MemberTypes MemberType + { + get { return IsNested ? MemberTypes.NestedType : MemberTypes.TypeInfo; } + } + + public virtual string AssemblyQualifiedName + { + // NOTE the assembly name is not escaped here, only when used in a generic type instantiation + get { return this.FullName + ", " + this.Assembly.FullName; } + } + + public abstract Type BaseType + { + get; + } + + public abstract TypeAttributes Attributes + { + get; + } + + public virtual Type GetElementType() + { + return null; + } + + internal virtual void CheckBaked() + { + } + + public virtual Type[] __GetDeclaredTypes() + { + return Type.EmptyTypes; + } + + public virtual Type[] __GetDeclaredInterfaces() + { + return Type.EmptyTypes; + } + + public virtual MethodBase[] __GetDeclaredMethods() + { + return Empty.Array; + } + + public virtual __MethodImplMap __GetMethodImplMap() + { + throw new NotSupportedException(); + } + + public virtual FieldInfo[] __GetDeclaredFields() + { + return Empty.Array; + } + + public virtual EventInfo[] __GetDeclaredEvents() + { + return Empty.Array; + } + + public virtual PropertyInfo[] __GetDeclaredProperties() + { + return Empty.Array; + } + + public virtual CustomModifiers __GetCustomModifiers() + { + return new CustomModifiers(); + } + + [Obsolete("Please use __GetCustomModifiers() instead.")] + public Type[] __GetRequiredCustomModifiers() + { + return __GetCustomModifiers().GetRequired(); + } + + [Obsolete("Please use __GetCustomModifiers() instead.")] + public Type[] __GetOptionalCustomModifiers() + { + return __GetCustomModifiers().GetOptional(); + } + + public virtual __StandAloneMethodSig __MethodSignature + { + get { throw new InvalidOperationException(); } + } + + public bool HasElementType + { + get { return IsArray || IsByRef || IsPointer; } + } + + public bool IsArray + { + get { return sigElementType == Signature.ELEMENT_TYPE_ARRAY || sigElementType == Signature.ELEMENT_TYPE_SZARRAY; } + } + + public bool __IsVector + { + get { return sigElementType == Signature.ELEMENT_TYPE_SZARRAY; } + } + + public bool IsByRef + { + get { return sigElementType == Signature.ELEMENT_TYPE_BYREF; } + } + + public bool IsPointer + { + get { return sigElementType == Signature.ELEMENT_TYPE_PTR; } + } + + public bool __IsFunctionPointer + { + get { return sigElementType == Signature.ELEMENT_TYPE_FNPTR; } + } + + public virtual bool IsValueType + { + get + { + Type baseType = this.BaseType; + return baseType != null + && baseType.IsEnumOrValueType + && !this.IsEnumOrValueType; + } + } + + public bool IsGenericParameter + { + get { return sigElementType == Signature.ELEMENT_TYPE_VAR || sigElementType == Signature.ELEMENT_TYPE_MVAR; } + } + + public virtual int GenericParameterPosition + { + get { throw new NotSupportedException(); } + } + + public virtual MethodBase DeclaringMethod + { + get { return null; } + } + + public Type UnderlyingSystemType + { + get { return underlyingType; } + } + + public override Type DeclaringType + { + get { return null; } + } + + internal virtual TypeName TypeName + { + get { throw new InvalidOperationException(); } + } + + public string __Name + { + get { return TypeName.Name; } + } + + public string __Namespace + { + get { return TypeName.Namespace; } + } + + public abstract override string Name + { + get; + } + + public virtual string Namespace + { + get + { + if (IsNested) + { + return DeclaringType.Namespace; + } + return __Namespace; + } + } + + internal virtual int GetModuleBuilderToken() + { + throw new InvalidOperationException(); + } + + public static bool operator ==(Type t1, Type t2) + { + // Casting to object results in smaller code than calling ReferenceEquals and makes + // this method more likely to be inlined. + // On CLR v2 x86, microbenchmarks show this to be faster than calling ReferenceEquals. + return (object)t1 == (object)t2 + || ((object)t1 != null && (object)t2 != null && (object)t1.underlyingType == (object)t2.underlyingType); + } + + public static bool operator !=(Type t1, Type t2) + { + return !(t1 == t2); + } + + public bool Equals(Type type) + { + return this == type; + } + + public override bool Equals(object obj) + { + return Equals(obj as Type); + } + + public override int GetHashCode() + { + Type type = this.UnderlyingSystemType; + return ReferenceEquals(type, this) ? base.GetHashCode() : type.GetHashCode(); + } + + public Type[] GenericTypeArguments + { + get { return IsConstructedGenericType ? GetGenericArguments() : Type.EmptyTypes; } + } + + public virtual Type[] GetGenericArguments() + { + return Type.EmptyTypes; + } + + public virtual CustomModifiers[] __GetGenericArgumentsCustomModifiers() + { + return Empty.Array; + } + + [Obsolete("Please use __GetGenericArgumentsCustomModifiers() instead")] + public Type[][] __GetGenericArgumentsRequiredCustomModifiers() + { + CustomModifiers[] customModifiers = __GetGenericArgumentsCustomModifiers(); + Type[][] array = new Type[customModifiers.Length][]; + for (int i = 0; i < array.Length; i++) + { + array[i] = customModifiers[i].GetRequired(); + } + return array; + } + + [Obsolete("Please use __GetGenericArgumentsCustomModifiers() instead")] + public Type[][] __GetGenericArgumentsOptionalCustomModifiers() + { + CustomModifiers[] customModifiers = __GetGenericArgumentsCustomModifiers(); + Type[][] array = new Type[customModifiers.Length][]; + for (int i = 0; i < array.Length; i++) + { + array[i] = customModifiers[i].GetOptional(); + } + return array; + } + + public virtual Type GetGenericTypeDefinition() + { + throw new InvalidOperationException(); + } + + public StructLayoutAttribute StructLayoutAttribute + { + get + { + StructLayoutAttribute layout; + switch (this.Attributes & TypeAttributes.LayoutMask) + { + case TypeAttributes.AutoLayout: + layout = new StructLayoutAttribute(LayoutKind.Auto); + break; + case TypeAttributes.SequentialLayout: + layout = new StructLayoutAttribute(LayoutKind.Sequential); + break; + case TypeAttributes.ExplicitLayout: + layout = new StructLayoutAttribute(LayoutKind.Explicit); + break; + default: + throw new BadImageFormatException(); + } + switch (this.Attributes & TypeAttributes.StringFormatMask) + { + case TypeAttributes.AnsiClass: + layout.CharSet = CharSet.Ansi; + break; + case TypeAttributes.UnicodeClass: + layout.CharSet = CharSet.Unicode; + break; + case TypeAttributes.AutoClass: + layout.CharSet = CharSet.Auto; + break; + default: + layout.CharSet = CharSet.None; + break; + } + if (!__GetLayout(out layout.Pack, out layout.Size)) + { + // compatibility with System.Reflection + layout.Pack = 8; + } + return layout; + } + } + + public virtual bool __GetLayout(out int packingSize, out int typeSize) + { + packingSize = 0; + typeSize = 0; + return false; + } + + public virtual bool IsGenericType + { + get { return false; } + } + + public virtual bool IsGenericTypeDefinition + { + get { return false; } + } + + // .NET 4.5 API + public virtual bool IsConstructedGenericType + { + get { return false; } + } + + public virtual bool ContainsGenericParameters + { + get + { + if (this.IsGenericParameter) + { + return true; + } + foreach (Type arg in this.GetGenericArguments()) + { + if (arg.ContainsGenericParameters) + { + return true; + } + } + return false; + } + } + + public virtual Type[] GetGenericParameterConstraints() + { + throw new InvalidOperationException(); + } + + public virtual CustomModifiers[] __GetGenericParameterConstraintCustomModifiers() + { + throw new InvalidOperationException(); + } + + public virtual GenericParameterAttributes GenericParameterAttributes + { + get { throw new InvalidOperationException(); } + } + + public virtual int GetArrayRank() + { + throw new NotSupportedException(); + } + + public virtual int[] __GetArraySizes() + { + throw new NotSupportedException(); + } + + public virtual int[] __GetArrayLowerBounds() + { + throw new NotSupportedException(); + } + + // .NET 4.0 API + public virtual Type GetEnumUnderlyingType() + { + if (!this.IsEnum) + { + throw new ArgumentException(); + } + CheckBaked(); + return GetEnumUnderlyingTypeImpl(); + } + + internal Type GetEnumUnderlyingTypeImpl() + { + foreach (FieldInfo field in __GetDeclaredFields()) + { + if (!field.IsStatic) + { + // the CLR assumes that an enum has only one instance field, so we can do the same + return field.FieldType; + } + } + throw new InvalidOperationException(); + } + + public string[] GetEnumNames() + { + if (!IsEnum) + { + throw new ArgumentException(); + } + List names = new List(); + foreach (FieldInfo field in __GetDeclaredFields()) + { + if (field.IsLiteral) + { + names.Add(field.Name); + } + } + return names.ToArray(); + } + +#if !CORECLR + public string GetEnumName(object value) + { + if (!IsEnum) + { + throw new ArgumentException(); + } + if (value == null) + { + throw new ArgumentNullException(); + } + try + { + value = Convert.ChangeType(value, GetTypeCode(GetEnumUnderlyingType())); + } + catch (FormatException) + { + throw new ArgumentException(); + } + catch (OverflowException) + { + return null; + } + catch (InvalidCastException) + { + return null; + } + foreach (FieldInfo field in __GetDeclaredFields()) + { + if (field.IsLiteral && field.GetRawConstantValue().Equals(value)) + { + return field.Name; + } + } + return null; + } +#endif + + public bool IsEnumDefined(object value) + { + if (value is string) + { + return Array.IndexOf(GetEnumNames(), value) != -1; + } + if (!IsEnum) + { + throw new ArgumentException(); + } + if (value == null) + { + throw new ArgumentNullException(); + } + if (System.Type.GetTypeCode(value.GetType()) != GetTypeCode(GetEnumUnderlyingType())) + { + throw new ArgumentException(); + } + foreach (FieldInfo field in __GetDeclaredFields()) + { + if (field.IsLiteral && field.GetRawConstantValue().Equals(value)) + { + return true; + } + } + return false; + } + + public override string ToString() + { + return FullName; + } + + public abstract string FullName + { + get; + } + + protected string GetFullName() + { + string ns = TypeNameParser.Escape(this.__Namespace); + Type decl = this.DeclaringType; + if (decl == null) + { + if (ns == null) + { + return this.Name; + } + else + { + return ns + "." + this.Name; + } + } + else + { + if (ns == null) + { + return decl.FullName + "+" + this.Name; + } + else + { + return decl.FullName + "+" + ns + "." + this.Name; + } + } + } + + internal virtual bool IsModulePseudoType + { + get { return false; } + } + + internal virtual Type GetGenericTypeArgument(int index) + { + throw new InvalidOperationException(); + } + + public MemberInfo[] GetDefaultMembers() + { + Type defaultMemberAttribute = this.Module.universe.Import(typeof(System.Reflection.DefaultMemberAttribute)); + foreach (CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(this)) + { + if (cad.Constructor.DeclaringType.Equals(defaultMemberAttribute)) + { + return GetMember((string)cad.ConstructorArguments[0].Value); + } + } + return Empty.Array; + } + + public MemberInfo[] GetMember(string name) + { + return GetMember(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); + } + + public MemberInfo[] GetMember(string name, BindingFlags bindingAttr) + { + return GetMember(name, MemberTypes.All, bindingAttr); + } + + public MemberInfo[] GetMembers() + { + return GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); + } + + public MemberInfo[] GetMembers(BindingFlags bindingAttr) + { + List members = new List(); + members.AddRange(GetConstructors(bindingAttr)); + members.AddRange(GetMethods(bindingAttr)); + members.AddRange(GetFields(bindingAttr)); + members.AddRange(GetProperties(bindingAttr)); + members.AddRange(GetEvents(bindingAttr)); + members.AddRange(GetNestedTypes(bindingAttr)); + return members.ToArray(); + } + + public MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr) + { + MemberFilter filter; + if ((bindingAttr & BindingFlags.IgnoreCase) != 0) + { + name = name.ToLowerInvariant(); + filter = delegate(MemberInfo member, object filterCriteria) { return member.Name.ToLowerInvariant().Equals(filterCriteria); }; + } + else + { + filter = delegate(MemberInfo member, object filterCriteria) { return member.Name.Equals(filterCriteria); }; + } + return FindMembers(type, bindingAttr, filter, name); + } + + private static void AddMembers(List list, MemberFilter filter, object filterCriteria, MemberInfo[] members) + { + foreach (MemberInfo member in members) + { + if (filter == null || filter(member, filterCriteria)) + { + list.Add(member); + } + } + } + + public MemberInfo[] FindMembers(MemberTypes memberType, BindingFlags bindingAttr, MemberFilter filter, object filterCriteria) + { + List members = new List(); + if ((memberType & MemberTypes.Constructor) != 0) + { + AddMembers(members, filter, filterCriteria, GetConstructors(bindingAttr)); + } + if ((memberType & MemberTypes.Method) != 0) + { + AddMembers(members, filter, filterCriteria, GetMethods(bindingAttr)); + } + if ((memberType & MemberTypes.Field) != 0) + { + AddMembers(members, filter, filterCriteria, GetFields(bindingAttr)); + } + if ((memberType & MemberTypes.Property) != 0) + { + AddMembers(members, filter, filterCriteria, GetProperties(bindingAttr)); + } + if ((memberType & MemberTypes.Event) != 0) + { + AddMembers(members, filter, filterCriteria, GetEvents(bindingAttr)); + } + if ((memberType & MemberTypes.NestedType) != 0) + { + AddMembers(members, filter, filterCriteria, GetNestedTypes(bindingAttr)); + } + return members.ToArray(); + } + + private MemberInfo[] GetMembers() + { + if (typeof(T) == typeof(ConstructorInfo) || typeof(T) == typeof(MethodInfo)) + { + return __GetDeclaredMethods(); + } + else if (typeof(T) == typeof(FieldInfo)) + { + return __GetDeclaredFields(); + } + else if (typeof(T) == typeof(PropertyInfo)) + { + return __GetDeclaredProperties(); + } + else if (typeof(T) == typeof(EventInfo)) + { + return __GetDeclaredEvents(); + } + else if (typeof(T) == typeof(Type)) + { + return __GetDeclaredTypes(); + } + else + { + throw new InvalidOperationException(); + } + } + + private T[] GetMembers(BindingFlags flags) + where T : MemberInfo + { + CheckBaked(); + List list = new List(); + foreach (MemberInfo member in GetMembers()) + { + if (member is T && member.BindingFlagsMatch(flags)) + { + list.Add((T)member); + } + } + if ((flags & BindingFlags.DeclaredOnly) == 0) + { + for (Type type = this.BaseType; type != null; type = type.BaseType) + { + type.CheckBaked(); + foreach (MemberInfo member in type.GetMembers()) + { + if (member is T && member.BindingFlagsMatchInherited(flags)) + { + list.Add((T)member.SetReflectedType(this)); + } + } + } + } + return list.ToArray(); + } + + private T GetMemberByName(string name, BindingFlags flags, Predicate filter) + where T : MemberInfo + { + CheckBaked(); + if ((flags & BindingFlags.IgnoreCase) != 0) + { + name = name.ToLowerInvariant(); + } + T found = null; + foreach (MemberInfo member in GetMembers()) + { + if (member is T && member.BindingFlagsMatch(flags)) + { + string memberName = member.Name; + if ((flags & BindingFlags.IgnoreCase) != 0) + { + memberName = memberName.ToLowerInvariant(); + } + if (memberName == name && (filter == null || filter((T)member))) + { + if (found != null) + { + throw new AmbiguousMatchException(); + } + found = (T)member; + } + } + } + if ((flags & BindingFlags.DeclaredOnly) == 0) + { + for (Type type = this.BaseType; (found == null || typeof(T) == typeof(MethodInfo)) && type != null; type = type.BaseType) + { + type.CheckBaked(); + foreach (MemberInfo member in type.GetMembers()) + { + if (member is T && member.BindingFlagsMatchInherited(flags)) + { + string memberName = member.Name; + if ((flags & BindingFlags.IgnoreCase) != 0) + { + memberName = memberName.ToLowerInvariant(); + } + if (memberName == name && (filter == null || filter((T)member))) + { + if (found != null) + { + MethodInfo mi; + // TODO does this depend on HideBySig vs HideByName? + if ((mi = found as MethodInfo) != null + && mi.MethodSignature.MatchParameterTypes(((MethodBase)member).MethodSignature)) + { + continue; + } + throw new AmbiguousMatchException(); + } + found = (T)member.SetReflectedType(this); + } + } + } + } + } + return found; + } + + private T GetMemberByName(string name, BindingFlags flags) + where T : MemberInfo + { + return GetMemberByName(name, flags, null); + } + + public EventInfo GetEvent(string name) + { + return GetEvent(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); + } + + public EventInfo GetEvent(string name, BindingFlags bindingAttr) + { + return GetMemberByName(name, bindingAttr); + } + + public EventInfo[] GetEvents() + { + return GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); + } + + public EventInfo[] GetEvents(BindingFlags bindingAttr) + { + return GetMembers(bindingAttr); + } + + public FieldInfo GetField(string name) + { + return GetField(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); + } + + public FieldInfo GetField(string name, BindingFlags bindingAttr) + { + return GetMemberByName(name, bindingAttr); + } + + public FieldInfo[] GetFields() + { + return GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance); + } + + public FieldInfo[] GetFields(BindingFlags bindingAttr) + { + return GetMembers(bindingAttr); + } + + public Type[] GetInterfaces() + { + List list = new List(); + for (Type type = this; type != null; type = type.BaseType) + { + AddInterfaces(list, type); + } + return list.ToArray(); + } + + private static void AddInterfaces(List list, Type type) + { + foreach (Type iface in type.__GetDeclaredInterfaces()) + { + if (!list.Contains(iface)) + { + list.Add(iface); + AddInterfaces(list, iface); + } + } + } + + public MethodInfo[] GetMethods(BindingFlags bindingAttr) + { + CheckBaked(); + List list = new List(); + foreach (MethodBase mb in __GetDeclaredMethods()) + { + MethodInfo mi = mb as MethodInfo; + if (mi != null && mi.BindingFlagsMatch(bindingAttr)) + { + list.Add(mi); + } + } + if ((bindingAttr & BindingFlags.DeclaredOnly) == 0) + { + List baseMethods = new List(); + foreach (MethodInfo mi in list) + { + if (mi.IsVirtual) + { + baseMethods.Add(mi.GetBaseDefinition()); + } + } + for (Type type = this.BaseType; type != null; type = type.BaseType) + { + type.CheckBaked(); + foreach (MethodBase mb in type.__GetDeclaredMethods()) + { + MethodInfo mi = mb as MethodInfo; + if (mi != null && mi.BindingFlagsMatchInherited(bindingAttr)) + { + if (mi.IsVirtual) + { + if (baseMethods == null) + { + baseMethods = new List(); + } + else if (baseMethods.Contains(mi.GetBaseDefinition())) + { + continue; + } + baseMethods.Add(mi.GetBaseDefinition()); + } + list.Add((MethodInfo)mi.SetReflectedType(this)); + } + } + } + } + return list.ToArray(); + } + + public MethodInfo[] GetMethods() + { + return GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance); + } + + public MethodInfo GetMethod(string name) + { + return GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public); + } + + public MethodInfo GetMethod(string name, BindingFlags bindingAttr) + { + return GetMemberByName(name, bindingAttr); + } + + public MethodInfo GetMethod(string name, Type[] types) + { + return GetMethod(name, types, null); + } + + public MethodInfo GetMethod(string name, Type[] types, ParameterModifier[] modifiers) + { + return GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, types, modifiers); + } + + public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) + { + // first we try an exact match and only if that fails we fall back to using the binder + return GetMemberByName(name, bindingAttr, + delegate(MethodInfo method) { return method.MethodSignature.MatchParameterTypes(types); }) + ?? GetMethodWithBinder(name, bindingAttr, binder ?? DefaultBinder, types, modifiers); + } + + private T GetMethodWithBinder(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) + where T : MethodBase + { + List list = new List(); + GetMemberByName(name, bindingAttr, delegate(T method) { + list.Add(method); + return false; + }); + return (T)binder.SelectMethod(bindingAttr, list.ToArray(), types, modifiers); + } + + public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) + { + // FXBUG callConvention seems to be ignored + return GetMethod(name, bindingAttr, binder, types, modifiers); + } + + public ConstructorInfo[] GetConstructors() + { + return GetConstructors(BindingFlags.Public | BindingFlags.Instance); + } + + public ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) + { + return GetMembers(bindingAttr | BindingFlags.DeclaredOnly); + } + + public ConstructorInfo GetConstructor(Type[] types) + { + return GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, CallingConventions.Standard, types, null); + } + + public ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) + { + ConstructorInfo ci1 = null; + if ((bindingAttr & BindingFlags.Instance) != 0) + { + ci1 = GetConstructorImpl(ConstructorInfo.ConstructorName, bindingAttr, binder, types, modifiers); + } + if ((bindingAttr & BindingFlags.Static) != 0) + { + ConstructorInfo ci2 = GetConstructorImpl(ConstructorInfo.TypeConstructorName, bindingAttr, binder, types, modifiers); + if (ci2 != null) + { + if (ci1 != null) + { + throw new AmbiguousMatchException(); + } + return ci2; + } + } + return ci1; + } + + private ConstructorInfo GetConstructorImpl(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) + { + // first we try an exact match and only if that fails we fall back to using the binder + return GetMemberByName(name, bindingAttr | BindingFlags.DeclaredOnly, + delegate(ConstructorInfo ctor) { return ctor.MethodSignature.MatchParameterTypes(types); }) + ?? GetMethodWithBinder(name, bindingAttr, binder ?? DefaultBinder, types, modifiers); + } + + public ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder, CallingConventions callingConvention, Type[] types, ParameterModifier[] modifiers) + { + // FXBUG callConvention seems to be ignored + return GetConstructor(bindingAttr, binder, types, modifiers); + } + + internal Type ResolveNestedType(Module requester, TypeName typeName) + { + return FindNestedType(typeName) ?? Module.universe.GetMissingTypeOrThrow(requester, Module, this, typeName); + } + + // unlike the public API, this takes the namespace and name into account + internal virtual Type FindNestedType(TypeName name) + { + foreach (Type type in __GetDeclaredTypes()) + { + if (type.TypeName == name) + { + return type; + } + } + return null; + } + + internal virtual Type FindNestedTypeIgnoreCase(TypeName lowerCaseName) + { + foreach (Type type in __GetDeclaredTypes()) + { + if (type.TypeName.ToLowerInvariant() == lowerCaseName) + { + return type; + } + } + return null; + } + + public Type GetNestedType(string name) + { + return GetNestedType(name, BindingFlags.Public); + } + + public Type GetNestedType(string name, BindingFlags bindingAttr) + { + // FXBUG the namespace is ignored, so we can use GetMemberByName + return GetMemberByName(name, bindingAttr | BindingFlags.DeclaredOnly); + } + + public Type[] GetNestedTypes() + { + return GetNestedTypes(BindingFlags.Public); + } + + public Type[] GetNestedTypes(BindingFlags bindingAttr) + { + // FXBUG the namespace is ignored, so we can use GetMember + return GetMembers(bindingAttr | BindingFlags.DeclaredOnly); + } + + public PropertyInfo[] GetProperties() + { + return GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); + } + + public PropertyInfo[] GetProperties(BindingFlags bindingAttr) + { + return GetMembers(bindingAttr); + } + + public PropertyInfo GetProperty(string name) + { + return GetProperty(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); + } + + public PropertyInfo GetProperty(string name, BindingFlags bindingAttr) + { + return GetMemberByName(name, bindingAttr); + } + + public PropertyInfo GetProperty(string name, Type returnType) + { + const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static; + return GetMemberByName(name, flags, delegate(PropertyInfo prop) { return prop.PropertyType.Equals(returnType); }) + ?? GetPropertyWithBinder(name, flags, DefaultBinder, returnType, null, null); + } + + public PropertyInfo GetProperty(string name, Type[] types) + { + const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static; + return GetMemberByName(name, flags, delegate(PropertyInfo prop) { return prop.PropertySignature.MatchParameterTypes(types); }) + ?? GetPropertyWithBinder(name, flags, DefaultBinder, null, types, null); + } + + public PropertyInfo GetProperty(string name, Type returnType, Type[] types) + { + return GetProperty(name, returnType, types, null); + } + + public PropertyInfo GetProperty(string name, Type returnType, Type[] types, ParameterModifier[] modifiers) + { + return GetProperty(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static, null, returnType, types, modifiers); + } + + public PropertyInfo GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) + { + return GetMemberByName(name, bindingAttr, + delegate(PropertyInfo prop) { + return prop.PropertyType.Equals(returnType) && prop.PropertySignature.MatchParameterTypes(types); + }) + ?? GetPropertyWithBinder(name, bindingAttr, binder ?? DefaultBinder, returnType, types, modifiers); + } + + private PropertyInfo GetPropertyWithBinder(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) + { + List list = new List(); + GetMemberByName(name, bindingAttr, delegate(PropertyInfo property) { + list.Add(property); + return false; + }); + return binder.SelectProperty(bindingAttr, list.ToArray(), returnType, types, modifiers); + } + + public Type GetInterface(string name) + { + return GetInterface(name, false); + } + + public Type GetInterface(string name, bool ignoreCase) + { + if (ignoreCase) + { + name = name.ToLowerInvariant(); + } + Type found = null; + foreach (Type type in GetInterfaces()) + { + string typeName = type.FullName; + if (ignoreCase) + { + typeName = typeName.ToLowerInvariant(); + } + if (typeName == name) + { + if (found != null) + { + throw new AmbiguousMatchException(); + } + found = type; + } + } + return found; + } + + public Type[] FindInterfaces(TypeFilter filter, object filterCriteria) + { + List list = new List(); + foreach (Type type in GetInterfaces()) + { + if (filter(type, filterCriteria)) + { + list.Add(type); + } + } + return list.ToArray(); + } + + public ConstructorInfo TypeInitializer + { + get { return GetConstructor(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); } + } + + public bool IsPrimitive + { + get + { + return __IsBuiltIn + && ((sigElementType >= Signature.ELEMENT_TYPE_BOOLEAN && sigElementType <= Signature.ELEMENT_TYPE_R8) + || sigElementType == Signature.ELEMENT_TYPE_I + || sigElementType == Signature.ELEMENT_TYPE_U); + } + } + + public bool __IsBuiltIn + { + get + { + return (typeFlags & (TypeFlags.BuiltIn | TypeFlags.PotentialBuiltIn)) != 0 + && ((typeFlags & TypeFlags.BuiltIn) != 0 || ResolvePotentialBuiltInType()); + } + } + + internal byte SigElementType + { + get + { + // this property can only be called after __IsBuiltIn, HasElementType, __IsFunctionPointer or IsGenericParameter returned true + System.Diagnostics.Debug.Assert((typeFlags & TypeFlags.BuiltIn) != 0 || HasElementType || __IsFunctionPointer || IsGenericParameter); + return sigElementType; + } + } + + private bool ResolvePotentialBuiltInType() + { + // [ECMA 335] 8.2.2 Built-in value and reference types + typeFlags &= ~TypeFlags.PotentialBuiltIn; + Universe u = this.Universe; + switch (__Name) + { + case "Boolean": + return ResolvePotentialBuiltInType(u.System_Boolean, Signature.ELEMENT_TYPE_BOOLEAN); + case "Char": + return ResolvePotentialBuiltInType(u.System_Char, Signature.ELEMENT_TYPE_CHAR); + case "Object": + return ResolvePotentialBuiltInType(u.System_Object, Signature.ELEMENT_TYPE_OBJECT); + case "String": + return ResolvePotentialBuiltInType(u.System_String, Signature.ELEMENT_TYPE_STRING); + case "Single": + return ResolvePotentialBuiltInType(u.System_Single, Signature.ELEMENT_TYPE_R4); + case "Double": + return ResolvePotentialBuiltInType(u.System_Double, Signature.ELEMENT_TYPE_R8); + case "SByte": + return ResolvePotentialBuiltInType(u.System_SByte, Signature.ELEMENT_TYPE_I1); + case "Int16": + return ResolvePotentialBuiltInType(u.System_Int16, Signature.ELEMENT_TYPE_I2); + case "Int32": + return ResolvePotentialBuiltInType(u.System_Int32, Signature.ELEMENT_TYPE_I4); + case "Int64": + return ResolvePotentialBuiltInType(u.System_Int64, Signature.ELEMENT_TYPE_I8); + case "IntPtr": + return ResolvePotentialBuiltInType(u.System_IntPtr, Signature.ELEMENT_TYPE_I); + case "UIntPtr": + return ResolvePotentialBuiltInType(u.System_UIntPtr, Signature.ELEMENT_TYPE_U); + case "TypedReference": + return ResolvePotentialBuiltInType(u.System_TypedReference, Signature.ELEMENT_TYPE_TYPEDBYREF); + case "Byte": + return ResolvePotentialBuiltInType(u.System_Byte, Signature.ELEMENT_TYPE_U1); + case "UInt16": + return ResolvePotentialBuiltInType(u.System_UInt16, Signature.ELEMENT_TYPE_U2); + case "UInt32": + return ResolvePotentialBuiltInType(u.System_UInt32, Signature.ELEMENT_TYPE_U4); + case "UInt64": + return ResolvePotentialBuiltInType(u.System_UInt64, Signature.ELEMENT_TYPE_U8); + case "Void": // [LAMESPEC] missing from ECMA list for some reason + return ResolvePotentialBuiltInType(u.System_Void, Signature.ELEMENT_TYPE_VOID); + default: + throw new InvalidOperationException(); + } + } + + private bool ResolvePotentialBuiltInType(Type builtIn, byte elementType) + { + if (this == builtIn) + { + typeFlags |= TypeFlags.BuiltIn; + this.sigElementType = elementType; + return true; + } + return false; + } + + public bool IsEnum + { + get + { + Type baseType = this.BaseType; + return baseType != null + && baseType.IsEnumOrValueType + && baseType.__Name[0] == 'E'; + } + } + + public bool IsSealed + { + get { return (Attributes & TypeAttributes.Sealed) != 0; } + } + + public bool IsAbstract + { + get { return (Attributes & TypeAttributes.Abstract) != 0; } + } + + private bool CheckVisibility(TypeAttributes access) + { + return (Attributes & TypeAttributes.VisibilityMask) == access; + } + + public bool IsPublic + { + get { return CheckVisibility(TypeAttributes.Public); } + } + + public bool IsNestedPublic + { + get { return CheckVisibility(TypeAttributes.NestedPublic); } + } + + public bool IsNestedPrivate + { + get { return CheckVisibility(TypeAttributes.NestedPrivate); } + } + + public bool IsNestedFamily + { + get { return CheckVisibility(TypeAttributes.NestedFamily); } + } + + public bool IsNestedAssembly + { + get { return CheckVisibility(TypeAttributes.NestedAssembly); } + } + + public bool IsNestedFamANDAssem + { + get { return CheckVisibility(TypeAttributes.NestedFamANDAssem); } + } + + public bool IsNestedFamORAssem + { + get { return CheckVisibility(TypeAttributes.NestedFamORAssem); } + } + + public bool IsNotPublic + { + get { return CheckVisibility(TypeAttributes.NotPublic); } + } + + public bool IsImport + { + get { return (Attributes & TypeAttributes.Import) != 0; } + } + + public bool IsCOMObject + { + get { return IsClass && IsImport; } + } + +#if !CORECLR + public bool IsContextful + { + get { return IsSubclassOf(this.Module.universe.Import(typeof(ContextBoundObject))); } + } + + public bool IsMarshalByRef + { + get { return IsSubclassOf(this.Module.universe.Import(typeof(MarshalByRefObject))); } + } +#endif + + public virtual bool IsVisible + { + get { return IsPublic || (IsNestedPublic && this.DeclaringType.IsVisible); } + } + + public bool IsAnsiClass + { + get { return (Attributes & TypeAttributes.StringFormatMask) == TypeAttributes.AnsiClass; } + } + + public bool IsUnicodeClass + { + get { return (Attributes & TypeAttributes.StringFormatMask) == TypeAttributes.UnicodeClass; } + } + + public bool IsAutoClass + { + get { return (Attributes & TypeAttributes.StringFormatMask) == TypeAttributes.AutoClass; } + } + + public bool IsAutoLayout + { + get { return (Attributes & TypeAttributes.LayoutMask) == TypeAttributes.AutoLayout; } + } + + public bool IsLayoutSequential + { + get { return (Attributes & TypeAttributes.LayoutMask) == TypeAttributes.SequentialLayout; } + } + + public bool IsExplicitLayout + { + get { return (Attributes & TypeAttributes.LayoutMask) == TypeAttributes.ExplicitLayout; } + } + + public bool IsSpecialName + { + get { return (Attributes & TypeAttributes.SpecialName) != 0; } + } + + public bool IsSerializable + { + get { return (Attributes & TypeAttributes.Serializable) != 0; } + } + + public bool IsClass + { + get { return !IsInterface && !IsValueType; } + } + + public bool IsInterface + { + get { return (Attributes & TypeAttributes.Interface) != 0; } + } + + public bool IsNested + { + // FXBUG we check the declaring type (like .NET) and this results + // in IsNested returning true for a generic type parameter + get { return this.DeclaringType != null; } + } + + public bool __ContainsMissingType + { + get + { + if ((typeFlags & TypeFlags.ContainsMissingType_Mask) == TypeFlags.ContainsMissingType_Unknown) + { + // Generic parameter constraints can refer back to the type parameter they are part of, + // so to prevent infinite recursion, we set the Pending flag during computation. + typeFlags |= TypeFlags.ContainsMissingType_Pending; + typeFlags = (typeFlags & ~TypeFlags.ContainsMissingType_Mask) | (ContainsMissingTypeImpl ? TypeFlags.ContainsMissingType_Yes : TypeFlags.ContainsMissingType_No); + } + return (typeFlags & TypeFlags.ContainsMissingType_Mask) == TypeFlags.ContainsMissingType_Yes; + } + } + + internal static bool ContainsMissingType(Type[] types) + { + if (types == null) + { + return false; + } + foreach (Type type in types) + { + if (type.__ContainsMissingType) + { + return true; + } + } + return false; + } + + protected virtual bool ContainsMissingTypeImpl + { + get + { + return __IsMissing + || ContainsMissingType(GetGenericArguments()) + || __GetCustomModifiers().ContainsMissingType; + } + } + + public Type MakeArrayType() + { + return ArrayType.Make(this, new CustomModifiers()); + } + + public Type __MakeArrayType(CustomModifiers customModifiers) + { + return ArrayType.Make(this, customModifiers); + } + + [Obsolete("Please use __MakeArrayType(CustomModifiers) instead.")] + public Type __MakeArrayType(Type[] requiredCustomModifiers, Type[] optionalCustomModifiers) + { + return __MakeArrayType(CustomModifiers.FromReqOpt(requiredCustomModifiers, optionalCustomModifiers)); + } + + public Type MakeArrayType(int rank) + { + return __MakeArrayType(rank, new CustomModifiers()); + } + + public Type __MakeArrayType(int rank, CustomModifiers customModifiers) + { + return MultiArrayType.Make(this, rank, Empty.Array, new int[rank], customModifiers); + } + + [Obsolete("Please use __MakeArrayType(int, CustomModifiers) instead.")] + public Type __MakeArrayType(int rank, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers) + { + return __MakeArrayType(rank, CustomModifiers.FromReqOpt(requiredCustomModifiers, optionalCustomModifiers)); + } + + public Type __MakeArrayType(int rank, int[] sizes, int[] lobounds, CustomModifiers customModifiers) + { + return MultiArrayType.Make(this, rank, sizes ?? Empty.Array, lobounds ?? Empty.Array, customModifiers); + } + + [Obsolete("Please use __MakeArrayType(int, int[], int[], CustomModifiers) instead.")] + public Type __MakeArrayType(int rank, int[] sizes, int[] lobounds, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers) + { + return __MakeArrayType(rank, sizes, lobounds, CustomModifiers.FromReqOpt(requiredCustomModifiers, optionalCustomModifiers)); + } + + public Type MakeByRefType() + { + return ByRefType.Make(this, new CustomModifiers()); + } + + public Type __MakeByRefType(CustomModifiers customModifiers) + { + return ByRefType.Make(this, customModifiers); + } + + [Obsolete("Please use __MakeByRefType(CustomModifiers) instead.")] + public Type __MakeByRefType(Type[] requiredCustomModifiers, Type[] optionalCustomModifiers) + { + return __MakeByRefType(CustomModifiers.FromReqOpt(requiredCustomModifiers, optionalCustomModifiers)); + } + + public Type MakePointerType() + { + return PointerType.Make(this, new CustomModifiers()); + } + + public Type __MakePointerType(CustomModifiers customModifiers) + { + return PointerType.Make(this, customModifiers); + } + + [Obsolete("Please use __MakeByRefType(CustomModifiers) instead.")] + public Type __MakePointerType(Type[] requiredCustomModifiers, Type[] optionalCustomModifiers) + { + return __MakePointerType(CustomModifiers.FromReqOpt(requiredCustomModifiers, optionalCustomModifiers)); + } + + public Type MakeGenericType(params Type[] typeArguments) + { + return __MakeGenericType(typeArguments, null); + } + + public Type __MakeGenericType(Type[] typeArguments, CustomModifiers[] customModifiers) + { + if (!this.__IsMissing && !this.IsGenericTypeDefinition) + { + throw new InvalidOperationException(); + } + return GenericTypeInstance.Make(this, Util.Copy(typeArguments), customModifiers == null ? null : (CustomModifiers[])customModifiers.Clone()); + } + + [Obsolete("Please use __MakeGenericType(Type[], CustomModifiers[]) instead.")] + public Type __MakeGenericType(Type[] typeArguments, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers) + { + if (!this.__IsMissing && !this.IsGenericTypeDefinition) + { + throw new InvalidOperationException(); + } + CustomModifiers[] mods = null; + if (requiredCustomModifiers != null || optionalCustomModifiers != null) + { + mods = new CustomModifiers[typeArguments.Length]; + for (int i = 0; i < mods.Length; i++) + { + mods[i] = CustomModifiers.FromReqOpt(Util.NullSafeElementAt(requiredCustomModifiers, i), Util.NullSafeElementAt(optionalCustomModifiers, i)); + } + } + return GenericTypeInstance.Make(this, Util.Copy(typeArguments), mods); + } + + public static System.Type __GetSystemType(TypeCode typeCode) + { + switch (typeCode) + { + case TypeCode.Boolean: + return typeof(System.Boolean); + case TypeCode.Byte: + return typeof(System.Byte); + case TypeCode.Char: + return typeof(System.Char); + case TypeCode.DBNull: + return typeof(System.DBNull); + case TypeCode.DateTime: + return typeof(System.DateTime); + case TypeCode.Decimal: + return typeof(System.Decimal); + case TypeCode.Double: + return typeof(System.Double); + case TypeCode.Empty: + return null; + case TypeCode.Int16: + return typeof(System.Int16); + case TypeCode.Int32: + return typeof(System.Int32); + case TypeCode.Int64: + return typeof(System.Int64); + case TypeCode.Object: + return typeof(System.Object); + case TypeCode.SByte: + return typeof(System.SByte); + case TypeCode.Single: + return typeof(System.Single); + case TypeCode.String: + return typeof(System.String); + case TypeCode.UInt16: + return typeof(System.UInt16); + case TypeCode.UInt32: + return typeof(System.UInt32); + case TypeCode.UInt64: + return typeof(System.UInt64); + default: + throw new ArgumentOutOfRangeException(); + } + } + + public static TypeCode GetTypeCode(Type type) + { + if (type == null) + { + return TypeCode.Empty; + } + if (!type.__IsMissing && type.IsEnum) + { + type = type.GetEnumUnderlyingType(); + } + Universe u = type.Module.universe; + if (type == u.System_Boolean) + { + return TypeCode.Boolean; + } + else if (type == u.System_Char) + { + return TypeCode.Char; + } + else if (type == u.System_SByte) + { + return TypeCode.SByte; + } + else if (type == u.System_Byte) + { + return TypeCode.Byte; + } + else if (type == u.System_Int16) + { + return TypeCode.Int16; + } + else if (type == u.System_UInt16) + { + return TypeCode.UInt16; + } + else if (type == u.System_Int32) + { + return TypeCode.Int32; + } + else if (type == u.System_UInt32) + { + return TypeCode.UInt32; + } + else if (type == u.System_Int64) + { + return TypeCode.Int64; + } + else if (type == u.System_UInt64) + { + return TypeCode.UInt64; + } + else if (type == u.System_Single) + { + return TypeCode.Single; + } + else if (type == u.System_Double) + { + return TypeCode.Double; + } + else if (type == u.System_DateTime) + { + return TypeCode.DateTime; + } + else if (type == u.System_DBNull) + { + return TypeCode.DBNull; + } + else if (type == u.System_Decimal) + { + return TypeCode.Decimal; + } + else if (type == u.System_String) + { + return TypeCode.String; + } + else if (type.__IsMissing) + { + throw new MissingMemberException(type); + } + else + { + return TypeCode.Object; + } + } + + public Assembly Assembly + { + get { return Module.Assembly; } + } + + public bool IsAssignableFrom(Type type) + { + if (this.Equals(type)) + { + return true; + } + else if (type == null) + { + return false; + } + else if (this.IsArray && type.IsArray) + { + if (this.GetArrayRank() != type.GetArrayRank()) + { + return false; + } + else if (this.__IsVector && !type.__IsVector) + { + return false; + } + Type e1 = this.GetElementType(); + Type e2 = type.GetElementType(); + return e1.IsValueType == e2.IsValueType && e1.IsAssignableFrom(e2); + } + else if (this.IsCovariant(type)) + { + return true; + } + else if (this.IsSealed) + { + return false; + } + else if (this.IsInterface) + { + foreach (Type iface in type.GetInterfaces()) + { + if (this.Equals(iface) || this.IsCovariant(iface)) + { + return true; + } + } + return false; + } + else if (type.IsInterface) + { + return this == this.Module.universe.System_Object; + } + else if (type.IsPointer) + { + return this == this.Module.universe.System_Object || this == this.Module.universe.System_ValueType; + } + else + { + return type.IsSubclassOf(this); + } + } + + private bool IsCovariant(Type other) + { + if (this.IsConstructedGenericType + && other.IsConstructedGenericType + && this.GetGenericTypeDefinition() == other.GetGenericTypeDefinition()) + { + Type[] typeParameters = GetGenericTypeDefinition().GetGenericArguments(); + for (int i = 0; i < typeParameters.Length; i++) + { + Type t1 = this.GetGenericTypeArgument(i); + Type t2 = other.GetGenericTypeArgument(i); + if (t1.IsValueType != t2.IsValueType) + { + return false; + } + switch (typeParameters[i].GenericParameterAttributes & GenericParameterAttributes.VarianceMask) + { + case GenericParameterAttributes.Covariant: + if (!t1.IsAssignableFrom(t2)) + { + return false; + } + break; + case GenericParameterAttributes.Contravariant: + if (!t2.IsAssignableFrom(t1)) + { + return false; + } + break; + case GenericParameterAttributes.None: + if (t1 != t2) + { + return false; + } + break; + } + } + return true; + } + return false; + } + + public bool IsSubclassOf(Type type) + { + Type thisType = this.BaseType; + while (thisType != null) + { + if (thisType.Equals(type)) + { + return true; + } + thisType = thisType.BaseType; + } + return false; + } + + // This returns true if this type directly (i.e. not inherited from the base class) implements the interface. + // Note that a complicating factor is that the interface itself can be implemented by an interface that extends it. + private bool IsDirectlyImplementedInterface(Type interfaceType) + { + foreach (Type iface in __GetDeclaredInterfaces()) + { + if (interfaceType.IsAssignableFrom(iface)) + { + return true; + } + } + return false; + } + + public InterfaceMapping GetInterfaceMap(Type interfaceType) + { + CheckBaked(); + InterfaceMapping map; + map.InterfaceMethods = interfaceType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public); + map.InterfaceType = interfaceType; + map.TargetMethods = new MethodInfo[map.InterfaceMethods.Length]; + map.TargetType = this; + FillInInterfaceMethods(interfaceType, map.InterfaceMethods, map.TargetMethods); + return map; + } + + private void FillInInterfaceMethods(Type interfaceType, MethodInfo[] interfaceMethods, MethodInfo[] targetMethods) + { + FillInExplicitInterfaceMethods(interfaceMethods, targetMethods); + bool direct = IsDirectlyImplementedInterface(interfaceType); + if (direct) + { + FillInImplicitInterfaceMethods(interfaceMethods, targetMethods); + } + Type baseType = this.BaseType; + if (baseType != null) + { + baseType.FillInInterfaceMethods(interfaceType, interfaceMethods, targetMethods); + ReplaceOverriddenMethods(targetMethods); + } + if (direct) + { + for (Type type = this.BaseType; type != null && type.Module == Module; type = type.BaseType) + { + type.FillInImplicitInterfaceMethods(interfaceMethods, targetMethods); + } + } + } + + private void FillInImplicitInterfaceMethods(MethodInfo[] interfaceMethods, MethodInfo[] targetMethods) + { + MethodBase[] methods = null; + for (int i = 0; i < targetMethods.Length; i++) + { + if (targetMethods[i] == null) + { + if (methods == null) + { + methods = __GetDeclaredMethods(); + } + for (int j = 0; j < methods.Length; j++) + { + if (methods[j].IsVirtual + && methods[j].Name == interfaceMethods[i].Name + && methods[j].MethodSignature.Equals(interfaceMethods[i].MethodSignature)) + { + targetMethods[i] = (MethodInfo)methods[j]; + break; + } + } + } + } + } + + private void ReplaceOverriddenMethods(MethodInfo[] baseMethods) + { + __MethodImplMap impl = __GetMethodImplMap(); + for (int i = 0; i < baseMethods.Length; i++) + { + if (baseMethods[i] != null && !baseMethods[i].IsFinal) + { + MethodInfo def = baseMethods[i].GetBaseDefinition(); + for (int j = 0; j < impl.MethodDeclarations.Length; j++) + { + for (int k = 0; k < impl.MethodDeclarations[j].Length; k++) + { + if (impl.MethodDeclarations[j][k].GetBaseDefinition() == def) + { + baseMethods[i] = impl.MethodBodies[j]; + goto next; + } + } + } + MethodInfo candidate = FindMethod(def.Name, def.MethodSignature) as MethodInfo; + if (candidate != null && candidate.IsVirtual && !candidate.IsNewSlot) + { + baseMethods[i] = candidate; + } + } + next: ; + } + } + + internal void FillInExplicitInterfaceMethods(MethodInfo[] interfaceMethods, MethodInfo[] targetMethods) + { + __MethodImplMap impl = __GetMethodImplMap(); + for (int i = 0; i < impl.MethodDeclarations.Length; i++) + { + for (int j = 0; j < impl.MethodDeclarations[i].Length; j++) + { + int index = Array.IndexOf(interfaceMethods, impl.MethodDeclarations[i][j]); + if (index != -1 && targetMethods[index] == null) + { + targetMethods[index] = impl.MethodBodies[i]; + } + } + } + } + + Type IGenericContext.GetGenericTypeArgument(int index) + { + return GetGenericTypeArgument(index); + } + + Type IGenericContext.GetGenericMethodArgument(int index) + { + throw new BadImageFormatException(); + } + + Type IGenericBinder.BindTypeParameter(Type type) + { + return GetGenericTypeArgument(type.GenericParameterPosition); + } + + Type IGenericBinder.BindMethodParameter(Type type) + { + throw new BadImageFormatException(); + } + + internal virtual Type BindTypeParameters(IGenericBinder binder) + { + if (IsGenericTypeDefinition) + { + Type[] args = GetGenericArguments(); + Type.InplaceBindTypeParameters(binder, args); + return GenericTypeInstance.Make(this, args, null); + } + else + { + return this; + } + } + + private static void InplaceBindTypeParameters(IGenericBinder binder, Type[] types) + { + for (int i = 0; i < types.Length; i++) + { + types[i] = types[i].BindTypeParameters(binder); + } + } + + internal virtual MethodBase FindMethod(string name, MethodSignature signature) + { + foreach (MethodBase method in __GetDeclaredMethods()) + { + if (method.Name == name && method.MethodSignature.Equals(signature)) + { + return method; + } + } + return null; + } + + internal virtual FieldInfo FindField(string name, FieldSignature signature) + { + foreach (FieldInfo field in __GetDeclaredFields()) + { + if (field.Name == name && field.FieldSignature.Equals(signature)) + { + return field; + } + } + return null; + } + + internal bool IsAllowMultipleCustomAttribute + { + get + { + IList cad = CustomAttributeData.__GetCustomAttributes(this, this.Module.universe.System_AttributeUsageAttribute, false); + if (cad.Count == 1) + { + foreach (CustomAttributeNamedArgument arg in cad[0].NamedArguments) + { + if (arg.MemberInfo.Name == "AllowMultiple") + { + return (bool)arg.TypedValue.Value; + } + } + } + return false; + } + } + + internal Type MarkNotValueType() + { + typeFlags |= TypeFlags.NotValueType; + return this; + } + + internal Type MarkValueType() + { + typeFlags |= TypeFlags.ValueType; + return this; + } + + internal ConstructorInfo GetPseudoCustomAttributeConstructor(params Type[] parameterTypes) + { + Universe u = this.Module.universe; + MethodSignature methodSig = MethodSignature.MakeFromBuilder(u.System_Void, parameterTypes, new PackedCustomModifiers(), CallingConventions.Standard | CallingConventions.HasThis, 0); + MethodBase mb = + FindMethod(".ctor", methodSig) ?? + u.GetMissingMethodOrThrow(null, this, ".ctor", methodSig); + return (ConstructorInfo)mb; + } + + public MethodBase __CreateMissingMethod(string name, CallingConventions callingConvention, Type returnType, CustomModifiers returnTypeCustomModifiers, Type[] parameterTypes, CustomModifiers[] parameterTypeCustomModifiers) + { + return CreateMissingMethod(name, callingConvention, returnType, parameterTypes, PackedCustomModifiers.CreateFromExternal(returnTypeCustomModifiers, parameterTypeCustomModifiers, parameterTypes.Length)); + } + + private MethodBase CreateMissingMethod(string name, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, PackedCustomModifiers customModifiers) + { + MethodSignature sig = new MethodSignature( + returnType ?? this.Module.universe.System_Void, + Util.Copy(parameterTypes), + customModifiers, + callingConvention, + 0); + MethodInfo method = new MissingMethod(this, name, sig); + if (name == ".ctor" || name == ".cctor") + { + return new ConstructorInfoImpl(method); + } + return method; + } + + [Obsolete("Please use __CreateMissingMethod(string, CallingConventions, Type, CustomModifiers, Type[], CustomModifiers[]) instead")] + public MethodBase __CreateMissingMethod(string name, CallingConventions callingConvention, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers) + { + return CreateMissingMethod(name, callingConvention, returnType, parameterTypes, PackedCustomModifiers.CreateFromExternal(returnTypeOptionalCustomModifiers, returnTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers, parameterTypeRequiredCustomModifiers, parameterTypes.Length)); + } + + public FieldInfo __CreateMissingField(string name, Type fieldType, CustomModifiers customModifiers) + { + return new MissingField(this, name, FieldSignature.Create(fieldType, customModifiers)); + } + + [Obsolete("Please use __CreateMissingField(string, Type, CustomModifiers) instead")] + public FieldInfo __CreateMissingField(string name, Type fieldType, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers) + { + return __CreateMissingField(name, fieldType, CustomModifiers.FromReqOpt(requiredCustomModifiers, optionalCustomModifiers)); + } + + public PropertyInfo __CreateMissingProperty(string name, CallingConventions callingConvention, Type propertyType, CustomModifiers propertyTypeCustomModifiers, Type[] parameterTypes, CustomModifiers[] parameterTypeCustomModifiers) + { + PropertySignature sig = PropertySignature.Create(callingConvention, + propertyType, + parameterTypes, + PackedCustomModifiers.CreateFromExternal(propertyTypeCustomModifiers, parameterTypeCustomModifiers, Util.NullSafeLength(parameterTypes))); + return new MissingProperty(this, name, sig); + } + + internal virtual Type SetMetadataTokenForMissing(int token, int flags) + { + return this; + } + + internal virtual Type SetCyclicTypeForwarder() + { + return this; + } + + protected void MarkKnownType(string typeNamespace, string typeName) + { + // we assume that mscorlib won't have nested types with these names, + // so we don't check that we're not a nested type + if (typeNamespace == "System") + { + switch (typeName) + { + case "Boolean": + case "Char": + case "Object": + case "String": + case "Single": + case "Double": + case "SByte": + case "Int16": + case "Int32": + case "Int64": + case "IntPtr": + case "UIntPtr": + case "TypedReference": + case "Byte": + case "UInt16": + case "UInt32": + case "UInt64": + case "Void": + typeFlags |= TypeFlags.PotentialBuiltIn; + break; + case "Enum": + case "ValueType": + typeFlags |= TypeFlags.PotentialEnumOrValueType; + break; + } + } + } + + private bool ResolvePotentialEnumOrValueType() + { + if (this.Assembly == this.Universe.Mscorlib + || this.Assembly.GetName().Name.Equals("mscorlib", StringComparison.OrdinalIgnoreCase) + // check if mscorlib forwards the type (.NETCore profile reference mscorlib forwards System.Enum and System.ValueType to System.Runtime.dll) + || this.Universe.Mscorlib.FindType(TypeName) == this) + { + typeFlags = (typeFlags & ~TypeFlags.PotentialEnumOrValueType) | TypeFlags.EnumOrValueType; + return true; + } + else + { + typeFlags &= ~TypeFlags.PotentialEnumOrValueType; + return false; + } + } + + private bool IsEnumOrValueType + { + get + { + return (typeFlags & (TypeFlags.EnumOrValueType | TypeFlags.PotentialEnumOrValueType)) != 0 + && ((typeFlags & TypeFlags.EnumOrValueType) != 0 || ResolvePotentialEnumOrValueType()); + } + } + + internal virtual Universe Universe + { + get { return Module.universe; } + } + + internal sealed override bool BindingFlagsMatch(BindingFlags flags) + { + return BindingFlagsMatch(IsNestedPublic, flags, BindingFlags.Public, BindingFlags.NonPublic); + } + + internal sealed override MemberInfo SetReflectedType(Type type) + { + throw new InvalidOperationException(); + } + + internal override int GetCurrentToken() + { + return this.MetadataToken; + } + + internal sealed override List GetPseudoCustomAttributes(Type attributeType) + { + // types don't have pseudo custom attributes + return null; + } + + // in .NET this is an extension method, but we target .NET 2.0, so we have an instance method + public TypeInfo GetTypeInfo() + { + TypeInfo type = this as TypeInfo; + if (type == null) + { + throw new MissingMemberException(this); + } + return type; + } + + public virtual bool __IsTypeForwarder + { + get { return false; } + } + + public virtual bool __IsCyclicTypeForwarder + { + get { return false; } + } + } + + abstract class ElementHolderType : TypeInfo + { + protected readonly Type elementType; + private int token; + private readonly CustomModifiers mods; + + protected ElementHolderType(Type elementType, CustomModifiers mods, byte sigElementType) + : base(sigElementType) + { + this.elementType = elementType; + this.mods = mods; + } + + protected bool EqualsHelper(ElementHolderType other) + { + return other != null + && other.elementType.Equals(elementType) + && other.mods.Equals(mods); + } + + public override CustomModifiers __GetCustomModifiers() + { + return mods; + } + + public sealed override string Name + { + get { return elementType.Name + GetSuffix(); } + } + + public sealed override string Namespace + { + get { return elementType.Namespace; } + } + + public sealed override string FullName + { + get { return elementType.FullName + GetSuffix(); } + } + + public sealed override string ToString() + { + return elementType.ToString() + GetSuffix(); + } + + public sealed override Type GetElementType() + { + return elementType; + } + + public sealed override Module Module + { + get { return elementType.Module; } + } + + internal sealed override int GetModuleBuilderToken() + { + if (token == 0) + { + token = ((ModuleBuilder)elementType.Module).ImportType(this); + } + return token; + } + + public sealed override bool ContainsGenericParameters + { + get + { + Type type = elementType; + while (type.HasElementType) + { + type = type.GetElementType(); + } + return type.ContainsGenericParameters; + } + } + + protected sealed override bool ContainsMissingTypeImpl + { + get + { + Type type = elementType; + while (type.HasElementType) + { + type = type.GetElementType(); + } + return type.__ContainsMissingType + || mods.ContainsMissingType; + } + } + + internal sealed override Type BindTypeParameters(IGenericBinder binder) + { + Type type = elementType.BindTypeParameters(binder); + CustomModifiers mods = this.mods.Bind(binder); + if (ReferenceEquals(type, elementType) + && mods.Equals(this.mods)) + { + return this; + } + return Wrap(type, mods); + } + + internal override void CheckBaked() + { + elementType.CheckBaked(); + } + + internal sealed override Universe Universe + { + get { return elementType.Universe; } + } + + internal sealed override bool IsBaked + { + get { return elementType.IsBaked; } + } + + internal sealed override int GetCurrentToken() + { + // we don't have a token, so we return 0 (which is never a valid token) + return 0; + } + + internal abstract string GetSuffix(); + + protected abstract Type Wrap(Type type, CustomModifiers mods); + } + + sealed class ArrayType : ElementHolderType + { + internal static Type Make(Type type, CustomModifiers mods) + { + return type.Universe.CanonicalizeType(new ArrayType(type, mods)); + } + + private ArrayType(Type type, CustomModifiers mods) + : base(type, mods, Signature.ELEMENT_TYPE_SZARRAY) + { + } + + public override Type BaseType + { + get { return elementType.Module.universe.System_Array; } + } + + public override Type[] __GetDeclaredInterfaces() + { + return new Type[] { + this.Module.universe.Import(typeof(IList<>)).MakeGenericType(elementType), + this.Module.universe.Import(typeof(ICollection<>)).MakeGenericType(elementType), + this.Module.universe.Import(typeof(IEnumerable<>)).MakeGenericType(elementType) + }; + } + + public override MethodBase[] __GetDeclaredMethods() + { + Type[] int32 = new Type[] { this.Module.universe.System_Int32 }; + List list = new List(); + list.Add(new BuiltinArrayMethod(this.Module, this, "Set", CallingConventions.Standard | CallingConventions.HasThis, this.Module.universe.System_Void, new Type[] { this.Module.universe.System_Int32, elementType })); + list.Add(new BuiltinArrayMethod(this.Module, this, "Address", CallingConventions.Standard | CallingConventions.HasThis, elementType.MakeByRefType(), int32)); + list.Add(new BuiltinArrayMethod(this.Module, this, "Get", CallingConventions.Standard | CallingConventions.HasThis, elementType, int32)); + list.Add(new ConstructorInfoImpl(new BuiltinArrayMethod(this.Module, this, ".ctor", CallingConventions.Standard | CallingConventions.HasThis, this.Module.universe.System_Void, int32))); + for (Type type = elementType; type.__IsVector; type = type.GetElementType()) + { + Array.Resize(ref int32, int32.Length + 1); + int32[int32.Length - 1] = int32[0]; + list.Add(new ConstructorInfoImpl(new BuiltinArrayMethod(this.Module, this, ".ctor", CallingConventions.Standard | CallingConventions.HasThis, this.Module.universe.System_Void, int32))); + } + return list.ToArray(); + } + + public override TypeAttributes Attributes + { + get { return TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Serializable; } + } + + public override int GetArrayRank() + { + return 1; + } + + public override bool Equals(object o) + { + return EqualsHelper(o as ArrayType); + } + + public override int GetHashCode() + { + return elementType.GetHashCode() * 5; + } + + internal override string GetSuffix() + { + return "[]"; + } + + protected override Type Wrap(Type type, CustomModifiers mods) + { + return Make(type, mods); + } + } + + sealed class MultiArrayType : ElementHolderType + { + private readonly int rank; + private readonly int[] sizes; + private readonly int[] lobounds; + + internal static Type Make(Type type, int rank, int[] sizes, int[] lobounds, CustomModifiers mods) + { + return type.Universe.CanonicalizeType(new MultiArrayType(type, rank, sizes, lobounds, mods)); + } + + private MultiArrayType(Type type, int rank, int[] sizes, int[] lobounds, CustomModifiers mods) + : base(type, mods, Signature.ELEMENT_TYPE_ARRAY) + { + this.rank = rank; + this.sizes = sizes; + this.lobounds = lobounds; + } + + public override Type BaseType + { + get { return elementType.Module.universe.System_Array; } + } + + public override MethodBase[] __GetDeclaredMethods() + { + Type int32 = this.Module.universe.System_Int32; + Type[] setArgs = new Type[rank + 1]; + Type[] getArgs = new Type[rank]; + Type[] ctorArgs = new Type[rank * 2]; + for (int i = 0; i < rank; i++) + { + setArgs[i] = int32; + getArgs[i] = int32; + ctorArgs[i * 2 + 0] = int32; + ctorArgs[i * 2 + 1] = int32; + } + setArgs[rank] = elementType; + return new MethodBase[] { + new ConstructorInfoImpl(new BuiltinArrayMethod(this.Module, this, ".ctor", CallingConventions.Standard | CallingConventions.HasThis, this.Module.universe.System_Void, getArgs)), + new ConstructorInfoImpl(new BuiltinArrayMethod(this.Module, this, ".ctor", CallingConventions.Standard | CallingConventions.HasThis, this.Module.universe.System_Void, ctorArgs)), + new BuiltinArrayMethod(this.Module, this, "Set", CallingConventions.Standard | CallingConventions.HasThis, this.Module.universe.System_Void, setArgs), + new BuiltinArrayMethod(this.Module, this, "Address", CallingConventions.Standard | CallingConventions.HasThis, elementType.MakeByRefType(), getArgs), + new BuiltinArrayMethod(this.Module, this, "Get", CallingConventions.Standard | CallingConventions.HasThis, elementType, getArgs), + }; + } + + public override TypeAttributes Attributes + { + get { return TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Serializable; } + } + + public override int GetArrayRank() + { + return rank; + } + + public override int[] __GetArraySizes() + { + return Util.Copy(sizes); + } + + public override int[] __GetArrayLowerBounds() + { + return Util.Copy(lobounds); + } + + public override bool Equals(object o) + { + MultiArrayType at = o as MultiArrayType; + return EqualsHelper(at) + && at.rank == rank + && ArrayEquals(at.sizes, sizes) + && ArrayEquals(at.lobounds, lobounds); + } + + private static bool ArrayEquals(int[] i1, int[] i2) + { + if (i1.Length == i2.Length) + { + for (int i = 0; i < i1.Length; i++) + { + if (i1[i] != i2[i]) + { + return false; + } + } + return true; + } + return false; + } + + public override int GetHashCode() + { + return elementType.GetHashCode() * 9 + rank; + } + + internal override string GetSuffix() + { + if (rank == 1) + { + return "[*]"; + } + else + { + return "[" + new String(',', rank - 1) + "]"; + } + } + + protected override Type Wrap(Type type, CustomModifiers mods) + { + return Make(type, rank, sizes, lobounds, mods); + } + } + + sealed class BuiltinArrayMethod : ArrayMethod + { + internal BuiltinArrayMethod(Module module, Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes) + : base(module, arrayClass, methodName, callingConvention, returnType, parameterTypes) + { + } + + public override MethodAttributes Attributes + { + get { return this.Name == ".ctor" ? MethodAttributes.RTSpecialName | MethodAttributes.Public : MethodAttributes.Public; } + } + + public override MethodImplAttributes GetMethodImplementationFlags() + { + return MethodImplAttributes.IL; + } + + public override int MetadataToken + { + get { return 0x06000000; } + } + + public override MethodBody GetMethodBody() + { + return null; + } + + public override ParameterInfo[] GetParameters() + { + ParameterInfo[] parameterInfos = new ParameterInfo[parameterTypes.Length]; + for (int i = 0; i < parameterInfos.Length; i++) + { + parameterInfos[i] = new ParameterInfoImpl(this, parameterTypes[i], i); + } + return parameterInfos; + } + + public override ParameterInfo ReturnParameter + { + get { return new ParameterInfoImpl(this, this.ReturnType, -1); } + } + + private sealed class ParameterInfoImpl : ParameterInfo + { + private readonly MethodInfo method; + private readonly Type type; + private readonly int pos; + + internal ParameterInfoImpl(MethodInfo method, Type type, int pos) + { + this.method = method; + this.type = type; + this.pos = pos; + } + + public override Type ParameterType + { + get { return type; } + } + + public override string Name + { + get { return null; } + } + + public override ParameterAttributes Attributes + { + get { return ParameterAttributes.None; } + } + + public override int Position + { + get { return pos; } + } + + public override object RawDefaultValue + { + get { return null; } + } + + public override CustomModifiers __GetCustomModifiers() + { + return new CustomModifiers(); + } + + public override bool __TryGetFieldMarshal(out FieldMarshal fieldMarshal) + { + fieldMarshal = new FieldMarshal(); + return false; + } + + public override MemberInfo Member + { + get { return method.IsConstructor ? (MethodBase)new ConstructorInfoImpl(method) : method; } + } + + public override int MetadataToken + { + get { return 0x08000000; } + } + + internal override Module Module + { + get { return method.Module; } + } + } + } + + sealed class ByRefType : ElementHolderType + { + internal static Type Make(Type type, CustomModifiers mods) + { + return type.Universe.CanonicalizeType(new ByRefType(type, mods)); + } + + private ByRefType(Type type, CustomModifiers mods) + : base(type, mods, Signature.ELEMENT_TYPE_BYREF) + { + } + + public override bool Equals(object o) + { + return EqualsHelper(o as ByRefType); + } + + public override int GetHashCode() + { + return elementType.GetHashCode() * 3; + } + + public override Type BaseType + { + get { return null; } + } + + public override TypeAttributes Attributes + { + get { return 0; } + } + + internal override string GetSuffix() + { + return "&"; + } + + protected override Type Wrap(Type type, CustomModifiers mods) + { + return Make(type, mods); + } + } + + sealed class PointerType : ElementHolderType + { + internal static Type Make(Type type, CustomModifiers mods) + { + return type.Universe.CanonicalizeType(new PointerType(type, mods)); + } + + private PointerType(Type type, CustomModifiers mods) + : base(type, mods, Signature.ELEMENT_TYPE_PTR) + { + } + + public override bool Equals(object o) + { + return EqualsHelper(o as PointerType); + } + + public override int GetHashCode() + { + return elementType.GetHashCode() * 7; + } + + public override Type BaseType + { + get { return null; } + } + + public override TypeAttributes Attributes + { + get { return 0; } + } + + internal override string GetSuffix() + { + return "*"; + } + + protected override Type Wrap(Type type, CustomModifiers mods) + { + return Make(type, mods); + } + } + + sealed class GenericTypeInstance : TypeInfo + { + private readonly Type type; + private readonly Type[] args; + private readonly CustomModifiers[] mods; + private Type baseType; + private int token; + + internal static Type Make(Type type, Type[] typeArguments, CustomModifiers[] mods) + { + bool identity = true; + if (type is TypeBuilder || type is BakedType || type.__IsMissing) + { + // a TypeBuiler identity must be instantiated + identity = false; + } + else + { + // we must not instantiate the identity instance, because typeof(Foo<>).MakeGenericType(typeof(Foo<>).GetGenericArguments()) == typeof(Foo<>) + for (int i = 0; i < typeArguments.Length; i++) + { + if (typeArguments[i] != type.GetGenericTypeArgument(i) + || !IsEmpty(mods, i)) + { + identity = false; + break; + } + } + } + if (identity) + { + return type; + } + else + { + return type.Universe.CanonicalizeType(new GenericTypeInstance(type, typeArguments, mods)); + } + } + + private static bool IsEmpty(CustomModifiers[] mods, int i) + { + // we need to be extra careful, because mods doesn't not need to be in canonical format + // (Signature.ReadGenericInst() calls Make() directly, without copying the modifier arrays) + return mods == null || mods[i].IsEmpty; + } + + private GenericTypeInstance(Type type, Type[] args, CustomModifiers[] mods) + { + this.type = type; + this.args = args; + this.mods = mods; + } + + public override bool Equals(object o) + { + GenericTypeInstance gt = o as GenericTypeInstance; + return gt != null && gt.type.Equals(type) && Util.ArrayEquals(gt.args, args) + && Util.ArrayEquals(gt.mods, mods); + } + + public override int GetHashCode() + { + return type.GetHashCode() * 3 ^ Util.GetHashCode(args); + } + + public override string AssemblyQualifiedName + { + get + { + string fn = FullName; + return fn == null ? null : fn + ", " + type.Assembly.FullName; + } + } + + public override Type BaseType + { + get + { + if (baseType == null) + { + Type rawBaseType = type.BaseType; + if (rawBaseType == null) + { + baseType = rawBaseType; + } + else + { + baseType = rawBaseType.BindTypeParameters(this); + } + } + return baseType; + } + } + + public override bool IsValueType + { + get { return type.IsValueType; } + } + + public override bool IsVisible + { + get + { + if (base.IsVisible) + { + foreach (Type arg in args) + { + if (!arg.IsVisible) + { + return false; + } + } + return true; + } + return false; + } + } + + public override Type DeclaringType + { + get { return type.DeclaringType; } + } + + public override TypeAttributes Attributes + { + get { return type.Attributes; } + } + + internal override void CheckBaked() + { + type.CheckBaked(); + } + + public override FieldInfo[] __GetDeclaredFields() + { + FieldInfo[] fields = type.__GetDeclaredFields(); + for (int i = 0; i < fields.Length; i++) + { + fields[i] = fields[i].BindTypeParameters(this); + } + return fields; + } + + public override Type[] __GetDeclaredInterfaces() + { + Type[] interfaces = type.__GetDeclaredInterfaces(); + for (int i = 0; i < interfaces.Length; i++) + { + interfaces[i] = interfaces[i].BindTypeParameters(this); + } + return interfaces; + } + + public override MethodBase[] __GetDeclaredMethods() + { + MethodBase[] methods = type.__GetDeclaredMethods(); + for (int i = 0; i < methods.Length; i++) + { + methods[i] = methods[i].BindTypeParameters(this); + } + return methods; + } + + public override Type[] __GetDeclaredTypes() + { + return type.__GetDeclaredTypes(); + } + + public override EventInfo[] __GetDeclaredEvents() + { + EventInfo[] events = type.__GetDeclaredEvents(); + for (int i = 0; i < events.Length; i++) + { + events[i] = events[i].BindTypeParameters(this); + } + return events; + } + + public override PropertyInfo[] __GetDeclaredProperties() + { + PropertyInfo[] properties = type.__GetDeclaredProperties(); + for (int i = 0; i < properties.Length; i++) + { + properties[i] = properties[i].BindTypeParameters(this); + } + return properties; + } + + public override __MethodImplMap __GetMethodImplMap() + { + __MethodImplMap map = type.__GetMethodImplMap(); + map.TargetType = this; + for (int i = 0; i < map.MethodBodies.Length; i++) + { + map.MethodBodies[i] = (MethodInfo)map.MethodBodies[i].BindTypeParameters(this); + for (int j = 0; j < map.MethodDeclarations[i].Length; j++) + { + Type interfaceType = map.MethodDeclarations[i][j].DeclaringType; + if (interfaceType.IsGenericType) + { + map.MethodDeclarations[i][j] = (MethodInfo)map.MethodDeclarations[i][j].BindTypeParameters(this); + } + } + } + return map; + } + + public override string Namespace + { + get { return type.Namespace; } + } + + public override string Name + { + get { return type.Name; } + } + + public override string FullName + { + get + { + if (!this.__ContainsMissingType && this.ContainsGenericParameters) + { + return null; + } + StringBuilder sb = new StringBuilder(this.type.FullName); + sb.Append('['); + string sep = ""; + foreach (Type type in args) + { + sb.Append(sep).Append('[').Append(type.FullName).Append(", ").Append(type.Assembly.FullName.Replace("]", "\\]")).Append(']'); + sep = ","; + } + sb.Append(']'); + return sb.ToString(); + } + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(type.FullName); + sb.Append('['); + string sep = ""; + foreach (Type arg in args) + { + sb.Append(sep); + sb.Append(arg); + sep = ","; + } + sb.Append(']'); + return sb.ToString(); + } + + public override Module Module + { + get { return type.Module; } + } + + public override bool IsGenericType + { + get { return true; } + } + + public override bool IsConstructedGenericType + { + get { return true; } + } + + public override Type GetGenericTypeDefinition() + { + return type; + } + + public override Type[] GetGenericArguments() + { + return Util.Copy(args); + } + + public override CustomModifiers[] __GetGenericArgumentsCustomModifiers() + { + return mods != null ? (CustomModifiers[])mods.Clone() : new CustomModifiers[args.Length]; + } + + internal override Type GetGenericTypeArgument(int index) + { + return args[index]; + } + + public override bool ContainsGenericParameters + { + get + { + foreach (Type type in args) + { + if (type.ContainsGenericParameters) + { + return true; + } + } + return false; + } + } + + protected override bool ContainsMissingTypeImpl + { + get { return type.__ContainsMissingType || ContainsMissingType(args); } + } + + public override bool __GetLayout(out int packingSize, out int typeSize) + { + return type.__GetLayout(out packingSize, out typeSize); + } + + internal override int GetModuleBuilderToken() + { + if (token == 0) + { + token = ((ModuleBuilder)type.Module).ImportType(this); + } + return token; + } + + internal override Type BindTypeParameters(IGenericBinder binder) + { + for (int i = 0; i < args.Length; i++) + { + Type xarg = args[i].BindTypeParameters(binder); + if (!ReferenceEquals(xarg, args[i])) + { + Type[] xargs = new Type[args.Length]; + Array.Copy(args, xargs, i); + xargs[i++] = xarg; + for (; i < args.Length; i++) + { + xargs[i] = args[i].BindTypeParameters(binder); + } + return Make(type, xargs, null); + } + } + return this; + } + + internal override int GetCurrentToken() + { + return type.GetCurrentToken(); + } + + internal override bool IsBaked + { + get { return type.IsBaked; } + } + } + + sealed class FunctionPointerType : TypeInfo + { + private readonly Universe universe; + private readonly __StandAloneMethodSig sig; + + internal static Type Make(Universe universe, __StandAloneMethodSig sig) + { + return universe.CanonicalizeType(new FunctionPointerType(universe, sig)); + } + + private FunctionPointerType(Universe universe, __StandAloneMethodSig sig) + : base(Signature.ELEMENT_TYPE_FNPTR) + { + this.universe = universe; + this.sig = sig; + } + + public override bool Equals(object obj) + { + FunctionPointerType other = obj as FunctionPointerType; + return other != null + && other.universe == universe + && other.sig.Equals(sig); + } + + public override int GetHashCode() + { + return sig.GetHashCode(); + } + + public override __StandAloneMethodSig __MethodSignature + { + get { return sig; } + } + + public override Type BaseType + { + get { return null; } + } + + public override TypeAttributes Attributes + { + get { return 0; } + } + + public override string Name + { + get { throw new InvalidOperationException(); } + } + + public override string FullName + { + get { throw new InvalidOperationException(); } + } + + public override Module Module + { + get { throw new InvalidOperationException(); } + } + + internal override Universe Universe + { + get { return universe; } + } + + public override string ToString() + { + return ""; + } + + protected override bool ContainsMissingTypeImpl + { + get { return sig.ContainsMissingType; } + } + + internal override bool IsBaked + { + get { return true; } + } + } + + sealed class MarkerType : Type + { + // used by CustomModifiers and SignatureHelper + internal static readonly Type ModOpt = new MarkerType(Signature.ELEMENT_TYPE_CMOD_OPT); + internal static readonly Type ModReq = new MarkerType(Signature.ELEMENT_TYPE_CMOD_REQD); + // used by SignatureHelper + internal static readonly Type Sentinel = new MarkerType(Signature.SENTINEL); + internal static readonly Type Pinned = new MarkerType(Signature.ELEMENT_TYPE_PINNED); + + private MarkerType(byte sigElementType) + : base(sigElementType) + { + } + + public override Type BaseType + { + get { throw new InvalidOperationException(); } + } + + public override TypeAttributes Attributes + { + get { throw new InvalidOperationException(); } + } + + public override string Name + { + get { throw new InvalidOperationException(); } + } + + public override string FullName + { + get { throw new InvalidOperationException(); } + } + + public override Module Module + { + get { throw new InvalidOperationException(); } + } + + internal override bool IsBaked + { + get { throw new InvalidOperationException(); } + } + + public override bool __IsMissing + { + get { return false; } + } + } +} diff --git a/reflect/TypeInfo.cs b/reflect/TypeInfo.cs new file mode 100644 index 0000000..e0c6b70 --- /dev/null +++ b/reflect/TypeInfo.cs @@ -0,0 +1,163 @@ +/* + Copyright (C) 2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; + +namespace IKVM.Reflection +{ + public interface IReflectableType + { + TypeInfo GetTypeInfo(); + } + + public static class IntrospectionExtensions + { + // we target .NET 2.0 so we can't define an extension method + public static TypeInfo GetTypeInfo(/*this*/ Type type) + { + return type.GetTypeInfo(); + } + } + + public abstract class TypeInfo : Type, IReflectableType + { + private const BindingFlags Flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static; + + internal TypeInfo() + { + } + + internal TypeInfo(Type underlyingType) + : base(underlyingType) + { + } + + internal TypeInfo(byte sigElementType) + : base(sigElementType) + { + } + + public IEnumerable DeclaredConstructors + { + get { return GetConstructors(Flags); } + } + + public IEnumerable DeclaredEvents + { + get { return GetEvents(Flags); } + } + + public IEnumerable DeclaredFields + { + get { return GetFields(Flags); } + } + + public IEnumerable DeclaredMembers + { + get { return GetMembers(Flags); } + } + + public IEnumerable DeclaredMethods + { + get { return GetMethods(Flags); } + } + + public IEnumerable DeclaredNestedTypes + { + get + { + Type[] types = GetNestedTypes(Flags); + TypeInfo[] typeInfos = new TypeInfo[types.Length]; + for (int i = 0; i < types.Length; i++) + { + typeInfos[i] = types[i].GetTypeInfo(); + } + return typeInfos; + } + } + + public IEnumerable DeclaredProperties + { + get { return GetProperties(Flags); } + } + + public Type[] GenericTypeParameters + { + get { return IsGenericTypeDefinition ? GetGenericArguments() : Type.EmptyTypes; } + } + + public IEnumerable ImplementedInterfaces + { + get { return __GetDeclaredInterfaces(); } + } + + public Type AsType() + { + return this; + } + + public EventInfo GetDeclaredEvent(string name) + { + return GetEvent(name, Flags); + } + + public FieldInfo GetDeclaredField(string name) + { + return GetField(name, Flags); + } + + public MethodInfo GetDeclaredMethod(string name) + { + return GetMethod(name, Flags); + } + + public IEnumerable GetDeclaredMethods(string name) + { + List methods = new List(); + foreach (MethodInfo method in GetMethods(Flags)) + { + if (method.Name == name) + { + methods.Add(method); + } + } + return methods; + } + + public TypeInfo GetDeclaredNestedType(string name) + { + return GetNestedType(name, Flags).GetTypeInfo(); + } + + public PropertyInfo GetDeclaredProperty(string name) + { + return GetProperty(name, Flags); + } + + public bool IsAssignableFrom(TypeInfo typeInfo) + { + return base.IsAssignableFrom(typeInfo); + } + } +} diff --git a/reflect/TypeNameParser.cs b/reflect/TypeNameParser.cs new file mode 100644 index 0000000..1d31952 --- /dev/null +++ b/reflect/TypeNameParser.cs @@ -0,0 +1,625 @@ +/* + Copyright (C) 2009-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; + +namespace IKVM.Reflection +{ + // this respresents a type name as in metadata: + // - ns will be null for empty the namespace (never the empty string) + // - the strings are not escaped + struct TypeName : IEquatable + { + private readonly string ns; + private readonly string name; + + internal TypeName(string ns, string name) + { + if (name == null) + { + throw new ArgumentNullException("name"); + } + this.ns = ns; + this.name = name; + } + + internal string Name + { + get { return name; } + } + + internal string Namespace + { + get { return ns; } + } + + public static bool operator ==(TypeName o1, TypeName o2) + { + return o1.ns == o2.ns && o1.name == o2.name; + } + + public static bool operator !=(TypeName o1, TypeName o2) + { + return o1.ns != o2.ns || o1.name != o2.name; + } + + public override int GetHashCode() + { + return ns == null ? name.GetHashCode() : ns.GetHashCode() * 37 + name.GetHashCode(); + } + + public override bool Equals(object obj) + { + TypeName? other = obj as TypeName?; + return other != null && other.Value == this; + } + + public override string ToString() + { + return ns == null ? name : ns + "." + name; + } + + bool IEquatable.Equals(TypeName other) + { + return this == other; + } + + internal bool Matches(string fullName) + { + if (ns == null) + { + return name == fullName; + } + if (ns.Length + 1 + name.Length == fullName.Length) + { + return fullName.StartsWith(ns, StringComparison.Ordinal) + && fullName[ns.Length] == '.' + && fullName.EndsWith(name, StringComparison.Ordinal); + } + return false; + } + + internal TypeName ToLowerInvariant() + { + return new TypeName(ns == null ? null : ns.ToLowerInvariant(), name.ToLowerInvariant()); + } + + internal static TypeName Split(string name) + { + int dot = name.LastIndexOf('.'); + if (dot == -1) + { + return new TypeName(null, name); + } + else + { + return new TypeName(name.Substring(0, dot), name.Substring(dot + 1)); + } + } + } + + struct TypeNameParser + { + private const string SpecialChars = "\\+,[]*&"; + private const short SZARRAY = -1; + private const short BYREF = -2; + private const short POINTER = -3; + private readonly string name; + private readonly string[] nested; + private readonly string assemblyName; + private readonly short[] modifiers; + private readonly TypeNameParser[] genericParameters; + + internal static string Escape(string name) + { + if (name == null) + { + return null; + } + StringBuilder sb = null; + for (int pos = 0; pos < name.Length; pos++) + { + char c = name[pos]; + switch (c) + { + case '\\': + case '+': + case ',': + case '[': + case ']': + case '*': + case '&': + if (sb == null) + { + sb = new StringBuilder(name, 0, pos, name.Length + 3); + } + sb.Append("\\").Append(c); + break; + default: + if (sb != null) + { + sb.Append(c); + } + break; + } + } + return sb != null ? sb.ToString() : name; + } + + internal static string Unescape(string name) + { + int pos = name.IndexOf('\\'); + if (pos == -1) + { + return name; + } + StringBuilder sb = new StringBuilder(name, 0, pos, name.Length - 1); + for (; pos < name.Length; pos++) + { + char c = name[pos]; + if (c == '\\') + { + c = name[++pos]; + } + sb.Append(c); + } + return sb.ToString(); + } + + internal static TypeNameParser Parse(string typeName, bool throwOnError) + { + if (throwOnError) + { + Parser parser = new Parser(typeName); + return new TypeNameParser(ref parser, true); + } + else + { + try + { + Parser parser = new Parser(typeName); + return new TypeNameParser(ref parser, true); + } + catch (ArgumentException) + { + return new TypeNameParser(); + } + } + } + + private TypeNameParser(ref Parser parser, bool withAssemblyName) + { + bool genericParameter = parser.pos != 0; + name = parser.NextNamePart(); + nested = null; + parser.ParseNested(ref nested); + genericParameters = null; + parser.ParseGenericParameters(ref genericParameters); + modifiers = null; + parser.ParseModifiers(ref modifiers); + assemblyName = null; + if (withAssemblyName) + { + parser.ParseAssemblyName(genericParameter, ref assemblyName); + } + } + + internal bool Error + { + get { return name == null; } + } + + internal string FirstNamePart + { + get { return name; } + } + + internal string AssemblyName + { + get { return assemblyName; } + } + + private struct Parser + { + private readonly string typeName; + internal int pos; + + internal Parser(string typeName) + { + this.typeName = typeName; + this.pos = 0; + } + + private void Check(bool condition) + { + if (!condition) + { + throw new ArgumentException("Invalid type name '" + typeName + "'"); + } + } + + private void Consume(char c) + { + Check(pos < typeName.Length && typeName[pos++] == c); + } + + private bool TryConsume(char c) + { + if (pos < typeName.Length && typeName[pos] == c) + { + pos++; + return true; + } + else + { + return false; + } + } + + internal string NextNamePart() + { + SkipWhiteSpace(); + int start = pos; + for (; pos < typeName.Length; pos++) + { + char c = typeName[pos]; + if (c == '\\') + { + pos++; + Check(pos < typeName.Length && SpecialChars.IndexOf(typeName[pos]) != -1); + } + else if (SpecialChars.IndexOf(c) != -1) + { + break; + } + } + Check(pos - start != 0); + if (start == 0 && pos == typeName.Length) + { + return typeName; + } + else + { + return typeName.Substring(start, pos - start); + } + } + + internal void ParseNested(ref string[] nested) + { + while (TryConsume('+')) + { + Add(ref nested, NextNamePart()); + } + } + + internal void ParseGenericParameters(ref TypeNameParser[] genericParameters) + { + int saved = pos; + if (TryConsume('[')) + { + SkipWhiteSpace(); + if (TryConsume(']') || TryConsume('*') || TryConsume(',')) + { + // it's not a generic parameter list, but an array instead + pos = saved; + return; + } + do + { + SkipWhiteSpace(); + if (TryConsume('[')) + { + Add(ref genericParameters, new TypeNameParser(ref this, true)); + Consume(']'); + } + else + { + Add(ref genericParameters, new TypeNameParser(ref this, false)); + } + } + while (TryConsume(',')); + Consume(']'); + SkipWhiteSpace(); + } + } + + internal void ParseModifiers(ref short[] modifiers) + { + while (pos < typeName.Length) + { + switch (typeName[pos]) + { + case '*': + pos++; + Add(ref modifiers, POINTER); + break; + case '&': + pos++; + Add(ref modifiers, BYREF); + break; + case '[': + pos++; + Add(ref modifiers, ParseArray()); + Consume(']'); + break; + default: + return; + } + SkipWhiteSpace(); + } + } + + internal void ParseAssemblyName(bool genericParameter, ref string assemblyName) + { + if (pos < typeName.Length) + { + if (typeName[pos] == ']' && genericParameter) + { + // ok + } + else + { + Consume(','); + SkipWhiteSpace(); + if (genericParameter) + { + int start = pos; + while (pos < typeName.Length) + { + char c = typeName[pos]; + if (c == '\\') + { + pos++; + // a backslash itself is not legal in an assembly name, so we don't need to check for an escaped backslash + Check(pos < typeName.Length && typeName[pos++] == ']'); + } + else if (c == ']') + { + break; + } + else + { + pos++; + } + } + Check(pos < typeName.Length && typeName[pos] == ']'); + assemblyName = typeName.Substring(start, pos - start).Replace("\\]", "]"); + } + else + { + // only when an assembly name is used in a generic type parameter, will it be escaped + assemblyName = typeName.Substring(pos); + } + Check(assemblyName.Length != 0); + } + } + else + { + Check(!genericParameter); + } + } + + private short ParseArray() + { + SkipWhiteSpace(); + Check(pos < typeName.Length); + char c = typeName[pos]; + if (c == ']') + { + return SZARRAY; + } + else if (c == '*') + { + pos++; + SkipWhiteSpace(); + return 1; + } + else + { + short rank = 1; + while (TryConsume(',')) + { + Check(rank < short.MaxValue); + rank++; + SkipWhiteSpace(); + } + return rank; + } + } + + private void SkipWhiteSpace() + { + while (pos < typeName.Length && Char.IsWhiteSpace(typeName[pos])) + { + pos++; + } + } + + private static void Add(ref T[] array, T elem) + { + if (array == null) + { + array = new T[] { elem }; + return; + } + Array.Resize(ref array, array.Length + 1); + array[array.Length - 1] = elem; + } + } + + internal Type GetType(Universe universe, Module context, bool throwOnError, string originalName, bool resolve, bool ignoreCase) + { + Debug.Assert(!resolve || !ignoreCase); + TypeName name = TypeName.Split(this.name); + Type type; + if (assemblyName != null) + { + Assembly asm = universe.Load(assemblyName, context, throwOnError); + if (asm == null) + { + return null; + } + if (resolve) + { + type = asm.ResolveType(context, name); + } + else if (ignoreCase) + { + type = asm.FindTypeIgnoreCase(name.ToLowerInvariant()); + } + else + { + type = asm.FindType(name); + } + } + else if (context == null) + { + if (resolve) + { + type = universe.Mscorlib.ResolveType(context, name); + } + else if (ignoreCase) + { + type = universe.Mscorlib.FindTypeIgnoreCase(name.ToLowerInvariant()); + } + else + { + type = universe.Mscorlib.FindType(name); + } + } + else + { + if (ignoreCase) + { + name = name.ToLowerInvariant(); + type = context.FindTypeIgnoreCase(name); + } + else + { + type = context.FindType(name); + } + if (type == null && context != universe.Mscorlib.ManifestModule) + { + if (ignoreCase) + { + type = universe.Mscorlib.FindTypeIgnoreCase(name); + } + else + { + type = universe.Mscorlib.FindType(name); + } + } + if (type == null && resolve) + { + if (universe.Mscorlib.__IsMissing && !context.__IsMissing) + { + type = universe.Mscorlib.ResolveType(context, name); + } + else + { + type = context.Assembly.ResolveType(context, name); + } + } + } + return Expand(type, context, throwOnError, originalName, resolve, ignoreCase); + } + + internal Type Expand(Type type, Module context, bool throwOnError, string originalName, bool resolve, bool ignoreCase) + { + Debug.Assert(!resolve || !ignoreCase); + if (type == null) + { + if (throwOnError) + { + throw new TypeLoadException(originalName); + } + return null; + } + if (nested != null) + { + Type outer; + foreach (string nest in nested) + { + outer = type; + TypeName name = TypeName.Split(TypeNameParser.Unescape(nest)); + type = ignoreCase + ? outer.FindNestedTypeIgnoreCase(name.ToLowerInvariant()) + : outer.FindNestedType(name); + if (type == null) + { + if (resolve) + { + type = outer.Module.universe.GetMissingTypeOrThrow(context, outer.Module, outer, name); + } + else if (throwOnError) + { + throw new TypeLoadException(originalName); + } + else + { + return null; + } + } + } + } + if (genericParameters != null) + { + Type[] typeArgs = new Type[genericParameters.Length]; + for (int i = 0; i < typeArgs.Length; i++) + { + typeArgs[i] = genericParameters[i].GetType(type.Assembly.universe, context, throwOnError, originalName, resolve, ignoreCase); + if (typeArgs[i] == null) + { + return null; + } + } + type = type.MakeGenericType(typeArgs); + } + if (modifiers != null) + { + foreach (short modifier in modifiers) + { + switch (modifier) + { + case SZARRAY: + type = type.MakeArrayType(); + break; + case BYREF: + type = type.MakeByRefType(); + break; + case POINTER: + type = type.MakePointerType(); + break; + default: + type = type.MakeArrayType(modifier); + break; + } + } + } + return type; + } + } +} diff --git a/reflect/Universe.cs b/reflect/Universe.cs new file mode 100644 index 0000000..c34e0c9 --- /dev/null +++ b/reflect/Universe.cs @@ -0,0 +1,1249 @@ +/* + Copyright (C) 2009-2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.IO; +using System.Security; +using System.Text; +using System.Diagnostics; +using IKVM.Reflection.Reader; +using IKVM.Reflection.Emit; + +namespace IKVM.Reflection +{ + public sealed class ResolveEventArgs : EventArgs + { + private readonly string name; + private readonly Assembly requestingAssembly; + + public ResolveEventArgs(string name) + : this(name, null) + { + } + + public ResolveEventArgs(string name, Assembly requestingAssembly) + { + this.name = name; + this.requestingAssembly = requestingAssembly; + } + + public string Name + { + get { return name; } + } + + public Assembly RequestingAssembly + { + get { return requestingAssembly; } + } + } + + public enum AssemblyComparisonResult + { + Unknown = 0, + EquivalentFullMatch = 1, + EquivalentWeakNamed = 2, + EquivalentFXUnified = 3, + EquivalentUnified = 4, + NonEquivalentVersion = 5, + NonEquivalent = 6, + EquivalentPartialMatch = 7, + EquivalentPartialWeakNamed = 8, + EquivalentPartialUnified = 9, + EquivalentPartialFXUnified = 10, + NonEquivalentPartialVersion = 11, + } + + public delegate Assembly ResolveEventHandler(object sender, ResolveEventArgs args); + + public delegate void ResolvedMissingMemberHandler(Module requestingModule, MemberInfo member); + + /* + * UniverseOptions: + * + * None + * Default behavior, most compatible with System.Reflection[.Emit] + * + * EnableFunctionPointers + * Normally function pointers in signatures are replaced by System.IntPtr + * (for compatibility with System.Reflection), when this option is enabled + * they are represented as first class types (Type.__IsFunctionPointer will + * return true for them). + * + * DisableFusion + * Don't use native Fusion API to resolve assembly names. + * + * DisablePseudoCustomAttributeRetrieval + * Set this option to disable the generaton of pseudo-custom attributes + * when querying custom attributes. + * + * DontProvideAutomaticDefaultConstructor + * Normally TypeBuilder, like System.Reflection.Emit, will provide a default + * constructor for types that meet the requirements. By enabling this + * option this behavior is disabled. + * + * MetadataOnly + * By default, when a module is read in, the stream is kept open to satisfy + * subsequent lazy loading. In MetadataOnly mode only the metadata is read in + * and after that the stream is closed immediately. Subsequent lazy loading + * attempts will fail with an InvalidOperationException. + * APIs that are not available is MetadataOnly mode are: + * - Module.ResolveString() + * - Module.GetSignerCertificate() + * - Module.GetManifestResourceStream() + * - Module.__ReadDataFromRVA() + * - MethodBase.GetMethodBody() + * - FieldInfo.__GetDataFromRVA() + * + * DeterministicOutput + * The generated output file will depend only on the input. In other words, + * the PE file header time stamp will be set to zero and the module version + * id will be based on a SHA1 of the contents, instead of a random guid. + * This option can not be used in combination with PDB file generation. + */ + + [Flags] + public enum UniverseOptions + { + None = 0, + EnableFunctionPointers = 1, + DisableFusion = 2, + DisablePseudoCustomAttributeRetrieval = 4, + DontProvideAutomaticDefaultConstructor = 8, + MetadataOnly = 16, + ResolveMissingMembers = 32, + DisableWindowsRuntimeProjection = 64, + DecodeVersionInfoAttributeBlobs = 128, + DeterministicOutput = 256, + } + + public sealed class Universe : IDisposable + { + internal static readonly bool MonoRuntime = System.Type.GetType("Mono.Runtime") != null; + private readonly Dictionary canonicalizedTypes = new Dictionary(); + private readonly List assemblies = new List(); + private readonly List dynamicAssemblies = new List(); + private readonly Dictionary assembliesByName = new Dictionary(); + private readonly Dictionary importedTypes = new Dictionary(); + private Dictionary missingTypes; + private bool resolveMissingMembers; + private readonly bool enableFunctionPointers; + private readonly bool useNativeFusion; + private readonly bool returnPseudoCustomAttributes; + private readonly bool automaticallyProvideDefaultConstructor; + private readonly UniverseOptions options; + private Type typeof_System_Object; + private Type typeof_System_ValueType; + private Type typeof_System_Enum; + private Type typeof_System_Void; + private Type typeof_System_Boolean; + private Type typeof_System_Char; + private Type typeof_System_SByte; + private Type typeof_System_Byte; + private Type typeof_System_Int16; + private Type typeof_System_UInt16; + private Type typeof_System_Int32; + private Type typeof_System_UInt32; + private Type typeof_System_Int64; + private Type typeof_System_UInt64; + private Type typeof_System_Single; + private Type typeof_System_Double; + private Type typeof_System_String; + private Type typeof_System_IntPtr; + private Type typeof_System_UIntPtr; + private Type typeof_System_TypedReference; + private Type typeof_System_Type; + private Type typeof_System_Array; + private Type typeof_System_DateTime; + private Type typeof_System_DBNull; + private Type typeof_System_Decimal; + private Type typeof_System_AttributeUsageAttribute; + private Type typeof_System_Runtime_InteropServices_DllImportAttribute; + private Type typeof_System_Runtime_InteropServices_FieldOffsetAttribute; + private Type typeof_System_Runtime_InteropServices_MarshalAsAttribute; + private Type typeof_System_Runtime_InteropServices_UnmanagedType; + private Type typeof_System_Runtime_InteropServices_VarEnum; + private Type typeof_System_Runtime_InteropServices_PreserveSigAttribute; + private Type typeof_System_Runtime_InteropServices_CallingConvention; + private Type typeof_System_Runtime_InteropServices_CharSet; + private Type typeof_System_Runtime_CompilerServices_DecimalConstantAttribute; + private Type typeof_System_Reflection_AssemblyCopyrightAttribute; + private Type typeof_System_Reflection_AssemblyTrademarkAttribute; + private Type typeof_System_Reflection_AssemblyProductAttribute; + private Type typeof_System_Reflection_AssemblyCompanyAttribute; + private Type typeof_System_Reflection_AssemblyDescriptionAttribute; + private Type typeof_System_Reflection_AssemblyTitleAttribute; + private Type typeof_System_Reflection_AssemblyInformationalVersionAttribute; + private Type typeof_System_Reflection_AssemblyFileVersionAttribute; + private Type typeof_System_Security_Permissions_CodeAccessSecurityAttribute; + private Type typeof_System_Security_Permissions_PermissionSetAttribute; + private Type typeof_System_Security_Permissions_SecurityAction; + private List resolvers = new List(); + private Predicate missingTypeIsValueType; + + public Universe() + : this(UniverseOptions.None) + { + } + + public Universe(UniverseOptions options) + { + this.options = options; + enableFunctionPointers = (options & UniverseOptions.EnableFunctionPointers) != 0; + useNativeFusion = (options & UniverseOptions.DisableFusion) == 0 && GetUseNativeFusion(); + returnPseudoCustomAttributes = (options & UniverseOptions.DisablePseudoCustomAttributeRetrieval) == 0; + automaticallyProvideDefaultConstructor = (options & UniverseOptions.DontProvideAutomaticDefaultConstructor) == 0; + resolveMissingMembers = (options & UniverseOptions.ResolveMissingMembers) != 0; + } + + private static bool GetUseNativeFusion() + { + try + { + return Environment.OSVersion.Platform == PlatformID.Win32NT + && !MonoRuntime + && Environment.GetEnvironmentVariable("IKVM_DISABLE_FUSION") == null; + } + catch (System.Security.SecurityException) + { + return false; + } + } + + internal Assembly Mscorlib + { + get { return Load("mscorlib"); } + } + + private Type ImportMscorlibType(string ns, string name) + { + if (Mscorlib.__IsMissing) + { + return Mscorlib.ResolveType(null, new TypeName(ns, name)); + } + // We use FindType instead of ResolveType here, because on some versions of mscorlib some of + // the special types we use/support are missing and the type properties are defined to + // return null in that case. + // Note that we don't have to unescape type.Name here, because none of the names contain special characters. + return Mscorlib.FindType(new TypeName(ns, name)); + } + + private Type ResolvePrimitive(string name) + { + // Primitive here means that these types have a special metadata encoding, which means that + // there can be references to them without referring to them by name explicitly. + // We want these types to be usable even when they don't exist in mscorlib or there is no mscorlib loaded. + return Mscorlib.FindType(new TypeName("System", name)) ?? GetMissingType(null, Mscorlib.ManifestModule, null, new TypeName("System", name)); + } + + internal Type System_Object + { + get { return typeof_System_Object ?? (typeof_System_Object = ResolvePrimitive("Object")); } + } + + internal Type System_ValueType + { + // System.ValueType is not a primitive, but generic type parameters can have a ValueType constraint + // (we also don't want to return null here) + get { return typeof_System_ValueType ?? (typeof_System_ValueType = ResolvePrimitive("ValueType")); } + } + + internal Type System_Enum + { + // System.Enum is not a primitive, but we don't want to return null + get { return typeof_System_Enum ?? (typeof_System_Enum = ResolvePrimitive("Enum")); } + } + + internal Type System_Void + { + get { return typeof_System_Void ?? (typeof_System_Void = ResolvePrimitive("Void")); } + } + + internal Type System_Boolean + { + get { return typeof_System_Boolean ?? (typeof_System_Boolean = ResolvePrimitive("Boolean")); } + } + + internal Type System_Char + { + get { return typeof_System_Char ?? (typeof_System_Char = ResolvePrimitive("Char")); } + } + + internal Type System_SByte + { + get { return typeof_System_SByte ?? (typeof_System_SByte = ResolvePrimitive("SByte")); } + } + + internal Type System_Byte + { + get { return typeof_System_Byte ?? (typeof_System_Byte = ResolvePrimitive("Byte")); } + } + + internal Type System_Int16 + { + get { return typeof_System_Int16 ?? (typeof_System_Int16 = ResolvePrimitive("Int16")); } + } + + internal Type System_UInt16 + { + get { return typeof_System_UInt16 ?? (typeof_System_UInt16 = ResolvePrimitive("UInt16")); } + } + + internal Type System_Int32 + { + get { return typeof_System_Int32 ?? (typeof_System_Int32 = ResolvePrimitive("Int32")); } + } + + internal Type System_UInt32 + { + get { return typeof_System_UInt32 ?? (typeof_System_UInt32 = ResolvePrimitive("UInt32")); } + } + + internal Type System_Int64 + { + get { return typeof_System_Int64 ?? (typeof_System_Int64 = ResolvePrimitive("Int64")); } + } + + internal Type System_UInt64 + { + get { return typeof_System_UInt64 ?? (typeof_System_UInt64 = ResolvePrimitive("UInt64")); } + } + + internal Type System_Single + { + get { return typeof_System_Single ?? (typeof_System_Single = ResolvePrimitive("Single")); } + } + + internal Type System_Double + { + get { return typeof_System_Double ?? (typeof_System_Double = ResolvePrimitive("Double")); } + } + + internal Type System_String + { + get { return typeof_System_String ?? (typeof_System_String = ResolvePrimitive("String")); } + } + + internal Type System_IntPtr + { + get { return typeof_System_IntPtr ?? (typeof_System_IntPtr = ResolvePrimitive("IntPtr")); } + } + + internal Type System_UIntPtr + { + get { return typeof_System_UIntPtr ?? (typeof_System_UIntPtr = ResolvePrimitive("UIntPtr")); } + } + + internal Type System_TypedReference + { + get { return typeof_System_TypedReference ?? (typeof_System_TypedReference = ResolvePrimitive("TypedReference")); } + } + + internal Type System_Type + { + // System.Type is not a primitive, but it does have a special encoding in custom attributes + get { return typeof_System_Type ?? (typeof_System_Type = ResolvePrimitive("Type")); } + } + + internal Type System_Array + { + // System.Array is not a primitive, but it used as a base type for array types (that are primitives) + get { return typeof_System_Array ?? (typeof_System_Array = ResolvePrimitive("Array")); } + } + + internal Type System_DateTime + { + get { return typeof_System_DateTime ?? (typeof_System_DateTime = ImportMscorlibType("System", "DateTime")); } + } + + internal Type System_DBNull + { + get { return typeof_System_DBNull ?? (typeof_System_DBNull = ImportMscorlibType("System", "DBNull")); } + } + + internal Type System_Decimal + { + get { return typeof_System_Decimal ?? (typeof_System_Decimal = ImportMscorlibType("System", "Decimal")); } + } + + internal Type System_AttributeUsageAttribute + { + get { return typeof_System_AttributeUsageAttribute ?? (typeof_System_AttributeUsageAttribute = ImportMscorlibType("System", "AttributeUsageAttribute")); } + } + + internal Type System_Runtime_InteropServices_DllImportAttribute + { + get { return typeof_System_Runtime_InteropServices_DllImportAttribute ?? (typeof_System_Runtime_InteropServices_DllImportAttribute = ImportMscorlibType("System.Runtime.InteropServices", "DllImportAttribute")); } + } + + internal Type System_Runtime_InteropServices_FieldOffsetAttribute + { + get { return typeof_System_Runtime_InteropServices_FieldOffsetAttribute ?? (typeof_System_Runtime_InteropServices_FieldOffsetAttribute = ImportMscorlibType("System.Runtime.InteropServices", "FieldOffsetAttribute")); } + } + + internal Type System_Runtime_InteropServices_MarshalAsAttribute + { + get { return typeof_System_Runtime_InteropServices_MarshalAsAttribute ?? (typeof_System_Runtime_InteropServices_MarshalAsAttribute = ImportMscorlibType("System.Runtime.InteropServices", "MarshalAsAttribute")); } + } + + internal Type System_Runtime_InteropServices_UnmanagedType + { + get { return typeof_System_Runtime_InteropServices_UnmanagedType ?? (typeof_System_Runtime_InteropServices_UnmanagedType = ImportMscorlibType("System.Runtime.InteropServices", "UnmanagedType")); } + } + + internal Type System_Runtime_InteropServices_VarEnum + { + get { return typeof_System_Runtime_InteropServices_VarEnum ?? (typeof_System_Runtime_InteropServices_VarEnum = ImportMscorlibType("System.Runtime.InteropServices", "VarEnum")); } + } + + internal Type System_Runtime_InteropServices_PreserveSigAttribute + { + get { return typeof_System_Runtime_InteropServices_PreserveSigAttribute ?? (typeof_System_Runtime_InteropServices_PreserveSigAttribute = ImportMscorlibType("System.Runtime.InteropServices", "PreserveSigAttribute")); } + } + + internal Type System_Runtime_InteropServices_CallingConvention + { + get { return typeof_System_Runtime_InteropServices_CallingConvention ?? (typeof_System_Runtime_InteropServices_CallingConvention = ImportMscorlibType("System.Runtime.InteropServices", "CallingConvention")); } + } + + internal Type System_Runtime_InteropServices_CharSet + { + get { return typeof_System_Runtime_InteropServices_CharSet ?? (typeof_System_Runtime_InteropServices_CharSet = ImportMscorlibType("System.Runtime.InteropServices", "CharSet")); } + } + + internal Type System_Runtime_CompilerServices_DecimalConstantAttribute + { + get { return typeof_System_Runtime_CompilerServices_DecimalConstantAttribute ?? (typeof_System_Runtime_CompilerServices_DecimalConstantAttribute = ImportMscorlibType("System.Runtime.CompilerServices", "DecimalConstantAttribute")); } + } + + internal Type System_Reflection_AssemblyCopyrightAttribute + { + get { return typeof_System_Reflection_AssemblyCopyrightAttribute ?? (typeof_System_Reflection_AssemblyCopyrightAttribute = ImportMscorlibType("System.Reflection", "AssemblyCopyrightAttribute")); } + } + + internal Type System_Reflection_AssemblyTrademarkAttribute + { + get { return typeof_System_Reflection_AssemblyTrademarkAttribute ?? (typeof_System_Reflection_AssemblyTrademarkAttribute = ImportMscorlibType("System.Reflection", "AssemblyTrademarkAttribute")); } + } + + internal Type System_Reflection_AssemblyProductAttribute + { + get { return typeof_System_Reflection_AssemblyProductAttribute ?? (typeof_System_Reflection_AssemblyProductAttribute = ImportMscorlibType("System.Reflection", "AssemblyProductAttribute")); } + } + + internal Type System_Reflection_AssemblyCompanyAttribute + { + get { return typeof_System_Reflection_AssemblyCompanyAttribute ?? (typeof_System_Reflection_AssemblyCompanyAttribute = ImportMscorlibType("System.Reflection", "AssemblyCompanyAttribute")); } + } + + internal Type System_Reflection_AssemblyDescriptionAttribute + { + get { return typeof_System_Reflection_AssemblyDescriptionAttribute ?? (typeof_System_Reflection_AssemblyDescriptionAttribute = ImportMscorlibType("System.Reflection", "AssemblyDescriptionAttribute")); } + } + + internal Type System_Reflection_AssemblyTitleAttribute + { + get { return typeof_System_Reflection_AssemblyTitleAttribute ?? (typeof_System_Reflection_AssemblyTitleAttribute = ImportMscorlibType("System.Reflection", "AssemblyTitleAttribute")); } + } + + internal Type System_Reflection_AssemblyInformationalVersionAttribute + { + get { return typeof_System_Reflection_AssemblyInformationalVersionAttribute ?? (typeof_System_Reflection_AssemblyInformationalVersionAttribute = ImportMscorlibType("System.Reflection", "AssemblyInformationalVersionAttribute")); } + } + + internal Type System_Reflection_AssemblyFileVersionAttribute + { + get { return typeof_System_Reflection_AssemblyFileVersionAttribute ?? (typeof_System_Reflection_AssemblyFileVersionAttribute = ImportMscorlibType("System.Reflection", "AssemblyFileVersionAttribute")); } + } + + internal Type System_Security_Permissions_CodeAccessSecurityAttribute + { + get { return typeof_System_Security_Permissions_CodeAccessSecurityAttribute ?? (typeof_System_Security_Permissions_CodeAccessSecurityAttribute = ImportMscorlibType("System.Security.Permissions", "CodeAccessSecurityAttribute")); } + } + + internal Type System_Security_Permissions_PermissionSetAttribute + { + get { return typeof_System_Security_Permissions_PermissionSetAttribute ?? (typeof_System_Security_Permissions_PermissionSetAttribute = ImportMscorlibType("System.Security.Permissions", "PermissionSetAttribute")); } + } + + internal Type System_Security_Permissions_SecurityAction + { + get { return typeof_System_Security_Permissions_SecurityAction ?? (typeof_System_Security_Permissions_SecurityAction = ImportMscorlibType("System.Security.Permissions", "SecurityAction")); } + } + + internal bool HasMscorlib + { + get { return GetLoadedAssembly("mscorlib") != null; } + } + + public event ResolveEventHandler AssemblyResolve + { + add { resolvers.Add(value); } + remove { resolvers.Remove(value); } + } + + public Type Import(System.Type type) + { + Type imported; + if (!importedTypes.TryGetValue(type, out imported)) + { + imported = ImportImpl(type); + if (imported != null) + { + importedTypes.Add(type, imported); + } + } + return imported; + } + + private Type ImportImpl(System.Type type) + { + if (type.Assembly == typeof(IKVM.Reflection.Type).Assembly) + { + throw new ArgumentException("Did you really want to import " + type.FullName + "?"); + } + if (type.HasElementType) + { + if (type.IsArray) + { + if (type.Name.EndsWith("[]")) + { + return Import(type.GetElementType()).MakeArrayType(); + } + else + { + return Import(type.GetElementType()).MakeArrayType(type.GetArrayRank()); + } + } + else if (type.IsByRef) + { + return Import(type.GetElementType()).MakeByRefType(); + } + else if (type.IsPointer) + { + return Import(type.GetElementType()).MakePointerType(); + } + else + { + throw new InvalidOperationException(); + } + } + else if (type.IsGenericParameter) + { + if (type.DeclaringMethod != null) + { + throw new NotImplementedException(); + } + else + { + return Import(type.DeclaringType).GetGenericArguments()[type.GenericParameterPosition]; + } + } + else if (type.IsGenericType && !type.IsGenericTypeDefinition) + { + System.Type[] args = type.GetGenericArguments(); + Type[] importedArgs = new Type[args.Length]; + for (int i = 0; i < args.Length; i++) + { + importedArgs[i] = Import(args[i]); + } + return Import(type.GetGenericTypeDefinition()).MakeGenericType(importedArgs); + } + else if (type.Assembly == typeof(object).Assembly) + { + // make sure mscorlib types always end up in our mscorlib + return ResolveType(Mscorlib, type.FullName); + } + else + { + // FXBUG we parse the FullName here, because type.Namespace and type.Name are both broken on the CLR + return ResolveType(Import(type.Assembly), type.FullName); + } + } + + private Assembly Import(System.Reflection.Assembly asm) + { + return Load(asm.FullName); + } + + public RawModule OpenRawModule(string path) + { + path = Path.GetFullPath(path); + FileStream fs = null; + RawModule module; + try + { + fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); + module = OpenRawModule(fs, path); + if (!MetadataOnly) + { + fs = null; + } + } + finally + { + if (fs != null) + { + fs.Close(); + } + } + return module; + } + + public RawModule OpenRawModule(Stream stream, string location) + { + return OpenRawModule(stream, location, false); + } + + public RawModule OpenMappedRawModule(Stream stream, string location) + { + return OpenRawModule(stream, location, true); + } + + private RawModule OpenRawModule(Stream stream, string location, bool mapped) + { + if (!stream.CanRead || !stream.CanSeek || stream.Position != 0) + { + throw new ArgumentException("Stream must support read/seek and current position must be zero.", "stream"); + } + return new RawModule(new ModuleReader(null, this, stream, location, mapped)); + } + + public Assembly LoadAssembly(RawModule module) + { + string refname = module.GetAssemblyName().FullName; + Assembly asm = GetLoadedAssembly(refname); + if (asm == null) + { + AssemblyReader asm1 = module.ToAssembly(); + assemblies.Add(asm1); + asm = asm1; + } + return asm; + } + + public Assembly LoadFile(string path) + { + try + { + using (RawModule module = OpenRawModule(path)) + { + return LoadAssembly(module); + } + } + catch (IOException x) + { + throw new FileNotFoundException(x.Message, x); + } + catch (UnauthorizedAccessException x) + { + throw new FileNotFoundException(x.Message, x); + } + } + + private static string GetSimpleAssemblyName(string refname) + { + int pos; + string name; + if (Fusion.ParseAssemblySimpleName(refname, out pos, out name) != ParseAssemblyResult.OK) + { + throw new ArgumentException(); + } + return name; + } + + private Assembly GetLoadedAssembly(string refname) + { + Assembly asm; + if (!assembliesByName.TryGetValue(refname, out asm)) + { + string simpleName = GetSimpleAssemblyName(refname); + for (int i = 0; i < assemblies.Count; i++) + { + AssemblyComparisonResult result; + if (simpleName.Equals(assemblies[i].Name, StringComparison.OrdinalIgnoreCase) + && CompareAssemblyIdentity(refname, false, assemblies[i].FullName, false, out result)) + { + asm = assemblies[i]; + assembliesByName.Add(refname, asm); + break; + } + } + } + return asm; + } + + private Assembly GetDynamicAssembly(string refname) + { + string simpleName = GetSimpleAssemblyName(refname); + foreach (AssemblyBuilder asm in dynamicAssemblies) + { + AssemblyComparisonResult result; + if (simpleName.Equals(asm.Name, StringComparison.OrdinalIgnoreCase) + && CompareAssemblyIdentity(refname, false, asm.FullName, false, out result)) + { + return asm; + } + } + return null; + } + + public Assembly Load(string refname) + { + return Load(refname, null, true); + } + + internal Assembly Load(string refname, Module requestingModule, bool throwOnError) + { + Assembly asm = GetLoadedAssembly(refname); + if (asm != null) + { + return asm; + } + if (resolvers.Count == 0) + { + asm = DefaultResolver(refname, throwOnError); + } + else + { + ResolveEventArgs args = new ResolveEventArgs(refname, requestingModule == null ? null : requestingModule.Assembly); + foreach (ResolveEventHandler evt in resolvers) + { + asm = evt(this, args); + if (asm != null) + { + break; + } + } + if (asm == null) + { + asm = GetDynamicAssembly(refname); + } + } + if (asm != null) + { + string defname = asm.FullName; + if (refname != defname) + { + assembliesByName.Add(refname, asm); + } + return asm; + } + if (throwOnError) + { + throw new FileNotFoundException(refname); + } + return null; + } + + private Assembly DefaultResolver(string refname, bool throwOnError) + { + Assembly asm = GetDynamicAssembly(refname); + if (asm != null) + { + return asm; + } +#if CORECLR + return null; +#else + string fileName; + if (throwOnError) + { + try + { + fileName = System.Reflection.Assembly.ReflectionOnlyLoad(refname).Location; + } + catch (System.BadImageFormatException x) + { + throw new BadImageFormatException(x.Message, x); + } + } + else + { + try + { + fileName = System.Reflection.Assembly.ReflectionOnlyLoad(refname).Location; + } + catch (System.BadImageFormatException x) + { + throw new BadImageFormatException(x.Message, x); + } + catch (FileNotFoundException) + { + // we intentionally only swallow the FileNotFoundException, if the file exists but isn't a valid assembly, + // we should throw an exception + return null; + } + } + return LoadFile(fileName); +#endif + } + + public Type GetType(string assemblyQualifiedTypeName) + { + // to be more compatible with Type.GetType(), we could call Assembly.GetCallingAssembly(), + // import that assembly and pass it as the context, but implicitly importing is considered evil + return GetType(null, assemblyQualifiedTypeName, false, false); + } + + public Type GetType(string assemblyQualifiedTypeName, bool throwOnError) + { + // to be more compatible with Type.GetType(), we could call Assembly.GetCallingAssembly(), + // import that assembly and pass it as the context, but implicitly importing is considered evil + return GetType(null, assemblyQualifiedTypeName, throwOnError, false); + } + + public Type GetType(string assemblyQualifiedTypeName, bool throwOnError, bool ignoreCase) + { + // to be more compatible with Type.GetType(), we could call Assembly.GetCallingAssembly(), + // import that assembly and pass it as the context, but implicitly importing is considered evil + return GetType(null, assemblyQualifiedTypeName, throwOnError, ignoreCase); + } + + // note that context is slightly different from the calling assembly (System.Type.GetType), + // because context is passed to the AssemblyResolve event as the RequestingAssembly + public Type GetType(Assembly context, string assemblyQualifiedTypeName, bool throwOnError) + { + return GetType(context, assemblyQualifiedTypeName, throwOnError, false); + } + + // note that context is slightly different from the calling assembly (System.Type.GetType), + // because context is passed to the AssemblyResolve event as the RequestingAssembly + public Type GetType(Assembly context, string assemblyQualifiedTypeName, bool throwOnError, bool ignoreCase) + { + TypeNameParser parser = TypeNameParser.Parse(assemblyQualifiedTypeName, throwOnError); + if (parser.Error) + { + return null; + } + return parser.GetType(this, context == null ? null : context.ManifestModule, throwOnError, assemblyQualifiedTypeName, false, ignoreCase); + } + + // this is similar to GetType(Assembly context, string assemblyQualifiedTypeName, bool throwOnError), + // but instead it assumes that the type must exist (i.e. if EnableMissingMemberResolution is enabled + // it will create a missing type) + public Type ResolveType(Assembly context, string assemblyQualifiedTypeName) + { + TypeNameParser parser = TypeNameParser.Parse(assemblyQualifiedTypeName, false); + if (parser.Error) + { + return null; + } + return parser.GetType(this, context == null ? null : context.ManifestModule, false, assemblyQualifiedTypeName, true, false); + } + + public Type GetBuiltInType(string ns, string name) + { + if (ns != "System") + { + return null; + } + switch (name) + { + case "Boolean": + return System_Boolean; + case "Char": + return System_Char; + case "Object": + return System_Object; + case "String": + return System_String; + case "Single": + return System_Single; + case "Double": + return System_Double; + case "SByte": + return System_SByte; + case "Int16": + return System_Int16; + case "Int32": + return System_Int32; + case "Int64": + return System_Int64; + case "IntPtr": + return System_IntPtr; + case "UIntPtr": + return System_UIntPtr; + case "TypedReference": + return System_TypedReference; + case "Byte": + return System_Byte; + case "UInt16": + return System_UInt16; + case "UInt32": + return System_UInt32; + case "UInt64": + return System_UInt64; + case "Void": + return System_Void; + default: + return null; + } + } + + public Assembly[] GetAssemblies() + { + Assembly[] array = new Assembly[assemblies.Count + dynamicAssemblies.Count]; + for (int i = 0; i < assemblies.Count; i++) + { + array[i] = assemblies[i]; + } + for (int i = 0, j = assemblies.Count; j < array.Length; i++, j++) + { + array[j] = dynamicAssemblies[i]; + } + return array; + } + + // this is equivalent to the Fusion CompareAssemblyIdentity API + public bool CompareAssemblyIdentity(string assemblyIdentity1, bool unified1, string assemblyIdentity2, bool unified2, out AssemblyComparisonResult result) + { +#if CORECLR + return Fusion.CompareAssemblyIdentityPure(assemblyIdentity1, unified1, assemblyIdentity2, unified2, out result); +#else + return useNativeFusion + ? Fusion.CompareAssemblyIdentityNative(assemblyIdentity1, unified1, assemblyIdentity2, unified2, out result) + : Fusion.CompareAssemblyIdentityPure(assemblyIdentity1, unified1, assemblyIdentity2, unified2, out result); +#endif + } + + public AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access) + { + return new AssemblyBuilder(this, name, null, null); + } + + public AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access, IEnumerable assemblyAttributes) + { + return new AssemblyBuilder(this, name, null, assemblyAttributes); + } + + public AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access, string dir) + { + return new AssemblyBuilder(this, name, dir, null); + } + +#if !CORECLR +#if NET_4_0 + [Obsolete] +#endif + public AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access, string dir, PermissionSet requiredPermissions, PermissionSet optionalPermissions, PermissionSet refusedPermissions) + { + AssemblyBuilder ab = new AssemblyBuilder(this, name, dir, null); + AddLegacyPermissionSet(ab, requiredPermissions, System.Security.Permissions.SecurityAction.RequestMinimum); + AddLegacyPermissionSet(ab, optionalPermissions, System.Security.Permissions.SecurityAction.RequestOptional); + AddLegacyPermissionSet(ab, refusedPermissions, System.Security.Permissions.SecurityAction.RequestRefuse); + return ab; + } + + private static void AddLegacyPermissionSet(AssemblyBuilder ab, PermissionSet permissionSet, System.Security.Permissions.SecurityAction action) + { + if (permissionSet != null) + { + ab.__AddDeclarativeSecurity(CustomAttributeBuilder.__FromBlob(CustomAttributeBuilder.LegacyPermissionSet, (int)action, Encoding.Unicode.GetBytes(permissionSet.ToXml().ToString()))); + } + } +#endif + + internal void RegisterDynamicAssembly(AssemblyBuilder asm) + { + dynamicAssemblies.Add(asm); + } + + internal void RenameAssembly(Assembly assembly, AssemblyName oldName) + { + List remove = new List(); + foreach (KeyValuePair kv in assembliesByName) + { + if (kv.Value == assembly) + { + remove.Add(kv.Key); + } + } + foreach (string key in remove) + { + assembliesByName.Remove(key); + } + } + + public void Dispose() + { + foreach (Assembly asm in assemblies) + { + foreach (Module mod in asm.GetLoadedModules()) + { + mod.Dispose(); + } + } + foreach (AssemblyBuilder asm in dynamicAssemblies) + { + foreach (Module mod in asm.GetLoadedModules()) + { + mod.Dispose(); + } + } + } + + public Assembly CreateMissingAssembly(string assemblyName) + { + Assembly asm = new MissingAssembly(this, assemblyName); + string name = asm.FullName; + if (!assembliesByName.ContainsKey(name)) + { + assembliesByName.Add(name, asm); + } + return asm; + } + + [Obsolete("Please set UniverseOptions.ResolveMissingMembers instead.")] + public void EnableMissingMemberResolution() + { + resolveMissingMembers = true; + } + + internal bool MissingMemberResolution + { + get { return resolveMissingMembers; } + } + + internal bool EnableFunctionPointers + { + get { return enableFunctionPointers; } + } + + private struct ScopedTypeName : IEquatable + { + private readonly object scope; + private readonly TypeName name; + + internal ScopedTypeName(object scope, TypeName name) + { + this.scope = scope; + this.name = name; + } + + public override bool Equals(object obj) + { + ScopedTypeName? other = obj as ScopedTypeName?; + return other != null && ((IEquatable)other.Value).Equals(this); + } + + public override int GetHashCode() + { + return scope.GetHashCode() * 7 + name.GetHashCode(); + } + + bool IEquatable.Equals(ScopedTypeName other) + { + return other.scope == scope && other.name == name; + } + } + + private Type GetMissingType(Module requester, Module module, Type declaringType, TypeName typeName) + { + if (missingTypes == null) + { + missingTypes = new Dictionary(); + } + ScopedTypeName stn = new ScopedTypeName(declaringType ?? (object)module, typeName); + Type type; + if (!missingTypes.TryGetValue(stn, out type)) + { + type = new MissingType(module, declaringType, typeName.Namespace, typeName.Name); + missingTypes.Add(stn, type); + } + if (ResolvedMissingMember != null && !module.Assembly.__IsMissing) + { + ResolvedMissingMember(requester, type); + } + return type; + } + + internal Type GetMissingTypeOrThrow(Module requester, Module module, Type declaringType, TypeName typeName) + { + if (resolveMissingMembers || module.Assembly.__IsMissing) + { + return GetMissingType(requester, module, declaringType, typeName); + } + string fullName = TypeNameParser.Escape(typeName.ToString()); + if (declaringType != null) + { + fullName = declaringType.FullName + "+" + fullName; + } + throw new TypeLoadException(String.Format("Type '{0}' not found in assembly '{1}'", fullName, module.Assembly.FullName)); + } + + internal MethodBase GetMissingMethodOrThrow(Module requester, Type declaringType, string name, MethodSignature signature) + { + if (resolveMissingMembers) + { + MethodBase method = new MissingMethod(declaringType, name, signature); + if (name == ".ctor") + { + method = new ConstructorInfoImpl((MethodInfo)method); + } + if (ResolvedMissingMember != null) + { + ResolvedMissingMember(requester, method); + } + return method; + } +#if CORECLR + throw new MissingMethodException(declaringType.ToString() + "." + name); +#else + throw new MissingMethodException(declaringType.ToString(), name); +#endif + } + + internal FieldInfo GetMissingFieldOrThrow(Module requester, Type declaringType, string name, FieldSignature signature) + { + if (resolveMissingMembers) + { + FieldInfo field = new MissingField(declaringType, name, signature); + if (ResolvedMissingMember != null) + { + ResolvedMissingMember(requester, field); + } + return field; + } +#if CORECLR + throw new MissingFieldException(declaringType.ToString() + "." + name); +#else + throw new MissingFieldException(declaringType.ToString(), name); +#endif + } + + internal PropertyInfo GetMissingPropertyOrThrow(Module requester, Type declaringType, string name, PropertySignature propertySignature) + { + // HACK we need to check __IsMissing here, because Type doesn't have a FindProperty API + // since properties are never resolved, except by custom attributes + if (resolveMissingMembers || declaringType.__IsMissing) + { + PropertyInfo property = new MissingProperty(declaringType, name, propertySignature); + if (ResolvedMissingMember != null && !declaringType.__IsMissing) + { + ResolvedMissingMember(requester, property); + } + return property; + } +#if CORECLR + throw new System.MissingMemberException(declaringType.ToString() + "." + name); +#else + throw new System.MissingMemberException(declaringType.ToString(), name); +#endif + } + + internal Type CanonicalizeType(Type type) + { + Type canon; + if (!canonicalizedTypes.TryGetValue(type, out canon)) + { + canon = type; + canonicalizedTypes.Add(canon, canon); + } + return canon; + } + + public Type MakeFunctionPointer(__StandAloneMethodSig sig) + { + return FunctionPointerType.Make(this, sig); + } + + public __StandAloneMethodSig MakeStandAloneMethodSig(System.Runtime.InteropServices.CallingConvention callingConvention, Type returnType, CustomModifiers returnTypeCustomModifiers, Type[] parameterTypes, CustomModifiers[] parameterTypeCustomModifiers) + { + return new __StandAloneMethodSig(true, callingConvention, 0, returnType ?? this.System_Void, Util.Copy(parameterTypes), Type.EmptyTypes, + PackedCustomModifiers.CreateFromExternal(returnTypeCustomModifiers, parameterTypeCustomModifiers, Util.NullSafeLength(parameterTypes))); + } + + public __StandAloneMethodSig MakeStandAloneMethodSig(CallingConventions callingConvention, Type returnType, CustomModifiers returnTypeCustomModifiers, Type[] parameterTypes, Type[] optionalParameterTypes, CustomModifiers[] parameterTypeCustomModifiers) + { + return new __StandAloneMethodSig(false, 0, callingConvention, returnType ?? this.System_Void, Util.Copy(parameterTypes), Util.Copy(optionalParameterTypes), + PackedCustomModifiers.CreateFromExternal(returnTypeCustomModifiers, parameterTypeCustomModifiers, Util.NullSafeLength(parameterTypes) + Util.NullSafeLength(optionalParameterTypes))); + } + + public event ResolvedMissingMemberHandler ResolvedMissingMember; + + public event Predicate MissingTypeIsValueType + { + add + { + if (missingTypeIsValueType != null) + { + throw new InvalidOperationException("Only a single MissingTypeIsValueType handler can be registered."); + } + missingTypeIsValueType = value; + } + remove + { + if (value.Equals(missingTypeIsValueType)) + { + missingTypeIsValueType = null; + } + } + } + + public static Universe FromAssembly(Assembly assembly) + { + return assembly.universe; + } + + internal bool ResolveMissingTypeIsValueType(MissingType missingType) + { + if (missingTypeIsValueType != null) + { + return missingTypeIsValueType(missingType); + } + throw new MissingMemberException(missingType); + } + + internal bool ReturnPseudoCustomAttributes + { + get { return returnPseudoCustomAttributes; } + } + + internal bool AutomaticallyProvideDefaultConstructor + { + get { return automaticallyProvideDefaultConstructor; } + } + + internal bool MetadataOnly + { + get { return (options & UniverseOptions.MetadataOnly) != 0; } + } + + internal bool WindowsRuntimeProjection + { + get { return (options & UniverseOptions.DisableWindowsRuntimeProjection) == 0; } + } + + internal bool DecodeVersionInfoAttributeBlobs + { + get { return (options & UniverseOptions.DecodeVersionInfoAttributeBlobs) != 0; } + } + + internal bool Deterministic + { + get { return (options & UniverseOptions.DeterministicOutput) != 0; } + } + } +} diff --git a/reflect/Util.cs b/reflect/Util.cs new file mode 100644 index 0000000..7ca6a0f --- /dev/null +++ b/reflect/Util.cs @@ -0,0 +1,266 @@ +/* + Copyright (C) 2008-2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; + +namespace IKVM.Reflection +{ + public interface ICustomAttributeProvider + { + bool IsDefined(Type attributeType, bool inherit); + IList __GetCustomAttributes(Type attributeType, bool inherit); + } + +#if !CORECLR + [Serializable] +#endif + public sealed class FileFormatLimitationExceededException : InvalidOperationException + { + public const int META_E_STRINGSPACE_FULL = unchecked((int)0x80131198); + + public FileFormatLimitationExceededException(string message, int hresult) + : base(message) + { + this.HResult = hresult; + } + +#if !CORECLR + private FileFormatLimitationExceededException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) + : base(info, context) + { + } +#endif + + public int ErrorCode + { + get { return this.HResult; } + } + } + +#if !CORECLR + [Serializable] +#endif + public sealed class Missing +#if !CORECLR + : System.Runtime.Serialization.ISerializable +#endif + { + public static readonly Missing Value = new Missing(); + + private Missing() { } + +#if !CORECLR + void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) + { + info.SetType(typeof(SingletonSerializationHelper)); + } + + [Serializable] + private sealed class SingletonSerializationHelper : System.Runtime.Serialization.IObjectReference + { + public object GetRealObject(System.Runtime.Serialization.StreamingContext context) + { + return Value; + } + } +#endif + } + + static class Empty + { + internal static readonly T[] Array = new T[0]; + } + + static class Util + { + internal static int[] Copy(int[] array) + { + if (array == null || array.Length == 0) + { + return Empty.Array; + } + int[] copy = new int[array.Length]; + Array.Copy(array, copy, array.Length); + return copy; + } + + internal static Type[] Copy(Type[] array) + { + if (array == null || array.Length == 0) + { + return Type.EmptyTypes; + } + Type[] copy = new Type[array.Length]; + Array.Copy(array, copy, array.Length); + return copy; + } + + internal static T[] ToArray(List list, T[] empty) where V : T + { + if (list == null || list.Count == 0) + { + return empty; + } + T[] array = new T[list.Count]; + for (int i = 0; i < array.Length; i++) + { + array[i] = list[i]; + } + return array; + } + + internal static T[] ToArray(IEnumerable values) + { + return values == null + ? Empty.Array + : new List(values).ToArray(); + } + + // note that an empty array matches a null reference + internal static bool ArrayEquals(Type[] t1, Type[] t2) + { + if (t1 == t2) + { + return true; + } + if (t1 == null) + { + return t2.Length == 0; + } + else if (t2 == null) + { + return t1.Length == 0; + } + if (t1.Length == t2.Length) + { + for (int i = 0; i < t1.Length; i++) + { + if (!TypeEquals(t1[i], t2[i])) + { + return false; + } + } + return true; + } + return false; + } + + internal static bool TypeEquals(Type t1, Type t2) + { + if (t1 == t2) + { + return true; + } + if (t1 == null) + { + return false; + } + return t1.Equals(t2); + } + + internal static int GetHashCode(Type[] types) + { + if (types == null) + { + return 0; + } + int h = 0; + foreach (Type t in types) + { + if (t != null) + { + h *= 3; + h ^= t.GetHashCode(); + } + } + return h; + } + + internal static bool ArrayEquals(CustomModifiers[] m1, CustomModifiers[] m2) + { + if (m1 == null || m2 == null) + { + return m1 == m2; + } + if (m1.Length != m2.Length) + { + return false; + } + for (int i = 0; i < m1.Length; i++) + { + if (!m1[i].Equals(m2[i])) + { + return false; + } + } + return true; + } + + internal static int GetHashCode(CustomModifiers[] mods) + { + int h = 0; + if (mods != null) + { + foreach (CustomModifiers mod in mods) + { + h ^= mod.GetHashCode(); + } + } + return h; + } + + internal static T NullSafeElementAt(T[] array, int index) + { + return array == null ? default(T) : array[index]; + } + + internal static int NullSafeLength(T[] array) + { + return array == null ? 0 : array.Length; + } + } + + [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit)] + struct SingleConverter + { + [System.Runtime.InteropServices.FieldOffset(0)] + private int i; + [System.Runtime.InteropServices.FieldOffset(0)] + private float f; + + internal static int SingleToInt32Bits(float v) + { + SingleConverter c = new SingleConverter(); + c.f = v; + return c.i; + } + + internal static float Int32BitsToSingle(int v) + { + SingleConverter c = new SingleConverter(); + c.i = v; + return c.f; + } + } +} diff --git a/reflect/Writer/ByteBuffer.cs b/reflect/Writer/ByteBuffer.cs new file mode 100644 index 0000000..fd57d43 --- /dev/null +++ b/reflect/Writer/ByteBuffer.cs @@ -0,0 +1,352 @@ +/* + Copyright (C) 2008 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; +using IKVM.Reflection.Metadata; + +namespace IKVM.Reflection.Writer +{ + sealed class ByteBuffer + { + private byte[] buffer; + private int pos; + private int __length; // __length is only valid if > pos, otherwise pos is the current length + + internal ByteBuffer(int initialCapacity) + { + buffer = new byte[initialCapacity]; + } + + private ByteBuffer(byte[] wrap, int length) + { + this.buffer = wrap; + this.pos = length; + } + + internal int Position + { + get { return pos; } + set + { + if (value > this.Length || value > buffer.Length) + throw new ArgumentOutOfRangeException(); + __length = Math.Max(__length, pos); + pos = value; + } + } + + internal int Length + { + get { return Math.Max(pos, __length); } + } + + // insert count bytes at the current position (without advancing the current position) + internal void Insert(int count) + { + if (count > 0) + { + int len = this.Length; + int free = buffer.Length - len; + if (free < count) + { + Grow(count - free); + } + Buffer.BlockCopy(buffer, pos, buffer, pos + count, len - pos); + __length = Math.Max(__length, pos) + count; + } + else if (count < 0) + { + throw new ArgumentOutOfRangeException("count"); + } + } + + private void Grow(int minGrow) + { + byte[] newbuf = new byte[Math.Max(buffer.Length + minGrow, buffer.Length * 2)]; + Buffer.BlockCopy(buffer, 0, newbuf, 0, buffer.Length); + buffer = newbuf; + } + + // NOTE this does not advance the position + internal int GetInt32AtCurrentPosition() + { + return buffer[pos] + + (buffer[pos + 1] << 8) + + (buffer[pos + 2] << 16) + + (buffer[pos + 3] << 24); + } + + // NOTE this does not advance the position + internal byte GetByteAtCurrentPosition() + { + return buffer[pos]; + } + + // return the number of bytes that the compressed int at the current position takes + internal int GetCompressedUIntLength() + { + switch (buffer[pos] & 0xC0) + { + default: + return 1; + case 0x80: + return 2; + case 0xC0: + return 4; + } + } + + internal void Write(byte[] value) + { + if (pos + value.Length > buffer.Length) + Grow(value.Length); + Buffer.BlockCopy(value, 0, buffer, pos, value.Length); + pos += value.Length; + } + + internal void Write(byte value) + { + if (pos == buffer.Length) + Grow(1); + buffer[pos++] = value; + } + + internal void Write(sbyte value) + { + Write((byte)value); + } + + internal void Write(ushort value) + { + Write((short)value); + } + + internal void Write(short value) + { + if (pos + 2 > buffer.Length) + Grow(2); + buffer[pos++] = (byte)value; + buffer[pos++] = (byte)(value >> 8); + } + + internal void Write(uint value) + { + Write((int)value); + } + + internal void Write(int value) + { + if (pos + 4 > buffer.Length) + Grow(4); + buffer[pos++] = (byte)value; + buffer[pos++] = (byte)(value >> 8); + buffer[pos++] = (byte)(value >> 16); + buffer[pos++] = (byte)(value >> 24); + } + + internal void Write(ulong value) + { + Write((long)value); + } + + internal void Write(long value) + { + if (pos + 8 > buffer.Length) + Grow(8); + buffer[pos++] = (byte)value; + buffer[pos++] = (byte)(value >> 8); + buffer[pos++] = (byte)(value >> 16); + buffer[pos++] = (byte)(value >> 24); + buffer[pos++] = (byte)(value >> 32); + buffer[pos++] = (byte)(value >> 40); + buffer[pos++] = (byte)(value >> 48); + buffer[pos++] = (byte)(value >> 56); + } + + internal void Write(float value) + { + Write(SingleConverter.SingleToInt32Bits(value)); + } + + internal void Write(double value) + { + Write(BitConverter.DoubleToInt64Bits(value)); + } + + internal void Write(string str) + { + if (str == null) + { + Write((byte)0xFF); + } + else + { + byte[] buf = Encoding.UTF8.GetBytes(str); + WriteCompressedUInt(buf.Length); + Write(buf); + } + } + + internal void WriteCompressedUInt(int value) + { + if (value <= 0x7F) + { + Write((byte)value); + } + else if (value <= 0x3FFF) + { + Write((byte)(0x80 | (value >> 8))); + Write((byte)value); + } + else + { + Write((byte)(0xC0 | (value >> 24))); + Write((byte)(value >> 16)); + Write((byte)(value >> 8)); + Write((byte)value); + } + } + + internal void WriteCompressedInt(int value) + { + if (value >= 0) + { + WriteCompressedUInt(value << 1); + } + else if (value >= -64) + { + value = ((value << 1) & 0x7F) | 1; + Write((byte)value); + } + else if (value >= -8192) + { + value = ((value << 1) & 0x3FFF) | 1; + Write((byte)(0x80 | (value >> 8))); + Write((byte)value); + } + else + { + value = ((value << 1) & 0x1FFFFFFF) | 1; + Write((byte)(0xC0 | (value >> 24))); + Write((byte)(value >> 16)); + Write((byte)(value >> 8)); + Write((byte)value); + } + } + + internal void Write(ByteBuffer bb) + { + if (pos + bb.Length > buffer.Length) + Grow(bb.Length); + Buffer.BlockCopy(bb.buffer, 0, buffer, pos, bb.Length); + pos += bb.Length; + } + + internal void WriteTo(System.IO.Stream stream) + { + stream.Write(buffer, 0, this.Length); + } + + internal void Clear() + { + pos = 0; + __length = 0; + } + + internal void Align(int alignment) + { + if (pos + alignment > buffer.Length) + Grow(alignment); + int newpos = (pos + alignment - 1) & ~(alignment - 1); + while (pos < newpos) + buffer[pos++] = 0; + } + + internal void WriteTypeDefOrRefEncoded(int token) + { + switch (token >> 24) + { + case TypeDefTable.Index: + WriteCompressedUInt((token & 0xFFFFFF) << 2 | 0); + break; + case TypeRefTable.Index: + WriteCompressedUInt((token & 0xFFFFFF) << 2 | 1); + break; + case TypeSpecTable.Index: + WriteCompressedUInt((token & 0xFFFFFF) << 2 | 2); + break; + default: + throw new InvalidOperationException(); + } + } + + internal byte[] ToArray() + { + int len = this.Length; + byte[] buf = new byte[len]; + Buffer.BlockCopy(buffer, 0, buf, 0, len); + return buf; + } + + internal static ByteBuffer Wrap(byte[] buf) + { + return new ByteBuffer(buf, buf.Length); + } + + internal static ByteBuffer Wrap(byte[] buf, int length) + { + return new ByteBuffer(buf, length); + } + + internal bool Match(int pos, ByteBuffer bb2, int pos2, int len) + { + for (int i = 0; i < len; i++) + { + if (buffer[pos + i] != bb2.buffer[pos2 + i]) + { + return false; + } + } + return true; + } + + internal int Hash() + { + int hash = 0; + int len = this.Length; + for (int i = 0; i < len; i++) + { + hash *= 37; + hash ^= buffer[i]; + } + return hash; + } + + internal IKVM.Reflection.Reader.ByteReader GetBlob(int offset) + { + return IKVM.Reflection.Reader.ByteReader.FromBlob(buffer, offset); + } + } +} diff --git a/reflect/Writer/Heaps.cs b/reflect/Writer/Heaps.cs new file mode 100644 index 0000000..54beaa4 --- /dev/null +++ b/reflect/Writer/Heaps.cs @@ -0,0 +1,395 @@ +/* + Copyright (C) 2008 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics; +using IKVM.Reflection.Metadata; + +namespace IKVM.Reflection.Writer +{ + abstract class Heap + { + protected bool frozen; + protected int unalignedlength; + + internal void Write(MetadataWriter mw) + { + int pos = mw.Position; + WriteImpl(mw); + Debug.Assert(mw.Position == pos + unalignedlength); + int align = Length - unalignedlength; + for (int i = 0; i < align; i++) + { + mw.Write((byte)0); + } + } + + internal bool IsBig + { + get { return Length > 65535; } + } + + internal int Length + { + get + { + if (!frozen) + throw new InvalidOperationException(); + return (unalignedlength + 3) & ~3; + } + } + + protected abstract void WriteImpl(MetadataWriter mw); + } + + abstract class SimpleHeap : Heap + { + internal void Freeze() + { + if (frozen) + throw new InvalidOperationException(); + frozen = true; + unalignedlength = GetLength(); + } + + protected abstract int GetLength(); + } + + sealed class TableHeap : Heap + { + internal void Freeze(MetadataWriter mw) + { + if (frozen) + throw new InvalidOperationException(); + frozen = true; + unalignedlength = GetLength(mw); + } + + protected override void WriteImpl(MetadataWriter mw) + { + Table[] tables = mw.ModuleBuilder.GetTables(); + // Header + mw.Write(0); // Reserved + int ver = mw.ModuleBuilder.MDStreamVersion; + mw.Write((byte)(ver >> 16)); // MajorVersion + mw.Write((byte)ver); // MinorVersion + byte heapSizes = 0; + if (mw.ModuleBuilder.Strings.IsBig) + { + heapSizes |= 0x01; + } + if (mw.ModuleBuilder.Guids.IsBig) + { + heapSizes |= 0x02; + } + if (mw.ModuleBuilder.Blobs.IsBig) + { + heapSizes |= 0x04; + } + mw.Write(heapSizes);// HeapSizes + // LAMESPEC spec says reserved, but .NET 2.0 Ref.Emit sets it to 0x10 + mw.Write((byte)0x10); // Reserved + long bit = 1; + long valid = 0; + foreach (Table table in tables) + { + if (table != null && table.RowCount > 0) + { + valid |= bit; + } + bit <<= 1; + } + mw.Write(valid); // Valid + mw.Write(0x0016003301FA00L); // Sorted + // Rows + foreach (Table table in tables) + { + if (table != null && table.RowCount > 0) + { + mw.Write(table.RowCount); + } + } + // Tables + foreach (Table table in tables) + { + if (table != null && table.RowCount > 0) + { + int pos = mw.Position; + table.Write(mw); + Debug.Assert(mw.Position - pos == table.GetLength(mw)); + } + } + // unexplained extra padding + mw.Write((byte)0); + } + + private static int GetLength(MetadataWriter mw) + { + int len = 4 + 4 + 8 + 8; + foreach (Table table in mw.ModuleBuilder.GetTables()) + { + if (table != null && table.RowCount > 0) + { + len += 4; // row count + len += table.GetLength(mw); + } + } + // note that we pad one extra (unexplained) byte + return len + 1; + } + } + + sealed class StringHeap : SimpleHeap + { + private List list = new List(); + private Dictionary strings = new Dictionary(); + private int nextOffset; + + internal StringHeap() + { + Add(""); + } + + internal int Add(string str) + { + Debug.Assert(!frozen); + int offset; + if (!strings.TryGetValue(str, out offset)) + { + offset = nextOffset; + nextOffset += System.Text.Encoding.UTF8.GetByteCount(str) + 1; + list.Add(str); + strings.Add(str, offset); + } + return offset; + } + + internal string Find(int index) + { + foreach (KeyValuePair kv in strings) + { + if (kv.Value == index) + { + return kv.Key; + } + } + return null; + } + + protected override int GetLength() + { + return nextOffset; + } + + protected override void WriteImpl(MetadataWriter mw) + { + foreach (string str in list) + { + mw.Write(System.Text.Encoding.UTF8.GetBytes(str)); + mw.Write((byte)0); + } + } + } + + sealed class UserStringHeap : SimpleHeap + { + private List list = new List(); + private Dictionary strings = new Dictionary(); + private int nextOffset; + + internal UserStringHeap() + { + nextOffset = 1; + } + + internal bool IsEmpty + { + get { return nextOffset == 1; } + } + + internal int Add(string str) + { + Debug.Assert(!frozen); + int offset; + if (!strings.TryGetValue(str, out offset)) + { + int length = str.Length * 2 + 1 + MetadataWriter.GetCompressedUIntLength(str.Length * 2 + 1); + if (nextOffset + length > 0xFFFFFF) + { + throw new FileFormatLimitationExceededException("No logical space left to create more user strings.", FileFormatLimitationExceededException.META_E_STRINGSPACE_FULL); + } + offset = nextOffset; + nextOffset += length; + list.Add(str); + strings.Add(str, offset); + } + return offset; + } + + protected override int GetLength() + { + return nextOffset; + } + + protected override void WriteImpl(MetadataWriter mw) + { + mw.Write((byte)0); + foreach (string str in list) + { + mw.WriteCompressedUInt(str.Length * 2 + 1); + byte hasSpecialChars = 0; + foreach (char ch in str) + { + mw.Write((ushort)ch); + if (hasSpecialChars == 0 && (ch < 0x20 || ch > 0x7E)) + { + if (ch > 0x7E + || (ch >= 0x01 && ch <= 0x08) + || (ch >= 0x0E && ch <= 0x1F) + || ch == 0x27 + || ch == 0x2D) + { + hasSpecialChars = 1; + } + } + } + mw.Write(hasSpecialChars); + } + } + } + + sealed class GuidHeap : SimpleHeap + { + private List list = new List(); + + internal GuidHeap() + { + } + + internal int Add(Guid guid) + { + Debug.Assert(!frozen); + list.Add(guid); + return list.Count; + } + + protected override int GetLength() + { + return list.Count * 16; + } + + protected override void WriteImpl(MetadataWriter mw) + { + foreach (Guid guid in list) + { + mw.Write(guid.ToByteArray()); + } + } + } + + sealed class BlobHeap : SimpleHeap + { + private Key[] map = new Key[8179]; + private readonly ByteBuffer buf = new ByteBuffer(32); + + private struct Key + { + internal Key[] next; + internal int len; + internal int hash; + internal int offset; + } + + internal BlobHeap() + { + buf.Write((byte)0); + } + + internal int Add(ByteBuffer bb) + { + Debug.Assert(!frozen); + int bblen = bb.Length; + if (bblen == 0) + { + return 0; + } + int lenlen = MetadataWriter.GetCompressedUIntLength(bblen); + int hash = bb.Hash(); + int index = (hash & 0x7FFFFFFF) % map.Length; + Key[] keys = map; + int last = index; + while (keys[index].offset != 0) + { + if (keys[index].hash == hash + && keys[index].len == bblen + && buf.Match(keys[index].offset + lenlen, bb, 0, bblen)) + { + return keys[index].offset; + } + if (index == last) + { + if (keys[index].next == null) + { + keys[index].next = new Key[4]; + keys = keys[index].next; + index = 0; + break; + } + keys = keys[index].next; + index = -1; + last = keys.Length - 1; + } + index++; + } + int offset = buf.Position; + buf.WriteCompressedUInt(bblen); + buf.Write(bb); + keys[index].len = bblen; + keys[index].hash = hash; + keys[index].offset = offset; + return offset; + } + + protected override int GetLength() + { + return buf.Position; + } + + protected override void WriteImpl(MetadataWriter mw) + { + mw.Write(buf); + } + + internal bool IsEmpty + { + get { return buf.Position == 1; } + } + + internal IKVM.Reflection.Reader.ByteReader GetBlob(int blobIndex) + { + return buf.GetBlob(blobIndex); + } + } +} diff --git a/reflect/Writer/MetadataWriter.cs b/reflect/Writer/MetadataWriter.cs new file mode 100644 index 0000000..9f20571 --- /dev/null +++ b/reflect/Writer/MetadataWriter.cs @@ -0,0 +1,575 @@ +/* + Copyright (C) 2008 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.IO; +using System.Collections.Generic; +using System.Text; +using IKVM.Reflection.Emit; +using IKVM.Reflection.Metadata; + +namespace IKVM.Reflection.Writer +{ + sealed class MetadataWriter : MetadataRW + { + private readonly ModuleBuilder moduleBuilder; + private readonly Stream stream; + private readonly byte[] buffer = new byte[8]; + + internal MetadataWriter(ModuleBuilder module, Stream stream) + : base(module, module.Strings.IsBig, module.Guids.IsBig, module.Blobs.IsBig) + { + this.moduleBuilder = module; + this.stream = stream; + } + + internal ModuleBuilder ModuleBuilder + { + get { return moduleBuilder; } + } + + internal int Position + { + get { return (int)stream.Position; } + } + + internal void Write(ByteBuffer bb) + { + bb.WriteTo(stream); + } + + internal void WriteAsciiz(string value) + { + foreach (char c in value) + { + stream.WriteByte((byte)c); + } + stream.WriteByte(0); + } + + internal void Write(byte[] value) + { + stream.Write(value, 0, value.Length); + } + + internal void Write(byte[] buffer, int offset, int count) + { + stream.Write(buffer, offset, count); + } + + internal void Write(byte value) + { + stream.WriteByte(value); + } + + internal void Write(ushort value) + { + Write((short)value); + } + + internal void Write(short value) + { + stream.WriteByte((byte)value); + stream.WriteByte((byte)(value >> 8)); + } + + internal void Write(uint value) + { + Write((int)value); + } + + internal void Write(int value) + { + buffer[0] = (byte)value; + buffer[1] = (byte)(value >> 8); + buffer[2] = (byte)(value >> 16); + buffer[3] = (byte)(value >> 24); + stream.Write(buffer, 0, 4); + } + + internal void Write(ulong value) + { + Write((long)value); + } + + internal void Write(long value) + { + buffer[0] = (byte)value; + buffer[1] = (byte)(value >> 8); + buffer[2] = (byte)(value >> 16); + buffer[3] = (byte)(value >> 24); + buffer[4] = (byte)(value >> 32); + buffer[5] = (byte)(value >> 40); + buffer[6] = (byte)(value >> 48); + buffer[7] = (byte)(value >> 56); + stream.Write(buffer, 0, 8); + } + + internal void WriteCompressedUInt(int value) + { + if (value <= 0x7F) + { + Write((byte)value); + } + else if (value <= 0x3FFF) + { + Write((byte)(0x80 | (value >> 8))); + Write((byte)value); + } + else + { + Write((byte)(0xC0 | (value >> 24))); + Write((byte)(value >> 16)); + Write((byte)(value >> 8)); + Write((byte)value); + } + } + + internal static int GetCompressedUIntLength(int value) + { + if (value <= 0x7F) + { + return 1; + } + else if (value <= 0x3FFF) + { + return 2; + } + else + { + return 4; + } + } + + internal void WriteStringIndex(int index) + { + if (bigStrings) + { + Write(index); + } + else + { + Write((short)index); + } + } + + internal void WriteGuidIndex(int index) + { + if (bigGuids) + { + Write(index); + } + else + { + Write((short)index); + } + } + + internal void WriteBlobIndex(int index) + { + if (bigBlobs) + { + Write(index); + } + else + { + Write((short)index); + } + } + + internal void WriteTypeDefOrRef(int token) + { + switch (token >> 24) + { + case 0: + break; + case TypeDefTable.Index: + token = (token & 0xFFFFFF) << 2 | 0; + break; + case TypeRefTable.Index: + token = (token & 0xFFFFFF) << 2 | 1; + break; + case TypeSpecTable.Index: + token = (token & 0xFFFFFF) << 2 | 2; + break; + default: + throw new InvalidOperationException(); + } + if (bigTypeDefOrRef) + { + Write(token); + } + else + { + Write((short)token); + } + } + + internal void WriteEncodedTypeDefOrRef(int encodedToken) + { + if (bigTypeDefOrRef) + { + Write(encodedToken); + } + else + { + Write((short)encodedToken); + } + } + + internal void WriteHasCustomAttribute(int token) + { + int encodedToken = CustomAttributeTable.EncodeHasCustomAttribute(token); + if (bigHasCustomAttribute) + { + Write(encodedToken); + } + else + { + Write((short)encodedToken); + } + } + + internal void WriteCustomAttributeType(int token) + { + switch (token >> 24) + { + case MethodDefTable.Index: + token = (token & 0xFFFFFF) << 3 | 2; + break; + case MemberRefTable.Index: + token = (token & 0xFFFFFF) << 3 | 3; + break; + default: + throw new InvalidOperationException(); + } + if (bigCustomAttributeType) + { + Write(token); + } + else + { + Write((short)token); + } + } + + internal void WriteField(int index) + { + if (bigField) + { + Write(index & 0xFFFFFF); + } + else + { + Write((short)index); + } + } + + internal void WriteMethodDef(int index) + { + if (bigMethodDef) + { + Write(index & 0xFFFFFF); + } + else + { + Write((short)index); + } + } + + internal void WriteParam(int index) + { + if (bigParam) + { + Write(index & 0xFFFFFF); + } + else + { + Write((short)index); + } + } + + internal void WriteTypeDef(int index) + { + if (bigTypeDef) + { + Write(index & 0xFFFFFF); + } + else + { + Write((short)index); + } + } + + internal void WriteEvent(int index) + { + if (bigEvent) + { + Write(index & 0xFFFFFF); + } + else + { + Write((short)index); + } + } + + internal void WriteProperty(int index) + { + if (bigProperty) + { + Write(index & 0xFFFFFF); + } + else + { + Write((short)index); + } + } + + internal void WriteGenericParam(int index) + { + if (bigGenericParam) + { + Write(index & 0xFFFFFF); + } + else + { + Write((short)index); + } + } + + internal void WriteModuleRef(int index) + { + if (bigModuleRef) + { + Write(index & 0xFFFFFF); + } + else + { + Write((short)index); + } + } + + internal void WriteResolutionScope(int token) + { + switch (token >> 24) + { + case ModuleTable.Index: + token = (token & 0xFFFFFF) << 2 | 0; + break; + case ModuleRefTable.Index: + token = (token & 0xFFFFFF) << 2 | 1; + break; + case AssemblyRefTable.Index: + token = (token & 0xFFFFFF) << 2 | 2; + break; + case TypeRefTable.Index: + token = (token & 0xFFFFFF) << 2 | 3; + break; + default: + throw new InvalidOperationException(); + } + if (bigResolutionScope) + { + Write(token); + } + else + { + Write((short)token); + } + } + + internal void WriteMemberRefParent(int token) + { + switch (token >> 24) + { + case TypeDefTable.Index: + token = (token & 0xFFFFFF) << 3 | 0; + break; + case TypeRefTable.Index: + token = (token & 0xFFFFFF) << 3 | 1; + break; + case ModuleRefTable.Index: + token = (token & 0xFFFFFF) << 3 | 2; + break; + case MethodDefTable.Index: + token = (token & 0xFFFFFF) << 3 | 3; + break; + case TypeSpecTable.Index: + token = (token & 0xFFFFFF) << 3 | 4; + break; + default: + throw new InvalidOperationException(); + } + if (bigMemberRefParent) + { + Write(token); + } + else + { + Write((short)token); + } + } + + internal void WriteMethodDefOrRef(int token) + { + switch (token >> 24) + { + case MethodDefTable.Index: + token = (token & 0xFFFFFF) << 1 | 0; + break; + case MemberRefTable.Index: + token = (token & 0xFFFFFF) << 1 | 1; + break; + default: + throw new InvalidOperationException(); + } + if (bigMethodDefOrRef) + { + Write(token); + } + else + { + Write((short)token); + } + } + + internal void WriteHasConstant(int token) + { + int encodedToken = ConstantTable.EncodeHasConstant(token); + if (bigHasConstant) + { + Write(encodedToken); + } + else + { + Write((short)encodedToken); + } + } + + internal void WriteHasSemantics(int encodedToken) + { + // NOTE because we've already had to do the encoding (to be able to sort the table) + // here we simple write the value + if (bigHasSemantics) + { + Write(encodedToken); + } + else + { + Write((short)encodedToken); + } + } + + internal void WriteImplementation(int token) + { + switch (token >> 24) + { + case 0: + break; + case FileTable.Index: + token = (token & 0xFFFFFF) << 2 | 0; + break; + case AssemblyRefTable.Index: + token = (token & 0xFFFFFF) << 2 | 1; + break; + case ExportedTypeTable.Index: + token = (token & 0xFFFFFF) << 2 | 2; + break; + default: + throw new InvalidOperationException(); + } + if (bigImplementation) + { + Write(token); + } + else + { + Write((short)token); + } + } + + internal void WriteTypeOrMethodDef(int encodedToken) + { + // NOTE because we've already had to do the encoding (to be able to sort the table) + // here we simple write the value + if (bigTypeOrMethodDef) + { + Write(encodedToken); + } + else + { + Write((short)encodedToken); + } + } + + internal void WriteHasDeclSecurity(int encodedToken) + { + // NOTE because we've already had to do the encoding (to be able to sort the table) + // here we simple write the value + if (bigHasDeclSecurity) + { + Write(encodedToken); + } + else + { + Write((short)encodedToken); + } + } + + internal void WriteMemberForwarded(int token) + { + switch (token >> 24) + { + case FieldTable.Index: + token = (token & 0xFFFFFF) << 1 | 0; + break; + case MethodDefTable.Index: + token = (token & 0xFFFFFF) << 1 | 1; + break; + default: + throw new InvalidOperationException(); + } + if (bigMemberForwarded) + { + Write(token); + } + else + { + Write((short)token); + } + } + + internal void WriteHasFieldMarshal(int token) + { + int encodedToken = FieldMarshalTable.EncodeHasFieldMarshal(token); + if (bigHasFieldMarshal) + { + Write(encodedToken); + } + else + { + Write((short)encodedToken); + } + } + } +} diff --git a/reflect/Writer/ModuleWriter.cs b/reflect/Writer/ModuleWriter.cs new file mode 100644 index 0000000..7ef9c6d --- /dev/null +++ b/reflect/Writer/ModuleWriter.cs @@ -0,0 +1,463 @@ +/* + Copyright (C) 2008-2015 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Security.Cryptography; +using IKVM.Reflection.Emit; +using IKVM.Reflection.Impl; +using IKVM.Reflection.Metadata; + +namespace IKVM.Reflection.Writer +{ + static class ModuleWriter + { + internal static void WriteModule(StrongNameKeyPair keyPair, byte[] publicKey, ModuleBuilder moduleBuilder, + PEFileKinds fileKind, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine, + ResourceSection resources, int entryPointToken) + { + WriteModule(keyPair, publicKey, moduleBuilder, fileKind, portableExecutableKind, imageFileMachine, resources, entryPointToken, null); + } + + internal static void WriteModule(StrongNameKeyPair keyPair, byte[] publicKey, ModuleBuilder moduleBuilder, + PEFileKinds fileKind, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine, + ResourceSection resources, int entryPointToken, Stream stream) + { + if (stream == null) + { + string fileName = moduleBuilder.FullyQualifiedName; + bool mono = System.Type.GetType("Mono.Runtime") != null; + if (mono) + { + try + { + // Mono mmaps the file, so unlink the previous version since it may be in use + File.Delete(fileName); + } + catch { } + } + using (FileStream fs = new FileStream(fileName, FileMode.Create)) + { + WriteModuleImpl(keyPair, publicKey, moduleBuilder, fileKind, portableExecutableKind, imageFileMachine, resources, entryPointToken, fs); + } + // if we're running on Mono, mark the module as executable by using a Mono private API extension + if (mono) + { + File.SetAttributes(fileName, (FileAttributes)(unchecked((int)0x80000000))); + } + } + else + { + WriteModuleImpl(keyPair, publicKey, moduleBuilder, fileKind, portableExecutableKind, imageFileMachine, resources, entryPointToken, stream); + } + } + + private static void WriteModuleImpl(StrongNameKeyPair keyPair, byte[] publicKey, ModuleBuilder moduleBuilder, + PEFileKinds fileKind, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine, + ResourceSection resources, int entryPointToken, Stream stream) + { + moduleBuilder.ApplyUnmanagedExports(imageFileMachine); + moduleBuilder.FixupMethodBodyTokens(); + + int moduleVersionIdIndex = moduleBuilder.Guids.Add(moduleBuilder.GetModuleVersionIdOrEmpty()); + moduleBuilder.ModuleTable.Add(0, moduleBuilder.Strings.Add(moduleBuilder.moduleName), moduleVersionIdIndex, 0, 0); + + if (moduleBuilder.UserStrings.IsEmpty) + { + // for compat with Ref.Emit, if there aren't any user strings, we add one + moduleBuilder.UserStrings.Add(" "); + } + + if (resources != null) + { + resources.Finish(); + } + + PEWriter writer = new PEWriter(stream); + writer.Headers.OptionalHeader.FileAlignment = (uint)moduleBuilder.__FileAlignment; + switch (imageFileMachine) + { + case ImageFileMachine.I386: + writer.Headers.FileHeader.Machine = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386; + writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_32BIT_MACHINE; + writer.Headers.OptionalHeader.SizeOfStackReserve = moduleBuilder.GetStackReserve(0x100000); + break; + case ImageFileMachine.ARM: + writer.Headers.FileHeader.Machine = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_ARM; + writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_HEADER.IMAGE_FILE_LARGE_ADDRESS_AWARE; + writer.Headers.OptionalHeader.SizeOfStackReserve = moduleBuilder.GetStackReserve(0x100000); + writer.Headers.OptionalHeader.SectionAlignment = 0x1000; + break; + case ImageFileMachine.AMD64: + writer.Headers.FileHeader.Machine = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64; + writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_LARGE_ADDRESS_AWARE; + writer.Headers.FileHeader.SizeOfOptionalHeader = 0xF0; + writer.Headers.OptionalHeader.Magic = IMAGE_OPTIONAL_HEADER.IMAGE_NT_OPTIONAL_HDR64_MAGIC; + writer.Headers.OptionalHeader.SizeOfStackReserve = moduleBuilder.GetStackReserve(0x400000); + writer.Headers.OptionalHeader.SizeOfStackCommit = 0x4000; + writer.Headers.OptionalHeader.SizeOfHeapCommit = 0x2000; + break; + case ImageFileMachine.IA64: + writer.Headers.FileHeader.Machine = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64; + writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_LARGE_ADDRESS_AWARE; + writer.Headers.FileHeader.SizeOfOptionalHeader = 0xF0; + writer.Headers.OptionalHeader.Magic = IMAGE_OPTIONAL_HEADER.IMAGE_NT_OPTIONAL_HDR64_MAGIC; + writer.Headers.OptionalHeader.SizeOfStackReserve = moduleBuilder.GetStackReserve(0x400000); + writer.Headers.OptionalHeader.SizeOfStackCommit = 0x4000; + writer.Headers.OptionalHeader.SizeOfHeapCommit = 0x2000; + break; + default: + throw new ArgumentOutOfRangeException("imageFileMachine"); + } + if (fileKind == PEFileKinds.Dll) + { + writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_DLL; + } + + switch (fileKind) + { + case PEFileKinds.WindowApplication: + writer.Headers.OptionalHeader.Subsystem = IMAGE_OPTIONAL_HEADER.IMAGE_SUBSYSTEM_WINDOWS_GUI; + break; + default: + writer.Headers.OptionalHeader.Subsystem = IMAGE_OPTIONAL_HEADER.IMAGE_SUBSYSTEM_WINDOWS_CUI; + break; + } + writer.Headers.OptionalHeader.DllCharacteristics = (ushort)moduleBuilder.__DllCharacteristics; + + CliHeader cliHeader = new CliHeader(); + cliHeader.Cb = 0x48; + cliHeader.MajorRuntimeVersion = 2; + cliHeader.MinorRuntimeVersion = moduleBuilder.MDStreamVersion < 0x20000 ? (ushort)0 : (ushort)5; + if ((portableExecutableKind & PortableExecutableKinds.ILOnly) != 0) + { + cliHeader.Flags |= CliHeader.COMIMAGE_FLAGS_ILONLY; + } + if ((portableExecutableKind & PortableExecutableKinds.Required32Bit) != 0) + { + cliHeader.Flags |= CliHeader.COMIMAGE_FLAGS_32BITREQUIRED; + } + if ((portableExecutableKind & PortableExecutableKinds.Preferred32Bit) != 0) + { + cliHeader.Flags |= CliHeader.COMIMAGE_FLAGS_32BITREQUIRED | CliHeader.COMIMAGE_FLAGS_32BITPREFERRED; + } + if (keyPair != null) + { + cliHeader.Flags |= CliHeader.COMIMAGE_FLAGS_STRONGNAMESIGNED; + } + if (ModuleBuilder.IsPseudoToken(entryPointToken)) + { + entryPointToken = moduleBuilder.ResolvePseudoToken(entryPointToken); + } + cliHeader.EntryPointToken = (uint)entryPointToken; + + moduleBuilder.Strings.Freeze(); + moduleBuilder.UserStrings.Freeze(); + moduleBuilder.Guids.Freeze(); + moduleBuilder.Blobs.Freeze(); + MetadataWriter mw = new MetadataWriter(moduleBuilder, stream); + moduleBuilder.Tables.Freeze(mw); + TextSection code = new TextSection(writer, cliHeader, moduleBuilder, ComputeStrongNameSignatureLength(publicKey)); + + // Export Directory + if (code.ExportDirectoryLength != 0) + { + writer.Headers.OptionalHeader.DataDirectory[0].VirtualAddress = code.ExportDirectoryRVA; + writer.Headers.OptionalHeader.DataDirectory[0].Size = code.ExportDirectoryLength; + } + + // Import Directory + if (code.ImportDirectoryLength != 0) + { + writer.Headers.OptionalHeader.DataDirectory[1].VirtualAddress = code.ImportDirectoryRVA; + writer.Headers.OptionalHeader.DataDirectory[1].Size = code.ImportDirectoryLength; + } + + // Import Address Table Directory + if (code.ImportAddressTableLength != 0) + { + writer.Headers.OptionalHeader.DataDirectory[12].VirtualAddress = code.ImportAddressTableRVA; + writer.Headers.OptionalHeader.DataDirectory[12].Size = code.ImportAddressTableLength; + } + + // COM Descriptor Directory + writer.Headers.OptionalHeader.DataDirectory[14].VirtualAddress = code.ComDescriptorRVA; + writer.Headers.OptionalHeader.DataDirectory[14].Size = code.ComDescriptorLength; + + // Debug Directory + if (code.DebugDirectoryLength != 0) + { + writer.Headers.OptionalHeader.DataDirectory[6].VirtualAddress = code.DebugDirectoryRVA; + writer.Headers.OptionalHeader.DataDirectory[6].Size = code.DebugDirectoryLength; + } + + // Set the PE File timestamp + writer.Headers.FileHeader.TimeDateStamp = moduleBuilder.GetTimeDateStamp(); + + // we need to start by computing the number of sections, because code.PointerToRawData depends on that + writer.Headers.FileHeader.NumberOfSections = 2; + + if (moduleBuilder.initializedData.Length != 0) + { + // .sdata + writer.Headers.FileHeader.NumberOfSections++; + } + + if (resources != null) + { + // .rsrc + writer.Headers.FileHeader.NumberOfSections++; + } + + SectionHeader text = new SectionHeader(); + text.Name = ".text"; + text.VirtualAddress = code.BaseRVA; + text.VirtualSize = (uint)code.Length; + text.PointerToRawData = code.PointerToRawData; + text.SizeOfRawData = writer.ToFileAlignment((uint)code.Length); + text.Characteristics = SectionHeader.IMAGE_SCN_CNT_CODE | SectionHeader.IMAGE_SCN_MEM_EXECUTE | SectionHeader.IMAGE_SCN_MEM_READ; + + SectionHeader sdata = new SectionHeader(); + sdata.Name = ".sdata"; + sdata.VirtualAddress = text.VirtualAddress + writer.ToSectionAlignment(text.VirtualSize); + sdata.VirtualSize = (uint)moduleBuilder.initializedData.Length; + sdata.PointerToRawData = text.PointerToRawData + text.SizeOfRawData; + sdata.SizeOfRawData = writer.ToFileAlignment((uint)moduleBuilder.initializedData.Length); + sdata.Characteristics = SectionHeader.IMAGE_SCN_CNT_INITIALIZED_DATA | SectionHeader.IMAGE_SCN_MEM_READ | SectionHeader.IMAGE_SCN_MEM_WRITE; + + SectionHeader rsrc = new SectionHeader(); + rsrc.Name = ".rsrc"; + rsrc.VirtualAddress = sdata.VirtualAddress + writer.ToSectionAlignment(sdata.VirtualSize); + rsrc.PointerToRawData = sdata.PointerToRawData + sdata.SizeOfRawData; + rsrc.VirtualSize = resources == null ? 0 : (uint)resources.Length; + rsrc.SizeOfRawData = writer.ToFileAlignment(rsrc.VirtualSize); + rsrc.Characteristics = SectionHeader.IMAGE_SCN_MEM_READ | SectionHeader.IMAGE_SCN_CNT_INITIALIZED_DATA; + + if (rsrc.SizeOfRawData != 0) + { + // Resource Directory + writer.Headers.OptionalHeader.DataDirectory[2].VirtualAddress = rsrc.VirtualAddress; + writer.Headers.OptionalHeader.DataDirectory[2].Size = rsrc.VirtualSize; + } + + SectionHeader reloc = new SectionHeader(); + reloc.Name = ".reloc"; + reloc.VirtualAddress = rsrc.VirtualAddress + writer.ToSectionAlignment(rsrc.VirtualSize); + reloc.VirtualSize = code.PackRelocations(); + reloc.PointerToRawData = rsrc.PointerToRawData + rsrc.SizeOfRawData; + reloc.SizeOfRawData = writer.ToFileAlignment(reloc.VirtualSize); + reloc.Characteristics = SectionHeader.IMAGE_SCN_MEM_READ | SectionHeader.IMAGE_SCN_CNT_INITIALIZED_DATA | SectionHeader.IMAGE_SCN_MEM_DISCARDABLE; + + if (reloc.SizeOfRawData != 0) + { + // Base Relocation Directory + writer.Headers.OptionalHeader.DataDirectory[5].VirtualAddress = reloc.VirtualAddress; + writer.Headers.OptionalHeader.DataDirectory[5].Size = reloc.VirtualSize; + } + + writer.Headers.OptionalHeader.SizeOfCode = text.SizeOfRawData; + writer.Headers.OptionalHeader.SizeOfInitializedData = sdata.SizeOfRawData + rsrc.SizeOfRawData + reloc.SizeOfRawData; + writer.Headers.OptionalHeader.SizeOfUninitializedData = 0; + writer.Headers.OptionalHeader.SizeOfImage = reloc.VirtualAddress + writer.ToSectionAlignment(reloc.VirtualSize); + writer.Headers.OptionalHeader.SizeOfHeaders = text.PointerToRawData; + writer.Headers.OptionalHeader.BaseOfCode = code.BaseRVA; + writer.Headers.OptionalHeader.BaseOfData = sdata.VirtualAddress; + writer.Headers.OptionalHeader.ImageBase = (ulong)moduleBuilder.__ImageBase; + + if (imageFileMachine == ImageFileMachine.IA64) + { + // apparently for IA64 AddressOfEntryPoint points to the address of the entry point + // (i.e. there is an additional layer of indirection), so we add the offset to the pointer + writer.Headers.OptionalHeader.AddressOfEntryPoint = code.StartupStubRVA + 0x20; + } + else + { + writer.Headers.OptionalHeader.AddressOfEntryPoint = code.StartupStubRVA + writer.Thumb; + } + + writer.WritePEHeaders(); + writer.WriteSectionHeader(text); + if (sdata.SizeOfRawData != 0) + { + writer.WriteSectionHeader(sdata); + } + if (rsrc.SizeOfRawData != 0) + { + writer.WriteSectionHeader(rsrc); + } + if (reloc.SizeOfRawData != 0) + { + writer.WriteSectionHeader(reloc); + } + + stream.Seek(text.PointerToRawData, SeekOrigin.Begin); + int guidHeapOffset; + code.Write(mw, sdata.VirtualAddress, out guidHeapOffset); + + if (sdata.SizeOfRawData != 0) + { + stream.Seek(sdata.PointerToRawData, SeekOrigin.Begin); + mw.Write(moduleBuilder.initializedData); + } + + if (rsrc.SizeOfRawData != 0) + { + stream.Seek(rsrc.PointerToRawData, SeekOrigin.Begin); + resources.Write(mw, rsrc.VirtualAddress); + } + + if (reloc.SizeOfRawData != 0) + { + stream.Seek(reloc.PointerToRawData, SeekOrigin.Begin); + code.WriteRelocations(mw); + } + + // file alignment + stream.SetLength(reloc.PointerToRawData + reloc.SizeOfRawData); + + // if we don't have a guid, generate one based on the contents of the assembly + if (moduleBuilder.universe.Deterministic && moduleBuilder.GetModuleVersionIdOrEmpty() == Guid.Empty) + { + Guid guid = GenerateModuleVersionId(stream); + stream.Position = guidHeapOffset + (moduleVersionIdIndex - 1) * 16; + stream.Write(guid.ToByteArray(), 0, 16); + moduleBuilder.__SetModuleVersionId(guid); + } + + // do the strong naming + if (keyPair != null) + { + StrongName(stream, keyPair, writer.HeaderSize, text.PointerToRawData, code.StrongNameSignatureRVA - text.VirtualAddress + text.PointerToRawData, code.StrongNameSignatureLength); + } + +#if !NO_SYMBOL_WRITER + if (moduleBuilder.symbolWriter != null) + { + moduleBuilder.WriteSymbolTokenMap(); + moduleBuilder.symbolWriter.Close(); + } +#endif + } + + private static int ComputeStrongNameSignatureLength(byte[] publicKey) + { + if (publicKey == null) + { + return 0; + } + else if (publicKey.Length == 16) + { + // it must be the ECMA pseudo public key, we don't know the key size of the real key, but currently both Mono and Microsoft use a 1024 bit key size + return 128; + } + else + { + // for the supported strong naming algorithms, the signature size is the same as the key size + // (we have to subtract 32 for the header) + return publicKey.Length - 32; + } + } + + private static void StrongName(Stream stream, StrongNameKeyPair keyPair, uint headerLength, uint textSectionFileOffset, uint strongNameSignatureFileOffset, uint strongNameSignatureLength) + { + SHA1Managed hash = new SHA1Managed(); + using (CryptoStream cs = new CryptoStream(Stream.Null, hash, CryptoStreamMode.Write)) + { + stream.Seek(0, SeekOrigin.Begin); + byte[] buf = new byte[8192]; + HashChunk(stream, cs, buf, (int)headerLength); + stream.Seek(textSectionFileOffset, SeekOrigin.Begin); + HashChunk(stream, cs, buf, (int)(strongNameSignatureFileOffset - textSectionFileOffset)); + stream.Seek(strongNameSignatureLength, SeekOrigin.Current); + HashChunk(stream, cs, buf, (int)(stream.Length - (strongNameSignatureFileOffset + strongNameSignatureLength))); + } + using (RSA rsa = keyPair.CreateRSA()) + { + RSAPKCS1SignatureFormatter sign = new RSAPKCS1SignatureFormatter(rsa); + byte[] signature = sign.CreateSignature(hash); + Array.Reverse(signature); + if (signature.Length != strongNameSignatureLength) + { + throw new InvalidOperationException("Signature length mismatch"); + } + stream.Seek(strongNameSignatureFileOffset, SeekOrigin.Begin); + stream.Write(signature, 0, signature.Length); + } + + // compute the PE checksum + stream.Seek(0, SeekOrigin.Begin); + int count = (int)stream.Length / 4; + BinaryReader br = new BinaryReader(stream); + long sum = 0; + for (int i = 0; i < count; i++) + { + sum += br.ReadUInt32(); + int carry = (int)(sum >> 32); + sum &= 0xFFFFFFFFU; + sum += carry; + } + while ((sum >> 16) != 0) + { + sum = (sum & 0xFFFF) + (sum >> 16); + } + sum += stream.Length; + + // write the PE checksum, note that it is always at offset 0xD8 in the file + ByteBuffer bb = new ByteBuffer(4); + bb.Write((int)sum); + stream.Seek(0xD8, SeekOrigin.Begin); + bb.WriteTo(stream); + } + + internal static void HashChunk(Stream stream, CryptoStream cs, byte[] buf, int length) + { + while (length > 0) + { + int read = stream.Read(buf, 0, Math.Min(buf.Length, length)); + cs.Write(buf, 0, read); + length -= read; + } + } + + private static Guid GenerateModuleVersionId(Stream stream) + { + SHA1Managed hash = new SHA1Managed(); + using (CryptoStream cs = new CryptoStream(Stream.Null, hash, CryptoStreamMode.Write)) + { + stream.Seek(0, SeekOrigin.Begin); + byte[] buf = new byte[8192]; + HashChunk(stream, cs, buf, (int)stream.Length); + } + byte[] bytes = new byte[16]; + Buffer.BlockCopy(hash.Hash, 0, bytes, 0, bytes.Length); + // set GUID type to "version 4" (random) + bytes[7] &= 0x0F; + bytes[7] |= 0x40; + bytes[8] &= 0x3F; + bytes[8] |= 0x80; + return new Guid(bytes); + } + } +} diff --git a/reflect/Writer/PEWriter.cs b/reflect/Writer/PEWriter.cs new file mode 100644 index 0000000..1f441e8 --- /dev/null +++ b/reflect/Writer/PEWriter.cs @@ -0,0 +1,287 @@ +/* + Copyright (C) 2008-2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.IO; +using BYTE = System.Byte; +using WORD = System.UInt16; +using DWORD = System.UInt32; +using ULONGLONG = System.UInt64; +using IMAGE_DATA_DIRECTORY = IKVM.Reflection.Reader.IMAGE_DATA_DIRECTORY; + +namespace IKVM.Reflection.Writer +{ + sealed class PEWriter + { + private readonly BinaryWriter bw; + private readonly IMAGE_NT_HEADERS hdr = new IMAGE_NT_HEADERS(); + + internal PEWriter(Stream stream) + { + bw = new BinaryWriter(stream); + WriteMSDOSHeader(); + } + + public IMAGE_NT_HEADERS Headers + { + get { return hdr; } + } + + public uint HeaderSize + { + get + { + return (uint) + ((8 * 16) + // MSDOS header + 4 + // signature + 20 + // IMAGE_FILE_HEADER + hdr.FileHeader.SizeOfOptionalHeader + + hdr.FileHeader.NumberOfSections * 40); + } + } + + private void WriteMSDOSHeader() + { + bw.Write(new byte[] { + 0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, + 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD, + 0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x54, 0x68, + 0x69, 0x73, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, + 0x61, 0x6D, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, + 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6E, + 0x20, 0x69, 0x6E, 0x20, 0x44, 0x4F, 0x53, 0x20, + 0x6D, 0x6F, 0x64, 0x65, 0x2E, 0x0D, 0x0D, 0x0A, + 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }); + } + + internal void WritePEHeaders() + { + bw.Write(hdr.Signature); + + // IMAGE_FILE_HEADER + bw.Write(hdr.FileHeader.Machine); + bw.Write(hdr.FileHeader.NumberOfSections); + bw.Write(hdr.FileHeader.TimeDateStamp); + bw.Write(hdr.FileHeader.PointerToSymbolTable); + bw.Write(hdr.FileHeader.NumberOfSymbols); + bw.Write(hdr.FileHeader.SizeOfOptionalHeader); + bw.Write(hdr.FileHeader.Characteristics); + + // IMAGE_OPTIONAL_HEADER + hdr.OptionalHeader.Write(bw); + } + + internal void WriteSectionHeader(SectionHeader sectionHeader) + { + byte[] name = new byte[8]; + System.Text.Encoding.UTF8.GetBytes(sectionHeader.Name, 0, sectionHeader.Name.Length, name, 0); + bw.Write(name); + bw.Write(sectionHeader.VirtualSize); + bw.Write(sectionHeader.VirtualAddress); + bw.Write(sectionHeader.SizeOfRawData); + bw.Write(sectionHeader.PointerToRawData); + bw.Write(sectionHeader.PointerToRelocations); + bw.Write(sectionHeader.PointerToLinenumbers); + bw.Write(sectionHeader.NumberOfRelocations); + bw.Write(sectionHeader.NumberOfLinenumbers); + bw.Write(sectionHeader.Characteristics); + } + + internal uint ToFileAlignment(uint p) + { + return (p + (Headers.OptionalHeader.FileAlignment - 1)) & ~(Headers.OptionalHeader.FileAlignment - 1); + } + + internal uint ToSectionAlignment(uint p) + { + return (p + (Headers.OptionalHeader.SectionAlignment - 1)) & ~(Headers.OptionalHeader.SectionAlignment - 1); + } + + internal bool Is32Bit + { + get { return (Headers.FileHeader.Characteristics & IMAGE_FILE_HEADER.IMAGE_FILE_32BIT_MACHINE) != 0; } + } + + internal uint Thumb + { + // On ARM we need to set the least significant bit of the program counter to select the Thumb instruction set + get { return Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_ARM ? 1u : 0u; } + } + } + + sealed class IMAGE_NT_HEADERS + { + public DWORD Signature = 0x00004550; // "PE\0\0" + public IMAGE_FILE_HEADER FileHeader = new IMAGE_FILE_HEADER(); + public IMAGE_OPTIONAL_HEADER OptionalHeader = new IMAGE_OPTIONAL_HEADER(); + } + + sealed class IMAGE_FILE_HEADER + { + public const WORD IMAGE_FILE_MACHINE_I386 = 0x014c; + public const WORD IMAGE_FILE_MACHINE_ARM = 0x01c4; + public const WORD IMAGE_FILE_MACHINE_IA64 = 0x0200; + public const WORD IMAGE_FILE_MACHINE_AMD64 = 0x8664; + + public const WORD IMAGE_FILE_32BIT_MACHINE = 0x0100; + public const WORD IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002; + public const WORD IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020; + public const WORD IMAGE_FILE_DLL = 0x2000; + + public WORD Machine; + public WORD NumberOfSections; + public DWORD TimeDateStamp; + public DWORD PointerToSymbolTable = 0; + public DWORD NumberOfSymbols = 0; + public WORD SizeOfOptionalHeader = 0xE0; + public WORD Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE; + } + + sealed class IMAGE_OPTIONAL_HEADER + { + public const WORD IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b; + public const WORD IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b; + + public const WORD IMAGE_SUBSYSTEM_WINDOWS_GUI = 2; + public const WORD IMAGE_SUBSYSTEM_WINDOWS_CUI = 3; + + public WORD Magic = IMAGE_NT_OPTIONAL_HDR32_MAGIC; + public BYTE MajorLinkerVersion = 8; + public BYTE MinorLinkerVersion = 0; + public DWORD SizeOfCode; + public DWORD SizeOfInitializedData; + public DWORD SizeOfUninitializedData; + public DWORD AddressOfEntryPoint; + public DWORD BaseOfCode; + public DWORD BaseOfData; + public ULONGLONG ImageBase; + public DWORD SectionAlignment = 0x2000; + public DWORD FileAlignment; + public WORD MajorOperatingSystemVersion = 4; + public WORD MinorOperatingSystemVersion = 0; + public WORD MajorImageVersion = 0; + public WORD MinorImageVersion = 0; + public WORD MajorSubsystemVersion = 4; + public WORD MinorSubsystemVersion = 0; + public DWORD Win32VersionValue = 0; + public DWORD SizeOfImage; + public DWORD SizeOfHeaders; + public DWORD CheckSum = 0; + public WORD Subsystem; + public WORD DllCharacteristics; + public ULONGLONG SizeOfStackReserve; + public ULONGLONG SizeOfStackCommit = 0x1000; + public ULONGLONG SizeOfHeapReserve = 0x100000; + public ULONGLONG SizeOfHeapCommit = 0x1000; + public DWORD LoaderFlags = 0; + public DWORD NumberOfRvaAndSizes = 16; + public IMAGE_DATA_DIRECTORY[] DataDirectory = new IMAGE_DATA_DIRECTORY[16]; + + internal void Write(BinaryWriter bw) + { + bw.Write(Magic); + bw.Write(MajorLinkerVersion); + bw.Write(MinorLinkerVersion); + bw.Write(SizeOfCode); + bw.Write(SizeOfInitializedData); + bw.Write(SizeOfUninitializedData); + bw.Write(AddressOfEntryPoint); + bw.Write(BaseOfCode); + if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) + { + bw.Write(BaseOfData); + bw.Write((DWORD)ImageBase); + } + else + { + bw.Write(ImageBase); + } + bw.Write(SectionAlignment); + bw.Write(FileAlignment); + bw.Write(MajorOperatingSystemVersion); + bw.Write(MinorOperatingSystemVersion); + bw.Write(MajorImageVersion); + bw.Write(MinorImageVersion); + bw.Write(MajorSubsystemVersion); + bw.Write(MinorSubsystemVersion); + bw.Write(Win32VersionValue); + bw.Write(SizeOfImage); + bw.Write(SizeOfHeaders); + bw.Write(CheckSum); + bw.Write(Subsystem); + bw.Write(DllCharacteristics); + if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) + { + bw.Write((DWORD)SizeOfStackReserve); + bw.Write((DWORD)SizeOfStackCommit); + bw.Write((DWORD)SizeOfHeapReserve); + bw.Write((DWORD)SizeOfHeapCommit); + } + else + { + bw.Write(SizeOfStackReserve); + bw.Write(SizeOfStackCommit); + bw.Write(SizeOfHeapReserve); + bw.Write(SizeOfHeapCommit); + } + bw.Write(LoaderFlags); + bw.Write(NumberOfRvaAndSizes); + for (int i = 0; i < DataDirectory.Length; i++) + { + bw.Write(DataDirectory[i].VirtualAddress); + bw.Write(DataDirectory[i].Size); + } + } + } + + class SectionHeader + { + public const DWORD IMAGE_SCN_CNT_CODE = 0x00000020; + public const DWORD IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040; + public const DWORD IMAGE_SCN_MEM_DISCARDABLE = 0x02000000; + public const DWORD IMAGE_SCN_MEM_EXECUTE = 0x20000000; + public const DWORD IMAGE_SCN_MEM_READ = 0x40000000; + public const DWORD IMAGE_SCN_MEM_WRITE = 0x80000000; + + public string Name; // 8 byte UTF8 encoded 0-padded + public DWORD VirtualSize; + public DWORD VirtualAddress; + public DWORD SizeOfRawData; + public DWORD PointerToRawData; +#pragma warning disable 649 // the follow fields are never assigned to + public DWORD PointerToRelocations; + public DWORD PointerToLinenumbers; + public WORD NumberOfRelocations; + public WORD NumberOfLinenumbers; +#pragma warning restore 649 + public DWORD Characteristics; + } +} diff --git a/reflect/Writer/ResourceSection.cs b/reflect/Writer/ResourceSection.cs new file mode 100644 index 0000000..3789ca2 --- /dev/null +++ b/reflect/Writer/ResourceSection.cs @@ -0,0 +1,411 @@ +/* + Copyright (C) 2010-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using IKVM.Reflection.Reader; + +namespace IKVM.Reflection.Writer +{ + sealed class ResourceSection + { + private const int RT_ICON = 3; + private const int RT_GROUP_ICON = 14; + private const int RT_VERSION = 16; + private const int RT_MANIFEST = 24; + private ResourceDirectoryEntry root = new ResourceDirectoryEntry(new OrdinalOrName("root")); + private ByteBuffer bb; + private List linkOffsets; + + internal void AddVersionInfo(ByteBuffer versionInfo) + { + root[new OrdinalOrName(RT_VERSION)][new OrdinalOrName(1)][new OrdinalOrName(0)].Data = versionInfo; + } + + internal void AddIcon(byte[] iconFile) + { + BinaryReader br = new BinaryReader(new MemoryStream(iconFile)); + ushort idReserved = br.ReadUInt16(); + ushort idType = br.ReadUInt16(); + ushort idCount = br.ReadUInt16(); + if (idReserved != 0 || idType != 1) + { + throw new ArgumentException("The supplied byte array is not a valid .ico file."); + } + ByteBuffer group = new ByteBuffer(6 + 14 * idCount); + group.Write(idReserved); + group.Write(idType); + group.Write(idCount); + for (int i = 0; i < idCount; i++) + { + byte bWidth = br.ReadByte(); + byte bHeight = br.ReadByte(); + byte bColorCount = br.ReadByte(); + byte bReserved = br.ReadByte(); + ushort wPlanes = br.ReadUInt16(); + ushort wBitCount = br.ReadUInt16(); + uint dwBytesInRes = br.ReadUInt32(); + uint dwImageOffset = br.ReadUInt32(); + + // we start the icon IDs at 2 + ushort id = (ushort)(2 + i); + + group.Write(bWidth); + group.Write(bHeight); + group.Write(bColorCount); + group.Write(bReserved); + group.Write(wPlanes); + group.Write(wBitCount); + group.Write(dwBytesInRes); + group.Write(id); + + byte[] icon = new byte[dwBytesInRes]; + Buffer.BlockCopy(iconFile, (int)dwImageOffset, icon, 0, icon.Length); + root[new OrdinalOrName(RT_ICON)][new OrdinalOrName(id)][new OrdinalOrName(0)].Data = ByteBuffer.Wrap(icon); + } + root[new OrdinalOrName(RT_GROUP_ICON)][new OrdinalOrName(32512)][new OrdinalOrName(0)].Data = group; + } + + internal void AddManifest(byte[] manifest, ushort resourceID) + { + root[new OrdinalOrName(RT_MANIFEST)][new OrdinalOrName(resourceID)][new OrdinalOrName(0)].Data = ByteBuffer.Wrap(manifest); + } + + internal void ExtractResources(byte[] buf) + { + ByteReader br = new ByteReader(buf, 0, buf.Length); + while (br.Length >= 32) + { + br.Align(4); + RESOURCEHEADER hdr = new RESOURCEHEADER(br); + if (hdr.DataSize != 0) + { + root[hdr.TYPE][hdr.NAME][new OrdinalOrName(hdr.LanguageId)].Data = ByteBuffer.Wrap(br.ReadBytes(hdr.DataSize)); + } + } + } + + internal void Finish() + { + if (bb != null) + { + throw new InvalidOperationException(); + } + bb = new ByteBuffer(1024); + linkOffsets = new List(); + root.Write(bb, linkOffsets); + root = null; + } + + internal int Length + { + get { return bb.Length; } + } + + internal void Write(MetadataWriter mw, uint rva) + { + foreach (int offset in linkOffsets) + { + bb.Position = offset; + bb.Write(bb.GetInt32AtCurrentPosition() + (int)rva); + } + mw.Write(bb); + } + } + + sealed class ResourceDirectoryEntry + { + internal readonly OrdinalOrName OrdinalOrName; + internal ByteBuffer Data; + private int namedEntries; + private readonly List entries = new List(); + + internal ResourceDirectoryEntry(OrdinalOrName id) + { + this.OrdinalOrName = id; + } + + internal ResourceDirectoryEntry this[OrdinalOrName id] + { + get + { + foreach (ResourceDirectoryEntry entry in entries) + { + if (entry.OrdinalOrName.IsEqual(id)) + { + return entry; + } + } + // the entries must be sorted + ResourceDirectoryEntry newEntry = new ResourceDirectoryEntry(id); + if (id.Name == null) + { + for (int i = namedEntries; i < entries.Count; i++) + { + if (entries[i].OrdinalOrName.IsGreaterThan(id)) + { + entries.Insert(i, newEntry); + return newEntry; + } + } + entries.Add(newEntry); + return newEntry; + } + else + { + for (int i = 0; i < namedEntries; i++) + { + if (entries[i].OrdinalOrName.IsGreaterThan(id)) + { + entries.Insert(i, newEntry); + namedEntries++; + return newEntry; + } + } + entries.Insert(namedEntries++, newEntry); + return newEntry; + } + } + } + + private int DirectoryLength + { + get + { + if (Data != null) + { + return 16; + } + else + { + int length = 16 + entries.Count * 8; + foreach (ResourceDirectoryEntry entry in entries) + { + length += entry.DirectoryLength; + } + return length; + } + } + } + + internal void Write(ByteBuffer bb, List linkOffsets) + { + if (entries.Count != 0) + { + int stringTableOffset = this.DirectoryLength; + Dictionary strings = new Dictionary(); + ByteBuffer stringTable = new ByteBuffer(16); + int offset = 16 + entries.Count * 8; + for (int pass = 0; pass < 3; pass++) + { + Write(bb, pass, 0, ref offset, strings, ref stringTableOffset, stringTable); + } + // the pecoff spec says that the string table is between the directory entries and the data entries, + // but the windows linker puts them after the data entries, so we do too. + stringTable.Align(4); + offset += stringTable.Length; + WriteResourceDataEntries(bb, linkOffsets, ref offset); + bb.Write(stringTable); + WriteData(bb); + } + } + + private void WriteResourceDataEntries(ByteBuffer bb, List linkOffsets, ref int offset) + { + foreach (ResourceDirectoryEntry entry in entries) + { + if (entry.Data != null) + { + linkOffsets.Add(bb.Position); + bb.Write(offset); + bb.Write(entry.Data.Length); + bb.Write(0); // code page + bb.Write(0); // reserved + offset += (entry.Data.Length + 3) & ~3; + } + else + { + entry.WriteResourceDataEntries(bb, linkOffsets, ref offset); + } + } + } + + private void WriteData(ByteBuffer bb) + { + foreach (ResourceDirectoryEntry entry in entries) + { + if (entry.Data != null) + { + bb.Write(entry.Data); + bb.Align(4); + } + else + { + entry.WriteData(bb); + } + } + } + + private void Write(ByteBuffer bb, int writeDepth, int currentDepth, ref int offset, Dictionary strings, ref int stringTableOffset, ByteBuffer stringTable) + { + if (currentDepth == writeDepth) + { + // directory header + bb.Write(0); // Characteristics + bb.Write(0); // Time/Date Stamp + bb.Write(0); // Version (Major / Minor) + bb.Write((ushort)namedEntries); + bb.Write((ushort)(entries.Count - namedEntries)); + } + foreach (ResourceDirectoryEntry entry in entries) + { + if (currentDepth == writeDepth) + { + entry.WriteEntry(bb, ref offset, strings, ref stringTableOffset, stringTable); + } + else + { + entry.Write(bb, writeDepth, currentDepth + 1, ref offset, strings, ref stringTableOffset, stringTable); + } + } + } + + private void WriteEntry(ByteBuffer bb, ref int offset, Dictionary strings, ref int stringTableOffset, ByteBuffer stringTable) + { + WriteNameOrOrdinal(bb, OrdinalOrName, strings, ref stringTableOffset, stringTable); + if (Data == null) + { + bb.Write(0x80000000U | (uint)offset); + } + else + { + bb.Write(offset); + } + offset += 16 + entries.Count * 8; + } + + private static void WriteNameOrOrdinal(ByteBuffer bb, OrdinalOrName id, Dictionary strings, ref int stringTableOffset, ByteBuffer stringTable) + { + if (id.Name == null) + { + bb.Write((int)id.Ordinal); + } + else + { + int stringOffset; + if (!strings.TryGetValue(id.Name, out stringOffset)) + { + stringOffset = stringTableOffset; + strings.Add(id.Name, stringOffset); + stringTableOffset += id.Name.Length * 2 + 2; + stringTable.Write((ushort)id.Name.Length); + foreach (char c in id.Name) + { + stringTable.Write((short)c); + } + } + bb.Write(0x80000000U | (uint)stringOffset); + } + } + } + + struct OrdinalOrName + { + internal readonly ushort Ordinal; + internal readonly string Name; + + internal OrdinalOrName(ushort value) + { + Ordinal = value; + Name = null; + } + + internal OrdinalOrName(string value) + { + Ordinal = 0xFFFF; + Name = value; + } + + internal bool IsGreaterThan(OrdinalOrName other) + { + return this.Name == null + ? this.Ordinal > other.Ordinal + : String.Compare(this.Name, other.Name, StringComparison.OrdinalIgnoreCase) > 0; + } + + internal bool IsEqual(OrdinalOrName other) + { + return this.Name == null + ? this.Ordinal == other.Ordinal + : String.Compare(this.Name, other.Name, StringComparison.OrdinalIgnoreCase) == 0; + } + } + + struct RESOURCEHEADER + { + internal int DataSize; + internal int HeaderSize; + internal OrdinalOrName TYPE; + internal OrdinalOrName NAME; + internal int DataVersion; + internal ushort MemoryFlags; + internal ushort LanguageId; + internal int Version; + internal int Characteristics; + + internal RESOURCEHEADER(ByteReader br) + { + DataSize = br.ReadInt32(); + HeaderSize = br.ReadInt32(); + TYPE = ReadOrdinalOrName(br); + NAME = ReadOrdinalOrName(br); + br.Align(4); + DataVersion = br.ReadInt32(); + MemoryFlags = br.ReadUInt16(); + LanguageId = br.ReadUInt16(); + Version = br.ReadInt32(); + Characteristics = br.ReadInt32(); + } + + private static OrdinalOrName ReadOrdinalOrName(ByteReader br) + { + char c = br.ReadChar(); + if (c == 0xFFFF) + { + return new OrdinalOrName(br.ReadUInt16()); + } + else + { + StringBuilder sb = new StringBuilder(); + while (c != 0) + { + sb.Append(c); + c = br.ReadChar(); + } + return new OrdinalOrName(sb.ToString()); + } + } + } +} diff --git a/reflect/Writer/TextSection.cs b/reflect/Writer/TextSection.cs new file mode 100644 index 0000000..fceedcf --- /dev/null +++ b/reflect/Writer/TextSection.cs @@ -0,0 +1,921 @@ +/* + Copyright (C) 2008-2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Diagnostics; +using System.IO; +using System.Collections.Generic; +using System.Text; +using IKVM.Reflection.Emit; +using IKVM.Reflection.Impl; +using IKVM.Reflection.Metadata; + +namespace IKVM.Reflection.Writer +{ + sealed class TextSection + { + private readonly PEWriter peWriter; + private readonly CliHeader cliHeader; + private readonly ModuleBuilder moduleBuilder; + private readonly uint strongNameSignatureLength; + private readonly uint manifestResourcesLength; + private readonly ExportTables exportTables; + private readonly List relocations = new List(); + + internal TextSection(PEWriter peWriter, CliHeader cliHeader, ModuleBuilder moduleBuilder, int strongNameSignatureLength) + { + this.peWriter = peWriter; + this.cliHeader = cliHeader; + this.moduleBuilder = moduleBuilder; + this.strongNameSignatureLength = (uint)strongNameSignatureLength; + this.manifestResourcesLength = (uint)moduleBuilder.GetManifestResourcesLength(); + if (moduleBuilder.unmanagedExports.Count != 0) + { + this.exportTables = new ExportTables(this); + } + } + + internal uint PointerToRawData + { + get { return peWriter.ToFileAlignment(peWriter.HeaderSize); } + } + + internal uint BaseRVA + { + get { return peWriter.Headers.OptionalHeader.SectionAlignment; } + } + + internal uint ImportAddressTableRVA + { + get { return BaseRVA; } + } + + internal uint ImportAddressTableLength + { + get { return peWriter.Is32Bit ? 8u : 16u; } + } + + internal uint ComDescriptorRVA + { + get { return ImportAddressTableRVA + ImportAddressTableLength; } + } + + internal uint ComDescriptorLength + { + get { return cliHeader.Cb; } + } + + internal uint MethodBodiesRVA + { + get { return (ComDescriptorRVA + ComDescriptorLength + 7) & ~7U; } + } + + private uint MethodBodiesLength + { + get { return (uint)moduleBuilder.methodBodies.Length; } + } + + private uint ResourcesRVA + { + get + { + switch (peWriter.Headers.FileHeader.Machine) + { + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386: + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_ARM: + return (MethodBodiesRVA + MethodBodiesLength + 3) & ~3U; + default: + return (MethodBodiesRVA + MethodBodiesLength + 15) & ~15U; + } + } + } + + private uint ResourcesLength + { + get { return manifestResourcesLength; } + } + + internal uint StrongNameSignatureRVA + { + get + { + return (ResourcesRVA + ResourcesLength + 3) & ~3U; + } + } + + internal uint StrongNameSignatureLength + { + get + { + return strongNameSignatureLength; + } + } + + private uint MetadataRVA + { + get + { + return (StrongNameSignatureRVA + StrongNameSignatureLength + 3) & ~3U; + } + } + + private uint MetadataLength + { + get { return (uint)moduleBuilder.MetadataLength; } + } + + private uint VTableFixupsRVA + { + get { return (MetadataRVA + MetadataLength + 7) & ~7U; } + } + + private uint VTableFixupsLength + { + get { return (uint)moduleBuilder.vtablefixups.Count * 8; } + } + + internal uint DebugDirectoryRVA + { + get { return VTableFixupsRVA + VTableFixupsLength; } + } + + internal uint DebugDirectoryLength + { + get + { + if (DebugDirectoryContentsLength != 0) + { + return 28; + } + return 0; + } + } + + private uint DebugDirectoryContentsLength + { + get + { + if (moduleBuilder.symbolWriter != null) + { + IMAGE_DEBUG_DIRECTORY idd = new IMAGE_DEBUG_DIRECTORY(); + return (uint)SymbolSupport.GetDebugInfo(moduleBuilder.symbolWriter, ref idd).Length; + } + return 0; + } + } + + internal uint ExportDirectoryRVA + { + get { return (DebugDirectoryRVA + DebugDirectoryLength + DebugDirectoryContentsLength + 15) & ~15U; } + } + + internal uint ExportDirectoryLength + { + get { return moduleBuilder.unmanagedExports.Count == 0 ? 0U : 40U; } + } + + private uint ExportTablesRVA + { + get { return ExportDirectoryRVA + ExportDirectoryLength; } + } + + private uint ExportTablesLength + { + get { return exportTables == null ? 0U : exportTables.Length; } + } + + internal uint ImportDirectoryRVA + { + // on AMD64 (and probably IA64) the import directory needs to be 16 byte aligned (on I386 4 byte alignment is sufficient) + get { return (ExportTablesRVA + ExportTablesLength + 15) & ~15U; } + } + + internal uint ImportDirectoryLength + { + get { return (ImportHintNameTableRVA - ImportDirectoryRVA) + 27; } + } + + private uint ImportHintNameTableRVA + { + get + { + return peWriter.Is32Bit + ? (ImportDirectoryRVA + 48 + 15) & ~15U + : (ImportDirectoryRVA + 52 + 15) & ~15U; + } + } + + internal uint StartupStubRVA + { + get + { + if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64) + { + // note that the alignment is driven by the requirement that the two relocation fixups are in a single page + return (ImportDirectoryRVA + ImportDirectoryLength + 15U) & ~15U; + } + else + { + // the additional 2 bytes padding are to align the address in the jump (which is a relocation fixup) + return 2 + ((ImportDirectoryRVA + ImportDirectoryLength + 3U) & ~3U); + } + } + } + + internal uint StartupStubLength + { + get + { + switch (peWriter.Headers.FileHeader.Machine) + { + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386: + return 6; + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64: + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_ARM: + return 12; + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64: + return 48; + default: + throw new NotSupportedException(); + } + } + } + + private void WriteRVA(MetadataWriter mw, uint rva) + { + switch (peWriter.Headers.FileHeader.Machine) + { + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386: + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_ARM: + mw.Write(rva); + break; + default: + mw.Write((ulong)rva); + break; + } + } + + internal void Write(MetadataWriter mw, uint sdataRVA, out int guidHeapOffset) + { + // Now that we're ready to start writing, we need to do some fix ups + moduleBuilder.TypeRef.Fixup(moduleBuilder); + moduleBuilder.MethodDef.Fixup(this); + moduleBuilder.MethodImpl.Fixup(moduleBuilder); + moduleBuilder.MethodSemantics.Fixup(moduleBuilder); + moduleBuilder.InterfaceImpl.Fixup(); + moduleBuilder.ResolveInterfaceImplPseudoTokens(); + moduleBuilder.MemberRef.Fixup(moduleBuilder); + moduleBuilder.Constant.Fixup(moduleBuilder); + moduleBuilder.FieldMarshal.Fixup(moduleBuilder); + moduleBuilder.DeclSecurity.Fixup(moduleBuilder); + moduleBuilder.GenericParam.Fixup(moduleBuilder); + moduleBuilder.CustomAttribute.Fixup(moduleBuilder); + moduleBuilder.FieldLayout.Fixup(moduleBuilder); + moduleBuilder.FieldRVA.Fixup(moduleBuilder, (int)sdataRVA, (int)this.MethodBodiesRVA); + moduleBuilder.ImplMap.Fixup(moduleBuilder); + moduleBuilder.ExportedType.Fixup(moduleBuilder); + moduleBuilder.ManifestResource.Fixup(moduleBuilder); + moduleBuilder.MethodSpec.Fixup(moduleBuilder); + moduleBuilder.GenericParamConstraint.Fixup(moduleBuilder); + + // Import Address Table + AssertRVA(mw, ImportAddressTableRVA); + if (ImportAddressTableLength != 0) + { + WriteRVA(mw, ImportHintNameTableRVA); + WriteRVA(mw, 0); + } + + // CLI Header + AssertRVA(mw, ComDescriptorRVA); + cliHeader.MetaData.VirtualAddress = MetadataRVA; + cliHeader.MetaData.Size = MetadataLength; + if (ResourcesLength != 0) + { + cliHeader.Resources.VirtualAddress = ResourcesRVA; + cliHeader.Resources.Size = ResourcesLength; + } + if (StrongNameSignatureLength != 0) + { + cliHeader.StrongNameSignature.VirtualAddress = StrongNameSignatureRVA; + cliHeader.StrongNameSignature.Size = StrongNameSignatureLength; + } + if (VTableFixupsLength != 0) + { + cliHeader.VTableFixups.VirtualAddress = VTableFixupsRVA; + cliHeader.VTableFixups.Size = VTableFixupsLength; + } + cliHeader.Write(mw); + + // alignment padding + for (int i = (int)(MethodBodiesRVA - (ComDescriptorRVA + ComDescriptorLength)); i > 0; i--) + { + mw.Write((byte)0); + } + + // Method Bodies + mw.Write(moduleBuilder.methodBodies); + + // alignment padding + for (int i = (int)(ResourcesRVA - (MethodBodiesRVA + MethodBodiesLength)); i > 0; i--) + { + mw.Write((byte)0); + } + + // Resources + moduleBuilder.WriteResources(mw); + + // The strong name signature live here (if it exists), but it will written later + // and the following alignment padding will take care of reserving the space. + + // alignment padding + for (int i = (int)(MetadataRVA - (ResourcesRVA + ResourcesLength)); i > 0; i--) + { + mw.Write((byte)0); + } + + // Metadata + AssertRVA(mw, MetadataRVA); + moduleBuilder.WriteMetadata(mw, out guidHeapOffset); + + // alignment padding + for (int i = (int)(VTableFixupsRVA - (MetadataRVA + MetadataLength)); i > 0; i--) + { + mw.Write((byte)0); + } + + // VTableFixups + AssertRVA(mw, VTableFixupsRVA); + WriteVTableFixups(mw, sdataRVA); + + // Debug Directory + AssertRVA(mw, DebugDirectoryRVA); + WriteDebugDirectory(mw); + + // alignment padding + for (int i = (int)(ExportDirectoryRVA - (DebugDirectoryRVA + DebugDirectoryLength + DebugDirectoryContentsLength)); i > 0; i--) + { + mw.Write((byte)0); + } + + // Export Directory + AssertRVA(mw, ExportDirectoryRVA); + WriteExportDirectory(mw); + + // Export Tables + AssertRVA(mw, ExportTablesRVA); + WriteExportTables(mw, sdataRVA); + + // alignment padding + for (int i = (int)(ImportDirectoryRVA - (ExportTablesRVA + ExportTablesLength)); i > 0; i--) + { + mw.Write((byte)0); + } + + // Import Directory + AssertRVA(mw, ImportDirectoryRVA); + if (ImportDirectoryLength != 0) + { + WriteImportDirectory(mw); + } + + // alignment padding + for (int i = (int)(StartupStubRVA - (ImportDirectoryRVA + ImportDirectoryLength)); i > 0; i--) + { + mw.Write((byte)0); + } + + // Startup Stub + AssertRVA(mw, StartupStubRVA); + if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64) + { + /* + * 48 A1 00 20 40 00 00 00 00 00 mov rax,qword ptr [0000000000402000h] + * FF E0 jmp rax + */ + mw.Write((ushort)0xA148); + mw.Write(peWriter.Headers.OptionalHeader.ImageBase + ImportAddressTableRVA); + mw.Write((ushort)0xE0FF); + } + else if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64) + { + mw.Write(new byte[] { + 0x0B, 0x48, 0x00, 0x02, 0x18, 0x10, 0xA0, 0x40, 0x24, 0x30, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x10, 0x08, 0x00, 0x12, 0x18, 0x10, 0x60, 0x50, 0x04, 0x80, 0x03, 0x00, 0x60, 0x00, 0x80, 0x00 + }); + mw.Write(peWriter.Headers.OptionalHeader.ImageBase + StartupStubRVA); + mw.Write(peWriter.Headers.OptionalHeader.ImageBase + BaseRVA); + } + else if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386) + { + mw.Write((ushort)0x25FF); + mw.Write((uint)peWriter.Headers.OptionalHeader.ImageBase + ImportAddressTableRVA); + } + else if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_ARM) + { + uint rva = (uint)peWriter.Headers.OptionalHeader.ImageBase + ImportAddressTableRVA; + ushort lo = (ushort)rva; + ushort hi = (ushort)(rva >> 16); + mw.Write((ushort)(0xF240 + (lo >> 12))); + mw.Write((ushort)(0x0C00 + ((lo << 4) & 0xF000) + (lo & 0xFF))); + mw.Write((ushort)(0xF2C0 + (hi >> 12))); + mw.Write((ushort)(0x0C00 + ((hi << 4) & 0xF000) + (hi & 0xFF))); + mw.Write((ushort)0xF8DC); + mw.Write((ushort)0xF000); + } + else + { + throw new NotSupportedException(); + } + } + + [Conditional("DEBUG")] + private void AssertRVA(MetadataWriter mw, uint rva) + { + Debug.Assert(mw.Position - PointerToRawData + BaseRVA == rva); + } + + private void WriteVTableFixups(MetadataWriter mw, uint sdataRVA) + { + foreach (ModuleBuilder.VTableFixups fixups in moduleBuilder.vtablefixups) + { + mw.Write(fixups.initializedDataOffset + sdataRVA); + mw.Write(fixups.count); + mw.Write(fixups.type); + } + } + + private void WriteDebugDirectory(MetadataWriter mw) + { + if (DebugDirectoryLength != 0) + { + IMAGE_DEBUG_DIRECTORY idd = new IMAGE_DEBUG_DIRECTORY(); + idd.Characteristics = 0; + idd.TimeDateStamp = peWriter.Headers.FileHeader.TimeDateStamp; + byte[] buf = SymbolSupport.GetDebugInfo(moduleBuilder.symbolWriter, ref idd); + idd.PointerToRawData = (DebugDirectoryRVA - BaseRVA) + DebugDirectoryLength + PointerToRawData; + idd.AddressOfRawData = DebugDirectoryRVA + DebugDirectoryLength; + mw.Write(idd.Characteristics); + mw.Write(idd.TimeDateStamp); + mw.Write(idd.MajorVersion); + mw.Write(idd.MinorVersion); + mw.Write(idd.Type); + mw.Write(idd.SizeOfData); + mw.Write(idd.AddressOfRawData); + mw.Write(idd.PointerToRawData); + mw.Write(buf); + } + } + + private sealed class ExportTables + { + private readonly TextSection text; + internal readonly uint entries; + internal readonly uint ordinalBase; + internal readonly uint nameCount; + internal readonly uint namesLength; + internal readonly uint exportAddressTableRVA; + internal readonly uint exportNamePointerTableRVA; + internal readonly uint exportOrdinalTableRVA; + internal readonly uint namesRVA; + internal readonly uint stubsRVA; + private readonly uint stubLength; + + internal ExportTables(TextSection text) + { + this.text = text; + ordinalBase = GetOrdinalBase(out entries); + namesLength = GetExportNamesLength(out nameCount); + exportAddressTableRVA = text.ExportTablesRVA; + exportNamePointerTableRVA = exportAddressTableRVA + 4 * entries; + exportOrdinalTableRVA = exportNamePointerTableRVA + 4 * nameCount; + namesRVA = exportOrdinalTableRVA + 2 * nameCount; + stubsRVA = (namesRVA + namesLength + 15) & ~15U; + // note that we align the stubs to avoid having to deal with the relocation crossing a page boundary + switch (text.peWriter.Headers.FileHeader.Machine) + { + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386: + stubLength = 8; + break; + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64: + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_ARM: + stubLength = 16; + break; + default: + throw new NotSupportedException(); + } + } + + internal uint Length + { + get { return (stubsRVA + stubLength * (uint)text.moduleBuilder.unmanagedExports.Count) - text.ExportTablesRVA; } + } + + private uint GetOrdinalBase(out uint entries) + { + uint min = uint.MaxValue; + uint max = uint.MinValue; + foreach (UnmanagedExport exp in text.moduleBuilder.unmanagedExports) + { + uint ordinal = (uint)exp.ordinal; + min = Math.Min(min, ordinal); + max = Math.Max(max, ordinal); + } + entries = 1 + (max - min); + return min; + } + + private uint GetExportNamesLength(out uint nameCount) + { + nameCount = 0; + // the first name in the names list is the module name (the Export Directory contains a name of the current module) + uint length = (uint)text.moduleBuilder.fileName.Length + 1; + foreach (UnmanagedExport exp in text.moduleBuilder.unmanagedExports) + { + if (exp.name != null) + { + nameCount++; + length += (uint)exp.name.Length + 1; + } + } + return length; + } + + internal void Write(MetadataWriter mw, uint sdataRVA) + { + // sort the exports by ordinal + text.moduleBuilder.unmanagedExports.Sort(CompareUnmanagedExportOrdinals); + + // Now write the Export Address Table + text.AssertRVA(mw, exportAddressTableRVA); + for (int i = 0, pos = 0; i < entries; i++) + { + if (text.moduleBuilder.unmanagedExports[pos].ordinal == i + ordinalBase) + { + mw.Write(text.peWriter.Thumb + stubsRVA + (uint)pos * stubLength); + pos++; + } + else + { + mw.Write(0); + } + } + + // sort the exports by name + text.moduleBuilder.unmanagedExports.Sort(CompareUnmanagedExportNames); + + // Now write the Export Name Pointer Table + text.AssertRVA(mw, exportNamePointerTableRVA); + uint nameOffset = (uint)text.moduleBuilder.fileName.Length + 1; + foreach (UnmanagedExport exp in text.moduleBuilder.unmanagedExports) + { + if (exp.name != null) + { + mw.Write(namesRVA + nameOffset); + nameOffset += (uint)exp.name.Length + 1; + } + } + + // Now write the Export Ordinal Table + text.AssertRVA(mw, exportOrdinalTableRVA); + foreach (UnmanagedExport exp in text.moduleBuilder.unmanagedExports) + { + if (exp.name != null) + { + mw.Write((ushort)(exp.ordinal - ordinalBase)); + } + } + + // Now write the actual names + text.AssertRVA(mw, namesRVA); + mw.WriteAsciiz(text.moduleBuilder.fileName); + foreach (UnmanagedExport exp in text.moduleBuilder.unmanagedExports) + { + if (exp.name != null) + { + mw.WriteAsciiz(exp.name); + } + } + text.AssertRVA(mw, namesRVA + namesLength); + + // alignment padding + for (int i = (int)(stubsRVA - (namesRVA + namesLength)); i > 0; i--) + { + mw.Write((byte)0); + } + + // sort the exports by ordinal + text.moduleBuilder.unmanagedExports.Sort(CompareUnmanagedExportOrdinals); + + // Now write the stubs + text.AssertRVA(mw, stubsRVA); + + for (int i = 0, pos = 0; i < entries; i++) + { + if (text.moduleBuilder.unmanagedExports[pos].ordinal == i + ordinalBase) + { + switch (text.peWriter.Headers.FileHeader.Machine) + { + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386: + mw.Write((byte)0xFF); + mw.Write((byte)0x25); + mw.Write((uint)text.peWriter.Headers.OptionalHeader.ImageBase + text.moduleBuilder.unmanagedExports[pos].rva.initializedDataOffset + sdataRVA); + mw.Write((short)0); // alignment + break; + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64: + mw.Write((byte)0x48); + mw.Write((byte)0xA1); + mw.Write(text.peWriter.Headers.OptionalHeader.ImageBase + text.moduleBuilder.unmanagedExports[pos].rva.initializedDataOffset + sdataRVA); + mw.Write((byte)0xFF); + mw.Write((byte)0xE0); + mw.Write(0); // alignment + break; + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_ARM: + mw.Write((ushort)0xF8DF); + mw.Write((ushort)0xC008); + mw.Write((ushort)0xF8DC); + mw.Write((ushort)0xC000); + mw.Write((ushort)0x4760); + mw.Write((ushort)0xDEFE); + mw.Write((uint)text.peWriter.Headers.OptionalHeader.ImageBase + text.moduleBuilder.unmanagedExports[pos].rva.initializedDataOffset + sdataRVA); + break; + default: + throw new NotSupportedException(); + } + pos++; + } + } + } + + private static int CompareUnmanagedExportNames(UnmanagedExport x, UnmanagedExport y) + { + if (x.name == null) + { + return y.name == null ? 0 : 1; + } + if (y.name == null) + { + return -1; + } + return String.CompareOrdinal(x.name, y.name); + } + + private static int CompareUnmanagedExportOrdinals(UnmanagedExport x, UnmanagedExport y) + { + return x.ordinal.CompareTo(y.ordinal); + } + + internal void GetRelocations(List list) + { + ushort type; + uint rva; + switch (text.peWriter.Headers.FileHeader.Machine) + { + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386: + type = 0x3000; + rva = stubsRVA + 2; + break; + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64: + type = 0xA000; + rva = stubsRVA + 2; + break; + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_ARM: + type = 0x3000; + rva = stubsRVA + 12; + break; + default: + throw new NotSupportedException(); + } + + // we assume that unmanagedExports is still sorted by ordinal + for (int i = 0, pos = 0; i < entries; i++) + { + if (text.moduleBuilder.unmanagedExports[pos].ordinal == i + ordinalBase) + { + list.Add(new Relocation(type, rva + (uint)pos * stubLength)); + pos++; + } + } + } + } + + private uint GetOrdinalBase(out uint entries) + { + uint min = uint.MaxValue; + uint max = uint.MinValue; + foreach (UnmanagedExport exp in moduleBuilder.unmanagedExports) + { + uint ordinal = (uint)exp.ordinal; + min = Math.Min(min, ordinal); + max = Math.Max(max, ordinal); + } + entries = 1 + (max - min); + return min; + } + + private uint GetExportNamesLength(out uint nameCount) + { + nameCount = 0; + uint length = 0; + foreach (UnmanagedExport exp in moduleBuilder.unmanagedExports) + { + if (exp.name != null) + { + nameCount++; + length += (uint)exp.name.Length + 1; + } + } + return length; + } + + private void WriteExportDirectory(MetadataWriter mw) + { + if (ExportDirectoryLength != 0) + { + // Flags + mw.Write(0); + // Date/Time Stamp + mw.Write(peWriter.Headers.FileHeader.TimeDateStamp); + // Major Version + mw.Write((short)0); + // Minor Version + mw.Write((short)0); + // Name RVA + mw.Write(exportTables.namesRVA); + // Ordinal Base + mw.Write(exportTables.ordinalBase); + // Address Table Entries + mw.Write(exportTables.entries); + // Number of Name Pointers + mw.Write(exportTables.nameCount); + // Export Address Table RVA + mw.Write(exportTables.exportAddressTableRVA); + // Name Pointer RVA + mw.Write(exportTables.exportNamePointerTableRVA); + // Ordinal Table RVA + mw.Write(exportTables.exportOrdinalTableRVA); + } + } + + private void WriteExportTables(MetadataWriter mw, uint sdataRVA) + { + if (exportTables != null) + { + exportTables.Write(mw, sdataRVA); + } + } + + private void WriteImportDirectory(MetadataWriter mw) + { + mw.Write(ImportDirectoryRVA + 40); // ImportLookupTable + mw.Write(0); // DateTimeStamp + mw.Write(0); // ForwarderChain + mw.Write(ImportHintNameTableRVA + 14); // Name + mw.Write(ImportAddressTableRVA); + mw.Write(new byte[20]); + // Import Lookup Table + mw.Write(ImportHintNameTableRVA); // Hint/Name Table RVA + int size = 48; + if (!peWriter.Is32Bit) + { + size += 4; + mw.Write(0); + } + mw.Write(0); + + // alignment padding + for (int i = (int)(ImportHintNameTableRVA - (ImportDirectoryRVA + size)); i > 0; i--) + { + mw.Write((byte)0); + } + + // Hint/Name Table + AssertRVA(mw, ImportHintNameTableRVA); + mw.Write((ushort)0); // Hint + if ((peWriter.Headers.FileHeader.Characteristics & IMAGE_FILE_HEADER.IMAGE_FILE_DLL) != 0) + { + mw.WriteAsciiz("_CorDllMain"); + } + else + { + mw.WriteAsciiz("_CorExeMain"); + } + // Name + mw.WriteAsciiz("mscoree.dll"); + mw.Write((byte)0); + } + + internal int Length + { + get { return (int)(StartupStubRVA - BaseRVA + StartupStubLength); } + } + + struct Relocation : IComparable + { + internal readonly uint rva; + internal readonly ushort type; + + internal Relocation(ushort type, uint rva) + { + this.type = type; + this.rva = rva; + } + + int IComparable.CompareTo(Relocation other) + { + return rva.CompareTo(other.rva); + } + } + + struct RelocationBlock + { + internal readonly uint PageRVA; + internal readonly ushort[] TypeOffset; + + internal RelocationBlock(uint pageRva, ushort[] typeOffset) + { + this.PageRVA = pageRva; + this.TypeOffset = typeOffset; + } + } + + internal void WriteRelocations(MetadataWriter mw) + { + foreach (RelocationBlock block in relocations) + { + mw.Write(block.PageRVA); + mw.Write(8 + block.TypeOffset.Length * 2); + foreach (ushort typeOffset in block.TypeOffset) + { + mw.Write(typeOffset); + } + } + } + + internal uint PackRelocations() + { + List list = new List(); + switch (peWriter.Headers.FileHeader.Machine) + { + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386: + list.Add(new Relocation(0x3000, this.StartupStubRVA + 2)); + break; + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64: + list.Add(new Relocation(0xA000, this.StartupStubRVA + 2)); + break; + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64: + list.Add(new Relocation(0xA000, this.StartupStubRVA + 0x20)); + list.Add(new Relocation(0xA000, this.StartupStubRVA + 0x28)); + break; + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_ARM: + list.Add(new Relocation(0x7000, this.StartupStubRVA)); + break; + default: + throw new NotSupportedException(); + } + if (exportTables != null) + { + exportTables.GetRelocations(list); + } + list.Sort(); + uint size = 0; + for (int i = 0; i < list.Count; ) + { + uint pageRVA = list[i].rva & ~0xFFFU; + int count = 1; + while (i + count < list.Count && (list[i + count].rva & ~0xFFFU) == pageRVA) + { + count++; + } + ushort[] typeOffset = new ushort[(count + 1) & ~1]; + for (int j = 0; j < count; j++, i++) + { + typeOffset[j] = (ushort)(list[i].type + (list[i].rva - pageRVA)); + } + relocations.Add(new RelocationBlock(pageRVA, typeOffset)); + size += (uint)(8 + typeOffset.Length * 2); + } + return size; + } + } +} diff --git a/reflect/Writer/VersionInfo.cs b/reflect/Writer/VersionInfo.cs new file mode 100644 index 0000000..efb65ce --- /dev/null +++ b/reflect/Writer/VersionInfo.cs @@ -0,0 +1,282 @@ +/* + Copyright (C) 2008 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Globalization; +using IKVM.Reflection.Emit; + +namespace IKVM.Reflection.Writer +{ + sealed class VersionInfo + { + private AssemblyName name; + private string fileName; + internal string copyright; + internal string trademark; + internal string product; + internal string company; + private string description; + private string title; + internal string informationalVersion; + private string fileVersion; + + internal void SetName(AssemblyName name) + { + this.name = name; + } + + internal void SetFileName(string assemblyFileName) + { + this.fileName = System.IO.Path.GetFileName(assemblyFileName); + } + + internal void SetAttribute(AssemblyBuilder asm, CustomAttributeBuilder cab) + { + Universe u = cab.Constructor.Module.universe; + Type type = cab.Constructor.DeclaringType; + if (copyright == null && type == u.System_Reflection_AssemblyCopyrightAttribute) + { + copyright = (string)cab.DecodeBlob(asm).GetConstructorArgument(0); + } + else if (trademark == null && type == u.System_Reflection_AssemblyTrademarkAttribute) + { + trademark = (string)cab.DecodeBlob(asm).GetConstructorArgument(0); + } + else if (product == null && type == u.System_Reflection_AssemblyProductAttribute) + { + product = (string)cab.DecodeBlob(asm).GetConstructorArgument(0); + } + else if (company == null && type == u.System_Reflection_AssemblyCompanyAttribute) + { + company = (string)cab.DecodeBlob(asm).GetConstructorArgument(0); + } + else if (description == null && type == u.System_Reflection_AssemblyDescriptionAttribute) + { + description = (string)cab.DecodeBlob(asm).GetConstructorArgument(0); + } + else if (title == null && type == u.System_Reflection_AssemblyTitleAttribute) + { + title = (string)cab.DecodeBlob(asm).GetConstructorArgument(0); + } + else if (informationalVersion == null && type == u.System_Reflection_AssemblyInformationalVersionAttribute) + { + informationalVersion = (string)cab.DecodeBlob(asm).GetConstructorArgument(0); + } + else if (fileVersion == null && type == u.System_Reflection_AssemblyFileVersionAttribute) + { + fileVersion = (string)cab.DecodeBlob(asm).GetConstructorArgument(0); + } + } + + internal void Write(ByteBuffer bb) + { + if (fileVersion == null) + { + if (name.Version != null) + { + fileVersion = name.Version.ToString(); + } + else + { + fileVersion = "0.0.0.0"; + } + } + + int codepage = 1200; // Unicode codepage + int lcid = 0x7f; + try + { + if (name.CultureInfo != null) + { +#if CORECLR + throw new NotImplementedException(); +#else + lcid = name.CultureInfo.LCID; +#endif + } + } + catch (ArgumentException) + { + // AssemblyName.CultureInfo throws an ArgumentException if AssemblyBuilder.__SetAssemblyCulture() was used to specify a non-existing culture + } + + Version filever = ParseVersionRobust(fileVersion); + int fileVersionMajor = filever.Major; + int fileVersionMinor = filever.Minor; + int fileVersionBuild = filever.Build; + int fileVersionRevision = filever.Revision; + + int productVersionMajor = fileVersionMajor; + int productVersionMinor = fileVersionMinor; + int productVersionBuild = fileVersionBuild; + int productVersionRevision = fileVersionRevision; + if (informationalVersion != null) + { + Version productver = ParseVersionRobust(informationalVersion); + productVersionMajor = productver.Major; + productVersionMinor = productver.Minor; + productVersionBuild = productver.Build; + productVersionRevision = productver.Revision; + } + + ByteBuffer stringTable = new ByteBuffer(512); + stringTable.Write((short)0); // wLength (placeholder) + stringTable.Write((short)0); // wValueLength + stringTable.Write((short)1); // wType + WriteUTF16Z(stringTable, string.Format("{0:x4}{1:x4}", lcid, codepage)); + stringTable.Align(4); + + WriteString(stringTable, "Comments", description); + WriteString(stringTable, "CompanyName", company); + WriteString(stringTable, "FileDescription", title); + WriteString(stringTable, "FileVersion", fileVersion); + WriteString(stringTable, "InternalName", name.Name); + WriteString(stringTable, "LegalCopyright", copyright); + WriteString(stringTable, "LegalTrademarks", trademark); + WriteString(stringTable, "OriginalFilename", fileName); + WriteString(stringTable, "ProductName", product); + WriteString(stringTable, "ProductVersion", informationalVersion); + + stringTable.Position = 0; + stringTable.Write((short)stringTable.Length); + + ByteBuffer stringFileInfo = new ByteBuffer(512); + stringFileInfo.Write((short)0); // wLength (placeholder) + stringFileInfo.Write((short)0); // wValueLength + stringFileInfo.Write((short)1); // wType + WriteUTF16Z(stringFileInfo, "StringFileInfo"); + stringFileInfo.Align(4); + stringFileInfo.Write(stringTable); + stringFileInfo.Position = 0; + stringFileInfo.Write((short)stringFileInfo.Length); + + byte[] preamble1 = new byte[] { + // VS_VERSIONINFO (platform SDK) + 0x34, 0x00, // wValueLength + 0x00, 0x00, // wType + 0x56, 0x00, 0x53, 0x00, 0x5F, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4F, 0x00, 0x4E, 0x00, 0x5F, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x46, 0x00, 0x4F, 0x00, 0x00, 0x00, // "VS_VERSION_INFO\0" + 0x00, 0x00, // Padding1 (32 bit alignment) + // VS_FIXEDFILEINFO starts + 0xBD, 0x04, 0xEF, 0xFE, // dwSignature (0xFEEF04BD) + 0x00, 0x00, 0x01, 0x00, // dwStrucVersion + }; + byte[] preamble2 = new byte[] { + 0x3F, 0x00, 0x00, 0x00, // dwFileFlagsMask (??) + 0x00, 0x00, 0x00, 0x00, // dwFileFlags (??) + 0x04, 0x00, 0x00, 0x00, // dwFileOS + 0x02, 0x00, 0x00, 0x00, // dwFileType + 0x00, 0x00, 0x00, 0x00, // dwFileSubtype + 0x00, 0x00, 0x00, 0x00, // dwFileDateMS + 0x00, 0x00, 0x00, 0x00, // dwFileDateLS + // Padding2 (32 bit alignment) + // VarFileInfo + 0x44, 0x00, // wLength + 0x00, 0x00, // wValueLength + 0x01, 0x00, // wType + 0x56, 0x00, 0x61, 0x00, 0x72, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x66, 0x00, 0x6F, 0x00, 0x00, 0x00, // "VarFileInfo\0" + 0x00, 0x00, // Padding + // Var + 0x24, 0x00, // wLength + 0x04, 0x00, // wValueLength + 0x00, 0x00, // wType + 0x54, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x73, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x00, 0x00, // "Translation\0" + 0x00, 0x00, // Padding (32 bit alignment) + }; + bb.Write((short)(2 + preamble1.Length + 8 + 8 + preamble2.Length + 4 + stringFileInfo.Length)); + bb.Write(preamble1); + bb.Write((short)fileVersionMinor); + bb.Write((short)fileVersionMajor); + bb.Write((short)fileVersionRevision); + bb.Write((short)fileVersionBuild); + bb.Write((short)productVersionMinor); + bb.Write((short)productVersionMajor); + bb.Write((short)productVersionRevision); + bb.Write((short)productVersionBuild); + bb.Write(preamble2); + bb.Write((short)lcid); + bb.Write((short)codepage); + bb.Write(stringFileInfo); + } + + private static void WriteUTF16Z(ByteBuffer bb, string str) + { + foreach (char c in str) + { + bb.Write((short)c); + } + bb.Write((short)0); + } + + private static void WriteString(ByteBuffer bb, string name, string value) + { + value = value ?? " "; + int pos = bb.Position; + bb.Write((short)0); // wLength (placeholder) + bb.Write((short)(value.Length + 1));// wValueLength + bb.Write((short)1); // wType + WriteUTF16Z(bb, name); + bb.Align(4); + WriteUTF16Z(bb, value); + bb.Align(4); + int savedPos = bb.Position; + bb.Position = pos; + bb.Write((short)(savedPos - pos)); + bb.Position = savedPos; + } + + private static Version ParseVersionRobust(string ver) + { + int index = 0; + ushort major = ParseVersionPart(ver, ref index); + ushort minor = ParseVersionPart(ver, ref index); + ushort build = ParseVersionPart(ver, ref index); + ushort revision = ParseVersionPart(ver, ref index); + return new Version(major, minor, build, revision); + } + + private static ushort ParseVersionPart(string str, ref int pos) + { + ushort value = 0; + while (pos < str.Length) + { + char c = str[pos]; + if (c == '.') + { + pos++; + break; + } + else if (c >= '0' && c <= '9') + { + value *= 10; + value += (ushort)(c - '0'); + pos++; + } + else + { + break; + } + } + return value; + } + } +} diff --git a/reflect/coreclr.cs b/reflect/coreclr.cs new file mode 100644 index 0000000..999fd3a --- /dev/null +++ b/reflect/coreclr.cs @@ -0,0 +1,70 @@ +/* + Copyright (C) 2015 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; + +#if CORECLR +namespace System.Diagnostics +{ + static class Debug + { + [Conditional("DEBUG")] + internal static void Assert(bool cond) + { + if (!cond) + { + Environment.FailFast("assertion failed"); + } + } + } +} + +namespace System.Collections.Generic +{ + sealed class Stack + { + private readonly List items = new List(); + + internal void Push(T value) + { + items.Add(value); + } + + internal T Peek() + { + if (items.Count == 0) + { + throw new InvalidOperationException(); + } + return items[items.Count - 1]; + } + + internal T Pop() + { + T value = Peek(); + items.RemoveAt(items.Count - 1); + return value; + } + } +} +#endif diff --git a/reflect/reflect.build b/reflect/reflect.build new file mode 100644 index 0000000..53fed7f --- /dev/null +++ b/reflect/reflect.build @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/runtime/AssemblyClassLoader.cs b/runtime/AssemblyClassLoader.cs new file mode 100644 index 0000000..d3a9796 --- /dev/null +++ b/runtime/AssemblyClassLoader.cs @@ -0,0 +1,1347 @@ +/* + Copyright (C) 2002-2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.IO; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; +using System.Runtime.CompilerServices; +using FormatterServices = System.Runtime.Serialization.FormatterServices; +using IKVM.Attributes; +#if STATIC_COMPILER || STUB_GENERATOR +using IKVM.Reflection; +using Type = IKVM.Reflection.Type; +#else +using System.Reflection; +#endif + +namespace IKVM.Internal +{ + class AssemblyClassLoader : ClassLoaderWrapper + { + private static readonly Dictionary assemblyClassLoaders = new Dictionary(); + private AssemblyLoader assemblyLoader; + private string[] references; + private AssemblyClassLoader[] delegates; +#if !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + private JavaClassLoaderConstructionInProgress jclcip; + private java.security.ProtectionDomain protectionDomain; + private static Dictionary customClassLoaderRedirects; + private byte hasCustomClassLoader; /* 0 = unknown, 1 = yes, 2 = no */ +#endif + private Dictionary> exports; + private string[] exportedAssemblyNames; + private AssemblyLoader[] exportedAssemblies; + private Dictionary exportedLoaders; + + private sealed class AssemblyLoader + { + private readonly Assembly assembly; + private bool[] isJavaModule; + private Module[] modules; + private Dictionary nameMap; + private bool hasDotNetModule; + private AssemblyName[] internalsVisibleTo; + private string[] jarList; +#if !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + private sun.misc.URLClassPath urlClassPath; +#endif + + internal AssemblyLoader(Assembly assembly) + { + this.assembly = assembly; + modules = assembly.GetModules(false); + isJavaModule = new bool[modules.Length]; + for (int i = 0; i < modules.Length; i++) + { + object[] attr = AttributeHelper.GetJavaModuleAttributes(modules[i]); + if (attr.Length > 0) + { + isJavaModule[i] = true; + foreach (JavaModuleAttribute jma in attr) + { + string[] map = jma.GetClassMap(); + if (map != null) + { + if (nameMap == null) + { + nameMap = new Dictionary(); + } + for (int j = 0; j < map.Length; j += 2) + { + string key = map[j]; + string val = map[j + 1]; + // TODO if there is a name clash between modules, this will throw. + // Figure out how to handle that. + nameMap.Add(key, val); + } + } + string[] jars = jma.Jars; + if (jars != null) + { + if (jarList == null) + { + jarList = jars; + } + else + { + string[] newList = new string[jarList.Length + jars.Length]; + Array.Copy(jarList, newList, jarList.Length); + Array.Copy(jars, 0, newList, jarList.Length, jars.Length); + jarList = newList; + } + } + } + } + else + { + hasDotNetModule = true; + } + } + } + + internal bool HasJavaModule + { + get + { + for (int i = 0; i < isJavaModule.Length; i++) + { + if (isJavaModule[i]) + { + return true; + } + } + return false; + } + } + + internal Assembly Assembly + { + get { return assembly; } + } + + private Type GetType(string name) + { + try + { + return assembly.GetType(name); + } + catch (ArgumentException) + { + } + catch (FileLoadException x) + { + // this can only happen if the assembly was loaded in the ReflectionOnly + // context and the requested type references a type in another assembly + // that cannot be found in the ReflectionOnly context + // TODO figure out what other exceptions Assembly.GetType() can throw + Tracer.Info(Tracer.Runtime, x.Message); + } + return null; + } + + private Type GetType(Module mod, string name) + { + try + { + return mod.GetType(name); + } + catch (ArgumentException) + { + } + catch (FileLoadException x) + { + // this can only happen if the assembly was loaded in the ReflectionOnly + // context and the requested type references a type in another assembly + // that cannot be found in the ReflectionOnly context + // TODO figure out what other exceptions Assembly.GetType() can throw + Tracer.Info(Tracer.Runtime, x.Message); + } + return null; + } + + private Type GetJavaType(Module mod, string name) + { + try + { + string n = null; + if (nameMap != null) + { + nameMap.TryGetValue(name, out n); + } + Type t = GetType(mod, n != null ? n : name); + if (t == null) + { + n = name.Replace('$', '+'); + if (!ReferenceEquals(n, name)) + { + t = GetType(n); + } + } + if (t != null + && !AttributeHelper.IsHideFromJava(t) + && !t.IsArray + && !t.IsPointer + && !t.IsByRef) + { + return t; + } + } + catch (ArgumentException x) + { + // we can end up here because we replace the $ with a plus sign + // (or client code did a Class.forName() on an invalid name) + Tracer.Info(Tracer.Runtime, x.Message); + } + return null; + } + + internal TypeWrapper DoLoad(string name) + { + for (int i = 0; i < modules.Length; i++) + { + if (isJavaModule[i]) + { + Type type = GetJavaType(modules[i], name); + if (type != null) + { + // check the name to make sure that the canonical name was used + if (CompiledTypeWrapper.GetName(type) == name) + { + return CompiledTypeWrapper.newInstance(name, type); + } + } + } + else + { + // TODO should we catch ArgumentException and prohibit array, pointer and byref here? + Type type = GetType(modules[i], DotNetTypeWrapper.DemangleTypeName(name)); + if (type != null && DotNetTypeWrapper.IsAllowedOutside(type)) + { + // check the name to make sure that the canonical name was used + if (DotNetTypeWrapper.GetName(type) == name) + { + return DotNetTypeWrapper.Create(type, name); + } + } + } + } + if (hasDotNetModule) + { + // for fake types, we load the declaring outer type (the real one) and + // let that generated the manufactured nested classes + // (note that for generic outer types, we need to duplicate this in ClassLoaderWrapper.LoadGenericClass) + TypeWrapper outer = null; + if (name.EndsWith(DotNetTypeWrapper.DelegateInterfaceSuffix)) + { + outer = DoLoad(name.Substring(0, name.Length - DotNetTypeWrapper.DelegateInterfaceSuffix.Length)); + } + else if (name.EndsWith(DotNetTypeWrapper.AttributeAnnotationSuffix)) + { + outer = DoLoad(name.Substring(0, name.Length - DotNetTypeWrapper.AttributeAnnotationSuffix.Length)); + } + else if (name.EndsWith(DotNetTypeWrapper.AttributeAnnotationReturnValueSuffix)) + { + outer = DoLoad(name.Substring(0, name.Length - DotNetTypeWrapper.AttributeAnnotationReturnValueSuffix.Length)); + } + else if (name.EndsWith(DotNetTypeWrapper.AttributeAnnotationMultipleSuffix)) + { + outer = DoLoad(name.Substring(0, name.Length - DotNetTypeWrapper.AttributeAnnotationMultipleSuffix.Length)); + } + else if (name.EndsWith(DotNetTypeWrapper.EnumEnumSuffix)) + { + outer = DoLoad(name.Substring(0, name.Length - DotNetTypeWrapper.EnumEnumSuffix.Length)); + } + if (outer != null && outer.IsFakeTypeContainer) + { + foreach (TypeWrapper tw in outer.InnerClasses) + { + if (tw.Name == name) + { + return tw; + } + } + } + } + return null; + } + + internal string GetTypeNameAndType(Type type, out bool isJavaType) + { + Module mod = type.Module; + int moduleIndex = -1; + for (int i = 0; i < modules.Length; i++) + { + if (modules[i] == mod) + { + moduleIndex = i; + break; + } + } + if (isJavaModule[moduleIndex]) + { + isJavaType = true; + if (AttributeHelper.IsHideFromJava(type)) + { + return null; + } + return CompiledTypeWrapper.GetName(type); + } + else + { + isJavaType = false; + if (!DotNetTypeWrapper.IsAllowedOutside(type)) + { + return null; + } + return DotNetTypeWrapper.GetName(type); + } + } + + internal TypeWrapper CreateWrapperForAssemblyType(Type type) + { + bool isJavaType; + string name = GetTypeNameAndType(type, out isJavaType); + if (name == null) + { + return null; + } + if (isJavaType) + { + // since this type was compiled from Java source, we have to look for our + // attributes + return CompiledTypeWrapper.newInstance(name, type); + } + else + { + // since this type was not compiled from Java source, we don't need to + // look for our attributes, but we do need to filter unrepresentable + // stuff (and transform some other stuff) + return DotNetTypeWrapper.Create(type, name); + } + } + + internal bool InternalsVisibleTo(AssemblyName otherName) + { + if (internalsVisibleTo == null) + { + Interlocked.CompareExchange(ref internalsVisibleTo, AttributeHelper.GetInternalsVisibleToAttributes(assembly), null); + } + foreach (AssemblyName name in internalsVisibleTo) + { + // we match the simple name and PublicKeyToken (because the AssemblyName constructor used + // by GetInternalsVisibleToAttributes() only sets the PublicKeyToken, even if a PublicKey is specified) + if (ReflectUtil.MatchNameAndPublicKeyToken(name, otherName)) + { + return true; + } + } + return false; + } + +#if !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + internal java.util.Enumeration FindResources(string name) + { + if (urlClassPath == null) + { + if (jarList == null) + { + return gnu.java.util.EmptyEnumeration.getInstance(); + } + List urls = new List(); + foreach (string jar in jarList) + { + urls.Add(MakeResourceURL(assembly, jar)); + } + Interlocked.CompareExchange(ref urlClassPath, new sun.misc.URLClassPath(urls.ToArray()), null); + } + return urlClassPath.findResources(name, true); + } +#endif + } + + internal AssemblyClassLoader(Assembly assembly) + : this(assembly, null) + { + } + + internal AssemblyClassLoader(Assembly assembly, string[] fixedReferences) + : base(CodeGenOptions.None, null) + { + this.assemblyLoader = new AssemblyLoader(assembly); + this.references = fixedReferences; + } + +#if STATIC_COMPILER + internal static void PreloadExportedAssemblies(Assembly assembly) + { + if (assembly.GetManifestResourceInfo("ikvm.exports") != null) + { + using (Stream stream = assembly.GetManifestResourceStream("ikvm.exports")) + { + BinaryReader rdr = new BinaryReader(stream); + int assemblyCount = rdr.ReadInt32(); + for (int i = 0; i < assemblyCount; i++) + { + string assemblyName = rdr.ReadString(); + int typeCount = rdr.ReadInt32(); + if (typeCount != 0) + { + for (int j = 0; j < typeCount; j++) + { + rdr.ReadInt32(); + } + try + { + StaticCompiler.LoadFile(assembly.Location + "/../" + new AssemblyName(assemblyName).Name + ".dll"); + } + catch { } + } + } + } + } + } +#endif + + private void DoInitializeExports() + { + lock (this) + { + if (delegates == null) + { + if (!(ReflectUtil.IsDynamicAssembly(assemblyLoader.Assembly)) && assemblyLoader.Assembly.GetManifestResourceInfo("ikvm.exports") != null) + { + List wildcardExports = new List(); + using (Stream stream = assemblyLoader.Assembly.GetManifestResourceStream("ikvm.exports")) + { + BinaryReader rdr = new BinaryReader(stream); + int assemblyCount = rdr.ReadInt32(); + exports = new Dictionary>(); + exportedAssemblies = new AssemblyLoader[assemblyCount]; + exportedAssemblyNames = new string[assemblyCount]; + exportedLoaders = new Dictionary(); + for (int i = 0; i < assemblyCount; i++) + { + exportedAssemblyNames[i] = String.Intern(rdr.ReadString()); + int typeCount = rdr.ReadInt32(); + if (typeCount == 0 && references == null) + { + wildcardExports.Add(exportedAssemblyNames[i]); + } + for (int j = 0; j < typeCount; j++) + { + int hash = rdr.ReadInt32(); + List assemblies; + if (!exports.TryGetValue(hash, out assemblies)) + { + assemblies = new List(); + exports.Add(hash, assemblies); + } + assemblies.Add(i); + } + } + } + if (references == null) + { + references = wildcardExports.ToArray(); + } + } + else + { + AssemblyName[] refNames = assemblyLoader.Assembly.GetReferencedAssemblies(); + references = new string[refNames.Length]; + for (int i = 0; i < references.Length; i++) + { + references[i] = refNames[i].FullName; + } + } + Interlocked.Exchange(ref delegates, new AssemblyClassLoader[references.Length]); + } + } + } + + private void LazyInitExports() + { + if (delegates == null) + { + DoInitializeExports(); + } + } + + internal Assembly MainAssembly + { + get + { + return assemblyLoader.Assembly; + } + } + + internal Assembly GetAssembly(TypeWrapper wrapper) + { + Debug.Assert(wrapper.GetClassLoader() == this); + while (wrapper.IsFakeNestedType) + { + wrapper = wrapper.DeclaringTypeWrapper; + } + return wrapper.TypeAsBaseType.Assembly; + } + + private Assembly LoadAssemblyOrClearName(ref string name, bool exported) + { + if (name == null) + { + // previous load attemp failed + return null; + } + try + { +#if STATIC_COMPILER || STUB_GENERATOR + return StaticCompiler.Load(name); +#else + return Assembly.Load(name); +#endif + } + catch + { + // cache failure by clearing out the name the caller uses + name = null; + // should we issue a warning error (in ikvmc)? + return null; + } + } + + internal TypeWrapper DoLoad(string name) + { + TypeWrapper tw = assemblyLoader.DoLoad(name); + if (tw != null) + { + return RegisterInitiatingLoader(tw); + } + LazyInitExports(); + if (exports != null) + { + List assemblies; + if (exports.TryGetValue(JVM.PersistableHash(name), out assemblies)) + { + foreach (int index in assemblies) + { + AssemblyLoader loader = TryGetLoaderByIndex(index); + if (loader != null) + { + tw = loader.DoLoad(name); + if (tw != null) + { + return RegisterInitiatingLoader(tw); + } + } + } + } + } + return null; + } + + internal string GetTypeNameAndType(Type type, out bool isJavaType) + { + return GetLoader(type.Assembly).GetTypeNameAndType(type, out isJavaType); + } + + private AssemblyLoader TryGetLoaderByIndex(int index) + { + AssemblyLoader loader = exportedAssemblies[index]; + if (loader == null) + { + Assembly asm = LoadAssemblyOrClearName(ref exportedAssemblyNames[index], true); + if (asm != null) + { + loader = exportedAssemblies[index] = GetLoaderForExportedAssembly(asm); + } + } + return loader; + } + + internal List GetAllAvailableAssemblies() + { + List list = new List(); + list.Add(assemblyLoader.Assembly); + LazyInitExports(); + if (exportedAssemblies != null) + { + for (int i = 0; i < exportedAssemblies.Length; i++) + { + AssemblyLoader loader = TryGetLoaderByIndex(i); + if (loader != null && FromAssembly(loader.Assembly) == this) + { + list.Add(loader.Assembly); + } + } + } + return list; + } + + private AssemblyLoader GetLoader(Assembly assembly) + { + if (assemblyLoader.Assembly == assembly) + { + return assemblyLoader; + } + return GetLoaderForExportedAssembly(assembly); + } + + private AssemblyLoader GetLoaderForExportedAssembly(Assembly assembly) + { + LazyInitExports(); + AssemblyLoader loader; + lock (exportedLoaders) + { + exportedLoaders.TryGetValue(assembly, out loader); + } + if (loader == null) + { + loader = new AssemblyLoader(assembly); + lock (exportedLoaders) + { + AssemblyLoader existing; + if (exportedLoaders.TryGetValue(assembly, out existing)) + { + // another thread beat us to it + loader = existing; + } + else + { + exportedLoaders.Add(assembly, loader); + } + } + } + return loader; + } + + internal virtual TypeWrapper GetWrapperFromAssemblyType(Type type) + { + //Tracer.Info(Tracer.Runtime, "GetWrapperFromAssemblyType: {0}", type.FullName); + Debug.Assert(!type.Name.EndsWith("[]"), "!type.IsArray", type.FullName); + Debug.Assert(AssemblyClassLoader.FromAssembly(type.Assembly) == this); + + TypeWrapper wrapper = GetLoader(type.Assembly).CreateWrapperForAssemblyType(type); + if (wrapper != null) + { + if (type.IsGenericType && !type.IsGenericTypeDefinition) + { + // in the case of "magic" implementation generic type instances we'll end up here as well, + // but then wrapper.GetClassLoader() will return this anyway + wrapper = wrapper.GetClassLoader().RegisterInitiatingLoader(wrapper); + } + else + { + wrapper = RegisterInitiatingLoader(wrapper); + } + if (wrapper.TypeAsTBD != type && (!wrapper.IsRemapped || wrapper.TypeAsBaseType != type)) + { + // this really shouldn't happen, it means that we have two different types in our assembly that both + // have the same Java name +#if STATIC_COMPILER + throw new FatalCompilerErrorException(Message.AssemblyContainsDuplicateClassNames, type.FullName, wrapper.TypeAsTBD.FullName, wrapper.Name, type.Assembly.FullName); +#else + string msg = String.Format("\nType \"{0}\" and \"{1}\" both map to the same name \"{2}\".\n", type.FullName, wrapper.TypeAsTBD.FullName, wrapper.Name); + JVM.CriticalFailure(msg, null); +#endif + } + return wrapper; + } + return null; + } + + protected override TypeWrapper LoadClassImpl(string name, LoadMode mode) + { + TypeWrapper tw = FindLoadedClass(name); + if (tw != null) + { + return tw; + } +#if !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + while (hasCustomClassLoader != 2) + { + if (hasCustomClassLoader == 0) + { + Type customClassLoader = GetCustomClassLoaderType(); + if (customClassLoader == null) + { + hasCustomClassLoader = 2; + break; + } + WaitInitializeJavaClassLoader(customClassLoader); + hasCustomClassLoader = 1; + } + return base.LoadClassImpl(name, mode); + } +#endif + return LoadBootstrapIfNonJavaAssembly(name) + ?? LoadDynamic(name) + ?? FindOrLoadGenericClass(name, LoadMode.LoadOrNull); + } + + // this implements ikvm.runtime.AssemblyClassLoader.loadClass(), + // so unlike the above LoadClassImpl, it doesn't delegate to Java, + // but otherwise it should be the same algorithm + internal TypeWrapper LoadClass(string name) + { + return FindLoadedClass(name) + ?? LoadBootstrapIfNonJavaAssembly(name) + ?? LoadDynamic(name) + ?? FindOrLoadGenericClass(name, LoadMode.LoadOrNull); + } + + private TypeWrapper LoadBootstrapIfNonJavaAssembly(string name) + { + if (!assemblyLoader.HasJavaModule) + { + return GetBootstrapClassLoader().LoadClassByDottedNameFast(name); + } + return null; + } + + private TypeWrapper LoadDynamic(string name) + { +#if !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + string classFile = name.Replace('.', '/') + ".class"; + foreach (Resource res in GetBootstrapClassLoader().FindDelegateResources(classFile)) + { + return res.Loader.DefineDynamic(name, res.URL); + } + foreach (Resource res in FindDelegateResources(classFile)) + { + return res.Loader.DefineDynamic(name, res.URL); + } + foreach (java.net.URL url in FindResources(classFile)) + { + return DefineDynamic(name, url); + } +#endif + return null; + } + +#if !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + private TypeWrapper DefineDynamic(string name, java.net.URL url) + { + using (java.io.InputStream inp = url.openStream()) + { + byte[] buf = new byte[inp.available()]; + for (int pos = 0; pos < buf.Length; ) + { + int read = inp.read(buf, pos, buf.Length - pos); + if (read <= 0) + { + break; + } + pos += read; + } + return TypeWrapper.FromClass(Java_java_lang_ClassLoader.defineClass1(GetJavaClassLoader(), name, buf, 0, buf.Length, GetProtectionDomain(), null)); + } + } +#endif + + private TypeWrapper FindReferenced(string name) + { + for (int i = 0; i < delegates.Length; i++) + { + if (delegates[i] == null) + { + Assembly asm = LoadAssemblyOrClearName(ref references[i], false); + if (asm != null) + { + delegates[i] = AssemblyClassLoader.FromAssembly(asm); + } + } + if (delegates[i] != null) + { + TypeWrapper tw = delegates[i].DoLoad(name); + if (tw != null) + { + return RegisterInitiatingLoader(tw); + } + } + } + return null; + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + private static java.net.URL MakeResourceURL(Assembly asm, string name) + { +#if FIRST_PASS + return null; +#else + return new java.io.File(VirtualFileSystem.GetAssemblyResourcesPath(asm) + name).toURI().toURL(); +#endif + } + + internal IEnumerable FindResources(string unmangledName) + { + if (ReflectUtil.IsDynamicAssembly(assemblyLoader.Assembly)) + { + yield break; + } + bool found = false; +#if !FIRST_PASS + java.util.Enumeration urls = assemblyLoader.FindResources(unmangledName); + while (urls.hasMoreElements()) + { + found = true; + yield return (java.net.URL)urls.nextElement(); + } +#endif + if (!assemblyLoader.HasJavaModule) + { + if (unmangledName != "" && assemblyLoader.Assembly.GetManifestResourceInfo(unmangledName) != null) + { + found = true; + yield return MakeResourceURL(assemblyLoader.Assembly, unmangledName); + } + foreach (JavaResourceAttribute res in assemblyLoader.Assembly.GetCustomAttributes(typeof(IKVM.Attributes.JavaResourceAttribute), false)) + { + if (res.JavaName == unmangledName) + { + found = true; + yield return MakeResourceURL(assemblyLoader.Assembly, res.ResourceName); + } + } + } + string name = JVM.MangleResourceName(unmangledName); + if (assemblyLoader.Assembly.GetManifestResourceInfo(name) != null) + { + found = true; + yield return MakeResourceURL(assemblyLoader.Assembly, name); + } + LazyInitExports(); + if (exports != null) + { + List assemblies; + if (exports.TryGetValue(JVM.PersistableHash(unmangledName), out assemblies)) + { + foreach (int index in assemblies) + { + AssemblyLoader loader = exportedAssemblies[index]; + if (loader == null) + { + Assembly asm = LoadAssemblyOrClearName(ref exportedAssemblyNames[index], true); + if (asm == null) + { + continue; + } + loader = exportedAssemblies[index] = GetLoaderForExportedAssembly(asm); + } +#if !FIRST_PASS + urls = loader.FindResources(unmangledName); + while (urls.hasMoreElements()) + { + found = true; + yield return (java.net.URL)urls.nextElement(); + } +#endif + if (loader.Assembly.GetManifestResourceInfo(name) != null) + { + found = true; + yield return MakeResourceURL(loader.Assembly, name); + } + } + } + } + if (!found && unmangledName.EndsWith(".class", StringComparison.Ordinal) && unmangledName.IndexOf('.') == unmangledName.Length - 6) + { + TypeWrapper tw = FindLoadedClass(unmangledName.Substring(0, unmangledName.Length - 6).Replace('/', '.')); + if (tw != null && tw.GetClassLoader() == this && !tw.IsArray && !tw.IsDynamic) + { +#if !FIRST_PASS + yield return new java.io.File(VirtualFileSystem.GetAssemblyClassesPath(assemblyLoader.Assembly) + unmangledName).toURI().toURL(); +#endif + } + } + } + + protected struct Resource + { + internal readonly java.net.URL URL; + internal readonly AssemblyClassLoader Loader; + + internal Resource(java.net.URL url, AssemblyClassLoader loader) + { + this.URL = url; + this.Loader = loader; + } + } + + protected IEnumerable FindDelegateResources(string name) + { + LazyInitExports(); + for (int i = 0; i < delegates.Length; i++) + { + if (delegates[i] == null) + { + Assembly asm = LoadAssemblyOrClearName(ref references[i], false); + if (asm != null) + { + delegates[i] = AssemblyClassLoader.FromAssembly(asm); + } + } + if (delegates[i] != null && delegates[i] != GetBootstrapClassLoader()) + { + foreach (java.net.URL url in delegates[i].FindResources(name)) + { + yield return new Resource(url, delegates[i]); + } + } + } + } + + internal virtual IEnumerable GetResources(string name) + { + foreach (java.net.URL url in GetBootstrapClassLoader().GetResources(name)) + { + yield return url; + } + foreach (Resource res in FindDelegateResources(name)) + { + yield return res.URL; + } + foreach (java.net.URL url in FindResources(name)) + { + yield return url; + } + } +#endif // !STATIC_COMPILER + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + private sealed class JavaClassLoaderConstructionInProgress + { + internal readonly Thread Thread = Thread.CurrentThread; + internal java.lang.ClassLoader javaClassLoader; + internal int recursion; + } + + private java.lang.ClassLoader WaitInitializeJavaClassLoader(Type customClassLoader) + { + Interlocked.CompareExchange(ref jclcip, new JavaClassLoaderConstructionInProgress(), null); + JavaClassLoaderConstructionInProgress curr = jclcip; + if (curr != null) + { + if (curr.Thread == Thread.CurrentThread) + { + if (curr.javaClassLoader != null) + { + // we were recursively invoked during the class loader construction, + // so we have to return the partialy constructed class loader + return curr.javaClassLoader; + } + curr.recursion++; + try + { + if (javaClassLoader == null) + { + InitializeJavaClassLoader(curr, customClassLoader); + } + } + finally + { + // We only publish the class loader from the outer most invocation, otherwise + // an invocation of getClassLoader in the static initializer or constructor + // of the custom class loader would result in prematurely publishing it. + if (--curr.recursion == 0) + { + lock (this) + { + jclcip = null; + Monitor.PulseAll(this); + } + } + } + } + else + { + lock (this) + { + while (jclcip != null) + { + Monitor.Wait(this); + } + } + } + } + return javaClassLoader; + } + + internal override java.lang.ClassLoader GetJavaClassLoader() + { + if (javaClassLoader == null) + { + return WaitInitializeJavaClassLoader(GetCustomClassLoaderType()); + } + return javaClassLoader; + } + + internal virtual java.security.ProtectionDomain GetProtectionDomain() + { + if (protectionDomain == null) + { + Interlocked.CompareExchange(ref protectionDomain, new java.security.ProtectionDomain(assemblyLoader.Assembly), null); + } + return protectionDomain; + } +#endif + + protected override TypeWrapper FindLoadedClassLazy(string name) + { + return DoLoad(name) + ?? FindReferenced(name) + ?? FindOrLoadGenericClass(name, LoadMode.Find); + } + + internal override bool InternalsVisibleToImpl(TypeWrapper wrapper, TypeWrapper friend) + { + ClassLoaderWrapper other = friend.GetClassLoader(); + if (this == other) + { +#if STATIC_COMPILER || STUB_GENERATOR + return true; +#else + // we're OK if the type being accessed (wrapper) is a dynamic type + // or if the dynamic assembly has internal access + return GetAssembly(wrapper).Equals(GetTypeWrapperFactory().ModuleBuilder.Assembly) + || GetTypeWrapperFactory().HasInternalAccess; +#endif + } + AssemblyName otherName; +#if STATIC_COMPILER + CompilerClassLoader ccl = other as CompilerClassLoader; + if (ccl == null) + { + return false; + } + otherName = ccl.GetAssemblyName(); +#else + AssemblyClassLoader acl = other as AssemblyClassLoader; + if (acl == null) + { + return false; + } + otherName = acl.GetAssembly(friend).GetName(); +#endif + return GetLoader(GetAssembly(wrapper)).InternalsVisibleTo(otherName); + } + + // this method should not be used with dynamic Java assemblies + internal static AssemblyClassLoader FromAssembly(Assembly assembly) + { + AssemblyClassLoader loader; + lock (assemblyClassLoaders) + { + assemblyClassLoaders.TryGetValue(assembly, out loader); + } + if (loader == null) + { + loader = Create(assembly); + lock (assemblyClassLoaders) + { + AssemblyClassLoader existing; + if (assemblyClassLoaders.TryGetValue(assembly, out existing)) + { + // another thread won the race to create the class loader + loader = existing; + } + else + { + assemblyClassLoaders.Add(assembly, loader); + } + } + } + return loader; + } + + private static AssemblyClassLoader Create(Assembly assembly) + { + // If the assembly is a part of a multi-assembly shared class loader, + // it will export the __ type from the main assembly in the group. + Type forwarder = assembly.GetType("__"); + if (forwarder != null) + { + Assembly mainAssembly = forwarder.Assembly; + if (mainAssembly != assembly) + { + return FromAssembly(mainAssembly); + } + } +#if STATIC_COMPILER + if (JVM.CoreAssembly == null && CompilerClassLoader.IsCoreAssembly(assembly)) + { + JVM.CoreAssembly = assembly; + ClassLoaderWrapper.LoadRemappedTypes(); + } +#endif + if (assembly == JVM.CoreAssembly) + { + // This cast is necessary for ikvmc and a no-op for the runtime. + // Note that the cast cannot fail, because ikvmc will only return a non AssemblyClassLoader + // from GetBootstrapClassLoader() when compiling the core assembly and in that case JVM.CoreAssembly + // will be null. + return (AssemblyClassLoader)GetBootstrapClassLoader(); + } + return new AssemblyClassLoader(assembly); + } + + internal void AddDelegate(AssemblyClassLoader acl) + { + LazyInitExports(); + lock (this) + { + delegates = ArrayUtil.Concat(delegates, acl); + } + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal List> GetPackageInfo() + { + List> list = new List>(); + foreach (Module m in assemblyLoader.Assembly.GetModules(false)) + { + object[] attr = m.GetCustomAttributes(typeof(PackageListAttribute), false); + foreach (PackageListAttribute p in attr) + { + list.Add(new KeyValuePair(p.jar, p.packages)); + } + } + return list; + } +#endif + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + private Type GetCustomClassLoaderType() + { + LoadCustomClassLoaderRedirects(); + Assembly assembly = assemblyLoader.Assembly; + string assemblyName = assembly.FullName; + foreach (KeyValuePair kv in customClassLoaderRedirects) + { + string asm = kv.Key; + // FXBUG + // We only support matching on the assembly's simple name, + // because there appears to be no viable alternative. + // There is AssemblyName.ReferenceMatchesDefinition() + // but it is completely broken. + if (assemblyName.StartsWith(asm + ",")) + { + try + { + return Type.GetType(kv.Value, true); + } + catch (Exception x) + { + Tracer.Error(Tracer.Runtime, "Unable to load custom class loader {0} specified in app.config for assembly {1}: {2}", kv.Value, assembly, x); + } + break; + } + } + object[] attribs = assembly.GetCustomAttributes(typeof(CustomAssemblyClassLoaderAttribute), false); + if (attribs.Length == 1) + { + return ((CustomAssemblyClassLoaderAttribute)attribs[0]).Type; + } + return null; + } + + private void InitializeJavaClassLoader(JavaClassLoaderConstructionInProgress jclcip, Type customClassLoaderClass) + { + Assembly assembly = assemblyLoader.Assembly; + { + if (customClassLoaderClass != null) + { + try + { + if (!customClassLoaderClass.IsPublic && !customClassLoaderClass.Assembly.Equals(assembly)) + { + throw new Exception("Type not accessible"); + } + ConstructorInfo customClassLoaderCtor = customClassLoaderClass.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(Assembly) }, null); + if (customClassLoaderCtor == null) + { + throw new Exception("No constructor"); + } + if (!customClassLoaderCtor.IsPublic && !customClassLoaderClass.Assembly.Equals(assembly)) + { + customClassLoaderCtor = null; + throw new Exception("Constructor not accessible"); + } + // NOTE we're creating an uninitialized instance of the custom class loader here, so that getClassLoader will return the proper object + // when it is called during the construction of the custom class loader later on. This still doesn't make it safe to use the custom + // class loader before it is constructed, but at least the object instance is available and should anyone cache it, they will get the + // right object to use later on. + // Note that creating the unitialized instance will (unfortunately) trigger the static initializer. The static initializer can + // trigger a call to getClassLoader(), which means we can end up here recursively. + java.lang.ClassLoader newJavaClassLoader = (java.lang.ClassLoader)GetUninitializedObject(customClassLoaderClass); + if (jclcip.javaClassLoader == null) // check if we weren't invoked recursively and the nested invocation already did the work + { + jclcip.javaClassLoader = newJavaClassLoader; + SetWrapperForClassLoader(jclcip.javaClassLoader, this); + DoPrivileged(new CustomClassLoaderCtorCaller(customClassLoaderCtor, jclcip.javaClassLoader, assembly)); + Tracer.Info(Tracer.Runtime, "Created custom assembly class loader {0} for assembly {1}", customClassLoaderClass.FullName, assembly); + } + else + { + // we didn't initialize the object, so there is no need to finalize it + GC.SuppressFinalize(newJavaClassLoader); + } + } + catch (Exception x) + { + Tracer.Error(Tracer.Runtime, "Unable to create custom assembly class loader {0} for {1}: {2}", customClassLoaderClass.FullName, assembly, x); + } + } + } + if (jclcip.javaClassLoader == null) + { + jclcip.javaClassLoader = new ikvm.runtime.AssemblyClassLoader(); + SetWrapperForClassLoader(jclcip.javaClassLoader, this); + } + // finally we publish the class loader for other threads to see + Thread.MemoryBarrier(); + javaClassLoader = jclcip.javaClassLoader; + } + + // separate method to avoid LinkDemand killing the caller + // and to bridge transparent -> critical boundary + [System.Security.SecuritySafeCritical] + private static object GetUninitializedObject(Type type) + { + return FormatterServices.GetUninitializedObject(type); + } + + private static void LoadCustomClassLoaderRedirects() + { + if (customClassLoaderRedirects == null) + { + Dictionary dict = new Dictionary(); + try + { + foreach (string key in System.Configuration.ConfigurationManager.AppSettings.AllKeys) + { + const string prefix = "ikvm-classloader:"; + if (key.StartsWith(prefix)) + { + dict[key.Substring(prefix.Length)] = System.Configuration.ConfigurationManager.AppSettings.Get(key); + } + } + } + catch (Exception x) + { + Tracer.Error(Tracer.Runtime, "Error while reading custom class loader redirects: {0}", x); + } + finally + { + Interlocked.CompareExchange(ref customClassLoaderRedirects, dict, null); + } + } + } + + private sealed class CustomClassLoaderCtorCaller : java.security.PrivilegedAction + { + private ConstructorInfo ctor; + private object classLoader; + private Assembly assembly; + + internal CustomClassLoaderCtorCaller(ConstructorInfo ctor, object classLoader, Assembly assembly) + { + this.ctor = ctor; + this.classLoader = classLoader; + this.assembly = assembly; + } + + public object run() + { + ctor.Invoke(classLoader, new object[] { assembly }); + return null; + } + } +#endif + } + + sealed class BootstrapClassLoader : AssemblyClassLoader + { + internal BootstrapClassLoader() + : base(JVM.CoreAssembly, new string[] { + typeof(object).Assembly.FullName, // mscorlib + typeof(System.Uri).Assembly.FullName // System + }) + { + } + + internal override TypeWrapper GetWrapperFromAssemblyType(Type type) + { + // we have to special case the fake types here + if (type.IsGenericType && !type.IsGenericTypeDefinition) + { + TypeWrapper outer = ClassLoaderWrapper.GetWrapperFromType(type.GetGenericArguments()[0]); + foreach (TypeWrapper inner in outer.InnerClasses) + { + if (inner.TypeAsTBD == type) + { + return inner; + } + foreach (TypeWrapper inner2 in inner.InnerClasses) + { + if (inner2.TypeAsTBD == type) + { + return inner2; + } + } + } + return null; + } + return base.GetWrapperFromAssemblyType(type); + } + + protected override void CheckProhibitedPackage(string className) + { + } + +#if !FIRST_PASS && !STATIC_COMPILER && !STUB_GENERATOR + internal override java.lang.ClassLoader GetJavaClassLoader() + { + return null; + } + + internal override java.security.ProtectionDomain GetProtectionDomain() + { + return null; + } + + internal override IEnumerable GetResources(string name) + { + foreach (java.net.URL url in FindResources(name)) + { + yield return url; + } + foreach (Resource res in FindDelegateResources(name)) + { + yield return res.URL; + } + } +#endif + } +} diff --git a/runtime/AssemblyInfo.cs b/runtime/AssemblyInfo.cs new file mode 100644 index 0000000..d075ad2 --- /dev/null +++ b/runtime/AssemblyInfo.cs @@ -0,0 +1,57 @@ +/* + Copyright (C) 2002, 2003, 2004, 2005, 2006 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("IKVM.NET Runtime")] +[assembly: AssemblyDescription("JVM for Mono and .NET")] + +[assembly: System.Security.AllowPartiallyTrustedCallers] + +#if SIGNCODE +[assembly: InternalsVisibleTo("IKVM.Runtime.JNI, PublicKey=0024000004800000940000000602000000240000525341310004000001000100DD6B140E5209CAE3D1C710030021EF589D0F00D05ACA8771101A7E99E10EE063E66040DF96E6F842F717BFC5B62D2EC2B62CEB0282E4649790DACB424DB29B68ADC7EAEAB0356FCE04702379F84400B8427EDBB33DAB8720B9F16A42E2CDB87F885EF413DBC4229F2BD157C9B8DC2CD14866DEC5F31C764BFB9394CC3C60E6C0")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Core, PublicKey=0024000004800000940000000602000000240000525341310004000001000100DD6B140E5209CAE3D1C710030021EF589D0F00D05ACA8771101A7E99E10EE063E66040DF96E6F842F717BFC5B62D2EC2B62CEB0282E4649790DACB424DB29B68ADC7EAEAB0356FCE04702379F84400B8427EDBB33DAB8720B9F16A42E2CDB87F885EF413DBC4229F2BD157C9B8DC2CD14866DEC5F31C764BFB9394CC3C60E6C0")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Util, PublicKey=0024000004800000940000000602000000240000525341310004000001000100DD6B140E5209CAE3D1C710030021EF589D0F00D05ACA8771101A7E99E10EE063E66040DF96E6F842F717BFC5B62D2EC2B62CEB0282E4649790DACB424DB29B68ADC7EAEAB0356FCE04702379F84400B8427EDBB33DAB8720B9F16A42E2CDB87F885EF413DBC4229F2BD157C9B8DC2CD14866DEC5F31C764BFB9394CC3C60E6C0")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Security, PublicKey=0024000004800000940000000602000000240000525341310004000001000100DD6B140E5209CAE3D1C710030021EF589D0F00D05ACA8771101A7E99E10EE063E66040DF96E6F842F717BFC5B62D2EC2B62CEB0282E4649790DACB424DB29B68ADC7EAEAB0356FCE04702379F84400B8427EDBB33DAB8720B9F16A42E2CDB87F885EF413DBC4229F2BD157C9B8DC2CD14866DEC5F31C764BFB9394CC3C60E6C0")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Management, PublicKey=0024000004800000940000000602000000240000525341310004000001000100DD6B140E5209CAE3D1C710030021EF589D0F00D05ACA8771101A7E99E10EE063E66040DF96E6F842F717BFC5B62D2EC2B62CEB0282E4649790DACB424DB29B68ADC7EAEAB0356FCE04702379F84400B8427EDBB33DAB8720B9F16A42E2CDB87F885EF413DBC4229F2BD157C9B8DC2CD14866DEC5F31C764BFB9394CC3C60E6C0")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Media, PublicKey=0024000004800000940000000602000000240000525341310004000001000100DD6B140E5209CAE3D1C710030021EF589D0F00D05ACA8771101A7E99E10EE063E66040DF96E6F842F717BFC5B62D2EC2B62CEB0282E4649790DACB424DB29B68ADC7EAEAB0356FCE04702379F84400B8427EDBB33DAB8720B9F16A42E2CDB87F885EF413DBC4229F2BD157C9B8DC2CD14866DEC5F31C764BFB9394CC3C60E6C0")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Misc, PublicKey=0024000004800000940000000602000000240000525341310004000001000100DD6B140E5209CAE3D1C710030021EF589D0F00D05ACA8771101A7E99E10EE063E66040DF96E6F842F717BFC5B62D2EC2B62CEB0282E4649790DACB424DB29B68ADC7EAEAB0356FCE04702379F84400B8427EDBB33DAB8720B9F16A42E2CDB87F885EF413DBC4229F2BD157C9B8DC2CD14866DEC5F31C764BFB9394CC3C60E6C0")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Remoting, PublicKey=0024000004800000940000000602000000240000525341310004000001000100DD6B140E5209CAE3D1C710030021EF589D0F00D05ACA8771101A7E99E10EE063E66040DF96E6F842F717BFC5B62D2EC2B62CEB0282E4649790DACB424DB29B68ADC7EAEAB0356FCE04702379F84400B8427EDBB33DAB8720B9F16A42E2CDB87F885EF413DBC4229F2BD157C9B8DC2CD14866DEC5F31C764BFB9394CC3C60E6C0")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.SwingAWT, PublicKey=0024000004800000940000000602000000240000525341310004000001000100DD6B140E5209CAE3D1C710030021EF589D0F00D05ACA8771101A7E99E10EE063E66040DF96E6F842F717BFC5B62D2EC2B62CEB0282E4649790DACB424DB29B68ADC7EAEAB0356FCE04702379F84400B8427EDBB33DAB8720B9F16A42E2CDB87F885EF413DBC4229F2BD157C9B8DC2CD14866DEC5F31C764BFB9394CC3C60E6C0")] +#else +[assembly: InternalsVisibleTo("IKVM.Runtime.JNI")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Core")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Util")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Security")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Management")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Media")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Misc")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Remoting")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.SwingAWT")] +#endif diff --git a/runtime/AssemblyInfo.cs.in b/runtime/AssemblyInfo.cs.in new file mode 100644 index 0000000..c0e699d --- /dev/null +++ b/runtime/AssemblyInfo.cs.in @@ -0,0 +1,57 @@ +/* + Copyright (C) 2002, 2003, 2004, 2005, 2006 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("IKVM.NET Runtime")] +[assembly: AssemblyDescription("JVM for Mono and .NET")] + +[assembly: System.Security.AllowPartiallyTrustedCallers] + +#if SIGNCODE +[assembly: InternalsVisibleTo("IKVM.Runtime.JNI, PublicKey=@PUBLICKEY@")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Core, PublicKey=@PUBLICKEY@")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Util, PublicKey=@PUBLICKEY@")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Security, PublicKey=@PUBLICKEY@")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Management, PublicKey=@PUBLICKEY@")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Media, PublicKey=@PUBLICKEY@")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Misc, PublicKey=@PUBLICKEY@")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Remoting, PublicKey=@PUBLICKEY@")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.SwingAWT, PublicKey=@PUBLICKEY@")] +#else +[assembly: InternalsVisibleTo("IKVM.Runtime.JNI")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Core")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Util")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Security")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Management")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Media")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Misc")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.Remoting")] +[assembly: InternalsVisibleTo("IKVM.OpenJDK.SwingAWT")] +#endif diff --git a/runtime/Assertions.cs b/runtime/Assertions.cs new file mode 100644 index 0000000..28afed2 --- /dev/null +++ b/runtime/Assertions.cs @@ -0,0 +1,177 @@ +/* + Copyright (C) 2007-2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Globalization; +using IKVM.Internal; + +namespace IKVM.Runtime +{ + public static class Assertions + { + private static bool sysAsserts; + private static bool userAsserts; + private static OptionNode classes; + private static OptionNode packages; + + private sealed class OptionNode + { + internal readonly string name; + internal readonly bool enabled; + internal readonly OptionNode next; + + internal OptionNode(string name, bool enabled, OptionNode next) + { + this.name = name; + this.enabled = enabled; + this.next = next; + } + } + + private static void AddOption(string classOrPackage, bool enabled) + { + if (classOrPackage == null) + { + throw new ArgumentNullException("classOrPackage"); + } + + if (classOrPackage.EndsWith("...")) + { + packages = new OptionNode(classOrPackage.Substring(0, classOrPackage.Length - 3), enabled, packages); + } + else + { + classes = new OptionNode(classOrPackage, enabled, classes); + } + } + + public static void EnableAssertions(string classOrPackage) + { + AddOption(classOrPackage, true); + } + + public static void DisableAssertions(string classOrPackage) + { + AddOption(classOrPackage, false); + } + + public static void EnableAssertions() + { + userAsserts = true; + } + + public static void DisableAssertions() + { + userAsserts = false; + } + + public static void EnableSystemAssertions() + { + sysAsserts = true; + } + + public static void DisableSystemAssertions() + { + sysAsserts = false; + } + + internal static bool IsEnabled(TypeWrapper tw) + { + string className = tw.Name; + + // match class name + for (OptionNode n = classes; n != null; n = n.next) + { + if (n.name == className) + { + return n.enabled; + } + } + + // match package name + if (packages != null) + { + int len = className.Length; + while (len > 0 && className[--len] != '.') ; + + do + { + for (OptionNode n = packages; n != null; n = n.next) + { + if (String.Compare(n.name, 0, className, 0, len, false, CultureInfo.InvariantCulture) == 0 && len == n.name.Length) + { + return n.enabled; + } + } + while (len > 0 && className[--len] != '.') ; + } while (len > 0); + } + + return tw.GetClassLoader() == ClassLoaderWrapper.GetBootstrapClassLoader() ? sysAsserts : userAsserts; + } + + private static int Count(OptionNode n) + { + int count = 0; + while (n != null) + { + count++; + n = n.next; + } + return count; + } + + internal static object RetrieveDirectives() + { +#if FIRST_PASS + return null; +#else + java.lang.AssertionStatusDirectives asd = new java.lang.AssertionStatusDirectives(); + string[] arrStrings = new string[Count(classes)]; + bool[] arrBools = new bool[arrStrings.Length]; + OptionNode n = classes; + for (int i = 0; i < arrStrings.Length; i++) + { + arrStrings[i] = n.name; + arrBools[i] = n.enabled; + n = n.next; + } + asd.classes = arrStrings; + asd.classEnabled = arrBools; + arrStrings = new string[Count(packages)]; + arrBools = new bool[arrStrings.Length]; + n = packages; + for (int i = 0; i < arrStrings.Length; i++) + { + arrStrings[i] = n.name; + arrBools[i] = n.enabled; + n = n.next; + } + asd.packages = arrStrings; + asd.packageEnabled = arrBools; + asd.deflt = userAsserts; + return asd; +#endif + } + } +} diff --git a/runtime/BigEndianBinaryReader.cs b/runtime/BigEndianBinaryReader.cs new file mode 100644 index 0000000..318669b --- /dev/null +++ b/runtime/BigEndianBinaryReader.cs @@ -0,0 +1,242 @@ +/* + Copyright (C) 2002-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.IO; + +sealed class BigEndianBinaryReader +{ + private byte[] buf; + private int pos; + private int end; + + internal BigEndianBinaryReader(byte[] buf, int offset, int length) + { + this.buf = buf; + this.pos = offset; + this.end = checked(offset + length); + if(offset < 0 || length < 0 || buf.Length - offset < length) + { + throw new ClassFormatError("Truncated class file"); + } + } + + internal BigEndianBinaryReader Section(uint length) + { + BigEndianBinaryReader br = new BigEndianBinaryReader(buf, pos, checked((int)length)); + Skip(length); + return br; + } + + internal bool IsAtEnd + { + get + { + return pos == end; + } + } + + internal int Position + { + get + { + return pos; + } + } + + internal void Skip(uint count) + { + if(end - pos < count) + { + throw new ClassFormatError("Truncated class file"); + } + checked + { + pos += (int)count; + } + } + + internal byte ReadByte() + { + if(pos == end) + { + throw new ClassFormatError("Truncated class file"); + } + return buf[pos++]; + } + + internal sbyte ReadSByte() + { + if(pos == end) + { + throw new ClassFormatError("Truncated class file"); + } + return (sbyte)buf[pos++]; + } + + internal double ReadDouble() + { + return BitConverter.Int64BitsToDouble(ReadInt64()); + } + + internal short ReadInt16() + { + if(end - pos < 2) + { + throw new ClassFormatError("Truncated class file"); + } + short s = (short)((buf[pos] << 8) + buf[pos + 1]); + pos += 2; + return s; + } + + internal int ReadInt32() + { + if(end - pos < 4) + { + throw new ClassFormatError("Truncated class file"); + } + int i = (int)((buf[pos] << 24) + (buf[pos + 1] << 16) + (buf[pos + 2] << 8) + buf[pos + 3]); + pos += 4; + return i; + } + + internal long ReadInt64() + { + if(end - pos < 8) + { + throw new ClassFormatError("Truncated class file"); + } + uint i1 = (uint)((buf[pos] << 24) + (buf[pos + 1] << 16) + (buf[pos + 2] << 8) + buf[pos + 3]); + uint i2 = (uint)((buf[pos + 4] << 24) + (buf[pos + 5] << 16) + (buf[pos + 6] << 8) + buf[pos + 7]); + long l = (((long)i1) << 32) + i2; + pos += 8; + return l; + } + + internal float ReadSingle() + { + return BitConverter.ToSingle(BitConverter.GetBytes(ReadInt32()), 0); + } + + internal string ReadString(string classFile, int majorVersion) + { + int len = ReadUInt16(); + if(end - pos < len) + { + throw new ClassFormatError("{0} (Truncated class file)", classFile); + } + // special code path for ASCII strings (which occur *very* frequently) + for(int j = 0; j < len; j++) + { + if(buf[pos + j] == 0 || buf[pos + j] >= 128) + { + // NOTE we *cannot* use System.Text.UTF8Encoding, because this is *not* compatible + // (esp. for embedded nulls) + char[] ch = new char[len]; + int l = 0; + for(int i = 0; i < len; i++) + { + int c = buf[pos + i]; + int char2, char3; + switch (c >> 4) + { + case 0: + if(c == 0) + { + goto default; + } + break; + case 1: case 2: case 3: case 4: case 5: case 6: case 7: + // 0xxxxxxx + break; + case 12: case 13: + // 110x xxxx 10xx xxxx + char2 = buf[pos + ++i]; + if((char2 & 0xc0) != 0x80 || i >= len) + { + goto default; + } + c = (((c & 0x1F) << 6) | (char2 & 0x3F)); + if(c < 0x80 && c != 0 && majorVersion >= 48) + { + goto default; + } + break; + case 14: + // 1110 xxxx 10xx xxxx 10xx xxxx + char2 = buf[pos + ++i]; + char3 = buf[pos + ++i]; + if((char2 & 0xc0) != 0x80 || (char3 & 0xc0) != 0x80 || i >= len) + { + goto default; + } + c = (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); + if(c < 0x800 && majorVersion >= 48) + { + goto default; + } + break; + default: + throw new ClassFormatError("Illegal UTF8 string in constant pool in class file {0}", classFile ?? ""); + } + ch[l++] = (char)c; + } + pos += len; + return new String(ch, 0, l); + } + } + string s = System.Text.ASCIIEncoding.ASCII.GetString(buf, pos, len); + pos += len; + return s; + } + + internal ushort ReadUInt16() + { + if(end - pos < 2) + { + throw new ClassFormatError("Truncated class file"); + } + ushort s = (ushort)((buf[pos] << 8) + buf[pos + 1]); + pos += 2; + return s; + } + + internal uint ReadUInt32() + { + if(end - pos < 4) + { + throw new ClassFormatError("Truncated class file"); + } + uint i = (uint)((buf[pos] << 24) + (buf[pos + 1] << 16) + (buf[pos + 2] << 8) + buf[pos + 3]); + pos += 4; + return i; + } + + internal byte[] ToArray() + { + byte[] res = new byte[end - pos]; + Buffer.BlockCopy(buf, pos, res, 0, res.Length); + return res; + } +} diff --git a/runtime/Boxer.cs b/runtime/Boxer.cs new file mode 100644 index 0000000..880e015 --- /dev/null +++ b/runtime/Boxer.cs @@ -0,0 +1,212 @@ +/* + Copyright (C) 2011-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; + +namespace IKVM.Internal +{ + static class Boxer + { + private static readonly TypeWrapper javaLangByte; + private static readonly MethodWrapper byteValue; + private static readonly MethodWrapper valueOfByte; + private static readonly TypeWrapper javaLangBoolean; + private static readonly MethodWrapper booleanValue; + private static readonly MethodWrapper valueOfBoolean; + private static readonly TypeWrapper javaLangShort; + private static readonly MethodWrapper shortValue; + private static readonly MethodWrapper valueOfShort; + private static readonly TypeWrapper javaLangCharacter; + private static readonly MethodWrapper charValue; + private static readonly MethodWrapper valueOfCharacter; + private static readonly TypeWrapper javaLangInteger; + private static readonly MethodWrapper intValue; + private static readonly MethodWrapper valueOfInteger; + private static readonly TypeWrapper javaLangFloat; + private static readonly MethodWrapper floatValue; + private static readonly MethodWrapper valueOfFloat; + private static readonly TypeWrapper javaLangLong; + private static readonly MethodWrapper longValue; + private static readonly MethodWrapper valueOfLong; + private static readonly TypeWrapper javaLangDouble; + private static readonly MethodWrapper doubleValue; + private static readonly MethodWrapper valueOfDouble; + + static Boxer() + { + ClassLoaderWrapper bootClassLoader = ClassLoaderWrapper.GetBootstrapClassLoader(); + javaLangByte = bootClassLoader.LoadClassByDottedNameFast("java.lang.Byte"); + byteValue = javaLangByte.GetMethodWrapper("byteValue", "()B", false); + byteValue.Link(); + valueOfByte = javaLangByte.GetMethodWrapper("valueOf", "(B)Ljava.lang.Byte;", false); + valueOfByte.Link(); + javaLangBoolean = bootClassLoader.LoadClassByDottedNameFast("java.lang.Boolean"); + booleanValue = javaLangBoolean.GetMethodWrapper("booleanValue", "()Z", false); + booleanValue.Link(); + valueOfBoolean = javaLangBoolean.GetMethodWrapper("valueOf", "(Z)Ljava.lang.Boolean;", false); + valueOfBoolean.Link(); + javaLangShort = bootClassLoader.LoadClassByDottedNameFast("java.lang.Short"); + shortValue = javaLangShort.GetMethodWrapper("shortValue", "()S", false); + shortValue.Link(); + valueOfShort = javaLangShort.GetMethodWrapper("valueOf", "(S)Ljava.lang.Short;", false); + valueOfShort.Link(); + javaLangCharacter = bootClassLoader.LoadClassByDottedNameFast("java.lang.Character"); + charValue = javaLangCharacter.GetMethodWrapper("charValue", "()C", false); + charValue.Link(); + valueOfCharacter = javaLangCharacter.GetMethodWrapper("valueOf", "(C)Ljava.lang.Character;", false); + valueOfCharacter.Link(); + javaLangInteger = bootClassLoader.LoadClassByDottedNameFast("java.lang.Integer"); + intValue = javaLangInteger.GetMethodWrapper("intValue", "()I", false); + intValue.Link(); + valueOfInteger = javaLangInteger.GetMethodWrapper("valueOf", "(I)Ljava.lang.Integer;", false); + valueOfInteger.Link(); + javaLangFloat = bootClassLoader.LoadClassByDottedNameFast("java.lang.Float"); + floatValue = javaLangFloat.GetMethodWrapper("floatValue", "()F", false); + floatValue.Link(); + valueOfFloat = javaLangFloat.GetMethodWrapper("valueOf", "(F)Ljava.lang.Float;", false); + valueOfFloat.Link(); + javaLangLong = bootClassLoader.LoadClassByDottedNameFast("java.lang.Long"); + longValue = javaLangLong.GetMethodWrapper("longValue", "()J", false); + longValue.Link(); + valueOfLong = javaLangLong.GetMethodWrapper("valueOf", "(J)Ljava.lang.Long;", false); + valueOfLong.Link(); + javaLangDouble = bootClassLoader.LoadClassByDottedNameFast("java.lang.Double"); + doubleValue = javaLangDouble.GetMethodWrapper("doubleValue", "()D", false); + doubleValue.Link(); + valueOfDouble = javaLangDouble.GetMethodWrapper("valueOf", "(D)Ljava.lang.Double;", false); + valueOfDouble.Link(); + } + + internal static void EmitUnbox(CodeEmitter ilgen, TypeWrapper tw, bool cast) + { + if (tw == PrimitiveTypeWrapper.BYTE) + { + if (cast) + { + javaLangByte.EmitCheckcast(ilgen); + } + byteValue.EmitCall(ilgen); + } + else if (tw == PrimitiveTypeWrapper.BOOLEAN) + { + if (cast) + { + javaLangBoolean.EmitCheckcast(ilgen); + } + booleanValue.EmitCall(ilgen); + } + else if (tw == PrimitiveTypeWrapper.SHORT) + { + if (cast) + { + javaLangShort.EmitCheckcast(ilgen); + } + shortValue.EmitCall(ilgen); + } + else if (tw == PrimitiveTypeWrapper.CHAR) + { + if (cast) + { + javaLangCharacter.EmitCheckcast(ilgen); + } + charValue.EmitCall(ilgen); + } + else if (tw == PrimitiveTypeWrapper.INT) + { + if (cast) + { + javaLangInteger.EmitCheckcast(ilgen); + } + intValue.EmitCall(ilgen); + } + else if (tw == PrimitiveTypeWrapper.FLOAT) + { + if (cast) + { + javaLangFloat.EmitCheckcast(ilgen); + } + floatValue.EmitCall(ilgen); + } + else if (tw == PrimitiveTypeWrapper.LONG) + { + if (cast) + { + javaLangLong.EmitCheckcast(ilgen); + } + longValue.EmitCall(ilgen); + } + else if (tw == PrimitiveTypeWrapper.DOUBLE) + { + if (cast) + { + javaLangDouble.EmitCheckcast(ilgen); + } + doubleValue.EmitCall(ilgen); + } + else + { + throw new InvalidOperationException(); + } + } + + internal static void EmitBox(CodeEmitter ilgen, TypeWrapper tw) + { + if (tw == PrimitiveTypeWrapper.BYTE) + { + valueOfByte.EmitCall(ilgen); + } + else if (tw == PrimitiveTypeWrapper.BOOLEAN) + { + valueOfBoolean.EmitCall(ilgen); + } + else if (tw == PrimitiveTypeWrapper.SHORT) + { + valueOfShort.EmitCall(ilgen); + } + else if (tw == PrimitiveTypeWrapper.CHAR) + { + valueOfCharacter.EmitCall(ilgen); + } + else if (tw == PrimitiveTypeWrapper.INT) + { + valueOfInteger.EmitCall(ilgen); + } + else if (tw == PrimitiveTypeWrapper.FLOAT) + { + valueOfFloat.EmitCall(ilgen); + } + else if (tw == PrimitiveTypeWrapper.LONG) + { + valueOfLong.EmitCall(ilgen); + } + else if (tw == PrimitiveTypeWrapper.DOUBLE) + { + valueOfDouble.EmitCall(ilgen); + } + else + { + throw new InvalidOperationException(); + } + } + } +} diff --git a/runtime/ByteCode.cs b/runtime/ByteCode.cs new file mode 100644 index 0000000..4db70b4 --- /dev/null +++ b/runtime/ByteCode.cs @@ -0,0 +1,815 @@ +/* + Copyright (C) 2002, 2004, 2005, 2006 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; + +enum ByteCode : byte +{ + __nop = 0, + __aconst_null = 1, + __iconst_m1 = 2, + __iconst_0 = 3, + __iconst_1 = 4, + __iconst_2 = 5, + __iconst_3 = 6, + __iconst_4 = 7, + __iconst_5 = 8, + __lconst_0 = 9, + __lconst_1 = 10, + __fconst_0 = 11, + __fconst_1 = 12, + __fconst_2 = 13, + __dconst_0 = 14, + __dconst_1 = 15, + __bipush = 16, + __sipush = 17, + __ldc = 18, + __ldc_w = 19, + __ldc2_w = 20, + __iload = 21, + __lload = 22, + __fload = 23, + __dload = 24, + __aload = 25, + __iload_0 = 26, + __iload_1 = 27, + __iload_2 = 28, + __iload_3 = 29, + __lload_0 = 30, + __lload_1 = 31, + __lload_2 = 32, + __lload_3 = 33, + __fload_0 = 34, + __fload_1 = 35, + __fload_2 = 36, + __fload_3 = 37, + __dload_0 = 38, + __dload_1 = 39, + __dload_2 = 40, + __dload_3 = 41, + __aload_0 = 42, + __aload_1 = 43, + __aload_2 = 44, + __aload_3 = 45, + __iaload = 46, + __laload = 47, + __faload = 48, + __daload = 49, + __aaload = 50, + __baload = 51, + __caload = 52, + __saload = 53, + __istore = 54, + __lstore = 55, + __fstore = 56, + __dstore = 57, + __astore = 58, + __istore_0 = 59, + __istore_1 = 60, + __istore_2 = 61, + __istore_3 = 62, + __lstore_0 = 63, + __lstore_1 = 64, + __lstore_2 = 65, + __lstore_3 = 66, + __fstore_0 = 67, + __fstore_1 = 68, + __fstore_2 = 69, + __fstore_3 = 70, + __dstore_0 = 71, + __dstore_1 = 72, + __dstore_2 = 73, + __dstore_3 = 74, + __astore_0 = 75, + __astore_1 = 76, + __astore_2 = 77, + __astore_3 = 78, + __iastore = 79, + __lastore = 80, + __fastore = 81, + __dastore = 82, + __aastore = 83, + __bastore = 84, + __castore = 85, + __sastore = 86, + __pop = 87, + __pop2 = 88, + __dup = 89, + __dup_x1 = 90, + __dup_x2 = 91, + __dup2 = 92, + __dup2_x1 = 93, + __dup2_x2 = 94, + __swap = 95, + __iadd = 96, + __ladd = 97, + __fadd = 98, + __dadd = 99, + __isub = 100, + __lsub = 101, + __fsub = 102, + __dsub = 103, + __imul = 104, + __lmul = 105, + __fmul = 106, + __dmul = 107, + __idiv = 108, + __ldiv = 109, + __fdiv = 110, + __ddiv = 111, + __irem = 112, + __lrem = 113, + __frem = 114, + __drem = 115, + __ineg = 116, + __lneg = 117, + __fneg = 118, + __dneg = 119, + __ishl = 120, + __lshl = 121, + __ishr = 122, + __lshr = 123, + __iushr = 124, + __lushr = 125, + __iand = 126, + __land = 127, + __ior = 128, + __lor = 129, + __ixor = 130, + __lxor = 131, + __iinc = 132, + __i2l = 133, + __i2f = 134, + __i2d = 135, + __l2i = 136, + __l2f = 137, + __l2d = 138, + __f2i = 139, + __f2l = 140, + __f2d = 141, + __d2i = 142, + __d2l = 143, + __d2f = 144, + __i2b = 145, + __i2c = 146, + __i2s = 147, + __lcmp = 148, + __fcmpl = 149, + __fcmpg = 150, + __dcmpl = 151, + __dcmpg = 152, + __ifeq = 153, + __ifne = 154, + __iflt = 155, + __ifge = 156, + __ifgt = 157, + __ifle = 158, + __if_icmpeq = 159, + __if_icmpne = 160, + __if_icmplt = 161, + __if_icmpge = 162, + __if_icmpgt = 163, + __if_icmple = 164, + __if_acmpeq = 165, + __if_acmpne = 166, + __goto = 167, + __jsr = 168, + __ret = 169, + __tableswitch = 170, + __lookupswitch = 171, + __ireturn = 172, + __lreturn = 173, + __freturn = 174, + __dreturn = 175, + __areturn = 176, + __return = 177, + __getstatic = 178, + __putstatic = 179, + __getfield = 180, + __putfield = 181, + __invokevirtual = 182, + __invokespecial = 183, + __invokestatic = 184, + __invokeinterface = 185, + __invokedynamic = 186, + __new = 187, + __newarray = 188, + __anewarray = 189, + __arraylength = 190, + __athrow = 191, + __checkcast = 192, + __instanceof = 193, + __monitorenter = 194, + __monitorexit = 195, + __wide = 196, + __multianewarray = 197, + __ifnull = 198, + __ifnonnull = 199, + __goto_w = 200, + __jsr_w = 201 +} + +enum NormalizedByteCode : byte +{ + __nop = 0, + __aconst_null = 1, + __lconst_0 = 9, + __lconst_1 = 10, + __fconst_0 = 11, + __fconst_1 = 12, + __fconst_2 = 13, + __dconst_0 = 14, + __dconst_1 = 15, + __ldc = 18, + __iload = 21, + __lload = 22, + __fload = 23, + __dload = 24, + __aload = 25, + __iaload = 46, + __laload = 47, + __faload = 48, + __daload = 49, + __aaload = 50, + __baload = 51, + __caload = 52, + __saload = 53, + __istore = 54, + __lstore = 55, + __fstore = 56, + __dstore = 57, + __astore = 58, + __iastore = 79, + __lastore = 80, + __fastore = 81, + __dastore = 82, + __aastore = 83, + __bastore = 84, + __castore = 85, + __sastore = 86, + __pop = 87, + __pop2 = 88, + __dup = 89, + __dup_x1 = 90, + __dup_x2 = 91, + __dup2 = 92, + __dup2_x1 = 93, + __dup2_x2 = 94, + __swap = 95, + __iadd = 96, + __ladd = 97, + __fadd = 98, + __dadd = 99, + __isub = 100, + __lsub = 101, + __fsub = 102, + __dsub = 103, + __imul = 104, + __lmul = 105, + __fmul = 106, + __dmul = 107, + __idiv = 108, + __ldiv = 109, + __fdiv = 110, + __ddiv = 111, + __irem = 112, + __lrem = 113, + __frem = 114, + __drem = 115, + __ineg = 116, + __lneg = 117, + __fneg = 118, + __dneg = 119, + __ishl = 120, + __lshl = 121, + __ishr = 122, + __lshr = 123, + __iushr = 124, + __lushr = 125, + __iand = 126, + __land = 127, + __ior = 128, + __lor = 129, + __ixor = 130, + __lxor = 131, + __iinc = 132, + __i2l = 133, + __i2f = 134, + __i2d = 135, + __l2i = 136, + __l2f = 137, + __l2d = 138, + __f2i = 139, + __f2l = 140, + __f2d = 141, + __d2i = 142, + __d2l = 143, + __d2f = 144, + __i2b = 145, + __i2c = 146, + __i2s = 147, + __lcmp = 148, + __fcmpl = 149, + __fcmpg = 150, + __dcmpl = 151, + __dcmpg = 152, + __ifeq = 153, + __ifne = 154, + __iflt = 155, + __ifge = 156, + __ifgt = 157, + __ifle = 158, + __if_icmpeq = 159, + __if_icmpne = 160, + __if_icmplt = 161, + __if_icmpge = 162, + __if_icmpgt = 163, + __if_icmple = 164, + __if_acmpeq = 165, + __if_acmpne = 166, + __goto = 167, + __jsr = 168, + __ret = 169, + __tableswitch = 170, + __lookupswitch = 171, + __ireturn = 172, + __lreturn = 173, + __freturn = 174, + __dreturn = 175, + __areturn = 176, + __return = 177, + __getstatic = 178, + __putstatic = 179, + __getfield = 180, + __putfield = 181, + __invokevirtual = 182, + __invokespecial = 183, + __invokestatic = 184, + __invokeinterface = 185, + __invokedynamic = 186, + __new = 187, + __newarray = 188, + __anewarray = 189, + __arraylength = 190, + __athrow = 191, + __checkcast = 192, + __instanceof = 193, + __monitorenter = 194, + __monitorexit = 195, + __multianewarray = 197, + __ifnull = 198, + __ifnonnull = 199, + // This is where the pseudo-bytecodes start + __privileged_invokestatic = 235, // the privileged bytecodes are used for accessing host class members + __privileged_invokevirtual = 237, + __privileged_invokespecial = 238, + __ldc_nothrow = 239, + __methodhandle_invoke = 240, + __methodhandle_link = 241, + __goto_finally = 242, + __intrinsic_gettype = 243, + __athrow_no_unmap = 244, + __dynamic_getstatic = 245, + __dynamic_putstatic = 246, + __dynamic_getfield = 247, + __dynamic_putfield = 248, + __dynamic_invokeinterface = 249, + __dynamic_invokestatic = 250, + __dynamic_invokevirtual = 251, + __dynamic_invokespecial = 252, + __clone_array = 253, + __static_error = 254, // not a real instruction, this signals an instruction that is compiled as an exception + __iconst = 255 +} + +enum ByteCodeMode : byte +{ + Unused, + Simple, + Constant_1, + Constant_2, + Branch_2, + Local_1, + Constant_2_1_1, + Immediate_1, + Immediate_2, + Local_1_Immediate_1, + Tableswitch, + Lookupswitch, + Constant_2_Immediate_1, + Branch_4, + WidePrefix +} + +enum ByteCodeModeWide : byte +{ + Unused, + Local_2, + Local_2_Immediate_2 +} + +[Flags] +enum ByteCodeFlags : byte +{ + None = 0, + FixedArg = 1, + CannotThrow = 2 +} + +enum ByteCodeFlowControl : byte +{ + Next, + Branch, + CondBranch, + Return, + Throw, + Switch, +} + +struct ByteCodeMetaData +{ + private static ByteCodeMetaData[] data = new ByteCodeMetaData[256]; + private ByteCodeMode reg; + private ByteCodeModeWide wide; + private NormalizedByteCode normbc; + private ByteCodeFlags flags; + private int arg; + + private ByteCodeMetaData(ByteCode bc, ByteCodeMode reg, ByteCodeModeWide wide, bool cannotThrow) + { + this.reg = reg; + this.wide = wide; + this.normbc = (NormalizedByteCode)bc; + this.arg = 0; + this.flags = ByteCodeFlags.None; + if(cannotThrow) + { + this.flags |= ByteCodeFlags.CannotThrow; + } + data[(int)bc] = this; + } + + private ByteCodeMetaData(ByteCode bc, NormalizedByteCode normbc, ByteCodeMode reg, ByteCodeModeWide wide, bool cannotThrow) + { + this.reg = reg; + this.wide = wide; + this.normbc = normbc; + this.arg = 0; + this.flags = ByteCodeFlags.None; + if(cannotThrow) + { + this.flags |= ByteCodeFlags.CannotThrow; + } + data[(int)bc] = this; + } + + private ByteCodeMetaData(ByteCode bc, NormalizedByteCode normbc, int arg, ByteCodeMode reg, ByteCodeModeWide wide, bool cannotThrow) + { + this.reg = reg; + this.wide = wide; + this.normbc = normbc; + this.arg = arg; + this.flags = ByteCodeFlags.FixedArg; + if(cannotThrow) + { + this.flags |= ByteCodeFlags.CannotThrow; + } + data[(int)bc] = this; + } + + internal static NormalizedByteCode GetNormalizedByteCode(ByteCode bc) + { + return data[(int)bc].normbc; + } + + internal static int GetArg(ByteCode bc, int arg) + { + if((data[(int)bc].flags & ByteCodeFlags.FixedArg) != 0) + { + return data[(int)bc].arg; + } + return arg; + } + + internal static ByteCodeMode GetMode(ByteCode bc) + { + return data[(int)bc].reg; + } + + internal static ByteCodeModeWide GetWideMode(ByteCode bc) + { + return data[(int)bc].wide; + } + + internal static ByteCodeFlowControl GetFlowControl(NormalizedByteCode bc) + { + switch (bc) + { + case NormalizedByteCode.__tableswitch: + case NormalizedByteCode.__lookupswitch: + return ByteCodeFlowControl.Switch; + + case NormalizedByteCode.__goto: + case NormalizedByteCode.__goto_finally: + return ByteCodeFlowControl.Branch; + + case NormalizedByteCode.__ifeq: + case NormalizedByteCode.__ifne: + case NormalizedByteCode.__iflt: + case NormalizedByteCode.__ifge: + case NormalizedByteCode.__ifgt: + case NormalizedByteCode.__ifle: + case NormalizedByteCode.__if_icmpeq: + case NormalizedByteCode.__if_icmpne: + case NormalizedByteCode.__if_icmplt: + case NormalizedByteCode.__if_icmpge: + case NormalizedByteCode.__if_icmpgt: + case NormalizedByteCode.__if_icmple: + case NormalizedByteCode.__if_acmpeq: + case NormalizedByteCode.__if_acmpne: + case NormalizedByteCode.__ifnull: + case NormalizedByteCode.__ifnonnull: + return ByteCodeFlowControl.CondBranch; + + case NormalizedByteCode.__ireturn: + case NormalizedByteCode.__lreturn: + case NormalizedByteCode.__freturn: + case NormalizedByteCode.__dreturn: + case NormalizedByteCode.__areturn: + case NormalizedByteCode.__return: + return ByteCodeFlowControl.Return; + + case NormalizedByteCode.__athrow: + case NormalizedByteCode.__athrow_no_unmap: + case NormalizedByteCode.__static_error: + return ByteCodeFlowControl.Throw; + + default: + return ByteCodeFlowControl.Next; + } + } + + internal static bool CanThrowException(NormalizedByteCode bc) + { + switch(bc) + { + case NormalizedByteCode.__dynamic_invokeinterface: + case NormalizedByteCode.__dynamic_invokestatic: + case NormalizedByteCode.__dynamic_invokevirtual: + case NormalizedByteCode.__dynamic_getstatic: + case NormalizedByteCode.__dynamic_putstatic: + case NormalizedByteCode.__dynamic_getfield: + case NormalizedByteCode.__dynamic_putfield: + case NormalizedByteCode.__clone_array: + case NormalizedByteCode.__static_error: + case NormalizedByteCode.__methodhandle_invoke: + case NormalizedByteCode.__methodhandle_link: + return true; + case NormalizedByteCode.__iconst: + case NormalizedByteCode.__ldc_nothrow: + return false; + default: + return (data[(int)bc].flags & ByteCodeFlags.CannotThrow) == 0; + } + } + + internal static bool IsBranch(NormalizedByteCode bc) + { + switch (data[(int)bc].reg) + { + case ByteCodeMode.Branch_2: + case ByteCodeMode.Branch_4: + case ByteCodeMode.Lookupswitch: + case ByteCodeMode.Tableswitch: + return true; + default: + return false; + } + } + + static ByteCodeMetaData() + { + new ByteCodeMetaData(ByteCode.__nop, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__aconst_null, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iconst_m1, NormalizedByteCode.__iconst, -1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iconst_0, NormalizedByteCode.__iconst, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iconst_1, NormalizedByteCode.__iconst, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iconst_2, NormalizedByteCode.__iconst, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iconst_3, NormalizedByteCode.__iconst, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iconst_4, NormalizedByteCode.__iconst, 4, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iconst_5, NormalizedByteCode.__iconst, 5, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lconst_0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lconst_1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fconst_0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fconst_1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fconst_2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dconst_0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dconst_1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__bipush, NormalizedByteCode.__iconst, ByteCodeMode.Immediate_1, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__sipush, NormalizedByteCode.__iconst, ByteCodeMode.Immediate_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ldc, ByteCodeMode.Constant_1, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__ldc_w, NormalizedByteCode.__ldc, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__ldc2_w, NormalizedByteCode.__ldc, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__iload, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__lload, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__fload, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__dload, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__aload, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__iload_0, NormalizedByteCode.__iload, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iload_1, NormalizedByteCode.__iload, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iload_2, NormalizedByteCode.__iload, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iload_3, NormalizedByteCode.__iload, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lload_0, NormalizedByteCode.__lload, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lload_1, NormalizedByteCode.__lload, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lload_2, NormalizedByteCode.__lload, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lload_3, NormalizedByteCode.__lload, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fload_0, NormalizedByteCode.__fload, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fload_1, NormalizedByteCode.__fload, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fload_2, NormalizedByteCode.__fload, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fload_3, NormalizedByteCode.__fload, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dload_0, NormalizedByteCode.__dload, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dload_1, NormalizedByteCode.__dload, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dload_2, NormalizedByteCode.__dload, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dload_3, NormalizedByteCode.__dload, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__aload_0, NormalizedByteCode.__aload, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__aload_1, NormalizedByteCode.__aload, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__aload_2, NormalizedByteCode.__aload, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__aload_3, NormalizedByteCode.__aload, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iaload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__laload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__faload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__daload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__aaload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__baload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__caload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__saload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__istore, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__lstore, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__fstore, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__dstore, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__astore, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__istore_0, NormalizedByteCode.__istore, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__istore_1, NormalizedByteCode.__istore, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__istore_2, NormalizedByteCode.__istore, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__istore_3, NormalizedByteCode.__istore, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lstore_0, NormalizedByteCode.__lstore, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lstore_1, NormalizedByteCode.__lstore, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lstore_2, NormalizedByteCode.__lstore, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lstore_3, NormalizedByteCode.__lstore, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fstore_0, NormalizedByteCode.__fstore, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fstore_1, NormalizedByteCode.__fstore, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fstore_2, NormalizedByteCode.__fstore, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fstore_3, NormalizedByteCode.__fstore, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dstore_0, NormalizedByteCode.__dstore, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dstore_1, NormalizedByteCode.__dstore, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dstore_2, NormalizedByteCode.__dstore, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dstore_3, NormalizedByteCode.__dstore, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__astore_0, NormalizedByteCode.__astore, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__astore_1, NormalizedByteCode.__astore, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__astore_2, NormalizedByteCode.__astore, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__astore_3, NormalizedByteCode.__astore, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__lastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__fastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__dastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__aastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__bastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__castore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__sastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__pop, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__pop2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dup, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dup_x1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dup_x2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dup2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dup2_x1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dup2_x2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__swap, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iadd, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ladd, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fadd, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dadd, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__isub, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lsub, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fsub, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dsub, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__imul, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lmul, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fmul, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dmul, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__idiv, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__ldiv, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__fdiv, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ddiv, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__irem, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__lrem, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__frem, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__drem, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ineg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lneg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fneg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dneg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ishl, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lshl, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ishr, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lshr, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iushr, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lushr, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iand, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__land, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ior, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lor, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ixor, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lxor, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iinc, ByteCodeMode.Local_1_Immediate_1, ByteCodeModeWide.Local_2_Immediate_2, true); + new ByteCodeMetaData(ByteCode.__i2l, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__i2f, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__i2d, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__l2i, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__l2f, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__l2d, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__f2i, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__f2l, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__f2d, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__d2i, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__d2l, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__d2f, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__i2b, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__i2c, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__i2s, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lcmp, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fcmpl, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fcmpg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dcmpl, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dcmpg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ifeq, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ifne, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iflt, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ifge, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ifgt, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ifle, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_icmpeq, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_icmpne, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_icmplt, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_icmpge, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_icmpgt, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_icmple, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_acmpeq, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_acmpne, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__goto, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__jsr, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ret, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__tableswitch, ByteCodeMode.Tableswitch, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lookupswitch, ByteCodeMode.Lookupswitch, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ireturn, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lreturn, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__freturn, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dreturn, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__areturn, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__return, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__getstatic, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__putstatic, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__getfield, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__putfield, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__invokevirtual, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__invokespecial, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__invokestatic, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__invokeinterface, ByteCodeMode.Constant_2_1_1, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__invokedynamic, ByteCodeMode.Constant_2_1_1, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__new, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__newarray, ByteCodeMode.Immediate_1, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__anewarray, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__arraylength, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__athrow, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__checkcast, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__instanceof, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__monitorenter, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__monitorexit, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__wide, NormalizedByteCode.__nop, ByteCodeMode.WidePrefix, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__multianewarray, ByteCodeMode.Constant_2_Immediate_1, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__ifnull, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ifnonnull, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__goto_w, NormalizedByteCode.__goto, ByteCodeMode.Branch_4, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__jsr_w, NormalizedByteCode.__jsr, ByteCodeMode.Branch_4, ByteCodeModeWide.Unused, true); + } +} diff --git a/runtime/ByteCodeHelper.cs b/runtime/ByteCodeHelper.cs new file mode 100644 index 0000000..ed23a77 --- /dev/null +++ b/runtime/ByteCodeHelper.cs @@ -0,0 +1,1265 @@ +/* + Copyright (C) 2002-2015 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Reflection; +using System.Diagnostics; +using System.Threading; +using IKVM.Attributes; +using IKVM.Internal; +using System.Runtime.InteropServices; + +namespace IKVM.Runtime +{ + static class GhostTag + { + private static volatile PassiveWeakDictionary dict; + + internal static void SetTag(object obj, RuntimeTypeHandle typeHandle) + { + SetTag(obj, ClassLoaderWrapper.GetWrapperFromType(Type.GetTypeFromHandle(typeHandle))); + } + + internal static void SetTag(object obj, TypeWrapper wrapper) + { + if(dict == null) + { + PassiveWeakDictionary newDict = new PassiveWeakDictionary(); +#pragma warning disable 0420 // don't whine about CompareExchange not respecting 'volatile' + if(Interlocked.CompareExchange(ref dict, newDict, null) != null) +#pragma warning restore + { + newDict.Dispose(); + } + } + dict.Add(obj, wrapper); + } + + internal static TypeWrapper GetTag(object obj) + { + if(dict != null) + { + TypeWrapper tw; + dict.TryGetValue(obj, out tw); + return tw; + } + return null; + } + + // this method is called from .IsInstanceArray() + internal static bool IsGhostArrayInstance(object obj, RuntimeTypeHandle typeHandle, int rank) + { + TypeWrapper tw1 = GhostTag.GetTag(obj); + if(tw1 != null) + { + TypeWrapper tw2 = ClassLoaderWrapper.GetWrapperFromType(Type.GetTypeFromHandle(typeHandle)).MakeArrayType(rank); + return tw1.IsAssignableTo(tw2); + } + return false; + } + + // this method is called from .CastArray() + [HideFromJava] + internal static void ThrowClassCastException(object obj, RuntimeTypeHandle typeHandle, int rank) + { +#if !FIRST_PASS + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + sb.Append(ikvm.runtime.Util.getClassFromObject(obj).getName()).Append(" cannot be cast to ") + .Append('[', rank).Append('L').Append(ikvm.runtime.Util.getClassFromTypeHandle(typeHandle).getName()).Append(';'); + throw new java.lang.ClassCastException(sb.ToString()); +#endif + } + } + + public static class ByteCodeHelper + { + [DebuggerStepThroughAttribute] + public static object multianewarray(RuntimeTypeHandle typeHandle, int[] lengths) + { + for(int i = 0; i < lengths.Length; i++) + { + if(lengths[i] < 0) + { +#if !FIRST_PASS + throw new java.lang.NegativeArraySizeException(); +#endif + } + } + return MultianewarrayHelper(Type.GetTypeFromHandle(typeHandle).GetElementType(), lengths, 0); + } + + private static object MultianewarrayHelper(Type elemType, int[] lengths, int index) + { + object o = Array.CreateInstance(elemType, lengths[index++]); + if(index < lengths.Length) + { + elemType = elemType.GetElementType(); + object[] a = (object[])o; + for(int i = 0; i < a.Length; i++) + { + a[i] = MultianewarrayHelper(elemType, lengths, index); + } + } + return o; + } + + [DebuggerStepThroughAttribute] + public static object multianewarray_ghost(RuntimeTypeHandle typeHandle, int[] lengths) + { + Type type = Type.GetTypeFromHandle(typeHandle); + int rank = 0; + while(ReflectUtil.IsVector(type)) + { + rank++; + type = type.GetElementType(); + } + object obj = multianewarray(ArrayTypeWrapper.MakeArrayType(typeof(object), rank).TypeHandle, lengths); + GhostTag.SetTag(obj, typeHandle); + return obj; + } + + [DebuggerStepThroughAttribute] + public static T[] anewarray_ghost(int length, RuntimeTypeHandle typeHandle) + { + T[] obj = new T[length]; + GhostTag.SetTag(obj, typeHandle); + return obj; + } + + [DebuggerStepThroughAttribute] + public static object DynamicMultianewarray(int[] lengths, java.lang.Class clazz) + { +#if FIRST_PASS + return null; +#else + Profiler.Count("DynamicMultianewarray"); + TypeWrapper wrapper = TypeWrapper.FromClass(clazz); + object obj = multianewarray(wrapper.TypeAsArrayType.TypeHandle, lengths); + if (wrapper.IsGhostArray) + { + GhostTag.SetTag(obj, wrapper); + } + return obj; +#endif + } + + [DebuggerStepThroughAttribute] + public static object DynamicNewarray(int length, java.lang.Class clazz) + { +#if FIRST_PASS + return null; +#else + Profiler.Count("DynamicNewarray"); + if(length < 0) + { + throw new java.lang.NegativeArraySizeException(); + } + TypeWrapper wrapper = TypeWrapper.FromClass(clazz); + Array obj = Array.CreateInstance(wrapper.TypeAsArrayType, length); + if (wrapper.IsGhost || wrapper.IsGhostArray) + { + GhostTag.SetTag(obj, wrapper.MakeArrayType(1)); + } + return obj; +#endif + } + + [DebuggerStepThroughAttribute] + public static void DynamicAastore(object arrayref, int index, object val) + { +#if !FIRST_PASS + Profiler.Count("DynamicAastore"); + ((Array)arrayref).SetValue(val, index); +#endif + } + + [DebuggerStepThroughAttribute] + public static object DynamicAaload(object arrayref, int index) + { +#if FIRST_PASS + return null; +#else + Profiler.Count("DynamicAaload"); + return ((Array)arrayref).GetValue(index); +#endif + } + + // the sole purpose of this method is to check whether the clazz can be instantiated (but not to actually do it) + [DebuggerStepThroughAttribute] + public static void DynamicNewCheckOnly(java.lang.Class clazz) + { +#if !FIRST_PASS + Profiler.Count("DynamicNewCheckOnly"); + TypeWrapper wrapper = TypeWrapper.FromClass(clazz); + if(wrapper.IsAbstract) + { + throw new java.lang.InstantiationError(wrapper.Name); + } + wrapper.RunClassInit(); +#endif + } + + private static TypeWrapper LoadTypeWrapper(string clazz, ikvm.@internal.CallerID callerId) + { +#if FIRST_PASS + return null; +#else + try + { + TypeWrapper context = TypeWrapper.FromClass(callerId.getCallerClass()); + TypeWrapper wrapper = ClassLoaderWrapper.FromCallerID(callerId).LoadClassByDottedName(clazz); + java.lang.ClassLoader loader = callerId.getCallerClassLoader(); + if(loader != null) + { + loader.checkPackageAccess(wrapper.ClassObject, callerId.getCallerClass().pd); + } + if(!wrapper.IsAccessibleFrom(context)) + { + throw new java.lang.IllegalAccessError("Try to access class " + wrapper.Name + " from class " + context.Name); + } + wrapper.Finish(); + return wrapper; + } + catch(RetargetableJavaException x) + { + throw x.ToJava(); + } +#endif + } + + [DebuggerStepThroughAttribute] + public static java.lang.Class DynamicClassLiteral(string clazz, ikvm.@internal.CallerID callerId) + { +#if FIRST_PASS + return null; +#else + Profiler.Count("DynamicClassLiteral"); + return LoadTypeWrapper(clazz, callerId).ClassObject; +#endif + } + + [DebuggerStepThroughAttribute] + public static object DynamicCast(object obj, java.lang.Class clazz) + { +#if FIRST_PASS + return null; +#else + Debug.Assert(obj != null); + Profiler.Count("DynamicCast"); + if (!DynamicInstanceOf(obj, clazz)) + { + throw new java.lang.ClassCastException(NativeCode.ikvm.runtime.Util.GetTypeWrapperFromObject(obj).Name + " cannot be cast to " + clazz.getName()); + } + return obj; +#endif + } + + [DebuggerStepThroughAttribute] + public static bool DynamicInstanceOf(object obj, java.lang.Class clazz) + { +#if FIRST_PASS + return false; +#else + Debug.Assert(obj != null); + Profiler.Count("DynamicInstanceOf"); + TypeWrapper tw = TypeWrapper.FromClass(clazz); + // we have to mimick the bytecode behavior, which allows these .NET-isms to show through + if (tw.TypeAsBaseType == typeof(Array)) + { + return obj is Array; + } + if (tw.TypeAsBaseType == typeof(string)) + { + return obj is string; + } + if (tw.TypeAsBaseType == typeof(IComparable)) + { + return obj is IComparable; + } + return tw.IsInstance(obj); +#endif + } + + [DebuggerStepThrough] + public static java.lang.invoke.MethodType DynamicLoadMethodType(ref java.lang.invoke.MethodType cache, string sig, ikvm.@internal.CallerID callerID) + { + if (cache == null) + { + DynamicLoadMethodTypeImpl(ref cache, sig, callerID); + } + return cache; + } + + private static void DynamicLoadMethodTypeImpl(ref java.lang.invoke.MethodType cache, string sig, ikvm.@internal.CallerID callerID) + { +#if !FIRST_PASS + try + { + ClassLoaderWrapper loader = ClassLoaderWrapper.FromCallerID(callerID); + TypeWrapper[] args = loader.ArgTypeWrapperListFromSig(sig, LoadMode.LoadOrThrow); + java.lang.Class[] ptypes = new java.lang.Class[args.Length]; + for (int i = 0; i < ptypes.Length; i++) + { + ptypes[i] = args[i].ClassObject; + } + Interlocked.CompareExchange(ref cache, java.lang.invoke.MethodType.methodType(loader.RetTypeWrapperFromSig(sig, LoadMode.LoadOrThrow).ClassObject, ptypes), null); + } + catch (RetargetableJavaException x) + { + throw x.ToJava(); + } +#endif + } + + [DebuggerStepThrough] + public static java.lang.invoke.MethodHandle DynamicLoadMethodHandle(ref java.lang.invoke.MethodHandle cache, int kind, string clazz, string name, string sig, ikvm.@internal.CallerID callerID) + { + if (cache == null) + { + Interlocked.CompareExchange(ref cache, DynamicLoadMethodHandleImpl(kind, clazz, name, sig, callerID), null); + } + return cache; + } + + private static java.lang.invoke.MethodHandle DynamicLoadMethodHandleImpl(int kind, string clazz, string name, string sig, ikvm.@internal.CallerID callerID) + { +#if FIRST_PASS + return null; +#else + java.lang.Class refc = LoadTypeWrapper(clazz, callerID).ClassObject; + try + { + switch ((ClassFile.RefKind)kind) + { + case ClassFile.RefKind.getStatic: + case ClassFile.RefKind.putStatic: + case ClassFile.RefKind.getField: + case ClassFile.RefKind.putField: + java.lang.Class type = ClassLoaderWrapper.FromCallerID(callerID).FieldTypeWrapperFromSig(sig, LoadMode.LoadOrThrow).ClassObject; + return java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(callerID.getCallerClass(), kind, refc, name, type); + default: + java.lang.invoke.MethodType mt = null; + DynamicLoadMethodType(ref mt, sig, callerID); + // HACK linkMethodHandleConstant is broken for MethodHandle.invoke[Exact] + if (kind == (int)ClassFile.RefKind.invokeVirtual && refc == CoreClasses.java.lang.invoke.MethodHandle.Wrapper.ClassObject) + { + switch (name) + { + case "invokeExact": + return java.lang.invoke.MethodHandles.exactInvoker(mt); + case "invoke": + return java.lang.invoke.MethodHandles.invoker(mt); + } + } + return java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(callerID.getCallerClass(), kind, refc, name, mt); + } + } + catch (RetargetableJavaException x) + { + throw x.ToJava(); + } +#endif + } + + [DebuggerStepThrough] + public static T DynamicBinderMemberLookup(int kind, string clazz, string name, string sig, ikvm.@internal.CallerID callerID) + where T : class /* delegate */ + { +#if FIRST_PASS + return null; +#else + try + { + java.lang.invoke.MethodHandle mh = DynamicLoadMethodHandleImpl(kind, clazz, name, sig, callerID); + return GetDelegateForInvokeExact(java.lang.invoke.MethodHandles.explicitCastArguments(mh, MethodHandleUtil.GetDelegateMethodType(typeof(T)))); + } + catch (java.lang.IncompatibleClassChangeError x) + { + if (x.getCause() is java.lang.NoSuchMethodException) + { + throw new java.lang.NoSuchMethodError(x.getCause().Message); + } + if (x.getCause() is java.lang.NoSuchFieldException) + { + throw new java.lang.NoSuchFieldError(x.getCause().Message); + } + if (x.getCause() is java.lang.IllegalAccessException) + { + throw new java.lang.IllegalAccessError(x.getCause().Message); + } + throw; + } +#endif + } + + [DebuggerStepThrough] + public static Delegate DynamicCreateDelegate(object obj, Type delegateType, string name, string sig) + { +#if FIRST_PASS + return null; +#else + TypeWrapper tw = TypeWrapper.FromClass(ikvm.runtime.Util.getClassFromObject(obj)); + MethodWrapper mw = tw.GetMethodWrapper(name, sig, true); + if (mw == null || mw.IsStatic || !mw.IsPublic) + { +#if NO_REF_EMIT + java.lang.invoke.MethodType methodType = MethodHandleUtil.GetDelegateMethodType(delegateType); + if (methodType.parameterCount() > MethodHandleUtil.MaxArity) + { + throw new NotImplementedException(); + } + java.lang.invoke.MethodHandle exception = java.lang.invoke.MethodHandles.publicLookup() + .findConstructor(mw == null || mw.IsStatic ? typeof(java.lang.AbstractMethodError) : typeof(java.lang.IllegalAccessError), + java.lang.invoke.MethodType.methodType(typeof(void), typeof(string))) + .bindTo(tw.Name + ".Invoke" + sig); + return Delegate.CreateDelegate(delegateType, + java.lang.invoke.MethodHandles.dropArguments( + java.lang.invoke.MethodHandles.foldArguments(java.lang.invoke.MethodHandles.throwException(methodType.returnType(), exception.type().returnType()), exception), + 0, methodType.parameterArray()).vmtarget, "Invoke"); +#else + MethodInfo invoke = delegateType.GetMethod("Invoke"); + ParameterInfo[] parameters = invoke.GetParameters(); + Type[] parameterTypes = new Type[parameters.Length + 1]; + parameterTypes[0] = typeof(object); + for (int i = 0; i < parameters.Length; i++) + { + parameterTypes[i + 1] = parameters[i].ParameterType; + } + System.Reflection.Emit.DynamicMethod dm = new System.Reflection.Emit.DynamicMethod("Invoke", invoke.ReturnType, parameterTypes); + CodeEmitter ilgen = CodeEmitter.Create(dm); + ilgen.Emit(System.Reflection.Emit.OpCodes.Ldstr, tw.Name + ".Invoke" + sig); + ClassLoaderWrapper.GetBootstrapClassLoader() + .LoadClassByDottedName(mw == null || mw.IsStatic ? "java.lang.AbstractMethodError" : "java.lang.IllegalAccessError") + .GetMethodWrapper("", "(Ljava.lang.String;)V", false) + .EmitNewobj(ilgen); + ilgen.Emit(System.Reflection.Emit.OpCodes.Throw); + ilgen.DoEmit(); + return dm.CreateDelegate(delegateType, obj); +#endif + } + else + { + mw.ResolveMethod(); + return Delegate.CreateDelegate(delegateType, obj, (MethodInfo)mw.GetMethod()); + } +#endif + } + + [DebuggerStepThrough] + public static ikvm.@internal.CallerID DynamicCallerID(object capability) + { + return ((DynamicCallerIDProvider)capability).GetCallerID(); + } + + [DebuggerStepThrough] + public static java.lang.invoke.MethodHandle DynamicEraseInvokeExact(java.lang.invoke.MethodHandle mh, java.lang.invoke.MethodType expected, java.lang.invoke.MethodType target) + { +#if FIRST_PASS + return null; +#else + if (mh.type() != expected) + { + throw new java.lang.invoke.WrongMethodTypeException(); + } + return java.lang.invoke.MethodHandles.explicitCastArguments(mh, target); +#endif + } + + [DebuggerStepThroughAttribute] + public static int f2i(float f) + { + if (f > int.MinValue && f < int.MaxValue) + { + return (int)f; + } + if (f <= int.MinValue) + { + return int.MinValue; + } + if (f >= int.MaxValue) + { + return int.MaxValue; + } + return 0; + } + + [DebuggerStepThroughAttribute] + public static long f2l(float f) + { + if (f > long.MinValue && f < long.MaxValue) + { + return (long)f; + } + if (f <= long.MinValue) + { + return long.MinValue; + } + if (f >= long.MaxValue) + { + return long.MaxValue; + } + return 0; + } + + [DebuggerStepThroughAttribute] + public static int d2i(double d) + { + if (d > int.MinValue && d < int.MaxValue) + { + return (int)d; + } + if (d <= int.MinValue) + { + return int.MinValue; + } + if (d >= int.MaxValue) + { + return int.MaxValue; + } + return 0; + } + + [DebuggerStepThroughAttribute] + public static long d2l(double d) + { + if (d > long.MinValue && d < long.MaxValue) + { + return (long)d; + } + if (d <= long.MinValue) + { + return long.MinValue; + } + if (d >= long.MaxValue) + { + return long.MaxValue; + } + return 0; + } + + // This is used by static JNI and synchronized methods that need a class object + [DebuggerStepThroughAttribute] + public static object GetClassFromTypeHandle(RuntimeTypeHandle typeHandle) + { + return NativeCode.ikvm.runtime.Util.getClassFromTypeHandle(typeHandle); + } + + [DebuggerStepThroughAttribute] + public static void arraycopy(object src, int srcStart, object dest, int destStart, int len) + { +#if !FIRST_PASS + // If the two arrays are the same, we can use the fast path, but we're also required to do so, + // to get the required memmove semantics. + if(src == dest) + { + try + { + arraycopy_fast((Array)src, srcStart, (Array)dest, destStart, len); + return; + } + catch(InvalidCastException) + { + throw new java.lang.ArrayStoreException(); + } + } + else if(src == null || dest == null) + { + throw new java.lang.NullPointerException(); + } + else if(len < 0) + { + throw new java.lang.ArrayIndexOutOfBoundsException(); + } + else + { + object[] src1 = src as object[]; + object[] dst1 = dest as object[]; + if(src1 != null && dst1 != null) + { + // for small copies, don't bother comparing the types as this is relatively expensive + if(len > 50 && src.GetType() == dest.GetType()) + { + arraycopy_fast(src1, srcStart, dst1, destStart, len); + return; + } + else + { + for(; len > 0; len--) + { + // NOTE we don't need to catch ArrayTypeMismatchException & IndexOutOfRangeException, because + // they automatically get converted to the Java equivalents anyway. + dst1[destStart++] = src1[srcStart++]; + } + return; + } + } + else if(src.GetType() != dest.GetType() && + (IsPrimitiveArrayType(src.GetType()) || IsPrimitiveArrayType(dest.GetType()))) + { + // we don't want to allow copying a primitive into an object array! + throw new java.lang.ArrayStoreException(); + } + else + { + try + { + arraycopy_fast((Array)src, srcStart, (Array)dest, destStart, len); + return; + } + catch(InvalidCastException) + { + throw new java.lang.ArrayStoreException(); + } + } + } +#endif // !FIRST_PASS + } + + private static bool IsPrimitiveArrayType(Type type) + { + return type.IsArray && ClassLoaderWrapper.GetWrapperFromType(type.GetElementType()).IsPrimitive; + } + + [DebuggerStepThroughAttribute] + public static void arraycopy_fast(Array src, int srcStart, Array dest, int destStart, int len) + { +#if !FIRST_PASS + try + { + Array.Copy(src, srcStart, dest, destStart, len); + } + catch(ArgumentNullException) + { + throw new java.lang.NullPointerException(); + } + catch(ArgumentException) + { + throw new java.lang.ArrayIndexOutOfBoundsException(); + } +#endif // !FIRST_PASS + } + + [DebuggerStepThroughAttribute] + public static void arraycopy_primitive_8(Array src, int srcStart, Array dest, int destStart, int len) + { +#if !FIRST_PASS + try + { + checked + { + Buffer.BlockCopy(src, srcStart * 8, dest, destStart * 8, len * 8); + return; + } + } + catch(ArgumentNullException) + { + throw new java.lang.NullPointerException(); + } + catch(OverflowException) + { + throw new java.lang.ArrayIndexOutOfBoundsException(); + } + catch(ArgumentException) + { + throw new java.lang.ArrayIndexOutOfBoundsException(); + } +#endif // !FIRST_PASS + } + + [DebuggerStepThroughAttribute] + public static void arraycopy_primitive_4(Array src, int srcStart, Array dest, int destStart, int len) + { +#if !FIRST_PASS + try + { + checked + { + Buffer.BlockCopy(src, srcStart * 4, dest, destStart * 4, len * 4); + return; + } + } + catch(ArgumentNullException) + { + throw new java.lang.NullPointerException(); + } + catch(OverflowException) + { + throw new java.lang.ArrayIndexOutOfBoundsException(); + } + catch(ArgumentException) + { + throw new java.lang.ArrayIndexOutOfBoundsException(); + } +#endif // !FIRST_PASS + } + + [DebuggerStepThroughAttribute] + public static void arraycopy_primitive_2(Array src, int srcStart, Array dest, int destStart, int len) + { +#if !FIRST_PASS + try + { + checked + { + Buffer.BlockCopy(src, srcStart * 2, dest, destStart * 2, len * 2); + return; + } + } + catch(ArgumentNullException) + { + throw new java.lang.NullPointerException(); + } + catch(OverflowException) + { + throw new java.lang.ArrayIndexOutOfBoundsException(); + } + catch(ArgumentException) + { + throw new java.lang.ArrayIndexOutOfBoundsException(); + } +#endif // !FIRST_PASS + } + + [DebuggerStepThroughAttribute] + public static void arraycopy_primitive_1(Array src, int srcStart, Array dest, int destStart, int len) + { +#if !FIRST_PASS + try + { + Buffer.BlockCopy(src, srcStart, dest, destStart, len); + return; + } + catch(ArgumentNullException) + { + throw new java.lang.NullPointerException(); + } + catch(OverflowException) + { + throw new java.lang.ArrayIndexOutOfBoundsException(); + } + catch(ArgumentException) + { + throw new java.lang.ArrayIndexOutOfBoundsException(); + } +#endif // !FIRST_PASS + } + + [HideFromJava] + public static void VerboseCastFailure(RuntimeTypeHandle typeHandle, object obj) + { +#if !FIRST_PASS + Type t1 = obj.GetType(); + Type t2 = Type.GetTypeFromHandle(typeHandle); + string msg; + if(t1.Assembly.FullName == t2.Assembly.FullName && t1.Assembly.Location != t2.Assembly.Location) + { + string l1 = t1.Assembly.Location; + string l2 = t2.Assembly.Location; + if(l1 == "") + { + l1 = "unknown location"; + } + if(l2 == "") + { + l2 = "unknown location"; + } + msg = String.Format("Object of type \"{0}\" loaded from {1} cannot be cast to \"{2}\" loaded from {3}", t1.AssemblyQualifiedName, l1, t2.AssemblyQualifiedName, l2); + } + else + { + msg = String.Format("Object of type \"{0}\" cannot be cast to \"{1}\"", t1.AssemblyQualifiedName, t2.AssemblyQualifiedName); + } + throw new java.lang.ClassCastException(msg); +#endif // !FIRST_PASS + } + + public static bool SkipFinalizer() + { +#if FIRST_PASS + return false; +#else + return Environment.HasShutdownStarted && !java.lang.Shutdown.runFinalizersOnExit; +#endif + } + + public static long VolatileRead(ref long v) + { +#if NO_REF_EMIT && !FIRST_PASS + lock (VolatileLongDoubleFieldWrapper.lockObject) + { + return v; + } +#else + return Interlocked.Read(ref v); +#endif + } + + public static void VolatileWrite(ref long v, long newValue) + { +#if NO_REF_EMIT && !FIRST_PASS + lock (VolatileLongDoubleFieldWrapper.lockObject) + { + v = newValue; + } +#else + Interlocked.Exchange(ref v, newValue); +#endif + } + + public static double VolatileRead(ref double v) + { +#if NO_REF_EMIT && !FIRST_PASS + lock (VolatileLongDoubleFieldWrapper.lockObject) + { + return v; + } +#else + return Interlocked.CompareExchange(ref v, 0.0, 0.0); +#endif + } + + public static void VolatileWrite(ref double v, double newValue) + { +#if NO_REF_EMIT && !FIRST_PASS + lock (VolatileLongDoubleFieldWrapper.lockObject) + { + v = newValue; + } +#else + Interlocked.Exchange(ref v, newValue); +#endif + } + + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] + public static void InitializeModule(Module module) + { + Assembly asm = Assembly.GetCallingAssembly(); + if (module.Assembly != asm) + { + throw new ArgumentOutOfRangeException(); + } + object classLoader = AssemblyClassLoader.FromAssembly(asm).GetJavaClassLoader(); + Action init = (Action)Delegate.CreateDelegate(typeof(Action), classLoader, "InitializeModule", false, false); + if (init != null) + { + init(module); + } + } + + public static T GetDotNetEnumField(string name) +#if !FIRST_PASS + where T : java.lang.Enum +#endif + { +#if FIRST_PASS + return default(T); +#else + try + { + return (T)java.lang.Enum.valueOf(ikvm.@internal.ClassLiteral.Value, name); + } + catch (java.lang.IllegalArgumentException) + { + throw new java.lang.NoSuchFieldError(ikvm.@internal.ClassLiteral.Value.getName() + "." + name); + } +#endif + } + + [Flags] + public enum MapFlags + { + None = 0, + NoRemapping = 1, + Unused = 2, + } + + [HideFromJava] + public static T MapException(Exception x, MapFlags mode) where T : Exception + { + return ExceptionHelper.MapException(x, (mode & MapFlags.NoRemapping) == 0, (mode & MapFlags.Unused) != 0); + } + + [HideFromJava] + public static Exception DynamicMapException(Exception x, MapFlags mode, java.lang.Class exceptionClass) + { +#if FIRST_PASS + return null; +#else + TypeWrapper exceptionTypeWrapper = TypeWrapper.FromClass(exceptionClass); + mode &= ~MapFlags.NoRemapping; + if (exceptionTypeWrapper.IsSubTypeOf(CoreClasses.cli.System.Exception.Wrapper)) + { + mode |= MapFlags.NoRemapping; + } + Type exceptionType = exceptionTypeWrapper == CoreClasses.java.lang.Throwable.Wrapper ? typeof(System.Exception) : exceptionTypeWrapper.TypeAsBaseType; + return (Exception)ByteCodeHelperMethods.mapException.MakeGenericMethod(exceptionType).Invoke(null, new object[] { x, mode }); +#endif + } + + public static T GetDelegateForInvokeExact(global::java.lang.invoke.MethodHandle h) + where T : class + { +#if FIRST_PASS + return null; +#else + T del = h._invokeExactDelegate as T; + if (del == null) + { + del = MethodHandleUtil.GetDelegateForInvokeExact(h); + } + return del; +#endif + } + + public static T GetDelegateForInvoke(global::java.lang.invoke.MethodHandle h, java.lang.invoke.MethodType realType, ref InvokeCache cache) + where T : class + { +#if FIRST_PASS + return null; +#else + T del; + if (cache.Type == h.type() && (del = (h.isVarargsCollector() ? cache.varArg : cache.fixedArg)) != null) + { + return del; + } + del = h.form.vmentry.vmtarget as T; + if (del == null) + { + global::java.lang.invoke.MethodHandle adapter = global::java.lang.invoke.MethodHandles.exactInvoker(h.type()); + if (h.isVarargsCollector()) + { + adapter = adapter.asVarargsCollector(h.type().parameterType(h.type().parameterCount() - 1)); + } + // if realType is set, the delegate contains erased unloadable types + if (realType != null) + { + adapter = adapter.asType(realType.insertParameterTypes(0, ikvm.@internal.ClassLiteral.Value)).asFixedArity(); + } + adapter = adapter.asType(MethodHandleUtil.GetDelegateMethodType(typeof(T))); + del = GetDelegateForInvokeExact(adapter); + if (cache.TrySetType(h.type())) + { + if (h.isVarargsCollector()) + { + cache.varArg = del; + } + else + { + cache.fixedArg = del; + } + } + } + return del; +#endif + } + + public static T GetDelegateForInvokeBasic(java.lang.invoke.MethodHandle h) + where T : class + { +#if FIRST_PASS + return null; +#else + T del = h.form.vmentry.vmtarget as T; + if (del == null) + { + del = MethodHandleUtil.GetVoidAdapter(h.form.vmentry) as T; + } + return del; +#endif + } + + public static java.lang.invoke.MethodType LoadMethodType() + where T : class // Delegate + { +#if FIRST_PASS + return null; +#else + return MethodHandleUtil.GetDelegateMethodType(typeof(T)); +#endif + } + + [HideFromJava] + public static void LinkIndyCallSite(ref IndyCallSite site, java.lang.invoke.CallSite cs, Exception x) + where T : class // Delegate + { +#if !FIRST_PASS + // when a CallSite is first constructed, it doesn't call MethodHandleNatives.setCallSiteTargetNormal(), + // so we have to check if we need to initialize it here (i.e. attach an IndyCallSite to it) + if (cs != null) + { + if (cs.ics == null) + { + Java_java_lang_invoke_MethodHandleNatives.InitializeCallSite(cs); + } + lock (cs.ics) + { + cs.ics.SetTarget(cs.target); + } + } + IndyCallSite ics; + if (x != null || cs == null || (ics = cs.ics as IndyCallSite) == null) + { + x = MapException(x ?? (cs == null + ? (Exception)new java.lang.ClassCastException("bootstrap method failed to produce a CallSite") + : new java.lang.invoke.WrongMethodTypeException()), MapFlags.None); + java.lang.invoke.MethodType type = LoadMethodType(); + java.lang.invoke.MethodHandle exc = x is java.lang.BootstrapMethodError + ? java.lang.invoke.MethodHandles.constant(typeof(java.lang.BootstrapMethodError), x) + : java.lang.invoke.MethodHandles.publicLookup().findConstructor(typeof(java.lang.BootstrapMethodError), java.lang.invoke.MethodType.methodType(typeof(void), typeof(string), typeof(Exception))) + .bindTo("call site initialization exception").bindTo(x); + ics = new IndyCallSite(); + ((IIndyCallSite)ics).SetTarget( + java.lang.invoke.MethodHandles.dropArguments( + java.lang.invoke.MethodHandles.foldArguments( + java.lang.invoke.MethodHandles.throwException(type.returnType(), typeof(java.lang.BootstrapMethodError)), + exc), + 0, type.parameterArray())); + } + IndyCallSite curr = site; + if (curr.IsBootstrap) + { + Interlocked.CompareExchange(ref site, ics, curr); + } +#endif + } + + [HideFromJava] + public static void DynamicLinkIndyCallSite(ref IndyCallSite site, java.lang.invoke.CallSite cs, Exception x, string signature, ikvm.@internal.CallerID callerID) + where T : class // Delegate + { +#if !FIRST_PASS + // when a CallSite is first constructed, it doesn't call MethodHandleNatives.setCallSiteTargetNormal(), + // so we have to check if we need to initialize it here (i.e. attach an IndyCallSite to it) + if (cs != null) + { + if (cs.ics == null) + { + Java_java_lang_invoke_MethodHandleNatives.InitializeCallSite(cs); + } + lock (cs.ics) + { + cs.ics.SetTarget(cs.target); + } + } + java.lang.invoke.MethodType typeCache = null; + IndyCallSite ics; + if (x != null || cs == null || cs.type() != DynamicLoadMethodType(ref typeCache, signature, callerID)) + { + x = MapException(x ?? (cs == null + ? (Exception)new java.lang.ClassCastException("bootstrap method failed to produce a CallSite") + : new java.lang.invoke.WrongMethodTypeException()), MapFlags.None); + java.lang.invoke.MethodType type = LoadMethodType(); + java.lang.invoke.MethodHandle exc = x is java.lang.BootstrapMethodError + ? java.lang.invoke.MethodHandles.constant(typeof(java.lang.BootstrapMethodError), x) + : java.lang.invoke.MethodHandles.publicLookup().findConstructor(typeof(java.lang.BootstrapMethodError), java.lang.invoke.MethodType.methodType(typeof(void), typeof(string), typeof(Exception))) + .bindTo("call site initialization exception").bindTo(x); + ics = new IndyCallSite(); + ((IIndyCallSite)ics).SetTarget( + java.lang.invoke.MethodHandles.dropArguments( + java.lang.invoke.MethodHandles.foldArguments( + java.lang.invoke.MethodHandles.throwException(type.returnType(), typeof(java.lang.BootstrapMethodError)), + exc), + 0, type.parameterArray())); + } + else + { + ics = new IndyCallSite(); + ((IIndyCallSite)ics).SetTarget(cs.dynamicInvoker().asType(LoadMethodType())); + } + IndyCallSite curr = site; + if (curr.IsBootstrap) + { + Interlocked.CompareExchange(ref site, ics, curr); + } +#endif + } + } + + interface IIndyCallSite + { + void SetTarget(java.lang.invoke.MethodHandle mh); + } + + public sealed class IndyCallSite + : IIndyCallSite + where T : class // Delegate + { + internal readonly bool IsBootstrap; + private volatile T target; + + internal IndyCallSite() + { + } + + internal IndyCallSite(T target, bool bootstrap) + { + this.IsBootstrap = bootstrap; + this.target = target; + } + + void IIndyCallSite.SetTarget(java.lang.invoke.MethodHandle mh) + { +#if !FIRST_PASS + target = ByteCodeHelper.GetDelegateForInvokeExact(mh); +#endif + } + + public static IndyCallSite CreateBootstrap(T bootstrap) + { + return new IndyCallSite(bootstrap, true); + } + + public T GetTarget() + { + return target; + } + } + + public struct InvokeCache + where T : class + { +#if CLASSGC + private WeakReference weakRef; + + internal java.lang.invoke.MethodType Type + { + get { return weakRef == null ? null : (java.lang.invoke.MethodType)weakRef.Target; } + } + + internal bool TrySetType(java.lang.invoke.MethodType newType) + { + if (weakRef == null) + { + return Interlocked.CompareExchange(ref weakRef, new WeakReference(newType), null) == null; + } + return Type == newType; + } +#else + private java.lang.invoke.MethodType type; + + internal java.lang.invoke.MethodType Type + { + get { return type; } + } + + internal bool TrySetType(java.lang.invoke.MethodType newType) + { + Interlocked.CompareExchange(ref type, newType, null); + return type == newType; + } +#endif + internal T fixedArg; + internal T varArg; + } + + [StructLayout(LayoutKind.Explicit)] + public struct DoubleConverter + { + [FieldOffset(0)] + private double d; + [FieldOffset(0)] + private long l; + + public static long ToLong(double value, ref DoubleConverter converter) + { + converter.d = value; + return converter.l; + } + + public static double ToDouble(long value, ref DoubleConverter converter) + { + converter.l = value; + return converter.d; + } + } + + [StructLayout(LayoutKind.Explicit)] + public struct FloatConverter + { + [FieldOffset(0)] + private float f; + [FieldOffset(0)] + private int i; + + public static int ToInt(float value, ref FloatConverter converter) + { + converter.f = value; + return converter.i; + } + + public static float ToFloat(int value, ref FloatConverter converter) + { + converter.i = value; + return converter.f; + } + } + + public struct MHA + { + public T1 t1; + public T2 t2; + public T3 t3; + public T4 t4; + public T5 t5; + public T6 t6; + public T7 t7; + public T8 t8; + + public MHA(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) + { + this.t1 = t1; + this.t2 = t2; + this.t3 = t3; + this.t4 = t4; + this.t5 = t5; + this.t6 = t6; + this.t7 = t7; + this.t8 = t8; + } + } + + public delegate void MHV(); + public delegate void MHV(T1 t1); + public delegate void MHV(T1 t1, T2 t2); + public delegate void MHV(T1 t1, T2 t2, T3 t3); + public delegate void MHV(T1 t1, T2 t2, T3 t3, T4 t4); + public delegate void MHV(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5); + public delegate void MHV(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6); + public delegate void MHV(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7); + public delegate void MHV(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8); + + public delegate TResult MH(); + public delegate TResult MH(T1 t1); + public delegate TResult MH(T1 t1, T2 t2); + public delegate TResult MH(T1 t1, T2 t2, T3 t3); + public delegate TResult MH(T1 t1, T2 t2, T3 t3, T4 t4); + public delegate TResult MH(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5); + public delegate TResult MH(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6); + public delegate TResult MH(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7); + public delegate TResult MH(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8); + + public static class LiveObjectHolder + { + public static object[] values; + } +} diff --git a/runtime/ClassFile.cs b/runtime/ClassFile.cs new file mode 100644 index 0000000..9752fe8 --- /dev/null +++ b/runtime/ClassFile.cs @@ -0,0 +1,4005 @@ +/* + Copyright (C) 2002-2015 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.IO; +using System.Collections.Generic; +using IKVM.Attributes; + +namespace IKVM.Internal +{ + enum HardError : short + { + NoClassDefFoundError, + IllegalAccessError, + InstantiationError, + IncompatibleClassChangeError, + NoSuchFieldError, + AbstractMethodError, + NoSuchMethodError, + LinkageError, + // "exceptions" that are wrapped in an IncompatibleClassChangeError + IllegalAccessException, + // if an error is added here, it must also be added to MethodAnalyzer.SetHardError() + } + + [Flags] + enum ClassFileParseOptions + { + None = 0, + LocalVariableTable = 1, + LineNumberTable = 2, + RelaxedClassNameValidation = 4, + TrustedAnnotations = 8, + RemoveAssertions = 16, + } + + sealed class ClassFile + { + private ConstantPoolItem[] constantpool; + // Modifiers is a ushort, so the next four fields combine into two 32 bit slots + private Modifiers access_flags; + private ushort this_class; + private ushort super_class; + private ushort flags; + private const ushort FLAG_MASK_MAJORVERSION = 0xFF; + private const ushort FLAG_MASK_DEPRECATED = 0x100; + private const ushort FLAG_MASK_INTERNAL = 0x200; + private const ushort FLAG_CALLERSENSITIVE = 0x400; + private const ushort FLAG_LAMBDAFORM_COMPILED = 0x800; + private const ushort FLAG_LAMBDAFORM_HIDDEN = 0x1000; + private const ushort FLAG_FORCEINLINE = 0x2000; + private const ushort FLAG_HAS_ASSERTIONS = 0x4000; + private ConstantPoolItemClass[] interfaces; + private Field[] fields; + private Method[] methods; + private string sourceFile; +#if STATIC_COMPILER + private string sourcePath; +#endif + private string ikvmAssembly; + private InnerClass[] innerClasses; + private object[] annotations; + private string signature; + private string[] enclosingMethod; + private BootstrapMethod[] bootstrapMethods; + private byte[] runtimeVisibleTypeAnnotations; + + private static class SupportedVersions + { + internal static readonly int Minimum = 45; + internal static readonly int Maximum = Experimental.JDK_9 ? 53 : 52; + } + +#if STATIC_COMPILER + // This method parses just enough of the class file to obtain its name and + // determine if the class is a possible ikvmstub generated stub, it doesn't + // validate the class file structure, but it may throw a ClassFormatError if it + // encounters bogus data + internal static string GetClassName(byte[] buf, int offset, int length, out bool isstub) + { + isstub = false; + BigEndianBinaryReader br = new BigEndianBinaryReader(buf, offset, length); + if(br.ReadUInt32() != 0xCAFEBABE) + { + throw new ClassFormatError("Bad magic number"); + } + int minorVersion = br.ReadUInt16(); + int majorVersion = br.ReadUInt16(); + if((majorVersion & FLAG_MASK_MAJORVERSION) != majorVersion + || majorVersion < SupportedVersions.Minimum + || majorVersion > SupportedVersions.Maximum + || (majorVersion == SupportedVersions.Minimum && minorVersion < 3) + || (majorVersion == SupportedVersions.Maximum && minorVersion != 0)) + { + throw new UnsupportedClassVersionError(majorVersion + "." + minorVersion); + } + int constantpoolcount = br.ReadUInt16(); + int[] cpclass = new int[constantpoolcount]; + string[] utf8_cp = new string[constantpoolcount]; + for(int i = 1; i < constantpoolcount; i++) + { + Constant tag = (Constant)br.ReadByte(); + switch(tag) + { + case Constant.Class: + cpclass[i] = br.ReadUInt16(); + break; + case Constant.Double: + case Constant.Long: + br.Skip(8); + i++; + break; + case Constant.Fieldref: + case Constant.InterfaceMethodref: + case Constant.Methodref: + case Constant.InvokeDynamic: + case Constant.NameAndType: + case Constant.Float: + case Constant.Integer: + br.Skip(4); + break; + case Constant.MethodHandle: + br.Skip(3); + break; + case Constant.String: + case Constant.MethodType: + br.Skip(2); + break; + case Constant.Utf8: + isstub |= (utf8_cp[i] = br.ReadString(null, majorVersion)) == "IKVM.NET.Assembly"; + break; + default: + throw new ClassFormatError("Illegal constant pool type 0x{0:X}", tag); + } + } + br.ReadUInt16(); // access_flags + try + { + return String.Intern(utf8_cp[cpclass[br.ReadUInt16()]].Replace('/', '.')); + } + catch(Exception x) + { + throw new ClassFormatError("{0}: {1}", x.GetType().Name, x.Message); + } + } +#endif // STATIC_COMPILER + + internal ClassFile(byte[] buf, int offset, int length, string inputClassName, ClassFileParseOptions options, object[] constantPoolPatches) + { + try + { + BigEndianBinaryReader br = new BigEndianBinaryReader(buf, offset, length); + if(br.ReadUInt32() != 0xCAFEBABE) + { + throw new ClassFormatError("{0} (Bad magic number)", inputClassName); + } + ushort minorVersion = br.ReadUInt16(); + ushort majorVersion = br.ReadUInt16(); + if((majorVersion & FLAG_MASK_MAJORVERSION) != majorVersion + || majorVersion < SupportedVersions.Minimum + || majorVersion > SupportedVersions.Maximum + || (majorVersion == SupportedVersions.Minimum && minorVersion < 3) + || (majorVersion == SupportedVersions.Maximum && minorVersion != 0)) + { + throw new UnsupportedClassVersionError(inputClassName + " (" + majorVersion + "." + minorVersion + ")"); + } + flags = majorVersion; + int constantpoolcount = br.ReadUInt16(); + constantpool = new ConstantPoolItem[constantpoolcount]; + string[] utf8_cp = new string[constantpoolcount]; + for(int i = 1; i < constantpoolcount; i++) + { + Constant tag = (Constant)br.ReadByte(); + switch(tag) + { + case Constant.Class: + constantpool[i] = new ConstantPoolItemClass(br); + break; + case Constant.Double: + constantpool[i] = new ConstantPoolItemDouble(br); + i++; + break; + case Constant.Fieldref: + constantpool[i] = new ConstantPoolItemFieldref(br); + break; + case Constant.Float: + constantpool[i] = new ConstantPoolItemFloat(br); + break; + case Constant.Integer: + constantpool[i] = new ConstantPoolItemInteger(br); + break; + case Constant.InterfaceMethodref: + constantpool[i] = new ConstantPoolItemInterfaceMethodref(br); + break; + case Constant.Long: + constantpool[i] = new ConstantPoolItemLong(br); + i++; + break; + case Constant.Methodref: + constantpool[i] = new ConstantPoolItemMethodref(br); + break; + case Constant.NameAndType: + constantpool[i] = new ConstantPoolItemNameAndType(br); + break; + case Constant.MethodHandle: + if (majorVersion < 51) + goto default; + constantpool[i] = new ConstantPoolItemMethodHandle(br); + break; + case Constant.MethodType: + if (majorVersion < 51) + goto default; + constantpool[i] = new ConstantPoolItemMethodType(br); + break; + case Constant.InvokeDynamic: + if (majorVersion < 51) + goto default; + constantpool[i] = new ConstantPoolItemInvokeDynamic(br); + break; + case Constant.String: + constantpool[i] = new ConstantPoolItemString(br); + break; + case Constant.Utf8: + utf8_cp[i] = br.ReadString(inputClassName, majorVersion); + break; + default: + throw new ClassFormatError("{0} (Illegal constant pool type 0x{1:X})", inputClassName, tag); + } + } + if (constantPoolPatches != null) + { + PatchConstantPool(constantPoolPatches, utf8_cp, inputClassName); + } + for(int i = 1; i < constantpoolcount; i++) + { + if(constantpool[i] != null) + { + try + { + constantpool[i].Resolve(this, utf8_cp, options); + } + catch(ClassFormatError x) + { + // HACK at this point we don't yet have the class name, so any exceptions throw + // are missing the class name + throw new ClassFormatError("{0} ({1})", inputClassName, x.Message); + } + catch(IndexOutOfRangeException) + { + throw new ClassFormatError("{0} (Invalid constant pool item #{1})", inputClassName, i); + } + catch(InvalidCastException) + { + throw new ClassFormatError("{0} (Invalid constant pool item #{1})", inputClassName, i); + } + } + } + access_flags = (Modifiers)br.ReadUInt16(); + // NOTE although the vmspec says (in 4.1) that interfaces must be marked abstract, earlier versions of + // javac (JDK 1.1) didn't do this, so the VM doesn't enforce this rule for older class files. + // NOTE although the vmspec implies (in 4.1) that ACC_SUPER is illegal on interfaces, it doesn't enforce this + // for older class files. + // (See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6320322) + if((IsInterface && IsFinal) + || (IsAbstract && IsFinal) + || (majorVersion >= 49 && IsAnnotation && !IsInterface) + || (majorVersion >= 49 && IsInterface && (!IsAbstract || IsSuper || IsEnum))) + { + throw new ClassFormatError("{0} (Illegal class modifiers 0x{1:X})", inputClassName, access_flags); + } + this_class = br.ReadUInt16(); + ValidateConstantPoolItemClass(inputClassName, this_class); + super_class = br.ReadUInt16(); + ValidateConstantPoolItemClass(inputClassName, super_class); + if(IsInterface && (super_class == 0 || this.SuperClass.Name != "java.lang.Object")) + { + throw new ClassFormatError("{0} (Interfaces must have java.lang.Object as superclass)", Name); + } + // most checks are already done by ConstantPoolItemClass.Resolve, but since it allows + // array types, we do need to check for that + if(this.Name[0] == '[') + { + throw new ClassFormatError("Bad name"); + } + int interfaces_count = br.ReadUInt16(); + interfaces = new ConstantPoolItemClass[interfaces_count]; + for(int i = 0; i < interfaces.Length; i++) + { + int index = br.ReadUInt16(); + if(index == 0 || index >= constantpool.Length) + { + throw new ClassFormatError("{0} (Illegal constant pool index)", Name); + } + ConstantPoolItemClass cpi = constantpool[index] as ConstantPoolItemClass; + if(cpi == null) + { + throw new ClassFormatError("{0} (Interface name has bad constant type)", Name); + } + interfaces[i] = cpi; + } + CheckDuplicates(interfaces, "Repetitive interface name"); + int fields_count = br.ReadUInt16(); + fields = new Field[fields_count]; + for(int i = 0; i < fields_count; i++) + { + fields[i] = new Field(this, utf8_cp, br); + string name = fields[i].Name; + if(!IsValidFieldName(name, majorVersion)) + { + throw new ClassFormatError("{0} (Illegal field name \"{1}\")", Name, name); + } + } + CheckDuplicates(fields, "Repetitive field name/signature"); + int methods_count = br.ReadUInt16(); + methods = new Method[methods_count]; + for(int i = 0; i < methods_count; i++) + { + methods[i] = new Method(this, utf8_cp, options, br); + string name = methods[i].Name; + string sig = methods[i].Signature; + if(!IsValidMethodName(name, majorVersion)) + { + if(!ReferenceEquals(name, StringConstants.INIT) && !ReferenceEquals(name, StringConstants.CLINIT)) + { + throw new ClassFormatError("{0} (Illegal method name \"{1}\")", Name, name); + } + if(!sig.EndsWith("V")) + { + throw new ClassFormatError("{0} (Method \"{1}\" has illegal signature \"{2}\")", Name, name, sig); + } + if((options & ClassFileParseOptions.RemoveAssertions) != 0 && methods[i].IsClassInitializer) + { + RemoveAssertionInit(methods[i]); + } + } + } + CheckDuplicates(methods, "Repetitive method name/signature"); + int attributes_count = br.ReadUInt16(); + for(int i = 0; i < attributes_count; i++) + { + switch(GetConstantPoolUtf8String(utf8_cp, br.ReadUInt16())) + { + case "Deprecated": + if(br.ReadUInt32() != 0) + { + throw new ClassFormatError("Invalid Deprecated attribute length"); + } + flags |= FLAG_MASK_DEPRECATED; + break; + case "SourceFile": + if(br.ReadUInt32() != 2) + { + throw new ClassFormatError("SourceFile attribute has incorrect length"); + } + sourceFile = GetConstantPoolUtf8String(utf8_cp, br.ReadUInt16()); + break; + case "InnerClasses": + { + BigEndianBinaryReader rdr = br; + uint attribute_length = br.ReadUInt32(); + ushort count = rdr.ReadUInt16(); + if(this.MajorVersion >= 49 && attribute_length != 2 + count * (2 + 2 + 2 + 2)) + { + throw new ClassFormatError("{0} (InnerClasses attribute has incorrect length)", this.Name); + } + innerClasses = new InnerClass[count]; + for(int j = 0; j < innerClasses.Length; j++) + { + innerClasses[j].innerClass = rdr.ReadUInt16(); + innerClasses[j].outerClass = rdr.ReadUInt16(); + innerClasses[j].name = rdr.ReadUInt16(); + innerClasses[j].accessFlags = (Modifiers)rdr.ReadUInt16(); + if(innerClasses[j].innerClass != 0 && !(GetConstantPoolItem(innerClasses[j].innerClass) is ConstantPoolItemClass)) + { + throw new ClassFormatError("{0} (inner_class_info_index has bad constant pool index)", this.Name); + } + if(innerClasses[j].outerClass != 0 && !(GetConstantPoolItem(innerClasses[j].outerClass) is ConstantPoolItemClass)) + { + throw new ClassFormatError("{0} (outer_class_info_index has bad constant pool index)", this.Name); + } + if(innerClasses[j].name != 0 && utf8_cp[innerClasses[j].name] == null) + { + throw new ClassFormatError("{0} (inner class name has bad constant pool index)", this.Name); + } + if(innerClasses[j].innerClass == innerClasses[j].outerClass) + { + throw new ClassFormatError("{0} (Class is both inner and outer class)", this.Name); + } + if(innerClasses[j].innerClass != 0 && innerClasses[j].outerClass != 0) + { + MarkLinkRequiredConstantPoolItem(innerClasses[j].innerClass); + MarkLinkRequiredConstantPoolItem(innerClasses[j].outerClass); + } + } + break; + } + case "Signature": + if(majorVersion < 49) + { + goto default; + } + if(br.ReadUInt32() != 2) + { + throw new ClassFormatError("Signature attribute has incorrect length"); + } + signature = GetConstantPoolUtf8String(utf8_cp, br.ReadUInt16()); + break; + case "EnclosingMethod": + if(majorVersion < 49) + { + goto default; + } + if(br.ReadUInt32() != 4) + { + throw new ClassFormatError("EnclosingMethod attribute has incorrect length"); + } + else + { + ushort class_index = br.ReadUInt16(); + ushort method_index = br.ReadUInt16(); + ValidateConstantPoolItemClass(inputClassName, class_index); + if(method_index == 0) + { + enclosingMethod = new string[] { + GetConstantPoolClass(class_index), + null, + null + }; + } + else + { + ConstantPoolItemNameAndType m = GetConstantPoolItem(method_index) as ConstantPoolItemNameAndType; + if(m == null) + { + throw new ClassFormatError("{0} (Bad constant pool index #{1})", inputClassName, method_index); + } + enclosingMethod = new string[] { + GetConstantPoolClass(class_index), + GetConstantPoolUtf8String(utf8_cp, m.name_index), + GetConstantPoolUtf8String(utf8_cp, m.descriptor_index).Replace('/', '.') + }; + } + } + break; + case "RuntimeVisibleAnnotations": + if(majorVersion < 49) + { + goto default; + } + annotations = ReadAnnotations(br, this, utf8_cp); + break; +#if STATIC_COMPILER + case "RuntimeInvisibleAnnotations": + if(majorVersion < 49) + { + goto default; + } + foreach(object[] annot in ReadAnnotations(br, this, utf8_cp)) + { + if(annot[1].Equals("Likvm/lang/Internal;")) + { + this.access_flags &= ~Modifiers.AccessMask; + flags |= FLAG_MASK_INTERNAL; + } + } + break; +#endif + case "BootstrapMethods": + if(majorVersion < 51) + { + goto default; + } + bootstrapMethods = ReadBootstrapMethods(br, this); + break; + case "RuntimeVisibleTypeAnnotations": + if(majorVersion < 52) + { + goto default; + } + CreateUtf8ConstantPoolItems(utf8_cp); + runtimeVisibleTypeAnnotations = br.Section(br.ReadUInt32()).ToArray(); + break; + case "IKVM.NET.Assembly": + if(br.ReadUInt32() != 2) + { + throw new ClassFormatError("IKVM.NET.Assembly attribute has incorrect length"); + } + ikvmAssembly = GetConstantPoolUtf8String(utf8_cp, br.ReadUInt16()); + break; + default: + br.Skip(br.ReadUInt32()); + break; + } + } + // validate the invokedynamic entries to point into the bootstrapMethods array + for(int i = 1; i < constantpoolcount; i++) + { + ConstantPoolItemInvokeDynamic cpi; + if(constantpool[i] != null + && (cpi = constantpool[i] as ConstantPoolItemInvokeDynamic) != null) + { + if(bootstrapMethods == null || cpi.BootstrapMethod >= bootstrapMethods.Length) + { + throw new ClassFormatError("Short length on BootstrapMethods in class file"); + } + } + } + if(br.Position != offset + length) + { + throw new ClassFormatError("Extra bytes at the end of the class file"); + } + } + catch(OverflowException) + { + throw new ClassFormatError("Truncated class file (or section)"); + } + catch(IndexOutOfRangeException) + { + // TODO we should throw more specific errors + throw new ClassFormatError("Unspecified class file format error"); + } + // catch(Exception x) + // { + // Console.WriteLine(x); + // FileStream fs = File.Create(inputClassName + ".broken"); + // fs.Write(buf, offset, length); + // fs.Close(); + // throw; + // } + } + + private void CreateUtf8ConstantPoolItems(string[] utf8_cp) + { + for (int i = 0; i < constantpool.Length; i++) + { + if (constantpool[i] == null && utf8_cp[i] != null) + { + constantpool[i] = new ConstantPoolItemUtf8(utf8_cp[i]); + } + } + } + + private void CheckDuplicates(T[] members, string msg) + where T : IEquatable + { + if (members.Length < 100) + { + for (int i = 0; i < members.Length; i++) + { + for (int j = 0; j < i; j++) + { + if (members[i].Equals(members[j])) + { + throw new ClassFormatError("{0} ({1})", Name, msg); + } + } + } + } + else + { + Dictionary dict = new Dictionary(); + for (int i = 0; i < members.Length; i++) + { + if (dict.ContainsKey(members[i])) + { + throw new ClassFormatError("{0} ({1})", Name, msg); + } + dict.Add(members[i], null); + } + } + } + + private void PatchConstantPool(object[] constantPoolPatches, string[] utf8_cp, string inputClassName) + { +#if !STATIC_COMPILER && !FIRST_PASS + for (int i = 0; i < constantPoolPatches.Length; i++) + { + if (constantPoolPatches[i] != null) + { + if (utf8_cp[i] != null) + { + if (!(constantPoolPatches[i] is string)) + { + throw new ClassFormatError("Illegal utf8 patch at {0} in class file {1}", i, inputClassName); + } + utf8_cp[i] = (string)constantPoolPatches[i]; + } + else if (constantpool[i] != null) + { + switch (constantpool[i].GetConstantType()) + { + case ConstantType.String: + constantpool[i] = new ConstantPoolItemLiveObject(constantPoolPatches[i]); + break; + case ConstantType.Class: + java.lang.Class clazz; + string name; + if ((clazz = constantPoolPatches[i] as java.lang.Class) != null) + { + TypeWrapper tw = TypeWrapper.FromClass(clazz); + constantpool[i] = new ConstantPoolItemClass(tw.Name, tw); + } + else if ((name = constantPoolPatches[i] as string) != null) + { + constantpool[i] = new ConstantPoolItemClass(String.Intern(name.Replace('/', '.')), null); + } + else + { + throw new ClassFormatError("Illegal class patch at {0} in class file {1}", i, inputClassName); + } + break; + case ConstantType.Integer: + ((ConstantPoolItemInteger)constantpool[i]).v = ((java.lang.Integer)constantPoolPatches[i]).intValue(); + break; + case ConstantType.Long: + ((ConstantPoolItemLong)constantpool[i]).l = ((java.lang.Long)constantPoolPatches[i]).longValue(); + break; + case ConstantType.Float: + ((ConstantPoolItemFloat)constantpool[i]).v = ((java.lang.Float)constantPoolPatches[i]).floatValue(); + break; + case ConstantType.Double: + ((ConstantPoolItemDouble)constantpool[i]).d = ((java.lang.Double)constantPoolPatches[i]).doubleValue(); + break; + default: + throw new NotImplementedException("ConstantPoolPatch: " + constantPoolPatches[i]); + } + } + } + } +#endif + } + + private void MarkLinkRequiredConstantPoolItem(int index) + { + if (index > 0 && index < constantpool.Length && constantpool[index] != null) + { + constantpool[index].MarkLinkRequired(); + } + } + + private static BootstrapMethod[] ReadBootstrapMethods(BigEndianBinaryReader br, ClassFile classFile) + { + BigEndianBinaryReader rdr = br.Section(br.ReadUInt32()); + ushort count = rdr.ReadUInt16(); + BootstrapMethod[] bsm = new BootstrapMethod[count]; + for(int i = 0; i < bsm.Length; i++) + { + ushort bsm_index = rdr.ReadUInt16(); + if(bsm_index >= classFile.constantpool.Length || !(classFile.constantpool[bsm_index] is ConstantPoolItemMethodHandle)) + { + throw new ClassFormatError("bootstrap_method_index {0} has bad constant type in class file {1}", bsm_index, classFile.Name); + } + classFile.MarkLinkRequiredConstantPoolItem(bsm_index); + ushort argument_count = rdr.ReadUInt16(); + ushort[] args = new ushort[argument_count]; + for(int j = 0; j < args.Length; j++) + { + ushort argument_index = rdr.ReadUInt16(); + if(!classFile.IsValidConstant(argument_index)) + { + throw new ClassFormatError("argument_index {0} has bad constant type in class file {1}", argument_index, classFile.Name); + } + classFile.MarkLinkRequiredConstantPoolItem(argument_index); + args[j] = argument_index; + } + bsm[i] = new BootstrapMethod(bsm_index, args); + } + if(!rdr.IsAtEnd) + { + throw new ClassFormatError("Bad length on BootstrapMethods in class file {0}", classFile.Name); + } + return bsm; + } + + private bool IsValidConstant(ushort index) + { + if(index < constantpool.Length && constantpool[index] != null) + { + try + { + constantpool[index].GetConstantType(); + return true; + } + catch (InvalidOperationException) { } + } + return false; + } + + private static object[] ReadAnnotations(BigEndianBinaryReader br, ClassFile classFile, string[] utf8_cp) + { + BigEndianBinaryReader rdr = br.Section(br.ReadUInt32()); + ushort num_annotations = rdr.ReadUInt16(); + object[] annotations = new object[num_annotations]; + for(int i = 0; i < annotations.Length; i++) + { + annotations[i] = ReadAnnotation(rdr, classFile, utf8_cp); + } + if(!rdr.IsAtEnd) + { + throw new ClassFormatError("{0} (RuntimeVisibleAnnotations attribute has wrong length)", classFile.Name); + } + return annotations; + } + + private static object ReadAnnotation(BigEndianBinaryReader rdr, ClassFile classFile, string[] utf8_cp) + { + string type = classFile.GetConstantPoolUtf8String(utf8_cp, rdr.ReadUInt16()); + ushort num_element_value_pairs = rdr.ReadUInt16(); + object[] annot = new object[2 + num_element_value_pairs * 2]; + annot[0] = AnnotationDefaultAttribute.TAG_ANNOTATION; + annot[1] = type; + for(int i = 0; i < num_element_value_pairs; i++) + { + annot[2 + i * 2 + 0] = classFile.GetConstantPoolUtf8String(utf8_cp, rdr.ReadUInt16()); + annot[2 + i * 2 + 1] = ReadAnnotationElementValue(rdr, classFile, utf8_cp); + } + return annot; + } + + private static object ReadAnnotationElementValue(BigEndianBinaryReader rdr, ClassFile classFile, string[] utf8_cp) + { + try + { + byte tag = rdr.ReadByte(); + switch (tag) + { + case (byte)'Z': + return classFile.GetConstantPoolConstantInteger(rdr.ReadUInt16()) != 0; + case (byte)'B': + return (byte)classFile.GetConstantPoolConstantInteger(rdr.ReadUInt16()); + case (byte)'C': + return (char)classFile.GetConstantPoolConstantInteger(rdr.ReadUInt16()); + case (byte)'S': + return (short)classFile.GetConstantPoolConstantInteger(rdr.ReadUInt16()); + case (byte)'I': + return classFile.GetConstantPoolConstantInteger(rdr.ReadUInt16()); + case (byte)'F': + return classFile.GetConstantPoolConstantFloat(rdr.ReadUInt16()); + case (byte)'J': + return classFile.GetConstantPoolConstantLong(rdr.ReadUInt16()); + case (byte)'D': + return classFile.GetConstantPoolConstantDouble(rdr.ReadUInt16()); + case (byte)'s': + return classFile.GetConstantPoolUtf8String(utf8_cp, rdr.ReadUInt16()); + case (byte)'e': + { + ushort type_name_index = rdr.ReadUInt16(); + ushort const_name_index = rdr.ReadUInt16(); + return new object[] { + AnnotationDefaultAttribute.TAG_ENUM, + classFile.GetConstantPoolUtf8String(utf8_cp, type_name_index), + classFile.GetConstantPoolUtf8String(utf8_cp, const_name_index) + }; + } + case (byte)'c': + return new object[] { + AnnotationDefaultAttribute.TAG_CLASS, + classFile.GetConstantPoolUtf8String(utf8_cp, rdr.ReadUInt16()) + }; + case (byte)'@': + return ReadAnnotation(rdr, classFile, utf8_cp); + case (byte)'[': + { + ushort num_values = rdr.ReadUInt16(); + object[] array = new object[num_values + 1]; + array[0] = AnnotationDefaultAttribute.TAG_ARRAY; + for (int i = 0; i < num_values; i++) + { + array[i + 1] = ReadAnnotationElementValue(rdr, classFile, utf8_cp); + } + return array; + } + default: + throw new ClassFormatError("Invalid tag {0} in annotation element_value", tag); + } + } + catch (NullReferenceException) + { + } + catch (InvalidCastException) + { + } + catch (IndexOutOfRangeException) + { + } + return new object[] { AnnotationDefaultAttribute.TAG_ERROR, "java.lang.IllegalArgumentException", "Wrong type at constant pool index" }; + } + + private void ValidateConstantPoolItemClass(string classFile, ushort index) + { + if(index >= constantpool.Length || !(constantpool[index] is ConstantPoolItemClass)) + { + throw new ClassFormatError("{0} (Bad constant pool index #{1})", classFile, index); + } + } + + private static bool IsValidMethodName(string name, int majorVersion) + { + if(name.Length == 0) + { + return false; + } + for(int i = 0; i < name.Length; i++) + { + if(".;[/<>".IndexOf(name[i]) != -1) + { + return false; + } + } + return majorVersion >= 49 || IsValidPre49Identifier(name); + } + + private static bool IsValidFieldName(string name, int majorVersion) + { + if(name.Length == 0) + { + return false; + } + for(int i = 0; i < name.Length; i++) + { + if(".;[/".IndexOf(name[i]) != -1) + { + return false; + } + } + return majorVersion >= 49 || IsValidPre49Identifier(name); + } + + private static bool IsValidPre49Identifier(string name) + { + if(!Char.IsLetter(name[0]) && "$_".IndexOf(name[0]) == -1) + { + return false; + } + for(int i = 1; i < name.Length; i++) + { + if(!Char.IsLetterOrDigit(name[i]) && "$_".IndexOf(name[i]) == -1) + { + return false; + } + } + return true; + } + + internal static bool IsValidFieldSig(string sig) + { + return IsValidFieldSigImpl(sig, 0, sig.Length); + } + + private static bool IsValidFieldSigImpl(string sig, int start, int end) + { + if(start >= end) + { + return false; + } + switch(sig[start]) + { + case 'L': + return sig.IndexOf(';', start + 1) == end - 1; + case '[': + while(sig[start] == '[') + { + start++; + if(start == end) + { + return false; + } + } + return IsValidFieldSigImpl(sig, start, end); + case 'B': + case 'Z': + case 'C': + case 'S': + case 'I': + case 'J': + case 'F': + case 'D': + return start == end - 1; + default: + return false; + } + } + + internal static bool IsValidMethodSig(string sig) + { + if(sig.Length < 3 || sig[0] != '(') + { + return false; + } + int end = sig.IndexOf(')'); + if(end == -1) + { + return false; + } + if(!sig.EndsWith(")V") && !IsValidFieldSigImpl(sig, end + 1, sig.Length)) + { + return false; + } + for(int i = 1; i < end; i++) + { + switch(sig[i]) + { + case 'B': + case 'Z': + case 'C': + case 'S': + case 'I': + case 'J': + case 'F': + case 'D': + break; + case 'L': + i = sig.IndexOf(';', i); + break; + case '[': + while(sig[i] == '[') + { + i++; + } + if("BZCSIJFDL".IndexOf(sig[i]) == -1) + { + return false; + } + if(sig[i] == 'L') + { + i = sig.IndexOf(';', i); + } + break; + default: + return false; + } + if(i == -1 || i >= end) + { + return false; + } + } + return true; + } + + internal int MajorVersion + { + get + { + return flags & FLAG_MASK_MAJORVERSION; + } + } + + internal void Link(TypeWrapper thisType, LoadMode mode) + { + // this is not just an optimization, it's required for anonymous classes to be able to refer to themselves + ((ConstantPoolItemClass)constantpool[this_class]).LinkSelf(thisType); + for(int i = 1; i < constantpool.Length; i++) + { + if(constantpool[i] != null) + { + constantpool[i].Link(thisType, mode); + } + } + } + + internal Modifiers Modifiers + { + get + { + return access_flags; + } + } + + internal bool IsAbstract + { + get + { + // interfaces are implicitly abstract + return (access_flags & (Modifiers.Abstract | Modifiers.Interface)) != 0; + } + } + + internal bool IsFinal + { + get + { + return (access_flags & Modifiers.Final) != 0; + } + } + + internal bool IsPublic + { + get + { + return (access_flags & Modifiers.Public) != 0; + } + } + + internal bool IsInterface + { + get + { + return (access_flags & Modifiers.Interface) != 0; + } + } + + internal bool IsEnum + { + get + { + return (access_flags & Modifiers.Enum) != 0; + } + } + + internal bool IsAnnotation + { + get + { + return (access_flags & Modifiers.Annotation) != 0; + } + } + + internal bool IsSuper + { + get + { + return (access_flags & Modifiers.Super) != 0; + } + } + + internal bool IsReferenced(Field fld) + { + foreach(ConstantPoolItem cpi in constantpool) + { + ConstantPoolItemFieldref fieldref = cpi as ConstantPoolItemFieldref; + if(fieldref != null && + fieldref.Class == this.Name && + fieldref.Name == fld.Name && + fieldref.Signature == fld.Signature) + { + return true; + } + } + return false; + } + + internal ConstantPoolItemFieldref GetFieldref(int index) + { + return (ConstantPoolItemFieldref)constantpool[index]; + } + + // this won't throw an exception if index is invalid + // (used by IsSideEffectFreeStaticInitializer) + internal ConstantPoolItemFieldref SafeGetFieldref(int index) + { + if(index > 0 && index < constantpool.Length) + { + return constantpool[index] as ConstantPoolItemFieldref; + } + return null; + } + + // NOTE this returns an MI, because it used for both normal methods and interface methods + internal ConstantPoolItemMI GetMethodref(int index) + { + return (ConstantPoolItemMI)constantpool[index]; + } + + // this won't throw an exception if index is invalid + // (used by IsAccessBridge) + internal ConstantPoolItemMI SafeGetMethodref(int index) + { + if (index > 0 && index < constantpool.Length) + { + return constantpool[index] as ConstantPoolItemMI; + } + return null; + } + + internal ConstantPoolItemInvokeDynamic GetInvokeDynamic(int index) + { + return (ConstantPoolItemInvokeDynamic)constantpool[index]; + } + + private ConstantPoolItem GetConstantPoolItem(int index) + { + return constantpool[index]; + } + + internal string GetConstantPoolClass(int index) + { + return ((ConstantPoolItemClass)constantpool[index]).Name; + } + + private bool SafeIsConstantPoolClass(int index) + { + if(index > 0 && index < constantpool.Length) + { + return constantpool[index] as ConstantPoolItemClass != null; + } + return false; + } + + internal TypeWrapper GetConstantPoolClassType(int index) + { + return ((ConstantPoolItemClass)constantpool[index]).GetClassType(); + } + + private string GetConstantPoolUtf8String(string[] utf8_cp, int index) + { + string s = utf8_cp[index]; + if(s == null) + { + if(this_class == 0) + { + throw new ClassFormatError("Bad constant pool index #{0}", index); + } + else + { + throw new ClassFormatError("{0} (Bad constant pool index #{1})", this.Name, index); + } + } + return s; + } + + internal ConstantType GetConstantPoolConstantType(int index) + { + return constantpool[index].GetConstantType(); + } + + internal double GetConstantPoolConstantDouble(int index) + { + return ((ConstantPoolItemDouble)constantpool[index]).Value; + } + + internal float GetConstantPoolConstantFloat(int index) + { + return ((ConstantPoolItemFloat)constantpool[index]).Value; + } + + internal int GetConstantPoolConstantInteger(int index) + { + return ((ConstantPoolItemInteger)constantpool[index]).Value; + } + + internal long GetConstantPoolConstantLong(int index) + { + return ((ConstantPoolItemLong)constantpool[index]).Value; + } + + internal string GetConstantPoolConstantString(int index) + { + return ((ConstantPoolItemString)constantpool[index]).Value; + } + + internal ConstantPoolItemMethodHandle GetConstantPoolConstantMethodHandle(int index) + { + return (ConstantPoolItemMethodHandle)constantpool[index]; + } + + internal ConstantPoolItemMethodType GetConstantPoolConstantMethodType(int index) + { + return (ConstantPoolItemMethodType)constantpool[index]; + } + + internal object GetConstantPoolConstantLiveObject(int index) + { + return ((ConstantPoolItemLiveObject)constantpool[index]).Value; + } + + internal string Name + { + get + { + return GetConstantPoolClass(this_class); + } + } + + internal ConstantPoolItemClass SuperClass + { + get + { + return (ConstantPoolItemClass)constantpool[super_class]; + } + } + + internal Field[] Fields + { + get + { + return fields; + } + } + + internal Method[] Methods + { + get + { + return methods; + } + } + + internal ConstantPoolItemClass[] Interfaces + { + get + { + return interfaces; + } + } + + internal string SourceFileAttribute + { + get + { + return sourceFile; + } + } + + internal string SourcePath + { +#if STATIC_COMPILER + get { return sourcePath; } + set { sourcePath = value; } +#else + get { return sourceFile; } +#endif + } + + internal object[] Annotations + { + get + { + return annotations; + } + } + + internal string GenericSignature + { + get + { + return signature; + } + } + + internal string[] EnclosingMethod + { + get + { + return enclosingMethod; + } + } + + internal byte[] RuntimeVisibleTypeAnnotations + { + get + { + return runtimeVisibleTypeAnnotations; + } + } + + internal object[] GetConstantPool() + { + object[] cp = new object[constantpool.Length]; + for (int i = 1; i < cp.Length; i++) + { + if (constantpool[i] != null) + { + cp[i] = constantpool[i].GetRuntimeValue(); + } + } + return cp; + } + + internal string IKVMAssemblyAttribute + { + get + { + return ikvmAssembly; + } + } + + internal bool DeprecatedAttribute + { + get + { + return (flags & FLAG_MASK_DEPRECATED) != 0; + } + } + + internal bool IsInternal + { + get + { + return (flags & FLAG_MASK_INTERNAL) != 0; + } + } + + // for use by ikvmc (to implement the -privatepackage option) + internal void SetInternal() + { + access_flags &= ~Modifiers.AccessMask; + flags |= FLAG_MASK_INTERNAL; + } + + internal bool HasAssertions + { + get + { + return (flags & FLAG_HAS_ASSERTIONS) != 0; + } + } + + internal bool HasInitializedFields + { + get + { + foreach (Field f in fields) + { + if (f.IsStatic && !f.IsFinal && f.ConstantValue != null) + { + return true; + } + } + return false; + } + } + + internal BootstrapMethod GetBootstrapMethod(int index) + { + return bootstrapMethods[index]; + } + + internal struct BootstrapMethod + { + private ushort bsm_index; + private ushort[] args; + + internal BootstrapMethod(ushort bsm_index, ushort[] args) + { + this.bsm_index = bsm_index; + this.args = args; + } + + internal int BootstrapMethodIndex + { + get { return bsm_index; } + } + + internal int ArgumentCount + { + get { return args.Length; } + } + + internal int GetArgument(int index) + { + return args[index]; + } + } + + internal struct InnerClass + { + internal ushort innerClass; // ConstantPoolItemClass + internal ushort outerClass; // ConstantPoolItemClass + internal ushort name; // ConstantPoolItemUtf8 + internal Modifiers accessFlags; + } + + internal InnerClass[] InnerClasses + { + get + { + return innerClasses; + } + } + + internal enum RefKind + { + getField = 1, + getStatic = 2, + putField = 3, + putStatic = 4, + invokeVirtual = 5, + invokeStatic = 6, + invokeSpecial = 7, + newInvokeSpecial = 8, + invokeInterface = 9 + } + + internal enum ConstantType + { + Integer, + Long, + Float, + Double, + String, + Class, + MethodHandle, + MethodType, + LiveObject, // used by anonymous class constant pool patching + } + + internal abstract class ConstantPoolItem + { + internal virtual void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options) + { + } + + internal virtual void Link(TypeWrapper thisType, LoadMode mode) + { + } + + internal virtual ConstantType GetConstantType() + { + throw new InvalidOperationException(); + } + + internal virtual void MarkLinkRequired() + { + } + + // this is used for sun.reflect.ConstantPool + // it returns a boxed System.Int32, System.Int64, System.Float, System.Double or a string + internal virtual object GetRuntimeValue() + { + return null; + } + } + + internal sealed class ConstantPoolItemClass : ConstantPoolItem, IEquatable + { + private ushort name_index; + private string name; + private TypeWrapper typeWrapper; + private static char[] invalidJava15Characters = { '.', ';', '[', ']' }; + + internal ConstantPoolItemClass(BigEndianBinaryReader br) + { + name_index = br.ReadUInt16(); + } + + internal ConstantPoolItemClass(string name, TypeWrapper typeWrapper) + { + this.name = name; + this.typeWrapper = typeWrapper; + } + + internal override void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options) + { + // if the item was patched, we already have a name + if(name != null) + { + return; + } + name = classFile.GetConstantPoolUtf8String(utf8_cp, name_index); + if(name.Length > 0) + { + // We don't enforce the strict class name rules in the static compiler, since HotSpot doesn't enforce *any* rules on + // class names for the system (and boot) class loader. We still need to enforce the 1.5 restrictions, because we + // rely on those invariants. +#if !STATIC_COMPILER + if(classFile.MajorVersion < 49 && (options & ClassFileParseOptions.RelaxedClassNameValidation) == 0) + { + char prev = name[0]; + if(Char.IsLetter(prev) || prev == '$' || prev == '_' || prev == '[' || prev == '/') + { + int skip = 1; + int end = name.Length; + if(prev == '[') + { + if(!IsValidFieldSig(name)) + { + goto barf; + } + while(name[skip] == '[') + { + skip++; + } + if(name.EndsWith(";")) + { + end--; + } + } + for(int i = skip; i < end; i++) + { + char c = name[i]; + if(!Char.IsLetterOrDigit(c) && c != '$' && c != '_' && (c != '/' || prev == '/')) + { + goto barf; + } + prev = c; + } + name = String.Intern(name.Replace('/', '.')); + return; + } + } + else +#endif + { + // since 1.5 the restrictions on class names have been greatly reduced + int start = 0; + int end = name.Length; + if(name[0] == '[') + { + if(!IsValidFieldSig(name)) + { + goto barf; + } + // the semicolon is only allowed at the end and IsValidFieldSig enforces this, + // but since invalidJava15Characters contains the semicolon, we decrement end + // to make the following check against invalidJava15Characters ignore the + // trailing semicolon. + if(name[end - 1] == ';') + { + end--; + } + while(name[start] == '[') + { + start++; + } + } + if(name.IndexOfAny(invalidJava15Characters, start, end - start) >= 0) + { + goto barf; + } + name = String.Intern(name.Replace('/', '.')); + return; + } + } + barf: + throw new ClassFormatError("Invalid class name \"{0}\"", name); + } + + internal override void MarkLinkRequired() + { + if(typeWrapper == null) + { + typeWrapper = VerifierTypeWrapper.Null; + } + } + + internal void LinkSelf(TypeWrapper thisType) + { + this.typeWrapper = thisType; + } + + internal override void Link(TypeWrapper thisType, LoadMode mode) + { + if(typeWrapper == VerifierTypeWrapper.Null) + { + TypeWrapper tw = thisType.GetClassLoader().LoadClass(name, mode | LoadMode.WarnClassNotFound); +#if !STATIC_COMPILER && !FIRST_PASS + if(!tw.IsUnloadable) + { + try + { + thisType.GetClassLoader().CheckPackageAccess(tw, thisType.ClassObject.pd); + } + catch(java.lang.SecurityException) + { + tw = new UnloadableTypeWrapper(name); + } + } +#endif + typeWrapper = tw; + } + } + + internal string Name + { + get + { + return name; + } + } + + internal TypeWrapper GetClassType() + { + return typeWrapper; + } + + internal override ConstantType GetConstantType() + { + return ConstantType.Class; + } + + public sealed override int GetHashCode() + { + return name.GetHashCode(); + } + + public bool Equals(ConstantPoolItemClass other) + { + return ReferenceEquals(name, other.name); + } + } + + private sealed class ConstantPoolItemDouble : ConstantPoolItem + { + internal double d; + + internal ConstantPoolItemDouble(BigEndianBinaryReader br) + { + d = br.ReadDouble(); + } + + internal override ConstantType GetConstantType() + { + return ConstantType.Double; + } + + internal double Value + { + get + { + return d; + } + } + + internal override object GetRuntimeValue() + { + return d; + } + } + + internal abstract class ConstantPoolItemFMI : ConstantPoolItem + { + private ushort class_index; + private ushort name_and_type_index; + private ConstantPoolItemClass clazz; + private string name; + private string descriptor; + + internal ConstantPoolItemFMI(BigEndianBinaryReader br) + { + class_index = br.ReadUInt16(); + name_and_type_index = br.ReadUInt16(); + } + + internal override void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options) + { + ConstantPoolItemNameAndType name_and_type = (ConstantPoolItemNameAndType)classFile.GetConstantPoolItem(name_and_type_index); + clazz = (ConstantPoolItemClass)classFile.GetConstantPoolItem(class_index); + // if the constant pool items referred to were strings, GetConstantPoolItem returns null + if(name_and_type == null || clazz == null) + { + throw new ClassFormatError("Bad index in constant pool"); + } + name = String.Intern(classFile.GetConstantPoolUtf8String(utf8_cp, name_and_type.name_index)); + descriptor = classFile.GetConstantPoolUtf8String(utf8_cp, name_and_type.descriptor_index); + Validate(name, descriptor, classFile.MajorVersion); + descriptor = String.Intern(descriptor.Replace('/', '.')); + } + + protected abstract void Validate(string name, string descriptor, int majorVersion); + + internal override void MarkLinkRequired() + { + clazz.MarkLinkRequired(); + } + + internal override void Link(TypeWrapper thisType, LoadMode mode) + { + clazz.Link(thisType, mode); + } + + internal string Name + { + get + { + return name; + } + } + + internal string Signature + { + get + { + return descriptor; + } + } + + internal string Class + { + get + { + return clazz.Name; + } + } + + internal TypeWrapper GetClassType() + { + return clazz.GetClassType(); + } + + internal abstract MemberWrapper GetMember(); + } + + internal sealed class ConstantPoolItemFieldref : ConstantPoolItemFMI + { + private FieldWrapper field; + private TypeWrapper fieldTypeWrapper; + + internal ConstantPoolItemFieldref(BigEndianBinaryReader br) : base(br) + { + } + + protected override void Validate(string name, string descriptor, int majorVersion) + { + if(!IsValidFieldSig(descriptor)) + { + throw new ClassFormatError("Invalid field signature \"{0}\"", descriptor); + } + if(!IsValidFieldName(name, majorVersion)) + { + throw new ClassFormatError("Invalid field name \"{0}\"", name); + } + } + + internal TypeWrapper GetFieldType() + { + return fieldTypeWrapper; + } + + internal override void Link(TypeWrapper thisType, LoadMode mode) + { + base.Link(thisType, mode); + lock(this) + { + if(fieldTypeWrapper != null) + { + return; + } + } + FieldWrapper fw = null; + TypeWrapper wrapper = GetClassType(); + if(wrapper == null) + { + return; + } + if(!wrapper.IsUnloadable) + { + fw = wrapper.GetFieldWrapper(Name, Signature); + if(fw != null) + { + fw.Link(mode); + } + } + ClassLoaderWrapper classLoader = thisType.GetClassLoader(); + TypeWrapper fld = classLoader.FieldTypeWrapperFromSig(this.Signature, mode); + lock(this) + { + if(fieldTypeWrapper == null) + { + fieldTypeWrapper = fld; + field = fw; + } + } + } + + internal FieldWrapper GetField() + { + return field; + } + + internal override MemberWrapper GetMember() + { + return field; + } + } + + internal class ConstantPoolItemMI : ConstantPoolItemFMI + { + private TypeWrapper[] argTypeWrappers; + private TypeWrapper retTypeWrapper; + protected MethodWrapper method; + protected MethodWrapper invokespecialMethod; + + internal ConstantPoolItemMI(BigEndianBinaryReader br) : base(br) + { + } + + protected override void Validate(string name, string descriptor, int majorVersion) + { + if(!IsValidMethodSig(descriptor)) + { + throw new ClassFormatError("Method {0} has invalid signature {1}", name, descriptor); + } + if(!IsValidMethodName(name, majorVersion)) + { + if(!ReferenceEquals(name, StringConstants.INIT)) + { + throw new ClassFormatError("Invalid method name \"{0}\"", name); + } + if(!descriptor.EndsWith("V")) + { + throw new ClassFormatError("Method {0} has invalid signature {1}", name, descriptor); + } + } + } + + internal override void Link(TypeWrapper thisType, LoadMode mode) + { + base.Link(thisType, mode); + lock(this) + { + if(argTypeWrappers != null) + { + return; + } + } + ClassLoaderWrapper classLoader = thisType.GetClassLoader(); + TypeWrapper[] args = classLoader.ArgTypeWrapperListFromSig(this.Signature, mode); + TypeWrapper ret = classLoader.RetTypeWrapperFromSig(this.Signature, mode); + lock(this) + { + if(argTypeWrappers == null) + { + argTypeWrappers = args; + retTypeWrapper = ret; + } + } + } + + internal TypeWrapper[] GetArgTypes() + { + return argTypeWrappers; + } + + internal TypeWrapper GetRetType() + { + return retTypeWrapper; + } + + internal MethodWrapper GetMethod() + { + return method; + } + + internal MethodWrapper GetMethodForInvokespecial() + { + return invokespecialMethod != null ? invokespecialMethod : method; + } + + internal override MemberWrapper GetMember() + { + return method; + } + } + + internal sealed class ConstantPoolItemMethodref : ConstantPoolItemMI + { + internal ConstantPoolItemMethodref(BigEndianBinaryReader br) : base(br) + { + } + + internal override void Link(TypeWrapper thisType, LoadMode mode) + { + base.Link(thisType, mode); + TypeWrapper wrapper = GetClassType(); + if(wrapper != null && !wrapper.IsUnloadable) + { + method = wrapper.GetMethodWrapper(Name, Signature, !ReferenceEquals(Name, StringConstants.INIT)); + if(method != null) + { + method.Link(mode); + } + if(Name != StringConstants.INIT + && !thisType.IsInterface + && (!JVM.AllowNonVirtualCalls || (thisType.Modifiers & Modifiers.Super) == Modifiers.Super) + && thisType != wrapper + && thisType.IsSubTypeOf(wrapper)) + { + invokespecialMethod = thisType.BaseTypeWrapper.GetMethodWrapper(Name, Signature, true); + if(invokespecialMethod != null) + { + invokespecialMethod.Link(mode); + } + } + } + } + } + + internal sealed class ConstantPoolItemInterfaceMethodref : ConstantPoolItemMI + { + internal ConstantPoolItemInterfaceMethodref(BigEndianBinaryReader br) : base(br) + { + } + + internal override void Link(TypeWrapper thisType, LoadMode mode) + { + base.Link(thisType, mode); + TypeWrapper wrapper = GetClassType(); + if(wrapper != null) + { + if(!wrapper.IsUnloadable) + { + method = wrapper.GetInterfaceMethod(Name, Signature); + } + if(method == null) + { + // NOTE vmspec 5.4.3.4 clearly states that an interfacemethod may also refer to a method in Object + method = CoreClasses.java.lang.Object.Wrapper.GetMethodWrapper(Name, Signature, false); + } + if(method != null) + { + method.Link(mode); + } + } + } + } + + private sealed class ConstantPoolItemFloat : ConstantPoolItem + { + internal float v; + + internal ConstantPoolItemFloat(BigEndianBinaryReader br) + { + v = br.ReadSingle(); + } + + internal override ConstantType GetConstantType() + { + return ConstantType.Float; + } + + internal float Value + { + get + { + return v; + } + } + + internal override object GetRuntimeValue() + { + return v; + } + } + + private sealed class ConstantPoolItemInteger : ConstantPoolItem + { + internal int v; + + internal ConstantPoolItemInteger(BigEndianBinaryReader br) + { + v = br.ReadInt32(); + } + + internal override ConstantType GetConstantType() + { + return ConstantType.Integer; + } + + internal int Value + { + get + { + return v; + } + } + + internal override object GetRuntimeValue() + { + return v; + } + } + + private sealed class ConstantPoolItemLong : ConstantPoolItem + { + internal long l; + + internal ConstantPoolItemLong(BigEndianBinaryReader br) + { + l = br.ReadInt64(); + } + + internal override ConstantType GetConstantType() + { + return ConstantType.Long; + } + + internal long Value + { + get + { + return l; + } + } + + internal override object GetRuntimeValue() + { + return l; + } + } + + private sealed class ConstantPoolItemNameAndType : ConstantPoolItem + { + internal ushort name_index; + internal ushort descriptor_index; + + internal ConstantPoolItemNameAndType(BigEndianBinaryReader br) + { + name_index = br.ReadUInt16(); + descriptor_index = br.ReadUInt16(); + } + + internal override void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options) + { + if(classFile.GetConstantPoolUtf8String(utf8_cp, name_index) == null + || classFile.GetConstantPoolUtf8String(utf8_cp, descriptor_index) == null) + { + throw new ClassFormatError("Illegal constant pool index"); + } + } + } + + internal sealed class ConstantPoolItemMethodHandle : ConstantPoolItem + { + private byte ref_kind; + private ushort method_index; + private ConstantPoolItemFMI cpi; + + internal ConstantPoolItemMethodHandle(BigEndianBinaryReader br) + { + ref_kind = br.ReadByte(); + method_index = br.ReadUInt16(); + } + + internal override void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options) + { + switch ((RefKind)ref_kind) + { + case RefKind.getField: + case RefKind.getStatic: + case RefKind.putField: + case RefKind.putStatic: + cpi = classFile.GetConstantPoolItem(method_index) as ConstantPoolItemFieldref; + break; + case RefKind.invokeSpecial: + case RefKind.invokeVirtual: + case RefKind.invokeStatic: + case RefKind.newInvokeSpecial: + cpi = classFile.GetConstantPoolItem(method_index) as ConstantPoolItemMethodref; + if (cpi == null && classFile.MajorVersion >= 52 && ((RefKind)ref_kind == RefKind.invokeStatic || (RefKind)ref_kind == RefKind.invokeSpecial)) + goto case RefKind.invokeInterface; + break; + case RefKind.invokeInterface: + cpi = classFile.GetConstantPoolItem(method_index) as ConstantPoolItemInterfaceMethodref; + break; + } + if (cpi == null) + { + throw new ClassFormatError("Invalid constant pool item MethodHandle"); + } + if (ReferenceEquals(cpi.Name, StringConstants.INIT) && Kind != RefKind.newInvokeSpecial) + { + throw new ClassFormatError("Bad method name"); + } + } + + internal override void MarkLinkRequired() + { + cpi.MarkLinkRequired(); + } + + internal string Class + { + get { return cpi.Class; } + } + + internal string Name + { + get { return cpi.Name; } + } + + internal string Signature + { + get { return cpi.Signature; } + } + + internal ConstantPoolItemFMI MemberConstantPoolItem + { + get { return cpi; } + } + + internal RefKind Kind + { + get { return (RefKind)ref_kind; } + } + + internal MemberWrapper Member + { + get { return cpi.GetMember(); } + } + + internal TypeWrapper GetClassType() + { + return cpi.GetClassType(); + } + + internal override void Link(TypeWrapper thisType, LoadMode mode) + { + cpi.Link(thisType, mode); + } + + internal override ConstantType GetConstantType() + { + return ConstantType.MethodHandle; + } + } + + internal sealed class ConstantPoolItemMethodType : ConstantPoolItem + { + private ushort signature_index; + private string descriptor; + private TypeWrapper[] argTypeWrappers; + private TypeWrapper retTypeWrapper; + + internal ConstantPoolItemMethodType(BigEndianBinaryReader br) + { + signature_index = br.ReadUInt16(); + } + + internal override void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options) + { + string descriptor = classFile.GetConstantPoolUtf8String(utf8_cp, signature_index); + if (descriptor == null || !IsValidMethodSig(descriptor)) + { + throw new ClassFormatError("Invalid MethodType signature"); + } + this.descriptor = String.Intern(descriptor.Replace('/', '.')); + } + + internal override void Link(TypeWrapper thisType, LoadMode mode) + { + lock (this) + { + if (argTypeWrappers != null) + { + return; + } + } + ClassLoaderWrapper classLoader = thisType.GetClassLoader(); + TypeWrapper[] args = classLoader.ArgTypeWrapperListFromSig(descriptor, mode); + TypeWrapper ret = classLoader.RetTypeWrapperFromSig(descriptor, mode); + lock (this) + { + if (argTypeWrappers == null) + { + argTypeWrappers = args; + retTypeWrapper = ret; + } + } + } + + internal string Signature + { + get { return descriptor; } + } + + internal TypeWrapper[] GetArgTypes() + { + return argTypeWrappers; + } + + internal TypeWrapper GetRetType() + { + return retTypeWrapper; + } + + internal override ConstantType GetConstantType() + { + return ConstantType.MethodType; + } + } + + internal sealed class ConstantPoolItemInvokeDynamic : ConstantPoolItem + { + private ushort bootstrap_specifier_index; + private ushort name_and_type_index; + private string name; + private string descriptor; + private TypeWrapper[] argTypeWrappers; + private TypeWrapper retTypeWrapper; + + internal ConstantPoolItemInvokeDynamic(BigEndianBinaryReader br) + { + bootstrap_specifier_index = br.ReadUInt16(); + name_and_type_index = br.ReadUInt16(); + } + + internal override void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options) + { + ConstantPoolItemNameAndType name_and_type = (ConstantPoolItemNameAndType)classFile.GetConstantPoolItem(name_and_type_index); + // if the constant pool items referred to were strings, GetConstantPoolItem returns null + if (name_and_type == null) + { + throw new ClassFormatError("Bad index in constant pool"); + } + name = String.Intern(classFile.GetConstantPoolUtf8String(utf8_cp, name_and_type.name_index)); + descriptor = String.Intern(classFile.GetConstantPoolUtf8String(utf8_cp, name_and_type.descriptor_index).Replace('/', '.')); + } + + internal override void Link(TypeWrapper thisType, LoadMode mode) + { + lock (this) + { + if (argTypeWrappers != null) + { + return; + } + } + ClassLoaderWrapper classLoader = thisType.GetClassLoader(); + TypeWrapper[] args = classLoader.ArgTypeWrapperListFromSig(descriptor, mode); + TypeWrapper ret = classLoader.RetTypeWrapperFromSig(descriptor, mode); + lock (this) + { + if (argTypeWrappers == null) + { + argTypeWrappers = args; + retTypeWrapper = ret; + } + } + } + + internal TypeWrapper[] GetArgTypes() + { + return argTypeWrappers; + } + + internal TypeWrapper GetRetType() + { + return retTypeWrapper; + } + + internal string Name + { + get { return name; } + } + + internal string Signature + { + get { return descriptor; } + } + + internal ushort BootstrapMethod + { + get { return bootstrap_specifier_index; } + } + } + + private sealed class ConstantPoolItemString : ConstantPoolItem + { + private ushort string_index; + private string s; + + internal ConstantPoolItemString(BigEndianBinaryReader br) + { + string_index = br.ReadUInt16(); + } + + internal override void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options) + { + s = classFile.GetConstantPoolUtf8String(utf8_cp, string_index); + } + + internal override ConstantType GetConstantType() + { + return ConstantType.String; + } + + internal string Value + { + get + { + return s; + } + } + } + + // this is only used to copy strings into "constantpool" when we see a RuntimeVisibleTypeAnnotations attribute, + // because we need a consistent way of exposing constant pool items to the runtime and that case + private sealed class ConstantPoolItemUtf8 : ConstantPoolItem + { + private readonly string str; + + internal ConstantPoolItemUtf8(string str) + { + this.str = str; + } + + internal override object GetRuntimeValue() + { + return str; + } + } + + private sealed class ConstantPoolItemLiveObject : ConstantPoolItem + { + internal readonly object Value; + + internal ConstantPoolItemLiveObject(object value) + { + this.Value = value; + } + + internal override ConstantType GetConstantType() + { + return ConstantType.LiveObject; + } + } + + internal enum Constant + { + Utf8 = 1, + Integer = 3, + Float = 4, + Long = 5, + Double = 6, + Class = 7, + String = 8, + Fieldref = 9, + Methodref = 10, + InterfaceMethodref = 11, + NameAndType = 12, + MethodHandle = 15, + MethodType = 16, + InvokeDynamic = 18, + } + + internal abstract class FieldOrMethod : IEquatable + { + // Note that Modifiers is a ushort, so it combines nicely with the following ushort field + protected Modifiers access_flags; + protected ushort flags; + private string name; + private string descriptor; + protected string signature; + protected object[] annotations; + protected byte[] runtimeVisibleTypeAnnotations; + + internal FieldOrMethod(ClassFile classFile, string[] utf8_cp, BigEndianBinaryReader br) + { + access_flags = (Modifiers)br.ReadUInt16(); + name = String.Intern(classFile.GetConstantPoolUtf8String(utf8_cp, br.ReadUInt16())); + descriptor = classFile.GetConstantPoolUtf8String(utf8_cp, br.ReadUInt16()); + ValidateSig(classFile, descriptor); + descriptor = String.Intern(descriptor.Replace('/', '.')); + } + + protected abstract void ValidateSig(ClassFile classFile, string descriptor); + + internal string Name + { + get + { + return name; + } + } + + internal string Signature + { + get + { + return descriptor; + } + } + + internal object[] Annotations + { + get + { + return annotations; + } + } + + internal string GenericSignature + { + get + { + return signature; + } + } + + internal Modifiers Modifiers + { + get + { + return (Modifiers)access_flags; + } + } + + internal bool IsAbstract + { + get + { + return (access_flags & Modifiers.Abstract) != 0; + } + } + + internal bool IsFinal + { + get + { + return (access_flags & Modifiers.Final) != 0; + } + } + + internal bool IsPublic + { + get + { + return (access_flags & Modifiers.Public) != 0; + } + } + + internal bool IsPrivate + { + get + { + return (access_flags & Modifiers.Private) != 0; + } + } + + internal bool IsProtected + { + get + { + return (access_flags & Modifiers.Protected) != 0; + } + } + + internal bool IsStatic + { + get + { + return (access_flags & Modifiers.Static) != 0; + } + } + + internal bool IsSynchronized + { + get + { + return (access_flags & Modifiers.Synchronized) != 0; + } + } + + internal bool IsVolatile + { + get + { + return (access_flags & Modifiers.Volatile) != 0; + } + } + + internal bool IsTransient + { + get + { + return (access_flags & Modifiers.Transient) != 0; + } + } + + internal bool IsNative + { + get + { + return (access_flags & Modifiers.Native) != 0; + } + } + + internal bool IsEnum + { + get + { + return (access_flags & Modifiers.Enum) != 0; + } + } + + internal bool DeprecatedAttribute + { + get + { + return (flags & FLAG_MASK_DEPRECATED) != 0; + } + } + + internal bool IsInternal + { + get + { + return (flags & FLAG_MASK_INTERNAL) != 0; + } + } + + internal byte[] RuntimeVisibleTypeAnnotations + { + get + { + return runtimeVisibleTypeAnnotations; + } + } + + public sealed override int GetHashCode() + { + return name.GetHashCode() ^ descriptor.GetHashCode(); + } + + public bool Equals(FieldOrMethod other) + { + return ReferenceEquals(name, other.name) && ReferenceEquals(descriptor, other.descriptor); + } + } + + internal sealed class Field : FieldOrMethod + { + private object constantValue; + private string[] propertyGetterSetter; + + internal Field(ClassFile classFile, string[] utf8_cp, BigEndianBinaryReader br) : base(classFile, utf8_cp, br) + { + if((IsPrivate && IsPublic) || (IsPrivate && IsProtected) || (IsPublic && IsProtected) + || (IsFinal && IsVolatile) + || (classFile.IsInterface && (!IsPublic || !IsStatic || !IsFinal || IsTransient))) + { + throw new ClassFormatError("{0} (Illegal field modifiers: 0x{1:X})", classFile.Name, access_flags); + } + int attributes_count = br.ReadUInt16(); + for(int i = 0; i < attributes_count; i++) + { + switch(classFile.GetConstantPoolUtf8String(utf8_cp, br.ReadUInt16())) + { + case "Deprecated": + if(br.ReadUInt32() != 0) + { + throw new ClassFormatError("Invalid Deprecated attribute length"); + } + flags |= FLAG_MASK_DEPRECATED; + break; + case "ConstantValue": + { + if(br.ReadUInt32() != 2) + { + throw new ClassFormatError("Invalid ConstantValue attribute length"); + } + ushort index = br.ReadUInt16(); + try + { + switch(Signature) + { + case "I": + constantValue = classFile.GetConstantPoolConstantInteger(index); + break; + case "S": + constantValue = (short)classFile.GetConstantPoolConstantInteger(index); + break; + case "B": + constantValue = (byte)classFile.GetConstantPoolConstantInteger(index); + break; + case "C": + constantValue = (char)classFile.GetConstantPoolConstantInteger(index); + break; + case "Z": + constantValue = classFile.GetConstantPoolConstantInteger(index) != 0; + break; + case "J": + constantValue = classFile.GetConstantPoolConstantLong(index); + break; + case "F": + constantValue = classFile.GetConstantPoolConstantFloat(index); + break; + case "D": + constantValue = classFile.GetConstantPoolConstantDouble(index); + break; + case "Ljava.lang.String;": + constantValue = classFile.GetConstantPoolConstantString(index); + break; + default: + throw new ClassFormatError("{0} (Invalid signature for constant)", classFile.Name); + } + } + catch(InvalidCastException) + { + throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name); + } + catch(IndexOutOfRangeException) + { + throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name); + } + catch(InvalidOperationException) + { + throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name); + } + catch(NullReferenceException) + { + throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name); + } + break; + } + case "Signature": + if(classFile.MajorVersion < 49) + { + goto default; + } + if(br.ReadUInt32() != 2) + { + throw new ClassFormatError("Signature attribute has incorrect length"); + } + signature = classFile.GetConstantPoolUtf8String(utf8_cp, br.ReadUInt16()); + break; + case "RuntimeVisibleAnnotations": + if(classFile.MajorVersion < 49) + { + goto default; + } + annotations = ReadAnnotations(br, classFile, utf8_cp); + break; + case "RuntimeInvisibleAnnotations": + if(classFile.MajorVersion < 49) + { + goto default; + } + foreach(object[] annot in ReadAnnotations(br, classFile, utf8_cp)) + { + if(annot[1].Equals("Likvm/lang/Property;")) + { + DecodePropertyAnnotation(classFile, annot); + } +#if STATIC_COMPILER + else if(annot[1].Equals("Likvm/lang/Internal;")) + { + this.access_flags &= ~Modifiers.AccessMask; + flags |= FLAG_MASK_INTERNAL; + } +#endif + } + break; + case "RuntimeVisibleTypeAnnotations": + if (classFile.MajorVersion < 52) + { + goto default; + } + classFile.CreateUtf8ConstantPoolItems(utf8_cp); + runtimeVisibleTypeAnnotations = br.Section(br.ReadUInt32()).ToArray(); + break; + default: + br.Skip(br.ReadUInt32()); + break; + } + } + } + + private void DecodePropertyAnnotation(ClassFile classFile, object[] annot) + { + if(propertyGetterSetter != null) + { + Tracer.Error(Tracer.ClassLoading, "Ignoring duplicate ikvm.lang.Property annotation on {0}.{1}", classFile.Name, this.Name); + return; + } + propertyGetterSetter = new string[2]; + for(int i = 2; i < annot.Length - 1; i += 2) + { + string value = annot[i + 1] as string; + if(value == null) + { + propertyGetterSetter = null; + break; + } + if(annot[i].Equals("get") && propertyGetterSetter[0] == null) + { + propertyGetterSetter[0] = value; + } + else if(annot[i].Equals("set") && propertyGetterSetter[1] == null) + { + propertyGetterSetter[1] = value; + } + else + { + propertyGetterSetter = null; + break; + } + } + if(propertyGetterSetter == null || propertyGetterSetter[0] == null) + { + propertyGetterSetter = null; + Tracer.Error(Tracer.ClassLoading, "Ignoring malformed ikvm.lang.Property annotation on {0}.{1}", classFile.Name, this.Name); + return; + } + } + + protected override void ValidateSig(ClassFile classFile, string descriptor) + { + if(!IsValidFieldSig(descriptor)) + { + throw new ClassFormatError("{0} (Field \"{1}\" has invalid signature \"{2}\")", classFile.Name, this.Name, descriptor); + } + } + + internal object ConstantValue + { + get + { + return constantValue; + } + } + + internal void PatchConstantValue(object value) + { + constantValue = value; + } + + internal bool IsStaticFinalConstant + { + get { return (access_flags & (Modifiers.Final | Modifiers.Static)) == (Modifiers.Final | Modifiers.Static) && constantValue != null; } + } + + internal bool IsProperty + { + get + { + return propertyGetterSetter != null; + } + } + + internal string PropertyGetter + { + get + { + return propertyGetterSetter[0]; + } + } + + internal string PropertySetter + { + get + { + return propertyGetterSetter[1]; + } + } + } + + internal sealed class Method : FieldOrMethod + { + private Code code; + private string[] exceptions; + private LowFreqData low; + private MethodParametersEntry[] parameters; + + sealed class LowFreqData + { + internal object annotationDefault; + internal object[][] parameterAnnotations; +#if STATIC_COMPILER + internal string DllExportName; + internal int DllExportOrdinal; + internal string InterlockedCompareAndSetField; +#endif + } + + internal Method(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options, BigEndianBinaryReader br) : base(classFile, utf8_cp, br) + { + // vmspec 4.6 says that all flags, except ACC_STRICT are ignored on + // however, since Java 7 it does need to be marked static + if(ReferenceEquals(Name, StringConstants.CLINIT) && ReferenceEquals(Signature, StringConstants.SIG_VOID) && (classFile.MajorVersion < 51 || IsStatic)) + { + access_flags &= Modifiers.Strictfp; + access_flags |= (Modifiers.Static | Modifiers.Private); + } + else + { + // LAMESPEC: vmspec 4.6 says that abstract methods can not be strictfp (and this makes sense), but + // javac (pre 1.5) is broken and marks abstract methods as strictfp (if you put the strictfp on the class) + if((ReferenceEquals(Name, StringConstants.INIT) && (IsStatic || IsSynchronized || IsFinal || IsAbstract || IsNative)) + || (IsPrivate && IsPublic) || (IsPrivate && IsProtected) || (IsPublic && IsProtected) + || (IsAbstract && (IsFinal || IsNative || IsPrivate || IsStatic || IsSynchronized)) + || (classFile.IsInterface && classFile.MajorVersion <= 51 && (!IsPublic || IsFinal || IsNative || IsSynchronized || !IsAbstract)) + || (classFile.IsInterface && classFile.MajorVersion >= 52 && (!(IsPublic || IsPrivate) || IsFinal || IsNative || IsSynchronized))) + { + throw new ClassFormatError("Method {0} in class {1} has illegal modifiers: 0x{2:X}", Name, classFile.Name, (int)access_flags); + } + } + int attributes_count = br.ReadUInt16(); + for(int i = 0; i < attributes_count; i++) + { + switch(classFile.GetConstantPoolUtf8String(utf8_cp, br.ReadUInt16())) + { + case "Deprecated": + if(br.ReadUInt32() != 0) + { + throw new ClassFormatError("Invalid Deprecated attribute length"); + } + flags |= FLAG_MASK_DEPRECATED; + break; + case "Code": + { + if(!code.IsEmpty) + { + throw new ClassFormatError("{0} (Duplicate Code attribute)", classFile.Name); + } + BigEndianBinaryReader rdr = br.Section(br.ReadUInt32()); + code.Read(classFile, utf8_cp, this, rdr, options); + if(!rdr.IsAtEnd) + { + throw new ClassFormatError("{0} (Code attribute has wrong length)", classFile.Name); + } + break; + } + case "Exceptions": + { + if(exceptions != null) + { + throw new ClassFormatError("{0} (Duplicate Exceptions attribute)", classFile.Name); + } + BigEndianBinaryReader rdr = br.Section(br.ReadUInt32()); + ushort count = rdr.ReadUInt16(); + exceptions = new string[count]; + for(int j = 0; j < count; j++) + { + exceptions[j] = classFile.GetConstantPoolClass(rdr.ReadUInt16()); + } + if(!rdr.IsAtEnd) + { + throw new ClassFormatError("{0} (Exceptions attribute has wrong length)", classFile.Name); + } + break; + } + case "Signature": + if(classFile.MajorVersion < 49) + { + goto default; + } + if(br.ReadUInt32() != 2) + { + throw new ClassFormatError("Signature attribute has incorrect length"); + } + signature = classFile.GetConstantPoolUtf8String(utf8_cp, br.ReadUInt16()); + break; + case "RuntimeVisibleAnnotations": + if(classFile.MajorVersion < 49) + { + goto default; + } + annotations = ReadAnnotations(br, classFile, utf8_cp); + if ((options & ClassFileParseOptions.TrustedAnnotations) != 0) + { + foreach(object[] annot in annotations) + { + switch((string)annot[1]) + { +#if STATIC_COMPILER + case "Lsun/reflect/CallerSensitive;": + flags |= FLAG_CALLERSENSITIVE; + break; +#endif + case "Ljava/lang/invoke/LambdaForm$Compiled;": + flags |= FLAG_LAMBDAFORM_COMPILED; + break; + case "Ljava/lang/invoke/LambdaForm$Hidden;": + flags |= FLAG_LAMBDAFORM_HIDDEN; + break; + case "Ljava/lang/invoke/ForceInline;": + flags |= FLAG_FORCEINLINE; + break; + } + } + } + break; + case "RuntimeVisibleParameterAnnotations": + { + if(classFile.MajorVersion < 49) + { + goto default; + } + if(low == null) + { + low = new LowFreqData(); + } + BigEndianBinaryReader rdr = br.Section(br.ReadUInt32()); + byte num_parameters = rdr.ReadByte(); + low.parameterAnnotations = new object[num_parameters][]; + for(int j = 0; j < num_parameters; j++) + { + ushort num_annotations = rdr.ReadUInt16(); + low.parameterAnnotations[j] = new object[num_annotations]; + for(int k = 0; k < num_annotations; k++) + { + low.parameterAnnotations[j][k] = ReadAnnotation(rdr, classFile, utf8_cp); + } + } + if(!rdr.IsAtEnd) + { + throw new ClassFormatError("{0} (RuntimeVisibleParameterAnnotations attribute has wrong length)", classFile.Name); + } + break; + } + case "AnnotationDefault": + { + if(classFile.MajorVersion < 49) + { + goto default; + } + if(low == null) + { + low = new LowFreqData(); + } + BigEndianBinaryReader rdr = br.Section(br.ReadUInt32()); + low.annotationDefault = ReadAnnotationElementValue(rdr, classFile, utf8_cp); + if(!rdr.IsAtEnd) + { + throw new ClassFormatError("{0} (AnnotationDefault attribute has wrong length)", classFile.Name); + } + break; + } +#if STATIC_COMPILER + case "RuntimeInvisibleAnnotations": + if(classFile.MajorVersion < 49) + { + goto default; + } + foreach(object[] annot in ReadAnnotations(br, classFile, utf8_cp)) + { + if(annot[1].Equals("Likvm/lang/Internal;")) + { + if (classFile.IsInterface) + { + StaticCompiler.IssueMessage(Message.InterfaceMethodCantBeInternal, classFile.Name, this.Name, this.Signature); + } + else + { + this.access_flags &= ~Modifiers.AccessMask; + flags |= FLAG_MASK_INTERNAL; + } + } + if(annot[1].Equals("Likvm/lang/DllExport;")) + { + string name = null; + int? ordinal = null; + for (int j = 2; j < annot.Length; j += 2) + { + if (annot[j].Equals("name") && annot[j + 1] is string) + { + name = (string)annot[j + 1]; + } + else if (annot[j].Equals("ordinal") && annot[j + 1] is int) + { + ordinal = (int)annot[j + 1]; + } + } + if (name != null && ordinal != null) + { + if (!IsStatic) + { + StaticCompiler.IssueMessage(Message.DllExportMustBeStaticMethod, classFile.Name, this.Name, this.Signature); + } + else + { + if (low == null) + { + low = new LowFreqData(); + } + low.DllExportName = name; + low.DllExportOrdinal = ordinal.Value; + } + } + } + if(annot[1].Equals("Likvm/internal/InterlockedCompareAndSet;")) + { + string field = null; + for (int j = 2; j < annot.Length; j += 2) + { + if (annot[j].Equals("value") && annot[j + 1] is string) + { + field = (string)annot[j + 1]; + } + } + if (field != null) + { + if (low == null) + { + low = new LowFreqData(); + } + low.InterlockedCompareAndSetField = field; + } + } + } + break; +#endif + case "MethodParameters": + { + if(classFile.MajorVersion < 52) + { + goto default; + } + if(parameters != null) + { + throw new ClassFormatError("{0} (Duplicate MethodParameters attribute)", classFile.Name); + } + parameters = ReadMethodParameters(br, utf8_cp); + break; + } + case "RuntimeVisibleTypeAnnotations": + if (classFile.MajorVersion < 52) + { + goto default; + } + classFile.CreateUtf8ConstantPoolItems(utf8_cp); + runtimeVisibleTypeAnnotations = br.Section(br.ReadUInt32()).ToArray(); + break; + default: + br.Skip(br.ReadUInt32()); + break; + } + } + if(IsAbstract || IsNative) + { + if(!code.IsEmpty) + { + throw new ClassFormatError("Code attribute in native or abstract methods in class file " + classFile.Name); + } + } + else + { + if(code.IsEmpty) + { + if(ReferenceEquals(this.Name, StringConstants.CLINIT)) + { + code.verifyError = string.Format("Class {0}, method {1} signature {2}: No Code attribute", classFile.Name, this.Name, this.Signature); + return; + } + throw new ClassFormatError("Absent Code attribute in method that is not native or abstract in class file " + classFile.Name); + } + } + } + + private static MethodParametersEntry[] ReadMethodParameters(BigEndianBinaryReader br, string[] utf8_cp) + { + uint length = br.ReadUInt32(); + if(length > 0) + { + BigEndianBinaryReader rdr = br.Section(length); + byte parameters_count = rdr.ReadByte(); + if(length == 1 + parameters_count * 4) + { + MethodParametersEntry[] parameters = new MethodParametersEntry[parameters_count]; + for(int j = 0; j < parameters_count; j++) + { + ushort name = rdr.ReadUInt16(); + if(name >= utf8_cp.Length || (name != 0 && utf8_cp[name] == null)) + { + return MethodParametersEntry.Malformed; + } + parameters[j].name = utf8_cp[name]; + parameters[j].flags = rdr.ReadUInt16(); + } + return parameters; + } + } + throw new ClassFormatError("Invalid MethodParameters method attribute length " + length + " in class file"); + } + + protected override void ValidateSig(ClassFile classFile, string descriptor) + { + if(!IsValidMethodSig(descriptor)) + { + throw new ClassFormatError("{0} (Method \"{1}\" has invalid signature \"{2}\")", classFile.Name, this.Name, descriptor); + } + } + + internal bool IsStrictfp + { + get + { + return (access_flags & Modifiers.Strictfp) != 0; + } + } + + internal bool IsVirtual + { + get + { + return (access_flags & (Modifiers.Static | Modifiers.Private)) == 0 + && !IsConstructor; + } + } + + // Is this the ()V method? + internal bool IsClassInitializer + { + get + { + return ReferenceEquals(Name, StringConstants.CLINIT) && ReferenceEquals(Signature, StringConstants.SIG_VOID) && IsStatic; + } + } + + internal bool IsConstructor + { + get + { + return ReferenceEquals(Name, StringConstants.INIT); + } + } + +#if STATIC_COMPILER + internal bool IsCallerSensitive + { + get + { + return (flags & FLAG_CALLERSENSITIVE) != 0; + } + } +#endif + + internal bool IsLambdaFormCompiled + { + get + { + return (flags & FLAG_LAMBDAFORM_COMPILED) != 0; + } + } + + internal bool IsLambdaFormHidden + { + get + { + return (flags & FLAG_LAMBDAFORM_HIDDEN) != 0; + } + } + + internal bool IsForceInline + { + get + { + return (flags & FLAG_FORCEINLINE) != 0; + } + } + + internal string[] ExceptionsAttribute + { + get + { + return exceptions; + } + } + + internal object[][] ParameterAnnotations + { + get + { + return low == null ? null : low.parameterAnnotations; + } + } + + internal object AnnotationDefault + { + get + { + return low == null ? null : low.annotationDefault; + } + } + +#if STATIC_COMPILER + internal string DllExportName + { + get + { + return low == null ? null : low.DllExportName; + } + } + + internal int DllExportOrdinal + { + get + { + return low == null ? -1 : low.DllExportOrdinal; + } + } + + internal string InterlockedCompareAndSetField + { + get + { + return low == null ? null : low.InterlockedCompareAndSetField; + } + } +#endif + + internal string VerifyError + { + get + { + return code.verifyError; + } + } + + // maps argument 'slot' (as encoded in the xload/xstore instructions) into the ordinal + internal int[] ArgMap + { + get + { + return code.argmap; + } + } + + internal int MaxStack + { + get + { + return code.max_stack; + } + } + + internal int MaxLocals + { + get + { + return code.max_locals; + } + } + + internal Instruction[] Instructions + { + get + { + return code.instructions; + } + set + { + code.instructions = value; + } + } + + internal ExceptionTableEntry[] ExceptionTable + { + get + { + return code.exception_table; + } + set + { + code.exception_table = value; + } + } + + internal LineNumberTableEntry[] LineNumberTableAttribute + { + get + { + return code.lineNumberTable; + } + } + + internal LocalVariableTableEntry[] LocalVariableTableAttribute + { + get + { + return code.localVariableTable; + } + } + + internal MethodParametersEntry[] MethodParameters + { + get + { + return parameters; + } + } + + internal bool MalformedMethodParameters + { + get + { + return parameters == MethodParametersEntry.Malformed; + } + } + + internal bool HasJsr + { + get + { + return code.hasJsr; + } + } + + private struct Code + { + internal bool hasJsr; + internal string verifyError; + internal ushort max_stack; + internal ushort max_locals; + internal Instruction[] instructions; + internal ExceptionTableEntry[] exception_table; + internal int[] argmap; + internal LineNumberTableEntry[] lineNumberTable; + internal LocalVariableTableEntry[] localVariableTable; + + internal void Read(ClassFile classFile, string[] utf8_cp, Method method, BigEndianBinaryReader br, ClassFileParseOptions options) + { + max_stack = br.ReadUInt16(); + max_locals = br.ReadUInt16(); + uint code_length = br.ReadUInt32(); + if(code_length == 0 || code_length > 65535) + { + throw new ClassFormatError("Invalid method Code length {1} in class file {0}", classFile.Name, code_length); + } + Instruction[] instructions = new Instruction[code_length + 1]; + int basePosition = br.Position; + int instructionIndex = 0; + try + { + BigEndianBinaryReader rdr = br.Section(code_length); + while(!rdr.IsAtEnd) + { + instructions[instructionIndex].Read((ushort)(rdr.Position - basePosition), rdr, classFile); + hasJsr |= instructions[instructionIndex].NormalizedOpCode == NormalizedByteCode.__jsr; + instructionIndex++; + } + // we add an additional nop instruction to make it easier for consumers of the code array + instructions[instructionIndex++].SetTermNop((ushort)(rdr.Position - basePosition)); + } + catch(ClassFormatError x) + { + // any class format errors in the code block are actually verify errors + verifyError = x.Message; + } + this.instructions = new Instruction[instructionIndex]; + Array.Copy(instructions, 0, this.instructions, 0, instructionIndex); + // build the pcIndexMap + int[] pcIndexMap = new int[this.instructions[instructionIndex - 1].PC + 1]; + for(int i = 0; i < pcIndexMap.Length; i++) + { + pcIndexMap[i] = -1; + } + for(int i = 0; i < instructionIndex - 1; i++) + { + pcIndexMap[this.instructions[i].PC] = i; + } + // convert branch offsets to indexes + for(int i = 0; i < instructionIndex - 1; i++) + { + switch(this.instructions[i].NormalizedOpCode) + { + case NormalizedByteCode.__ifeq: + case NormalizedByteCode.__ifne: + case NormalizedByteCode.__iflt: + case NormalizedByteCode.__ifge: + case NormalizedByteCode.__ifgt: + case NormalizedByteCode.__ifle: + case NormalizedByteCode.__if_icmpeq: + case NormalizedByteCode.__if_icmpne: + case NormalizedByteCode.__if_icmplt: + case NormalizedByteCode.__if_icmpge: + case NormalizedByteCode.__if_icmpgt: + case NormalizedByteCode.__if_icmple: + case NormalizedByteCode.__if_acmpeq: + case NormalizedByteCode.__if_acmpne: + case NormalizedByteCode.__ifnull: + case NormalizedByteCode.__ifnonnull: + case NormalizedByteCode.__goto: + case NormalizedByteCode.__jsr: + this.instructions[i].SetTargetIndex(pcIndexMap[this.instructions[i].Arg1 + this.instructions[i].PC]); + break; + case NormalizedByteCode.__tableswitch: + case NormalizedByteCode.__lookupswitch: + this.instructions[i].MapSwitchTargets(pcIndexMap); + break; + } + } + // read exception table + ushort exception_table_length = br.ReadUInt16(); + exception_table = new ExceptionTableEntry[exception_table_length]; + for(int i = 0; i < exception_table_length; i++) + { + ushort start_pc = br.ReadUInt16(); + ushort end_pc = br.ReadUInt16(); + ushort handler_pc = br.ReadUInt16(); + ushort catch_type = br.ReadUInt16(); + if(start_pc >= end_pc + || end_pc > code_length + || handler_pc >= code_length + || (catch_type != 0 && !classFile.SafeIsConstantPoolClass(catch_type))) + { + throw new ClassFormatError("Illegal exception table: {0}.{1}{2}", classFile.Name, method.Name, method.Signature); + } + classFile.MarkLinkRequiredConstantPoolItem(catch_type); + // if start_pc, end_pc or handler_pc is invalid (i.e. doesn't point to the start of an instruction), + // the index will be -1 and this will be handled by the verifier + int startIndex = pcIndexMap[start_pc]; + int endIndex; + if (end_pc == code_length) + { + // it is legal for end_pc to point to just after the last instruction, + // but since there isn't an entry in our pcIndexMap for that, we have + // a special case for this + endIndex = instructionIndex - 1; + } + else + { + endIndex = pcIndexMap[end_pc]; + } + int handlerIndex = pcIndexMap[handler_pc]; + exception_table[i] = new ExceptionTableEntry(startIndex, endIndex, handlerIndex, catch_type, i); + } + ushort attributes_count = br.ReadUInt16(); + for(int i = 0; i < attributes_count; i++) + { + switch(classFile.GetConstantPoolUtf8String(utf8_cp, br.ReadUInt16())) + { + case "LineNumberTable": + if((options & ClassFileParseOptions.LineNumberTable) != 0) + { + BigEndianBinaryReader rdr = br.Section(br.ReadUInt32()); + int count = rdr.ReadUInt16(); + lineNumberTable = new LineNumberTableEntry[count]; + for(int j = 0; j < count; j++) + { + lineNumberTable[j].start_pc = rdr.ReadUInt16(); + lineNumberTable[j].line_number = rdr.ReadUInt16(); + if(lineNumberTable[j].start_pc >= code_length) + { + throw new ClassFormatError("{0} (LineNumberTable has invalid pc)", classFile.Name); + } + } + if(!rdr.IsAtEnd) + { + throw new ClassFormatError("{0} (LineNumberTable attribute has wrong length)", classFile.Name); + } + } + else + { + br.Skip(br.ReadUInt32()); + } + break; + case "LocalVariableTable": + if((options & ClassFileParseOptions.LocalVariableTable) != 0) + { + BigEndianBinaryReader rdr = br.Section(br.ReadUInt32()); + int count = rdr.ReadUInt16(); + localVariableTable = new LocalVariableTableEntry[count]; + for(int j = 0; j < count; j++) + { + localVariableTable[j].start_pc = rdr.ReadUInt16(); + localVariableTable[j].length = rdr.ReadUInt16(); + localVariableTable[j].name = classFile.GetConstantPoolUtf8String(utf8_cp, rdr.ReadUInt16()); + localVariableTable[j].descriptor = classFile.GetConstantPoolUtf8String(utf8_cp, rdr.ReadUInt16()).Replace('/', '.'); + localVariableTable[j].index = rdr.ReadUInt16(); + } + // NOTE we're intentionally not checking that we're at the end of the section + // (optional attributes shouldn't cause ClassFormatError) + } + else + { + br.Skip(br.ReadUInt32()); + } + break; + default: + br.Skip(br.ReadUInt32()); + break; + } + } + // build the argmap + string sig = method.Signature; + List args = new List(); + int pos = 0; + if(!method.IsStatic) + { + args.Add(pos++); + } + for(int i = 1; sig[i] != ')'; i++) + { + args.Add(pos++); + switch(sig[i]) + { + case 'L': + i = sig.IndexOf(';', i); + break; + case 'D': + case 'J': + args.Add(-1); + break; + case '[': + { + while(sig[i] == '[') + { + i++; + } + if(sig[i] == 'L') + { + i = sig.IndexOf(';', i); + } + break; + } + } + } + argmap = args.ToArray(); + if(args.Count > max_locals) + { + throw new ClassFormatError("{0} (Arguments can't fit into locals)", classFile.Name); + } + } + + internal bool IsEmpty + { + get + { + return instructions == null; + } + } + } + + internal sealed class ExceptionTableEntry + { + internal readonly int startIndex; + internal readonly int endIndex; + internal readonly int handlerIndex; + internal readonly ushort catch_type; + internal readonly int ordinal; + internal readonly bool isFinally; + + internal ExceptionTableEntry(int startIndex, int endIndex, int handlerIndex, ushort catch_type, int ordinal) + : this(startIndex, endIndex, handlerIndex, catch_type, ordinal, false) + { + } + + internal ExceptionTableEntry(int startIndex, int endIndex, int handlerIndex, ushort catch_type, int ordinal, bool isFinally) + { + this.startIndex = startIndex; + this.endIndex = endIndex; + this.handlerIndex = handlerIndex; + this.catch_type = catch_type; + this.ordinal = ordinal; + this.isFinally = isFinally; + } + } + + [Flags] + internal enum InstructionFlags : byte + { + Reachable = 1, + Processed = 2, + BranchTarget = 4, + } + + internal struct Instruction + { + private ushort pc; + private NormalizedByteCode normopcode; + private int arg1; + private short arg2; + private SwitchEntry[] switch_entries; + + struct SwitchEntry + { + internal int value; + internal int target; + } + + internal void SetHardError(HardError error, int messageId) + { + normopcode = NormalizedByteCode.__static_error; + arg2 = (short)error; + arg1 = messageId; + } + + internal HardError HardError + { + get + { + return (HardError)arg2; + } + } + + internal int HandlerIndex + { + get { return (ushort)arg2; } + } + + internal int HardErrorMessageId + { + get + { + return arg1; + } + } + + internal void PatchOpCode(NormalizedByteCode bc) + { + this.normopcode = bc; + } + + internal void PatchOpCode(NormalizedByteCode bc, int arg1) + { + this.normopcode = bc; + this.arg1 = arg1; + } + + internal void PatchOpCode(NormalizedByteCode bc, int arg1, short arg2) + { + this.normopcode = bc; + this.arg1 = arg1; + this.arg2 = arg2; + } + + internal void SetPC(int pc) + { + this.pc = (ushort)pc; + } + + internal void SetTargetIndex(int targetIndex) + { + this.arg1 = targetIndex; + } + + internal void SetTermNop(ushort pc) + { + // TODO what happens if we already have exactly the maximum number of instructions? + this.pc = pc; + this.normopcode = NormalizedByteCode.__nop; + } + + internal void MapSwitchTargets(int[] pcIndexMap) + { + arg1 = pcIndexMap[arg1 + pc]; + for (int i = 0; i < switch_entries.Length; i++) + { + switch_entries[i].target = pcIndexMap[switch_entries[i].target + pc]; + } + } + + internal void Read(ushort pc, BigEndianBinaryReader br, ClassFile classFile) + { + this.pc = pc; + ByteCode bc = (ByteCode)br.ReadByte(); + switch(ByteCodeMetaData.GetMode(bc)) + { + case ByteCodeMode.Simple: + break; + case ByteCodeMode.Constant_1: + arg1 = br.ReadByte(); + classFile.MarkLinkRequiredConstantPoolItem(arg1); + break; + case ByteCodeMode.Local_1: + arg1 = br.ReadByte(); + break; + case ByteCodeMode.Constant_2: + arg1 = br.ReadUInt16(); + classFile.MarkLinkRequiredConstantPoolItem(arg1); + break; + case ByteCodeMode.Branch_2: + arg1 = br.ReadInt16(); + break; + case ByteCodeMode.Branch_4: + arg1 = br.ReadInt32(); + break; + case ByteCodeMode.Constant_2_1_1: + arg1 = br.ReadUInt16(); + classFile.MarkLinkRequiredConstantPoolItem(arg1); + arg2 = br.ReadByte(); + if(br.ReadByte() != 0) + { + throw new ClassFormatError("invokeinterface filler must be zero"); + } + break; + case ByteCodeMode.Immediate_1: + arg1 = br.ReadSByte(); + break; + case ByteCodeMode.Immediate_2: + arg1 = br.ReadInt16(); + break; + case ByteCodeMode.Local_1_Immediate_1: + arg1 = br.ReadByte(); + arg2 = br.ReadSByte(); + break; + case ByteCodeMode.Constant_2_Immediate_1: + arg1 = br.ReadUInt16(); + classFile.MarkLinkRequiredConstantPoolItem(arg1); + arg2 = br.ReadSByte(); + break; + case ByteCodeMode.Tableswitch: + { + // skip the padding + uint p = pc + 1u; + uint align = ((p + 3) & 0x7ffffffc) - p; + br.Skip(align); + int default_offset = br.ReadInt32(); + this.arg1 = default_offset; + int low = br.ReadInt32(); + int high = br.ReadInt32(); + if(low > high || high > 16384L + low) + { + throw new ClassFormatError("Incorrect tableswitch"); + } + SwitchEntry[] entries = new SwitchEntry[high - low + 1]; + for(int i = low; i < high; i++) + { + entries[i - low].value = i; + entries[i - low].target = br.ReadInt32(); + } + // do the last entry outside the loop, to avoid overflowing "i", if high == int.MaxValue + entries[high - low].value = high; + entries[high - low].target = br.ReadInt32(); + this.switch_entries = entries; + break; + } + case ByteCodeMode.Lookupswitch: + { + // skip the padding + uint p = pc + 1u; + uint align = ((p + 3) & 0x7ffffffc) - p; + br.Skip(align); + int default_offset = br.ReadInt32(); + this.arg1 = default_offset; + int count = br.ReadInt32(); + if(count < 0 || count > 16384) + { + throw new ClassFormatError("Incorrect lookupswitch"); + } + SwitchEntry[] entries = new SwitchEntry[count]; + for(int i = 0; i < count; i++) + { + entries[i].value = br.ReadInt32(); + entries[i].target = br.ReadInt32(); + } + this.switch_entries = entries; + break; + } + case ByteCodeMode.WidePrefix: + bc = (ByteCode)br.ReadByte(); + // NOTE the PC of a wide instruction is actually the PC of the + // wide prefix, not the following instruction (vmspec 4.9.2) + switch(ByteCodeMetaData.GetWideMode(bc)) + { + case ByteCodeModeWide.Local_2: + arg1 = br.ReadUInt16(); + break; + case ByteCodeModeWide.Local_2_Immediate_2: + arg1 = br.ReadUInt16(); + arg2 = br.ReadInt16(); + break; + default: + throw new ClassFormatError("Invalid wide prefix on opcode: {0}", bc); + } + break; + default: + throw new ClassFormatError("Invalid opcode: {0}", bc); + } + this.normopcode = ByteCodeMetaData.GetNormalizedByteCode(bc); + arg1 = ByteCodeMetaData.GetArg(bc, arg1); + } + + internal int PC + { + get + { + return pc; + } + } + + internal NormalizedByteCode NormalizedOpCode + { + get + { + return normopcode; + } + } + + internal int Arg1 + { + get + { + return arg1; + } + } + + internal int TargetIndex + { + get + { + return arg1; + } + set + { + arg1 = value; + } + } + + internal int Arg2 + { + get + { + return arg2; + } + } + + internal int NormalizedArg1 + { + get + { + return arg1; + } + } + + internal int DefaultTarget + { + get + { + return arg1; + } + set + { + arg1 = value; + } + } + + internal int SwitchEntryCount + { + get + { + return switch_entries.Length; + } + } + + internal int GetSwitchValue(int i) + { + return switch_entries[i].value; + } + + internal int GetSwitchTargetIndex(int i) + { + return switch_entries[i].target; + } + + internal void SetSwitchTargets(int[] targets) + { + SwitchEntry[] newEntries = (SwitchEntry[])switch_entries.Clone(); + for (int i = 0; i < newEntries.Length; i++) + { + newEntries[i].target = targets[i]; + } + switch_entries = newEntries; + } + } + + internal struct LineNumberTableEntry + { + internal ushort start_pc; + internal ushort line_number; + } + + internal struct LocalVariableTableEntry + { + internal ushort start_pc; + internal ushort length; + internal string name; + internal string descriptor; + internal ushort index; + } + } + + internal Field GetField(string name, string sig) + { + for (int i = 0; i < fields.Length; i++) + { + if (fields[i].Name == name && fields[i].Signature == sig) + { + return fields[i]; + } + } + return null; + } + + private void RemoveAssertionInit(Method m) + { + /* We match the following code sequence: + * 0 ldc + * 2 invokevirtual + * 5 ifne 12 + * 8 iconst_1 + * 9 goto 13 + * 12 iconst_0 + * 13 putstatic boolean > + */ + ConstantPoolItemFieldref fieldref; + Field field; + if (m.Instructions[0].NormalizedOpCode == NormalizedByteCode.__ldc && SafeIsConstantPoolClass(m.Instructions[0].Arg1) + && m.Instructions[1].NormalizedOpCode == NormalizedByteCode.__invokevirtual && IsDesiredAssertionStatusMethodref(m.Instructions[1].Arg1) + && m.Instructions[2].NormalizedOpCode == NormalizedByteCode.__ifne && m.Instructions[2].TargetIndex == 5 + && m.Instructions[3].NormalizedOpCode == NormalizedByteCode.__iconst && m.Instructions[3].Arg1 == 1 + && m.Instructions[4].NormalizedOpCode == NormalizedByteCode.__goto && m.Instructions[4].TargetIndex == 6 + && m.Instructions[5].NormalizedOpCode == NormalizedByteCode.__iconst && m.Instructions[5].Arg1 == 0 + && m.Instructions[6].NormalizedOpCode == NormalizedByteCode.__putstatic && (fieldref = SafeGetFieldref(m.Instructions[6].Arg1)) != null + && fieldref.Class == Name && fieldref.Signature == "Z" + && (field = GetField(fieldref.Name, fieldref.Signature)) != null + && field.IsStatic && field.IsFinal + && !HasBranchIntoRegion(m.Instructions, 7, m.Instructions.Length, 0, 7) + && !HasStaticFieldWrite(m.Instructions, 7, m.Instructions.Length, field) + && !HasExceptionHandlerInRegion(m.ExceptionTable, 0, 7)) + { + field.PatchConstantValue(true); + m.Instructions[0].PatchOpCode(NormalizedByteCode.__goto, 7); + flags |= FLAG_HAS_ASSERTIONS; + } + } + + private bool IsDesiredAssertionStatusMethodref(int cpi) + { + ConstantPoolItemMethodref method = SafeGetMethodref(cpi) as ConstantPoolItemMethodref; + return method != null + && method.Class == "java.lang.Class" + && method.Name == "desiredAssertionStatus" + && method.Signature == "()Z"; + } + + private static bool HasBranchIntoRegion(Method.Instruction[] instructions, int checkStart, int checkEnd, int regionStart, int regionEnd) + { + for (int i = checkStart; i < checkEnd; i++) + { + switch (instructions[i].NormalizedOpCode) + { + case NormalizedByteCode.__ifeq: + case NormalizedByteCode.__ifne: + case NormalizedByteCode.__iflt: + case NormalizedByteCode.__ifge: + case NormalizedByteCode.__ifgt: + case NormalizedByteCode.__ifle: + case NormalizedByteCode.__if_icmpeq: + case NormalizedByteCode.__if_icmpne: + case NormalizedByteCode.__if_icmplt: + case NormalizedByteCode.__if_icmpge: + case NormalizedByteCode.__if_icmpgt: + case NormalizedByteCode.__if_icmple: + case NormalizedByteCode.__if_acmpeq: + case NormalizedByteCode.__if_acmpne: + case NormalizedByteCode.__ifnull: + case NormalizedByteCode.__ifnonnull: + case NormalizedByteCode.__goto: + case NormalizedByteCode.__jsr: + if (instructions[i].TargetIndex > regionStart && instructions[i].TargetIndex < regionEnd) + { + return true; + } + break; + case NormalizedByteCode.__tableswitch: + case NormalizedByteCode.__lookupswitch: + if (instructions[i].DefaultTarget > regionStart && instructions[i].DefaultTarget < regionEnd) + { + return true; + } + for (int j = 0; j < instructions[i].SwitchEntryCount; j++) + { + if (instructions[i].GetSwitchTargetIndex(j) > regionStart && instructions[i].GetSwitchTargetIndex(j) < regionEnd) + { + return true; + } + } + break; + } + } + return false; + } + + private bool HasStaticFieldWrite(Method.Instruction[] instructions, int checkStart, int checkEnd, Field field) + { + for (int i = checkStart; i < checkEnd; i++) + { + if (instructions[i].NormalizedOpCode == NormalizedByteCode.__putstatic) + { + ConstantPoolItemFieldref fieldref = SafeGetFieldref(instructions[i].Arg1); + if (fieldref != null && fieldref.Class == Name && fieldref.Name == field.Name && fieldref.Signature == field.Signature) + { + return true; + } + } + } + return false; + } + + private static bool HasExceptionHandlerInRegion(Method.ExceptionTableEntry[] entries, int regionStart, int regionEnd) + { + for (int i = 0; i < entries.Length; i++) + { + if (entries[i].handlerIndex > regionStart && entries[i].handlerIndex < regionEnd) + { + return true; + } + } + return false; + } + } +} diff --git a/runtime/ClassLoaderWrapper.cs b/runtime/ClassLoaderWrapper.cs new file mode 100644 index 0000000..d04d05d --- /dev/null +++ b/runtime/ClassLoaderWrapper.cs @@ -0,0 +1,1652 @@ +/* + Copyright (C) 2002-2015 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +#if STATIC_COMPILER || STUB_GENERATOR +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; +using ProtectionDomain = System.Object; +#else +using System.Reflection; +using System.Reflection.Emit; +using ProtectionDomain = java.security.ProtectionDomain; +#endif +using System.IO; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; +using System.Runtime.CompilerServices; +using IKVM.Attributes; + +namespace IKVM.Internal +{ + [Flags] + enum CodeGenOptions + { + None = 0, + Debug = 1, + NoStackTraceInfo = 2, + StrictFinalFieldSemantics = 4, + NoJNI = 8, + RemoveAsserts = 16, + NoAutomagicSerialization = 32, + DisableDynamicBinding = 64, + NoRefEmitHelpers = 128, + RemoveUnusedFields = 256, + } + + [Flags] + enum LoadMode + { + // These are the modes that should be used + Find = ReturnNull, + LoadOrNull = Load | ReturnNull, + LoadOrThrow = Load | ThrowClassNotFound, + Link = Load | ReturnUnloadable | SuppressExceptions, + + // call into Java class loader + Load = 0x0001, + + // return value + DontReturnUnloadable = 0x0002, // This is used with a bitwise OR to disable returning unloadable + ReturnUnloadable = 0x0004, + ReturnNull = 0x0004 | DontReturnUnloadable, + ThrowClassNotFound = 0x0008 | DontReturnUnloadable, + MaskReturn = ReturnUnloadable | ReturnNull | ThrowClassNotFound, + + // exceptions (not ClassNotFoundException) + SuppressExceptions = 0x0010, + + // warnings + WarnClassNotFound = 0x0020, + } + +#if !STUB_GENERATOR + abstract class TypeWrapperFactory + { + internal abstract ModuleBuilder ModuleBuilder { get; } + internal abstract TypeWrapper DefineClassImpl(Dictionary types, TypeWrapper host, ClassFile f, ClassLoaderWrapper classLoader, ProtectionDomain protectionDomain); + internal abstract bool ReserveName(string name); + internal abstract string AllocMangledName(DynamicTypeWrapper tw); + internal abstract Type DefineUnloadable(string name); + internal abstract Type DefineDelegate(int parameterCount, bool returnVoid); + internal abstract bool HasInternalAccess { get; } +#if CLASSGC + internal abstract void AddInternalsVisibleTo(Assembly friend); +#endif + } +#endif // !STUB_GENERATOR + + class ClassLoaderWrapper + { + private static readonly object wrapperLock = new object(); + private static readonly Dictionary globalTypeToTypeWrapper = new Dictionary(); +#if STATIC_COMPILER || STUB_GENERATOR + private static ClassLoaderWrapper bootstrapClassLoader; +#else + private static AssemblyClassLoader bootstrapClassLoader; +#endif + private static List genericClassLoaders; +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + protected java.lang.ClassLoader javaClassLoader; +#endif +#if !STUB_GENERATOR + private TypeWrapperFactory factory; +#endif // !STUB_GENERATOR + private readonly Dictionary types = new Dictionary(); + private readonly Dictionary defineClassInProgress = new Dictionary(); + private List nativeLibraries; + private readonly CodeGenOptions codegenoptions; +#if CLASSGC + private Dictionary typeToTypeWrapper; + private static ConditionalWeakTable dynamicAssemblies; +#endif + private static readonly Dictionary remappedTypes = new Dictionary(); + +#if STATIC_COMPILER || STUB_GENERATOR + // HACK this is used by the ahead-of-time compiler to overrule the bootstrap classloader + // when we're compiling the core class libraries and by ikvmstub with the -bootstrap option + internal static void SetBootstrapClassLoader(ClassLoaderWrapper bootstrapClassLoader) + { + Debug.Assert(ClassLoaderWrapper.bootstrapClassLoader == null); + + ClassLoaderWrapper.bootstrapClassLoader = bootstrapClassLoader; + } +#endif + + static ClassLoaderWrapper() + { + globalTypeToTypeWrapper[PrimitiveTypeWrapper.BOOLEAN.TypeAsTBD] = PrimitiveTypeWrapper.BOOLEAN; + globalTypeToTypeWrapper[PrimitiveTypeWrapper.BYTE.TypeAsTBD] = PrimitiveTypeWrapper.BYTE; + globalTypeToTypeWrapper[PrimitiveTypeWrapper.CHAR.TypeAsTBD] = PrimitiveTypeWrapper.CHAR; + globalTypeToTypeWrapper[PrimitiveTypeWrapper.DOUBLE.TypeAsTBD] = PrimitiveTypeWrapper.DOUBLE; + globalTypeToTypeWrapper[PrimitiveTypeWrapper.FLOAT.TypeAsTBD] = PrimitiveTypeWrapper.FLOAT; + globalTypeToTypeWrapper[PrimitiveTypeWrapper.INT.TypeAsTBD] = PrimitiveTypeWrapper.INT; + globalTypeToTypeWrapper[PrimitiveTypeWrapper.LONG.TypeAsTBD] = PrimitiveTypeWrapper.LONG; + globalTypeToTypeWrapper[PrimitiveTypeWrapper.SHORT.TypeAsTBD] = PrimitiveTypeWrapper.SHORT; + globalTypeToTypeWrapper[PrimitiveTypeWrapper.VOID.TypeAsTBD] = PrimitiveTypeWrapper.VOID; + LoadRemappedTypes(); + } + + internal static void LoadRemappedTypes() + { + // if we're compiling the core, coreAssembly will be null + Assembly coreAssembly = JVM.CoreAssembly; + if(coreAssembly != null && remappedTypes.Count ==0) + { + RemappedClassAttribute[] remapped = AttributeHelper.GetRemappedClasses(coreAssembly); + if(remapped.Length > 0) + { + foreach(RemappedClassAttribute r in remapped) + { + remappedTypes.Add(r.RemappedType, r.Name); + } + } + else + { +#if STATIC_COMPILER + throw new FatalCompilerErrorException(Message.CoreClassesMissing); +#else + JVM.CriticalFailure("Failed to find core classes in core library", null); +#endif + } + } + } + + internal ClassLoaderWrapper(CodeGenOptions codegenoptions, object javaClassLoader) + { + this.codegenoptions = codegenoptions; +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + this.javaClassLoader = (java.lang.ClassLoader)javaClassLoader; +#endif + } + + internal static bool IsRemappedType(Type type) + { + return remappedTypes.ContainsKey(type); + } + +#if STATIC_COMPILER || STUB_GENERATOR + internal void SetRemappedType(Type type, TypeWrapper tw) + { + lock(types) + { + types.Add(tw.Name, tw); + } + lock(globalTypeToTypeWrapper) + { + globalTypeToTypeWrapper.Add(type, tw); + } + remappedTypes.Add(type, tw.Name); + } +#endif + + // return the TypeWrapper if it is already loaded, this exists for DynamicTypeWrapper.SetupGhosts + // and implements ClassLoader.findLoadedClass() + internal TypeWrapper FindLoadedClass(string name) + { + if (name.Length > 1 && name[0] == '[') + { + return FindOrLoadArrayClass(name, LoadMode.Find); + } + TypeWrapper tw; + lock (types) + { + types.TryGetValue(name, out tw); + } + return tw ?? FindLoadedClassLazy(name); + } + + protected virtual TypeWrapper FindLoadedClassLazy(string name) + { + return null; + } + + internal TypeWrapper RegisterInitiatingLoader(TypeWrapper tw) + { + Debug.Assert(tw != null); + Debug.Assert(!tw.IsUnloadable); + Debug.Assert(!tw.IsPrimitive); + + try + { + // critical code in the finally block to avoid Thread.Abort interrupting the thread + } + finally + { + tw = RegisterInitiatingLoaderCritical(tw); + } + return tw; + } + + private TypeWrapper RegisterInitiatingLoaderCritical(TypeWrapper tw) + { + lock(types) + { + TypeWrapper existing; + types.TryGetValue(tw.Name, out existing); + if(existing != tw) + { + if(existing != null) + { + // another thread beat us to it, discard the new TypeWrapper and + // return the previous one + return existing; + } + // NOTE if types.ContainsKey(tw.Name) is true (i.e. the value is null), + // we currently have a DefineClass in progress on another thread and we've + // beaten that thread to the punch by loading the class from a parent class + // loader instead. This is ok as DefineClass will throw a LinkageError when + // it is done. + types[tw.Name] = tw; + } + } + return tw; + } + + internal bool EmitDebugInfo + { + get + { + return (codegenoptions & CodeGenOptions.Debug) != 0; + } + } + + internal bool EmitStackTraceInfo + { + get + { + // NOTE we're negating the flag here! + return (codegenoptions & CodeGenOptions.NoStackTraceInfo) == 0; + } + } + + internal bool StrictFinalFieldSemantics + { + get + { + return (codegenoptions & CodeGenOptions.StrictFinalFieldSemantics) != 0; + } + } + + internal bool NoJNI + { + get + { + return (codegenoptions & CodeGenOptions.NoJNI) != 0; + } + } + + internal bool RemoveAsserts + { + get + { + return (codegenoptions & CodeGenOptions.RemoveAsserts) != 0; + } + } + + internal bool NoAutomagicSerialization + { + get + { + return (codegenoptions & CodeGenOptions.NoAutomagicSerialization) != 0; + } + } + + internal bool DisableDynamicBinding + { + get + { + return (codegenoptions & CodeGenOptions.DisableDynamicBinding) != 0; + } + } + + internal bool EmitNoRefEmitHelpers + { + get + { + return (codegenoptions & CodeGenOptions.NoRefEmitHelpers) != 0; + } + } + + internal bool RemoveUnusedFields + { + get + { + return (codegenoptions & CodeGenOptions.RemoveUnusedFields) != 0; + } + } + + internal bool WorkaroundAbstractMethodWidening + { + get + { + // pre-Roslyn C# compiler doesn't like widening access to abstract methods + return true; + } + } + + internal bool WorkaroundInterfaceFields + { + get + { + // pre-Roslyn C# compiler doesn't allow access to interface fields + return true; + } + } + + internal bool WorkaroundInterfacePrivateMethods + { + get + { + // pre-Roslyn C# compiler doesn't like interfaces that have non-public methods + return true; + } + } + + internal bool WorkaroundInterfaceStaticMethods + { + get + { + // pre-Roslyn C# compiler doesn't allow access to interface static methods + return true; + } + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal bool RelaxedClassNameValidation + { + get + { +#if FIRST_PASS + return true; +#else + return JVM.relaxedVerification && (javaClassLoader == null || java.lang.ClassLoader.isTrustedLoader(javaClassLoader)); +#endif + } + } +#endif // !STATIC_COMPILER && !STUB_GENERATOR + + protected virtual void CheckProhibitedPackage(string className) + { + if (className.StartsWith("java.", StringComparison.Ordinal)) + { + throw new JavaSecurityException("Prohibited package name: " + className.Substring(0, className.LastIndexOf('.'))); + } + } + +#if !STUB_GENERATOR + internal TypeWrapper DefineClass(ClassFile f, ProtectionDomain protectionDomain) + { +#if !STATIC_COMPILER + string dotnetAssembly = f.IKVMAssemblyAttribute; + if(dotnetAssembly != null) + { + // It's a stub class generated by ikvmstub (or generated by the runtime when getResource was + // called on a statically compiled class). + ClassLoaderWrapper loader; + try + { + loader = ClassLoaderWrapper.GetAssemblyClassLoaderByName(dotnetAssembly); + } + catch(Exception x) + { + // TODO don't catch all exceptions here + throw new NoClassDefFoundError(f.Name + " (" + x.Message + ")"); + } + TypeWrapper tw = loader.LoadClassByDottedNameFast(f.Name); + if(tw == null) + { + throw new NoClassDefFoundError(f.Name + " (type not found in " + dotnetAssembly + ")"); + } + return RegisterInitiatingLoader(tw); + } +#endif + CheckProhibitedPackage(f.Name); + // check if the class already exists if we're an AssemblyClassLoader + if(FindLoadedClassLazy(f.Name) != null) + { + throw new LinkageError("duplicate class definition: " + f.Name); + } + TypeWrapper def; + try + { + // critical code in the finally block to avoid Thread.Abort interrupting the thread + } + finally + { + def = DefineClassCritical(f, protectionDomain); + } + return def; + } + + private TypeWrapper DefineClassCritical(ClassFile f, ProtectionDomain protectionDomain) + { + lock(types) + { + if(types.ContainsKey(f.Name)) + { + throw new LinkageError("duplicate class definition: " + f.Name); + } + // mark the type as "loading in progress", so that we can detect circular dependencies. + types.Add(f.Name, null); + defineClassInProgress.Add(f.Name, Thread.CurrentThread); + } + try + { + return GetTypeWrapperFactory().DefineClassImpl(types, null, f, this, protectionDomain); + } + finally + { + lock(types) + { + if(types[f.Name] == null) + { + // if loading the class fails, we remove the indicator that we're busy loading the class, + // because otherwise we get a ClassCircularityError if we try to load the class again. + types.Remove(f.Name); + } + defineClassInProgress.Remove(f.Name); + Monitor.PulseAll(types); + } + } + } + + internal TypeWrapperFactory GetTypeWrapperFactory() + { + if(factory == null) + { + lock(this) + { + try + { + // critical code in the finally block to avoid Thread.Abort interrupting the thread + } + finally + { + if(factory == null) + { +#if CLASSGC + if(dynamicAssemblies == null) + { + Interlocked.CompareExchange(ref dynamicAssemblies, new ConditionalWeakTable(), null); + } + typeToTypeWrapper = new Dictionary(); + DynamicClassLoader instance = DynamicClassLoader.Get(this); + dynamicAssemblies.Add(instance.ModuleBuilder.Assembly.ManifestModule.Assembly, this); + this.factory = instance; +#else + factory = DynamicClassLoader.Get(this); +#endif + } + } + } + } + return factory; + } +#endif // !STUB_GENERATOR + + internal TypeWrapper LoadClassByDottedName(string name) + { + return LoadClass(name, LoadMode.LoadOrThrow); + } + + internal TypeWrapper LoadClassByDottedNameFast(string name) + { + return LoadClass(name, LoadMode.LoadOrNull); + } + + internal TypeWrapper LoadClass(string name, LoadMode mode) + { + Profiler.Enter("LoadClass"); + try + { + TypeWrapper tw = LoadRegisteredOrPendingClass(name); + if (tw != null) + { + return tw; + } + if (name.Length > 1 && name[0] == '[') + { + tw = FindOrLoadArrayClass(name, mode); + } + else + { + tw = LoadClassImpl(name, mode); + } + if (tw != null) + { + return RegisterInitiatingLoader(tw); + } +#if STATIC_COMPILER + if (!(name.Length > 1 && name[0] == '[') && ((mode & LoadMode.WarnClassNotFound) != 0) || WarningLevelHigh) + { + IssueMessage(Message.ClassNotFound, name); + } +#else + if (!(name.Length > 1 && name[0] == '[')) + { + Tracer.Error(Tracer.ClassLoading, "Class not found: {0}", name); + } +#endif + switch (mode & LoadMode.MaskReturn) + { + case LoadMode.ReturnNull: + return null; + case LoadMode.ReturnUnloadable: + return new UnloadableTypeWrapper(name); + case LoadMode.ThrowClassNotFound: + throw new ClassNotFoundException(name); + default: + throw new InvalidOperationException(); + } + } + finally + { + Profiler.Leave("LoadClass"); + } + } + + private TypeWrapper LoadRegisteredOrPendingClass(string name) + { + TypeWrapper tw; + lock (types) + { + if (types.TryGetValue(name, out tw) && tw == null) + { + Thread defineThread; + if (defineClassInProgress.TryGetValue(name, out defineThread)) + { + if (Thread.CurrentThread == defineThread) + { + throw new ClassCircularityError(name); + } + // the requested class is currently being defined by another thread, + // so we have to wait on that + while (defineClassInProgress.ContainsKey(name)) + { + Monitor.Wait(types); + } + // the defineClass may have failed, so we need to use TryGetValue + types.TryGetValue(name, out tw); + } + } + } + return tw; + } + + private TypeWrapper FindOrLoadArrayClass(string name, LoadMode mode) + { + int dims = 1; + while(name[dims] == '[') + { + dims++; + if(dims == name.Length) + { + // malformed class name + return null; + } + } + if(name[dims] == 'L') + { + if(!name.EndsWith(";") || name.Length <= dims + 2 || name[dims + 1] == '[') + { + // malformed class name + return null; + } + string elemClass = name.Substring(dims + 1, name.Length - dims - 2); + // NOTE it's important that we're registered as the initiating loader + // for the element type here + TypeWrapper type = LoadClass(elemClass, mode | LoadMode.DontReturnUnloadable); + if(type != null) + { + type = CreateArrayType(name, type, dims); + } + return type; + } + if(name.Length != dims + 1) + { + // malformed class name + return null; + } + switch(name[dims]) + { + case 'B': + return CreateArrayType(name, PrimitiveTypeWrapper.BYTE, dims); + case 'C': + return CreateArrayType(name, PrimitiveTypeWrapper.CHAR, dims); + case 'D': + return CreateArrayType(name, PrimitiveTypeWrapper.DOUBLE, dims); + case 'F': + return CreateArrayType(name, PrimitiveTypeWrapper.FLOAT, dims); + case 'I': + return CreateArrayType(name, PrimitiveTypeWrapper.INT, dims); + case 'J': + return CreateArrayType(name, PrimitiveTypeWrapper.LONG, dims); + case 'S': + return CreateArrayType(name, PrimitiveTypeWrapper.SHORT, dims); + case 'Z': + return CreateArrayType(name, PrimitiveTypeWrapper.BOOLEAN, dims); + default: + return null; + } + } + + internal TypeWrapper FindOrLoadGenericClass(string name, LoadMode mode) + { + // we don't want to expose any failures to load any of the component types + mode = (mode & LoadMode.MaskReturn) | LoadMode.ReturnNull; + + // we need to handle delegate methods here (for generic delegates) + // (note that other types with manufactured inner classes such as Attribute and Enum can't be generic) + if (name.EndsWith(DotNetTypeWrapper.DelegateInterfaceSuffix)) + { + TypeWrapper outer = FindOrLoadGenericClass(name.Substring(0, name.Length - DotNetTypeWrapper.DelegateInterfaceSuffix.Length), mode); + if (outer != null && outer.IsFakeTypeContainer) + { + foreach (TypeWrapper tw in outer.InnerClasses) + { + if (tw.Name == name) + { + return tw; + } + } + } + } + // generic class name grammar: + // + // mangled(open_generic_type_name) "_$$$_" M(parameter_class_name) ( "_$$_" M(parameter_class_name) )* "_$$$$_" + // + // mangled() is the normal name mangling algorithm + // M() is a replacement of "__" with "$$005F$$005F" followed by a replace of "." with "__" + // + int pos = name.IndexOf("_$$$_"); + if(pos <= 0 || !name.EndsWith("_$$$$_")) + { + return null; + } + TypeWrapper def = LoadClass(name.Substring(0, pos), mode); + if (def == null || !def.TypeAsTBD.IsGenericTypeDefinition) + { + return null; + } + Type type = def.TypeAsTBD; + List typeParamNames = new List(); + pos += 5; + int start = pos; + int nest = 0; + for(;;) + { + pos = name.IndexOf("_$$", pos); + if(pos == -1) + { + return null; + } + if(name.IndexOf("_$$_", pos, 4) == pos) + { + if(nest == 0) + { + typeParamNames.Add(name.Substring(start, pos - start)); + start = pos + 4; + } + pos += 4; + } + else if(name.IndexOf("_$$$_", pos, 5) == pos) + { + nest++; + pos += 5; + } + else if(name.IndexOf("_$$$$_", pos, 6) == pos) + { + if(nest == 0) + { + if(pos + 6 != name.Length) + { + return null; + } + typeParamNames.Add(name.Substring(start, pos - start)); + break; + } + nest--; + pos += 6; + } + else + { + pos += 3; + } + } + Type[] typeArguments = new Type[typeParamNames.Count]; + for(int i = 0; i < typeArguments.Length; i++) + { + string s = (string)typeParamNames[i]; + // only do the unmangling for non-generic types (because we don't want to convert + // the double underscores in two adjacent _$$$_ or _$$$$_ markers) + if(s.IndexOf("_$$$_") == -1) + { + s = s.Replace("__", "."); + s = s.Replace("$$005F$$005F", "__"); + } + int dims = 0; + while(s.Length > dims && s[dims] == 'A') + { + dims++; + } + if(s.Length == dims) + { + return null; + } + TypeWrapper tw; + switch(s[dims]) + { + case 'L': + tw = LoadClass(s.Substring(dims + 1), mode); + if(tw == null) + { + return null; + } + tw.Finish(); + break; + case 'Z': + tw = PrimitiveTypeWrapper.BOOLEAN; + break; + case 'B': + tw = PrimitiveTypeWrapper.BYTE; + break; + case 'S': + tw = PrimitiveTypeWrapper.SHORT; + break; + case 'C': + tw = PrimitiveTypeWrapper.CHAR; + break; + case 'I': + tw = PrimitiveTypeWrapper.INT; + break; + case 'F': + tw = PrimitiveTypeWrapper.FLOAT; + break; + case 'J': + tw = PrimitiveTypeWrapper.LONG; + break; + case 'D': + tw = PrimitiveTypeWrapper.DOUBLE; + break; + default: + return null; + } + if(dims > 0) + { + tw = tw.MakeArrayType(dims); + } + typeArguments[i] = tw.TypeAsSignatureType; + } + try + { + type = type.MakeGenericType(typeArguments); + } + catch(ArgumentException) + { + // one of the typeArguments failed to meet the constraints + return null; + } + TypeWrapper wrapper = GetWrapperFromType(type); + if(wrapper != null && wrapper.Name != name) + { + // the name specified was not in canonical form + return null; + } + return wrapper; + } + + protected virtual TypeWrapper LoadClassImpl(string name, LoadMode mode) + { + TypeWrapper tw = FindOrLoadGenericClass(name, mode); + if(tw != null) + { + return tw; + } +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + if((mode & LoadMode.Load) == 0) + { + return null; + } + Profiler.Enter("ClassLoader.loadClass"); + try + { + java.lang.Class c = GetJavaClassLoader().loadClassInternal(name); + if(c == null) + { + return null; + } + TypeWrapper type = TypeWrapper.FromClass(c); + if(type.Name != name) + { + // the class loader is trying to trick us + return null; + } + return type; + } + catch(java.lang.ClassNotFoundException x) + { + if((mode & LoadMode.MaskReturn) == LoadMode.ThrowClassNotFound) + { + throw new ClassLoadingException(ikvm.runtime.Util.mapException(x), name); + } + return null; + } + catch(java.lang.ThreadDeath) + { + throw; + } + catch(Exception x) + { + if((mode & LoadMode.SuppressExceptions) == 0) + { + throw new ClassLoadingException(ikvm.runtime.Util.mapException(x), name); + } + if(Tracer.ClassLoading.TraceError) + { + java.lang.ClassLoader cl = GetJavaClassLoader(); + if(cl != null) + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + string sep = ""; + while(cl != null) + { + sb.Append(sep).Append(cl); + sep = " -> "; + cl = cl.getParent(); + } + Tracer.Error(Tracer.ClassLoading, "ClassLoader chain: {0}", sb); + } + Exception m = ikvm.runtime.Util.mapException(x); + Tracer.Error(Tracer.ClassLoading, m.ToString() + Environment.NewLine + m.StackTrace); + } + return null; + } + finally + { + Profiler.Leave("ClassLoader.loadClass"); + } +#else + return null; +#endif + } + + private static TypeWrapper CreateArrayType(string name, TypeWrapper elementTypeWrapper, int dims) + { + Debug.Assert(new String('[', dims) + elementTypeWrapper.SigName == name); + Debug.Assert(!elementTypeWrapper.IsUnloadable && !elementTypeWrapper.IsVerifierType && !elementTypeWrapper.IsArray); + Debug.Assert(dims >= 1); + return elementTypeWrapper.GetClassLoader().RegisterInitiatingLoader(new ArrayTypeWrapper(elementTypeWrapper, name)); + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal virtual java.lang.ClassLoader GetJavaClassLoader() + { +#if FIRST_PASS + return null; +#else + return javaClassLoader; +#endif + } +#endif + + // NOTE this exposes potentially unfinished types + internal Type[] ArgTypeListFromSig(string sig) + { + if(sig[1] == ')') + { + return Type.EmptyTypes; + } + TypeWrapper[] wrappers = ArgTypeWrapperListFromSig(sig, LoadMode.LoadOrThrow); + Type[] types = new Type[wrappers.Length]; + for(int i = 0; i < wrappers.Length; i++) + { + types[i] = wrappers[i].TypeAsSignatureType; + } + return types; + } + + // NOTE: this will ignore anything following the sig marker (so that it can be used to decode method signatures) + private TypeWrapper SigDecoderWrapper(ref int index, string sig, LoadMode mode) + { + switch(sig[index++]) + { + case 'B': + return PrimitiveTypeWrapper.BYTE; + case 'C': + return PrimitiveTypeWrapper.CHAR; + case 'D': + return PrimitiveTypeWrapper.DOUBLE; + case 'F': + return PrimitiveTypeWrapper.FLOAT; + case 'I': + return PrimitiveTypeWrapper.INT; + case 'J': + return PrimitiveTypeWrapper.LONG; + case 'L': + { + int pos = index; + index = sig.IndexOf(';', index) + 1; + return LoadClass(sig.Substring(pos, index - pos - 1), mode); + } + case 'S': + return PrimitiveTypeWrapper.SHORT; + case 'Z': + return PrimitiveTypeWrapper.BOOLEAN; + case 'V': + return PrimitiveTypeWrapper.VOID; + case '[': + { + // TODO this can be optimized + string array = "["; + while(sig[index] == '[') + { + index++; + array += "["; + } + switch(sig[index]) + { + case 'L': + { + int pos = index; + index = sig.IndexOf(';', index) + 1; + return LoadClass(array + sig.Substring(pos, index - pos), mode); + } + case 'B': + case 'C': + case 'D': + case 'F': + case 'I': + case 'J': + case 'S': + case 'Z': + return LoadClass(array + sig[index++], mode); + default: + throw new InvalidOperationException(sig.Substring(index)); + } + } + default: + throw new InvalidOperationException(sig.Substring(index)); + } + } + + internal TypeWrapper FieldTypeWrapperFromSig(string sig, LoadMode mode) + { + int index = 0; + return SigDecoderWrapper(ref index, sig, mode); + } + + internal TypeWrapper RetTypeWrapperFromSig(string sig, LoadMode mode) + { + int index = sig.IndexOf(')') + 1; + return SigDecoderWrapper(ref index, sig, mode); + } + + internal TypeWrapper[] ArgTypeWrapperListFromSig(string sig, LoadMode mode) + { + if(sig[1] == ')') + { + return TypeWrapper.EmptyArray; + } + List list = new List(); + for(int i = 1; sig[i] != ')';) + { + list.Add(SigDecoderWrapper(ref i, sig, mode)); + } + return list.ToArray(); + } + +#if STATIC_COMPILER || STUB_GENERATOR + internal static ClassLoaderWrapper GetBootstrapClassLoader() +#else + internal static AssemblyClassLoader GetBootstrapClassLoader() +#endif + { + lock(wrapperLock) + { + if(bootstrapClassLoader == null) + { + bootstrapClassLoader = new BootstrapClassLoader(); + } + return bootstrapClassLoader; + } + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal static ClassLoaderWrapper GetClassLoaderWrapper(java.lang.ClassLoader javaClassLoader) + { + if(javaClassLoader == null) + { + return GetBootstrapClassLoader(); + } + lock(wrapperLock) + { +#if FIRST_PASS + ClassLoaderWrapper wrapper = null; +#else + ClassLoaderWrapper wrapper = +#if __MonoCS__ + // MONOBUG the redundant cast to ClassLoaderWrapper is to workaround an mcs bug + (ClassLoaderWrapper)(object) +#endif + javaClassLoader.wrapper; +#endif + if(wrapper == null) + { + CodeGenOptions opt = CodeGenOptions.None; + if(JVM.EmitSymbols) + { + opt |= CodeGenOptions.Debug; + } +#if NET_4_0 + if (!AppDomain.CurrentDomain.IsFullyTrusted) + { + opt |= CodeGenOptions.NoAutomagicSerialization; + } +#endif + wrapper = new ClassLoaderWrapper(opt, javaClassLoader); + SetWrapperForClassLoader(javaClassLoader, wrapper); + } + return wrapper; + } + } +#endif + +#if CLASSGC + internal static ClassLoaderWrapper GetClassLoaderForDynamicJavaAssembly(Assembly asm) + { + ClassLoaderWrapper loader; + dynamicAssemblies.TryGetValue(asm, out loader); + return loader; + } +#endif // CLASSGC + + internal static TypeWrapper GetWrapperFromType(Type type) + { +#if STATIC_COMPILER + if (type.__ContainsMissingType) + { + return new UnloadableTypeWrapper(type); + } +#endif + //Tracer.Info(Tracer.Runtime, "GetWrapperFromType: {0}", type.AssemblyQualifiedName); +#if !STATIC_COMPILER + TypeWrapper.AssertFinished(type); +#endif + Debug.Assert(!type.IsPointer); + Debug.Assert(!type.IsByRef); + TypeWrapper wrapper; + lock(globalTypeToTypeWrapper) + { + globalTypeToTypeWrapper.TryGetValue(type, out wrapper); + } + if(wrapper != null) + { + return wrapper; + } +#if STUB_GENERATOR + if(type.__IsMissing || type.__ContainsMissingType) + { + wrapper = new UnloadableTypeWrapper("Missing/" + type.Assembly.FullName); + globalTypeToTypeWrapper.Add(type, wrapper); + return wrapper; + } +#endif + string remapped; + if(remappedTypes.TryGetValue(type, out remapped)) + { + wrapper = LoadClassCritical(remapped); + } + else if(ReflectUtil.IsVector(type)) + { + // it might be an array of a dynamically compiled Java type + int rank = 1; + Type elem = type.GetElementType(); + while(ReflectUtil.IsVector(elem)) + { + rank++; + elem = elem.GetElementType(); + } + wrapper = GetWrapperFromType(elem).MakeArrayType(rank); + } + else + { + Assembly asm = type.Assembly; +#if CLASSGC + ClassLoaderWrapper loader = null; + if(dynamicAssemblies != null && dynamicAssemblies.TryGetValue(asm, out loader)) + { + lock(loader.typeToTypeWrapper) + { + TypeWrapper tw; + if(loader.typeToTypeWrapper.TryGetValue(type, out tw)) + { + return tw; + } + // it must be an anonymous type then + Debug.Assert(AnonymousTypeWrapper.IsAnonymous(type)); + } + } +#endif +#if !STATIC_COMPILER && !STUB_GENERATOR + if(AnonymousTypeWrapper.IsAnonymous(type)) + { + Dictionary typeToTypeWrapper; +#if CLASSGC + typeToTypeWrapper = loader != null ? loader.typeToTypeWrapper : globalTypeToTypeWrapper; +#else + typeToTypeWrapper = globalTypeToTypeWrapper; +#endif + TypeWrapper tw = new AnonymousTypeWrapper(type); + lock(typeToTypeWrapper) + { + if(!typeToTypeWrapper.TryGetValue(type, out wrapper)) + { + typeToTypeWrapper.Add(type, wrapper = tw); + } + } + return wrapper; + } + if(ReflectUtil.IsReflectionOnly(type)) + { + // historically we've always returned null for types that don't have a corresponding TypeWrapper (or java.lang.Class) + return null; + } +#endif + // if the wrapper doesn't already exist, that must mean that the type + // is a .NET type (or a pre-compiled Java class), which means that it + // was "loaded" by an assembly classloader + wrapper = AssemblyClassLoader.FromAssembly(asm).GetWrapperFromAssemblyType(type); + } +#if CLASSGC + if(type.Assembly.IsDynamic) + { + // don't cache types in dynamic assemblies, because they might live in a RunAndCollect assembly + // TODO we also shouldn't cache generic type instances that have a GCable type parameter + return wrapper; + } +#endif + lock(globalTypeToTypeWrapper) + { + try + { + // critical code in the finally block to avoid Thread.Abort interrupting the thread + } + finally + { + globalTypeToTypeWrapper[type] = wrapper; + } + } + return wrapper; + } + + internal static ClassLoaderWrapper GetGenericClassLoader(TypeWrapper wrapper) + { + Type type = wrapper.TypeAsTBD; + Debug.Assert(type.IsGenericType); + Debug.Assert(!type.ContainsGenericParameters); + + List list = new List(); + list.Add(AssemblyClassLoader.FromAssembly(type.Assembly)); + foreach(Type arg in type.GetGenericArguments()) + { + ClassLoaderWrapper loader = GetWrapperFromType(arg).GetClassLoader(); + if(!list.Contains(loader) && loader != bootstrapClassLoader) + { + list.Add(loader); + } + } + ClassLoaderWrapper[] key = list.ToArray(); + ClassLoaderWrapper matchingLoader = GetGenericClassLoaderByKey(key); + matchingLoader.RegisterInitiatingLoader(wrapper); + return matchingLoader; + } + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + internal static object DoPrivileged(java.security.PrivilegedAction action) + { + return java.security.AccessController.doPrivileged(action, ikvm.@internal.CallerID.create(typeof(java.lang.ClassLoader).TypeHandle)); + } +#endif + + private static ClassLoaderWrapper GetGenericClassLoaderByKey(ClassLoaderWrapper[] key) + { + lock(wrapperLock) + { + if(genericClassLoaders == null) + { + genericClassLoaders = new List(); + } + foreach(GenericClassLoaderWrapper loader in genericClassLoaders) + { + if(loader.Matches(key)) + { + return loader; + } + } +#if STATIC_COMPILER || STUB_GENERATOR || FIRST_PASS + GenericClassLoaderWrapper newLoader = new GenericClassLoaderWrapper(key, null); +#else + java.lang.ClassLoader javaClassLoader = new ikvm.runtime.GenericClassLoader(); + GenericClassLoaderWrapper newLoader = new GenericClassLoaderWrapper(key, javaClassLoader); + SetWrapperForClassLoader(javaClassLoader, newLoader); +#endif + genericClassLoaders.Add(newLoader); + return newLoader; + } + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + protected internal static void SetWrapperForClassLoader(java.lang.ClassLoader javaClassLoader, ClassLoaderWrapper wrapper) + { +#if __MonoCS__ || FIRST_PASS + typeof(java.lang.ClassLoader).GetField("wrapper", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(javaClassLoader, wrapper); +#else + javaClassLoader.wrapper = wrapper; +#endif + } +#endif + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal static ClassLoaderWrapper GetGenericClassLoaderByName(string name) + { + Debug.Assert(name.StartsWith("[[") && name.EndsWith("]]")); + Stack> stack = new Stack>(); + List list = null; + for(int i = 0; i < name.Length; i++) + { + if(name[i] == '[') + { + if(name[i + 1] == '[') + { + stack.Push(list); + list = new List(); + if(name[i + 2] == '[') + { + i++; + } + } + else + { + int start = i + 1; + i = name.IndexOf(']', i); + list.Add(ClassLoaderWrapper.GetAssemblyClassLoaderByName(name.Substring(start, i - start))); + } + } + else if(name[i] == ']') + { + ClassLoaderWrapper loader = GetGenericClassLoaderByKey(list.ToArray()); + list = stack.Pop(); + if(list == null) + { + return loader; + } + list.Add(loader); + } + else + { + throw new InvalidOperationException(); + } + } + throw new InvalidOperationException(); + } + + internal static ClassLoaderWrapper GetAssemblyClassLoaderByName(string name) + { + if(name.StartsWith("[[")) + { + return GetGenericClassLoaderByName(name); + } + return AssemblyClassLoader.FromAssembly(Assembly.Load(name)); + } +#endif + + internal static int GetGenericClassLoaderId(ClassLoaderWrapper wrapper) + { + lock(wrapperLock) + { + return genericClassLoaders.IndexOf(wrapper as GenericClassLoaderWrapper); + } + } + + internal static ClassLoaderWrapper GetGenericClassLoaderById(int id) + { + lock(wrapperLock) + { + return genericClassLoaders[id]; + } + } + + internal void SetWrapperForType(Type type, TypeWrapper wrapper) + { +#if !STATIC_COMPILER + TypeWrapper.AssertFinished(type); +#endif + Dictionary dict; +#if CLASSGC + dict = typeToTypeWrapper ?? globalTypeToTypeWrapper; +#else + dict = globalTypeToTypeWrapper; +#endif + lock (dict) + { + try + { + // critical code in the finally block to avoid Thread.Abort interrupting the thread + } + finally + { + dict.Add(type, wrapper); + } + } + } + + internal static TypeWrapper LoadClassCritical(string name) + { +#if STATIC_COMPILER + TypeWrapper wrapper = GetBootstrapClassLoader().LoadClassByDottedNameFast(name); + if (wrapper == null) + { + throw new FatalCompilerErrorException(Message.CriticalClassNotFound, name); + } + return wrapper; +#else + try + { + return GetBootstrapClassLoader().LoadClassByDottedName(name); + } + catch(Exception x) + { + JVM.CriticalFailure("Loading of critical class failed", x); + return null; + } +#endif + } + + internal void RegisterNativeLibrary(IntPtr p) + { + lock(this) + { + try + { + // critical code in the finally block to avoid Thread.Abort interrupting the thread + } + finally + { + if(nativeLibraries == null) + { + nativeLibraries = new List(); + } + nativeLibraries.Add(p); + } + } + } + + internal void UnregisterNativeLibrary(IntPtr p) + { + lock(this) + { + try + { + // critical code in the finally block to avoid Thread.Abort interrupting the thread + } + finally + { + nativeLibraries.Remove(p); + } + } + } + + internal IntPtr[] GetNativeLibraries() + { + lock(this) + { + if(nativeLibraries == null) + { + return new IntPtr[0]; + } + return nativeLibraries.ToArray(); + } + } + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + public override string ToString() + { + object javaClassLoader = GetJavaClassLoader(); + if(javaClassLoader == null) + { + return "null"; + } + return String.Format("{0}@{1:X}", GetWrapperFromType(javaClassLoader.GetType()).Name, javaClassLoader.GetHashCode()); + } +#endif + + internal virtual bool InternalsVisibleToImpl(TypeWrapper wrapper, TypeWrapper friend) + { + Debug.Assert(wrapper.GetClassLoader() == this); + return this == friend.GetClassLoader(); + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + // this method is used by IKVM.Runtime.JNI + internal static ClassLoaderWrapper FromCallerID(ikvm.@internal.CallerID callerID) + { +#if FIRST_PASS + return null; +#else + return GetClassLoaderWrapper(callerID.getCallerClassLoader()); +#endif + } +#endif + +#if STATIC_COMPILER + internal virtual void IssueMessage(Message msgId, params string[] values) + { + // it's not ideal when we end up here (because it means we're emitting a warning that is not associated with a specific output target), + // but it happens when we're decoding something in a referenced assembly that either doesn't make sense or contains an unloadable type + StaticCompiler.IssueMessage(msgId, values); + } +#endif + + internal void CheckPackageAccess(TypeWrapper tw, ProtectionDomain pd) + { +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + if (javaClassLoader != null) + { + javaClassLoader.checkPackageAccess(tw.ClassObject, pd); + } +#endif + } + +#if !STUB_GENERATOR + internal ClassFileParseOptions ClassFileParseOptions + { + get + { +#if STATIC_COMPILER + ClassFileParseOptions cfp = ClassFileParseOptions.LocalVariableTable; + if (EmitStackTraceInfo) + { + cfp |= ClassFileParseOptions.LineNumberTable; + } + if (bootstrapClassLoader is CompilerClassLoader) + { + cfp |= ClassFileParseOptions.TrustedAnnotations; + } + if (RemoveAsserts) + { + cfp |= ClassFileParseOptions.RemoveAssertions; + } + return cfp; +#else + ClassFileParseOptions cfp = ClassFileParseOptions.LineNumberTable; + if (EmitDebugInfo) + { + cfp |= ClassFileParseOptions.LocalVariableTable; + } + if (RelaxedClassNameValidation) + { + cfp |= ClassFileParseOptions.RelaxedClassNameValidation; + } + if (this == bootstrapClassLoader) + { + cfp |= ClassFileParseOptions.TrustedAnnotations; + } + return cfp; +#endif + } + } +#endif + +#if STATIC_COMPILER + internal virtual bool WarningLevelHigh + { + get { return false; } + } + + internal virtual bool NoParameterReflection + { + get { return false; } + } +#endif + } + + sealed class GenericClassLoaderWrapper : ClassLoaderWrapper + { + private readonly ClassLoaderWrapper[] delegates; + + internal GenericClassLoaderWrapper(ClassLoaderWrapper[] delegates, object javaClassLoader) + : base(CodeGenOptions.None, javaClassLoader) + { + this.delegates = delegates; + } + + internal bool Matches(ClassLoaderWrapper[] key) + { + if(key.Length == delegates.Length) + { + for(int i = 0; i < key.Length; i++) + { + if(key[i] != delegates[i]) + { + return false; + } + } + return true; + } + return false; + } + + protected override TypeWrapper FindLoadedClassLazy(string name) + { + TypeWrapper tw1 = FindOrLoadGenericClass(name, LoadMode.Find); + if (tw1 != null) + { + return tw1; + } + foreach (ClassLoaderWrapper loader in delegates) + { + TypeWrapper tw = loader.FindLoadedClass(name); + if (tw != null && tw.GetClassLoader() == loader) + { + return tw; + } + } + return null; + } + + internal string GetName() + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + sb.Append('['); + foreach(ClassLoaderWrapper loader in delegates) + { + sb.Append('['); + GenericClassLoaderWrapper gcl = loader as GenericClassLoaderWrapper; + if(gcl != null) + { + sb.Append(gcl.GetName()); + } + else + { + sb.Append(((AssemblyClassLoader)loader).MainAssembly.FullName); + } + sb.Append(']'); + } + sb.Append(']'); + return sb.ToString(); + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal java.util.Enumeration GetResources(string name) + { +#if FIRST_PASS + return null; +#else + java.util.Vector v = new java.util.Vector(); + foreach (java.net.URL url in GetBootstrapClassLoader().GetResources(name)) + { + v.add(url); + } + if (name.EndsWith(".class", StringComparison.Ordinal) && name.IndexOf('.') == name.Length - 6) + { + TypeWrapper tw = FindLoadedClass(name.Substring(0, name.Length - 6).Replace('/', '.')); + if (tw != null && !tw.IsArray && !tw.IsDynamic) + { + ClassLoaderWrapper loader = tw.GetClassLoader(); + if (loader is GenericClassLoaderWrapper) + { + v.add(new java.net.URL("ikvmres", "gen", ClassLoaderWrapper.GetGenericClassLoaderId(loader), "/" + name)); + } + else if (loader is AssemblyClassLoader) + { + foreach (java.net.URL url in ((AssemblyClassLoader)loader).FindResources(name)) + { + v.add(url); + } + } + } + } + return v.elements(); +#endif + } + + internal java.net.URL FindResource(string name) + { +#if !FIRST_PASS + if (name.EndsWith(".class", StringComparison.Ordinal) && name.IndexOf('.') == name.Length - 6) + { + TypeWrapper tw = FindLoadedClass(name.Substring(0, name.Length - 6).Replace('/', '.')); + if (tw != null && tw.GetClassLoader() == this && !tw.IsArray && !tw.IsDynamic) + { + return new java.net.URL("ikvmres", "gen", ClassLoaderWrapper.GetGenericClassLoaderId(this), "/" + name); + } + } +#endif + return null; + } +#endif + } +} diff --git a/runtime/CodeEmitter.cs b/runtime/CodeEmitter.cs new file mode 100644 index 0000000..253de25 --- /dev/null +++ b/runtime/CodeEmitter.cs @@ -0,0 +1,3018 @@ +/* + Copyright (C) 2002-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +//#define LABELCHECK +#define CHECK_INVARIANTS +using System; +using System.Collections.Generic; +#if STATIC_COMPILER +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif +using System.Runtime.InteropServices; +using System.Diagnostics.SymbolStore; +using System.Diagnostics; + +namespace IKVM.Internal +{ + sealed class CodeEmitterLabel + { + internal readonly Label Label; + internal int Temp; + + internal CodeEmitterLabel(Label label) + { + this.Label = label; + } + } + + sealed class CodeEmitterLocal + { + private Type type; + private string name; + private LocalBuilder local; + + internal CodeEmitterLocal(Type type) + { + this.type = type; + } + + internal Type LocalType + { + get { return type; } + } + + internal void SetLocalSymInfo(string name) + { + this.name = name; + } + + internal int __LocalIndex + { + get { return local == null ? 0xFFFF : local.LocalIndex; } + } + + internal void Emit(ILGenerator ilgen, OpCode opcode) + { + if (local == null) + { + // it's a temporary local that is only allocated on-demand + local = ilgen.DeclareLocal(type); + } + ilgen.Emit(opcode, local); + } + + internal void Declare(ILGenerator ilgen) + { + local = ilgen.DeclareLocal(type); + if (name != null) + { + local.SetLocalSymInfo(name); + } + } + } + + sealed class CodeEmitter + { + private static readonly MethodInfo objectToString = Types.Object.GetMethod("ToString", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null); + private static readonly MethodInfo verboseCastFailure = JVM.SafeGetEnvironmentVariable("IKVM_VERBOSE_CAST") == null ? null : ByteCodeHelperMethods.VerboseCastFailure; + private static readonly MethodInfo monitorEnter = JVM.Import(typeof(System.Threading.Monitor)).GetMethod("Enter", BindingFlags.Public | BindingFlags.Static, null, new Type[] { Types.Object }, null); + private static readonly MethodInfo monitorExit = JVM.Import(typeof(System.Threading.Monitor)).GetMethod("Exit", BindingFlags.Public | BindingFlags.Static, null, new Type[] { Types.Object }, null); + private static readonly bool experimentalOptimizations = JVM.SafeGetEnvironmentVariable("IKVM_EXPERIMENTAL_OPTIMIZATIONS") != null; + private static MethodInfo memoryBarrier; + private ILGenerator ilgen_real; +#if !STATIC_COMPILER + private bool inFinally; + private Stack exceptionStack = new Stack(); +#endif + private IKVM.Attributes.LineNumberTableAttribute.LineNumberWriter linenums; + private CodeEmitterLocal[] tempLocals = new CodeEmitterLocal[32]; + private ISymbolDocumentWriter symbols; + private List code = new List(10); + private readonly Type declaringType; +#if LABELCHECK + private Dictionary labels = new Dictionary(); +#endif + + static CodeEmitter() + { + if (experimentalOptimizations) + { + Console.Error.WriteLine("IKVM.NET experimental optimizations enabled."); + } + } + + enum CodeType : short + { + Unreachable, + OpCode, + BeginScope, + EndScope, + DeclareLocal, + ReleaseTempLocal, + SequencePoint, + LineNumber, + Label, + BeginExceptionBlock, + BeginCatchBlock, + BeginFaultBlock, + BeginFinallyBlock, + EndExceptionBlock, + MemoryBarrier, + TailCallPrevention, + ClearStack, + MonitorEnter, + MonitorExit, + } + + enum CodeTypeFlags : short + { + None = 0, + EndFaultOrFinally = 1, + } + + struct OpCodeWrapper + { + internal readonly CodeType pseudo; + private readonly CodeTypeFlags flags; + internal readonly OpCode opcode; + private readonly object data; + + internal OpCodeWrapper(CodeType pseudo, object data) + { + this.pseudo = pseudo; + this.flags = CodeTypeFlags.None; + this.opcode = OpCodes.Nop; + this.data = data; + } + + internal OpCodeWrapper(CodeType pseudo, CodeTypeFlags flags) + { + this.pseudo = pseudo; + this.flags = flags; + this.opcode = OpCodes.Nop; + this.data = null; + } + + internal OpCodeWrapper(OpCode opcode, object data) + { + this.pseudo = CodeType.OpCode; + this.flags = CodeTypeFlags.None; + this.opcode = opcode; + this.data = data; + } + + internal bool Match(OpCodeWrapper other) + { + return other.pseudo == pseudo + && other.opcode == opcode + && (other.data == data || (data != null && data.Equals(other.data))); + } + + internal bool HasLabel + { + get { return data is CodeEmitterLabel; } + } + + internal CodeEmitterLabel Label + { + get { return (CodeEmitterLabel)data; } + } + + internal bool MatchLabel(OpCodeWrapper other) + { + return data == other.data; + } + + internal CodeEmitterLabel[] Labels + { + get { return (CodeEmitterLabel[])data; } + } + + internal bool HasLocal + { + get { return data is CodeEmitterLocal; } + } + + internal CodeEmitterLocal Local + { + get { return (CodeEmitterLocal)data; } + } + + internal bool MatchLocal(OpCodeWrapper other) + { + return data == other.data; + } + + internal bool HasValueByte + { + get { return data is byte; } + } + + internal byte ValueByte + { + get { return (byte)data; } + } + + internal short ValueInt16 + { + get { return (short)data; } + } + + internal int ValueInt32 + { + get { return (int)data; } + } + + internal long ValueInt64 + { + get { return (long)data; } + } + + internal Type Type + { + get { return (Type)data; } + } + + internal FieldInfo FieldInfo + { + get { return (FieldInfo)data; } + } + + internal MethodBase MethodBase + { + get { return (MethodBase)data; } + } + + internal int Size + { + get + { + switch (pseudo) + { + case CodeType.Unreachable: + case CodeType.BeginScope: + case CodeType.EndScope: + case CodeType.DeclareLocal: + case CodeType.ReleaseTempLocal: + case CodeType.LineNumber: + case CodeType.Label: + case CodeType.BeginExceptionBlock: + return 0; + case CodeType.SequencePoint: + return 1; + case CodeType.BeginCatchBlock: + case CodeType.BeginFaultBlock: + case CodeType.BeginFinallyBlock: + case CodeType.EndExceptionBlock: +#if STATIC_COMPILER + return 0; +#else + if ((flags & CodeTypeFlags.EndFaultOrFinally) != 0) + { + return 1 + 2; + } + return 5 + 2; +#endif + case CodeType.MemoryBarrier: + case CodeType.MonitorEnter: + case CodeType.MonitorExit: + return 5; + case CodeType.TailCallPrevention: + return 2; + case CodeType.ClearStack: + return 2; + case CodeType.OpCode: + if (data == null) + { + return opcode.Size; + } + else if (data is int) + { + return opcode.Size + 4;; + } + else if (data is long) + { + return opcode.Size + 8; + } + else if (data is MethodInfo) + { + return opcode.Size + 4; + } + else if (data is ConstructorInfo) + { + return opcode.Size + 4; + } + else if (data is FieldInfo) + { + return opcode.Size + 4; + } + else if (data is sbyte) + { + return opcode.Size + 1; + } + else if (data is byte) + { + return opcode.Size + 1; + } + else if (data is short) + { + return opcode.Size + 2; + } + else if (data is float) + { + return opcode.Size + 4; + } + else if (data is double) + { + return opcode.Size + 8; + } + else if (data is string) + { + return opcode.Size + 4; + } + else if (data is Type) + { + return opcode.Size + 4; + } + else if (data is CodeEmitterLocal) + { + int index = ((CodeEmitterLocal)data).__LocalIndex; + if(index < 4 && opcode.Value != OpCodes.Ldloca.Value && opcode.Value != OpCodes.Ldloca_S.Value) + { + return 1; + } + else if(index < 256) + { + return 2; + } + else + { + return 4; + } + } + else if (data is CodeEmitterLabel) + { + switch(opcode.OperandType) + { + case OperandType.InlineBrTarget: + return opcode.Size + 4; + case OperandType.ShortInlineBrTarget: + return opcode.Size + 1; + default: + throw new InvalidOperationException(); + } + } + else if (data is CodeEmitterLabel[]) + { + return 5 + ((CodeEmitterLabel[])data).Length * 4; + } + else if (data is CalliWrapper) + { + return 5; + } + else + { + throw new InvalidOperationException(); + } + default: + throw new InvalidOperationException(); + } + } + } + + internal void RealEmit(int ilOffset, CodeEmitter codeEmitter, ref int lineNumber) + { + if (pseudo == CodeType.OpCode) + { + if (lineNumber != -1) + { + if (codeEmitter.linenums == null) + { + codeEmitter.linenums = new IKVM.Attributes.LineNumberTableAttribute.LineNumberWriter(32); + } + codeEmitter.linenums.AddMapping(ilOffset, lineNumber); + lineNumber = -1; + } + codeEmitter.RealEmitOpCode(opcode, data); + } + else if (pseudo == CodeType.LineNumber) + { + lineNumber = (int)data; + } + else + { + codeEmitter.RealEmitPseudoOpCode(ilOffset, pseudo, data); + } + } + + public override string ToString() + { + return pseudo.ToString() + " " + data; + } + } + + sealed class CalliWrapper + { + internal readonly CallingConvention unmanagedCallConv; + internal readonly Type returnType; + internal readonly Type[] parameterTypes; + + internal CalliWrapper(CallingConvention unmanagedCallConv, Type returnType, Type[] parameterTypes) + { + this.unmanagedCallConv = unmanagedCallConv; + this.returnType = returnType; + this.parameterTypes = parameterTypes == null ? null : (Type[])parameterTypes.Clone(); + } + } + + internal static CodeEmitter Create(MethodBuilder mb) + { + return new CodeEmitter(mb.GetILGenerator(), mb.DeclaringType); + } + +#if !STATIC_COMPILER + internal static CodeEmitter Create(DynamicMethod dm) + { + return new CodeEmitter(dm.GetILGenerator(), null); + } +#endif + + private CodeEmitter(ILGenerator ilgen, Type declaringType) + { +#if STATIC_COMPILER + ilgen.__DisableExceptionBlockAssistance(); +#endif + this.ilgen_real = ilgen; + this.declaringType = declaringType; + } + + private void EmitPseudoOpCode(CodeType type, object data) + { + code.Add(new OpCodeWrapper(type, data)); + } + + private void EmitOpCode(OpCode opcode, object arg) + { + code.Add(new OpCodeWrapper(opcode, arg)); + } + + private void RealEmitPseudoOpCode(int ilOffset, CodeType type, object data) + { + switch (type) + { + case CodeType.Unreachable: + break; + case CodeType.BeginScope: + ilgen_real.BeginScope(); + break; + case CodeType.EndScope: + ilgen_real.EndScope(); + break; + case CodeType.DeclareLocal: + ((CodeEmitterLocal)data).Declare(ilgen_real); + break; + case CodeType.ReleaseTempLocal: + break; + case CodeType.SequencePoint: + ilgen_real.MarkSequencePoint(symbols, (int)data, 0, (int)data + 1, 0); + // we emit a nop to make sure we always have an instruction associated with the sequence point + ilgen_real.Emit(OpCodes.Nop); + break; + case CodeType.Label: + ilgen_real.MarkLabel(((CodeEmitterLabel)data).Label); + break; + case CodeType.BeginExceptionBlock: + ilgen_real.BeginExceptionBlock(); + break; + case CodeType.BeginCatchBlock: + ilgen_real.BeginCatchBlock((Type)data); + break; + case CodeType.BeginFaultBlock: + ilgen_real.BeginFaultBlock(); + break; + case CodeType.BeginFinallyBlock: + ilgen_real.BeginFinallyBlock(); + break; + case CodeType.EndExceptionBlock: + ilgen_real.EndExceptionBlock(); +#if !STATIC_COMPILER + // HACK to keep the verifier happy we need this bogus jump + // (because of the bogus Leave that Ref.Emit ends the try block with) + ilgen_real.Emit(OpCodes.Br_S, (sbyte)-2); +#endif + break; + case CodeType.MemoryBarrier: + if (memoryBarrier == null) + { + memoryBarrier = JVM.Import(typeof(System.Threading.Thread)).GetMethod("MemoryBarrier", Type.EmptyTypes); + } + ilgen_real.Emit(OpCodes.Call, memoryBarrier); + break; + case CodeType.MonitorEnter: + ilgen_real.Emit(OpCodes.Call, monitorEnter); + break; + case CodeType.MonitorExit: + ilgen_real.Emit(OpCodes.Call, monitorExit); + break; + case CodeType.TailCallPrevention: + ilgen_real.Emit(OpCodes.Ldnull); + ilgen_real.Emit(OpCodes.Pop); + break; + case CodeType.ClearStack: + ilgen_real.Emit(OpCodes.Leave_S, (byte)0); + break; + default: + throw new InvalidOperationException(); + } + } + + private void RealEmitOpCode(OpCode opcode, object arg) + { + if (arg == null) + { + ilgen_real.Emit(opcode); + } + else if (arg is int) + { + ilgen_real.Emit(opcode, (int)arg); + } + else if (arg is long) + { + ilgen_real.Emit(opcode, (long)arg); + } + else if (arg is MethodInfo) + { + ilgen_real.Emit(opcode, (MethodInfo)arg); + } + else if (arg is ConstructorInfo) + { + ilgen_real.Emit(opcode, (ConstructorInfo)arg); + } + else if (arg is FieldInfo) + { + ilgen_real.Emit(opcode, (FieldInfo)arg); + } + else if (arg is sbyte) + { + ilgen_real.Emit(opcode, (sbyte)arg); + } + else if (arg is byte) + { + ilgen_real.Emit(opcode, (byte)arg); + } + else if (arg is short) + { + ilgen_real.Emit(opcode, (short)arg); + } + else if (arg is float) + { + ilgen_real.Emit(opcode, (float)arg); + } + else if (arg is double) + { + ilgen_real.Emit(opcode, (double)arg); + } + else if (arg is string) + { + ilgen_real.Emit(opcode, (string)arg); + } + else if (arg is Type) + { + ilgen_real.Emit(opcode, (Type)arg); + } + else if (arg is CodeEmitterLocal) + { + CodeEmitterLocal local = (CodeEmitterLocal)arg; + local.Emit(ilgen_real, opcode); + } + else if (arg is CodeEmitterLabel) + { + CodeEmitterLabel label = (CodeEmitterLabel)arg; + ilgen_real.Emit(opcode, label.Label); + } + else if (arg is CodeEmitterLabel[]) + { + CodeEmitterLabel[] labels = (CodeEmitterLabel[])arg; + Label[] real = new Label[labels.Length]; + for (int i = 0; i < labels.Length; i++) + { + real[i] = labels[i].Label; + } + ilgen_real.Emit(opcode, real); + } + else if (arg is CalliWrapper) + { + CalliWrapper args = (CalliWrapper)arg; + ilgen_real.EmitCalli(opcode, args.unmanagedCallConv, args.returnType, args.parameterTypes); + } + else + { + throw new InvalidOperationException(); + } + } + + private void RemoveJumpNext() + { + for (int i = 1; i < code.Count; i++) + { + if (code[i].pseudo == CodeType.Label) + { + if (code[i - 1].opcode == OpCodes.Br + && code[i - 1].MatchLabel(code[i])) + { + code.RemoveAt(i - 1); + i--; + } + else if (i >= 2 + && code[i - 1].pseudo == CodeType.LineNumber + && code[i - 2].opcode == OpCodes.Br + && code[i - 2].MatchLabel(code[i])) + { + code.RemoveAt(i - 2); + i--; + } + } + } + } + + private void AnnihilateStoreReleaseTempLocals() + { + for (int i = 1; i < code.Count; i++) + { + if (code[i].opcode == OpCodes.Stloc) + { + if (code[i + 1].pseudo == CodeType.ReleaseTempLocal + && code[i].Local == code[i + 1].Local) + { + code[i] = new OpCodeWrapper(OpCodes.Pop, null); + } + else if (code[i + 1].opcode == OpCodes.Ldloc + && code[i + 1].Local == code[i].Local + && code[i + 2].pseudo == CodeType.ReleaseTempLocal + && code[i + 2].Local == code[i].Local) + { + code.RemoveRange(i, 2); + } + } + } + } + + private void AnnihilatePops() + { + for (int i = 1; i < code.Count; i++) + { + if (code[i].opcode == OpCodes.Pop) + { + // search backwards for a candidate push to annihilate + int stack = 0; + for (int j = i - 1; j >= 0; j--) + { + if (IsSideEffectFreePush(j)) + { + if (stack == 0) + { + code.RemoveAt(i); + code.RemoveAt(j); + i -= 2; + break; + } + stack++; + } + else if (code[j].opcode == OpCodes.Stloc) + { + stack--; + } + else if (code[j].opcode == OpCodes.Shl + || code[j].opcode == OpCodes.And + || code[j].opcode == OpCodes.Add + || code[j].opcode == OpCodes.Sub) + { + if (stack == 0) + { + break; + } + stack--; + } + else if (code[j].opcode == OpCodes.Conv_Ovf_I4 + || code[j].opcode == OpCodes.Conv_I8 + || code[j].opcode == OpCodes.Ldlen) + { + if (stack == 0) + { + break; + } + // no stack effect + } + else + { + break; + } + } + } + } + } + + private bool IsSideEffectFreePush(int index) + { + if (code[index].opcode == OpCodes.Ldstr) + { + return true; + } + else if (code[index].opcode == OpCodes.Ldnull) + { + return true; + } + else if (code[index].opcode == OpCodes.Ldsfld) + { + FieldInfo field = code[index].FieldInfo; + if (field != null) + { + // Here we are considering BeforeFieldInit to mean that we really don't care about + // when the type is initialized (which is what we mean in the rest of the IKVM code as well) + // but it is good to point it out here because strictly speaking we're violating the + // BeforeFieldInit contract here by considering dummy loads not to be field accesses. + if ((field.DeclaringType.Attributes & TypeAttributes.BeforeFieldInit) != 0) + { + return true; + } + // If we're accessing a field in the current type, it can't trigger the static initializer + // (unless beforefieldinit is set, but see above for that scenario) + if (field.DeclaringType == declaringType) + { + return true; + } + } + return false; + } + else if (code[index].opcode == OpCodes.Ldc_I4) + { + return true; + } + else if (code[index].opcode == OpCodes.Ldc_I8) + { + return true; + } + else if (code[index].opcode == OpCodes.Ldc_R4) + { + return true; + } + else if (code[index].opcode == OpCodes.Ldc_R8) + { + return true; + } + else if (code[index].opcode == OpCodes.Ldloc) + { + return true; + } + else if (code[index].opcode == OpCodes.Ldarg) + { + return true; + } + else if (code[index].opcode == OpCodes.Ldarg_S) + { + return true; + } + else if (code[index].opcode == OpCodes.Ldarg_0) + { + return true; + } + else if (code[index].opcode == OpCodes.Ldarg_1) + { + return true; + } + else if (code[index].opcode == OpCodes.Ldarg_2) + { + return true; + } + else if (code[index].opcode == OpCodes.Ldarg_3) + { + return true; + } + else + { + return false; + } + } + + private void OptimizeBranchSizes() + { + int offset = 0; + for (int i = 0; i < code.Count; i++) + { + if (code[i].pseudo == CodeType.Label) + { + code[i].Label.Temp = offset; + } + offset += code[i].Size; + } + offset = 0; + for (int i = 0; i < code.Count; i++) + { + int prevOffset = offset; + offset += code[i].Size; + if (code[i].HasLabel && code[i].opcode.OperandType == OperandType.InlineBrTarget) + { + CodeEmitterLabel label = code[i].Label; + int diff = label.Temp - (prevOffset + code[i].opcode.Size + 1); + if (-128 <= diff && diff <= 127) + { + OpCode opcode = code[i].opcode; + if (opcode == OpCodes.Brtrue) + { + opcode = OpCodes.Brtrue_S; + } + else if (opcode == OpCodes.Brfalse) + { + opcode = OpCodes.Brfalse_S; + } + else if (opcode == OpCodes.Br) + { + opcode = OpCodes.Br_S; + } + else if (opcode == OpCodes.Beq) + { + opcode = OpCodes.Beq_S; + } + else if (opcode == OpCodes.Bne_Un) + { + opcode = OpCodes.Bne_Un_S; + } + else if (opcode == OpCodes.Ble) + { + opcode = OpCodes.Ble_S; + } + else if (opcode == OpCodes.Ble_Un) + { + opcode = OpCodes.Ble_Un_S; + } + else if (opcode == OpCodes.Blt) + { + opcode = OpCodes.Blt_S; + } + else if (opcode == OpCodes.Blt_Un) + { + opcode = OpCodes.Blt_Un_S; + } + else if (opcode == OpCodes.Bge) + { + opcode = OpCodes.Bge_S; + } + else if (opcode == OpCodes.Bge_Un) + { + opcode = OpCodes.Bge_Un_S; + } + else if (opcode == OpCodes.Bgt) + { + opcode = OpCodes.Bgt_S; + } + else if (opcode == OpCodes.Bgt_Un) + { + opcode = OpCodes.Bgt_Un_S; + } + else if (opcode == OpCodes.Leave) + { + opcode = OpCodes.Leave_S; + } + code[i] = new OpCodeWrapper(opcode, label); + } + } + } + } + + private void OptimizePatterns() + { + SetLabelRefCounts(); + for (int i = 1; i < code.Count; i++) + { + if (code[i].opcode == OpCodes.Isinst + && code[i + 1].opcode == OpCodes.Ldnull + && code[i + 2].opcode == OpCodes.Cgt_Un + && (code[i + 3].opcode == OpCodes.Brfalse || code[i + 3].opcode == OpCodes.Brtrue)) + { + code.RemoveRange(i + 1, 2); + } + else if (code[i].opcode == OpCodes.Ldelem_I1 + && code[i + 1].opcode == OpCodes.Ldc_I4 && code[i + 1].ValueInt32 == 255 + && code[i + 2].opcode == OpCodes.And) + { + code[i] = new OpCodeWrapper(OpCodes.Ldelem_U1, null); + code.RemoveRange(i + 1, 2); + } + else if (code[i].opcode == OpCodes.Ldelem_I1 + && code[i + 1].opcode == OpCodes.Conv_I8 + && code[i + 2].opcode == OpCodes.Ldc_I8 && code[i + 2].ValueInt64 == 255 + && code[i + 3].opcode == OpCodes.And) + { + code[i] = new OpCodeWrapper(OpCodes.Ldelem_U1, null); + code.RemoveRange(i + 2, 2); + } + else if (code[i].opcode == OpCodes.Ldc_I4 + && code[i + 1].opcode == OpCodes.Ldc_I4 + && code[i + 2].opcode == OpCodes.And) + { + code[i] = new OpCodeWrapper(OpCodes.Ldc_I4, code[i].ValueInt32 & code[i + 1].ValueInt32); + code.RemoveRange(i + 1, 2); + } + else if (MatchCompare(i, OpCodes.Cgt, OpCodes.Clt_Un, Types.Double) // dcmpl + || MatchCompare(i, OpCodes.Cgt, OpCodes.Clt_Un, Types.Single)) // fcmpl + { + PatchCompare(i, OpCodes.Ble_Un, OpCodes.Blt_Un, OpCodes.Bge, OpCodes.Bgt); + } + else if (MatchCompare(i, OpCodes.Cgt_Un, OpCodes.Clt, Types.Double) // dcmpg + || MatchCompare(i, OpCodes.Cgt_Un, OpCodes.Clt, Types.Single)) // fcmpg + { + PatchCompare(i, OpCodes.Ble, OpCodes.Blt, OpCodes.Bge_Un, OpCodes.Bgt_Un); + } + else if (MatchCompare(i, OpCodes.Cgt, OpCodes.Clt, Types.Int64)) // lcmp + { + PatchCompare(i, OpCodes.Ble, OpCodes.Blt, OpCodes.Bge, OpCodes.Bgt); + } + else if (i < code.Count - 10 + && code[i].opcode == OpCodes.Ldc_I4 + && code[i + 1].opcode == OpCodes.Dup + && code[i + 2].opcode == OpCodes.Ldc_I4_M1 + && code[i + 3].opcode == OpCodes.Bne_Un + && code[i + 4].opcode == OpCodes.Pop + && code[i + 5].opcode == OpCodes.Neg + && code[i + 6].opcode == OpCodes.Br + && code[i + 7].pseudo == CodeType.Label && code[i + 7].MatchLabel(code[i + 3]) && code[i + 7].Label.Temp == 1 + && code[i + 8].opcode == OpCodes.Div + && code[i + 9].pseudo == CodeType.Label && code[i + 9].Label == code[i + 6].Label && code[i + 9].Label.Temp == 1) + { + int divisor = code[i].ValueInt32; + if (divisor == -1) + { + code[i] = code[i + 5]; + code.RemoveRange(i + 1, 9); + } + else + { + code[i + 1] = code[i + 8]; + code.RemoveRange(i + 2, 8); + } + } + else if (i < code.Count - 11 + && code[i].opcode == OpCodes.Ldc_I8 + && code[i + 1].opcode == OpCodes.Dup + && code[i + 2].opcode == OpCodes.Ldc_I4_M1 + && code[i + 3].opcode == OpCodes.Conv_I8 + && code[i + 4].opcode == OpCodes.Bne_Un + && code[i + 5].opcode == OpCodes.Pop + && code[i + 6].opcode == OpCodes.Neg + && code[i + 7].opcode == OpCodes.Br + && code[i + 8].pseudo == CodeType.Label && code[i + 8].MatchLabel(code[i + 4]) && code[i + 8].Label.Temp == 1 + && code[i + 9].opcode == OpCodes.Div + && code[i + 10].pseudo == CodeType.Label && code[i + 10].MatchLabel(code[i + 7]) && code[i + 10].Label.Temp == 1) + { + long divisor = code[i].ValueInt64; + if (divisor == -1) + { + code[i] = code[i + 6]; + code.RemoveRange(i + 1, 10); + } + else + { + code[i + 1] = code[i + 9]; + code.RemoveRange(i + 2, 9); + } + } + else if (code[i].opcode == OpCodes.Box + && code[i + 1].opcode == OpCodes.Unbox && code[i + 1].Type == code[i].Type) + { + CodeEmitterLocal local = new CodeEmitterLocal(code[i].Type); + code[i] = new OpCodeWrapper(OpCodes.Stloc, local); + code[i + 1] = new OpCodeWrapper(OpCodes.Ldloca, local); + } + else if (i < code.Count - 13 + && code[i + 0].opcode == OpCodes.Box + && code[i + 1].opcode == OpCodes.Dup + && code[i + 2].opcode == OpCodes.Brtrue + && code[i + 3].opcode == OpCodes.Pop + && code[i + 4].opcode == OpCodes.Ldloca && code[i + 4].Local.LocalType == code[i + 0].Type + && code[i + 5].opcode == OpCodes.Initobj && code[i + 5].Type == code[i + 0].Type + && code[i + 6].opcode == OpCodes.Ldloc && code[i + 6].Local == code[i + 4].Local + && code[i + 7].pseudo == CodeType.ReleaseTempLocal && code[i + 7].Local == code[i + 6].Local + && code[i + 8].opcode == OpCodes.Br + && code[i + 9].pseudo == CodeType.Label && code[i + 9].MatchLabel(code[i + 2]) && code[i + 9].Label.Temp == 1 + && code[i + 10].opcode == OpCodes.Unbox && code[i + 10].Type == code[i + 0].Type + && code[i + 11].opcode == OpCodes.Ldobj && code[i + 11].Type == code[i + 0].Type + && code[i + 12].pseudo == CodeType.Label && code[i + 12].MatchLabel(code[i + 8]) && code[i + 12].Label.Temp == 1) + { + code.RemoveRange(i, 13); + } + + // NOTE intentionally not an else, because we want to optimize the code generated by the earlier compare optimization + if (i < code.Count - 6 + && code[i].opcode.FlowControl == FlowControl.Cond_Branch + && code[i + 1].opcode == OpCodes.Ldc_I4 && code[i + 1].ValueInt32 == 1 + && code[i + 2].opcode == OpCodes.Br + && code[i + 3].pseudo == CodeType.Label && code[i + 3].MatchLabel(code[i]) && code[i + 3].Label.Temp == 1 + && code[i + 4].opcode == OpCodes.Ldc_I4 && code[i + 4].ValueInt32 == 0 + && code[i + 5].pseudo == CodeType.Label && code[i + 5].MatchLabel(code[i + 2]) && code[i + 5].Label.Temp == 1) + { + if (code[i].opcode == OpCodes.Bne_Un) + { + code[i] = new OpCodeWrapper(OpCodes.Ceq, null); + code.RemoveRange(i + 1, 5); + } + else if (code[i].opcode == OpCodes.Beq) + { + code[i + 0] = new OpCodeWrapper(OpCodes.Ceq, null); + code[i + 1] = new OpCodeWrapper(OpCodes.Ldc_I4, 0); + code[i + 2] = new OpCodeWrapper(OpCodes.Ceq, null); + code.RemoveRange(i + 3, 3); + } + else if (code[i].opcode == OpCodes.Ble || code[i].opcode == OpCodes.Ble_Un) + { + code[i] = new OpCodeWrapper(OpCodes.Cgt, null); + code.RemoveRange(i + 1, 5); + } + else if (code[i].opcode == OpCodes.Blt) + { + code[i] = new OpCodeWrapper(OpCodes.Clt, null); + code[i + 1] = new OpCodeWrapper(OpCodes.Ldc_I4, 0); + code[i + 2] = new OpCodeWrapper(OpCodes.Ceq, null); + code.RemoveRange(i + 3, 3); + } + else if (code[i].opcode == OpCodes.Blt_Un) + { + code[i] = new OpCodeWrapper(OpCodes.Clt_Un, null); + code[i + 1] = new OpCodeWrapper(OpCodes.Ldc_I4, 0); + code[i + 2] = new OpCodeWrapper(OpCodes.Ceq, null); + code.RemoveRange(i + 3, 3); + } + else if (code[i].opcode == OpCodes.Bge || code[i].opcode == OpCodes.Bge_Un) + { + code[i] = new OpCodeWrapper(OpCodes.Clt, null); + code.RemoveRange(i + 1, 5); + } + else if (code[i].opcode == OpCodes.Bgt) + { + code[i] = new OpCodeWrapper(OpCodes.Cgt, null); + code[i + 1] = new OpCodeWrapper(OpCodes.Ldc_I4, 0); + code[i + 2] = new OpCodeWrapper(OpCodes.Ceq, null); + code.RemoveRange(i + 3, 3); + } + else if (code[i].opcode == OpCodes.Bgt_Un) + { + code[i] = new OpCodeWrapper(OpCodes.Cgt_Un, null); + code[i + 1] = new OpCodeWrapper(OpCodes.Ldc_I4, 0); + code[i + 2] = new OpCodeWrapper(OpCodes.Ceq, null); + code.RemoveRange(i + 3, 3); + } + } + } + } + + private bool MatchCompare(int index, OpCode cmp1, OpCode cmp2, Type type) + { + return code[index].opcode == OpCodes.Stloc && code[index].Local.LocalType == type + && code[index + 1].opcode == OpCodes.Stloc && code[index + 1].Local.LocalType == type + && code[index + 2].opcode == OpCodes.Ldloc && code[index + 2].MatchLocal(code[index + 1]) + && code[index + 3].opcode == OpCodes.Ldloc && code[index + 3].MatchLocal(code[index]) + && code[index + 4].opcode == cmp1 + && code[index + 5].opcode == OpCodes.Ldloc && code[index + 5].MatchLocal(code[index + 1]) + && code[index + 6].opcode == OpCodes.Ldloc && code[index + 6].MatchLocal(code[index]) + && code[index + 7].opcode == cmp2 + && code[index + 8].opcode == OpCodes.Sub + && code[index + 9].pseudo == CodeType.ReleaseTempLocal && code[index + 9].Local == code[index].Local + && code[index + 10].pseudo == CodeType.ReleaseTempLocal && code[index + 10].Local == code[index + 1].Local + && ((code[index + 11].opcode.FlowControl == FlowControl.Cond_Branch && code[index + 11].HasLabel) || + (code[index + 11].opcode == OpCodes.Ldc_I4_0 + && (code[index + 12].opcode.FlowControl == FlowControl.Cond_Branch && code[index + 12].HasLabel))); + } + + private void PatchCompare(int index, OpCode ble, OpCode blt, OpCode bge, OpCode bgt) + { + if (code[index + 11].opcode == OpCodes.Brtrue) + { + code[index] = new OpCodeWrapper(OpCodes.Bne_Un, code[index + 11].Label); + code.RemoveRange(index + 1, 11); + } + else if (code[index + 11].opcode == OpCodes.Brfalse) + { + code[index] = new OpCodeWrapper(OpCodes.Beq, code[index + 11].Label); + code.RemoveRange(index + 1, 11); + } + else if (code[index + 11].opcode == OpCodes.Ldc_I4_0) + { + if (code[index + 12].opcode == OpCodes.Ble) + { + code[index] = new OpCodeWrapper(ble, code[index + 12].Label); + code.RemoveRange(index + 1, 12); + } + else if (code[index + 12].opcode == OpCodes.Blt) + { + code[index] = new OpCodeWrapper(blt, code[index + 12].Label); + code.RemoveRange(index + 1, 12); + } + else if (code[index + 12].opcode == OpCodes.Bge) + { + code[index] = new OpCodeWrapper(bge, code[index + 12].Label); + code.RemoveRange(index + 1, 12); + } + else if (code[index + 12].opcode == OpCodes.Bgt) + { + code[index] = new OpCodeWrapper(bgt, code[index + 12].Label); + code.RemoveRange(index + 1, 12); + } + } + } + + private void OptimizeEncodings() + { + for (int i = 0; i < code.Count; i++) + { + if (code[i].opcode == OpCodes.Ldc_I4) + { + code[i] = OptimizeLdcI4(code[i].ValueInt32); + } + else if (code[i].opcode == OpCodes.Ldc_I8) + { + OptimizeLdcI8(i); + } + } + } + + private OpCodeWrapper OptimizeLdcI4(int value) + { + switch (value) + { + case -1: + return new OpCodeWrapper(OpCodes.Ldc_I4_M1, null); + case 0: + return new OpCodeWrapper(OpCodes.Ldc_I4_0, null); + case 1: + return new OpCodeWrapper(OpCodes.Ldc_I4_1, null); + case 2: + return new OpCodeWrapper(OpCodes.Ldc_I4_2, null); + case 3: + return new OpCodeWrapper(OpCodes.Ldc_I4_3, null); + case 4: + return new OpCodeWrapper(OpCodes.Ldc_I4_4, null); + case 5: + return new OpCodeWrapper(OpCodes.Ldc_I4_5, null); + case 6: + return new OpCodeWrapper(OpCodes.Ldc_I4_6, null); + case 7: + return new OpCodeWrapper(OpCodes.Ldc_I4_7, null); + case 8: + return new OpCodeWrapper(OpCodes.Ldc_I4_8, null); + default: + if (value >= -128 && value <= 127) + { + return new OpCodeWrapper(OpCodes.Ldc_I4_S, (sbyte)value); + } + else + { + return new OpCodeWrapper(OpCodes.Ldc_I4, value); + } + } + } + + private void OptimizeLdcI8(int index) + { + long value = code[index].ValueInt64; + OpCode opc = OpCodes.Nop; + switch (value) + { + case -1: + opc = OpCodes.Ldc_I4_M1; + break; + case 0: + opc = OpCodes.Ldc_I4_0; + break; + case 1: + opc = OpCodes.Ldc_I4_1; + break; + case 2: + opc = OpCodes.Ldc_I4_2; + break; + case 3: + opc = OpCodes.Ldc_I4_3; + break; + case 4: + opc = OpCodes.Ldc_I4_4; + break; + case 5: + opc = OpCodes.Ldc_I4_5; + break; + case 6: + opc = OpCodes.Ldc_I4_6; + break; + case 7: + opc = OpCodes.Ldc_I4_7; + break; + case 8: + opc = OpCodes.Ldc_I4_8; + break; + default: + if (value >= -2147483648L && value <= 4294967295L) + { + if (value >= -128 && value <= 127) + { + code[index] = new OpCodeWrapper(OpCodes.Ldc_I4_S, (sbyte)value); + } + else + { + code[index] = new OpCodeWrapper(OpCodes.Ldc_I4, (int)value); + } + if (value < 0) + { + code.Insert(index + 1, new OpCodeWrapper(OpCodes.Conv_I8, null)); + } + else + { + code.Insert(index + 1, new OpCodeWrapper(OpCodes.Conv_U8, null)); + } + } + break; + } + if (opc != OpCodes.Nop) + { + code[index] = new OpCodeWrapper(opc, null); + code.Insert(index + 1, new OpCodeWrapper(OpCodes.Conv_I8, null)); + } + } + + private void ChaseBranches() + { + /* + * Here we do a couple of different optimizations to unconditional branches: + * - a branch to a ret or endfinally will be replaced + * by the ret or endfinally instruction (because that is always at least as efficient) + * - a branch to a branch will remove the indirection + * - a leave to a branch or leave will remove the indirection + */ + SetLabelIndexes(); + for (int i = 0; i < code.Count; i++) + { + if (code[i].opcode == OpCodes.Br) + { + int target = code[i].Label.Temp + 1; + if (code[target].pseudo == CodeType.LineNumber) + { + // line number info on endfinally or ret is probably useless anyway + target++; + } + if (code[target].opcode == OpCodes.Endfinally || code[target].opcode == OpCodes.Ret) + { + code[i] = code[target]; + } + else + { + CodeEmitterLabel label = null; + while (code[target].opcode == OpCodes.Br && target != i) + { + label = code[target].Label; + target = code[target].Label.Temp + 1; + } + if (label != null) + { + code[i] = new OpCodeWrapper(OpCodes.Br, label); + } + } + } + else if (code[i].opcode == OpCodes.Leave) + { + int target = code[i].Label.Temp + 1; + CodeEmitterLabel label = null; + while ((code[target].opcode == OpCodes.Br || code[target].opcode == OpCodes.Leave) && target != i) + { + label = code[target].Label; + target = code[target].Label.Temp + 1; + } + if (label != null) + { + code[i] = new OpCodeWrapper(OpCodes.Leave, label); + } + } + } + } + + private void RemoveSingletonBranches() + { + /* + * Here we try to remove unconditional branches that jump to a label with ref count of one + * and where the code is not otherwise used. + */ + SetLabelRefCounts(); + // now increment label refcounts for labels that are also reachable via the preceding instruction + bool reachable = true; + for (int i = 0; i < code.Count; i++) + { + if (reachable) + { + switch (code[i].pseudo) + { + case CodeType.Label: + code[i].Label.Temp++; + break; + case CodeType.BeginCatchBlock: + case CodeType.BeginFaultBlock: + case CodeType.BeginFinallyBlock: + case CodeType.EndExceptionBlock: + throw new InvalidOperationException(); + case CodeType.OpCode: + switch (code[i].opcode.FlowControl) + { + case FlowControl.Branch: + case FlowControl.Return: + case FlowControl.Throw: + reachable = false; + break; + } + break; + } + } + else + { + switch (code[i].pseudo) + { + case CodeType.Label: + reachable = code[i].Label.Temp > 0; + break; + case CodeType.BeginCatchBlock: + case CodeType.BeginFaultBlock: + case CodeType.BeginFinallyBlock: + reachable = true; + break; + } + } + } + + // now remove the unconditional branches to labels with a refcount of one + for (int i = 0; i < code.Count; i++) + { + if (code[i].opcode == OpCodes.Br && code[i].Label.Temp == 1) + { + int target = FindLabel(code[i].Label) + 1; + for (int j = target; j < code.Count; j++) + { + switch (code[j].pseudo) + { + case CodeType.OpCode: + if (code[j].HasLocal && FindLocal(code[j].Local) > i) + { + // we cannot local variable usage before the declaration + goto breakOuter; + } + switch (code[j].opcode.FlowControl) + { + case FlowControl.Branch: + case FlowControl.Return: + case FlowControl.Throw: + // we've found a viable sequence of opcode to move to the branch location + List range = code.GetRange(target, j - target + 1); + if (target < i) + { + code.RemoveAt(i); + code.InsertRange(i, range); + code.RemoveRange(target - 1, range.Count + 1); + i -= range.Count + 1; + } + else + { + code.RemoveRange(target - 1, range.Count + 1); + code.RemoveAt(i); + code.InsertRange(i, range); + } + goto breakOuter; + } + break; + case CodeType.Label: + case CodeType.BeginExceptionBlock: + case CodeType.DeclareLocal: + goto breakOuter; + } + } + breakOuter: ; + } + } + } + + private int FindLabel(CodeEmitterLabel label) + { + for (int i = 0; i < code.Count; i++) + { + if (code[i].pseudo == CodeType.Label && code[i].Label == label) + { + return i; + } + } + throw new InvalidOperationException(); + } + + private int FindLocal(CodeEmitterLocal local) + { + for (int i = 0; i < code.Count; i++) + { + if (code[i].pseudo == CodeType.DeclareLocal && code[i].Local == local) + { + return i; + } + } + // if the local variable isn't declared, it is a temporary that is allocated on demand + // (so we can move their usage freely) + return 0; + } + + private void SortPseudoOpCodes() + { + for (int i = 0; i < code.Count - 1; i++) + { + switch (code[i].pseudo) + { + case CodeType.ReleaseTempLocal: + for (int j = i - 1; ; j--) + { + if (j == -1) + { + code.RemoveAt(i); + break; + } + if (code[j].HasLocal && code[j].Local == code[i].Local) + { + MoveInstruction(i, j + 1); + break; + } + } + break; + } + } + } + + private void MoveInstruction(int i, int j) + { + if (i == j - 1 || i == j + 1) + { + OpCodeWrapper temp = code[i]; + code[i] = code[j]; + code[j] = temp; + } + else if (i < j) + { + code.Insert(j, code[i]); + code.RemoveAt(i); + } + else if (i > j) + { + OpCodeWrapper temp = code[i]; + code.RemoveAt(i); + code.Insert(j, temp); + } + } + + private void ClearLabelTemp() + { + for (int i = 0; i < code.Count; i++) + { + if (code[i].pseudo == CodeType.Label) + { + code[i].Label.Temp = 0; + } + } + } + + private void SetLabelIndexes() + { + for (int i = 0; i < code.Count; i++) + { + if (code[i].pseudo == CodeType.Label) + { + code[i].Label.Temp = i; + } + } + } + + private void SetLabelRefCounts() + { + ClearLabelTemp(); + for (int i = 0; i < code.Count; i++) + { + if (code[i].pseudo == CodeType.OpCode) + { + if (code[i].HasLabel) + { + code[i].Label.Temp++; + } + else if (code[i].opcode == OpCodes.Switch) + { + foreach (CodeEmitterLabel label in code[i].Labels) + { + label.Temp++; + } + } + } + } + } + + private void RemoveUnusedLabels() + { + SetLabelRefCounts(); + for (int i = 0; i < code.Count; i++) + { + while (code[i].pseudo == CodeType.Label && code[i].Label.Temp == 0) + { + code.RemoveAt(i); + } + } + } + + private void RemoveDeadCode() + { + ClearLabelTemp(); + const int ReachableFlag = 1; + const int ProcessedFlag = 2; + bool reachable = true; + bool done = false; + while (!done) + { + done = true; + for (int i = 0; i < code.Count; i++) + { + if (reachable) + { + if (code[i].pseudo == CodeType.Label) + { + if (code[i].Label.Temp == ProcessedFlag) + { + done = false; + } + code[i].Label.Temp |= ReachableFlag; + } + else if (code[i].pseudo == CodeType.OpCode) + { + if (code[i].HasLabel) + { + if (code[i].Label.Temp == ProcessedFlag) + { + done = false; + } + code[i].Label.Temp |= ReachableFlag; + } + else if (code[i].opcode == OpCodes.Switch) + { + foreach (CodeEmitterLabel label in code[i].Labels) + { + if (label.Temp == ProcessedFlag) + { + done = false; + } + label.Temp |= ReachableFlag; + } + } + switch (code[i].opcode.FlowControl) + { + case FlowControl.Cond_Branch: + if (!code[i].HasLabel && code[i].opcode != OpCodes.Switch) + { + throw new NotSupportedException(); + } + break; + case FlowControl.Branch: + case FlowControl.Return: + case FlowControl.Throw: + reachable = false; + break; + } + } + } + else if (code[i].pseudo == CodeType.BeginCatchBlock) + { + reachable = true; + } + else if (code[i].pseudo == CodeType.BeginFaultBlock) + { + reachable = true; + } + else if (code[i].pseudo == CodeType.BeginFinallyBlock) + { + reachable = true; + } + else if (code[i].pseudo == CodeType.Label && (code[i].Label.Temp & ReachableFlag) != 0) + { + reachable = true; + } + if (code[i].pseudo == CodeType.Label) + { + code[i].Label.Temp |= ProcessedFlag; + } + } + } + reachable = true; + int firstUnreachable = -1; + for (int i = 0; i < code.Count; i++) + { + if (reachable) + { + if (code[i].pseudo == CodeType.OpCode) + { + switch (code[i].opcode.FlowControl) + { + case FlowControl.Branch: + case FlowControl.Return: + case FlowControl.Throw: + reachable = false; + firstUnreachable = i + 1; + break; + } + } + } + else + { + switch (code[i].pseudo) + { + case CodeType.OpCode: + break; + case CodeType.Label: + if ((code[i].Label.Temp & ReachableFlag) != 0) + { + goto case CodeType.BeginCatchBlock; + } + break; + case CodeType.BeginCatchBlock: + case CodeType.BeginFaultBlock: + case CodeType.BeginFinallyBlock: + code.RemoveRange(firstUnreachable, i - firstUnreachable); + i = firstUnreachable; + firstUnreachable = -1; + reachable = true; + break; + default: + code.RemoveRange(firstUnreachable, i - firstUnreachable); + i = firstUnreachable; + firstUnreachable++; + break; + } + } + } + if (!reachable) + { + code.RemoveRange(firstUnreachable, code.Count - firstUnreachable); + } + + // TODO can't we incorporate this in the above code? + // remove exception blocks with empty try blocks + // (which can happen if the try block is unreachable) + for (int i = 0; i < code.Count; i++) + { + restart: + if (code[i].pseudo == CodeType.BeginExceptionBlock) + { + for (int k = 0; ; k++) + { + switch (code[i + k].pseudo) + { + case CodeType.BeginCatchBlock: + case CodeType.BeginFaultBlock: + case CodeType.BeginFinallyBlock: + int depth = 0; + for (int j = i + 1; ; j++) + { + switch (code[j].pseudo) + { + case CodeType.BeginExceptionBlock: + depth++; + break; + case CodeType.EndExceptionBlock: + if (depth == 0) + { + code.RemoveRange(i, (j - i) + 1); + goto restart; + } + depth--; + break; + } + } + case CodeType.OpCode: + goto next; + } + } + } + next: ; + } + } + + private void DeduplicateBranchSourceTargetCode() + { + SetLabelIndexes(); + for (int i = 0; i < code.Count; i++) + { + if (code[i].opcode == OpCodes.Br && code[i].HasLabel) + { + int source = i - 1; + int target = code[i].Label.Temp - 1; + while (source >= 0 && target >= 0) + { + switch (code[source].pseudo) + { + case CodeType.LineNumber: + case CodeType.OpCode: + break; + default: + goto break_while; + } + if (!code[source].Match(code[target])) + { + break; + } + switch (code[source].opcode.FlowControl) + { + case FlowControl.Branch: + case FlowControl.Cond_Branch: + goto break_while; + } + source--; + target--; + } + break_while: ; + source++; + target++; + if (source != i && target > 0 && source != target - 1) + { + // TODO for now we only do this optimization if there happens to be an appriopriate label + if (code[target - 1].pseudo == CodeType.Label) + { + code[source] = new OpCodeWrapper(OpCodes.Br, code[target - 1].Label); + for (int j = source + 1; j <= i; j++) + { + // We can't depend on DCE for code correctness (we have to maintain all MSIL invariants at all times), + // so we patch out the unused code. + code[j] = new OpCodeWrapper(CodeType.Unreachable, null); + } + } + } + } + } + } + + private void OptimizeStackTransfer() + { + for (int i = 0; i < code.Count; i++) + { + if (code[i].opcode == OpCodes.Ldloc + && code[i + 1].opcode == OpCodes.Stloc + && code[i + 2].pseudo == CodeType.BeginExceptionBlock + && code[i + 3].opcode == OpCodes.Ldloc && code[i + 3].MatchLocal(code[i + 1]) + && code[i + 4].pseudo == CodeType.ReleaseTempLocal && code[i + 4].MatchLocal(code[i + 3])) + { + code[i + 1] = code[i]; + code[i] = code[i + 2]; + code.RemoveRange(i + 2, 3); + } + } + } + + private void MergeExceptionBlocks() + { + // The first loop will convert all Begin[Exception|Catch|Fault|Finally]Block and EndExceptionBlock + // pseudo opcodes into a cyclic linked list (EndExceptionBlock links back to BeginExceptionBlock) + // to allow for easy traversal in the next loop. + int[] extra = new int[code.Count]; + Stack stack = new Stack(); + int currentBeginExceptionBlock = -1; + int currentLast = -1; + for (int i = 0; i < code.Count; i++) + { + switch (code[i].pseudo) + { + case CodeType.BeginExceptionBlock: + stack.Push(currentBeginExceptionBlock); + currentBeginExceptionBlock = i; + currentLast = i; + break; + case CodeType.EndExceptionBlock: + extra[currentLast] = i; + extra[i] = currentBeginExceptionBlock; + currentBeginExceptionBlock = stack.Pop(); + currentLast = currentBeginExceptionBlock; + if (currentLast != -1) + { + while (extra[currentLast] != 0) + { + currentLast = extra[currentLast]; + } + } + break; + case CodeType.BeginCatchBlock: + case CodeType.BeginFaultBlock: + case CodeType.BeginFinallyBlock: + extra[currentLast] = i; + currentLast = i; + break; + } + } + + // Now we look for consecutive exception blocks that have the same fault handler + for (int i = 0; i < code.Count - 1; i++) + { + if (code[i].pseudo == CodeType.EndExceptionBlock + && code[i + 1].pseudo == CodeType.BeginExceptionBlock) + { + if (IsFaultOnlyBlock(extra, extra[i]) && IsFaultOnlyBlock(extra, i + 1)) + { + int beginFault1 = extra[extra[i]]; + int beginFault2 = extra[i + 1]; + int length1 = extra[beginFault1] - beginFault1; + int length2 = extra[beginFault2] - beginFault2; + if (length1 == length2 && MatchHandlers(beginFault1, beginFault2, length1)) + { + // Check if the labels at the start of the handler are reachable from outside + // of the new combined block. + for (int j = i + 2; j < beginFault2; j++) + { + if (code[j].pseudo == CodeType.OpCode) + { + break; + } + else if (code[j].pseudo == CodeType.Label) + { + if (HasBranchTo(0, extra[i], code[j].Label) + || HasBranchTo(beginFault2 + length2, code.Count, code[j].Label)) + { + goto no_merge; + } + } + } + // Merge the two blocks by overwritting the first fault block and + // the BeginExceptionBlock of the second block. + for (int j = beginFault1; j < i + 2; j++) + { + code[j] = new OpCodeWrapper(OpCodes.Nop, null); + } + // Repair the linking structure. + extra[extra[i]] = beginFault2; + extra[extra[beginFault2]] = extra[i]; + } + } + no_merge: ; + } + } + } + + private bool HasBranchTo(int start, int end, CodeEmitterLabel label) + { + for (int i = start; i < end; i++) + { + if (code[i].HasLabel) + { + if (code[i].Label == label) + { + return true; + } + } + else if (code[i].opcode == OpCodes.Switch) + { + foreach (CodeEmitterLabel swlbl in code[i].Labels) + { + if (swlbl == label) + { + return true; + } + } + } + } + return false; + } + + private bool MatchHandlers(int beginFault1, int beginFault2, int length) + { + for (int i = 0; i < length; i++) + { + if (!code[beginFault1 + i].Match(code[beginFault2 + i])) + { + return false; + } + } + return true; + } + + private bool IsFaultOnlyBlock(int[] extra, int begin) + { + return code[extra[begin]].pseudo == CodeType.BeginFaultBlock + && code[extra[extra[begin]]].pseudo == CodeType.EndExceptionBlock; + } + + private void ConvertSynchronizedFaultToFinally() + { + bool labelIndexSet = false; + int start = -1; + int nest = 0; + int next = -1; + for (int i = 0; i < code.Count; i++) + { + switch (code[i].pseudo) + { + case CodeType.BeginExceptionBlock: + if (nest == 0) + { + start = i; + } + else if (nest == 1 && next <= start) + { + next = i; + } + nest++; + break; + case CodeType.BeginCatchBlock: + case CodeType.BeginFinallyBlock: + if (nest == 1) + { + nest = 0; + if (next > start) + { + // while we were processing the outer block, we encountered a nested BeginExceptionBlock + // so now that we've failed the outer, restart at the first nested block + i = start = next; + nest = 1; + } + } + else + { + next = -1; + } + break; + case CodeType.BeginFaultBlock: + if (nest == 1) + { + int beginFault = i; + if (code[i + 1].pseudo == CodeType.LineNumber) + { + i++; + } + // check if the fault handler is the synchronized block exit pattern + if (code[i + 1].opcode == OpCodes.Ldloc + && code[i + 2].pseudo == CodeType.MonitorExit + && code[i + 3].opcode == OpCodes.Endfinally) + { + if (!labelIndexSet) + { + labelIndexSet = true; + SetLabelIndexes(); + } + // now make two passes through the try block to 1) see if all leave + // opcodes that leave the try block do a synchronized block exit + // and 2) patch out the synchronized block exit + for (int pass = 0; pass < 2; pass++) + { + for (int j = start; j < i; j++) + { + if (code[j].opcode == OpCodes.Leave) + { + int target = code[j].Label.Temp; + if (target < start || target > i) + { + // check if the code preceding the leave matches the fault block + if ((code[j - 1].opcode == OpCodes.Pop || code[j - 1].opcode == OpCodes.Stloc) + && code[j - 2].pseudo == CodeType.MonitorExit + && code[j - 3].Match(code[i + 1])) + { + if (pass == 1) + { + // move the leave to the top of the sequence we're removing + code[j - 3] = code[j - 1]; + code[j - 2] = code[j - 0]; + code[j - 1] = new OpCodeWrapper(CodeType.Unreachable, CodeTypeFlags.None); + code[j - 0] = new OpCodeWrapper(CodeType.Unreachable, CodeTypeFlags.None); + } + } + else if (code[j - 1].pseudo == CodeType.MonitorExit + && code[j - 2].Match(code[i + 1])) + { + if (pass == 1) + { + // move the leave to the top of the sequence we're removing + code[j - 2] = code[j]; + code[j - 1] = new OpCodeWrapper(CodeType.Unreachable, CodeTypeFlags.None); + code[j - 0] = new OpCodeWrapper(CodeType.Unreachable, CodeTypeFlags.None); + } + } + else + { + goto fail; + } + } + } + } + } + // if we end up here, all leaves have been successfully patched, + // so now we turn the BeginFaultBlock into a BeginFinallyBlock + code[beginFault] = new OpCodeWrapper(CodeType.BeginFinallyBlock, CodeTypeFlags.None); + fail: ; + } + goto case CodeType.BeginFinallyBlock; + } + break; + case CodeType.EndExceptionBlock: + nest--; + break; + } + } + } + + private void RemoveRedundantMemoryBarriers() + { + int lastMemoryBarrier = -1; + for (int i = 0; i < code.Count; i++) + { + switch (code[i].pseudo) + { + case CodeType.MemoryBarrier: + if (lastMemoryBarrier != -1) + { + code.RemoveAt(lastMemoryBarrier); + i--; + } + lastMemoryBarrier = i; + break; + case CodeType.OpCode: + if (code[i].opcode == OpCodes.Volatile) + { + if (code[i + 1].opcode != OpCodes.Stfld && code[i + 1].opcode != OpCodes.Stsfld) + { + lastMemoryBarrier = -1; + } + } + else if (code[i].opcode.FlowControl != FlowControl.Next) + { + lastMemoryBarrier = -1; + } + break; + } + } + } + + private static bool MatchLdarg(OpCodeWrapper opc, out short arg) + { + if (opc.opcode == OpCodes.Ldarg) + { + arg = opc.ValueInt16; + return true; + } + else if (opc.opcode == OpCodes.Ldarg_S) + { + arg = opc.ValueByte; + return true; + } + else if (opc.opcode == OpCodes.Ldarg_0) + { + arg = 0; + return true; + } + else if (opc.opcode == OpCodes.Ldarg_1) + { + arg = 1; + return true; + } + else if (opc.opcode == OpCodes.Ldarg_2) + { + arg = 2; + return true; + } + else if (opc.opcode == OpCodes.Ldarg_3) + { + arg = 3; + return true; + } + else + { + arg = -1; + return false; + } + } + + private bool IsBranchEqNe(OpCode opcode) + { + return opcode == OpCodes.Beq + || opcode == OpCodes.Bne_Un; + } + + private void CLRv4_x64_JIT_Workaround() + { + for (int i = 0; i < code.Count - 2; i++) + { + // This is a workaround for https://connect.microsoft.com/VisualStudio/feedback/details/566946/x64-jit-optimization-bug + // + // Testing shows that the bug appears to be very specific and requires a comparison of a method argument with zero. + // For example, the problem goes away when the method argument is first assigned to a local variable and then + // the comparison (and subsequent use) is done against the local variable. + // + // This means we only have to detect these specific patterns: + // + // ldc.i8 0x0 ldarg + // ldarg ldc.i8 0x0 + // beq/bne beq/bne + // + // The workaround is to replace ldarg with ldarga/ldind.i8. Looking at the generated code by the x86 and x64 JITs + // this appears to be as efficient as the ldarg and it avoids the x64 bug. + if (code[i].opcode == OpCodes.Ldc_I8 && code[i].ValueInt64 == 0) + { + short arg; + int m; + if (i > 0 && MatchLdarg(code[i - 1], out arg) && IsBranchEqNe(code[i + 1].opcode)) + { + m = i - 1; + } + else if (MatchLdarg(code[i + 1], out arg) && IsBranchEqNe(code[i + 2].opcode)) + { + m = i + 1; + } + else + { + continue; + } + code[m] = new OpCodeWrapper(OpCodes.Ldarga, arg); + code.Insert(m + 1, new OpCodeWrapper(OpCodes.Ldind_I8, null)); + } + } + } + + [Conditional("CHECK_INVARIANTS")] + private void CheckInvariants() + { + CheckInvariantBranchInOrOutOfBlocks(); + CheckInvariantOpCodeUsage(); + CheckInvariantLocalVariables(); + } + + private void CheckInvariantBranchInOrOutOfBlocks() + { + /* + * We maintain an invariant that a branch (other than an explicit leave) + * can never branch out or into an exception block (try or handler). + * This is a stronger invariant than requirement by MSIL, because + * we also disallow the following sequence: + * + * Br Label0 + * ... + * BeginExceptionBlock + * Label0: + * ... + * Br Label0 + * + * This should be rewritten as: + * + * Br Label0 + * ... + * Label0: + * BeginExceptionBlock + * Label1: + * ... + * Br Label1 + */ + int blockId = 0; + int nextBlockId = 1; + Stack blocks = new Stack(); + for (int i = 0; i < code.Count; i++) + { + switch (code[i].pseudo) + { + case CodeType.Label: + code[i].Label.Temp = blockId; + break; + case CodeType.BeginExceptionBlock: + blocks.Push(blockId); + goto case CodeType.BeginFinallyBlock; + case CodeType.BeginFinallyBlock: + case CodeType.BeginFaultBlock: + case CodeType.BeginCatchBlock: + blockId = nextBlockId++; + break; + case CodeType.EndExceptionBlock: + blockId = blocks.Pop(); + break; + } + } + if (blocks.Count != 0) + { + throw new InvalidOperationException("Unbalanced exception blocks"); + } + blockId = 0; + nextBlockId = 1; + for (int i = 0; i < code.Count; i++) + { + switch (code[i].pseudo) + { + case CodeType.OpCode: + if (code[i].HasLabel + && code[i].opcode != OpCodes.Leave + && code[i].Label.Temp != blockId) + { + DumpMethod(); + throw new InvalidOperationException("Invalid branch " + code[i].opcode.Name + " at offset " + i + " from block " + blockId + " to " + code[i].Label.Temp); + } + break; + case CodeType.BeginExceptionBlock: + blocks.Push(blockId); + goto case CodeType.BeginFinallyBlock; + case CodeType.BeginFinallyBlock: + case CodeType.BeginFaultBlock: + case CodeType.BeginCatchBlock: + blockId = nextBlockId++; + break; + case CodeType.EndExceptionBlock: + blockId = blocks.Pop(); + break; + } + } + } + + private void CheckInvariantOpCodeUsage() + { + for (int i = 0; i < code.Count; i++) + { + switch (code[i].opcode.FlowControl) + { + case FlowControl.Branch: + case FlowControl.Cond_Branch: + if (!code[i].HasLabel && code[i].opcode != OpCodes.Switch) + { + throw new InvalidOperationException(); + } + break; + } + } + } + + private void CheckInvariantLocalVariables() + { + List locals = new List(); + for (int i = 0; i < code.Count; i++) + { + if (code[i].pseudo == CodeType.DeclareLocal) + { + if (locals.Contains(code[i].Local)) + { + throw new InvalidOperationException("Local variable used before declaration"); + } + } + else if (code[i].HasLocal) + { + locals.Add(code[i].Local); + } + } + } + + private void MoveLocalDeclarationToBeginScope() + { + int pos = 0; + for (int i = 0; i < code.Count; i++) + { + switch (code[i].pseudo) + { + case CodeType.BeginScope: + pos = i + 1; + break; + case CodeType.DeclareLocal: + OpCodeWrapper decl = code[i]; + code.RemoveAt(i); + code.Insert(pos++, decl); + break; + } + } + } + + internal void DoEmit() + { + OptimizePatterns(); + CLRv4_x64_JIT_Workaround(); + RemoveRedundantMemoryBarriers(); + + if (experimentalOptimizations) + { + CheckInvariants(); + MoveLocalDeclarationToBeginScope(); + + for (int i = 0; i < 4; i++) + { + RemoveJumpNext(); + CheckInvariants(); + ChaseBranches(); + CheckInvariants(); + RemoveSingletonBranches(); + CheckInvariants(); + RemoveUnusedLabels(); + CheckInvariants(); + SortPseudoOpCodes(); + CheckInvariants(); + AnnihilatePops(); + CheckInvariants(); + AnnihilateStoreReleaseTempLocals(); + CheckInvariants(); + DeduplicateBranchSourceTargetCode(); + CheckInvariants(); + OptimizeStackTransfer(); + CheckInvariants(); + MergeExceptionBlocks(); + CheckInvariants(); + ConvertSynchronizedFaultToFinally(); + CheckInvariants(); + RemoveDeadCode(); + CheckInvariants(); + } + } + +#if STATIC_COMPILER + OptimizeEncodings(); + OptimizeBranchSizes(); +#endif + + int ilOffset = 0; + int lineNumber = -1; + for (int i = 0; i < code.Count; i++) + { + code[i].RealEmit(ilOffset, this, ref lineNumber); +#if STATIC_COMPILER || NET_4_0 + ilOffset = ilgen_real.ILOffset; +#else + ilOffset += code[i].Size; +#endif + } + } + + internal void DumpMethod() + { + Dictionary labelIndexes = new Dictionary(); + for (int i = 0; i < code.Count; i++) + { + if (code[i].pseudo == CodeType.Label) + { + labelIndexes.Add(code[i].Label, i); + } + } + Console.WriteLine("======================"); + for (int i = 0; i < code.Count; i++) + { + if (code[i].pseudo == CodeType.OpCode) + { + Console.Write(" " + code[i].opcode.Name); + if (code[i].HasLabel) + { + Console.Write(" label" + labelIndexes[code[i].Label]); + } + else if (code[i].opcode == OpCodes.Ldarg_S || code[i].opcode == OpCodes.Ldarga_S) + { + Console.Write(" " + code[i].ValueByte); + } + else if (code[i].opcode == OpCodes.Ldarg || code[i].opcode == OpCodes.Ldarga) + { + Console.Write(" " + code[i].ValueInt16); + } + else if (code[i].opcode == OpCodes.Isinst || code[i].opcode == OpCodes.Castclass || code[i].opcode == OpCodes.Box || code[i].opcode == OpCodes.Unbox || code[i].opcode == OpCodes.Ldobj || code[i].opcode == OpCodes.Newarr) + { + Console.Write(" " + code[i].Type); + } + else if (code[i].opcode == OpCodes.Call || code[i].opcode == OpCodes.Callvirt) + { + Console.Write(" " + code[i].MethodBase); + } + else if (code[i].opcode == OpCodes.Ldfld || code[i].opcode == OpCodes.Ldsfld || code[i].opcode == OpCodes.Stfld || code[i].opcode == OpCodes.Stsfld) + { + Console.Write(" " + code[i].FieldInfo); + } + else if (code[i].opcode == OpCodes.Ldc_I4) + { + Console.Write(" " + code[i].ValueInt32); + } + else if (code[i].opcode == OpCodes.Ldloc || code[i].opcode == OpCodes.Stloc) + { + Console.Write(" " + code[i].Local.__LocalIndex); + } + Console.WriteLine(); + } + else if (code[i].pseudo == CodeType.Label) + { + Console.WriteLine("label{0}: // temp = {1}", i, code[i].Label.Temp); + } + else if (code[i].pseudo == CodeType.DeclareLocal) + { + Console.WriteLine("local #{0} = {1}", code[i].Local.__LocalIndex, code[i].Local.LocalType); + } + else + { + Console.WriteLine(code[i]); + } + } + } + + internal void DefineSymbolDocument(ModuleBuilder module, string url, Guid language, Guid languageVendor, Guid documentType) + { + symbols = module.DefineDocument(url, language, languageVendor, documentType); + } + + internal CodeEmitterLocal UnsafeAllocTempLocal(Type type) + { + int free = -1; + for (int i = 0; i < tempLocals.Length; i++) + { + CodeEmitterLocal lb = tempLocals[i]; + if (lb == null) + { + if (free == -1) + { + free = i; + } + } + else if (lb.LocalType == type) + { + return lb; + } + } + CodeEmitterLocal lb1 = DeclareLocal(type); + if (free != -1) + { + tempLocals[free] = lb1; + } + return lb1; + } + + internal CodeEmitterLocal AllocTempLocal(Type type) + { + for (int i = 0; i < tempLocals.Length; i++) + { + CodeEmitterLocal lb = tempLocals[i]; + if (lb != null && lb.LocalType == type) + { + tempLocals[i] = null; + return lb; + } + } + return new CodeEmitterLocal(type); + } + + internal void ReleaseTempLocal(CodeEmitterLocal lb) + { + EmitPseudoOpCode(CodeType.ReleaseTempLocal, lb); + for (int i = 0; i < tempLocals.Length; i++) + { + if (tempLocals[i] == null) + { + tempLocals[i] = lb; + break; + } + } + } + + internal void BeginCatchBlock(Type exceptionType) + { + EmitPseudoOpCode(CodeType.BeginCatchBlock, exceptionType); + } + + internal void BeginExceptionBlock() + { +#if !STATIC_COMPILER + exceptionStack.Push(inFinally); + inFinally = false; +#endif + EmitPseudoOpCode(CodeType.BeginExceptionBlock, null); + } + + internal void BeginFaultBlock() + { +#if !STATIC_COMPILER + inFinally = true; +#endif + EmitPseudoOpCode(CodeType.BeginFaultBlock, null); + } + + internal void BeginFinallyBlock() + { +#if !STATIC_COMPILER + inFinally = true; +#endif + EmitPseudoOpCode(CodeType.BeginFinallyBlock, null); + } + + internal void BeginScope() + { + EmitPseudoOpCode(CodeType.BeginScope, null); + } + + internal CodeEmitterLocal DeclareLocal(Type localType) + { + CodeEmitterLocal local = new CodeEmitterLocal(localType); + EmitPseudoOpCode(CodeType.DeclareLocal, local); + return local; + } + + internal CodeEmitterLabel DefineLabel() + { + CodeEmitterLabel label = new CodeEmitterLabel(ilgen_real.DefineLabel()); +#if LABELCHECK + labels.Add(label, new System.Diagnostics.StackFrame(1, true)); +#endif + return label; + } + + internal void Emit(OpCode opcode) + { + EmitOpCode(opcode, null); + } + + internal void EmitUnaligned(byte alignment) + { + EmitOpCode(OpCodes.Unaligned, alignment); + } + + internal void Emit(OpCode opcode, MethodBase mb) + { + EmitOpCode(opcode, mb); + } + + internal void EmitLdc_R8(double arg) + { + EmitOpCode(OpCodes.Ldc_R8, arg); + } + + internal void Emit(OpCode opcode, FieldInfo field) + { + EmitOpCode(opcode, field); + } + + internal void EmitLdarg(int arg) + { + Debug.Assert(0 <= arg && arg < 65536); + switch (arg) + { + case 0: + EmitOpCode(OpCodes.Ldarg_0, null); + break; + case 1: + EmitOpCode(OpCodes.Ldarg_1, null); + break; + case 2: + EmitOpCode(OpCodes.Ldarg_2, null); + break; + case 3: + EmitOpCode(OpCodes.Ldarg_3, null); + break; + default: + if (arg < 256) + { + EmitOpCode(OpCodes.Ldarg_S, (byte)arg); + } + else + { + EmitOpCode(OpCodes.Ldarg, (short)arg); + } + break; + } + } + + internal void EmitLdarga(int arg) + { + Debug.Assert(0 <= arg && arg < 65536); + if (arg < 256) + { + EmitOpCode(OpCodes.Ldarga_S, (byte)arg); + } + else + { + EmitOpCode(OpCodes.Ldarga, (short)arg); + } + } + + internal void EmitStarg(int arg) + { + Debug.Assert(0 <= arg && arg < 65536); + if (arg < 256) + { + EmitOpCode(OpCodes.Starg_S, (byte)arg); + } + else + { + EmitOpCode(OpCodes.Starg, (short)arg); + } + } + + internal void EmitLdc_I8(long arg) + { + EmitOpCode(OpCodes.Ldc_I8, arg); + } + + internal void EmitBr(CodeEmitterLabel label) + { + EmitOpCode(OpCodes.Br, label); + } + + internal void EmitBeq(CodeEmitterLabel label) + { + EmitOpCode(OpCodes.Beq, label); + } + + internal void EmitBne_Un(CodeEmitterLabel label) + { + EmitOpCode(OpCodes.Bne_Un, label); + } + + internal void EmitBle_Un(CodeEmitterLabel label) + { + EmitOpCode(OpCodes.Ble_Un, label); + } + + internal void EmitBlt_Un(CodeEmitterLabel label) + { + EmitOpCode(OpCodes.Blt_Un, label); + } + + internal void EmitBge_Un(CodeEmitterLabel label) + { + EmitOpCode(OpCodes.Bge_Un, label); + } + + internal void EmitBle(CodeEmitterLabel label) + { + EmitOpCode(OpCodes.Ble, label); + } + + internal void EmitBlt(CodeEmitterLabel label) + { + EmitOpCode(OpCodes.Blt, label); + } + + internal void EmitBge(CodeEmitterLabel label) + { + EmitOpCode(OpCodes.Bge, label); + } + + internal void EmitBgt(CodeEmitterLabel label) + { + EmitOpCode(OpCodes.Bgt, label); + } + + internal void EmitBrtrue(CodeEmitterLabel label) + { + EmitOpCode(OpCodes.Brtrue, label); + } + + internal void EmitBrfalse(CodeEmitterLabel label) + { + EmitOpCode(OpCodes.Brfalse, label); + } + + internal void EmitLeave(CodeEmitterLabel label) + { + EmitOpCode(OpCodes.Leave, label); + } + + internal void EmitSwitch(CodeEmitterLabel[] labels) + { + EmitOpCode(OpCodes.Switch, labels); + } + + internal void Emit(OpCode opcode, CodeEmitterLocal local) + { + EmitOpCode(opcode, local); + } + + internal void EmitLdc_R4(float arg) + { + EmitOpCode(OpCodes.Ldc_R4, arg); + } + + internal void Emit(OpCode opcode, string arg) + { + EmitOpCode(opcode, arg); + } + + internal void Emit(OpCode opcode, Type cls) + { + EmitOpCode(opcode, cls); + } + + internal void EmitCalli(OpCode opcode, CallingConvention unmanagedCallConv, Type returnType, Type[] parameterTypes) + { + EmitOpCode(opcode, new CalliWrapper(unmanagedCallConv, returnType, parameterTypes)); + } + + internal void EndExceptionBlock() + { +#if STATIC_COMPILER + EmitPseudoOpCode(CodeType.EndExceptionBlock, null); +#else + EmitPseudoOpCode(CodeType.EndExceptionBlock, inFinally ? CodeTypeFlags.EndFaultOrFinally : CodeTypeFlags.None); + inFinally = exceptionStack.Pop(); +#endif + } + + internal void EndScope() + { + EmitPseudoOpCode(CodeType.EndScope, null); + } + + internal void MarkLabel(CodeEmitterLabel loc) + { +#if LABELCHECK + labels.Remove(loc); +#endif + EmitPseudoOpCode(CodeType.Label, loc); + } + + internal void ThrowException(Type excType) + { + Emit(OpCodes.Newobj, excType.GetConstructor(Type.EmptyTypes)); + Emit(OpCodes.Throw); + } + + internal void SetLineNumber(ushort line) + { + if (symbols != null) + { + EmitPseudoOpCode(CodeType.SequencePoint, (int)line); + } + EmitPseudoOpCode(CodeType.LineNumber, (int)line); + } + + internal byte[] GetLineNumberTable() + { + return linenums == null ? null : linenums.ToArray(); + } + +#if STATIC_COMPILER + internal void EmitLineNumberTable(MethodBuilder mb) + { + if(linenums != null) + { + AttributeHelper.SetLineNumberTable(mb, linenums); + } + } +#endif // STATIC_COMPILER + + internal void EmitThrow(string dottedClassName) + { + TypeWrapper exception = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedName(dottedClassName); + MethodWrapper mw = exception.GetMethodWrapper("", "()V", false); + mw.Link(); + mw.EmitNewobj(this); + Emit(OpCodes.Throw); + } + + internal void EmitThrow(string dottedClassName, string message) + { + TypeWrapper exception = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedName(dottedClassName); + Emit(OpCodes.Ldstr, message); + MethodWrapper mw = exception.GetMethodWrapper("", "(Ljava.lang.String;)V", false); + mw.Link(); + mw.EmitNewobj(this); + Emit(OpCodes.Throw); + } + + internal void EmitNullCheck() + { + // I think this is the most efficient way to generate a NullReferenceException if the reference is null + Emit(OpCodes.Ldvirtftn, objectToString); + Emit(OpCodes.Pop); + } + + internal void EmitCastclass(Type type) + { + if (verboseCastFailure != null) + { + CodeEmitterLocal lb = DeclareLocal(Types.Object); + Emit(OpCodes.Stloc, lb); + Emit(OpCodes.Ldloc, lb); + Emit(OpCodes.Isinst, type); + Emit(OpCodes.Dup); + CodeEmitterLabel ok = DefineLabel(); + EmitBrtrue(ok); + Emit(OpCodes.Ldloc, lb); + EmitBrfalse(ok); // handle null + Emit(OpCodes.Ldtoken, type); + Emit(OpCodes.Ldloc, lb); + Emit(OpCodes.Call, verboseCastFailure); + MarkLabel(ok); + } + else + { + Emit(OpCodes.Castclass, type); + } + } + + // This is basically the same as Castclass, except that it + // throws an IncompatibleClassChangeError on failure. + internal void EmitAssertType(Type type) + { + CodeEmitterLabel isnull = DefineLabel(); + Emit(OpCodes.Dup); + EmitBrfalse(isnull); + Emit(OpCodes.Isinst, type); + Emit(OpCodes.Dup); + CodeEmitterLabel ok = DefineLabel(); + EmitBrtrue(ok); + EmitThrow("java.lang.IncompatibleClassChangeError"); + MarkLabel(isnull); + Emit(OpCodes.Pop); + Emit(OpCodes.Ldnull); + MarkLabel(ok); + } + + internal void EmitUnboxSpecial(Type type) + { + // NOTE if the reference is null, we treat it as a default instance of the value type. + Emit(OpCodes.Dup); + CodeEmitterLabel label1 = DefineLabel(); + EmitBrtrue(label1); + Emit(OpCodes.Pop); + CodeEmitterLocal local = AllocTempLocal(type); + Emit(OpCodes.Ldloca, local); + Emit(OpCodes.Initobj, type); + Emit(OpCodes.Ldloc, local); + ReleaseTempLocal(local); + CodeEmitterLabel label2 = DefineLabel(); + EmitBr(label2); + MarkLabel(label1); + Emit(OpCodes.Unbox, type); + Emit(OpCodes.Ldobj, type); + MarkLabel(label2); + } + + internal void EmitLdc_I4(int i) + { + EmitOpCode(OpCodes.Ldc_I4, i); + } + + internal void Emit_idiv() + { + // we need to special case dividing by -1, because the CLR div instruction + // throws an OverflowException when dividing Int32.MinValue by -1, and + // Java just silently overflows + Emit(OpCodes.Dup); + Emit(OpCodes.Ldc_I4_M1); + CodeEmitterLabel label = DefineLabel(); + EmitBne_Un(label); + Emit(OpCodes.Pop); + Emit(OpCodes.Neg); + CodeEmitterLabel label2 = DefineLabel(); + EmitBr(label2); + MarkLabel(label); + Emit(OpCodes.Div); + MarkLabel(label2); + } + + internal void Emit_ldiv() + { + // we need to special case dividing by -1, because the CLR div instruction + // throws an OverflowException when dividing Int32.MinValue by -1, and + // Java just silently overflows + Emit(OpCodes.Dup); + Emit(OpCodes.Ldc_I4_M1); + Emit(OpCodes.Conv_I8); + CodeEmitterLabel label = DefineLabel(); + EmitBne_Un(label); + Emit(OpCodes.Pop); + Emit(OpCodes.Neg); + CodeEmitterLabel label2 = DefineLabel(); + EmitBr(label2); + MarkLabel(label); + Emit(OpCodes.Div); + MarkLabel(label2); + } + + internal void Emit_instanceof(Type type) + { + Emit(OpCodes.Isinst, type); + Emit(OpCodes.Ldnull); + Emit(OpCodes.Cgt_Un); + } + + internal enum Comparison + { + LessOrEqual, + LessThan, + GreaterOrEqual, + GreaterThan + } + + internal void Emit_if_le_lt_ge_gt(Comparison comp, CodeEmitterLabel label) + { + // don't change this Ldc_I4_0 to Ldc_I4(0) because the optimizer recognizes + // only this specific pattern + Emit(OpCodes.Ldc_I4_0); + switch (comp) + { + case Comparison.LessOrEqual: + EmitBle(label); + break; + case Comparison.LessThan: + EmitBlt(label); + break; + case Comparison.GreaterOrEqual: + EmitBge(label); + break; + case Comparison.GreaterThan: + EmitBgt(label); + break; + } + } + + private void EmitCmp(Type type, OpCode cmp1, OpCode cmp2) + { + CodeEmitterLocal value1 = AllocTempLocal(type); + CodeEmitterLocal value2 = AllocTempLocal(type); + Emit(OpCodes.Stloc, value2); + Emit(OpCodes.Stloc, value1); + Emit(OpCodes.Ldloc, value1); + Emit(OpCodes.Ldloc, value2); + Emit(cmp1); + Emit(OpCodes.Ldloc, value1); + Emit(OpCodes.Ldloc, value2); + Emit(cmp2); + Emit(OpCodes.Sub); + ReleaseTempLocal(value2); + ReleaseTempLocal(value1); + } + + internal void Emit_lcmp() + { + EmitCmp(Types.Int64, OpCodes.Cgt, OpCodes.Clt); + } + + internal void Emit_fcmpl() + { + EmitCmp(Types.Single, OpCodes.Cgt, OpCodes.Clt_Un); + } + + internal void Emit_fcmpg() + { + EmitCmp(Types.Single, OpCodes.Cgt_Un, OpCodes.Clt); + } + + internal void Emit_dcmpl() + { + EmitCmp(Types.Double, OpCodes.Cgt, OpCodes.Clt_Un); + } + + internal void Emit_dcmpg() + { + EmitCmp(Types.Double, OpCodes.Cgt_Un, OpCodes.Clt); + } + + internal void Emit_And_I4(int v) + { + EmitLdc_I4(v); + Emit(OpCodes.And); + } + + internal void CheckLabels() + { +#if LABELCHECK + foreach(System.Diagnostics.StackFrame frame in labels.Values) + { + string name = frame.GetFileName() + ":" + frame.GetFileLineNumber(); + IKVM.Internal.JVM.CriticalFailure("Label failure: " + name, null); + } +#endif + } + + internal void EmitMemoryBarrier() + { + EmitPseudoOpCode(CodeType.MemoryBarrier, null); + } + + internal void EmitTailCallPrevention() + { + EmitPseudoOpCode(CodeType.TailCallPrevention, null); + } + + internal void EmitClearStack() + { + EmitPseudoOpCode(CodeType.ClearStack, null); + } + + internal void EmitMonitorEnter() + { + EmitPseudoOpCode(CodeType.MonitorEnter, null); + } + + internal void EmitMonitorExit() + { + EmitPseudoOpCode(CodeType.MonitorExit, null); + } + } +} diff --git a/runtime/CoreClasses.cs b/runtime/CoreClasses.cs new file mode 100644 index 0000000..8f555a3 --- /dev/null +++ b/runtime/CoreClasses.cs @@ -0,0 +1,141 @@ +/* + Copyright (C) 2004-2015 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +namespace IKVM.Internal +{ + internal static class CoreClasses + { + internal static class cli + { + internal static class System + { + internal static class Object + { + // NOTE we have a dummy static initializer, to make sure we don't get the beforeFieldInit attribute + // (we don't want the classes to be loaded prematurely, because they might not be available then) + static Object() { } + internal static readonly TypeWrapper Wrapper = DotNetTypeWrapper.GetWrapperFromDotNetType(Types.Object); + } + + internal static class Exception + { + // NOTE we have a dummy static initializer, to make sure we don't get the beforeFieldInit attribute + // (we don't want the classes to be loaded prematurely, because they might not be available then) + static Exception() { } + internal static readonly TypeWrapper Wrapper = DotNetTypeWrapper.GetWrapperFromDotNetType(Types.Exception); + } + } + } + + internal static class ikvm + { + internal static class @internal + { + internal static class CallerID + { + // NOTE we have a dummy static initializer, to make sure we don't get the beforeFieldInit attribute + // (we don't want the classes to be loaded prematurely, because they might not be available then) + static CallerID() { } + internal static readonly TypeWrapper Wrapper = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.CallerID"); + } + } + } + + internal static class java + { + internal static class io + { + internal static class Serializable + { + // NOTE we have a dummy static initializer, to make sure we don't get the beforeFieldInit attribute + // (we don't want the classes to be loaded prematurely, because they might not be available then) + static Serializable() { } + internal static readonly TypeWrapper Wrapper = ClassLoaderWrapper.LoadClassCritical("java.io.Serializable"); + } + } + + internal static class lang + { + internal static class Object + { + // NOTE we have a dummy static initializer, to make sure we don't get the beforeFieldInit attribute + // (we don't want the classes to be loaded prematurely, because they might not be available then) + static Object() {} + internal static readonly TypeWrapper Wrapper = ClassLoaderWrapper.LoadClassCritical("java.lang.Object"); + } + + internal static class String + { + // NOTE we have a dummy static initializer, to make sure we don't get the beforeFieldInit attribute + // (we don't want the classes to be loaded prematurely, because they might not be available then) + static String() {} + internal static readonly TypeWrapper Wrapper = ClassLoaderWrapper.LoadClassCritical("java.lang.String"); + } + + internal static class Class + { + // NOTE we have a dummy static initializer, to make sure we don't get the beforeFieldInit attribute + // (we don't want the classes to be loaded prematurely, because they might not be available then) + static Class() {} + internal static readonly TypeWrapper Wrapper = ClassLoaderWrapper.LoadClassCritical("java.lang.Class"); + } + + internal static class Cloneable + { + // NOTE we have a dummy static initializer, to make sure we don't get the beforeFieldInit attribute + // (we don't want the classes to be loaded prematurely, because they might not be available then) + static Cloneable() {} + internal static readonly TypeWrapper Wrapper = ClassLoaderWrapper.LoadClassCritical("java.lang.Cloneable"); + } + + internal static class Throwable + { + // NOTE we have a dummy static initializer, to make sure we don't get the beforeFieldInit attribute + // (we don't want the classes to be loaded prematurely, because they might not be available then) + static Throwable() {} + internal static readonly TypeWrapper Wrapper = ClassLoaderWrapper.LoadClassCritical("java.lang.Throwable"); + } + + internal static class invoke + { + internal static class MethodHandle + { + // NOTE we have a dummy static initializer, to make sure we don't get the beforeFieldInit attribute + // (we don't want the classes to be loaded prematurely, because they might not be available then) + static MethodHandle() { } + internal static readonly TypeWrapper Wrapper = ClassLoaderWrapper.LoadClassCritical("java.lang.invoke.MethodHandle"); + } + + internal static class MethodType + { + // NOTE we have a dummy static initializer, to make sure we don't get the beforeFieldInit attribute + // (we don't want the classes to be loaded prematurely, because they might not be available then) + static MethodType() { } + internal static readonly TypeWrapper Wrapper = ClassLoaderWrapper.LoadClassCritical("java.lang.invoke.MethodType"); + } + } + } + } + } +} diff --git a/runtime/DotNetTypeWrapper.cs b/runtime/DotNetTypeWrapper.cs new file mode 100644 index 0000000..a180901 --- /dev/null +++ b/runtime/DotNetTypeWrapper.cs @@ -0,0 +1,2812 @@ +/* + Copyright (C) 2002-2015 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +#if STATIC_COMPILER || STUB_GENERATOR +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif +using System.Diagnostics; +using System.Security; +using System.Security.Permissions; +using IKVM.Attributes; + +namespace IKVM.Internal +{ + sealed class DotNetTypeWrapper : TypeWrapper + { + private const string NamePrefix = "cli."; + internal const string DelegateInterfaceSuffix = "$Method"; + internal const string AttributeAnnotationSuffix = "$Annotation"; + internal const string AttributeAnnotationReturnValueSuffix = "$__ReturnValue"; + internal const string AttributeAnnotationMultipleSuffix = "$__Multiple"; + internal const string EnumEnumSuffix = "$__Enum"; + internal const string GenericEnumEnumTypeName = "ikvm.internal.EnumEnum`1"; + internal const string GenericDelegateInterfaceTypeName = "ikvm.internal.DelegateInterface`1"; + internal const string GenericAttributeAnnotationTypeName = "ikvm.internal.AttributeAnnotation`1"; + internal const string GenericAttributeAnnotationReturnValueTypeName = "ikvm.internal.AttributeAnnotationReturnValue`1"; + internal const string GenericAttributeAnnotationMultipleTypeName = "ikvm.internal.AttributeAnnotationMultiple`1"; + private static readonly Dictionary types = new Dictionary(); + private readonly Type type; + private TypeWrapper baseTypeWrapper; + private volatile TypeWrapper[] innerClasses; + private TypeWrapper outerClass; + private volatile TypeWrapper[] interfaces; + + private static Modifiers GetModifiers(Type type) + { + Modifiers modifiers = 0; + if (type.IsPublic) + { + modifiers |= Modifiers.Public; + } + else if (type.IsNestedPublic) + { + modifiers |= Modifiers.Static; + if (type.IsVisible) + { + modifiers |= Modifiers.Public; + } + } + else if (type.IsNestedPrivate) + { + modifiers |= Modifiers.Private | Modifiers.Static; + } + else if (type.IsNestedFamily || type.IsNestedFamORAssem) + { + modifiers |= Modifiers.Protected | Modifiers.Static; + } + else if (type.IsNestedAssembly || type.IsNestedFamANDAssem) + { + modifiers |= Modifiers.Static; + } + + if (type.IsSealed) + { + modifiers |= Modifiers.Final; + } + else if (type.IsAbstract) // we can't be abstract if we're final + { + modifiers |= Modifiers.Abstract; + } + if (type.IsInterface) + { + modifiers |= Modifiers.Interface; + } + return modifiers; + } + + // NOTE when this is called on a remapped type, the "warped" underlying type name is returned. + // E.g. GetName(typeof(object)) returns "cli.System.Object". + internal static string GetName(Type type) + { + Debug.Assert(!type.Name.EndsWith("[]") && !AttributeHelper.IsJavaModule(type.Module)); + + string name = type.FullName; + + if (name == null) + { + // generic type parameters don't have a full name + return null; + } + + if (type.IsGenericType && !type.ContainsGenericParameters) + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + sb.Append(MangleTypeName(type.GetGenericTypeDefinition().FullName)); + sb.Append("_$$$_"); + string sep = ""; + foreach (Type t1 in type.GetGenericArguments()) + { + Type t = t1; + sb.Append(sep); + // NOTE we can't use ClassLoaderWrapper.GetWrapperFromType() here to get t's name, + // because we might be resolving a generic type that refers to a type that is in + // the process of being constructed. + // + // For example: + // class Base { } + // class Derived : Base { } + // + while (ReflectUtil.IsVector(t)) + { + t = t.GetElementType(); + sb.Append('A'); + } + if (PrimitiveTypeWrapper.IsPrimitiveType(t)) + { + sb.Append(ClassLoaderWrapper.GetWrapperFromType(t).SigName); + } + else + { + string s; + if (ClassLoaderWrapper.IsRemappedType(t) || AttributeHelper.IsJavaModule(t.Module)) + { + s = ClassLoaderWrapper.GetWrapperFromType(t).Name; + } + else + { + s = DotNetTypeWrapper.GetName(t); + } + // only do the mangling for non-generic types (because we don't want to convert + // the double underscores in two adjacent _$$$_ or _$$$$_ markers) + if (s.IndexOf("_$$$_") == -1) + { + s = s.Replace("__", "$$005F$$005F"); + s = s.Replace(".", "__"); + } + sb.Append('L').Append(s); + } + sep = "_$$_"; + } + sb.Append("_$$$$_"); + return sb.ToString(); + } + + if (AttributeHelper.IsNoPackagePrefix(type) + && name.IndexOf('$') == -1) + { + return name.Replace('+', '$'); + } + + return MangleTypeName(name); + } + + private static string MangleTypeName(string name) + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(NamePrefix, NamePrefix.Length + name.Length); + bool escape = false; + bool nested = false; + for (int i = 0; i < name.Length; i++) + { + char c = name[i]; + if (c == '+' && !escape && (sb.Length == 0 || sb[sb.Length - 1] != '$')) + { + nested = true; + sb.Append('$'); + } + else if ("_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".IndexOf(c) != -1 + || (c == '.' && !escape && !nested)) + { + sb.Append(c); + } + else + { + sb.Append("$$"); + sb.Append(string.Format("{0:X4}", (int)c)); + } + if (c == '\\') + { + escape = !escape; + } + else + { + escape = false; + } + } + return sb.ToString(); + } + + // NOTE if the name is not a valid mangled type name, no demangling is done and the + // original string is returned + // NOTE we don't enforce canonical form, this is not required, because we cannot + // guarantee it for unprefixed names anyway, so the caller is responsible for + // ensuring that the original name was in fact the canonical name. + internal static string DemangleTypeName(string name) + { + if (!name.StartsWith(NamePrefix)) + { + return name.Replace('$', '+'); + } + System.Text.StringBuilder sb = new System.Text.StringBuilder(name.Length - NamePrefix.Length); + for (int i = NamePrefix.Length; i < name.Length; i++) + { + char c = name[i]; + if (c == '$') + { + if (i + 1 < name.Length && name[i + 1] != '$') + { + sb.Append('+'); + } + else + { + i++; + if (i + 5 > name.Length) + { + return name; + } + int digit0 = "0123456789ABCDEF".IndexOf(name[++i]); + int digit1 = "0123456789ABCDEF".IndexOf(name[++i]); + int digit2 = "0123456789ABCDEF".IndexOf(name[++i]); + int digit3 = "0123456789ABCDEF".IndexOf(name[++i]); + if (digit0 == -1 || digit1 == -1 || digit2 == -1 || digit3 == -1) + { + return name; + } + sb.Append((char)((digit0 << 12) + (digit1 << 8) + (digit2 << 4) + digit3)); + } + } + else + { + sb.Append(c); + } + } + return sb.ToString(); + } + + // TODO from a perf pov it may be better to allow creation of TypeWrappers, + // but to simply make sure they don't have ClassObject + internal static bool IsAllowedOutside(Type type) + { + // SECURITY we never expose types from IKVM.Runtime, because doing so would lead to a security hole, + // since the reflection implementation lives inside this assembly, all internal members would + // be accessible through Java reflection. +#if !FIRST_PASS && !STATIC_COMPILER && !STUB_GENERATOR + if (type.Assembly == typeof(DotNetTypeWrapper).Assembly) + { + return false; + } + if (type.Assembly == Java_java_lang_SecurityManager.jniAssembly) + { + return false; + } +#endif + return true; + } + + // We allow open generic types to be visible to Java code as very limited classes (or interfaces). + // They are always package private and have the abstract and final modifiers set, this makes them + // inaccessible and invalid from a Java point of view. The intent is to avoid any usage of these + // classes. They exist solely for the purpose of stack walking, because the .NET runtime will report + // open generic types when walking the stack (as a performance optimization). We cannot (reliably) map + // these classes to their instantiations, so we report the open generic type class instead. + // Note also that these classes can only be used as a "handle" to the type, they expose no members, + // don't implement any interfaces and the base class is always object. + private sealed class OpenGenericTypeWrapper : TypeWrapper + { + private readonly Type type; + + private static Modifiers GetModifiers(Type type) + { + Modifiers modifiers = Modifiers.Abstract | Modifiers.Final; + if (type.IsInterface) + { + modifiers |= Modifiers.Interface; + } + return modifiers; + } + + internal OpenGenericTypeWrapper(Type type, string name) + : base(TypeFlags.None, GetModifiers(type), name) + { + this.type = type; + } + + internal override TypeWrapper BaseTypeWrapper + { + get { return type.IsInterface ? null : CoreClasses.java.lang.Object.Wrapper; } + } + + internal override Type TypeAsTBD + { + get { return type; } + } + + internal override ClassLoaderWrapper GetClassLoader() + { + return AssemblyClassLoader.FromAssembly(type.Assembly); + } + + protected override void LazyPublishMembers() + { + SetFields(FieldWrapper.EmptyArray); + SetMethods(MethodWrapper.EmptyArray); + } + } + + internal abstract class FakeTypeWrapper : TypeWrapper + { + private readonly TypeWrapper baseWrapper; + + protected FakeTypeWrapper(Modifiers modifiers, string name, TypeWrapper baseWrapper) + : base(TypeFlags.None, modifiers, name) + { + this.baseWrapper = baseWrapper; + } + + internal sealed override TypeWrapper BaseTypeWrapper + { + get { return baseWrapper; } + } + + internal sealed override bool IsFakeNestedType + { + get { return true; } + } + + internal sealed override Modifiers ReflectiveModifiers + { + get { return Modifiers | Modifiers.Static; } + } + } + + private sealed class DelegateInnerClassTypeWrapper : FakeTypeWrapper + { + private readonly Type fakeType; + + internal DelegateInnerClassTypeWrapper(string name, Type delegateType) + : base(Modifiers.Public | Modifiers.Interface | Modifiers.Abstract, name, null) + { +#if STATIC_COMPILER || STUB_GENERATOR + this.fakeType = FakeTypes.GetDelegateType(delegateType); +#elif !FIRST_PASS + this.fakeType = typeof(ikvm.@internal.DelegateInterface<>).MakeGenericType(delegateType); +#endif + MethodInfo invoke = delegateType.GetMethod("Invoke"); + ParameterInfo[] parameters = invoke.GetParameters(); + TypeWrapper[] argTypeWrappers = new TypeWrapper[parameters.Length]; + System.Text.StringBuilder sb = new System.Text.StringBuilder("("); + MemberFlags flags = MemberFlags.None; + for (int i = 0; i < parameters.Length; i++) + { + Type parameterType = parameters[i].ParameterType; + if (parameterType.IsByRef) + { + flags |= MemberFlags.DelegateInvokeWithByRefParameter; + parameterType = ArrayTypeWrapper.MakeArrayType(parameterType.GetElementType(), 1); + } + argTypeWrappers[i] = ClassLoaderWrapper.GetWrapperFromType(parameterType); + sb.Append(argTypeWrappers[i].SigName); + } + TypeWrapper returnType = ClassLoaderWrapper.GetWrapperFromType(invoke.ReturnType); + sb.Append(")").Append(returnType.SigName); + MethodWrapper invokeMethod = new DynamicOnlyMethodWrapper(this, "Invoke", sb.ToString(), returnType, argTypeWrappers, flags); + SetMethods(new MethodWrapper[] { invokeMethod }); + SetFields(FieldWrapper.EmptyArray); + } + + internal override TypeWrapper DeclaringTypeWrapper + { + get + { + return ClassLoaderWrapper.GetWrapperFromType(fakeType.GetGenericArguments()[0]); + } + } + + internal override ClassLoaderWrapper GetClassLoader() + { + return DeclaringTypeWrapper.GetClassLoader(); + } + + internal override Type TypeAsTBD + { + get + { + return fakeType; + } + } + + internal override bool IsFastClassLiteralSafe + { + get { return true; } + } + + internal override MethodParametersEntry[] GetMethodParameters(MethodWrapper mw) + { + return DeclaringTypeWrapper.GetMethodParameters(DeclaringTypeWrapper.GetMethodWrapper(mw.Name, mw.Signature, false)); + } + } + + private class DynamicOnlyMethodWrapper : MethodWrapper + { + internal DynamicOnlyMethodWrapper(TypeWrapper declaringType, string name, string sig, TypeWrapper returnType, TypeWrapper[] parameterTypes, MemberFlags flags) + : base(declaringType, name, sig, null, returnType, parameterTypes, Modifiers.Public | Modifiers.Abstract, flags) + { + } + + internal sealed override bool IsDynamicOnly + { + get + { + return true; + } + } + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + [HideFromJava] + internal sealed override object Invoke(object obj, object[] args) + { + // a DynamicOnlyMethodWrapper is an interface method, but now that we've been called on an actual object instance, + // we can resolve to a real method and call that instead + TypeWrapper tw = TypeWrapper.FromClass(NativeCode.ikvm.runtime.Util.getClassFromObject(obj)); + MethodWrapper mw = tw.GetMethodWrapper(this.Name, this.Signature, true); + if (mw == null || mw.IsStatic) + { + throw new java.lang.AbstractMethodError(tw.Name + "." + this.Name + this.Signature); + } + if (!mw.IsPublic) + { + throw new java.lang.IllegalAccessError(tw.Name + "." + this.Name + this.Signature); + } + mw.Link(); + mw.ResolveMethod(); + return mw.Invoke(obj, args); + } +#endif // !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + } + + private sealed class EnumEnumTypeWrapper : FakeTypeWrapper + { + private readonly Type fakeType; + + internal EnumEnumTypeWrapper(string name, Type enumType) + : base(Modifiers.Public | Modifiers.Enum | Modifiers.Final, name, ClassLoaderWrapper.LoadClassCritical("java.lang.Enum")) + { +#if STATIC_COMPILER || STUB_GENERATOR + this.fakeType = FakeTypes.GetEnumType(enumType); +#elif !FIRST_PASS + this.fakeType = typeof(ikvm.@internal.EnumEnum<>).MakeGenericType(enumType); +#endif + } + +#if !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + internal object GetUnspecifiedValue() + { + return GetFieldWrapper("__unspecified", this.SigName).GetValue(null); + } +#endif + + private sealed class EnumFieldWrapper : FieldWrapper + { +#if !STATIC_COMPILER && !STUB_GENERATOR + private readonly int ordinal; + private object val; +#endif + + internal EnumFieldWrapper(TypeWrapper tw, string name, int ordinal) + : base(tw, tw, name, tw.SigName, Modifiers.Public | Modifiers.Static | Modifiers.Final | Modifiers.Enum, null, MemberFlags.None) + { +#if !STATIC_COMPILER && !STUB_GENERATOR + this.ordinal = ordinal; +#endif + } + +#if !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + internal override object GetValue(object obj) + { + if (val == null) + { + System.Threading.Interlocked.CompareExchange(ref val, Activator.CreateInstance(this.DeclaringType.TypeAsTBD, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, new object[] { this.Name, ordinal }, null), null); + } + return val; + } + + internal override void SetValue(object obj, object value) + { + } +#endif + +#if EMITTERS + protected override void EmitGetImpl(CodeEmitter ilgen) + { +#if STATIC_COMPILER + Type typeofByteCodeHelper = StaticCompiler.GetRuntimeType("IKVM.Runtime.ByteCodeHelper"); +#else + Type typeofByteCodeHelper = typeof(IKVM.Runtime.ByteCodeHelper); +#endif + ilgen.Emit(OpCodes.Ldstr, this.Name); + ilgen.Emit(OpCodes.Call, typeofByteCodeHelper.GetMethod("GetDotNetEnumField").MakeGenericMethod(this.DeclaringType.TypeAsBaseType)); + } + + protected override void EmitSetImpl(CodeEmitter ilgen) + { + } +#endif // EMITTERS + } + + private sealed class EnumValuesMethodWrapper : MethodWrapper + { + internal EnumValuesMethodWrapper(TypeWrapper declaringType) + : base(declaringType, "values", "()[" + declaringType.SigName, null, declaringType.MakeArrayType(1), TypeWrapper.EmptyArray, Modifiers.Public | Modifiers.Static, MemberFlags.None) + { + } + + internal override bool IsDynamicOnly + { + get + { + return true; + } + } + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + internal override object Invoke(object obj, object[] args) + { + FieldWrapper[] values = this.DeclaringType.GetFields(); + object[] array = (object[])Array.CreateInstance(this.DeclaringType.TypeAsArrayType, values.Length); + for (int i = 0; i < values.Length; i++) + { + array[i] = values[i].GetValue(null); + } + return array; + } +#endif // !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + } + + private sealed class EnumValueOfMethodWrapper : MethodWrapper + { + internal EnumValueOfMethodWrapper(TypeWrapper declaringType) + : base(declaringType, "valueOf", "(Ljava.lang.String;)" + declaringType.SigName, null, declaringType, new TypeWrapper[] { CoreClasses.java.lang.String.Wrapper }, Modifiers.Public | Modifiers.Static, MemberFlags.None) + { + } + + internal override bool IsDynamicOnly + { + get + { + return true; + } + } + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + internal override object Invoke(object obj, object[] args) + { + FieldWrapper[] values = this.DeclaringType.GetFields(); + for (int i = 0; i < values.Length; i++) + { + if (values[i].Name.Equals(args[0])) + { + return values[i].GetValue(null); + } + } + throw new java.lang.IllegalArgumentException("" + args[0]); + } +#endif // !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + } + + protected override void LazyPublishMembers() + { + List fields = new List(); + int ordinal = 0; + foreach (FieldInfo field in this.DeclaringTypeWrapper.TypeAsTBD.GetFields(BindingFlags.Static | BindingFlags.Public)) + { + if (field.IsLiteral) + { + fields.Add(new EnumFieldWrapper(this, field.Name, ordinal++)); + } + } + // TODO if the enum already has an __unspecified value, rename this one + fields.Add(new EnumFieldWrapper(this, "__unspecified", ordinal++)); + SetFields(fields.ToArray()); + SetMethods(new MethodWrapper[] { new EnumValuesMethodWrapper(this), new EnumValueOfMethodWrapper(this) }); + base.LazyPublishMembers(); + } + + internal override TypeWrapper DeclaringTypeWrapper + { + get + { + return ClassLoaderWrapper.GetWrapperFromType(fakeType.GetGenericArguments()[0]); + } + } + + internal override ClassLoaderWrapper GetClassLoader() + { + return DeclaringTypeWrapper.GetClassLoader(); + } + + internal override Type TypeAsTBD + { + get + { + return fakeType; + } + } + + internal override bool IsFastClassLiteralSafe + { + get { return true; } + } + } + + internal abstract class AttributeAnnotationTypeWrapperBase : FakeTypeWrapper + { + internal AttributeAnnotationTypeWrapperBase(string name) + : base(Modifiers.Public | Modifiers.Interface | Modifiers.Abstract | Modifiers.Annotation, name, null) + { + } + + internal sealed override ClassLoaderWrapper GetClassLoader() + { + return DeclaringTypeWrapper.GetClassLoader(); + } + + internal sealed override TypeWrapper[] Interfaces + { + get + { + return new TypeWrapper[] { ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedName("java.lang.annotation.Annotation") }; + } + } + + internal sealed override bool IsFastClassLiteralSafe + { + get { return true; } + } + + internal abstract AttributeTargets AttributeTargets { get; } + } + + private sealed class AttributeAnnotationTypeWrapper : AttributeAnnotationTypeWrapperBase + { + private readonly Type fakeType; + private readonly Type attributeType; + private volatile TypeWrapper[] innerClasses; + + internal AttributeAnnotationTypeWrapper(string name, Type attributeType) + : base(name) + { +#if STATIC_COMPILER || STUB_GENERATOR + this.fakeType = FakeTypes.GetAttributeType(attributeType); +#elif !FIRST_PASS + this.fakeType = typeof(ikvm.@internal.AttributeAnnotation<>).MakeGenericType(attributeType); +#endif + this.attributeType = attributeType; + } + + private static bool IsSupportedType(Type type) + { + // Java annotations only support one-dimensional arrays + if (ReflectUtil.IsVector(type)) + { + type = type.GetElementType(); + } + return type == Types.String + || type == Types.Boolean + || type == Types.Byte + || type == Types.Char + || type == Types.Int16 + || type == Types.Int32 + || type == Types.Single + || type == Types.Int64 + || type == Types.Double + || type == Types.Type + || type.IsEnum; + } + + internal static void GetConstructors(Type type, out ConstructorInfo defCtor, out ConstructorInfo singleOneArgCtor) + { + defCtor = null; + int oneArgCtorCount = 0; + ConstructorInfo oneArgCtor = null; + ConstructorInfo[] constructors = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance); + // HACK we have a special rule to make some additional custom attributes from mscorlib usable: + // Attributes that have two constructors, one an enum and another one taking a byte, short or int, + // we only expose the enum constructor. + if (constructors.Length == 2 && type.Assembly == Types.Object.Assembly) + { + ParameterInfo[] p0 = constructors[0].GetParameters(); + ParameterInfo[] p1 = constructors[1].GetParameters(); + if (p0.Length == 1 && p1.Length == 1) + { + Type t0 = p0[0].ParameterType; + Type t1 = p1[0].ParameterType; + bool swapped = false; + if (t1.IsEnum) + { + Type tmp = t0; + t0 = t1; + t1 = tmp; + swapped = true; + } + if (t0.IsEnum && (t1 == Types.Byte || t1 == Types.Int16 || t1 == Types.Int32)) + { + if (swapped) + { + singleOneArgCtor = constructors[1]; + } + else + { + singleOneArgCtor = constructors[0]; + } + return; + } + } + } + if (type.Assembly == Types.Object.Assembly) + { + if (type.FullName == "System.Runtime.CompilerServices.MethodImplAttribute") + { + foreach (ConstructorInfo ci in constructors) + { + ParameterInfo[] p = ci.GetParameters(); + if (p.Length == 1 && p[0].ParameterType.IsEnum) + { + singleOneArgCtor = ci; + return; + } + } + } + } + foreach (ConstructorInfo ci in constructors) + { + ParameterInfo[] args = ci.GetParameters(); + if (args.Length == 0) + { + defCtor = ci; + } + else if (args.Length == 1) + { + if (IsSupportedType(args[0].ParameterType)) + { + oneArgCtor = ci; + oneArgCtorCount++; + } + else + { + // set to two to make sure we don't see the oneArgCtor as viable + oneArgCtorCount = 2; + } + } + } + singleOneArgCtor = oneArgCtorCount == 1 ? oneArgCtor : null; + } + + private sealed class AttributeAnnotationMethodWrapper : DynamicOnlyMethodWrapper + { + private readonly bool optional; + + internal AttributeAnnotationMethodWrapper(AttributeAnnotationTypeWrapper tw, string name, Type type, bool optional) + : this(tw, name, MapType(type, false), optional) + { + } + + private static TypeWrapper MapType(Type type, bool isArray) + { + if (type == Types.String) + { + return CoreClasses.java.lang.String.Wrapper; + } + else if (type == Types.Boolean) + { + return PrimitiveTypeWrapper.BOOLEAN; + } + else if (type == Types.Byte) + { + return PrimitiveTypeWrapper.BYTE; + } + else if (type == Types.Char) + { + return PrimitiveTypeWrapper.CHAR; + } + else if (type == Types.Int16) + { + return PrimitiveTypeWrapper.SHORT; + } + else if (type == Types.Int32) + { + return PrimitiveTypeWrapper.INT; + } + else if (type == Types.Single) + { + return PrimitiveTypeWrapper.FLOAT; + } + else if (type == Types.Int64) + { + return PrimitiveTypeWrapper.LONG; + } + else if (type == Types.Double) + { + return PrimitiveTypeWrapper.DOUBLE; + } + else if (type == Types.Type) + { + return CoreClasses.java.lang.Class.Wrapper; + } + else if (type.IsEnum) + { + foreach (TypeWrapper tw in ClassLoaderWrapper.GetWrapperFromType(type).InnerClasses) + { + if (tw is EnumEnumTypeWrapper) + { + if (!isArray && type.IsDefined(JVM.Import(typeof(FlagsAttribute)), false)) + { + return tw.MakeArrayType(1); + } + return tw; + } + } + throw new InvalidOperationException(); + } + else if (!isArray && ReflectUtil.IsVector(type)) + { + return MapType(type.GetElementType(), true).MakeArrayType(1); + } + else + { + throw new NotImplementedException(); + } + } + + private AttributeAnnotationMethodWrapper(AttributeAnnotationTypeWrapper tw, string name, TypeWrapper returnType, bool optional) + : base(tw, name, "()" + returnType.SigName, returnType, TypeWrapper.EmptyArray, MemberFlags.None) + { + this.optional = optional; + } + + internal override bool IsOptionalAttributeAnnotationValue + { + get { return optional; } + } + } + + protected override void LazyPublishMembers() + { + List methods = new List(); + ConstructorInfo defCtor; + ConstructorInfo singleOneArgCtor; + GetConstructors(attributeType, out defCtor, out singleOneArgCtor); + if (singleOneArgCtor != null) + { + methods.Add(new AttributeAnnotationMethodWrapper(this, "value", singleOneArgCtor.GetParameters()[0].ParameterType, defCtor != null)); + } + foreach (PropertyInfo pi in attributeType.GetProperties(BindingFlags.Instance | BindingFlags.Public)) + { + // the getter and setter methods both need to be public + // the getter signature must be: Getter() + // the setter signature must be: void Setter() + // the property type needs to be a supported type + MethodInfo getter = pi.GetGetMethod(); + MethodInfo setter = pi.GetSetMethod(); + ParameterInfo[] parameters; + if (getter != null && getter.GetParameters().Length == 0 && getter.ReturnType == pi.PropertyType + && setter != null && (parameters = setter.GetParameters()).Length == 1 && parameters[0].ParameterType == pi.PropertyType && setter.ReturnType == Types.Void + && IsSupportedType(pi.PropertyType)) + { + AddMethodIfUnique(methods, new AttributeAnnotationMethodWrapper(this, pi.Name, pi.PropertyType, true)); + } + } + foreach (FieldInfo fi in attributeType.GetFields(BindingFlags.Public | BindingFlags.Instance)) + { + if (!fi.IsInitOnly && IsSupportedType(fi.FieldType)) + { + AddMethodIfUnique(methods, new AttributeAnnotationMethodWrapper(this, fi.Name, fi.FieldType, true)); + } + } + SetMethods(methods.ToArray()); + base.LazyPublishMembers(); + } + + private static void AddMethodIfUnique(List methods, MethodWrapper method) + { + foreach (MethodWrapper mw in methods) + { + if (mw.Name == method.Name && mw.Signature == method.Signature) + { + // ignore duplicate + return; + } + } + methods.Add(method); + } + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + internal override object GetAnnotationDefault(MethodWrapper mw) + { + if (mw.IsOptionalAttributeAnnotationValue) + { + if (mw.ReturnType == PrimitiveTypeWrapper.BOOLEAN) + { + return java.lang.Boolean.FALSE; + } + else if (mw.ReturnType == PrimitiveTypeWrapper.BYTE) + { + return java.lang.Byte.valueOf((byte)0); + } + else if (mw.ReturnType == PrimitiveTypeWrapper.CHAR) + { + return java.lang.Character.valueOf((char)0); + } + else if (mw.ReturnType == PrimitiveTypeWrapper.SHORT) + { + return java.lang.Short.valueOf((short)0); + } + else if (mw.ReturnType == PrimitiveTypeWrapper.INT) + { + return java.lang.Integer.valueOf(0); + } + else if (mw.ReturnType == PrimitiveTypeWrapper.FLOAT) + { + return java.lang.Float.valueOf(0F); + } + else if (mw.ReturnType == PrimitiveTypeWrapper.LONG) + { + return java.lang.Long.valueOf(0L); + } + else if (mw.ReturnType == PrimitiveTypeWrapper.DOUBLE) + { + return java.lang.Double.valueOf(0D); + } + else if (mw.ReturnType == CoreClasses.java.lang.String.Wrapper) + { + return ""; + } + else if (mw.ReturnType == CoreClasses.java.lang.Class.Wrapper) + { + return (java.lang.Class)typeof(ikvm.@internal.__unspecified); + } + else if (mw.ReturnType is EnumEnumTypeWrapper) + { + EnumEnumTypeWrapper eetw = (EnumEnumTypeWrapper)mw.ReturnType; + return eetw.GetUnspecifiedValue(); + } + else if (mw.ReturnType.IsArray) + { + return Array.CreateInstance(mw.ReturnType.TypeAsArrayType, 0); + } + } + return null; + } +#endif // !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + + internal override TypeWrapper DeclaringTypeWrapper + { + get + { + return ClassLoaderWrapper.GetWrapperFromType(attributeType); + } + } + + internal override Type TypeAsTBD + { + get + { + return fakeType; + } + } + + private sealed class ReturnValueAnnotationTypeWrapper : AttributeAnnotationTypeWrapperBase + { + private readonly Type fakeType; + private readonly AttributeAnnotationTypeWrapper declaringType; + + internal ReturnValueAnnotationTypeWrapper(AttributeAnnotationTypeWrapper declaringType) + : base(declaringType.Name + AttributeAnnotationReturnValueSuffix) + { +#if STATIC_COMPILER || STUB_GENERATOR + this.fakeType = FakeTypes.GetAttributeReturnValueType(declaringType.attributeType); +#elif !FIRST_PASS + this.fakeType = typeof(ikvm.@internal.AttributeAnnotationReturnValue<>).MakeGenericType(declaringType.attributeType); +#endif + this.declaringType = declaringType; + } + + protected override void LazyPublishMembers() + { + TypeWrapper tw = declaringType; + if (declaringType.GetAttributeUsage().AllowMultiple) + { + tw = tw.MakeArrayType(1); + } + SetMethods(new MethodWrapper[] { new DynamicOnlyMethodWrapper(this, "value", "()" + tw.SigName, tw, TypeWrapper.EmptyArray, MemberFlags.None) }); + SetFields(FieldWrapper.EmptyArray); + } + + internal override TypeWrapper DeclaringTypeWrapper + { + get + { + return declaringType; + } + } + + internal override Type TypeAsTBD + { + get + { + return fakeType; + } + } + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + internal override object[] GetDeclaredAnnotations() + { + java.util.HashMap targetMap = new java.util.HashMap(); + targetMap.put("value", new java.lang.annotation.ElementType[] { java.lang.annotation.ElementType.METHOD }); + java.util.HashMap retentionMap = new java.util.HashMap(); + retentionMap.put("value", java.lang.annotation.RetentionPolicy.RUNTIME); + return new object[] { + java.lang.reflect.Proxy.newProxyInstance(null, new java.lang.Class[] { typeof(java.lang.annotation.Target) }, new sun.reflect.annotation.AnnotationInvocationHandler(typeof(java.lang.annotation.Target), targetMap)), + java.lang.reflect.Proxy.newProxyInstance(null, new java.lang.Class[] { typeof(java.lang.annotation.Retention) }, new sun.reflect.annotation.AnnotationInvocationHandler(typeof(java.lang.annotation.Retention), retentionMap)) + }; + } +#endif + + private sealed class ReturnValueAnnotation : Annotation + { + private readonly AttributeAnnotationTypeWrapper type; + + internal ReturnValueAnnotation(AttributeAnnotationTypeWrapper type) + { + this.type = type; + } + + internal override void ApplyReturnValue(ClassLoaderWrapper loader, MethodBuilder mb, ref ParameterBuilder pb, object annotation) + { + // TODO make sure the descriptor is correct + Annotation ann = type.Annotation; + object[] arr = (object[])annotation; + for (int i = 2; i < arr.Length; i += 2) + { + if ("value".Equals(arr[i])) + { + if (pb == null) + { + pb = mb.DefineParameter(0, ParameterAttributes.None, null); + } + object[] value = (object[])arr[i + 1]; + if (value[0].Equals(AnnotationDefaultAttribute.TAG_ANNOTATION)) + { + ann.Apply(loader, pb, value); + } + else + { + for (int j = 1; j < value.Length; j++) + { + ann.Apply(loader, pb, value[j]); + } + } + break; + } + } + } + + internal override void Apply(ClassLoaderWrapper loader, MethodBuilder mb, object annotation) + { + } + + internal override void Apply(ClassLoaderWrapper loader, AssemblyBuilder ab, object annotation) + { + } + + internal override void Apply(ClassLoaderWrapper loader, FieldBuilder fb, object annotation) + { + } + + internal override void Apply(ClassLoaderWrapper loader, ParameterBuilder pb, object annotation) + { + } + + internal override void Apply(ClassLoaderWrapper loader, TypeBuilder tb, object annotation) + { + } + + internal override void Apply(ClassLoaderWrapper loader, PropertyBuilder pb, object annotation) + { + } + + internal override bool IsCustomAttribute + { + get { return type.Annotation.IsCustomAttribute; } + } + } + + internal override Annotation Annotation + { + get + { + return new ReturnValueAnnotation(declaringType); + } + } + + internal override AttributeTargets AttributeTargets + { + get { return AttributeTargets.ReturnValue; } + } + } + + private sealed class MultipleAnnotationTypeWrapper : AttributeAnnotationTypeWrapperBase + { + private readonly Type fakeType; + private readonly AttributeAnnotationTypeWrapper declaringType; + + internal MultipleAnnotationTypeWrapper(AttributeAnnotationTypeWrapper declaringType) + : base(declaringType.Name + AttributeAnnotationMultipleSuffix) + { +#if STATIC_COMPILER || STUB_GENERATOR + this.fakeType = FakeTypes.GetAttributeMultipleType(declaringType.attributeType); +#elif !FIRST_PASS + this.fakeType = typeof(ikvm.@internal.AttributeAnnotationMultiple<>).MakeGenericType(declaringType.attributeType); +#endif + this.declaringType = declaringType; + } + + protected override void LazyPublishMembers() + { + TypeWrapper tw = declaringType.MakeArrayType(1); + SetMethods(new MethodWrapper[] { new DynamicOnlyMethodWrapper(this, "value", "()" + tw.SigName, tw, TypeWrapper.EmptyArray, MemberFlags.None) }); + SetFields(FieldWrapper.EmptyArray); + } + + internal override TypeWrapper DeclaringTypeWrapper + { + get + { + return declaringType; + } + } + + internal override Type TypeAsTBD + { + get + { + return fakeType; + } + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal override object[] GetDeclaredAnnotations() + { + return declaringType.GetDeclaredAnnotations(); + } +#endif + + private sealed class MultipleAnnotation : Annotation + { + private readonly AttributeAnnotationTypeWrapper type; + + internal MultipleAnnotation(AttributeAnnotationTypeWrapper type) + { + this.type = type; + } + + private static object[] UnwrapArray(object annotation) + { + // TODO make sure the descriptor is correct + object[] arr = (object[])annotation; + for (int i = 2; i < arr.Length; i += 2) + { + if ("value".Equals(arr[i])) + { + object[] value = (object[])arr[i + 1]; + object[] rc = new object[value.Length - 1]; + Array.Copy(value, 1, rc, 0, rc.Length); + return rc; + } + } + return new object[0]; + } + + internal override void Apply(ClassLoaderWrapper loader, MethodBuilder mb, object annotation) + { + Annotation annot = type.Annotation; + foreach (object ann in UnwrapArray(annotation)) + { + annot.Apply(loader, mb, ann); + } + } + + internal override void Apply(ClassLoaderWrapper loader, AssemblyBuilder ab, object annotation) + { + Annotation annot = type.Annotation; + foreach (object ann in UnwrapArray(annotation)) + { + annot.Apply(loader, ab, ann); + } + } + + internal override void Apply(ClassLoaderWrapper loader, FieldBuilder fb, object annotation) + { + Annotation annot = type.Annotation; + foreach (object ann in UnwrapArray(annotation)) + { + annot.Apply(loader, fb, ann); + } + } + + internal override void Apply(ClassLoaderWrapper loader, ParameterBuilder pb, object annotation) + { + Annotation annot = type.Annotation; + foreach (object ann in UnwrapArray(annotation)) + { + annot.Apply(loader, pb, ann); + } + } + + internal override void Apply(ClassLoaderWrapper loader, TypeBuilder tb, object annotation) + { + Annotation annot = type.Annotation; + foreach (object ann in UnwrapArray(annotation)) + { + annot.Apply(loader, tb, ann); + } + } + + internal override void Apply(ClassLoaderWrapper loader, PropertyBuilder pb, object annotation) + { + Annotation annot = type.Annotation; + foreach (object ann in UnwrapArray(annotation)) + { + annot.Apply(loader, pb, ann); + } + } + + internal override bool IsCustomAttribute + { + get { return type.Annotation.IsCustomAttribute; } + } + } + + internal override Annotation Annotation + { + get + { + return new MultipleAnnotation(declaringType); + } + } + + internal override AttributeTargets AttributeTargets + { + get { return declaringType.AttributeTargets; } + } + } + + internal override TypeWrapper[] InnerClasses + { + get + { + if (innerClasses == null) + { + innerClasses = GetInnerClasses(); + } + return innerClasses; + } + } + + private TypeWrapper[] GetInnerClasses() + { + List list = new List(); + AttributeUsageAttribute attr = GetAttributeUsage(); + if ((attr.ValidOn & AttributeTargets.ReturnValue) != 0) + { + list.Add(GetClassLoader().RegisterInitiatingLoader(new ReturnValueAnnotationTypeWrapper(this))); + } + if (attr.AllowMultiple) + { + list.Add(GetClassLoader().RegisterInitiatingLoader(new MultipleAnnotationTypeWrapper(this))); + } + return list.ToArray(); + } + + internal override bool IsFakeTypeContainer + { + get + { + return true; + } + } + + private AttributeUsageAttribute GetAttributeUsage() + { + AttributeTargets validOn = AttributeTargets.All; + bool allowMultiple = false; + bool inherited = true; + foreach (CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(attributeType)) + { + if (cad.Constructor.DeclaringType == JVM.Import(typeof(AttributeUsageAttribute))) + { + if (cad.ConstructorArguments.Count == 1 && cad.ConstructorArguments[0].ArgumentType == JVM.Import(typeof(AttributeTargets))) + { + validOn = (AttributeTargets)cad.ConstructorArguments[0].Value; + } + foreach (CustomAttributeNamedArgument cana in cad.NamedArguments) + { + if (cana.MemberInfo.Name == "AllowMultiple") + { + allowMultiple = (bool)cana.TypedValue.Value; + } + else if (cana.MemberInfo.Name == "Inherited") + { + inherited = (bool)cana.TypedValue.Value; + } + } + } + } + AttributeUsageAttribute attr = new AttributeUsageAttribute(validOn); + attr.AllowMultiple = allowMultiple; + attr.Inherited = inherited; + return attr; + } + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + internal override object[] GetDeclaredAnnotations() + { + // note that AttributeUsageAttribute.Inherited does not map to java.lang.annotation.Inherited + AttributeTargets validOn = GetAttributeUsage().ValidOn; + List targets = new List(); + if ((validOn & (AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Delegate | AttributeTargets.Assembly)) != 0) + { + targets.Add(java.lang.annotation.ElementType.TYPE); + } + if ((validOn & AttributeTargets.Constructor) != 0) + { + targets.Add(java.lang.annotation.ElementType.CONSTRUCTOR); + } + if ((validOn & AttributeTargets.Field) != 0) + { + targets.Add(java.lang.annotation.ElementType.FIELD); + } + if ((validOn & AttributeTargets.Method) != 0) + { + targets.Add(java.lang.annotation.ElementType.METHOD); + } + if ((validOn & AttributeTargets.Parameter) != 0) + { + targets.Add(java.lang.annotation.ElementType.PARAMETER); + } + java.util.HashMap targetMap = new java.util.HashMap(); + targetMap.put("value", targets.ToArray()); + java.util.HashMap retentionMap = new java.util.HashMap(); + retentionMap.put("value", java.lang.annotation.RetentionPolicy.RUNTIME); + return new object[] { + java.lang.reflect.Proxy.newProxyInstance(null, new java.lang.Class[] { typeof(java.lang.annotation.Target) }, new sun.reflect.annotation.AnnotationInvocationHandler(typeof(java.lang.annotation.Target), targetMap)), + java.lang.reflect.Proxy.newProxyInstance(null, new java.lang.Class[] { typeof(java.lang.annotation.Retention) }, new sun.reflect.annotation.AnnotationInvocationHandler(typeof(java.lang.annotation.Retention), retentionMap)) + }; + } +#endif + + private sealed class AttributeAnnotation : Annotation + { + private readonly Type type; + + internal AttributeAnnotation(Type type) + { + this.type = type; + } + + private CustomAttributeBuilder MakeCustomAttributeBuilder(ClassLoaderWrapper loader, object annotation) + { + object[] arr = (object[])annotation; + ConstructorInfo defCtor; + ConstructorInfo singleOneArgCtor; + object ctorArg = null; + GetConstructors(type, out defCtor, out singleOneArgCtor); + List properties = new List(); + List propertyValues = new List(); + List fields = new List(); + List fieldValues = new List(); + for (int i = 2; i < arr.Length; i += 2) + { + string name = (string)arr[i]; + if (name == "value" && singleOneArgCtor != null) + { + ctorArg = ConvertValue(loader, singleOneArgCtor.GetParameters()[0].ParameterType, arr[i + 1]); + } + else + { + PropertyInfo pi = type.GetProperty(name, BindingFlags.Public | BindingFlags.Instance); + if (pi != null) + { + properties.Add(pi); + propertyValues.Add(ConvertValue(loader, pi.PropertyType, arr[i + 1])); + } + else + { + FieldInfo fi = type.GetField(name, BindingFlags.Public | BindingFlags.Instance); + if (fi != null) + { + fields.Add(fi); + fieldValues.Add(ConvertValue(loader, fi.FieldType, arr[i + 1])); + } + } + } + } + if (ctorArg == null && defCtor == null) + { + // TODO required argument is missing + } + return new CustomAttributeBuilder(ctorArg == null ? defCtor : singleOneArgCtor, + ctorArg == null ? new object[0] : new object[] { ctorArg }, + properties.ToArray(), + propertyValues.ToArray(), + fields.ToArray(), + fieldValues.ToArray()); + } + + internal override void Apply(ClassLoaderWrapper loader, TypeBuilder tb, object annotation) + { + if (type == JVM.Import(typeof(System.Runtime.InteropServices.StructLayoutAttribute)) && tb.BaseType != Types.Object) + { + // we have to handle this explicitly, because if we apply an illegal StructLayoutAttribute, + // TypeBuilder.CreateType() will later on throw an exception. +#if STATIC_COMPILER + loader.IssueMessage(Message.IgnoredCustomAttribute, type.FullName, "Type '" + tb.FullName + "' does not extend cli.System.Object"); +#else + Tracer.Error(Tracer.Runtime, "StructLayoutAttribute cannot be applied to {0}, because it does not directly extend cli.System.Object", tb.FullName); +#endif + return; + } + if (type.IsSubclassOf(Types.SecurityAttribute)) + { +#if STATIC_COMPILER + tb.__AddDeclarativeSecurity(MakeCustomAttributeBuilder(loader, annotation)); +#elif STUB_GENERATOR +#else + SecurityAction action; + PermissionSet permSet; + if (MakeDeclSecurity(type, annotation, out action, out permSet)) + { + tb.AddDeclarativeSecurity(action, permSet); + } +#endif + } + else + { + tb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + } + + internal override void Apply(ClassLoaderWrapper loader, MethodBuilder mb, object annotation) + { + if (type.IsSubclassOf(Types.SecurityAttribute)) + { +#if STATIC_COMPILER + mb.__AddDeclarativeSecurity(MakeCustomAttributeBuilder(loader, annotation)); +#elif STUB_GENERATOR +#else + SecurityAction action; + PermissionSet permSet; + if (MakeDeclSecurity(type, annotation, out action, out permSet)) + { + mb.AddDeclarativeSecurity(action, permSet); + } +#endif + } + else + { + mb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + } + + internal override void Apply(ClassLoaderWrapper loader, FieldBuilder fb, object annotation) + { + if (type.IsSubclassOf(Types.SecurityAttribute)) + { + // you can't add declarative security to a field + } + else + { + fb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + } + + internal override void Apply(ClassLoaderWrapper loader, ParameterBuilder pb, object annotation) + { + if (type.IsSubclassOf(Types.SecurityAttribute)) + { + // you can't add declarative security to a parameter + } + else if (type == JVM.Import(typeof(System.Runtime.InteropServices.DefaultParameterValueAttribute))) + { + // TODO with the current custom attribute annotation restrictions it is impossible to use this CA, + // but if we make it possible, we should also implement it here + throw new NotImplementedException(); + } + else + { + pb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + } + + internal override void Apply(ClassLoaderWrapper loader, AssemblyBuilder ab, object annotation) + { + if (type.IsSubclassOf(Types.SecurityAttribute)) + { +#if STATIC_COMPILER + ab.__AddDeclarativeSecurity(MakeCustomAttributeBuilder(loader, annotation)); +#endif + } +#if STATIC_COMPILER + else if (type == JVM.Import(typeof(System.Runtime.CompilerServices.TypeForwardedToAttribute))) + { + ab.__AddTypeForwarder((Type)ConvertValue(loader, Types.Type, ((object[])annotation)[3])); + } + else if (type == JVM.Import(typeof(System.Reflection.AssemblyVersionAttribute))) + { + string str = (string)ConvertValue(loader, Types.String, ((object[])annotation)[3]); + Version version; + if (IkvmcCompiler.TryParseVersion(str, out version)) + { + ab.__SetAssemblyVersion(version); + } + else + { + loader.IssueMessage(Message.InvalidCustomAttribute, type.FullName, "The version '" + str + "' is invalid."); + } + } + else if (type == JVM.Import(typeof(System.Reflection.AssemblyCultureAttribute))) + { + string str = (string)ConvertValue(loader, Types.String, ((object[])annotation)[3]); + if (str != "") + { + ab.__SetAssemblyCulture(str); + } + } + else if (type == JVM.Import(typeof(System.Reflection.AssemblyDelaySignAttribute)) + || type == JVM.Import(typeof(System.Reflection.AssemblyKeyFileAttribute)) + || type == JVM.Import(typeof(System.Reflection.AssemblyKeyNameAttribute))) + { + loader.IssueMessage(Message.IgnoredCustomAttribute, type.FullName, "Please use the corresponding compiler switch."); + } + else if (type == JVM.Import(typeof(System.Reflection.AssemblyAlgorithmIdAttribute))) + { + // this attribute is currently not exposed as an annotation and isn't very interesting + throw new NotImplementedException(); + } + else if (type == JVM.Import(typeof(System.Reflection.AssemblyFlagsAttribute))) + { + // this attribute is currently not exposed as an annotation and isn't very interesting + throw new NotImplementedException(); + } +#endif + else + { + ab.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + } + + internal override void Apply(ClassLoaderWrapper loader, PropertyBuilder pb, object annotation) + { + if (type.IsSubclassOf(Types.SecurityAttribute)) + { + // you can't add declarative security to a property + } + else + { + pb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + } + + internal override bool IsCustomAttribute + { + get { return true; } + } + } + + internal override Annotation Annotation + { + get + { + return new AttributeAnnotation(attributeType); + } + } + + internal override AttributeTargets AttributeTargets + { + get { return GetAttributeUsage().ValidOn; } + } + } + + internal static TypeWrapper GetWrapperFromDotNetType(Type type) + { + TypeWrapper tw; + lock (types) + { + types.TryGetValue(type, out tw); + } + if (tw == null) + { + tw = AssemblyClassLoader.FromAssembly(type.Assembly).GetWrapperFromAssemblyType(type); + lock (types) + { + types[type] = tw; + } + } + return tw; + } + + private static TypeWrapper GetBaseTypeWrapper(Type type) + { + if (type.IsInterface) + { + return null; + } + else if (ClassLoaderWrapper.IsRemappedType(type)) + { + // Remapped types extend their alter ego + // (e.g. cli.System.Object must appear to be derived from java.lang.Object) + // except when they're sealed, of course. + if (type.IsSealed) + { + return CoreClasses.java.lang.Object.Wrapper; + } + return ClassLoaderWrapper.GetWrapperFromType(type); + } + else if (ClassLoaderWrapper.IsRemappedType(type.BaseType)) + { + return GetWrapperFromDotNetType(type.BaseType); + } + else + { + return ClassLoaderWrapper.GetWrapperFromType(type.BaseType); + } + } + + internal static TypeWrapper Create(Type type, string name) + { + if (type.ContainsGenericParameters) + { + return new OpenGenericTypeWrapper(type, name); + } + else + { + return new DotNetTypeWrapper(type, name); + } + } + + private DotNetTypeWrapper(Type type, string name) + : base(TypeFlags.None, GetModifiers(type), name) + { + Debug.Assert(!(type.IsByRef), type.FullName); + Debug.Assert(!(type.IsPointer), type.FullName); + Debug.Assert(!(type.Name.EndsWith("[]")), type.FullName); + Debug.Assert(!(type is TypeBuilder), type.FullName); + Debug.Assert(!(AttributeHelper.IsJavaModule(type.Module))); + + this.type = type; + } + + internal override TypeWrapper BaseTypeWrapper + { + get { return baseTypeWrapper ?? (baseTypeWrapper = GetBaseTypeWrapper(type)); } + } + + internal override ClassLoaderWrapper GetClassLoader() + { + if (type.IsGenericType) + { + return ClassLoaderWrapper.GetGenericClassLoader(this); + } + return AssemblyClassLoader.FromAssembly(type.Assembly); + } + + private sealed class MulticastDelegateCtorMethodWrapper : MethodWrapper + { + internal MulticastDelegateCtorMethodWrapper(TypeWrapper declaringType) + : base(declaringType, "", "()V", null, PrimitiveTypeWrapper.VOID, TypeWrapper.EmptyArray, Modifiers.Protected, MemberFlags.None) + { + } + } + + internal static string GetDelegateInvokeStubName(Type delegateType) + { + MethodInfo delegateInvoke = delegateType.GetMethod("Invoke"); + ParameterInfo[] parameters = delegateInvoke.GetParameters(); + string name = null; + for (int i = 0; i < parameters.Length; i++) + { + if (parameters[i].ParameterType.IsByRef) + { + name = (name ?? "") + "_" + i; + } + } + return name ?? "Invoke"; + } + + private sealed class DelegateMethodWrapper : MethodWrapper + { + private readonly ConstructorInfo delegateConstructor; + private readonly DelegateInnerClassTypeWrapper iface; + + internal DelegateMethodWrapper(TypeWrapper declaringType, DelegateInnerClassTypeWrapper iface) + : base(declaringType, "", "(" + iface.SigName + ")V", null, PrimitiveTypeWrapper.VOID, new TypeWrapper[] { iface }, Modifiers.Public, MemberFlags.Intrinsic) + { + this.delegateConstructor = declaringType.TypeAsTBD.GetConstructor(new Type[] { Types.Object, Types.IntPtr }); + this.iface = iface; + } + +#if EMITTERS + internal override bool EmitIntrinsic(EmitIntrinsicContext context) + { + TypeWrapper targetType = context.GetStackTypeWrapper(0, 0); + if (targetType.IsUnloadable || targetType.IsInterface) + { + return false; + } + // we know that a DelegateInnerClassTypeWrapper has only one method + Debug.Assert(iface.GetMethods().Length == 1); + MethodWrapper mw = targetType.GetMethodWrapper(GetDelegateInvokeStubName(DeclaringType.TypeAsTBD), iface.GetMethods()[0].Signature, true); + if (mw == null || mw.IsStatic || !mw.IsPublic) + { + context.Emitter.Emit(OpCodes.Ldftn, CreateErrorStub(context, targetType, mw == null || mw.IsStatic)); + context.Emitter.Emit(OpCodes.Newobj, delegateConstructor); + return true; + } + // TODO linking here is not safe + mw.Link(); + context.Emitter.Emit(OpCodes.Dup); + context.Emitter.Emit(OpCodes.Ldvirtftn, mw.GetMethod()); + context.Emitter.Emit(OpCodes.Newobj, delegateConstructor); + return true; + } + + private MethodInfo CreateErrorStub(EmitIntrinsicContext context, TypeWrapper targetType, bool isAbstract) + { + MethodInfo invoke = delegateConstructor.DeclaringType.GetMethod("Invoke"); + ParameterInfo[] parameters = invoke.GetParameters(); + Type[] parameterTypes = new Type[parameters.Length + 1]; + parameterTypes[0] = Types.Object; + for (int i = 0; i < parameters.Length; i++) + { + parameterTypes[i + 1] = parameters[i].ParameterType; + } + MethodBuilder mb = context.Context.DefineDelegateInvokeErrorStub(invoke.ReturnType, parameterTypes); + CodeEmitter ilgen = CodeEmitter.Create(mb); + ilgen.EmitThrow(isAbstract ? "java.lang.AbstractMethodError" : "java.lang.IllegalAccessError", targetType.Name + ".Invoke" + iface.GetMethods()[0].Signature); + ilgen.DoEmit(); + return mb; + } + + internal override void EmitNewobj(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Ldtoken, delegateConstructor.DeclaringType); + ilgen.Emit(OpCodes.Call, Compiler.getTypeFromHandleMethod); + ilgen.Emit(OpCodes.Ldstr, GetDelegateInvokeStubName(DeclaringType.TypeAsTBD)); + ilgen.Emit(OpCodes.Ldstr, iface.GetMethods()[0].Signature); + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicCreateDelegate); + ilgen.Emit(OpCodes.Castclass, delegateConstructor.DeclaringType); + } + + internal override void EmitCall(CodeEmitter ilgen) + { + // This is a bit of a hack. We bind the existing delegate to a new delegate to be able to reuse the DynamicCreateDelegate error + // handling. This leaks out to the user because Delegate.Target will return the target delegate instead of the bound object. + + // create the target delegate + EmitNewobj(ilgen); + + // invoke the constructor, binding the delegate to the target delegate + ilgen.Emit(OpCodes.Dup); + ilgen.Emit(OpCodes.Ldvirtftn, MethodHandleUtil.GetDelegateInvokeMethod(delegateConstructor.DeclaringType)); + ilgen.Emit(OpCodes.Call, delegateConstructor); + } +#endif // EMITTERS + } + + private sealed class ByRefMethodWrapper : SmartMethodWrapper + { +#if !STATIC_COMPILER + private readonly bool[] byrefs; +#endif + private readonly Type[] args; + + internal ByRefMethodWrapper(Type[] args, bool[] byrefs, TypeWrapper declaringType, string name, string sig, MethodBase method, TypeWrapper returnType, TypeWrapper[] parameterTypes, Modifiers modifiers, bool hideFromReflection) + : base(declaringType, name, sig, method, returnType, parameterTypes, modifiers, hideFromReflection ? MemberFlags.HideFromReflection : MemberFlags.None) + { + this.args = args; +#if !STATIC_COMPILER + this.byrefs = byrefs; +#endif + } + +#if EMITTERS + protected override void CallImpl(CodeEmitter ilgen) + { + ConvertByRefArgs(ilgen); + ilgen.Emit(OpCodes.Call, GetMethod()); + } + + protected override void CallvirtImpl(CodeEmitter ilgen) + { + ConvertByRefArgs(ilgen); + ilgen.Emit(OpCodes.Callvirt, GetMethod()); + } + + protected override void NewobjImpl(CodeEmitter ilgen) + { + ConvertByRefArgs(ilgen); + ilgen.Emit(OpCodes.Newobj, GetMethod()); + } + + private void ConvertByRefArgs(CodeEmitter ilgen) + { + CodeEmitterLocal[] locals = new CodeEmitterLocal[args.Length]; + for (int i = args.Length - 1; i >= 0; i--) + { + Type type = args[i]; + if (type.IsByRef) + { + type = ArrayTypeWrapper.MakeArrayType(type.GetElementType(), 1); + } + locals[i] = ilgen.DeclareLocal(type); + ilgen.Emit(OpCodes.Stloc, locals[i]); + } + for (int i = 0; i < args.Length; i++) + { + ilgen.Emit(OpCodes.Ldloc, locals[i]); + if (args[i].IsByRef) + { + ilgen.Emit(OpCodes.Ldc_I4_0); + ilgen.Emit(OpCodes.Ldelema, args[i].GetElementType()); + } + } + } +#endif // EMITTERS + } + + private sealed class EnumWrapMethodWrapper : MethodWrapper + { + internal EnumWrapMethodWrapper(DotNetTypeWrapper tw, TypeWrapper fieldType) + : base(tw, "wrap", "(" + fieldType.SigName + ")" + tw.SigName, null, tw, new TypeWrapper[] { fieldType }, Modifiers.Static | Modifiers.Public, MemberFlags.None) + { + } + +#if EMITTERS + internal override void EmitCall(CodeEmitter ilgen) + { + // We don't actually need to do anything here! + // The compiler will insert a boxing operation after calling us and that will + // result in our argument being boxed (since that's still sitting on the stack). + } +#endif // EMITTERS + +#if !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + internal override object Invoke(object obj, object[] args) + { + return Enum.ToObject(DeclaringType.TypeAsTBD, args[0]); + } +#endif + } + + internal sealed class EnumValueFieldWrapper : FieldWrapper + { + private readonly Type underlyingType; + + internal EnumValueFieldWrapper(DotNetTypeWrapper tw, TypeWrapper fieldType) + : base(tw, fieldType, "Value", fieldType.SigName, new ExModifiers(Modifiers.Public | Modifiers.Final, false), null) + { + underlyingType = EnumHelper.GetUnderlyingType(tw.type); + } + +#if EMITTERS + protected override void EmitGetImpl(CodeEmitter ilgen) + { + // NOTE if the reference on the stack is null, we *want* the NullReferenceException, so we don't use TypeWrapper.EmitUnbox + ilgen.Emit(OpCodes.Unbox, underlyingType); + ilgen.Emit(OpCodes.Ldobj, underlyingType); + } + + protected override void EmitSetImpl(CodeEmitter ilgen) + { + // NOTE even though the field is final, JNI reflection can still be used to set its value! + CodeEmitterLocal temp = ilgen.AllocTempLocal(underlyingType); + ilgen.Emit(OpCodes.Stloc, temp); + ilgen.Emit(OpCodes.Unbox, underlyingType); + ilgen.Emit(OpCodes.Ldloc, temp); + ilgen.Emit(OpCodes.Stobj, underlyingType); + ilgen.ReleaseTempLocal(temp); + } +#endif // EMITTERS + +#if !STUB_GENERATOR && !STATIC_COMPILER && !FIRST_PASS + internal override object GetValue(object obj) + { + return obj; + } + + internal override void SetValue(object obj, object value) + { + obj.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance)[0].SetValue(obj, value); + } +#endif + } + + private sealed class ValueTypeDefaultCtor : MethodWrapper + { + internal ValueTypeDefaultCtor(DotNetTypeWrapper tw) + : base(tw, "", "()V", null, PrimitiveTypeWrapper.VOID, TypeWrapper.EmptyArray, Modifiers.Public, MemberFlags.None) + { + } + +#if EMITTERS + internal override void EmitNewobj(CodeEmitter ilgen) + { + CodeEmitterLocal local = ilgen.DeclareLocal(DeclaringType.TypeAsTBD); + ilgen.Emit(OpCodes.Ldloc, local); + ilgen.Emit(OpCodes.Box, DeclaringType.TypeAsTBD); + } + + internal override void EmitCall(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Pop); + } +#endif // EMITTERS + +#if !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + internal override object CreateInstance(object[] args) + { + return Activator.CreateInstance(DeclaringType.TypeAsTBD); + } +#endif + } + + private sealed class FinalizeMethodWrapper : MethodWrapper + { + internal FinalizeMethodWrapper(DotNetTypeWrapper tw) + : base(tw, "finalize", "()V", null, PrimitiveTypeWrapper.VOID, TypeWrapper.EmptyArray, Modifiers.Protected | Modifiers.Final, MemberFlags.None) + { + } + +#if EMITTERS + internal override void EmitCall(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Pop); + } + + internal override void EmitCallvirt(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Pop); + } +#endif // EMITTERS + } + + private sealed class CloneMethodWrapper : MethodWrapper + { + internal CloneMethodWrapper(DotNetTypeWrapper tw) + : base(tw, "clone", "()Ljava.lang.Object;", null, CoreClasses.java.lang.Object.Wrapper, TypeWrapper.EmptyArray, Modifiers.Protected | Modifiers.Final, MemberFlags.None) + { + } + +#if EMITTERS + internal override void EmitCall(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Dup); + ilgen.Emit(OpCodes.Isinst, CoreClasses.java.lang.Cloneable.Wrapper.TypeAsBaseType); + CodeEmitterLabel label1 = ilgen.DefineLabel(); + ilgen.EmitBrtrue(label1); + CodeEmitterLabel label2 = ilgen.DefineLabel(); + ilgen.EmitBrfalse(label2); + ilgen.EmitThrow("java.lang.CloneNotSupportedException"); + ilgen.MarkLabel(label2); + ilgen.EmitThrow("java.lang.NullPointerException"); + ilgen.MarkLabel(label1); + ilgen.Emit(OpCodes.Call, Types.Object.GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null)); + } + + internal override void EmitCallvirt(CodeEmitter ilgen) + { + EmitCall(ilgen); + } +#endif // EMITTERS + } + + protected override void LazyPublishMembers() + { + // special support for enums + if (type.IsEnum) + { + Type underlyingType = EnumHelper.GetUnderlyingType(type); + Type javaUnderlyingType; + if (underlyingType == Types.SByte) + { + javaUnderlyingType = Types.Byte; + } + else if (underlyingType == Types.UInt16) + { + javaUnderlyingType = Types.Int16; + } + else if (underlyingType == Types.UInt32) + { + javaUnderlyingType = Types.Int32; + } + else if (underlyingType == Types.UInt64) + { + javaUnderlyingType = Types.Int64; + } + else + { + javaUnderlyingType = underlyingType; + } + TypeWrapper fieldType = ClassLoaderWrapper.GetWrapperFromType(javaUnderlyingType); + FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Static); + List fieldsList = new List(); + for (int i = 0; i < fields.Length; i++) + { + if (fields[i].FieldType == type) + { + string name = fields[i].Name; + if (name == "Value") + { + name = "_Value"; + } + else if (name.StartsWith("_") && name.EndsWith("Value")) + { + name = "_" + name; + } + object val = EnumHelper.GetPrimitiveValue(underlyingType, fields[i].GetRawConstantValue()); + fieldsList.Add(new ConstantFieldWrapper(this, fieldType, name, fieldType.SigName, Modifiers.Public | Modifiers.Static | Modifiers.Final, fields[i], val, MemberFlags.None)); + } + } + fieldsList.Add(new EnumValueFieldWrapper(this, fieldType)); + SetFields(fieldsList.ToArray()); + SetMethods(new MethodWrapper[] { new EnumWrapMethodWrapper(this, fieldType) }); + } + else + { + List fieldsList = new List(); + FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + for (int i = 0; i < fields.Length; i++) + { + // TODO for remapped types, instance fields need to be converted to static getter/setter methods + if (fields[i].FieldType.IsPointer) + { + // skip, pointer fields are not supported + } + else + { + // TODO handle name/signature clash + fieldsList.Add(CreateFieldWrapperDotNet(AttributeHelper.GetModifiers(fields[i], true).Modifiers, fields[i].Name, fields[i].FieldType, fields[i])); + } + } + SetFields(fieldsList.ToArray()); + + Dictionary methodsList = new Dictionary(); + + // special case for delegate constructors! + if (IsDelegate(type)) + { + TypeWrapper iface = InnerClasses[0]; + DelegateMethodWrapper mw = new DelegateMethodWrapper(this, (DelegateInnerClassTypeWrapper)iface); + methodsList.Add(mw.Name + mw.Signature, mw); + } + + // add a protected default constructor to MulticastDelegate to make it easier to define a delegate in Java + if (type == Types.MulticastDelegate) + { + methodsList.Add("()V", new MulticastDelegateCtorMethodWrapper(this)); + } + + ConstructorInfo[] constructors = type.GetConstructors(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + for (int i = 0; i < constructors.Length; i++) + { + string name; + string sig; + TypeWrapper[] args; + TypeWrapper ret; + if (MakeMethodDescriptor(constructors[i], out name, out sig, out args, out ret)) + { + MethodWrapper mw = CreateMethodWrapper(name, sig, args, ret, constructors[i], false); + string key = mw.Name + mw.Signature; + if (!methodsList.ContainsKey(key)) + { + methodsList.Add(key, mw); + } + } + } + + if (type.IsValueType && !methodsList.ContainsKey("()V")) + { + // Value types have an implicit default ctor + methodsList.Add("()V", new ValueTypeDefaultCtor(this)); + } + + MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + for (int i = 0; i < methods.Length; i++) + { + if (methods[i].IsStatic && type.IsInterface) + { + // skip, Java cannot deal with static methods on interfaces + } + else + { + string name; + string sig; + TypeWrapper[] args; + TypeWrapper ret; + if (MakeMethodDescriptor(methods[i], out name, out sig, out args, out ret)) + { + if (!methods[i].IsStatic && !methods[i].IsPrivate && BaseTypeWrapper != null) + { + MethodWrapper baseMethod = BaseTypeWrapper.GetMethodWrapper(name, sig, true); + if (baseMethod != null && baseMethod.IsFinal && !baseMethod.IsStatic && !baseMethod.IsPrivate) + { + continue; + } + } + MethodWrapper mw = CreateMethodWrapper(name, sig, args, ret, methods[i], false); + string key = mw.Name + mw.Signature; + MethodWrapper existing; + methodsList.TryGetValue(key, out existing); + if (existing == null || existing is ByRefMethodWrapper) + { + methodsList[key] = mw; + } + } + else if (methods[i].IsAbstract) + { + SetHasUnsupportedAbstractMethods(); + } + } + } + + // make sure that all the interface methods that we implement are available as public methods, + // otherwise javac won't like the class. + if (!type.IsInterface) + { + Type[] interfaces = type.GetInterfaces(); + for (int i = 0; i < interfaces.Length; i++) + { + // we only handle public (or nested public) types, because we're potentially adding a + // method that should be callable by anyone through the interface + if (interfaces[i].IsVisible) + { + if (ClassLoaderWrapper.IsRemappedType(interfaces[i])) + { + TypeWrapper tw = ClassLoaderWrapper.GetWrapperFromType(interfaces[i]); + foreach (MethodWrapper mw in tw.GetMethods()) + { + // HACK we need to link here, because during a core library build we might reference java.lang.AutoCloseable (via IDisposable) before it has been linked + mw.Link(); + InterfaceMethodStubHelper(methodsList, mw.GetMethod(), mw.Name, mw.Signature, mw.GetParameters(), mw.ReturnType); + } + } + InterfaceMapping map = type.GetInterfaceMap(interfaces[i]); + for (int j = 0; j < map.InterfaceMethods.Length; j++) + { + if (map.TargetMethods[j] == null + || ((!map.TargetMethods[j].IsPublic || map.TargetMethods[j].Name != map.InterfaceMethods[j].Name) + && map.TargetMethods[j].DeclaringType == type)) + { + string name; + string sig; + TypeWrapper[] args; + TypeWrapper ret; + if (MakeMethodDescriptor(map.InterfaceMethods[j], out name, out sig, out args, out ret)) + { + InterfaceMethodStubHelper(methodsList, map.InterfaceMethods[j], name, sig, args, ret); + } + } + } + } + } + } + + // for non-final remapped types, we need to add all the virtual methods in our alter ego (which + // appears as our base class) and make them final (to prevent Java code from overriding these + // methods, which don't really exist). + if (ClassLoaderWrapper.IsRemappedType(type) && !type.IsSealed && !type.IsInterface) + { + TypeWrapper baseTypeWrapper = this.BaseTypeWrapper; + while (baseTypeWrapper != null) + { + foreach (MethodWrapper m in baseTypeWrapper.GetMethods()) + { + if (!m.IsStatic && !m.IsFinal && (m.IsPublic || m.IsProtected) && m.Name != "") + { + string key = m.Name + m.Signature; + if (!methodsList.ContainsKey(key)) + { + if (m.IsProtected) + { + if (m.Name == "finalize" && m.Signature == "()V") + { + methodsList.Add(key, new FinalizeMethodWrapper(this)); + } + else if (m.Name == "clone" && m.Signature == "()Ljava.lang.Object;") + { + methodsList.Add(key, new CloneMethodWrapper(this)); + } + else + { + // there should be a special MethodWrapper for this method + throw new InvalidOperationException("Missing protected method support for " + baseTypeWrapper.Name + "::" + m.Name + m.Signature); + } + } + else + { + methodsList.Add(key, new BaseFinalMethodWrapper(this, m)); + } + } + } + } + baseTypeWrapper = baseTypeWrapper.BaseTypeWrapper; + } + } + +#if !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + // support serializing .NET exceptions (by replacing them with a placeholder exception) + if (typeof(Exception).IsAssignableFrom(type) + && !typeof(java.io.Serializable.__Interface).IsAssignableFrom(type) + && !methodsList.ContainsKey("writeReplace()Ljava.lang.Object;")) + { + methodsList.Add("writeReplace()Ljava.lang.Object;", new ExceptionWriteReplaceMethodWrapper(this)); + } +#endif // !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + + MethodWrapper[] methodArray = new MethodWrapper[methodsList.Count]; + methodsList.Values.CopyTo(methodArray, 0); + SetMethods(methodArray); + } + } + +#if !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + private sealed class ExceptionWriteReplaceMethodWrapper : MethodWrapper + { + internal ExceptionWriteReplaceMethodWrapper(TypeWrapper declaringType) + : base(declaringType, "writeReplace", "()Ljava.lang.Object;", null, CoreClasses.java.lang.Object.Wrapper, TypeWrapper.EmptyArray, Modifiers.Private, MemberFlags.None) + { + } + + internal override bool IsDynamicOnly + { + get { return true; } + } + + internal override object Invoke(object obj, object[] args) + { + Exception x = (Exception)obj; + com.sun.xml.@internal.ws.developer.ServerSideException sse + = new com.sun.xml.@internal.ws.developer.ServerSideException(ikvm.extensions.ExtensionMethods.getClass(x).getName(), x.Message); + sse.initCause(x.InnerException); + sse.setStackTrace(ikvm.extensions.ExtensionMethods.getStackTrace(x)); + return sse; + } + } +#endif // !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + + private void InterfaceMethodStubHelper(Dictionary methodsList, MethodBase method, string name, string sig, TypeWrapper[] args, TypeWrapper ret) + { + string key = name + sig; + MethodWrapper existing; + methodsList.TryGetValue(key, out existing); + if (existing == null && BaseTypeWrapper != null) + { + MethodWrapper baseMethod = BaseTypeWrapper.GetMethodWrapper(name, sig, true); + if (baseMethod != null && !baseMethod.IsStatic && baseMethod.IsPublic) + { + return; + } + } + if (existing == null || existing is ByRefMethodWrapper || existing.IsStatic || !existing.IsPublic) + { + // TODO if existing != null, we need to rename the existing method (but this is complicated because + // it also affects subclasses). This is especially required is the existing method is abstract, + // because otherwise we won't be able to create any subclasses in Java. + methodsList[key] = CreateMethodWrapper(name, sig, args, ret, method, true); + } + } + + private sealed class BaseFinalMethodWrapper : MethodWrapper + { + private readonly MethodWrapper m; + + internal BaseFinalMethodWrapper(DotNetTypeWrapper tw, MethodWrapper m) + : base(tw, m.Name, m.Signature, null, null, null, (m.Modifiers & ~Modifiers.Abstract) | Modifiers.Final, MemberFlags.None) + { + this.m = m; + } + + protected override void DoLinkMethod() + { + } + +#if EMITTERS + internal override void EmitCall(CodeEmitter ilgen) + { + // we direct EmitCall to EmitCallvirt, because we always want to end up at the instancehelper method + // (EmitCall would go to our alter ego .NET type and that wouldn't be legal) + m.EmitCallvirt(ilgen); + } + + internal override void EmitCallvirt(CodeEmitter ilgen) + { + m.EmitCallvirt(ilgen); + } +#endif // EMITTERS + } + + internal static bool IsUnsupportedAbstractMethod(MethodBase mb) + { + if (mb.IsAbstract) + { + MethodInfo mi = (MethodInfo)mb; + if (mi.ReturnType.IsByRef || IsPointerType(mi.ReturnType) || mb.IsGenericMethodDefinition) + { + return true; + } + foreach (ParameterInfo p in mi.GetParameters()) + { + if (p.ParameterType.IsByRef || IsPointerType(p.ParameterType)) + { + return true; + } + } + } + return false; + } + + private static bool IsPointerType(Type type) + { + while (type.HasElementType) + { + if (type.IsPointer) + { + return true; + } + type = type.GetElementType(); + } +#if STATIC_COMPILER || STUB_GENERATOR + return type.__IsFunctionPointer; +#else + return false; +#endif + } + + private bool MakeMethodDescriptor(MethodBase mb, out string name, out string sig, out TypeWrapper[] args, out TypeWrapper ret) + { + if (mb.IsGenericMethodDefinition) + { + name = null; + sig = null; + args = null; + ret = null; + return false; + } + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + sb.Append('('); + ParameterInfo[] parameters = mb.GetParameters(); + args = new TypeWrapper[parameters.Length]; + for (int i = 0; i < parameters.Length; i++) + { + Type type = parameters[i].ParameterType; + if (IsPointerType(type)) + { + name = null; + sig = null; + args = null; + ret = null; + return false; + } + if (type.IsByRef) + { + type = ArrayTypeWrapper.MakeArrayType(type.GetElementType(), 1); + if (mb.IsAbstract) + { + // Since we cannot override methods with byref arguments, we don't report abstract + // methods with byref args. + name = null; + sig = null; + args = null; + ret = null; + return false; + } + } + TypeWrapper tw = ClassLoaderWrapper.GetWrapperFromType(type); + args[i] = tw; + sb.Append(tw.SigName); + } + sb.Append(')'); + if (mb is ConstructorInfo) + { + ret = PrimitiveTypeWrapper.VOID; + if (mb.IsStatic) + { + name = ""; + } + else + { + name = ""; + } + sb.Append(ret.SigName); + sig = sb.ToString(); + return true; + } + else + { + Type type = ((MethodInfo)mb).ReturnType; + if (IsPointerType(type) || type.IsByRef) + { + name = null; + sig = null; + ret = null; + return false; + } + ret = ClassLoaderWrapper.GetWrapperFromType(type); + sb.Append(ret.SigName); + name = mb.Name; + sig = sb.ToString(); + return true; + } + } + + internal override TypeWrapper[] Interfaces + { + get + { + if (interfaces == null) + { + interfaces = GetImplementedInterfacesAsTypeWrappers(type); + } + return interfaces; + } + } + + private static bool IsAttribute(Type type) + { + if (!type.IsAbstract && type.IsSubclassOf(Types.Attribute) && type.IsVisible) + { + // + // Based on the number of constructors and their arguments, we distinguish several types + // of attributes: + // | def ctor | single 1-arg ctor + // ----------------------------------------------------------------- + // complex only (i.e. Annotation{N}) | | + // all optional fields/properties | X | + // required "value" | | X + // optional "value" | X | X + // ----------------------------------------------------------------- + // + // TODO currently we don't support "complex only" attributes. + // + ConstructorInfo defCtor; + ConstructorInfo singleOneArgCtor; + AttributeAnnotationTypeWrapper.GetConstructors(type, out defCtor, out singleOneArgCtor); + return defCtor != null || singleOneArgCtor != null; + } + return false; + } + + private static bool IsDelegate(Type type) + { + // HACK non-public delegates do not get the special treatment (because they are likely to refer to + // non-public types in the arg list and they're not really useful anyway) + // NOTE we don't have to check in what assembly the type lives, because this is a DotNetTypeWrapper, + // we know that it is a different assembly. + if (!type.IsAbstract && type.IsSubclassOf(Types.MulticastDelegate) && type.IsVisible) + { + MethodInfo invoke = type.GetMethod("Invoke"); + if (invoke != null) + { + foreach (ParameterInfo p in invoke.GetParameters()) + { + // we don't support delegates with pointer parameters + if (IsPointerType(p.ParameterType)) + { + return false; + } + } + return !IsPointerType(invoke.ReturnType); + } + } + return false; + } + + internal override TypeWrapper[] InnerClasses + { + get + { + if (innerClasses == null) + { + innerClasses = GetInnerClasses(); + } + return innerClasses; + } + } + + private TypeWrapper[] GetInnerClasses() + { + Type[] nestedTypes = type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic); + List list = new List(nestedTypes.Length); + for (int i = 0; i < nestedTypes.Length; i++) + { + if (!nestedTypes[i].IsGenericTypeDefinition) + { + list.Add(ClassLoaderWrapper.GetWrapperFromType(nestedTypes[i])); + } + } + if (IsDelegate(type)) + { + list.Add(GetClassLoader().RegisterInitiatingLoader(new DelegateInnerClassTypeWrapper(Name + DelegateInterfaceSuffix, type))); + } + if (IsAttribute(type)) + { + list.Add(GetClassLoader().RegisterInitiatingLoader(new AttributeAnnotationTypeWrapper(Name + AttributeAnnotationSuffix, type))); + } + if (type.IsEnum && type.IsVisible) + { + list.Add(GetClassLoader().RegisterInitiatingLoader(new EnumEnumTypeWrapper(Name + EnumEnumSuffix, type))); + } + return list.ToArray(); + } + + internal override bool IsFakeTypeContainer + { + get + { + return IsDelegate(type) || IsAttribute(type) || (type.IsEnum && type.IsVisible); + } + } + + internal override TypeWrapper DeclaringTypeWrapper + { + get + { + if (outerClass == null) + { + Type outer = type.DeclaringType; + if (outer != null && !type.IsGenericType) + { + outerClass = GetWrapperFromDotNetType(outer); + } + } + return outerClass; + } + } + + internal override Modifiers ReflectiveModifiers + { + get + { + if (DeclaringTypeWrapper != null) + { + return Modifiers | Modifiers.Static; + } + return Modifiers; + } + } + + private FieldWrapper CreateFieldWrapperDotNet(Modifiers modifiers, string name, Type fieldType, FieldInfo field) + { + TypeWrapper type = ClassLoaderWrapper.GetWrapperFromType(fieldType); + if (field.IsLiteral) + { + return new ConstantFieldWrapper(this, type, name, type.SigName, modifiers, field, null, MemberFlags.None); + } + else + { + return FieldWrapper.Create(this, type, field, name, type.SigName, new ExModifiers(modifiers, false)); + } + } + + // this method detects if type derives from our java.lang.Object or java.lang.Throwable implementation types + private static bool IsRemappedImplDerived(Type type) + { + for (; type != null; type = type.BaseType) + { + if (!ClassLoaderWrapper.IsRemappedType(type) && ClassLoaderWrapper.GetWrapperFromType(type).IsRemapped) + { + return true; + } + } + return false; + } + + private MethodWrapper CreateMethodWrapper(string name, string sig, TypeWrapper[] argTypeWrappers, TypeWrapper retTypeWrapper, MethodBase mb, bool privateInterfaceImplHack) + { + ExModifiers exmods = AttributeHelper.GetModifiers(mb, true); + Modifiers mods = exmods.Modifiers; + if (name == "Finalize" && sig == "()V" && !mb.IsStatic && + IsRemappedImplDerived(TypeAsBaseType)) + { + // TODO if the .NET also has a "finalize" method, we need to hide that one (or rename it, or whatever) + MethodWrapper mw = new SimpleCallMethodWrapper(this, "finalize", "()V", (MethodInfo)mb, PrimitiveTypeWrapper.VOID, TypeWrapper.EmptyArray, mods, MemberFlags.None, SimpleOpCode.Call, SimpleOpCode.Callvirt); + mw.SetDeclaredExceptions(new string[] { "java.lang.Throwable" }); + return mw; + } + ParameterInfo[] parameters = mb.GetParameters(); + Type[] args = new Type[parameters.Length]; + bool hasByRefArgs = false; + bool[] byrefs = null; + for (int i = 0; i < parameters.Length; i++) + { + args[i] = parameters[i].ParameterType; + if (parameters[i].ParameterType.IsByRef) + { + if (byrefs == null) + { + byrefs = new bool[args.Length]; + } + byrefs[i] = true; + hasByRefArgs = true; + } + } + if (privateInterfaceImplHack) + { + mods &= ~Modifiers.Abstract; + mods |= Modifiers.Final; + } + if (hasByRefArgs) + { + if (!(mb is ConstructorInfo) && !mb.IsStatic) + { + mods |= Modifiers.Final; + } + return new ByRefMethodWrapper(args, byrefs, this, name, sig, mb, retTypeWrapper, argTypeWrappers, mods, false); + } + else + { + return new TypicalMethodWrapper(this, name, sig, mb, retTypeWrapper, argTypeWrappers, mods, MemberFlags.None); + } + } + + internal override Type TypeAsTBD + { + get + { + return type; + } + } + + internal override bool IsRemapped + { + get + { + return ClassLoaderWrapper.IsRemappedType(type); + } + } + +#if EMITTERS + internal override void EmitInstanceOf(CodeEmitter ilgen) + { + if (IsRemapped) + { + TypeWrapper shadow = ClassLoaderWrapper.GetWrapperFromType(type); + MethodInfo method = shadow.TypeAsBaseType.GetMethod("__"); + if (method != null) + { + ilgen.Emit(OpCodes.Call, method); + return; + } + } + ilgen.Emit_instanceof(type); + } + + internal override void EmitCheckcast(CodeEmitter ilgen) + { + if (IsRemapped) + { + TypeWrapper shadow = ClassLoaderWrapper.GetWrapperFromType(type); + MethodInfo method = shadow.TypeAsBaseType.GetMethod("__"); + if (method != null) + { + ilgen.Emit(OpCodes.Call, method); + return; + } + } + ilgen.EmitCastclass(type); + } +#endif // EMITTERS + + internal override MethodParametersEntry[] GetMethodParameters(MethodWrapper mw) + { + MethodBase mb = mw.GetMethod(); + if (mb == null) + { + return null; + } + ParameterInfo[] parameters = mb.GetParameters(); + if (parameters.Length == 0) + { + return null; + } + MethodParametersEntry[] mp = new MethodParametersEntry[parameters.Length]; + bool hasName = false; + for (int i = 0; i < mp.Length; i++) + { + string name = parameters[i].Name; + bool empty = String.IsNullOrEmpty(name); + if (empty) + { + name = "arg" + i; + } + mp[i].name = name; + hasName |= !empty; + } + if (!hasName) + { + return null; + } + return mp; + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal override object[] GetDeclaredAnnotations() + { + return type.GetCustomAttributes(false); + } + + internal override object[] GetFieldAnnotations(FieldWrapper fw) + { + FieldInfo fi = fw.GetField(); + if (fi == null) + { + return null; + } + return fi.GetCustomAttributes(false); + } + + internal override object[] GetMethodAnnotations(MethodWrapper mw) + { + MethodBase mb = mw.GetMethod(); + if (mb == null) + { + return null; + } + return mb.GetCustomAttributes(false); + } + + internal override object[][] GetParameterAnnotations(MethodWrapper mw) + { + MethodBase mb = mw.GetMethod(); + if (mb == null) + { + return null; + } + ParameterInfo[] parameters = mb.GetParameters(); + object[][] attribs = new object[parameters.Length][]; + for (int i = 0; i < parameters.Length; i++) + { + attribs[i] = parameters[i].GetCustomAttributes(false); + } + return attribs; + } +#endif + + internal override bool IsFastClassLiteralSafe + { + get { return type != Types.Void && !type.IsPrimitive && !IsRemapped; } + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + // this override is only relevant for the runtime, because it handles the scenario + // where classes are dynamically loaded by the assembly class loader + // (i.e. injected into the assembly) + internal override bool IsPackageAccessibleFrom(TypeWrapper wrapper) + { + if (wrapper == DeclaringTypeWrapper) + { + return true; + } + if (!base.IsPackageAccessibleFrom(wrapper)) + { + return false; + } + // check accessibility for nested types + for (Type type = this.TypeAsTBD; type.IsNested; type = type.DeclaringType) + { + // we don't support family (protected) access + if (!type.IsNestedAssembly && !type.IsNestedFamORAssem && !type.IsNestedPublic) + { + return false; + } + } + return true; + } +#endif + } +} diff --git a/runtime/Dummy.OpenJDK.Core.cs b/runtime/Dummy.OpenJDK.Core.cs new file mode 100644 index 0000000..eac7518 --- /dev/null +++ b/runtime/Dummy.OpenJDK.Core.cs @@ -0,0 +1,102 @@ +/* + Copyright (C) 2010-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +namespace ikvm +{ + namespace @internal + { + public class CallerID { } + } +} + +namespace java +{ + namespace io + { + public class File { } + public class FileDescriptor { } + public class ObjectInputStream { } + public class ObjectOutputStream { } + public class ObjectStreamField { } + public class PrintStream { } + public class PrintWriter { } + } + + namespace lang + { + public class Class { } + public class ClassLoader { } + public class IllegalArgumentException { } + public class SecurityManager { } + public class StackTraceElement { } + + namespace invoke + { + public class DirectMethodHandle { } + public class LambdaForm { } + public class MemberName { } + public class MethodType { } + public class MethodHandle { } + public class CallSite { } + } + + namespace reflect + { + public class Constructor : Executable { } + public class Executable { } + public class Field { } + public class Method : Executable { } + } + } + + namespace net + { + public class URL { } + public class InetAddress { } + } + + namespace nio + { + public class ByteBuffer { } + } + + namespace security + { + public class AccessControlContext { } + public class ProtectionDomain { } + } + + namespace util + { + public class Enumeration { } + public class Vector { } + } +} + +namespace sun.reflect +{ + public interface ConstructorAccessor { } + public interface FieldAccessor { } + public interface MethodAccessor { } +} diff --git a/runtime/DynamicClassLoader.cs b/runtime/DynamicClassLoader.cs new file mode 100644 index 0000000..e31fbc7 --- /dev/null +++ b/runtime/DynamicClassLoader.cs @@ -0,0 +1,603 @@ +/* + Copyright (C) 2002-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.Serialization; +using System.Security.Cryptography; +#if STATIC_COMPILER +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; +using ProtectionDomain = System.Object; +#else +using System.Reflection; +using System.Reflection.Emit; +using ProtectionDomain = java.security.ProtectionDomain; +#endif + +namespace IKVM.Internal +{ + sealed class DynamicClassLoader : TypeWrapperFactory + { + // this PublicKey must be the same as the byte array in ForgedKeyPair + internal const string DynamicAssemblySuffixAndPublicKey = "-ikvm-runtime-injected, PublicKey=00240000048000009400000006020000002400005253413100040000010001009D674F3D63B8D7A4C428BD7388341B025C71AA61C6224CD53A12C21330A3159D300051FE2EED154FE30D70673A079E4529D0FD78113DCA771DA8B0C1EF2F77B73651D55645B0A4294F0AF9BF7078432E13D0F46F951D712C2FCF02EB15552C0FE7817FC0AED58E0984F86661BF64D882F29B619899DD264041E7D4992548EB9E"; +#if !STATIC_COMPILER + private static AssemblyBuilder jniProxyAssemblyBuilder; + private static List saveClassLoaders; + private static int dumpCounter; +#endif // !STATIC_COMPILER +#if STATIC_COMPILER || CLASSGC + private readonly Dictionary dynamicTypes = new Dictionary(); +#else + private static readonly Dictionary dynamicTypes = new Dictionary(); +#endif + private readonly ModuleBuilder moduleBuilder; + private readonly bool hasInternalAccess; +#if STATIC_COMPILER + private TypeBuilder proxiesContainer; + private List proxies; +#endif // STATIC_COMPILER + private Dictionary unloadables; + private TypeBuilder unloadableContainer; + private Type[] delegates; +#if !STATIC_COMPILER && !CLASSGC + private static DynamicClassLoader instance = new DynamicClassLoader(CreateModuleBuilder(), false); +#endif +#if CLASSGC + private List friends = new List(); +#endif + + [System.Security.SecuritySafeCritical] + static DynamicClassLoader() + { +#if !STATIC_COMPILER + // TODO AppDomain.TypeResolve requires ControlAppDomain permission, but if we don't have that, + // we should handle that by disabling dynamic class loading + AppDomain.CurrentDomain.TypeResolve += new ResolveEventHandler(OnTypeResolve); +#if !CLASSGC + // Ref.Emit doesn't like the "" name for types + // (since it already defines a pseudo-type named for global methods and fields) + dynamicTypes.Add("", null); +#endif // !CLASSGC +#endif // !STATIC_COMPILER + } + + internal DynamicClassLoader(ModuleBuilder moduleBuilder, bool hasInternalAccess) + { + this.moduleBuilder = moduleBuilder; + this.hasInternalAccess = hasInternalAccess; + +#if !STATIC_COMPILER + if (JVM.IsSaveDebugImage) + { + if (saveClassLoaders == null) + { + System.Threading.Interlocked.CompareExchange(ref saveClassLoaders, new List(), null); + } + lock (saveClassLoaders) + { + saveClassLoaders.Add(this); + } + } +#endif + +#if STATIC_COMPILER || CLASSGC + // Ref.Emit doesn't like the "" name for types + // (since it already defines a pseudo-type named for global methods and fields) + dynamicTypes.Add("", null); +#endif + } + +#if CLASSGC + internal override void AddInternalsVisibleTo(Assembly friend) + { + string name = friend.GetName().Name; + lock (friends) + { + if (!friends.Contains(name)) + { + friends.Add(name); + AttributeHelper.SetInternalsVisibleToAttribute((AssemblyBuilder)moduleBuilder.Assembly, name); + } + } + } +#endif // CLASSGC + +#if !STATIC_COMPILER + private static Assembly OnTypeResolve(object sender, ResolveEventArgs args) + { +#if CLASSGC + ClassLoaderWrapper loader = ClassLoaderWrapper.GetClassLoaderForDynamicJavaAssembly(args.RequestingAssembly); + if (loader == null) + { + return null; + } + DynamicClassLoader instance = (DynamicClassLoader)loader.GetTypeWrapperFactory(); + return Resolve(instance.dynamicTypes, args.Name); +#else + return Resolve(dynamicTypes, args.Name); +#endif + } + + private static Assembly Resolve(Dictionary dict, string name) + { + TypeWrapper type; + lock (dict) + { + dict.TryGetValue(name, out type); + } + if (type == null) + { + return null; + } + try + { + type.Finish(); + } + catch(RetargetableJavaException x) + { + throw x.ToJava(); + } + // NOTE We used to remove the type from the hashtable here, but that creates a race condition if + // another thread also fires the OnTypeResolve event while we're baking the type. + // I really would like to remove the type from the hashtable, but at the moment I don't see + // any way of doing that that wouldn't cause this race condition. + // UPDATE since we now also use the dynamicTypes hashtable to keep track of type names that + // have been used already, we cannot remove the keys. + return type.TypeAsTBD.Assembly; + } +#endif // !STATIC_COMPILER + + internal override bool ReserveName(string name) + { + lock(dynamicTypes) + { + if(dynamicTypes.ContainsKey(name)) + { + return false; + } + dynamicTypes.Add(name, null); + return true; + } + } + + internal override string AllocMangledName(DynamicTypeWrapper tw) + { + lock(dynamicTypes) + { + return TypeNameMangleImpl(dynamicTypes, tw.Name, tw); + } + } + + internal static string TypeNameMangleImpl(Dictionary dict, string name, TypeWrapper tw) + { + // the CLR maximum type name length is 1023 characters, + // but we need to leave some room for the suffix that we + // may need to append to make the name unique + const int MaxLength = 1000; + if (name.Length > MaxLength) + { + name = name.Substring(0, MaxLength) + "/truncated"; + } + string mangledTypeName = TypeNameUtil.ReplaceIllegalCharacters(name); + // FXBUG the CLR (both 1.1 and 2.0) doesn't like type names that end with a single period, + // it loses the trailing period in the name that gets passed in the TypeResolve event. + if (dict.ContainsKey(mangledTypeName) || mangledTypeName.EndsWith(".")) + { +#if STATIC_COMPILER + Tracer.Warning(Tracer.Compiler, "Class name clash: {0}", mangledTypeName); +#endif + // Java class names cannot contain slashes (since they are converted into periods), + // so we take advantage of that fact to create a unique name. + string baseName = mangledTypeName; + int instanceId = 0; + do + { + mangledTypeName = baseName + "/" + (++instanceId); + } while (dict.ContainsKey(mangledTypeName)); + } + dict.Add(mangledTypeName, tw); + return mangledTypeName; + } + + internal sealed override TypeWrapper DefineClassImpl(Dictionary types, TypeWrapper host, ClassFile f, ClassLoaderWrapper classLoader, ProtectionDomain protectionDomain) + { +#if STATIC_COMPILER + AotTypeWrapper type = new AotTypeWrapper(f, (CompilerClassLoader)classLoader); + type.CreateStep1(); + types[f.Name] = type; + return type; +#elif FIRST_PASS + return null; +#else + // this step can throw a retargettable exception, if the class is incorrect + DynamicTypeWrapper type = new DynamicTypeWrapper(host, f, classLoader, protectionDomain); + // This step actually creates the TypeBuilder. It is not allowed to throw any exceptions, + // if an exception does occur, it is due to a programming error in the IKVM or CLR runtime + // and will cause a CriticalFailure and exit the process. + type.CreateStep1(); + type.CreateStep2(); + if(types == null) + { + // we're defining an anonymous class, so we don't need any locking + TieClassAndWrapper(type, protectionDomain); + return type; + } + lock(types) + { + // in very extreme conditions another thread may have beaten us to it + // and loaded (not defined) a class with the same name, in that case + // we'll leak the the Reflection.Emit defined type. Also see the comment + // in ClassLoaderWrapper.RegisterInitiatingLoader(). + TypeWrapper race; + types.TryGetValue(f.Name, out race); + if(race == null) + { + types[f.Name] = type; + TieClassAndWrapper(type, protectionDomain); + } + else + { + throw new LinkageError("duplicate class definition: " + f.Name); + } + } + return type; +#endif // STATIC_COMPILER + } + +#if !STATIC_COMPILER && !FIRST_PASS + private static java.lang.Class TieClassAndWrapper(TypeWrapper type, ProtectionDomain protectionDomain) + { + java.lang.Class clazz = new java.lang.Class(null); +#if __MonoCS__ + TypeWrapper.SetTypeWrapperHack(clazz, type); +#else + clazz.typeWrapper = type; +#endif + clazz.pd = protectionDomain; + type.SetClassObject(clazz); + return clazz; + } +#endif + +#if STATIC_COMPILER + internal TypeBuilder DefineProxy(string name, TypeAttributes typeAttributes, Type parent, Type[] interfaces) + { + if (proxiesContainer == null) + { + proxiesContainer = moduleBuilder.DefineType(TypeNameUtil.ProxiesContainer, TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.Abstract); + AttributeHelper.HideFromJava(proxiesContainer); + AttributeHelper.SetEditorBrowsableNever(proxiesContainer); + proxies = new List(); + } + TypeBuilder tb = proxiesContainer.DefineNestedType(name, typeAttributes, parent, interfaces); + proxies.Add(tb); + return tb; + } +#endif + + internal override Type DefineUnloadable(string name) + { + lock(this) + { + if(unloadables == null) + { + unloadables = new Dictionary(); + } + TypeBuilder type; + if(unloadables.TryGetValue(name, out type)) + { + return type; + } + if(unloadableContainer == null) + { + unloadableContainer = moduleBuilder.DefineType(UnloadableTypeWrapper.ContainerTypeName, TypeAttributes.Interface | TypeAttributes.Abstract); + AttributeHelper.HideFromJava(unloadableContainer); + } + type = unloadableContainer.DefineNestedType(TypeNameUtil.MangleNestedTypeName(name), TypeAttributes.NestedPrivate | TypeAttributes.Interface | TypeAttributes.Abstract); + unloadables.Add(name, type); + return type; + } + } + + internal override Type DefineDelegate(int parameterCount, bool returnVoid) + { + lock (this) + { + if (delegates == null) + { + delegates = new Type[512]; + } + int index = parameterCount + (returnVoid ? 256 : 0); + Type type = delegates[index]; + if (type != null) + { + return type; + } + TypeBuilder tb = moduleBuilder.DefineType(returnVoid ? "__<>NVIV`" + parameterCount : "__<>NVI`" + (parameterCount + 1), TypeAttributes.NotPublic | TypeAttributes.Sealed, Types.MulticastDelegate); + string[] names = new string[parameterCount + (returnVoid ? 0 : 1)]; + for (int i = 0; i < names.Length; i++) + { + names[i] = "P" + i; + } + if (!returnVoid) + { + names[names.Length - 1] = "R"; + } + Type[] genericParameters = tb.DefineGenericParameters(names); + Type[] parameterTypes = genericParameters; + if (!returnVoid) + { + parameterTypes = new Type[genericParameters.Length - 1]; + Array.Copy(genericParameters, parameterTypes, parameterTypes.Length); + } + tb.DefineMethod(ConstructorInfo.ConstructorName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, Types.Void, new Type[] { Types.Object, Types.IntPtr }) + .SetImplementationFlags(MethodImplAttributes.Runtime); + MethodBuilder mb = tb.DefineMethod("Invoke", MethodAttributes.Public | MethodAttributes.NewSlot | MethodAttributes.Virtual, returnVoid ? Types.Void : genericParameters[genericParameters.Length - 1], parameterTypes); + mb.SetImplementationFlags(MethodImplAttributes.Runtime); + type = tb.CreateType(); + delegates[index] = type; + return type; + } + } + + internal override bool HasInternalAccess + { + get { return hasInternalAccess; } + } + + internal void FinishAll() + { + Dictionary done = new Dictionary(); + bool more = true; + while(more) + { + more = false; + List l = new List(dynamicTypes.Values); + foreach(TypeWrapper tw in l) + { + if(tw != null && !done.ContainsKey(tw)) + { + more = true; + done.Add(tw, tw); + Tracer.Info(Tracer.Runtime, "Finishing {0}", tw.TypeAsTBD.FullName); + tw.Finish(); + } + } + } + if(unloadableContainer != null) + { + unloadableContainer.CreateType(); + foreach(TypeBuilder tb in unloadables.Values) + { + tb.CreateType(); + } + } +#if STATIC_COMPILER + if(proxiesContainer != null) + { + proxiesContainer.CreateType(); + foreach(TypeBuilder tb in proxies) + { + tb.CreateType(); + } + } +#endif // STATIC_COMPILER + } + +#if !STATIC_COMPILER + internal static void SaveDebugImages() + { + Console.Error.WriteLine("Saving dynamic assemblies..."); + JVM.FinishingForDebugSave = true; + if (saveClassLoaders != null) + { + foreach (DynamicClassLoader instance in saveClassLoaders) + { + instance.FinishAll(); + AssemblyBuilder ab = (AssemblyBuilder)instance.ModuleBuilder.Assembly; + SaveDebugAssembly(ab); + } + } + if (jniProxyAssemblyBuilder != null) + { + SaveDebugAssembly(jniProxyAssemblyBuilder); + } + Console.Error.WriteLine("Saving done."); + } + + private static void SaveDebugAssembly(AssemblyBuilder ab) + { + Console.Error.WriteLine("Saving '{0}'", ab.GetName().Name + ".dll"); + ab.Save(ab.GetName().Name + ".dll"); + } + + internal static ModuleBuilder CreateJniProxyModuleBuilder() + { + AssemblyName name = new AssemblyName(); + name.Name = "jniproxy"; + jniProxyAssemblyBuilder = DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave, null); + return jniProxyAssemblyBuilder.DefineDynamicModule("jniproxy.dll", "jniproxy.dll"); + } +#endif + + internal sealed override ModuleBuilder ModuleBuilder + { + get + { + return moduleBuilder; + } + } + + [System.Security.SecuritySafeCritical] + internal static DynamicClassLoader Get(ClassLoaderWrapper loader) + { +#if STATIC_COMPILER + return new DynamicClassLoader(((CompilerClassLoader)loader).CreateModuleBuilder(), false); +#else + AssemblyClassLoader acl = loader as AssemblyClassLoader; + if (acl != null && ForgedKeyPair.Instance != null) + { + string name = acl.MainAssembly.GetName().Name + DynamicAssemblySuffixAndPublicKey; + foreach (InternalsVisibleToAttribute attr in acl.MainAssembly.GetCustomAttributes(typeof(InternalsVisibleToAttribute), false)) + { + if (attr.AssemblyName == name) + { + AssemblyName n = new AssemblyName(name); + n.KeyPair = ForgedKeyPair.Instance; + return new DynamicClassLoader(CreateModuleBuilder(n), true); + } + } + } +#if CLASSGC + DynamicClassLoader instance = new DynamicClassLoader(CreateModuleBuilder(), false); +#endif + return instance; +#endif + } + +#if !STATIC_COMPILER + sealed class ForgedKeyPair : StrongNameKeyPair + { + internal static readonly StrongNameKeyPair Instance; + + static ForgedKeyPair() + { + try + { + // this public key byte array must be the same as the public key in DynamicAssemblySuffixAndPublicKey + Instance = new ForgedKeyPair(new byte[] { + 0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x94, 0x00, 0x00, + 0x00, 0x06, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, + 0x41, 0x31, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x9D, + 0x67, 0x4F, 0x3D, 0x63, 0xB8, 0xD7, 0xA4, 0xC4, 0x28, 0xBD, 0x73, + 0x88, 0x34, 0x1B, 0x02, 0x5C, 0x71, 0xAA, 0x61, 0xC6, 0x22, 0x4C, + 0xD5, 0x3A, 0x12, 0xC2, 0x13, 0x30, 0xA3, 0x15, 0x9D, 0x30, 0x00, + 0x51, 0xFE, 0x2E, 0xED, 0x15, 0x4F, 0xE3, 0x0D, 0x70, 0x67, 0x3A, + 0x07, 0x9E, 0x45, 0x29, 0xD0, 0xFD, 0x78, 0x11, 0x3D, 0xCA, 0x77, + 0x1D, 0xA8, 0xB0, 0xC1, 0xEF, 0x2F, 0x77, 0xB7, 0x36, 0x51, 0xD5, + 0x56, 0x45, 0xB0, 0xA4, 0x29, 0x4F, 0x0A, 0xF9, 0xBF, 0x70, 0x78, + 0x43, 0x2E, 0x13, 0xD0, 0xF4, 0x6F, 0x95, 0x1D, 0x71, 0x2C, 0x2F, + 0xCF, 0x02, 0xEB, 0x15, 0x55, 0x2C, 0x0F, 0xE7, 0x81, 0x7F, 0xC0, + 0xAE, 0xD5, 0x8E, 0x09, 0x84, 0xF8, 0x66, 0x61, 0xBF, 0x64, 0xD8, + 0x82, 0xF2, 0x9B, 0x61, 0x98, 0x99, 0xDD, 0x26, 0x40, 0x41, 0xE7, + 0xD4, 0x99, 0x25, 0x48, 0xEB, 0x9E + }); + } + catch + { + } + } + + private ForgedKeyPair(byte[] publicKey) + : base(ToInfo(publicKey), new StreamingContext()) + { + } + + private static SerializationInfo ToInfo(byte[] publicKey) + { + byte[] privateKey = publicKey; + if (JVM.IsSaveDebugImage) + { + CspParameters cspParams = new CspParameters(); + cspParams.KeyContainerName = null; + cspParams.Flags = CspProviderFlags.UseArchivableKey; + cspParams.KeyNumber = 2; + RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024, cspParams); + privateKey = rsa.ExportCspBlob(true); + } + SerializationInfo info = new SerializationInfo(typeof(StrongNameKeyPair), new FormatterConverter()); + info.AddValue("_keyPairExported", true); + info.AddValue("_keyPairArray", privateKey); + info.AddValue("_keyPairContainer", null); + info.AddValue("_publicKey", publicKey); + return info; + } + } + + private static ModuleBuilder CreateModuleBuilder() + { + AssemblyName name = new AssemblyName(); + if(JVM.IsSaveDebugImage) + { + name.Name = "ikvmdump-" + System.Threading.Interlocked.Increment(ref dumpCounter); + } + else + { + name.Name = "ikvm_dynamic_assembly__" + (uint)Environment.TickCount; + } + return CreateModuleBuilder(name); + } + + private static ModuleBuilder CreateModuleBuilder(AssemblyName name) + { + DateTime now = DateTime.Now; + name.Version = new Version(now.Year, (now.Month * 100) + now.Day, (now.Hour * 100) + now.Minute, (now.Second * 1000) + now.Millisecond); + List attribs = new List(); + AssemblyBuilderAccess access; + if(JVM.IsSaveDebugImage) + { + access = AssemblyBuilderAccess.RunAndSave; + } +#if CLASSGC + else if(JVM.classUnloading + // DefineDynamicAssembly(..., RunAndCollect, ...) does a demand for PermissionSet(Unrestricted), so we want to avoid that in partial trust scenarios + && AppDomain.CurrentDomain.IsFullyTrusted) + { + access = AssemblyBuilderAccess.RunAndCollect; + } +#endif + else + { + access = AssemblyBuilderAccess.Run; + } +#if NET_4_0 + if(!AppDomain.CurrentDomain.IsFullyTrusted) + { + attribs.Add(new CustomAttributeBuilder(typeof(System.Security.SecurityTransparentAttribute).GetConstructor(Type.EmptyTypes), new object[0])); + } +#endif + AssemblyBuilder assemblyBuilder = DefineDynamicAssembly(name, access, attribs); + AttributeHelper.SetRuntimeCompatibilityAttribute(assemblyBuilder); + bool debug = JVM.EmitSymbols; + CustomAttributeBuilder debugAttr = new CustomAttributeBuilder(typeof(DebuggableAttribute).GetConstructor(new Type[] { typeof(bool), typeof(bool) }), new object[] { true, debug }); + assemblyBuilder.SetCustomAttribute(debugAttr); + ModuleBuilder moduleBuilder = JVM.IsSaveDebugImage ? assemblyBuilder.DefineDynamicModule(name.Name, name.Name + ".dll", debug) : assemblyBuilder.DefineDynamicModule(name.Name, debug); + moduleBuilder.SetCustomAttribute(new CustomAttributeBuilder(typeof(IKVM.Attributes.JavaModuleAttribute).GetConstructor(Type.EmptyTypes), new object[0])); + return moduleBuilder; + } + + private static AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access, IEnumerable assemblyAttributes) + { +#if NET_4_0 + return AppDomain.CurrentDomain.DefineDynamicAssembly(name, access, null, true, assemblyAttributes); +#else + return AppDomain.CurrentDomain.DefineDynamicAssembly(name, access, null, null, null, null, null, true, assemblyAttributes); +#endif + } +#endif // !STATIC_COMPILER + } +} diff --git a/runtime/DynamicMethodUtils.cs b/runtime/DynamicMethodUtils.cs new file mode 100644 index 0000000..d1e2cc0 --- /dev/null +++ b/runtime/DynamicMethodUtils.cs @@ -0,0 +1,92 @@ +/* + Copyright (C) 2007-2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Reflection; +using System.Reflection.Emit; +using System.Security; +using System.Security.Permissions; +using System.Threading; +using IKVM.Internal; + +static class DynamicMethodUtils +{ +#if NET_4_0 + private static Module dynamicModule; +#endif + + [SecuritySafeCritical] + internal static DynamicMethod Create(string name, Type owner, bool nonPublic, Type returnType, Type[] paramTypes) + { + try + { +#if NET_4_0 + if (dynamicModule == null) + { + // we have to create a module that is security critical to hold the dynamic method, if we want to be able to emit unverifiable code + AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(""), AssemblyBuilderAccess.RunAndCollect); + Interlocked.CompareExchange(ref dynamicModule, ab.DefineDynamicModule(""), null); + } + return new DynamicMethod(name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, paramTypes, dynamicModule, true); +#else + if (!ReflectUtil.CanOwnDynamicMethod(owner)) + { + // interfaces and arrays aren't allowed as owners of dynamic methods + return new DynamicMethod(name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, paramTypes, owner.Module, true); + } + else + { + return new DynamicMethod(name, returnType, paramTypes, owner); + } +#endif + } + catch (SecurityException) + { + if (nonPublic && !RestrictedMemberAccess) + { + // we don't have RestrictedMemberAccess, so we stick the dynamic method in our module and hope for the best + // (i.e. that we're trying to access something with assembly access in an assembly that lets us) + return new DynamicMethod(name, returnType, paramTypes, typeof(DynamicMethodUtils).Module); + } + // apparently we don't have full trust, so we try again with .NET 2.0 SP1 method + // and we only request restrictSkipVisibility if it is required + return new DynamicMethod(name, returnType, paramTypes, nonPublic); + } + } + + private static bool RestrictedMemberAccess + { + get + { + try + { + new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess).Demand(); + return true; + } + catch (SecurityException) + { + return false; + } + } + } +} diff --git a/runtime/DynamicTypeWrapper.cs b/runtime/DynamicTypeWrapper.cs new file mode 100644 index 0000000..72685c1 --- /dev/null +++ b/runtime/DynamicTypeWrapper.cs @@ -0,0 +1,7390 @@ +/* + Copyright (C) 2002-2015 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +#if STATIC_COMPILER +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; +using DynamicOrAotTypeWrapper = IKVM.Internal.AotTypeWrapper; +using ProtectionDomain = System.Object; +#else +using System.Reflection; +using System.Reflection.Emit; +using DynamicOrAotTypeWrapper = IKVM.Internal.DynamicTypeWrapper; +using ProtectionDomain = java.security.ProtectionDomain; +#endif +using System.Diagnostics; +using System.Security; +using System.Security.Permissions; +using IKVM.Attributes; + +namespace IKVM.Internal +{ +#if STATIC_COMPILER + abstract class DynamicTypeWrapper : TypeWrapper +#else +#pragma warning disable 628 // don't complain about protected members in sealed type + sealed class DynamicTypeWrapper : TypeWrapper +#endif + { +#if STATIC_COMPILER + protected readonly CompilerClassLoader classLoader; +#else + protected readonly ClassLoaderWrapper classLoader; +#endif + private volatile DynamicImpl impl; + private readonly TypeWrapper baseTypeWrapper; + private readonly TypeWrapper[] interfaces; + private readonly string sourceFileName; +#if !STATIC_COMPILER + private byte[][] lineNumberTables; +#endif + private MethodBase automagicSerializationCtor; + + private TypeWrapper LoadTypeWrapper(ClassLoaderWrapper classLoader, ProtectionDomain pd, ClassFile.ConstantPoolItemClass clazz) + { + // check for patched constant pool items + TypeWrapper tw = clazz.GetClassType(); + if (tw == null || tw == VerifierTypeWrapper.Null) + { + tw = classLoader.LoadClassByDottedNameFast(clazz.Name); + } + if (tw == null) + { + throw new NoClassDefFoundError(clazz.Name); + } + CheckMissing(this, tw); + classLoader.CheckPackageAccess(tw, pd); + return tw; + } + + private static void CheckMissing(TypeWrapper prev, TypeWrapper tw) + { +#if STATIC_COMPILER + do + { + UnloadableTypeWrapper missing = tw as UnloadableTypeWrapper; + if (missing != null) + { + Type mt = ReflectUtil.GetMissingType(missing.MissingType); + if (mt.Assembly.__IsMissing) + { + throw new FatalCompilerErrorException(Message.MissingBaseTypeReference, mt.FullName, mt.Assembly.FullName); + } + throw new FatalCompilerErrorException(Message.MissingBaseType, mt.FullName, mt.Assembly.FullName, + prev.TypeAsBaseType.FullName, prev.TypeAsBaseType.Module.Name); + } + foreach (TypeWrapper iface in tw.Interfaces) + { + CheckMissing(tw, iface); + } + prev = tw; + tw = tw.BaseTypeWrapper; + } + while (tw != null); +#endif + } + +#if STATIC_COMPILER + internal DynamicTypeWrapper(TypeWrapper host, ClassFile f, CompilerClassLoader classLoader, ProtectionDomain pd) +#else + internal DynamicTypeWrapper(TypeWrapper host, ClassFile f, ClassLoaderWrapper classLoader, ProtectionDomain pd) +#endif + : base(f.IsInternal ? TypeFlags.InternalAccess : host != null ? TypeFlags.Anonymous : TypeFlags.None, f.Modifiers, f.Name) + { + Profiler.Count("DynamicTypeWrapper"); + this.classLoader = classLoader; + this.sourceFileName = f.SourceFileAttribute; + if (f.IsInterface) + { + // interfaces can't "override" final methods in object + foreach (ClassFile.Method method in f.Methods) + { + MethodWrapper mw; + if (method.IsVirtual + && (mw = CoreClasses.java.lang.Object.Wrapper.GetMethodWrapper(method.Name, method.Signature, false)) != null + && mw.IsVirtual + && mw.IsFinal) + { + throw new VerifyError("class " + f.Name + " overrides final method " + method.Name + "." + method.Signature); + } + } + } + else + { + this.baseTypeWrapper = LoadTypeWrapper(classLoader, pd, f.SuperClass); + if (!BaseTypeWrapper.IsAccessibleFrom(this)) + { + throw new IllegalAccessError("Class " + f.Name + " cannot access its superclass " + BaseTypeWrapper.Name); + } + if (BaseTypeWrapper.IsFinal) + { + throw new VerifyError("Class " + f.Name + " extends final class " + BaseTypeWrapper.Name); + } + if (BaseTypeWrapper.IsInterface) + { + throw new IncompatibleClassChangeError("Class " + f.Name + " has interface " + BaseTypeWrapper.Name + " as superclass"); + } + if (BaseTypeWrapper.TypeAsTBD == Types.Delegate) + { + throw new VerifyError(BaseTypeWrapper.Name + " cannot be used as a base class"); + } + // NOTE defining value types, enums is not supported in IKVM v1 + if (BaseTypeWrapper.TypeAsTBD == Types.ValueType || BaseTypeWrapper.TypeAsTBD == Types.Enum) + { + throw new VerifyError("Defining value types in Java is not implemented in IKVM v1"); + } + if (IsDelegate) + { + VerifyDelegate(f); + } +#if CLASSGC + if (JVM.classUnloading && BaseTypeWrapper.TypeAsBaseType == typeof(ContextBoundObject)) + { + throw new VerifyError("Extending ContextBoundObject is not supported in dynamic mode with class GC enabled."); + } +#endif + } + +#if CLASSGC + if (JVM.classUnloading) + { + VerifyRunAndCollect(f); + } +#endif + + ClassFile.ConstantPoolItemClass[] interfaces = f.Interfaces; + this.interfaces = new TypeWrapper[interfaces.Length]; + for (int i = 0; i < interfaces.Length; i++) + { + TypeWrapper iface = LoadTypeWrapper(classLoader, pd, interfaces[i]); + if (!iface.IsAccessibleFrom(this)) + { + throw new IllegalAccessError("Class " + f.Name + " cannot access its superinterface " + iface.Name); + } + if (!iface.IsInterface) + { + throw new IncompatibleClassChangeError("Implementing class"); + } + this.interfaces[i] = iface; + } + + impl = new JavaTypeImpl(host, f, this); + } + +#if CLASSGC + private static void VerifyRunAndCollect(ClassFile f) + { + if (f.Annotations != null) + { + foreach (object[] ann in f.Annotations) + { + if (ann[1].Equals("Lcli/System/Runtime/InteropServices/ComImportAttribute$Annotation;")) + { + throw new VerifyError("ComImportAttribute is not supported in dynamic mode with class GC enabled."); + } + } + } + foreach (ClassFile.Field field in f.Fields) + { + if (field.Annotations != null) + { + foreach (object[] ann in field.Annotations) + { + if (ann[1].Equals("Lcli/System/ThreadStaticAttribute$Annotation;")) + { + throw new VerifyError("ThreadStaticAttribute is not supported in dynamic mode with class GC enabled."); + } + if (ann[1].Equals("Lcli/System/ContextStaticAttribute$Annotation;")) + { + throw new VerifyError("ContextStaticAttribute is not supported in dynamic mode with class GC enabled."); + } + } + } + } + foreach (ClassFile.Method method in f.Methods) + { + if (method.Annotations != null) + { + foreach (object[] ann in method.Annotations) + { + if (ann[1].Equals("Lcli/System/Runtime/InteropServices/DllImportAttribute$Annotation;")) + { + throw new VerifyError("DllImportAttribute is not supported in dynamic mode with class GC enabled."); + } + } + } + } + } +#endif + + private void VerifyDelegate(ClassFile f) + { + if (!f.IsFinal) + { + throw new VerifyError("Delegate must be final"); + } + ClassFile.Method invoke = null; + ClassFile.Method beginInvoke = null; + ClassFile.Method endInvoke = null; + ClassFile.Method constructor = null; + foreach (ClassFile.Method m in f.Methods) + { + if (m.Name == "Invoke") + { + if (invoke != null) + { + throw new VerifyError("Delegate may only have a single Invoke method"); + } + invoke = m; + } + else if (m.Name == "BeginInvoke") + { + if (beginInvoke != null) + { + throw new VerifyError("Delegate may only have a single BeginInvoke method"); + } + beginInvoke = m; + } + else if (m.Name == "EndInvoke") + { + if (endInvoke != null) + { + throw new VerifyError("Delegate may only have a single EndInvoke method"); + } + endInvoke = m; + } + else if (m.Name == "") + { + if (constructor != null) + { + throw new VerifyError("Delegate may only have a single constructor"); + } + constructor = m; + } + else if (m.IsNative) + { + throw new VerifyError("Delegate may not have any native methods besides Invoke, BeginInvoke and EndInvoke"); + } + } + if (invoke == null || constructor == null) + { + throw new VerifyError("Delegate must have a constructor and an Invoke method"); + } + if (!invoke.IsPublic || !invoke.IsNative || invoke.IsFinal || invoke.IsStatic) + { + throw new VerifyError("Delegate Invoke method must be a public native non-final instance method"); + } + if ((beginInvoke != null && endInvoke == null) || (beginInvoke == null && endInvoke != null)) + { + throw new VerifyError("Delegate must have both BeginInvoke and EndInvoke or neither"); + } + if (!constructor.IsPublic) + { + throw new VerifyError("Delegate constructor must be public"); + } + if (constructor.Instructions.Length < 3 + || constructor.Instructions[0].NormalizedOpCode != NormalizedByteCode.__aload + || constructor.Instructions[0].NormalizedArg1 != 0 + || constructor.Instructions[1].NormalizedOpCode != NormalizedByteCode.__invokespecial + || constructor.Instructions[2].NormalizedOpCode != NormalizedByteCode.__return) + { + throw new VerifyError("Delegate constructor must be empty"); + } + if (f.Fields.Length != 0) + { + throw new VerifyError("Delegate may not declare any fields"); + } + TypeWrapper iface = classLoader.LoadClassByDottedNameFast(f.Name + DotNetTypeWrapper.DelegateInterfaceSuffix); + DelegateInnerClassCheck(iface != null); + DelegateInnerClassCheck(iface.IsInterface); + DelegateInnerClassCheck(iface.IsPublic); + DelegateInnerClassCheck(iface.GetClassLoader() == classLoader); + MethodWrapper[] methods = iface.GetMethods(); + DelegateInnerClassCheck(methods.Length == 1 && methods[0].Name == "Invoke"); + if (methods[0].Signature != invoke.Signature) + { + throw new VerifyError("Delegate Invoke method signature must be identical to inner interface Invoke method signature"); + } + if (iface.Interfaces.Length != 0) + { + throw new VerifyError("Delegate inner interface may not extend any interfaces"); + } + if (constructor.Signature != "(" + iface.SigName + ")V") + { + throw new VerifyError("Delegate constructor must take a single argument of type inner Method interface"); + } + if (beginInvoke != null && beginInvoke.Signature != invoke.Signature.Substring(0, invoke.Signature.IndexOf(')')) + "Lcli.System.AsyncCallback;Ljava.lang.Object;)Lcli.System.IAsyncResult;") + { + throw new VerifyError("Delegate BeginInvoke method has incorrect signature"); + } + if (endInvoke != null && endInvoke.Signature != "(Lcli.System.IAsyncResult;)" + invoke.Signature.Substring(invoke.Signature.IndexOf(')') + 1)) + { + throw new VerifyError("Delegate EndInvoke method has incorrect signature"); + } + } + + private static void DelegateInnerClassCheck(bool cond) + { + if (!cond) + { + throw new VerifyError("Delegate must have a public inner interface named Method with a single method named Invoke"); + } + } + + private bool IsDelegate + { + get + { + TypeWrapper baseTypeWrapper = BaseTypeWrapper; + return baseTypeWrapper != null && baseTypeWrapper.TypeAsTBD == Types.MulticastDelegate; + } + } + + internal sealed override TypeWrapper BaseTypeWrapper + { + get { return baseTypeWrapper; } + } + + internal override ClassLoaderWrapper GetClassLoader() + { + return classLoader; + } + + internal override Modifiers ReflectiveModifiers + { + get + { + return impl.ReflectiveModifiers; + } + } + + internal override TypeWrapper[] Interfaces + { + get + { + return interfaces; + } + } + + internal override TypeWrapper[] InnerClasses + { + get + { + return impl.InnerClasses; + } + } + + internal override TypeWrapper DeclaringTypeWrapper + { + get + { + return impl.DeclaringTypeWrapper; + } + } + + internal override Type TypeAsTBD + { + get + { + return impl.Type; + } + } + + internal override void Finish() + { + // we don't need locking, because Finish is Thread safe + impl = impl.Finish(); + } + + internal void CreateStep1() + { + ((JavaTypeImpl)impl).CreateStep1(); + } + + internal void CreateStep2() + { + ((JavaTypeImpl)impl).CreateStep2(); + } + + private bool IsSerializable + { + get + { + return this.IsSubTypeOf(CoreClasses.java.io.Serializable.Wrapper); + } + } + + private abstract class DynamicImpl + { + internal abstract Type Type { get; } + internal abstract TypeWrapper[] InnerClasses { get; } + internal abstract TypeWrapper DeclaringTypeWrapper { get; } + internal abstract Modifiers ReflectiveModifiers { get; } + internal abstract DynamicImpl Finish(); + internal abstract MethodBase LinkMethod(MethodWrapper mw); + internal abstract FieldInfo LinkField(FieldWrapper fw); + internal abstract void EmitRunClassConstructor(CodeEmitter ilgen); + internal abstract string GetGenericSignature(); + internal abstract string[] GetEnclosingMethod(); + internal abstract string GetGenericMethodSignature(int index); + internal abstract string GetGenericFieldSignature(int index); + internal abstract object[] GetDeclaredAnnotations(); + internal abstract object GetMethodDefaultValue(int index); + internal abstract object[] GetMethodAnnotations(int index); + internal abstract object[][] GetParameterAnnotations(int index); + internal abstract MethodParametersEntry[] GetMethodParameters(int index); + internal abstract object[] GetFieldAnnotations(int index); + internal abstract MethodInfo GetFinalizeMethod(); + internal abstract object[] GetConstantPool(); + internal abstract byte[] GetRawTypeAnnotations(); + internal abstract byte[] GetMethodRawTypeAnnotations(int index); + internal abstract byte[] GetFieldRawTypeAnnotations(int index); + internal abstract TypeWrapper Host { get; } + } + + private sealed class JavaTypeImpl : DynamicImpl + { + private readonly TypeWrapper host; + private readonly ClassFile classFile; + private readonly DynamicOrAotTypeWrapper wrapper; + private TypeBuilder typeBuilder; + private MethodWrapper[] methods; + private MethodWrapper[][] baseMethods; + private FieldWrapper[] fields; + private FinishedTypeImpl finishedType; + private bool finishInProgress; + private MethodBuilder clinitMethod; + private MethodBuilder finalizeMethod; + private int recursionCount; +#if STATIC_COMPILER + private DynamicTypeWrapper enclosingClassWrapper; + private AnnotationBuilder annotationBuilder; + private TypeBuilder enumBuilder; + private TypeBuilder privateInterfaceMethods; + private Dictionary nestedTypeNames; // only keys are used, values are always null +#endif + + internal JavaTypeImpl(TypeWrapper host, ClassFile f, DynamicTypeWrapper wrapper) + { + Tracer.Info(Tracer.Compiler, "constructing JavaTypeImpl for " + f.Name); + this.host = host; + this.classFile = f; + this.wrapper = (DynamicOrAotTypeWrapper)wrapper; + } + + internal void CreateStep1() + { + // process all methods (needs to be done first, because property fields depend on being able to lookup the accessor methods) + bool hasclinit = wrapper.BaseTypeWrapper == null ? false : wrapper.BaseTypeWrapper.HasStaticInitializer; + methods = new MethodWrapper[classFile.Methods.Length]; + baseMethods = new MethodWrapper[classFile.Methods.Length][]; + for (int i = 0; i < methods.Length; i++) + { + MemberFlags flags = MemberFlags.None; + ClassFile.Method m = classFile.Methods[i]; + if (m.IsClassInitializer) + { +#if STATIC_COMPILER + bool noop; + if (IsSideEffectFreeStaticInitializerOrNoop(m, out noop)) + { + if (noop) + { + flags |= MemberFlags.NoOp; + } + } + else + { + hasclinit = true; + } +#else + hasclinit = true; +#endif + } + if (m.IsInternal) + { + flags |= MemberFlags.InternalAccess; + } +#if STATIC_COMPILER + if (m.IsCallerSensitive && SupportsCallerID(m)) + { + flags |= MemberFlags.CallerID; + } +#endif + if (wrapper.IsGhost && m.IsVirtual) + { + // note that a GhostMethodWrapper can also represent a default interface method + methods[i] = new GhostMethodWrapper(wrapper, m.Name, m.Signature, null, null, null, null, m.Modifiers, flags); + } + else if (m.IsConstructor && wrapper.IsDelegate) + { + methods[i] = new DelegateConstructorMethodWrapper(wrapper, m); + } + else if (classFile.IsInterface && !m.IsStatic && !m.IsPublic) + { + // we can't use callvirt to call interface private instance methods (because we have to compile them as static methods, + // since the CLR doesn't support interface instance methods), so need a special MethodWrapper + methods[i] = new PrivateInterfaceMethodWrapper(wrapper, m.Name, m.Signature, null, null, null, m.Modifiers, flags); + } + else if (classFile.IsInterface && m.IsVirtual && !m.IsAbstract) + { + // note that a GhostMethodWrapper can also represent a default interface method + methods[i] = new DefaultInterfaceMethodWrapper(wrapper, m.Name, m.Signature, null, null, null, null, m.Modifiers, flags); + } + else + { + if (!classFile.IsInterface && m.IsVirtual) + { + bool explicitOverride; + baseMethods[i] = FindBaseMethods(m, out explicitOverride); + if (explicitOverride) + { + flags |= MemberFlags.ExplicitOverride; + } + } + methods[i] = new TypicalMethodWrapper(wrapper, m.Name, m.Signature, null, null, null, m.Modifiers, flags); + } + } + if (hasclinit) + { + wrapper.SetHasStaticInitializer(); + } + if (!wrapper.IsInterface || wrapper.IsPublic) + { + List methodsArray = new List(methods); + List baseMethodsArray = new List(baseMethods); + AddMirandaMethods(methodsArray, baseMethodsArray, wrapper); + methods = methodsArray.ToArray(); + baseMethods = baseMethodsArray.ToArray(); + } + if (!wrapper.IsInterface) + { + AddDelegateInvokeStubs(wrapper, ref methods); + } + wrapper.SetMethods(methods); + + fields = new FieldWrapper[classFile.Fields.Length]; + for (int i = 0; i < fields.Length; i++) + { + ClassFile.Field fld = classFile.Fields[i]; + if (fld.IsStaticFinalConstant) + { + TypeWrapper fieldType = null; +#if !STATIC_COMPILER + fieldType = ClassLoaderWrapper.GetBootstrapClassLoader().FieldTypeWrapperFromSig(fld.Signature, LoadMode.LoadOrThrow); +#endif + fields[i] = new ConstantFieldWrapper(wrapper, fieldType, fld.Name, fld.Signature, fld.Modifiers, null, fld.ConstantValue, MemberFlags.None); + } + else if (fld.IsProperty) + { + fields[i] = new DynamicPropertyFieldWrapper(wrapper, fld); + } + else + { + fields[i] = FieldWrapper.Create(wrapper, null, null, fld.Name, fld.Signature, new ExModifiers(fld.Modifiers, fld.IsInternal)); + } + } +#if STATIC_COMPILER + wrapper.AddMapXmlFields(ref fields); +#endif + wrapper.SetFields(fields); + } + +#if STATIC_COMPILER + private bool SupportsCallerID(ClassFile.Method method) + { + if ((classFile.Name == "sun.reflect.Reflection" && method.Name == "getCallerClass") + || (classFile.Name == "java.lang.SecurityManager" && method.Name == "checkMemberAccess")) + { + // ignore CallerSensitive on methods that don't need CallerID parameter + return false; + } + else if (method.IsStatic) + { + return true; + } + else if ((classFile.IsFinal || classFile.Name == "java.lang.Runtime" || classFile.Name == "java.io.ObjectStreamClass") + && wrapper.BaseTypeWrapper.GetMethodWrapper(method.Name, method.Signature, true) == null + && !HasInterfaceMethod(wrapper, method.Name, method.Signature)) + { + // We only support CallerID instance methods on final or effectively final types, + // because we don't support interface stubs with CallerID. + // We also don't support a CallerID method overriding a method or implementing an interface. + return true; + } + else if (RequiresDynamicReflectionCallerClass(classFile.Name, method.Name, method.Signature)) + { + // We don't support CallerID for virtual methods that can be overridden or implement an interface, + // so these methods will do a dynamic stack walk if when Reflection.getCallerClass() is used. + return false; + } + else + { + // If we end up here, we either have to add support or add them to the white-list in the above clause + // to allow them to fall back to dynamic stack walking. + StaticCompiler.IssueMessage(Message.CallerSensitiveOnUnsupportedMethod, classFile.Name, method.Name, method.Signature); + return false; + } + } + + private static bool HasInterfaceMethod(TypeWrapper tw, string name, string signature) + { + for (; tw != null; tw = tw.BaseTypeWrapper) + { + foreach (TypeWrapper iface in tw.Interfaces) + { + if (iface.GetMethodWrapper(name, signature, false) != null) + { + return true; + } + if (HasInterfaceMethod(iface, name, signature)) + { + return true; + } + } + } + return false; + } +#endif + + internal void CreateStep2() + { +#if STATIC_COMPILER + if (typeBuilder != null) + { + // in the static compiler we need to create the TypeBuilder from outer to inner + // and to avoid having to sort the classes this way, we instead call CreateStep2 + // on demand for outer wrappers and this necessitates us to keep track of + // whether we've already been called + return; + } +#endif + // this method is not allowed to throw exceptions (if it does, the runtime will abort) + bool hasclinit = wrapper.HasStaticInitializer; + string mangledTypeName = wrapper.classLoader.GetTypeWrapperFactory().AllocMangledName(wrapper); + ClassFile f = classFile; + try + { + TypeAttributes typeAttribs = 0; + if (f.IsAbstract) + { + typeAttribs |= TypeAttributes.Abstract; + } + if (f.IsFinal) + { + typeAttribs |= TypeAttributes.Sealed; + } + if (!hasclinit) + { + typeAttribs |= TypeAttributes.BeforeFieldInit; + } +#if STATIC_COMPILER + bool cantNest = false; + bool setModifiers = false; + TypeBuilder enclosing = null; + string enclosingClassName = null; + // we only compile inner classes as nested types in the static compiler, because it has a higher cost + // and doesn't buy us anything in dynamic mode (and if fact, due to an FXBUG it would make handling + // the TypeResolve event very hard) + ClassFile.InnerClass outerClass = getOuterClass(); + if (outerClass.outerClass != 0) + { + enclosingClassName = classFile.GetConstantPoolClass(outerClass.outerClass); + } + else if (f.EnclosingMethod != null) + { + enclosingClassName = f.EnclosingMethod[0]; + } + if (enclosingClassName != null) + { + if (!CheckInnerOuterNames(f.Name, enclosingClassName)) + { + Tracer.Warning(Tracer.Compiler, "Incorrect {0} attribute on {1}", outerClass.outerClass != 0 ? "InnerClasses" : "EnclosingMethod", f.Name); + } + else + { + try + { + enclosingClassWrapper = wrapper.classLoader.LoadClassByDottedNameFast(enclosingClassName) as DynamicTypeWrapper; + } + catch (RetargetableJavaException x) + { + Tracer.Warning(Tracer.Compiler, "Unable to load outer class {0} for inner class {1} ({2}: {3})", enclosingClassName, f.Name, x.GetType().Name, x.Message); + } + if (enclosingClassWrapper != null) + { + // make sure the relationship is reciprocal (otherwise we run the risk of + // baking the outer type before the inner type) and that the inner and outer + // class live in the same class loader (when doing a multi target compilation, + // it is possible to split the two classes across assemblies) + JavaTypeImpl oimpl = enclosingClassWrapper.impl as JavaTypeImpl; + if (oimpl != null && enclosingClassWrapper.GetClassLoader() == wrapper.GetClassLoader()) + { + ClassFile outerClassFile = oimpl.classFile; + ClassFile.InnerClass[] outerInnerClasses = outerClassFile.InnerClasses; + if (outerInnerClasses == null) + { + enclosingClassWrapper = null; + } + else + { + bool ok = false; + for (int i = 0; i < outerInnerClasses.Length; i++) + { + if (((outerInnerClasses[i].outerClass != 0 && outerClassFile.GetConstantPoolClass(outerInnerClasses[i].outerClass) == outerClassFile.Name) + || (outerInnerClasses[i].outerClass == 0 && outerClass.outerClass == 0)) + && outerInnerClasses[i].innerClass != 0 + && outerClassFile.GetConstantPoolClass(outerInnerClasses[i].innerClass) == f.Name) + { + ok = true; + break; + } + } + if (!ok) + { + enclosingClassWrapper = null; + } + } + } + else + { + enclosingClassWrapper = null; + } + if (enclosingClassWrapper != null) + { + enclosingClassWrapper.CreateStep2(); + enclosing = oimpl.typeBuilder; + if (outerClass.outerClass == 0) + { + // we need to record that we're not an inner classes, but an enclosed class + typeAttribs |= TypeAttributes.SpecialName; + } + } + else + { + Tracer.Warning(Tracer.Compiler, "Non-reciprocal inner class {0}", f.Name); + } + } + } + } + if (f.IsPublic) + { + if (enclosing != null) + { + if (enclosingClassWrapper.IsPublic) + { + typeAttribs |= TypeAttributes.NestedPublic; + } + else + { + // We're a public type nested inside a non-public type, this means that we can't compile this type as a nested type, + // because that would mean it wouldn't be visible outside the assembly. + cantNest = true; + typeAttribs |= TypeAttributes.Public; + } + } + else + { + typeAttribs |= TypeAttributes.Public; + } + } + else if (enclosing != null) + { + typeAttribs |= TypeAttributes.NestedAssembly; + } +#else // STATIC_COMPILER + if (f.IsPublic) + { + typeAttribs |= TypeAttributes.Public; + } +#endif // STATIC_COMPILER + if (f.IsInterface) + { + typeAttribs |= TypeAttributes.Interface | TypeAttributes.Abstract; +#if STATIC_COMPILER + // if any "meaningless" bits are set, preserve them + setModifiers |= (f.Modifiers & (Modifiers)0x99CE) != 0; + // by default we assume interfaces are abstract, so in the exceptional case we need a ModifiersAttribute + setModifiers |= (f.Modifiers & Modifiers.Abstract) == 0; + if (enclosing != null && !cantNest) + { + if (wrapper.IsGhost) + { + // TODO this is low priority, since the current Java class library doesn't define any ghost interfaces + // as inner classes + throw new NotImplementedException(); + } + // LAMESPEC the CLI spec says interfaces cannot contain nested types (Part.II, 9.6), but that rule isn't enforced + // (and broken by J# as well), so we'll just ignore it too. + typeBuilder = enclosing.DefineNestedType(AllocNestedTypeName(enclosingClassWrapper.Name, f.Name), typeAttribs); + } + else + { + if (wrapper.IsGhost) + { + typeBuilder = wrapper.DefineGhostType(mangledTypeName, typeAttribs); + } + else + { + typeBuilder = wrapper.classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(mangledTypeName, typeAttribs); + } + } +#else // STATIC_COMPILER + typeBuilder = wrapper.classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(mangledTypeName, typeAttribs); +#endif // STATIC_COMPILER + } + else + { + typeAttribs |= TypeAttributes.Class; +#if STATIC_COMPILER + // if any "meaningless" bits are set, preserve them + setModifiers |= (f.Modifiers & (Modifiers)0x99CE) != 0; + // by default we assume ACC_SUPER for classes, so in the exceptional case we need a ModifiersAttribute + setModifiers |= !f.IsSuper; + if (enclosing != null && !cantNest) + { + // LAMESPEC the CLI spec says interfaces cannot contain nested types (Part.II, 9.6), but that rule isn't enforced + // (and broken by J# as well), so we'll just ignore it too. + typeBuilder = enclosing.DefineNestedType(AllocNestedTypeName(enclosingClassWrapper.Name, f.Name), typeAttribs); + } + else +#endif // STATIC_COMPILER + { + typeBuilder = wrapper.classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(mangledTypeName, typeAttribs); + } + } +#if STATIC_COMPILER + // When we're statically compiling, we associate the typeBuilder with the wrapper. This enables types in referenced assemblies to refer back to + // types that we're currently compiling (i.e. a cyclic dependency between the currently assembly we're compiling and a referenced assembly). + wrapper.GetClassLoader().SetWrapperForType(typeBuilder, wrapper); + if (outerClass.outerClass != 0) + { + if (enclosing != null && cantNest) + { + AttributeHelper.SetNonNestedInnerClass(enclosing, f.Name); + } + if (enclosing == null || cantNest) + { + AttributeHelper.SetNonNestedOuterClass(typeBuilder, enclosingClassName); + } + } + if (classFile.InnerClasses != null) + { + foreach (ClassFile.InnerClass inner in classFile.InnerClasses) + { + string name = classFile.GetConstantPoolClass(inner.innerClass); + bool exists = false; + try + { + exists = wrapper.GetClassLoader().LoadClassByDottedNameFast(name) != null; + } + catch (RetargetableJavaException) { } + if (!exists) + { + AttributeHelper.SetNonNestedInnerClass(typeBuilder, name); + } + } + } + if (typeBuilder.FullName != wrapper.Name + && wrapper.Name.Replace('$', '+') != typeBuilder.FullName) + { + wrapper.classLoader.AddNameMapping(wrapper.Name, typeBuilder.FullName); + } + if (f.IsAnnotation && Annotation.HasRetentionPolicyRuntime(f.Annotations)) + { + annotationBuilder = new AnnotationBuilder(this, enclosing); + wrapper.SetAnnotation(annotationBuilder); + } + // For Java 5 Enum types, we generate a nested .NET enum. + // This is primarily to support annotations that take enum parameters. + if (f.IsEnum && f.IsPublic) + { + AddCliEnum(); + } + AddInnerClassAttribute(enclosing != null, outerClass.innerClass != 0, mangledTypeName, outerClass.accessFlags); + if (classFile.DeprecatedAttribute && !Annotation.HasObsoleteAttribute(classFile.Annotations)) + { + AttributeHelper.SetDeprecatedAttribute(typeBuilder); + } + if (classFile.GenericSignature != null) + { + AttributeHelper.SetSignatureAttribute(typeBuilder, classFile.GenericSignature); + } + if (classFile.EnclosingMethod != null) + { + if (outerClass.outerClass == 0 && enclosing != null && !cantNest) + { + // we don't need to record the enclosing type, if we're compiling the current type as a nested type because of the EnclosingMethod attribute + AttributeHelper.SetEnclosingMethodAttribute(typeBuilder, null, classFile.EnclosingMethod[1], classFile.EnclosingMethod[2]); + } + else + { + AttributeHelper.SetEnclosingMethodAttribute(typeBuilder, classFile.EnclosingMethod[0], classFile.EnclosingMethod[1], classFile.EnclosingMethod[2]); + } + } + if (classFile.RuntimeVisibleTypeAnnotations != null) + { + AttributeHelper.SetRuntimeVisibleTypeAnnotationsAttribute(typeBuilder, classFile.RuntimeVisibleTypeAnnotations); + } + if (wrapper.classLoader.EmitStackTraceInfo) + { + if (f.SourceFileAttribute != null) + { + if ((enclosingClassWrapper == null && f.SourceFileAttribute == typeBuilder.Name + ".java") + || (enclosingClassWrapper != null && f.SourceFileAttribute == enclosingClassWrapper.sourceFileName)) + { + // we don't need to record the name because it matches our heuristic + } + else + { + AttributeHelper.SetSourceFile(typeBuilder, f.SourceFileAttribute); + } + } + else + { + AttributeHelper.SetSourceFile(typeBuilder, null); + } + } + // NOTE in Whidbey we can (and should) use CompilerGeneratedAttribute to mark Synthetic types + if (setModifiers || classFile.IsInternal || (classFile.Modifiers & (Modifiers.Synthetic | Modifiers.Annotation | Modifiers.Enum)) != 0) + { + AttributeHelper.SetModifiers(typeBuilder, classFile.Modifiers, classFile.IsInternal); + } +#endif // STATIC_COMPILER + if (hasclinit) + { + AddClinitTrigger(); + } + if (HasStructLayoutAttributeAnnotation(classFile)) + { + // when we have a StructLayoutAttribute, field order is significant, + // so we link all fields here to make sure they are created in class file order. + foreach (FieldWrapper fw in fields) + { + fw.Link(); + } + } + } +#if STATIC_COMPILER + finally { } +#else + catch (Exception x) + { + JVM.CriticalFailure("Exception during JavaTypeImpl.CreateStep2", x); + } +#endif + } + +#if STATIC_COMPILER + private void AddInnerClassAttribute(bool isNestedType, bool isInnerClass, string mangledTypeName, Modifiers innerClassFlags) + { + string name = classFile.Name; + + if (isNestedType) + { + if (name == enclosingClassWrapper.Name + "$" + typeBuilder.Name) + { + name = null; + } + } + else if (name == mangledTypeName) + { + name = null; + } + + if ((isInnerClass && CompiledTypeWrapper.PredictReflectiveModifiers(wrapper) != innerClassFlags) || name != null) + { + // HACK we abuse the InnerClassAttribute to record to real name for non-inner classes as well + AttributeHelper.SetInnerClass(typeBuilder, name, isInnerClass ? innerClassFlags : wrapper.Modifiers); + } + } + + private void AddCliEnum() + { + CompilerClassLoader ccl = wrapper.classLoader; + string name = "__Enum"; + while (!ccl.ReserveName(classFile.Name + "$" + name)) + { + name += "_"; + } + enumBuilder = typeBuilder.DefineNestedType(name, TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.NestedPublic | TypeAttributes.Serializable, Types.Enum); + AttributeHelper.HideFromJava(enumBuilder); + enumBuilder.DefineField("value__", Types.Int32, FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName); + for (int i = 0; i < classFile.Fields.Length; i++) + { + if (classFile.Fields[i].IsEnum) + { + FieldBuilder fieldBuilder = enumBuilder.DefineField(classFile.Fields[i].Name, enumBuilder, FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal); + fieldBuilder.SetConstant(i); + } + } + wrapper.SetEnumType(enumBuilder); + } +#endif + + private void AddClinitTrigger() + { + // We create a empty method that we can use to trigger our .cctor + // (previously we used RuntimeHelpers.RunClassConstructor, but that is slow and requires additional privileges) + MethodAttributes attribs = MethodAttributes.Static | MethodAttributes.SpecialName; + if (classFile.IsAbstract) + { + bool hasfields = false; + // If we have any public static fields, the cctor trigger must (and may) be public as well + foreach (ClassFile.Field fld in classFile.Fields) + { + if (fld.IsPublic && fld.IsStatic) + { + hasfields = true; + break; + } + } + attribs |= hasfields ? MethodAttributes.Public : MethodAttributes.FamORAssem; + } + else + { + attribs |= MethodAttributes.Public; + } + clinitMethod = typeBuilder.DefineMethod("__", attribs, null, null); + clinitMethod.GetILGenerator().Emit(OpCodes.Ret); + // FXBUG on .NET 2.0 RTM x64 the JIT sometimes throws an InvalidProgramException while trying to inline this method, + // so we prevent inlining for now (it also turns out that on x86 not inlining this method actually has a positive perf impact in some cases...) + // http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=285772 + clinitMethod.SetImplementationFlags(clinitMethod.GetMethodImplementationFlags() | MethodImplAttributes.NoInlining); + } + + private sealed class DelegateConstructorMethodWrapper : MethodWrapper + { + private MethodBuilder constructor; + private MethodInfo invoke; + + internal DelegateConstructorMethodWrapper(DynamicTypeWrapper tw, ClassFile.Method m) + : base(tw, m.Name, m.Signature, null, null, null, m.Modifiers, MemberFlags.None) + { + } + + internal void DoLink(TypeBuilder typeBuilder) + { + MethodAttributes attribs = MethodAttributes.HideBySig | MethodAttributes.Public; + constructor = ReflectUtil.DefineConstructor(typeBuilder, attribs, new Type[] { Types.Object, Types.IntPtr }); + constructor.SetImplementationFlags(MethodImplAttributes.Runtime); + MethodWrapper mw = GetParameters()[0].GetMethods()[0]; + mw.Link(); + invoke = (MethodInfo)mw.GetMethod(); + } + + internal override void EmitNewobj(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Dup); + ilgen.Emit(OpCodes.Ldvirtftn, invoke); + ilgen.Emit(OpCodes.Newobj, constructor); + } + } + + private static bool HasStructLayoutAttributeAnnotation(ClassFile c) + { + if (c.Annotations != null) + { + foreach (object[] annot in c.Annotations) + { + if ("Lcli/System/Runtime/InteropServices/StructLayoutAttribute$Annotation;".Equals(annot[1])) + { + return true; + } + } + } + return false; + } + +#if STATIC_COMPILER + private ClassFile.InnerClass getOuterClass() + { + ClassFile.InnerClass[] innerClasses = classFile.InnerClasses; + if (innerClasses != null) + { + for (int j = 0; j < innerClasses.Length; j++) + { + if (innerClasses[j].innerClass != 0 + && classFile.GetConstantPoolClass(innerClasses[j].innerClass) == classFile.Name) + { + return innerClasses[j]; + } + } + } + return new ClassFile.InnerClass(); + } + + private bool IsSideEffectFreeStaticInitializerOrNoop(ClassFile.Method m, out bool noop) + { + if (m.ExceptionTable.Length != 0) + { + noop = false; + return false; + } + noop = true; + for (int i = 0; i < m.Instructions.Length; i++) + { + NormalizedByteCode bc; + while ((bc = m.Instructions[i].NormalizedOpCode) == NormalizedByteCode.__goto) + { + int target = m.Instructions[i].TargetIndex; + if (target <= i) + { + // backward branch means we can't do anything + noop = false; + return false; + } + // we must skip the unused instructions because the "remove assertions" optimization + // uses a goto to remove the (now unused) code + i = target; + } + if (bc == NormalizedByteCode.__getstatic || bc == NormalizedByteCode.__putstatic) + { + ClassFile.ConstantPoolItemFieldref fld = classFile.SafeGetFieldref(m.Instructions[i].Arg1); + if (fld == null || fld.Class != classFile.Name) + { + noop = false; + return false; + } + // don't allow getstatic to load non-primitive fields, because that would + // cause the verifier to try to load the type + if (bc == NormalizedByteCode.__getstatic && "L[".IndexOf(fld.Signature[0]) != -1) + { + noop = false; + return false; + } + ClassFile.Field field = classFile.GetField(fld.Name, fld.Signature); + if (field == null) + { + noop = false; + return false; + } + if (bc == NormalizedByteCode.__putstatic) + { + if (field.IsProperty && field.PropertySetter != null) + { + noop = false; + return false; + } + } + else if (field.IsProperty && field.PropertyGetter != null) + { + noop = false; + return false; + } + } + else if (ByteCodeMetaData.CanThrowException(bc)) + { + noop = false; + return false; + } + else if (bc == NormalizedByteCode.__aconst_null + || (bc == NormalizedByteCode.__iconst && m.Instructions[i].Arg1 == 0) + || bc == NormalizedByteCode.__return + || bc == NormalizedByteCode.__nop) + { + // valid instructions in a potential noop + } + else + { + noop = false; + } + } + // the method needs to be verifiable to be side effect free, since we already analysed it, + // we know that the verifier won't try to load any types (which isn't allowed at this time) + try + { + new MethodAnalyzer(null, wrapper, null, classFile, m, wrapper.classLoader); + return true; + } + catch (VerifyError) + { + return false; + } + } +#endif // STATIC_COMPILER + + private MethodWrapper GetMethodWrapperDuringCtor(TypeWrapper lookup, IList methods, string name, string sig) + { + if (lookup == wrapper) + { + foreach (MethodWrapper mw in methods) + { + if (mw.Name == name && mw.Signature == sig) + { + return mw; + } + } + if (lookup.BaseTypeWrapper == null) + { + return null; + } + else + { + return lookup.BaseTypeWrapper.GetMethodWrapper(name, sig, true); + } + } + else + { + return lookup.GetMethodWrapper(name, sig, true); + } + } + + private void AddMirandaMethods(List methods, List baseMethods, TypeWrapper tw) + { + foreach (TypeWrapper iface in tw.Interfaces) + { + if (iface.IsPublic && this.wrapper.IsInterface) + { + // for interfaces, we only need miranda methods for non-public interfaces that we extend + continue; + } + AddMirandaMethods(methods, baseMethods, iface); + foreach (MethodWrapper ifmethod in iface.GetMethods()) + { + // skip and non-virtual interface methods introduced in Java 8 + if (ifmethod.IsVirtual) + { + TypeWrapper lookup = wrapper; + while (lookup != null) + { + MethodWrapper mw = GetMethodWrapperDuringCtor(lookup, methods, ifmethod.Name, ifmethod.Signature); + if (mw == null || (mw.IsMirandaMethod && mw.DeclaringType != wrapper)) + { + mw = MirandaMethodWrapper.Create(wrapper, ifmethod); + methods.Add(mw); + baseMethods.Add(new MethodWrapper[] { ifmethod }); + break; + } + if (mw.IsMirandaMethod && mw.DeclaringType == wrapper) + { + methods[methods.IndexOf(mw)] = ((MirandaMethodWrapper)mw).Update(ifmethod); + break; + } + if (!mw.IsStatic || mw.DeclaringType == wrapper) + { + break; + } + lookup = mw.DeclaringType.BaseTypeWrapper; + } + } + } + } + } + + private void AddDelegateInvokeStubs(TypeWrapper tw, ref MethodWrapper[] methods) + { + foreach (TypeWrapper iface in tw.Interfaces) + { + if (iface.IsFakeNestedType + && iface.GetMethods().Length == 1 + && iface.GetMethods()[0].IsDelegateInvokeWithByRefParameter) + { + MethodWrapper mw = new DelegateInvokeStubMethodWrapper(wrapper, iface.DeclaringTypeWrapper.TypeAsBaseType, iface.GetMethods()[0].Signature); + if (GetMethodWrapperDuringCtor(wrapper, methods, mw.Name, mw.Signature) == null) + { + methods = ArrayUtil.Concat(methods, mw); + } + } + AddDelegateInvokeStubs(iface, ref methods); + } + } + + private sealed class DelegateInvokeStubMethodWrapper : MethodWrapper + { + private readonly Type delegateType; + + internal DelegateInvokeStubMethodWrapper(TypeWrapper declaringType, Type delegateType, string sig) + : base(declaringType, DotNetTypeWrapper.GetDelegateInvokeStubName(delegateType), sig, null, null, null, Modifiers.Public | Modifiers.Final, MemberFlags.HideFromReflection) + { + this.delegateType = delegateType; + } + + internal MethodInfo DoLink(TypeBuilder tb) + { + MethodWrapper mw = this.DeclaringType.GetMethodWrapper("Invoke", this.Signature, true); + + MethodInfo invoke = delegateType.GetMethod("Invoke"); + ParameterInfo[] parameters = invoke.GetParameters(); + Type[] parameterTypes = new Type[parameters.Length]; + for (int i = 0; i < parameterTypes.Length; i++) + { + parameterTypes[i] = parameters[i].ParameterType; + } + MethodBuilder mb = tb.DefineMethod(this.Name, MethodAttributes.Public, invoke.ReturnType, parameterTypes); + AttributeHelper.HideFromReflection(mb); + CodeEmitter ilgen = CodeEmitter.Create(mb); + if (mw == null || mw.IsStatic || !mw.IsPublic) + { + ilgen.EmitThrow(mw == null || mw.IsStatic ? "java.lang.AbstractMethodError" : "java.lang.IllegalAccessError", DeclaringType.Name + ".Invoke" + Signature); + ilgen.DoEmit(); + return mb; + } + CodeEmitterLocal[] byrefs = new CodeEmitterLocal[parameters.Length]; + for (int i = 0; i < parameters.Length; i++) + { + if (parameters[i].ParameterType.IsByRef) + { + Type elemType = parameters[i].ParameterType.GetElementType(); + CodeEmitterLocal local = ilgen.DeclareLocal(ArrayTypeWrapper.MakeArrayType(elemType, 1)); + byrefs[i] = local; + ilgen.Emit(OpCodes.Ldc_I4_1); + ilgen.Emit(OpCodes.Newarr, elemType); + ilgen.Emit(OpCodes.Stloc, local); + ilgen.Emit(OpCodes.Ldloc, local); + ilgen.Emit(OpCodes.Ldc_I4_0); + ilgen.EmitLdarg(i + 1); + ilgen.Emit(OpCodes.Ldobj, elemType); + ilgen.Emit(OpCodes.Stelem, elemType); + } + } + ilgen.BeginExceptionBlock(); + ilgen.Emit(OpCodes.Ldarg_0); + for (int i = 0; i < parameters.Length; i++) + { + if (byrefs[i] != null) + { + ilgen.Emit(OpCodes.Ldloc, byrefs[i]); + } + else + { + ilgen.EmitLdarg(i + 1); + } + } + mw.Link(); + mw.EmitCallvirt(ilgen); + CodeEmitterLocal returnValue = null; + if (mw.ReturnType != PrimitiveTypeWrapper.VOID) + { + returnValue = ilgen.DeclareLocal(mw.ReturnType.TypeAsSignatureType); + ilgen.Emit(OpCodes.Stloc, returnValue); + } + CodeEmitterLabel exit = ilgen.DefineLabel(); + ilgen.EmitLeave(exit); + ilgen.BeginFinallyBlock(); + for (int i = 0; i < parameters.Length; i++) + { + if (byrefs[i] != null) + { + Type elemType = byrefs[i].LocalType.GetElementType(); + ilgen.EmitLdarg(i + 1); + ilgen.Emit(OpCodes.Ldloc, byrefs[i]); + ilgen.Emit(OpCodes.Ldc_I4_0); + ilgen.Emit(OpCodes.Ldelem, elemType); + ilgen.Emit(OpCodes.Stobj, elemType); + } + } + ilgen.Emit(OpCodes.Endfinally); + ilgen.EndExceptionBlock(); + ilgen.MarkLabel(exit); + if (returnValue != null) + { + ilgen.Emit(OpCodes.Ldloc, returnValue); + } + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + return mb; + } + } + +#if STATIC_COMPILER + private static bool CheckInnerOuterNames(string inner, string outer) + { + // do some sanity checks on the inner/outer class names + return inner.Length > outer.Length + 1 && inner[outer.Length] == '$' && inner.StartsWith(outer, StringComparison.Ordinal); + } + + private string AllocNestedTypeName(string outer, string inner) + { + Debug.Assert(CheckInnerOuterNames(inner, outer)); + if (nestedTypeNames == null) + { + nestedTypeNames = new Dictionary(); + } + return DynamicClassLoader.TypeNameMangleImpl(nestedTypeNames, inner.Substring(outer.Length + 1), null); + } +#endif // STATIC_COMPILER + + private int GetMethodIndex(MethodWrapper mw) + { + for (int i = 0; i < methods.Length; i++) + { + if (methods[i] == mw) + { + return i; + } + } + throw new InvalidOperationException(); + } + + private static void CheckLoaderConstraints(MethodWrapper mw, MethodWrapper baseMethod) + { + if (mw.ReturnType != baseMethod.ReturnType) + { + if (mw.ReturnType.IsUnloadable || baseMethod.ReturnType.IsUnloadable) + { + // unloadable types can never cause a loader constraint violation + if (mw.ReturnType.IsUnloadable && baseMethod.ReturnType.IsUnloadable) + { + ((UnloadableTypeWrapper)mw.ReturnType).SetCustomModifier(((UnloadableTypeWrapper)baseMethod.ReturnType).CustomModifier); + } + } + else + { +#if STATIC_COMPILER + StaticCompiler.LinkageError("Method \"{2}.{3}{4}\" has a return type \"{0}\" and tries to override method \"{5}.{3}{4}\" that has a return type \"{1}\"", mw.ReturnType, baseMethod.ReturnType, mw.DeclaringType.Name, mw.Name, mw.Signature, baseMethod.DeclaringType.Name); +#else + // when we're finishing types to save a debug image (in dynamic mode) we don't care about loader constraints anymore + // (and we can't throw a LinkageError, because that would prevent the debug image from being saved) + if (!JVM.FinishingForDebugSave) + { + throw new LinkageError("Loader constraints violated"); + } +#endif + } + } + TypeWrapper[] here = mw.GetParameters(); + TypeWrapper[] there = baseMethod.GetParameters(); + for (int i = 0; i < here.Length; i++) + { + if (here[i] != there[i]) + { + if (here[i].IsUnloadable || there[i].IsUnloadable) + { + // unloadable types can never cause a loader constraint violation + if (here[i].IsUnloadable && there[i].IsUnloadable) + { + ((UnloadableTypeWrapper)here[i]).SetCustomModifier(((UnloadableTypeWrapper)there[i]).CustomModifier); + } + } + else + { +#if STATIC_COMPILER + StaticCompiler.LinkageError("Method \"{2}.{3}{4}\" has an argument type \"{0}\" and tries to override method \"{5}.{3}{4}\" that has an argument type \"{1}\"", here[i], there[i], mw.DeclaringType.Name, mw.Name, mw.Signature, baseMethod.DeclaringType.Name); +#else + // when we're finishing types to save a debug image (in dynamic mode) we don't care about loader constraints anymore + // (and we can't throw a LinkageError, because that would prevent the debug image from being saved) + if (!JVM.FinishingForDebugSave) + { + throw new LinkageError("Loader constraints violated"); + } +#endif + } + } + } + } + + private int GetFieldIndex(FieldWrapper fw) + { + for (int i = 0; i < fields.Length; i++) + { + if (fields[i] == fw) + { + return i; + } + } + throw new InvalidOperationException(); + } + + internal override FieldInfo LinkField(FieldWrapper fw) + { + if (fw is DynamicPropertyFieldWrapper) + { + ((DynamicPropertyFieldWrapper)fw).DoLink(typeBuilder); + return null; + } + int fieldIndex = GetFieldIndex(fw); +#if STATIC_COMPILER + if (wrapper.GetClassLoader().RemoveUnusedFields + && fw.IsPrivate + && fw.IsStatic + && fw.IsFinal + && !fw.IsSerialVersionUID + && classFile.Fields[fieldIndex].Annotations == null + && !classFile.IsReferenced(classFile.Fields[fieldIndex])) + { + // unused, so we skip it + Tracer.Info(Tracer.Compiler, "Unused field {0}::{1}", wrapper.Name, fw.Name); + return null; + } + // for compatibility with broken Java code that assumes that reflection returns the fields in class declaration + // order, we emit the fields in class declaration order in the .NET metadata (and then when we retrieve them + // using .NET reflection, we sort on metadata token.) + if (fieldIndex > 0) + { + if (!fields[fieldIndex - 1].IsLinked) + { + for (int i = 0; i < fieldIndex; i++) + { + fields[i].Link(); + } + } + } + if (fieldIndex >= classFile.Fields.Length) + { + // this must be a field defined in map.xml + FieldAttributes fieldAttribs = 0; + if (fw.IsPublic) + { + fieldAttribs |= FieldAttributes.Public; + } + else if (fw.IsProtected) + { + fieldAttribs |= FieldAttributes.FamORAssem; + } + else if (fw.IsPrivate) + { + fieldAttribs |= FieldAttributes.Private; + } + else + { + fieldAttribs |= FieldAttributes.Assembly; + } + if (fw.IsStatic) + { + fieldAttribs |= FieldAttributes.Static; + } + if (fw.IsFinal) + { + fieldAttribs |= FieldAttributes.InitOnly; + } + return DefineField(fw.Name, fw.FieldTypeWrapper, fieldAttribs, fw.IsVolatile); + } +#endif // STATIC_COMPILER + FieldBuilder field; + ClassFile.Field fld = classFile.Fields[fieldIndex]; + FieldAttributes attribs = 0; + string realFieldName = UnicodeUtil.EscapeInvalidSurrogates(fld.Name); + if (!ReferenceEquals(realFieldName, fld.Name)) + { + attribs |= FieldAttributes.SpecialName; + } + MethodAttributes methodAttribs = MethodAttributes.HideBySig; +#if STATIC_COMPILER + bool setModifiers = fld.IsInternal || (fld.Modifiers & (Modifiers.Synthetic | Modifiers.Enum)) != 0; +#endif + if (fld.IsPrivate) + { + attribs |= FieldAttributes.Private; + } + else if (fld.IsProtected) + { + attribs |= FieldAttributes.FamORAssem; + methodAttribs |= MethodAttributes.FamORAssem; + } + else if (fld.IsPublic) + { + attribs |= FieldAttributes.Public; + methodAttribs |= MethodAttributes.Public; + } + else + { + attribs |= FieldAttributes.Assembly; + methodAttribs |= MethodAttributes.Assembly; + } + + if (fld.IsStatic) + { + attribs |= FieldAttributes.Static; + methodAttribs |= MethodAttributes.Static; + } + // NOTE "constant" static finals are converted into literals + // TODO it would be possible for Java code to change the value of a non-blank static final, but I don't + // know if we want to support this (since the Java JITs don't really support it either) + if (fld.IsStaticFinalConstant) + { + Profiler.Count("Static Final Constant"); + attribs |= FieldAttributes.Literal; + field = DefineField(realFieldName, fw.FieldTypeWrapper, attribs, false); + field.SetConstant(fld.ConstantValue); + } + else + { +#if STATIC_COMPILER + if (wrapper.IsPublic && wrapper.NeedsType2AccessStub(fw)) + { + // this field is going to get a type 2 access stub, so we hide the actual field + attribs &= ~FieldAttributes.FieldAccessMask; + attribs |= FieldAttributes.Assembly; + // instead of adding HideFromJava we rename the field to avoid confusing broken compilers + // see https://sourceforge.net/tracker/?func=detail&atid=525264&aid=3056721&group_id=69637 + // additional note: now that we maintain the ordering of the fields, we need to recognize + // these fields so that we know where to insert the corresponding accessor property FieldWrapper. + realFieldName = NamePrefix.Type2AccessStubBackingField + realFieldName; + } + else if (fld.IsFinal) + { + if (wrapper.IsInterface || wrapper.classLoader.StrictFinalFieldSemantics) + { + attribs |= FieldAttributes.InitOnly; + } + else + { + setModifiers = true; + } + } +#else + if (fld.IsFinal && wrapper.IsInterface) + { + attribs |= FieldAttributes.InitOnly; + } +#endif + + field = DefineField(realFieldName, fw.FieldTypeWrapper, attribs, fld.IsVolatile); + } + if (fld.IsTransient) + { + CustomAttributeBuilder transientAttrib = new CustomAttributeBuilder(JVM.Import(typeof(NonSerializedAttribute)).GetConstructor(Type.EmptyTypes), new object[0]); + field.SetCustomAttribute(transientAttrib); + } +#if STATIC_COMPILER + { + // if the Java modifiers cannot be expressed in .NET, we emit the Modifiers attribute to store + // the Java modifiers + if (setModifiers) + { + AttributeHelper.SetModifiers(field, fld.Modifiers, fld.IsInternal); + } + if (fld.DeprecatedAttribute && !Annotation.HasObsoleteAttribute(fld.Annotations)) + { + AttributeHelper.SetDeprecatedAttribute(field); + } + if (fld.GenericSignature != null) + { + AttributeHelper.SetSignatureAttribute(field, fld.GenericSignature); + } + if (fld.RuntimeVisibleTypeAnnotations != null) + { + AttributeHelper.SetRuntimeVisibleTypeAnnotationsAttribute(field, fld.RuntimeVisibleTypeAnnotations); + } + } +#endif // STATIC_COMPILER + return field; + } + + private FieldBuilder DefineField(string name, TypeWrapper tw, FieldAttributes attribs, bool isVolatile) + { + Type[] modreq = isVolatile ? new Type[] { Types.IsVolatile } : Type.EmptyTypes; + return typeBuilder.DefineField(name, tw.TypeAsSignatureType, modreq, wrapper.GetModOpt(tw, false), attribs); + } + + internal override void EmitRunClassConstructor(CodeEmitter ilgen) + { + if (clinitMethod != null) + { + ilgen.Emit(OpCodes.Call, clinitMethod); + } + } + + internal override DynamicImpl Finish() + { + TypeWrapper baseTypeWrapper = wrapper.BaseTypeWrapper; + if (baseTypeWrapper != null) + { + baseTypeWrapper.Finish(); + baseTypeWrapper.LinkAll(); + } + // NOTE there is a bug in the CLR (.NET 1.0 & 1.1 [1.2 is not yet available]) that + // causes the AppDomain.TypeResolve event to receive the incorrect type name for nested types. + // The Name in the ResolveEventArgs contains only the nested type name, not the full type name, + // for example, if the type being resolved is "MyOuterType+MyInnerType", then the event only + // receives "MyInnerType" as the name. Since we only compile inner classes as nested types + // when we're statically compiling, we can only run into this bug when we're statically compiling. + // NOTE To work around this bug, we have to make sure that all types that are going to be + // required in finished form, are finished explicitly here. It isn't clear what other types are + // required to be finished. I instrumented a static compilation of classpath.dll and this + // turned up no other cases of the TypeResolve event firing. + foreach (TypeWrapper iface in wrapper.interfaces) + { + iface.Finish(); + iface.LinkAll(); + } + // make sure all classes are loaded, before we start finishing the type. During finishing, we + // may not run any Java code, because that might result in a request to finish the type that we + // are in the process of finishing, and this would be a problem. + // Prevent infinity recursion for broken class loaders by keeping a recursion count and falling + // back to late binding if we recurse more than twice. + LoadMode mode = System.Threading.Interlocked.Increment(ref recursionCount) > 2 || (JVM.DisableEagerClassLoading && wrapper.Name != "sun.reflect.misc.Trampoline") + ? LoadMode.ReturnUnloadable + : LoadMode.Link; + try + { + classFile.Link(wrapper, mode); + for (int i = 0; i < fields.Length; i++) + { + fields[i].Link(mode); + } + for (int i = 0; i < methods.Length; i++) + { + methods[i].Link(mode); + } + } + finally + { + System.Threading.Interlocked.Decrement(ref recursionCount); + } + // this is the correct lock, FinishCore doesn't call any user code and mutates global state, + // so it needs to be protected by a lock. + lock (this) + { + FinishedTypeImpl impl; + try + { + // call FinishCore in the finally to avoid Thread.Abort interrupting the thread + } + finally + { + impl = FinishCore(); + } + return impl; + } + } + + private FinishedTypeImpl FinishCore() + { + // it is possible that the loading of the referenced classes triggered a finish of us, + // if that happens, we just return + if (finishedType != null) + { + return finishedType; + } + if (finishInProgress) + { + throw new InvalidOperationException("Recursive finish attempt for " + wrapper.Name); + } + finishInProgress = true; + Tracer.Info(Tracer.Compiler, "Finishing: {0}", wrapper.Name); + Profiler.Enter("JavaTypeImpl.Finish.Core"); + try + { + TypeWrapper declaringTypeWrapper = null; + TypeWrapper[] innerClassesTypeWrappers = TypeWrapper.EmptyArray; + // if we're an inner class, we need to attach an InnerClass attribute + ClassFile.InnerClass[] innerclasses = classFile.InnerClasses; + if (innerclasses != null) + { + // TODO consider not pre-computing innerClassesTypeWrappers and declaringTypeWrapper here + List wrappers = new List(); + for (int i = 0; i < innerclasses.Length; i++) + { + if (innerclasses[i].innerClass != 0 && innerclasses[i].outerClass != 0) + { + if (classFile.GetConstantPoolClassType(innerclasses[i].outerClass) == wrapper) + { + wrappers.Add(classFile.GetConstantPoolClassType(innerclasses[i].innerClass)); + } + if (classFile.GetConstantPoolClassType(innerclasses[i].innerClass) == wrapper) + { + declaringTypeWrapper = classFile.GetConstantPoolClassType(innerclasses[i].outerClass); + } + } + } + innerClassesTypeWrappers = wrappers.ToArray(); +#if STATIC_COMPILER + // before we bake our type, we need to link any inner annotations to allow them to create their attribute type (as a nested type) + foreach (TypeWrapper tw in innerClassesTypeWrappers) + { + DynamicTypeWrapper dtw = tw as DynamicTypeWrapper; + if (dtw != null) + { + JavaTypeImpl impl = dtw.impl as JavaTypeImpl; + if (impl != null) + { + if (impl.annotationBuilder != null) + { + impl.annotationBuilder.Link(); + } + } + } + } +#endif //STATIC_COMPILER + } +#if STATIC_COMPILER + if (annotationBuilder != null) + { + CustomAttributeBuilder cab = new CustomAttributeBuilder(JVM.LoadType(typeof(AnnotationAttributeAttribute)).GetConstructor(new Type[] { Types.String }), + new object[] { UnicodeUtil.EscapeInvalidSurrogates(annotationBuilder.AttributeTypeName) }); + typeBuilder.SetCustomAttribute(cab); + } + if (!wrapper.IsInterface && wrapper.IsMapUnsafeException) + { + // mark all exceptions that are unsafe for mapping with a custom attribute, + // so that at runtime we can quickly assertain if an exception type can be + // caught without filtering + AttributeHelper.SetExceptionIsUnsafeForMapping(typeBuilder); + } +#endif + + FinishContext context = new FinishContext(host, classFile, wrapper, typeBuilder); + Type type = context.FinishImpl(); +#if STATIC_COMPILER + if (annotationBuilder != null) + { + annotationBuilder.Finish(this); + } + if (enumBuilder != null) + { + enumBuilder.CreateType(); + } + if (privateInterfaceMethods != null) + { + privateInterfaceMethods.CreateType(); + } +#endif + MethodInfo finishedClinitMethod = clinitMethod; +#if !STATIC_COMPILER + if (finishedClinitMethod != null) + { + // In dynamic mode, we may need to emit a call to this method from a DynamicMethod which doesn't support calling unfinished methods, + // so we must resolve to the real method here. + finishedClinitMethod = type.GetMethod("__", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); + } +#endif + finishedType = new FinishedTypeImpl(type, innerClassesTypeWrappers, declaringTypeWrapper, wrapper.ReflectiveModifiers, Metadata.Create(classFile), finishedClinitMethod, finalizeMethod, host); + return finishedType; + } +#if !STATIC_COMPILER + catch (Exception x) + { + JVM.CriticalFailure("Exception during finishing of: " + wrapper.Name, x); + return null; + } +#endif + finally + { + Profiler.Leave("JavaTypeImpl.Finish.Core"); + } + } + +#if STATIC_COMPILER + private bool IsValidAnnotationElementType(string type) + { + if (type[0] == '[') + { + type = type.Substring(1); + } + switch (type) + { + case "Z": + case "B": + case "S": + case "C": + case "I": + case "J": + case "F": + case "D": + case "Ljava.lang.String;": + case "Ljava.lang.Class;": + return true; + } + if (type.StartsWith("L") && type.EndsWith(";")) + { + try + { + TypeWrapper tw = wrapper.GetClassLoader().LoadClassByDottedNameFast(type.Substring(1, type.Length - 2)); + if (tw != null) + { + if ((tw.Modifiers & Modifiers.Annotation) != 0) + { + return true; + } + if ((tw.Modifiers & Modifiers.Enum) != 0) + { + TypeWrapper enumType = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedNameFast("java.lang.Enum"); + if (enumType != null && tw.IsSubTypeOf(enumType)) + { + return true; + } + } + } + } + catch + { + } + } + return false; + } + + sealed class AnnotationBuilder : Annotation + { + private JavaTypeImpl impl; + private TypeBuilder outer; + private TypeBuilder annotationTypeBuilder; + private TypeBuilder attributeTypeBuilder; + private MethodBuilder defineConstructor; + + internal AnnotationBuilder(JavaTypeImpl o, TypeBuilder outer) + { + this.impl = o; + this.outer = outer; + } + + internal void Link() + { + if (impl == null) + { + return; + } + JavaTypeImpl o = impl; + impl = null; + + // Make sure the annotation type only has valid methods + for (int i = 0; i < o.methods.Length; i++) + { + if (!o.methods[i].IsStatic) + { + if (!o.methods[i].Signature.StartsWith("()")) + { + return; + } + if (!o.IsValidAnnotationElementType(o.methods[i].Signature.Substring(2))) + { + return; + } + } + } + + // we only set annotationTypeBuilder if we're valid + annotationTypeBuilder = o.typeBuilder; + + TypeWrapper annotationAttributeBaseType = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.AnnotationAttributeBase"); + + // make sure we don't clash with another class name + CompilerClassLoader ccl = o.wrapper.classLoader; + string name = UnicodeUtil.EscapeInvalidSurrogates(o.classFile.Name); + while (!ccl.ReserveName(name + "Attribute")) + { + name += "_"; + } + + TypeAttributes typeAttributes = TypeAttributes.Class | TypeAttributes.Sealed; + if (o.enclosingClassWrapper != null) + { + if (o.wrapper.IsPublic) + { + typeAttributes |= TypeAttributes.NestedPublic; + } + else + { + typeAttributes |= TypeAttributes.NestedAssembly; + } + attributeTypeBuilder = outer.DefineNestedType(o.AllocNestedTypeName(o.enclosingClassWrapper.Name, name + "Attribute"), typeAttributes, annotationAttributeBaseType.TypeAsBaseType); + } + else + { + if (o.wrapper.IsPublic) + { + typeAttributes |= TypeAttributes.Public; + } + else + { + typeAttributes |= TypeAttributes.NotPublic; + } + attributeTypeBuilder = o.wrapper.classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(name + "Attribute", typeAttributes, annotationAttributeBaseType.TypeAsBaseType); + } + if (o.wrapper.IsPublic) + { + // In the Java world, the class appears as a non-public proxy class + AttributeHelper.SetModifiers(attributeTypeBuilder, Modifiers.Final, false); + } + // NOTE we "abuse" the InnerClassAttribute to add a custom attribute to name the class "$Proxy[Annotation]" in the Java world + int dotindex = o.classFile.Name.LastIndexOf('.') + 1; + AttributeHelper.SetInnerClass(attributeTypeBuilder, o.classFile.Name.Substring(0, dotindex) + "$Proxy" + o.classFile.Name.Substring(dotindex), Modifiers.Final); + attributeTypeBuilder.AddInterfaceImplementation(o.typeBuilder); + AttributeHelper.SetImplementsAttribute(attributeTypeBuilder, new TypeWrapper[] { o.wrapper }); + + if (o.classFile.Annotations != null) + { + CustomAttributeBuilder attributeUsageAttribute = null; + bool hasAttributeUsageAttribute = false; + foreach (object[] def in o.classFile.Annotations) + { + if (def[1].Equals("Ljava/lang/annotation/Target;") && !hasAttributeUsageAttribute) + { + for (int i = 2; i < def.Length; i += 2) + { + if (def[i].Equals("value")) + { + object[] val = def[i + 1] as object[]; + if (val != null + && val.Length > 0 + && val[0].Equals(AnnotationDefaultAttribute.TAG_ARRAY)) + { + AttributeTargets targets = 0; + for (int j = 1; j < val.Length; j++) + { + object[] eval = val[j] as object[]; + if (eval != null + && eval.Length == 3 + && eval[0].Equals(AnnotationDefaultAttribute.TAG_ENUM) + && eval[1].Equals("Ljava/lang/annotation/ElementType;")) + { + switch ((string)eval[2]) + { + case "ANNOTATION_TYPE": + targets |= AttributeTargets.Interface; + break; + case "CONSTRUCTOR": + targets |= AttributeTargets.Constructor; + break; + case "FIELD": + targets |= AttributeTargets.Field; + break; + case "LOCAL_VARIABLE": + break; + case "METHOD": + targets |= AttributeTargets.Method; + break; + case "PACKAGE": + targets |= AttributeTargets.Interface; + break; + case "PARAMETER": + targets |= AttributeTargets.Parameter; + break; + case "TYPE": + targets |= AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Delegate | AttributeTargets.Enum; + break; + } + } + } + attributeUsageAttribute = new CustomAttributeBuilder(JVM.Import(typeof(AttributeUsageAttribute)).GetConstructor(new Type[] { JVM.Import(typeof(AttributeTargets)) }), new object[] { targets }); + } + } + } + } + else + { + // apply any .NET custom attributes that are on the annotation to the custom attribute we synthesize + // (for example, to allow AttributeUsageAttribute to be overridden) + Annotation annotation = Annotation.Load(o.wrapper, def); + if (annotation != null && annotation.IsCustomAttribute) + { + annotation.Apply(o.wrapper.GetClassLoader(), attributeTypeBuilder, def); + } + if (def[1].Equals("Lcli/System/AttributeUsageAttribute$Annotation;")) + { + hasAttributeUsageAttribute = true; + } + } + } + if (attributeUsageAttribute != null && !hasAttributeUsageAttribute) + { + attributeTypeBuilder.SetCustomAttribute(attributeUsageAttribute); + } + } + + defineConstructor = ReflectUtil.DefineConstructor(attributeTypeBuilder, MethodAttributes.Public, new Type[] { JVM.Import(typeof(object[])) }); + AttributeHelper.SetEditorBrowsableNever(defineConstructor); + } + + private static Type TypeWrapperToAnnotationParameterType(TypeWrapper tw) + { + bool isArray = false; + if (tw.IsArray) + { + isArray = true; + tw = tw.ElementTypeWrapper; + } + if (tw.Annotation != null) + { + // we don't support Annotation args + return null; + } + else + { + Type argType; + if (tw == CoreClasses.java.lang.Class.Wrapper) + { + argType = Types.Type; + } + else if (tw.EnumType != null) // is it a Java enum? + { + argType = tw.EnumType; + } + else if (IsDotNetEnum(tw)) + { + argType = tw.DeclaringTypeWrapper.TypeAsSignatureType; + } + else + { + argType = tw.TypeAsSignatureType; + } + if (isArray) + { + argType = ArrayTypeWrapper.MakeArrayType(argType, 1); + } + return argType; + } + } + + private static bool IsDotNetEnum(TypeWrapper tw) + { + return tw.IsFakeNestedType && (tw.Modifiers & Modifiers.Enum) != 0; + } + + internal string AttributeTypeName + { + get + { + Link(); + if (attributeTypeBuilder != null) + { + return attributeTypeBuilder.FullName; + } + return null; + } + } + + private static void EmitSetValueCall(TypeWrapper annotationAttributeBaseType, CodeEmitter ilgen, string name, TypeWrapper tw, int argIndex) + { + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ldstr, name); + ilgen.EmitLdarg(argIndex); + if (tw.TypeAsSignatureType.IsValueType) + { + ilgen.Emit(OpCodes.Box, tw.TypeAsSignatureType); + } + else if (tw.EnumType != null) // is it a Java enum? + { + ilgen.Emit(OpCodes.Box, tw.EnumType); + } + else if (IsDotNetEnum(tw)) + { + ilgen.Emit(OpCodes.Box, tw.DeclaringTypeWrapper.TypeAsSignatureType); + } + MethodWrapper setValueMethod = annotationAttributeBaseType.GetMethodWrapper("setValue", "(Ljava.lang.String;Ljava.lang.Object;)V", false); + setValueMethod.Link(); + setValueMethod.EmitCall(ilgen); + } + + internal void Finish(JavaTypeImpl o) + { + Link(); + if (annotationTypeBuilder == null) + { + // not a valid annotation type + return; + } + TypeWrapper annotationAttributeBaseType = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.AnnotationAttributeBase"); + annotationAttributeBaseType.Finish(); + + int requiredArgCount = 0; + int valueArg = -1; + bool unsupported = false; + for (int i = 0; i < o.methods.Length; i++) + { + if (!o.methods[i].IsStatic) + { + if (valueArg == -1 && o.methods[i].Name == "value") + { + valueArg = i; + } + if (o.classFile.Methods[i].AnnotationDefault == null) + { + if (TypeWrapperToAnnotationParameterType(o.methods[i].ReturnType) == null) + { + unsupported = true; + break; + } + requiredArgCount++; + } + } + } + + MethodBuilder defaultConstructor = ReflectUtil.DefineConstructor(attributeTypeBuilder, unsupported || requiredArgCount > 0 ? MethodAttributes.Private : MethodAttributes.Public, Type.EmptyTypes); + CodeEmitter ilgen; + + if (!unsupported) + { + if (requiredArgCount > 0) + { + Type[] args = new Type[requiredArgCount]; + for (int i = 0, j = 0; i < o.methods.Length; i++) + { + if (!o.methods[i].IsStatic) + { + if (o.classFile.Methods[i].AnnotationDefault == null) + { + args[j++] = TypeWrapperToAnnotationParameterType(o.methods[i].ReturnType); + } + } + } + MethodBuilder reqArgConstructor = ReflectUtil.DefineConstructor(attributeTypeBuilder, MethodAttributes.Public, args); + AttributeHelper.HideFromJava(reqArgConstructor); + ilgen = CodeEmitter.Create(reqArgConstructor); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Call, defaultConstructor); + for (int i = 0, j = 0; i < o.methods.Length; i++) + { + if (!o.methods[i].IsStatic) + { + if (o.classFile.Methods[i].AnnotationDefault == null) + { + reqArgConstructor.DefineParameter(++j, ParameterAttributes.None, o.methods[i].Name); + EmitSetValueCall(annotationAttributeBaseType, ilgen, o.methods[i].Name, o.methods[i].ReturnType, j); + } + } + } + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + else if (valueArg != -1) + { + // We don't have any required parameters, but we do have an optional "value" parameter, + // so we create an additional constructor (the default constructor will be public in this case) + // that accepts the value parameter. + Type argType = TypeWrapperToAnnotationParameterType(o.methods[valueArg].ReturnType); + if (argType != null) + { + MethodBuilder cb = ReflectUtil.DefineConstructor(attributeTypeBuilder, MethodAttributes.Public, new Type[] { argType }); + AttributeHelper.HideFromJava(cb); + cb.DefineParameter(1, ParameterAttributes.None, "value"); + ilgen = CodeEmitter.Create(cb); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Call, defaultConstructor); + EmitSetValueCall(annotationAttributeBaseType, ilgen, "value", o.methods[valueArg].ReturnType, 1); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + } + } + + ilgen = CodeEmitter.Create(defaultConstructor); + ilgen.Emit(OpCodes.Ldarg_0); + o.wrapper.EmitClassLiteral(ilgen); + annotationAttributeBaseType.GetMethodWrapper("", "(Ljava.lang.Class;)V", false).EmitCall(ilgen); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + + ilgen = CodeEmitter.Create(defineConstructor); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Call, defaultConstructor); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ldarg_1); + annotationAttributeBaseType.GetMethodWrapper("setDefinition", "([Ljava.lang.Object;)V", false).EmitCall(ilgen); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + + MethodWrapper getValueMethod = annotationAttributeBaseType.GetMethodWrapper("getValue", "(Ljava.lang.String;)Ljava.lang.Object;", false); + MethodWrapper getByteValueMethod = annotationAttributeBaseType.GetMethodWrapper("getByteValue", "(Ljava.lang.String;)B", false); + MethodWrapper getBooleanValueMethod = annotationAttributeBaseType.GetMethodWrapper("getBooleanValue", "(Ljava.lang.String;)Z", false); + MethodWrapper getCharValueMethod = annotationAttributeBaseType.GetMethodWrapper("getCharValue", "(Ljava.lang.String;)C", false); + MethodWrapper getShortValueMethod = annotationAttributeBaseType.GetMethodWrapper("getShortValue", "(Ljava.lang.String;)S", false); + MethodWrapper getIntValueMethod = annotationAttributeBaseType.GetMethodWrapper("getIntValue", "(Ljava.lang.String;)I", false); + MethodWrapper getFloatValueMethod = annotationAttributeBaseType.GetMethodWrapper("getFloatValue", "(Ljava.lang.String;)F", false); + MethodWrapper getLongValueMethod = annotationAttributeBaseType.GetMethodWrapper("getLongValue", "(Ljava.lang.String;)J", false); + MethodWrapper getDoubleValueMethod = annotationAttributeBaseType.GetMethodWrapper("getDoubleValue", "(Ljava.lang.String;)D", false); + for (int i = 0; i < o.methods.Length; i++) + { + // skip and non-virtual interface methods introduced in Java 8 + if (o.methods[i].IsVirtual) + { + MethodBuilder mb = o.methods[i].GetDefineMethodHelper().DefineMethod(o.wrapper, attributeTypeBuilder, o.methods[i].Name, MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot); + attributeTypeBuilder.DefineMethodOverride(mb, (MethodInfo)o.methods[i].GetMethod()); + ilgen = CodeEmitter.Create(mb); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ldstr, o.methods[i].Name); + if (o.methods[i].ReturnType.IsPrimitive) + { + if (o.methods[i].ReturnType == PrimitiveTypeWrapper.BYTE) + { + getByteValueMethod.EmitCall(ilgen); + } + else if (o.methods[i].ReturnType == PrimitiveTypeWrapper.BOOLEAN) + { + getBooleanValueMethod.EmitCall(ilgen); + } + else if (o.methods[i].ReturnType == PrimitiveTypeWrapper.CHAR) + { + getCharValueMethod.EmitCall(ilgen); + } + else if (o.methods[i].ReturnType == PrimitiveTypeWrapper.SHORT) + { + getShortValueMethod.EmitCall(ilgen); + } + else if (o.methods[i].ReturnType == PrimitiveTypeWrapper.INT) + { + getIntValueMethod.EmitCall(ilgen); + } + else if (o.methods[i].ReturnType == PrimitiveTypeWrapper.FLOAT) + { + getFloatValueMethod.EmitCall(ilgen); + } + else if (o.methods[i].ReturnType == PrimitiveTypeWrapper.LONG) + { + getLongValueMethod.EmitCall(ilgen); + } + else if (o.methods[i].ReturnType == PrimitiveTypeWrapper.DOUBLE) + { + getDoubleValueMethod.EmitCall(ilgen); + } + else + { + throw new InvalidOperationException(); + } + } + else + { + getValueMethod.EmitCall(ilgen); + o.methods[i].ReturnType.EmitCheckcast(ilgen); + } + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + + if (o.classFile.Methods[i].AnnotationDefault != null + && !(o.methods[i].Name == "value" && requiredArgCount == 0)) + { + // now add a .NET property for this annotation optional parameter + Type argType = TypeWrapperToAnnotationParameterType(o.methods[i].ReturnType); + if (argType != null) + { + PropertyBuilder pb = attributeTypeBuilder.DefineProperty(o.methods[i].Name, PropertyAttributes.None, argType, Type.EmptyTypes); + AttributeHelper.HideFromJava(pb); + MethodBuilder setter = attributeTypeBuilder.DefineMethod("set_" + o.methods[i].Name, MethodAttributes.Public, Types.Void, new Type[] { argType }); + AttributeHelper.HideFromJava(setter); + pb.SetSetMethod(setter); + ilgen = CodeEmitter.Create(setter); + EmitSetValueCall(annotationAttributeBaseType, ilgen, o.methods[i].Name, o.methods[i].ReturnType, 1); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + MethodBuilder getter = attributeTypeBuilder.DefineMethod("get_" + o.methods[i].Name, MethodAttributes.Public, argType, Type.EmptyTypes); + AttributeHelper.HideFromJava(getter); + pb.SetGetMethod(getter); + // TODO implement the getter method + ilgen = CodeEmitter.Create(getter); + ilgen.ThrowException(JVM.Import(typeof(NotImplementedException))); + ilgen.DoEmit(); + } + } + } + } + attributeTypeBuilder.CreateType(); + } + + private CustomAttributeBuilder MakeCustomAttributeBuilder(ClassLoaderWrapper loader, object annotation) + { + Link(); + ConstructorInfo ctor = defineConstructor != null + ? defineConstructor.__AsConstructorInfo() + : StaticCompiler.GetRuntimeType("IKVM.Attributes.DynamicAnnotationAttribute").GetConstructor(new Type[] { Types.Object.MakeArrayType() }); + return new CustomAttributeBuilder(ctor, new object[] { AnnotationDefaultAttribute.Escape(QualifyClassNames(loader, annotation)) }); + } + + internal override void Apply(ClassLoaderWrapper loader, TypeBuilder tb, object annotation) + { + tb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + + internal override void Apply(ClassLoaderWrapper loader, MethodBuilder mb, object annotation) + { + mb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + + internal override void Apply(ClassLoaderWrapper loader, FieldBuilder fb, object annotation) + { + fb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + + internal override void Apply(ClassLoaderWrapper loader, ParameterBuilder pb, object annotation) + { + pb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + + internal override void Apply(ClassLoaderWrapper loader, AssemblyBuilder ab, object annotation) + { + ab.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + + internal override void Apply(ClassLoaderWrapper loader, PropertyBuilder pb, object annotation) + { + pb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + + internal override bool IsCustomAttribute + { + get { return false; } + } + } +#endif // STATIC_COMPILER + + internal override TypeWrapper[] InnerClasses + { + get + { + throw new InvalidOperationException("InnerClasses is only available for finished types"); + } + } + + internal override TypeWrapper DeclaringTypeWrapper + { + get + { + throw new InvalidOperationException("DeclaringTypeWrapper is only available for finished types"); + } + } + + internal override Modifiers ReflectiveModifiers + { + get + { + Modifiers mods; + ClassFile.InnerClass[] innerclasses = classFile.InnerClasses; + if (innerclasses != null) + { + for (int i = 0; i < innerclasses.Length; i++) + { + if (innerclasses[i].innerClass != 0) + { + if (classFile.GetConstantPoolClass(innerclasses[i].innerClass) == wrapper.Name) + { + // the mask comes from RECOGNIZED_INNER_CLASS_MODIFIERS in src/hotspot/share/vm/classfile/classFileParser.cpp + // (minus ACC_SUPER) + mods = innerclasses[i].accessFlags & (Modifiers)0x761F; + if (classFile.IsInterface) + { + mods |= Modifiers.Abstract; + } + return mods; + } + } + } + } + // the mask comes from JVM_RECOGNIZED_CLASS_MODIFIERS in src/hotspot/share/vm/prims/jvm.h + // (minus ACC_SUPER) + mods = classFile.Modifiers & (Modifiers)0x7611; + if (classFile.IsInterface) + { + mods |= Modifiers.Abstract; + } + return mods; + } + } + + // this finds all methods that the specified name/sig is going to be overriding + private MethodWrapper[] FindBaseMethods(ClassFile.Method m, out bool explicitOverride) + { + Debug.Assert(!classFile.IsInterface); + Debug.Assert(m.Name != ""); + + // starting with Java 7 the algorithm changed + return classFile.MajorVersion >= 51 + ? FindBaseMethods7(m.Name, m.Signature, m.IsFinal && !m.IsPublic && !m.IsProtected, out explicitOverride) + : FindBaseMethodsLegacy(m.Name, m.Signature, out explicitOverride); + } + + private MethodWrapper[] FindBaseMethods7(string name, string sig, bool packageFinal, out bool explicitOverride) + { + // NOTE this implements the (completely broken) OpenJDK 7 b147 HotSpot behavior, + // not the algorithm specified in section 5.4.5 of the JavaSE7 JVM spec + // see http://weblog.ikvm.net/PermaLink.aspx?guid=bde44d8b-7ba9-4e0e-b3a6-b735627118ff and subsequent posts + // UPDATE as of JDK 7u65 and JDK 8u11, the algorithm changed again to handle package private methods differently + // this code has not been updated to reflect these changes (we're still at JDK 8 GA level) + explicitOverride = false; + MethodWrapper topPublicOrProtectedMethod = null; + TypeWrapper tw = wrapper.BaseTypeWrapper; + while (tw != null) + { + MethodWrapper baseMethod = tw.GetMethodWrapper(name, sig, true); + if (baseMethod == null) + { + break; + } + else if (baseMethod.IsAccessStub) + { + // ignore + } + else if (!baseMethod.IsStatic && (baseMethod.IsPublic || baseMethod.IsProtected)) + { + topPublicOrProtectedMethod = baseMethod; + } + tw = baseMethod.DeclaringType.BaseTypeWrapper; + } + tw = wrapper.BaseTypeWrapper; + while (tw != null) + { + MethodWrapper baseMethod = tw.GetMethodWrapper(name, sig, true); + if (baseMethod == null) + { + break; + } + else if (baseMethod.IsAccessStub) + { + // ignore + } + else if (baseMethod.IsPrivate) + { + // skip + } + else if (baseMethod.IsFinal && (baseMethod.IsPublic || baseMethod.IsProtected || IsAccessibleInternal(baseMethod) || baseMethod.DeclaringType.IsPackageAccessibleFrom(wrapper))) + { + throw new VerifyError("final method " + baseMethod.Name + baseMethod.Signature + " in " + baseMethod.DeclaringType.Name + " is overridden in " + wrapper.Name); + } + else if (baseMethod.IsStatic) + { + // skip + } + else if (topPublicOrProtectedMethod == null && !baseMethod.IsPublic && !baseMethod.IsProtected && !IsAccessibleInternal(baseMethod) && !baseMethod.DeclaringType.IsPackageAccessibleFrom(wrapper)) + { + // this is a package private method that we're not overriding (unless its vtable stream interleaves ours, which is a case we handle below) + explicitOverride = true; + } + else if (topPublicOrProtectedMethod != null && baseMethod.IsFinal && !baseMethod.IsPublic && !baseMethod.IsProtected && !IsAccessibleInternal(baseMethod) && !baseMethod.DeclaringType.IsPackageAccessibleFrom(wrapper)) + { + // this is package private final method that we would override had it not been final, but which is ignored by HotSpot (instead of throwing a VerifyError) + explicitOverride = true; + } + else if (topPublicOrProtectedMethod == null) + { + if (explicitOverride) + { + List list = new List(); + list.Add(baseMethod); + // we might still have to override package methods from another package if the vtable streams are interleaved with ours + tw = wrapper.BaseTypeWrapper; + while (tw != null) + { + MethodWrapper baseMethod2 = tw.GetMethodWrapper(name, sig, true); + if (baseMethod2 == null || baseMethod2 == baseMethod) + { + break; + } + MethodWrapper baseMethod3 = GetPackageBaseMethod(baseMethod.DeclaringType.BaseTypeWrapper, name, sig, baseMethod2.DeclaringType); + if (baseMethod3 != null) + { + if (baseMethod2.IsFinal) + { + baseMethod2 = baseMethod3; + } + bool found = false; + foreach (MethodWrapper mw in list) + { + if (mw.DeclaringType.IsPackageAccessibleFrom(baseMethod2.DeclaringType)) + { + // we should only add each package once + found = true; + break; + } + } + if (!found) + { + list.Add(baseMethod2); + } + } + tw = baseMethod2.DeclaringType.BaseTypeWrapper; + } + return list.ToArray(); + } + else + { + return new MethodWrapper[] { baseMethod }; + } + } + else + { + if (packageFinal) + { + // when a package final method overrides a public or protected method, HotSpot does not mark that vtable slot as final, + // so we need an explicit override to force the MethodAttributes.NewSlot flag, otherwise the CLR won't allow us + // to override the original method in subsequent derived types + explicitOverride = true; + } + + int majorVersion = 0; + if (!baseMethod.IsPublic && !baseMethod.IsProtected && + ((TryGetClassFileVersion(baseMethod.DeclaringType, ref majorVersion) && majorVersion < 51) + // if TryGetClassFileVersion fails, we know that it is safe to call GetMethod() so we look at the actual method attributes here, + // because access widing ensures that if the method had overridden the top level method it would also be public or protected + || (majorVersion == 0 && (LinkAndGetMethod(baseMethod).Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Assembly))) + { + // the method we're overriding is not public or protected, but there is a public or protected top level method, + // this means that baseMethod is part of a class with a major version < 51, so we have to explicitly override the top level method as well + // (we don't need to look for another package method to override, because by necessity baseMethod is already in our package) + return new MethodWrapper[] { baseMethod, topPublicOrProtectedMethod }; + } + else if (!topPublicOrProtectedMethod.DeclaringType.IsPackageAccessibleFrom(wrapper)) + { + // check if there is another method (in the same package) that we should override + tw = topPublicOrProtectedMethod.DeclaringType.BaseTypeWrapper; + while (tw != null) + { + MethodWrapper baseMethod2 = tw.GetMethodWrapper(name, sig, true); + if (baseMethod2 == null) + { + break; + } + if (baseMethod2.IsAccessStub) + { + // ignore + } + else if (baseMethod2.DeclaringType.IsPackageAccessibleFrom(wrapper) && !baseMethod2.IsPrivate) + { + if (baseMethod2.IsFinal) + { + throw new VerifyError("final method " + baseMethod2.Name + baseMethod2.Signature + " in " + baseMethod2.DeclaringType.Name + " is overridden in " + wrapper.Name); + } + if (!baseMethod2.IsStatic) + { + if (baseMethod2.IsPublic || baseMethod2.IsProtected) + { + break; + } + return new MethodWrapper[] { baseMethod, baseMethod2 }; + } + } + tw = baseMethod2.DeclaringType.BaseTypeWrapper; + } + } + return new MethodWrapper[] { baseMethod }; + } + tw = baseMethod.DeclaringType.BaseTypeWrapper; + } + return null; + } + + private bool IsAccessibleInternal(MethodWrapper mw) + { + return mw.IsInternal && mw.DeclaringType.InternalsVisibleTo(wrapper); + } + + private static MethodBase LinkAndGetMethod(MethodWrapper mw) + { + mw.Link(); + return mw.GetMethod(); + } + + private static bool TryGetClassFileVersion(TypeWrapper tw, ref int majorVersion) + { + DynamicTypeWrapper dtw = tw as DynamicTypeWrapper; + if (dtw != null) + { + JavaTypeImpl impl = dtw.impl as JavaTypeImpl; + if (impl != null) + { + majorVersion = impl.classFile.MajorVersion; + return true; + } + } + return false; + } + + private static MethodWrapper GetPackageBaseMethod(TypeWrapper tw, string name, string sig, TypeWrapper package) + { + while (tw != null) + { + MethodWrapper mw = tw.GetMethodWrapper(name, sig, true); + if (mw == null) + { + break; + } + if (mw.DeclaringType.IsPackageAccessibleFrom(package)) + { + return mw.IsFinal ? null : mw; + } + tw = mw.DeclaringType.BaseTypeWrapper; + } + return null; + } + + private MethodWrapper[] FindBaseMethodsLegacy(string name, string sig, out bool explicitOverride) + { + explicitOverride = false; + TypeWrapper tw = wrapper.BaseTypeWrapper; + while (tw != null) + { + MethodWrapper baseMethod = tw.GetMethodWrapper(name, sig, true); + if (baseMethod == null) + { + return null; + } + else if (baseMethod.IsAccessStub) + { + // ignore + } + // here are the complex rules for determining whether this method overrides the method we found + // RULE 1: final methods may not be overridden + // (note that we intentionally not check IsStatic here!) + else if (baseMethod.IsFinal + && !baseMethod.IsPrivate + && (baseMethod.IsPublic || baseMethod.IsProtected || baseMethod.DeclaringType.IsPackageAccessibleFrom(wrapper))) + { + throw new VerifyError("final method " + baseMethod.Name + baseMethod.Signature + " in " + baseMethod.DeclaringType.Name + " is overridden in " + wrapper.Name); + } + // RULE 1a: static methods are ignored (other than the RULE 1 check) + else if (baseMethod.IsStatic) + { + } + // RULE 2: public & protected methods can be overridden (package methods are handled by RULE 4) + // (by public, protected & *package* methods [even if they are in a different package]) + else if (baseMethod.IsPublic || baseMethod.IsProtected) + { + // if we already encountered a package method, we cannot override the base method of + // that package method + if (explicitOverride) + { + explicitOverride = false; + return null; + } + if (!baseMethod.DeclaringType.IsPackageAccessibleFrom(wrapper)) + { + // check if there is another method (in the same package) that we should override + tw = baseMethod.DeclaringType.BaseTypeWrapper; + while (tw != null) + { + MethodWrapper baseMethod2 = tw.GetMethodWrapper(name, sig, true); + if (baseMethod2 == null) + { + break; + } + if (baseMethod2.IsAccessStub) + { + // ignore + } + else if (baseMethod2.DeclaringType.IsPackageAccessibleFrom(wrapper) && !baseMethod2.IsPrivate) + { + if (baseMethod2.IsFinal) + { + throw new VerifyError("final method " + baseMethod2.Name + baseMethod2.Signature + " in " + baseMethod2.DeclaringType.Name + " is overridden in " + wrapper.Name); + } + if (!baseMethod2.IsStatic) + { + if (baseMethod2.IsPublic || baseMethod2.IsProtected) + { + break; + } + return new MethodWrapper[] { baseMethod, baseMethod2 }; + } + } + tw = baseMethod2.DeclaringType.BaseTypeWrapper; + } + } + return new MethodWrapper[] { baseMethod }; + } + // RULE 3: private and static methods are ignored + else if (!baseMethod.IsPrivate) + { + // RULE 4: package methods can only be overridden in the same package + if (baseMethod.DeclaringType.IsPackageAccessibleFrom(wrapper) + || (baseMethod.IsInternal && baseMethod.DeclaringType.InternalsVisibleTo(wrapper))) + { + return new MethodWrapper[] { baseMethod }; + } + // since we encountered a method with the same name/signature that we aren't overriding, + // we need to specify an explicit override + // NOTE we only do this if baseMethod isn't private, because if it is, Reflection.Emit + // will complain about the explicit MethodOverride (possibly a bug) + explicitOverride = true; + } + tw = baseMethod.DeclaringType.BaseTypeWrapper; + } + return null; + } + + private static MethodInfo GetBaseFinalizeMethod(TypeWrapper wrapper) + { + for (; ; ) + { + // HACK we get called during method linking (which is probably a bad idea) and + // it is possible for the base type not to be finished yet, so we look at the + // private state of the unfinished base types to find the finalize method. + DynamicTypeWrapper dtw = wrapper as DynamicTypeWrapper; + if (dtw == null) + { + break; + } + MethodWrapper mw = dtw.GetMethodWrapper(StringConstants.FINALIZE, StringConstants.SIG_VOID, false); + if (mw != null) + { + mw.Link(); + } + MethodInfo finalizeImpl = dtw.impl.GetFinalizeMethod(); + if (finalizeImpl != null) + { + return finalizeImpl; + } + wrapper = wrapper.BaseTypeWrapper; + } + if (wrapper == CoreClasses.java.lang.Object.Wrapper || wrapper == CoreClasses.java.lang.Throwable.Wrapper) + { + return Types.Object.GetMethod("Finalize", BindingFlags.NonPublic | BindingFlags.Instance); + } + Type type = wrapper.TypeAsBaseType; + MethodInfo baseFinalize = type.GetMethod("__", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null); + if (baseFinalize != null) + { + return baseFinalize; + } + while (type != null) + { + foreach (MethodInfo m in type.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) + { + if (m.Name == "Finalize" + && m.ReturnType == Types.Void + && m.GetParameters().Length == 0) + { + if (m.GetBaseDefinition().DeclaringType == Types.Object) + { + return m; + } + } + } + type = type.BaseType; + } + return null; + } + + private MethodAttributes GetPropertyAccess(MethodWrapper mw) + { + string sig = mw.ReturnType.SigName; + if (sig == "V") + { + sig = mw.GetParameters()[0].SigName; + } + int access = -1; + foreach (ClassFile.Field field in classFile.Fields) + { + if (field.IsProperty + && field.IsStatic == mw.IsStatic + && field.Signature == sig + && (field.PropertyGetter == mw.Name || field.PropertySetter == mw.Name)) + { + int nacc; + if (field.IsPublic) + { + nacc = 3; + } + else if (field.IsProtected) + { + nacc = 2; + } + else if (field.IsPrivate) + { + nacc = 0; + } + else + { + nacc = 1; + } + if (nacc > access) + { + access = nacc; + } + } + } + switch (access) + { + case 0: + return MethodAttributes.Private; + case 1: + return MethodAttributes.Assembly; + case 2: + return MethodAttributes.FamORAssem; + case 3: + return MethodAttributes.Public; + default: + throw new InvalidOperationException(); + } + } + + internal override MethodBase LinkMethod(MethodWrapper mw) + { + Debug.Assert(mw != null); + if (mw is DelegateConstructorMethodWrapper) + { + ((DelegateConstructorMethodWrapper)mw).DoLink(typeBuilder); + return null; + } + if (mw is DelegateInvokeStubMethodWrapper) + { + return ((DelegateInvokeStubMethodWrapper)mw).DoLink(typeBuilder); + } + if (mw.IsClassInitializer && mw.IsNoOp && (!wrapper.IsSerializable || HasSerialVersionUID)) + { + // we don't need to emit the , because it is empty and we're not serializable or have an explicit serialVersionUID + // (because we cannot affect serialVersionUID computation (which is the only way the presence of a can surface) + // we cannot do this optimization if the class is serializable but doesn't have a serialVersionUID) + return null; + } + int index = GetMethodIndex(mw); + if (baseMethods[index] != null) + { + foreach (MethodWrapper baseMethod in baseMethods[index]) + { + baseMethod.Link(); + CheckLoaderConstraints(mw, baseMethod); + } + } + Debug.Assert(mw.GetMethod() == null); + methods[index].AssertLinked(); + Profiler.Enter("JavaTypeImpl.GenerateMethod"); + try + { + if (index >= classFile.Methods.Length) + { + if (methods[index].IsMirandaMethod) + { + // We're a Miranda method or we're an inherited default interface method + Debug.Assert(baseMethods[index].Length == 1 && baseMethods[index][0].DeclaringType.IsInterface); + MirandaMethodWrapper mmw = (MirandaMethodWrapper)methods[index]; + MethodAttributes attr = MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.CheckAccessOnOverride; + MethodWrapper baseMiranda = null; + bool baseMirandaOverrideStub = false; + if (wrapper.BaseTypeWrapper == null || (baseMiranda = wrapper.BaseTypeWrapper.GetMethodWrapper(mw.Name, mw.Signature, true)) == null || !baseMiranda.IsMirandaMethod) + { + // we're not overriding a miranda method in a base class, so can we set the newslot flag + attr |= MethodAttributes.NewSlot; + } + else + { + baseMiranda.Link(); + if (CheckRequireOverrideStub(methods[index], baseMiranda)) + { + baseMirandaOverrideStub = true; + attr |= MethodAttributes.NewSlot; + } + } + if (wrapper.IsInterface || (wrapper.IsAbstract && mmw.BaseMethod.IsAbstract && mmw.Error == null)) + { + attr |= MethodAttributes.Abstract; + } + MethodBuilder mb = methods[index].GetDefineMethodHelper().DefineMethod(wrapper, typeBuilder, methods[index].Name, attr); + AttributeHelper.HideFromReflection(mb); + if (baseMirandaOverrideStub) + { + wrapper.GenerateOverrideStub(typeBuilder, baseMiranda, mb, methods[index]); + } + if ((!wrapper.IsAbstract && mmw.BaseMethod.IsAbstract) || (!wrapper.IsInterface && mmw.Error != null)) + { + string message = mmw.Error ?? (wrapper.Name + "." + methods[index].Name + methods[index].Signature); + CodeEmitter ilgen = CodeEmitter.Create(mb); + ilgen.EmitThrow(mmw.IsConflictError ? "java.lang.IncompatibleClassChangeError" : "java.lang.AbstractMethodError", message); + ilgen.DoEmit(); + wrapper.EmitLevel4Warning(mmw.IsConflictError ? HardError.IncompatibleClassChangeError : HardError.AbstractMethodError, message); + } +#if STATIC_COMPILER + if (wrapper.IsInterface && !mmw.IsAbstract) + { + // even though we're not visible to reflection., we need to record the fact that we have a default implementation + AttributeHelper.SetModifiers(mb, mmw.Modifiers, false); + } +#endif + return mb; + } + else + { + throw new InvalidOperationException(); + } + } + ClassFile.Method m = classFile.Methods[index]; + MethodBuilder method; + bool setModifiers = false; + if (methods[index].HasCallerID && (m.Modifiers & Modifiers.VarArgs) != 0) + { + // the implicit callerID parameter was added at the end so that means we shouldn't use ParamArrayAttribute, + // so we need to explicitly record that the method is varargs + setModifiers = true; + } + if (m.IsConstructor) + { + method = GenerateConstructor(methods[index]); + // strictfp is the only modifier that a constructor can have + if (m.IsStrictfp) + { + setModifiers = true; + } + } + else if (m.IsClassInitializer) + { + method = ReflectUtil.DefineTypeInitializer(typeBuilder, wrapper.classLoader); + } + else + { + method = GenerateMethod(index, m, ref setModifiers); + } + string[] exceptions = m.ExceptionsAttribute; + methods[index].SetDeclaredExceptions(exceptions); +#if STATIC_COMPILER + AttributeHelper.SetThrowsAttribute(method, exceptions); + if (setModifiers || m.IsInternal || (m.Modifiers & (Modifiers.Synthetic | Modifiers.Bridge)) != 0) + { + AttributeHelper.SetModifiers(method, m.Modifiers, m.IsInternal); + } + if ((m.Modifiers & (Modifiers.Synthetic | Modifiers.Bridge)) != 0 + && (m.IsPublic || m.IsProtected) + && wrapper.IsPublic + && !IsAccessBridge(classFile, m)) + { + AttributeHelper.SetEditorBrowsableNever(method); + // TODO on WHIDBEY apply CompilerGeneratedAttribute + } + if (m.DeprecatedAttribute && !Annotation.HasObsoleteAttribute(m.Annotations)) + { + AttributeHelper.SetDeprecatedAttribute(method); + } + if (m.GenericSignature != null) + { + AttributeHelper.SetSignatureAttribute(method, m.GenericSignature); + } + if (wrapper.GetClassLoader().NoParameterReflection) + { + // ignore MethodParameters (except to extract parameter names) + } + else if (m.MalformedMethodParameters) + { + AttributeHelper.SetMethodParametersAttribute(method, null); + } + else if (m.MethodParameters != null) + { + Modifiers[] modifiers = new Modifiers[m.MethodParameters.Length]; + for (int i = 0; i < modifiers.Length; i++) + { + modifiers[i] = (Modifiers)m.MethodParameters[i].flags; + } + AttributeHelper.SetMethodParametersAttribute(method, modifiers); + } + if (m.RuntimeVisibleTypeAnnotations != null) + { + AttributeHelper.SetRuntimeVisibleTypeAnnotationsAttribute(method, m.RuntimeVisibleTypeAnnotations); + } +#else // STATIC_COMPILER + if (setModifiers) + { + // shut up the compiler + } +#endif // STATIC_COMPILER + return method; + } + finally + { + Profiler.Leave("JavaTypeImpl.GenerateMethod"); + } + } + + private bool HasSerialVersionUID + { + get + { + foreach (FieldWrapper field in fields) + { + if (field.IsSerialVersionUID) + { + return true; + } + } + return false; + } + } + + private MethodBuilder GenerateConstructor(MethodWrapper mw) + { + MethodBuilder cb = mw.GetDefineMethodHelper().DefineConstructor(wrapper, typeBuilder, GetMethodAccess(mw) | MethodAttributes.HideBySig); + cb.SetImplementationFlags(MethodImplAttributes.NoInlining); + return cb; + } + + private MethodBuilder GenerateMethod(int index, ClassFile.Method m, ref bool setModifiers) + { + MethodAttributes attribs = MethodAttributes.HideBySig; + if (m.IsNative) + { + if (wrapper.IsPInvokeMethod(m)) + { + // this doesn't appear to be necessary, but we use the flag in Finish to know + // that we shouldn't emit a method body + attribs |= MethodAttributes.PinvokeImpl; + } + else + { + setModifiers = true; + } + } + if (methods[index].IsPropertyAccessor) + { + attribs |= GetPropertyAccess(methods[index]); + attribs |= MethodAttributes.SpecialName; + setModifiers = true; + } + else + { + attribs |= GetMethodAccess(methods[index]); + } + if (m.IsAbstract || (!m.IsStatic && m.IsPublic && classFile.IsInterface)) + { + // only if the classfile is abstract, we make the CLR method abstract, otherwise, + // we have to generate a method that throws an AbstractMethodError (because the JVM + // allows abstract methods in non-abstract classes) + if (classFile.IsAbstract) + { + if (classFile.IsPublic && !classFile.IsFinal && !(m.IsPublic || m.IsProtected)) + { + setModifiers = true; + } + else + { + if (!m.IsAbstract) + { + setModifiers = true; + } + attribs |= MethodAttributes.Abstract; + } + } + else + { + setModifiers = true; + } + } + if (m.IsFinal) + { + if (m.IsVirtual) + { + attribs |= MethodAttributes.Final; + } + else + { + setModifiers = true; + } + } + if (m.IsStatic) + { + attribs |= MethodAttributes.Static; + if (m.IsSynchronized) + { + setModifiers = true; + } + } + else if (!m.IsPrivate) + { + attribs |= MethodAttributes.Virtual | MethodAttributes.CheckAccessOnOverride; + } + string name = UnicodeUtil.EscapeInvalidSurrogates(m.Name); + if (!ReferenceEquals(name, m.Name)) + { + // mark as specialname to remind us to unescape the name + attribs |= MethodAttributes.SpecialName; + } +#if STATIC_COMPILER + if ((m.Modifiers & Modifiers.Bridge) != 0 && (m.IsPublic || m.IsProtected) && wrapper.IsPublic) + { + string sigbase = m.Signature.Substring(0, m.Signature.LastIndexOf(')') + 1); + foreach (MethodWrapper mw in methods) + { + if (mw.Name == m.Name && mw.Signature.StartsWith(sigbase) && mw.Signature != m.Signature) + { + // To prevent bridge methods with covariant return types from confusing + // other .NET compilers (like C#), we rename the bridge method. + name = NamePrefix.Bridge + name; + break; + } + } + } +#endif + if ((attribs & MethodAttributes.Virtual) != 0 && !classFile.IsInterface) + { + if (baseMethods[index] == null || (baseMethods[index].Length == 1 && baseMethods[index][0].DeclaringType.IsInterface)) + { + // we need to set NewSlot here, to prevent accidentally overriding methods + // (for example, if a Java class has a method "boolean Equals(object)", we don't want that method + // to override System.Object.Equals) + attribs |= MethodAttributes.NewSlot; + } + else + { + // if we have a method overriding a more accessible method (the JVM allows this), we need to make the + // method more accessible, because otherwise the CLR will complain that we're reducing access + bool hasPublicBaseMethod = false; + foreach (MethodWrapper baseMethodWrapper in baseMethods[index]) + { + MethodBase baseMethod = baseMethodWrapper.GetMethod(); + if ((baseMethod.IsPublic && !m.IsPublic) || + ((baseMethod.IsFamily || baseMethod.IsFamilyOrAssembly) && !m.IsPublic && !m.IsProtected) || + (!m.IsPublic && !m.IsProtected && !baseMethodWrapper.DeclaringType.IsPackageAccessibleFrom(wrapper))) + { + hasPublicBaseMethod |= baseMethod.IsPublic; + attribs &= ~MethodAttributes.MemberAccessMask; + attribs |= hasPublicBaseMethod ? MethodAttributes.Public : MethodAttributes.FamORAssem; + setModifiers = true; + } + } + } + } + MethodBuilder mb = null; +#if STATIC_COMPILER + mb = wrapper.DefineGhostMethod(typeBuilder, name, attribs, methods[index]); +#endif + if (mb == null) + { + bool needFinalize = false; + bool needDispatch = false; + MethodInfo baseFinalize = null; + if (baseMethods[index] != null && ReferenceEquals(m.Name, StringConstants.FINALIZE) && ReferenceEquals(m.Signature, StringConstants.SIG_VOID)) + { + baseFinalize = GetBaseFinalizeMethod(wrapper.BaseTypeWrapper); + if (baseMethods[index][0].DeclaringType == CoreClasses.java.lang.Object.Wrapper) + { + // This type is the first type in the hierarchy to introduce a finalize method + // (other than the one in java.lang.Object obviously), so we need to override + // the real Finalize method and emit a dispatch call to our finalize method. + needFinalize = true; + needDispatch = true; + } + else if (m.IsFinal) + { + // One of our base classes already has a finalize method, so we already are + // hooked into the real Finalize, but we need to override it again, to make it + // final (so that non-Java types cannot override it either). + needFinalize = true; + needDispatch = false; + // If the base class finalize was optimized away, we need a dispatch call after all. + if (baseFinalize.DeclaringType == Types.Object) + { + needDispatch = true; + } + } + else + { + // One of our base classes already has a finalize method, but it may have been an empty + // method so that the hookup to the real Finalize was optimized away, we need to check + // for that. + if (baseFinalize.DeclaringType == Types.Object) + { + needFinalize = true; + needDispatch = true; + } + } + if (needFinalize && + !m.IsAbstract && !m.IsNative && + (!m.IsFinal || classFile.IsFinal) && + m.Instructions.Length > 0 && + m.Instructions[0].NormalizedOpCode == NormalizedByteCode.__return) + { + // we've got an empty finalize method, so we don't need to override the real finalizer + // (not having a finalizer makes a huge perf difference) + needFinalize = false; + } + } + bool newslot = baseMethods[index] != null + && (methods[index].IsExplicitOverride || baseMethods[index][0].RealName != name || CheckRequireOverrideStub(methods[index], baseMethods[index][0])) + && !needFinalize; + if (newslot) + { + attribs |= MethodAttributes.NewSlot; + } + if (classFile.IsInterface && !m.IsPublic && !wrapper.IsGhost) + { + TypeBuilder tb = typeBuilder; +#if STATIC_COMPILER + if (wrapper.IsPublic && wrapper.classLoader.WorkaroundInterfacePrivateMethods) + { + // FXBUG csc.exe doesn't like non-public methods in interfaces, so we put them in a nested type + if (privateInterfaceMethods == null) + { + privateInterfaceMethods = typeBuilder.DefineNestedType(NestedTypeName.PrivateInterfaceMethods, + TypeAttributes.NestedPrivate | TypeAttributes.Sealed | TypeAttributes.Abstract | TypeAttributes.BeforeFieldInit); + } + tb = privateInterfaceMethods; + attribs &= ~MethodAttributes.MemberAccessMask; + attribs |= MethodAttributes.Assembly; + } +#endif + if (m.IsStatic) + { + mb = methods[index].GetDefineMethodHelper().DefineMethod(wrapper, tb, name, attribs); + } + else + { + // the CLR doesn't allow (non-virtual) instance methods in interfaces, + // so we need to turn it into a static method + mb = methods[index].GetDefineMethodHelper().DefineMethod(wrapper.GetClassLoader().GetTypeWrapperFactory(), + tb, NamePrefix.PrivateInterfaceInstanceMethod + name, attribs | MethodAttributes.Static | MethodAttributes.SpecialName, + typeBuilder, false); +#if STATIC_COMPILER + AttributeHelper.SetNameSig(mb, m.Name, m.Signature); +#endif + } + setModifiers = true; + } + else + { + mb = methods[index].GetDefineMethodHelper().DefineMethod(wrapper, typeBuilder, name, attribs); + } + if (baseMethods[index] != null && !needFinalize) + { + bool subsequent = false; + foreach (MethodWrapper baseMethod in baseMethods[index]) + { + if (CheckRequireOverrideStub(methods[index], baseMethod)) + { + wrapper.GenerateOverrideStub(typeBuilder, baseMethod, mb, methods[index]); + } + else if (subsequent || methods[index].IsExplicitOverride || baseMethod.RealName != name) + { + typeBuilder.DefineMethodOverride(mb, (MethodInfo)baseMethod.GetMethod()); + } + // the non-primary base methods always need an explicit method override + subsequent = true; + } + } + // if we're overriding java.lang.Object.finalize we need to emit a stub to override System.Object.Finalize, + // or if we're subclassing a non-Java class that has a Finalize method, we need a new Finalize override + if (needFinalize) + { + string finalizeName = baseFinalize.Name; + MethodWrapper mwClash = wrapper.GetMethodWrapper(finalizeName, StringConstants.SIG_VOID, true); + if (mwClash != null && mwClash.GetMethod() != baseFinalize) + { + finalizeName = "__"; + } + MethodAttributes attr = MethodAttributes.HideBySig | MethodAttributes.Virtual; + // make sure we don't reduce accessibility + attr |= baseFinalize.IsPublic ? MethodAttributes.Public : MethodAttributes.Family; + if (m.IsFinal) + { + attr |= MethodAttributes.Final; + } + finalizeMethod = typeBuilder.DefineMethod(finalizeName, attr, CallingConventions.Standard, Types.Void, Type.EmptyTypes); + if (finalizeName != baseFinalize.Name) + { + typeBuilder.DefineMethodOverride(finalizeMethod, baseFinalize); + } + AttributeHelper.HideFromJava(finalizeMethod); + CodeEmitter ilgen = CodeEmitter.Create(finalizeMethod); + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.SkipFinalizer); + CodeEmitterLabel skip = ilgen.DefineLabel(); + ilgen.EmitBrtrue(skip); + if (needDispatch) + { + ilgen.BeginExceptionBlock(); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Callvirt, mb); + ilgen.EmitLeave(skip); + ilgen.BeginCatchBlock(Types.Object); + ilgen.EmitLeave(skip); + ilgen.EndExceptionBlock(); + } + else + { + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Call, baseFinalize); + } + ilgen.MarkLabel(skip); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } +#if STATIC_COMPILER + if (classFile.Methods[index].AnnotationDefault != null) + { + CustomAttributeBuilder cab = new CustomAttributeBuilder(StaticCompiler.GetRuntimeType("IKVM.Attributes.AnnotationDefaultAttribute").GetConstructor(new Type[] { Types.Object }), + new object[] { AnnotationDefaultAttribute.Escape(classFile.Methods[index].AnnotationDefault) }); + mb.SetCustomAttribute(cab); + } +#endif // STATIC_COMPILER + } + + if ((methods[index].Modifiers & (Modifiers.Synchronized | Modifiers.Static)) == Modifiers.Synchronized) + { + mb.SetImplementationFlags(mb.GetMethodImplementationFlags() | MethodImplAttributes.Synchronized); + } + + if (classFile.Methods[index].IsForceInline) + { + const MethodImplAttributes AggressiveInlining = (MethodImplAttributes)256; + mb.SetImplementationFlags(mb.GetMethodImplementationFlags() | AggressiveInlining); + } + + if (classFile.Methods[index].IsLambdaFormCompiled || classFile.Methods[index].IsLambdaFormHidden) + { + HideFromJavaFlags flags = HideFromJavaFlags.None; + if (classFile.Methods[index].IsLambdaFormCompiled) + { + flags |= HideFromJavaFlags.StackWalk; + } + if (classFile.Methods[index].IsLambdaFormHidden) + { + flags |= HideFromJavaFlags.StackTrace; + } + AttributeHelper.HideFromJava(mb, flags); + } + + if (classFile.IsInterface && methods[index].IsVirtual && !methods[index].IsAbstract) + { + if (wrapper.IsGhost) + { + DefaultInterfaceMethodWrapper.SetImpl(methods[index], methods[index].GetDefineMethodHelper().DefineMethod(wrapper.GetClassLoader().GetTypeWrapperFactory(), + typeBuilder, NamePrefix.DefaultMethod + mb.Name, MethodAttributes.Public | MethodAttributes.SpecialName, + null, false)); + } + else + { + DefaultInterfaceMethodWrapper.SetImpl(methods[index], methods[index].GetDefineMethodHelper().DefineMethod(wrapper.GetClassLoader().GetTypeWrapperFactory(), + typeBuilder, NamePrefix.DefaultMethod + mb.Name, MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, + typeBuilder, false)); + } + } + + return mb; + } + + private static MethodAttributes GetMethodAccess(MethodWrapper mw) + { + switch (mw.Modifiers & Modifiers.AccessMask) + { + case Modifiers.Private: + return MethodAttributes.Private; + case Modifiers.Protected: + return MethodAttributes.FamORAssem; + case Modifiers.Public: + return MethodAttributes.Public; + default: + return MethodAttributes.Assembly; + } + } + +#if STATIC_COMPILER + // The classic example of an access bridge is StringBuilder.length(), the JDK 6 compiler + // generates this to work around a reflection problem (which otherwise wouldn't surface the + // length() method, because it is defined in the non-public base class AbstractStringBuilder.) + private static bool IsAccessBridge(ClassFile classFile, ClassFile.Method m) + { + // HACK this is a pretty gross hack + // We look at the method body to figure out if the bridge method calls another method with the exact + // same name/signature and if that is the case, we assume that it is an access bridge. + // This code is based on the javac algorithm in addBridgeIfNeeded(...) in com/sun/tools/javac/comp/TransTypes.java. + if ((m.Modifiers & (Modifiers.Abstract | Modifiers.Native | Modifiers.Public | Modifiers.Bridge)) == (Modifiers.Public | Modifiers.Bridge)) + { + foreach (ClassFile.Method.Instruction instr in m.Instructions) + { + if (instr.NormalizedOpCode == NormalizedByteCode.__invokespecial) + { + ClassFile.ConstantPoolItemMI cpi = classFile.SafeGetMethodref(instr.Arg1); + return cpi != null && cpi.Name == m.Name && cpi.Signature == m.Signature; + } + } + } + return false; + } +#endif // STATIC_COMPILER + + internal override Type Type + { + get + { + return typeBuilder; + } + } + + internal override string GetGenericSignature() + { + Debug.Fail("Unreachable code"); + return null; + } + + internal override string[] GetEnclosingMethod() + { + Debug.Fail("Unreachable code"); + return null; + } + + internal override string GetGenericMethodSignature(int index) + { + Debug.Fail("Unreachable code"); + return null; + } + + internal override string GetGenericFieldSignature(int index) + { + Debug.Fail("Unreachable code"); + return null; + } + + internal override object[] GetDeclaredAnnotations() + { + Debug.Fail("Unreachable code"); + return null; + } + + internal override object GetMethodDefaultValue(int index) + { + Debug.Fail("Unreachable code"); + return null; + } + + internal override object[] GetMethodAnnotations(int index) + { + Debug.Fail("Unreachable code"); + return null; + } + + internal override object[][] GetParameterAnnotations(int index) + { + Debug.Fail("Unreachable code"); + return null; + } + + internal override MethodParametersEntry[] GetMethodParameters(int index) + { + Debug.Fail("Unreachable code"); + return null; + } + + internal override object[] GetFieldAnnotations(int index) + { + Debug.Fail("Unreachable code"); + return null; + } + + internal override MethodInfo GetFinalizeMethod() + { + return finalizeMethod; + } + + internal override object[] GetConstantPool() + { + Debug.Fail("Unreachable code"); + return null; + } + + internal override byte[] GetRawTypeAnnotations() + { + Debug.Fail("Unreachable code"); + return null; + } + + internal override byte[] GetMethodRawTypeAnnotations(int index) + { + Debug.Fail("Unreachable code"); + return null; + } + + internal override byte[] GetFieldRawTypeAnnotations(int index) + { + Debug.Fail("Unreachable code"); + return null; + } + + internal override TypeWrapper Host + { + get { return host; } + } + } + + private sealed class Metadata + { + private readonly string[][] genericMetaData; + private readonly object[][] annotations; + private readonly MethodParametersEntry[][] methodParameters; + private readonly byte[][][] runtimeVisibleTypeAnnotations; + private readonly object[] constantPool; + + private Metadata(string[][] genericMetaData, object[][] annotations, MethodParametersEntry[][] methodParameters, + byte[][][] runtimeVisibleTypeAnnotations, object[] constantPool) + { + this.genericMetaData = genericMetaData; + this.annotations = annotations; + this.methodParameters = methodParameters; + this.runtimeVisibleTypeAnnotations = runtimeVisibleTypeAnnotations; + this.constantPool = constantPool; + } + + internal static Metadata Create(ClassFile classFile) + { + if (classFile.MajorVersion < 49) + { + return null; + } + string[][] genericMetaData = null; + object[][] annotations = null; + MethodParametersEntry[][] methodParameters = null; + byte[][][] runtimeVisibleTypeAnnotations = null; + for (int i = 0; i < classFile.Methods.Length; i++) + { + if (classFile.Methods[i].GenericSignature != null) + { + if (genericMetaData == null) + { + genericMetaData = new string[4][]; + } + if (genericMetaData[0] == null) + { + genericMetaData[0] = new string[classFile.Methods.Length]; + } + genericMetaData[0][i] = classFile.Methods[i].GenericSignature; + } + if (classFile.Methods[i].Annotations != null) + { + if (annotations == null) + { + annotations = new object[5][]; + } + if (annotations[1] == null) + { + annotations[1] = new object[classFile.Methods.Length]; + } + annotations[1][i] = classFile.Methods[i].Annotations; + } + if (classFile.Methods[i].ParameterAnnotations != null) + { + if (annotations == null) + { + annotations = new object[5][]; + } + if (annotations[2] == null) + { + annotations[2] = new object[classFile.Methods.Length]; + } + annotations[2][i] = classFile.Methods[i].ParameterAnnotations; + } + if (classFile.Methods[i].AnnotationDefault != null) + { + if (annotations == null) + { + annotations = new object[5][]; + } + if (annotations[3] == null) + { + annotations[3] = new object[classFile.Methods.Length]; + } + annotations[3][i] = classFile.Methods[i].AnnotationDefault; + } + if (classFile.Methods[i].MethodParameters != null) + { + if (methodParameters == null) + { + methodParameters = new MethodParametersEntry[classFile.Methods.Length][]; + } + methodParameters[i] = classFile.Methods[i].MethodParameters; + } + if (classFile.Methods[i].RuntimeVisibleTypeAnnotations != null) + { + if (runtimeVisibleTypeAnnotations == null) + { + runtimeVisibleTypeAnnotations = new byte[3][][]; + } + if (runtimeVisibleTypeAnnotations[1] == null) + { + runtimeVisibleTypeAnnotations[1] = new byte[classFile.Methods.Length][]; + } + runtimeVisibleTypeAnnotations[1][i] = classFile.Methods[i].RuntimeVisibleTypeAnnotations; + } + } + for (int i = 0; i < classFile.Fields.Length; i++) + { + if (classFile.Fields[i].GenericSignature != null) + { + if (genericMetaData == null) + { + genericMetaData = new string[4][]; + } + if (genericMetaData[1] == null) + { + genericMetaData[1] = new string[classFile.Fields.Length]; + } + genericMetaData[1][i] = classFile.Fields[i].GenericSignature; + } + if (classFile.Fields[i].Annotations != null) + { + if (annotations == null) + { + annotations = new object[5][]; + } + if (annotations[4] == null) + { + annotations[4] = new object[classFile.Fields.Length][]; + } + annotations[4][i] = classFile.Fields[i].Annotations; + } + if (classFile.Fields[i].RuntimeVisibleTypeAnnotations != null) + { + if (runtimeVisibleTypeAnnotations == null) + { + runtimeVisibleTypeAnnotations = new byte[3][][]; + } + if (runtimeVisibleTypeAnnotations[2] == null) + { + runtimeVisibleTypeAnnotations[2] = new byte[classFile.Fields.Length][]; + } + runtimeVisibleTypeAnnotations[2][i] = classFile.Fields[i].RuntimeVisibleTypeAnnotations; + } + } + if (classFile.EnclosingMethod != null) + { + if (genericMetaData == null) + { + genericMetaData = new string[4][]; + } + genericMetaData[2] = classFile.EnclosingMethod; + } + if (classFile.GenericSignature != null) + { + if (genericMetaData == null) + { + genericMetaData = new string[4][]; + } + genericMetaData[3] = new string[] { classFile.GenericSignature }; + } + if (classFile.Annotations != null) + { + if (annotations == null) + { + annotations = new object[5][]; + } + annotations[0] = classFile.Annotations; + } + if (classFile.RuntimeVisibleTypeAnnotations != null) + { + if (runtimeVisibleTypeAnnotations == null) + { + runtimeVisibleTypeAnnotations = new byte[3][][]; + } + runtimeVisibleTypeAnnotations[0] = new byte[1][] { classFile.RuntimeVisibleTypeAnnotations }; + } + if (genericMetaData != null || annotations != null || methodParameters != null || runtimeVisibleTypeAnnotations != null) + { + object[] constantPool = runtimeVisibleTypeAnnotations == null ? null : classFile.GetConstantPool(); + return new Metadata(genericMetaData, annotations, methodParameters, runtimeVisibleTypeAnnotations, constantPool); + } + return null; + } + + internal static string GetGenericSignature(Metadata m) + { + if (m != null && m.genericMetaData != null && m.genericMetaData[3] != null) + { + return m.genericMetaData[3][0]; + } + return null; + } + + internal static string[] GetEnclosingMethod(Metadata m) + { + if (m != null && m.genericMetaData != null) + { + return m.genericMetaData[2]; + } + return null; + } + + internal static string GetGenericMethodSignature(Metadata m, int index) + { + if (m != null && m.genericMetaData != null && m.genericMetaData[0] != null) + { + return m.genericMetaData[0][index]; + } + return null; + } + + internal static string GetGenericFieldSignature(Metadata m, int index) + { + if (m != null && m.genericMetaData != null && m.genericMetaData[1] != null) + { + return m.genericMetaData[1][index]; + } + return null; + } + + internal static object[] GetAnnotations(Metadata m) + { + if (m != null && m.annotations != null) + { + return m.annotations[0]; + } + return null; + } + + internal static object[] GetMethodAnnotations(Metadata m, int index) + { + if (m != null && m.annotations != null && m.annotations[1] != null) + { + return (object[])m.annotations[1][index]; + } + return null; + } + + internal static object[][] GetMethodParameterAnnotations(Metadata m, int index) + { + if (m != null && m.annotations != null && m.annotations[2] != null) + { + return (object[][])m.annotations[2][index]; + } + return null; + } + + internal static MethodParametersEntry[] GetMethodParameters(Metadata m, int index) + { + if (m != null && m.methodParameters != null) + { + return m.methodParameters[index]; + } + return null; + } + + internal static object GetMethodDefaultValue(Metadata m, int index) + { + if (m != null && m.annotations != null && m.annotations[3] != null) + { + return m.annotations[3][index]; + } + return null; + } + + // note that unlike GetGenericFieldSignature, the index is simply the field index + internal static object[] GetFieldAnnotations(Metadata m, int index) + { + if (m != null && m.annotations != null && m.annotations[4] != null) + { + return (object[])m.annotations[4][index]; + } + return null; + } + + internal static object[] GetConstantPool(Metadata m) + { + return m.constantPool; + } + + internal static byte[] GetRawTypeAnnotations(Metadata m) + { + if (m != null && m.runtimeVisibleTypeAnnotations != null && m.runtimeVisibleTypeAnnotations[0] != null) + { + return m.runtimeVisibleTypeAnnotations[0][0]; + } + return null; + } + + internal static byte[] GetMethodRawTypeAnnotations(Metadata m, int index) + { + if (m != null && m.runtimeVisibleTypeAnnotations != null && m.runtimeVisibleTypeAnnotations[1] != null) + { + return m.runtimeVisibleTypeAnnotations[1][index]; + } + return null; + } + + internal static byte[] GetFieldRawTypeAnnotations(Metadata m, int index) + { + if (m != null && m.runtimeVisibleTypeAnnotations != null && m.runtimeVisibleTypeAnnotations[2] != null) + { + return m.runtimeVisibleTypeAnnotations[2][index]; + } + return null; + } + } + + private sealed class FinishedTypeImpl : DynamicImpl + { + private readonly Type type; + private readonly TypeWrapper[] innerclasses; + private readonly TypeWrapper declaringTypeWrapper; + private readonly Modifiers reflectiveModifiers; + private readonly MethodInfo clinitMethod; + private readonly MethodInfo finalizeMethod; + private readonly Metadata metadata; + private readonly TypeWrapper host; + + internal FinishedTypeImpl(Type type, TypeWrapper[] innerclasses, TypeWrapper declaringTypeWrapper, Modifiers reflectiveModifiers, Metadata metadata, MethodInfo clinitMethod, MethodInfo finalizeMethod, TypeWrapper host) + { + this.type = type; + this.innerclasses = innerclasses; + this.declaringTypeWrapper = declaringTypeWrapper; + this.reflectiveModifiers = reflectiveModifiers; + this.clinitMethod = clinitMethod; + this.finalizeMethod = finalizeMethod; + this.metadata = metadata; + this.host = host; + } + + internal override TypeWrapper[] InnerClasses + { + get + { + // TODO compute the innerclasses lazily (and fix JavaTypeImpl to not always compute them) + return innerclasses; + } + } + + internal override TypeWrapper DeclaringTypeWrapper + { + get + { + // TODO compute lazily (and fix JavaTypeImpl to not always compute it) + return declaringTypeWrapper; + } + } + + internal override Modifiers ReflectiveModifiers + { + get + { + return reflectiveModifiers; + } + } + + internal override Type Type + { + get + { + return type; + } + } + + internal override void EmitRunClassConstructor(CodeEmitter ilgen) + { + if (clinitMethod != null) + { + ilgen.Emit(OpCodes.Call, clinitMethod); + } + } + + internal override DynamicImpl Finish() + { + return this; + } + + internal override MethodBase LinkMethod(MethodWrapper mw) + { + // we should never be called, because all methods on a finished type are already linked + Debug.Assert(false); + return mw.GetMethod(); + } + + internal override FieldInfo LinkField(FieldWrapper fw) + { + // we should never be called, because all fields on a finished type are already linked + Debug.Assert(false); + return fw.GetField(); + } + + internal override string GetGenericSignature() + { + return Metadata.GetGenericSignature(metadata); + } + + internal override string[] GetEnclosingMethod() + { + return Metadata.GetEnclosingMethod(metadata); + } + + internal override string GetGenericMethodSignature(int index) + { + return Metadata.GetGenericMethodSignature(metadata, index); + } + + internal override string GetGenericFieldSignature(int index) + { + return Metadata.GetGenericFieldSignature(metadata, index); + } + + internal override object[] GetDeclaredAnnotations() + { + return Metadata.GetAnnotations(metadata); + } + + internal override object GetMethodDefaultValue(int index) + { + return Metadata.GetMethodDefaultValue(metadata, index); + } + + internal override object[] GetMethodAnnotations(int index) + { + return Metadata.GetMethodAnnotations(metadata, index); + } + + internal override object[][] GetParameterAnnotations(int index) + { + return Metadata.GetMethodParameterAnnotations(metadata, index); + } + + internal override MethodParametersEntry[] GetMethodParameters(int index) + { + return Metadata.GetMethodParameters(metadata, index); + } + + internal override object[] GetFieldAnnotations(int index) + { + return Metadata.GetFieldAnnotations(metadata, index); + } + + internal override MethodInfo GetFinalizeMethod() + { + return finalizeMethod; + } + + internal override object[] GetConstantPool() + { + return Metadata.GetConstantPool(metadata); + } + + internal override byte[] GetRawTypeAnnotations() + { + return Metadata.GetRawTypeAnnotations(metadata); + } + + internal override byte[] GetMethodRawTypeAnnotations(int index) + { + return Metadata.GetMethodRawTypeAnnotations(metadata, index); + } + + internal override byte[] GetFieldRawTypeAnnotations(int index) + { + return Metadata.GetFieldRawTypeAnnotations(metadata, index); + } + + internal override TypeWrapper Host + { + get { return host; } + } + } + + internal sealed class FinishContext + { + private readonly TypeWrapper host; + private readonly ClassFile classFile; + private readonly DynamicOrAotTypeWrapper wrapper; + private readonly TypeBuilder typeBuilder; + private List nestedTypeBuilders; + private MethodInfo callerIDMethod; + private List items; + private Dictionary arfuMap; + private Dictionary invokespecialstubcache; + private Dictionary dynamicClassLiteral; +#if STATIC_COMPILER + private TypeBuilder interfaceHelperMethodsTypeBuilder; +#else + private List liveObjects; +#endif + + private struct Item + { + internal int key; + internal object value; + } + + internal FinishContext(TypeWrapper host, ClassFile classFile, DynamicOrAotTypeWrapper wrapper, TypeBuilder typeBuilder) + { + this.host = host; + this.classFile = classFile; + this.wrapper = wrapper; + this.typeBuilder = typeBuilder; + } + + internal DynamicTypeWrapper TypeWrapper + { + get { return wrapper; } + } + + internal T GetValue(int key) + where T : class, new() + { + if (items == null) + { + items = new List(); + } + for (int i = 0; i < items.Count; i++) + { + T value; + if (items[i].key == key && (value = items[i].value as T) != null) + { + return value; + } + } + Item item; + item.key = key; + T val = new T(); + item.value = val; + items.Add(item); + return val; + } + + internal void EmitDynamicClassLiteral(CodeEmitter ilgen, TypeWrapper tw, bool dynamicCallerID) + { + Debug.Assert(tw.IsUnloadable); + if (dynamicClassLiteral == null) + { + dynamicClassLiteral = new Dictionary(); + } + string cacheKey = tw.Name; + if (dynamicCallerID) + { + cacheKey += ";dynamic"; + } + MethodInfo method; + if (!dynamicClassLiteral.TryGetValue(cacheKey, out method)) + { + FieldBuilder fb = typeBuilder.DefineField("__<>class", CoreClasses.java.lang.Class.Wrapper.TypeAsSignatureType, FieldAttributes.PrivateScope | FieldAttributes.Static); + MethodBuilder mb = DefineHelperMethod("__<>class", CoreClasses.java.lang.Class.Wrapper.TypeAsSignatureType, Type.EmptyTypes); + CodeEmitter ilgen2 = CodeEmitter.Create(mb); + ilgen2.Emit(OpCodes.Ldsfld, fb); + CodeEmitterLabel label = ilgen2.DefineLabel(); + ilgen2.EmitBrtrue(label); + ilgen2.Emit(OpCodes.Ldstr, tw.Name); + EmitCallerID(ilgen2, dynamicCallerID); + ilgen2.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicClassLiteral); + ilgen2.Emit(OpCodes.Stsfld, fb); + ilgen2.MarkLabel(label); + ilgen2.Emit(OpCodes.Ldsfld, fb); + ilgen2.Emit(OpCodes.Ret); + ilgen2.DoEmit(); + method = mb; + dynamicClassLiteral.Add(cacheKey, method); + } + ilgen.Emit(OpCodes.Call, method); + } + + internal void EmitHostCallerID(CodeEmitter ilgen) + { +#if STATIC_COMPILER || FIRST_PASS + throw new InvalidOperationException(); +#else + EmitLiveObjectLoad(ilgen, DynamicCallerIDProvider.CreateCallerID(host)); + CoreClasses.ikvm.@internal.CallerID.Wrapper.EmitCheckcast(ilgen); +#endif + } + + internal void EmitCallerID(CodeEmitter ilgen, bool dynamic) + { +#if !FIRST_PASS && !STATIC_COMPILER + if (dynamic) + { + EmitLiveObjectLoad(ilgen, DynamicCallerIDProvider.Instance); + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicCallerID); + return; + } +#endif + if (callerIDMethod == null) + { + CreateGetCallerID(); + } + ilgen.Emit(OpCodes.Call, callerIDMethod); + } + + private void CreateGetCallerID() + { + TypeWrapper tw = CoreClasses.ikvm.@internal.CallerID.Wrapper; + FieldBuilder callerIDField = typeBuilder.DefineField("__", tw.TypeAsSignatureType, FieldAttributes.Private | FieldAttributes.Static | FieldAttributes.SpecialName); + MethodBuilder mb = DefineHelperMethod("__", tw.TypeAsSignatureType, Type.EmptyTypes); + callerIDMethod = mb; + CodeEmitter ilgen = CodeEmitter.Create(mb); + ilgen.Emit(OpCodes.Ldsfld, callerIDField); + CodeEmitterLabel done = ilgen.DefineLabel(); + ilgen.EmitBrtrue(done); + EmitCallerIDInitialization(ilgen, callerIDField); + ilgen.MarkLabel(done); + ilgen.Emit(OpCodes.Ldsfld, callerIDField); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + + private void RegisterNestedTypeBuilder(TypeBuilder tb) + { + if (nestedTypeBuilders == null) + { + nestedTypeBuilders = new List(); + } + nestedTypeBuilders.Add(tb); + } + + internal Type FinishImpl() + { + MethodWrapper[] methods = wrapper.GetMethods(); + FieldWrapper[] fields = wrapper.GetFields(); +#if STATIC_COMPILER + wrapper.FinishGhost(typeBuilder, methods); +#endif // STATIC_COMPILER + + if (!classFile.IsInterface) + { + // set the base type (this needs to be done before we emit any methods, because in the static compiler + // GetBaseTypeForDefineType() has the side effect of inserting the __WorkaroundBaseClass__ when necessary) + typeBuilder.SetParent(wrapper.GetBaseTypeForDefineType()); + } + + // if we're not abstract make sure we don't inherit any abstract methods + if (!wrapper.IsAbstract) + { + TypeWrapper parent = wrapper.BaseTypeWrapper; + // if parent is not abstract, the .NET implementation will never have abstract methods (only + // stubs that throw AbstractMethodError) + // NOTE interfaces are supposed to be abstract, but the VM doesn't enforce this, so + // we have to check for a null parent (interfaces have no parent). + while (parent != null && parent.IsAbstract) + { + foreach (MethodWrapper mw in parent.GetMethods()) + { + MethodInfo mi = mw.GetMethod() as MethodInfo; + if (mi != null && mi.IsAbstract && !mi.DeclaringType.IsInterface) + { + bool needStub = false; + bool needRename = false; + if (mw.IsPublic || mw.IsProtected) + { + MethodWrapper fmw = wrapper.GetMethodWrapper(mw.Name, mw.Signature, true); + while (fmw != mw && (fmw.IsStatic || fmw.IsPrivate)) + { + needRename = true; + fmw = fmw.DeclaringType.BaseTypeWrapper.GetMethodWrapper(mw.Name, mw.Signature, true); + } + if (fmw == mw && fmw.DeclaringType != wrapper) + { + needStub = true; + } + } + else + { + MethodWrapper fmw = wrapper.GetMethodWrapper(mw.Name, mw.Signature, true); + while (fmw != mw && (fmw.IsStatic || fmw.IsPrivate || !(mw.DeclaringType.IsPackageAccessibleFrom(fmw.DeclaringType) || (mw.IsInternal && mw.DeclaringType.InternalsVisibleTo(fmw.DeclaringType))))) + { + needRename = true; + fmw = fmw.DeclaringType.BaseTypeWrapper.GetMethodWrapper(mw.Name, mw.Signature, true); + } + if (fmw == mw && fmw.DeclaringType != wrapper) + { + needStub = true; + } + } + if (needStub) + { + // NOTE in Sun's JRE 1.4.1 this method cannot be overridden by subclasses, + // but I think this is a bug, so we'll support it anyway. + string name = mi.Name; + MethodAttributes attr = mi.Attributes & ~(MethodAttributes.Abstract | MethodAttributes.NewSlot); + if (needRename) + { + name = "__<>" + name + "/" + mi.DeclaringType.FullName; + attr = MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot; + } + MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(wrapper, typeBuilder, name, attr); + if (needRename) + { + typeBuilder.DefineMethodOverride(mb, mi); + } + AttributeHelper.HideFromJava(mb); + CodeEmitter ilgen = CodeEmitter.Create(mb); + ilgen.EmitThrow("java.lang.AbstractMethodError", mw.DeclaringType.Name + "." + mw.Name + mw.Signature); + ilgen.DoEmit(); + wrapper.EmitLevel4Warning(HardError.AbstractMethodError, mw.DeclaringType.Name + "." + mw.Name + mw.Signature); + } + } + } + parent = parent.BaseTypeWrapper; + } + } +#if STATIC_COMPILER + TypeBuilder tbDefaultMethods = null; +#endif + bool basehasclinit = wrapper.BaseTypeWrapper != null && wrapper.BaseTypeWrapper.HasStaticInitializer; + int clinitIndex = -1; + bool hasConstructor = false; + for (int i = 0; i < classFile.Methods.Length; i++) + { + ClassFile.Method m = classFile.Methods[i]; + MethodBuilder mb = (MethodBuilder)methods[i].GetMethod(); + if (mb == null) + { + // method doesn't really exist (e.g. delegate constructor or that is optimized away) + if (m.IsConstructor) + { + hasConstructor = true; + } + } + else if (m.IsClassInitializer) + { + // we handle the after we've done the other methods, + // to make it easier to inject code needed by the other methods + clinitIndex = i; + continue; + } + else if (m.IsConstructor) + { + hasConstructor = true; + CodeEmitter ilGenerator = CodeEmitter.Create(mb); + CompileConstructorBody(this, ilGenerator, i); + } + else + { +#if STATIC_COMPILER + if (methods[i].GetParameters().Length > MethodHandleUtil.MaxArity && methods[i].RequiresNonVirtualDispatcher && wrapper.GetClassLoader().EmitNoRefEmitHelpers) + { + wrapper.GetClassLoader().GetTypeWrapperFactory().DefineDelegate(methods[i].GetParameters().Length, methods[i].ReturnType == PrimitiveTypeWrapper.VOID); + } +#endif + if (m.IsAbstract) + { + bool stub = false; + if (!classFile.IsAbstract) + { + // NOTE in the JVM it is apparently legal for a non-abstract class to have abstract methods, but + // the CLR doens't allow this, so we have to emit a method that throws an AbstractMethodError + stub = true; + wrapper.EmitLevel4Warning(HardError.AbstractMethodError, classFile.Name + "." + m.Name + m.Signature); + } + else if (classFile.IsPublic && !classFile.IsFinal && !(m.IsPublic || m.IsProtected)) + { + // We have an abstract package accessible method in our public class. To allow a class in another + // assembly to subclass this class, we must fake the abstractness of this method. + stub = true; + } + if (stub) + { + CodeEmitter ilGenerator = CodeEmitter.Create(mb); + TraceHelper.EmitMethodTrace(ilGenerator, classFile.Name + "." + m.Name + m.Signature); + ilGenerator.EmitThrow("java.lang.AbstractMethodError", classFile.Name + "." + m.Name + m.Signature); + ilGenerator.DoEmit(); + } + } + else if (m.IsNative) + { + if ((mb.Attributes & MethodAttributes.PinvokeImpl) != 0) + { + continue; + } + if (wrapper.IsDelegate) + { + mb.SetImplementationFlags(mb.GetMethodImplementationFlags() | MethodImplAttributes.Runtime); + continue; + } + Profiler.Enter("JavaTypeImpl.Finish.Native"); + try + { + CodeEmitter ilGenerator = CodeEmitter.Create(mb); + TraceHelper.EmitMethodTrace(ilGenerator, classFile.Name + "." + m.Name + m.Signature); +#if STATIC_COMPILER + // do we have an implementation in map.xml? + if (wrapper.EmitMapXmlMethodPrologueAndOrBody(ilGenerator, classFile, m)) + { + ilGenerator.DoEmit(); + continue; + } + if (m.InterlockedCompareAndSetField != null && EmitInterlockedCompareAndSet(methods[i], m.InterlockedCompareAndSetField, ilGenerator)) + { + ilGenerator.DoEmit(); + continue; + } +#endif + // see if there exists a "managed JNI" class for this type + Type nativeCodeType = null; +#if STATIC_COMPILER + nativeCodeType = StaticCompiler.GetType(wrapper.GetClassLoader(), "IKVM.NativeCode." + classFile.Name.Replace('$', '+')); + if (nativeCodeType == null) + { + // simple JNI like class name mangling + nativeCodeType = StaticCompiler.GetType(wrapper.GetClassLoader(), "Java_" + classFile.Name.Replace('.', '_').Replace("$", "_00024")); + } +#endif + MethodInfo nativeMethod = null; + TypeWrapper[] args = methods[i].GetParameters(); + TypeWrapper[] nargs = args; + if (nativeCodeType != null) + { + if (!m.IsStatic) + { + nargs = ArrayUtil.Concat(wrapper, args); + } + if (methods[i].HasCallerID) + { + nargs = ArrayUtil.Concat(nargs, CoreClasses.ikvm.@internal.CallerID.Wrapper); + } + MethodInfo[] nativeCodeTypeMethods = nativeCodeType.GetMethods(BindingFlags.Static | BindingFlags.Public); + foreach (MethodInfo method in nativeCodeTypeMethods) + { + ParameterInfo[] param = method.GetParameters(); + int paramLength = param.Length; + while (paramLength != 0 && (param[paramLength - 1].IsIn || param[paramLength - 1].ParameterType.IsByRef)) + { + paramLength--; + } + TypeWrapper[] match = new TypeWrapper[paramLength]; + for (int j = 0; j < paramLength; j++) + { + match[j] = ClassLoaderWrapper.GetWrapperFromType(param[j].ParameterType); + } + if (m.Name == method.Name && IsCompatibleArgList(nargs, match)) + { + // TODO instead of taking the first matching method, we should find the best one + nativeMethod = method; + break; + } + } + } + if (nativeMethod != null) + { +#if STATIC_COMPILER + for (int j = 0; j < nargs.Length; j++) + { + ilGenerator.EmitLdarg(j); + } + ParameterInfo[] param = nativeMethod.GetParameters(); + for (int j = nargs.Length; j < param.Length; j++) + { + Type paramType = param[j].ParameterType; + TypeWrapper fieldTypeWrapper = ClassLoaderWrapper.GetWrapperFromType(paramType.IsByRef ? paramType.GetElementType() : paramType); + FieldWrapper field = wrapper.GetFieldWrapper(param[j].Name, fieldTypeWrapper.SigName); + if (field == null) + { + Console.Error.WriteLine("Error: Native method field binding not found: {0}.{1}{2}", classFile.Name, param[j].Name, fieldTypeWrapper.SigName); + StaticCompiler.errorCount++; + continue; + } + if (m.IsStatic && !field.IsStatic) + { + Console.Error.WriteLine("Error: Native method field binding cannot access instance field from static method: {0}.{1}{2}", classFile.Name, param[j].Name, fieldTypeWrapper.SigName); + StaticCompiler.errorCount++; + continue; + } + if (!field.IsAccessibleFrom(wrapper, wrapper, wrapper)) + { + Console.Error.WriteLine("Error: Native method field binding not accessible: {0}.{1}{2}", classFile.Name, param[j].Name, fieldTypeWrapper.SigName); + StaticCompiler.errorCount++; + continue; + } + if (paramType.IsByRef && field.IsFinal) + { + Console.Error.WriteLine("Error: Native method field binding cannot use ByRef for final field: {0}.{1}{2}", classFile.Name, param[j].Name, fieldTypeWrapper.SigName); + StaticCompiler.errorCount++; + continue; + } + field.Link(); + if (paramType.IsByRef && field.GetField() == null) + { + Console.Error.WriteLine("Error: Native method field binding cannot use ByRef on field without backing field: {0}.{1}{2}", classFile.Name, param[j].Name, fieldTypeWrapper.SigName); + StaticCompiler.errorCount++; + continue; + } + if (!field.IsStatic) + { + ilGenerator.EmitLdarg(0); + } + if (paramType.IsByRef) + { + ilGenerator.Emit(field.IsStatic ? OpCodes.Ldsflda : OpCodes.Ldflda, field.GetField()); + } + else + { + field.EmitGet(ilGenerator); + } + } + ilGenerator.Emit(OpCodes.Call, nativeMethod); + TypeWrapper retTypeWrapper = methods[i].ReturnType; + if (!retTypeWrapper.TypeAsTBD.Equals(nativeMethod.ReturnType) && !retTypeWrapper.IsGhost) + { + ilGenerator.Emit(OpCodes.Castclass, retTypeWrapper.TypeAsTBD); + } + ilGenerator.Emit(OpCodes.Ret); +#endif + } + else + { + if (wrapper.classLoader.NoJNI) + { + // since NoJniStubs can only be set when we're statically compiling, it is safe to use the "compiler" trace switch + Tracer.Warning(Tracer.Compiler, "Native method not implemented: {0}.{1}.{2}", classFile.Name, m.Name, m.Signature); + ilGenerator.EmitThrow("java.lang.UnsatisfiedLinkError", "Native method not implemented (compiled with -nojni): " + classFile.Name + "." + m.Name + m.Signature); + } +#if STATIC_COMPILER + else if (StaticCompiler.runtimeJniAssembly == null) + { + Console.Error.WriteLine("Error: Native method not implemented: {0}.{1}{2}", classFile.Name, m.Name, m.Signature); + StaticCompiler.errorCount++; + } +#endif + else + { + if (JVM.IsSaveDebugImage) + { +#if !STATIC_COMPILER + JniProxyBuilder.Generate(this, ilGenerator, wrapper, methods[i], typeBuilder, classFile, m, args); +#endif // !STATIC_COMPILER + } + else + { + JniBuilder.Generate(this, ilGenerator, wrapper, methods[i], typeBuilder, classFile, m, args, false); + } + } + } + ilGenerator.DoEmit(); + } + finally + { + Profiler.Leave("JavaTypeImpl.Finish.Native"); + } + } + else + { + if (m.IsVirtual && classFile.IsInterface) + { + mb = (MethodBuilder)DefaultInterfaceMethodWrapper.GetImpl(methods[i]); +#if STATIC_COMPILER + CreateDefaultMethodInterop(ref tbDefaultMethods, mb, methods[i]); +#endif + } + CodeEmitter ilGenerator = CodeEmitter.Create(mb); + if (!m.IsStatic && !m.IsPublic && classFile.IsInterface) + { + // Java 8 non-virtual interface method that we compile as a static method, + // we need to make sure the passed in this reference isn't null + ilGenerator.EmitLdarg(0); + if (wrapper.IsGhost) + { + ilGenerator.Emit(OpCodes.Ldfld, wrapper.GhostRefField); + } + ilGenerator.EmitNullCheck(); + } + TraceHelper.EmitMethodTrace(ilGenerator, classFile.Name + "." + m.Name + m.Signature); +#if STATIC_COMPILER + // do we have an implementation in map.xml? + if (wrapper.EmitMapXmlMethodPrologueAndOrBody(ilGenerator, classFile, m)) + { + ilGenerator.DoEmit(); + continue; + } +#endif // STATIC_COMPILER + bool nonleaf = false; + Compiler.Compile(this, host, wrapper, methods[i], classFile, m, ilGenerator, ref nonleaf); + ilGenerator.CheckLabels(); + ilGenerator.DoEmit(); + if (nonleaf && !m.IsForceInline) + { + mb.SetImplementationFlags(mb.GetMethodImplementationFlags() | MethodImplAttributes.NoInlining); + } +#if STATIC_COMPILER + ilGenerator.EmitLineNumberTable(mb); +#else // STATIC_COMPILER + byte[] linenumbers = ilGenerator.GetLineNumberTable(); + if (linenumbers != null) + { + if (wrapper.lineNumberTables == null) + { + wrapper.lineNumberTables = new byte[methods.Length][]; + } + wrapper.lineNumberTables[i] = linenumbers; + } +#endif // STATIC_COMPILER + } + } + } + + AddInheritedDefaultInterfaceMethods(methods); + + if (clinitIndex != -1 || (basehasclinit && !classFile.IsInterface) || classFile.HasInitializedFields) + { + MethodBuilder cb; + if (clinitIndex != -1) + { + cb = (MethodBuilder)methods[clinitIndex].GetMethod(); + } + else + { + cb = ReflectUtil.DefineTypeInitializer(typeBuilder, wrapper.classLoader); + AttributeHelper.HideFromJava(cb); + } + CodeEmitter ilGenerator = CodeEmitter.Create(cb); + // before we call the base class initializer, we need to set the non-final static ConstantValue fields + EmitConstantValueInitialization(fields, ilGenerator); + if (basehasclinit) + { + wrapper.BaseTypeWrapper.EmitRunClassConstructor(ilGenerator); + } + if (clinitIndex != -1) + { + CompileConstructorBody(this, ilGenerator, clinitIndex); + } + else + { + ilGenerator.Emit(OpCodes.Ret); + ilGenerator.DoEmit(); + } + ilGenerator.CheckLabels(); + } + + // add all interfaces that we implement (including the magic ones) and handle ghost conversions + ImplementInterfaces(wrapper.Interfaces, new List()); + + // NOTE non-final fields aren't allowed in interfaces so we don't have to initialize constant fields + if (!classFile.IsInterface) + { + // if a class has no constructor, we generate one otherwise Ref.Emit will create a default ctor + // and that has several problems: + // - base type may not have an accessible default constructor + // - Ref.Emit uses BaseType.GetConstructors() which may trigger a TypeResolve event + // - we don't want the synthesized constructor to show up in Java + if (!hasConstructor) + { + CodeEmitter ilgen = CodeEmitter.Create(ReflectUtil.DefineConstructor(typeBuilder, MethodAttributes.PrivateScope, Type.EmptyTypes)); + ilgen.Emit(OpCodes.Ldnull); + ilgen.Emit(OpCodes.Throw); + ilgen.DoEmit(); + } + + // here we loop thru all the interfaces to explicitly implement any methods that we inherit from + // base types that may have a different name from the name in the interface + // (e.g. interface that has an equals() method that should override System.Object.Equals()) + // also deals with interface methods that aren't implemented (generate a stub that throws AbstractMethodError) + // and with methods that aren't public (generate a stub that throws IllegalAccessError) + Dictionary doneSet = new Dictionary(); + TypeWrapper[] interfaces = wrapper.Interfaces; + for (int i = 0; i < interfaces.Length; i++) + { + ImplementInterfaceMethodStubs(doneSet, interfaces[i], false); + } + // if any of our base classes has an incomplete interface implementation we need to look through all + // the base class interfaces to see if we've got an implementation now + TypeWrapper baseTypeWrapper = wrapper.BaseTypeWrapper; + while (baseTypeWrapper.HasIncompleteInterfaceImplementation) + { + for (int i = 0; i < baseTypeWrapper.Interfaces.Length; i++) + { + ImplementInterfaceMethodStubs(doneSet, baseTypeWrapper.Interfaces[i], true); + } + baseTypeWrapper = baseTypeWrapper.BaseTypeWrapper; + } + if (!wrapper.IsAbstract && wrapper.HasUnsupportedAbstractMethods) + { + AddUnsupportedAbstractMethods(); + } + if (!wrapper.GetClassLoader().NoAutomagicSerialization) + { + wrapper.automagicSerializationCtor = Serialization.AddAutomagicSerialization(wrapper, typeBuilder); + } + } + +#if STATIC_COMPILER + // If we're an interface that has public/protected fields, we create an inner class + // to expose these fields to C# (which stubbornly refuses to see fields in interfaces). + AddInterfaceFieldsInterop(fields); + + // If we're a Java 8 interface with static methods, we create an inner class + // to expose these methods to C#. + AddInterfaceMethodsInterop(methods); + + // See if there is any additional metadata + wrapper.EmitMapXmlMetadata(typeBuilder, classFile, fields, methods); + + // if we inherit public members from non-public base classes or have public members with non-public types in their signature, we need access stubs + if (wrapper.IsPublic) + { + AddAccessStubs(); + } + + AddConstantPoolAttributeIfNecessary(classFile, typeBuilder); +#endif // STATIC_COMPILER + + for (int i = 0; i < classFile.Methods.Length; i++) + { + ClassFile.Method m = classFile.Methods[i]; + MethodBuilder mb = (MethodBuilder)methods[i].GetMethod(); + if (mb == null) + { + continue; + } + if (m.Annotations != null) + { + ParameterBuilder returnParameter = null; + foreach (object[] def in m.Annotations) + { + Annotation annotation = Annotation.Load(wrapper, def); + if (annotation != null) + { + annotation.Apply(wrapper.GetClassLoader(), mb, def); + annotation.ApplyReturnValue(wrapper.GetClassLoader(), mb, ref returnParameter, def); + } + } + } + string[] parameterNames; + AddMethodParameterInfo(m, methods[i], mb, out parameterNames); +#if STATIC_COMPILER + if (methods[i].HasCallerID) + { + AttributeHelper.SetEditorBrowsableNever(mb); + EmitCallerIDStub(methods[i], parameterNames); + } + if (m.DllExportName != null && wrapper.classLoader.TryEnableUnmanagedExports()) + { + mb.__AddUnmanagedExport(m.DllExportName, m.DllExportOrdinal); + } +#endif // STATIC_COMPILER + } + + for (int i = 0; i < classFile.Fields.Length; i++) + { + if (classFile.Fields[i].Annotations != null) + { + foreach (object[] def in classFile.Fields[i].Annotations) + { + Annotation annotation = Annotation.Load(wrapper, def); + if (annotation != null) + { + { + DynamicPropertyFieldWrapper prop = fields[i] as DynamicPropertyFieldWrapper; + if (prop != null) + { + annotation.Apply(wrapper.GetClassLoader(), prop.GetPropertyBuilder(), def); + } + else + { + annotation.Apply(wrapper.GetClassLoader(), (FieldBuilder)fields[i].GetField(), def); + } + } + } + } + } + } + + if (classFile.Annotations != null) + { + foreach (object[] def in classFile.Annotations) + { + Annotation annotation = Annotation.Load(wrapper, def); + if (annotation != null) + { + annotation.Apply(wrapper.GetClassLoader(), typeBuilder, def); + } + } + } + +#if STATIC_COMPILER + AddImplementsAttribute(); +#endif + + Type type; + Profiler.Enter("TypeBuilder.CreateType"); + try + { + type = typeBuilder.CreateType(); + if (nestedTypeBuilders != null) + { + ClassLoaderWrapper.LoadClassCritical("ikvm.internal.IntrinsicAtomicReferenceFieldUpdater").Finish(); + ClassLoaderWrapper.LoadClassCritical("ikvm.internal.IntrinsicThreadLocal").Finish(); + foreach (TypeBuilder tb in nestedTypeBuilders) + { + tb.CreateType(); + } + } +#if !STATIC_COMPILER + if (liveObjects != null) + { + typeof(IKVM.Runtime.LiveObjectHolder<>).MakeGenericType(type).GetField("values", BindingFlags.Static | BindingFlags.Public).SetValue(null, liveObjects.ToArray()); + } +#endif + } + finally + { + Profiler.Leave("TypeBuilder.CreateType"); + } +#if !STATIC_COMPILER + // When we're statically compiling we don't need to set the wrapper here, because we've already done so for the typeBuilder earlier. + wrapper.GetClassLoader().SetWrapperForType(type, wrapper); +#endif +#if STATIC_COMPILER + wrapper.FinishGhostStep2(); +#endif + BakedTypeCleanupHack.Process(wrapper); + return type; + } + +#if STATIC_COMPILER + private static void AddConstantPoolAttributeIfNecessary(ClassFile classFile, TypeBuilder typeBuilder) + { + object[] constantPool = null; + bool[] inUse = null; + MarkConstantPoolUsage(classFile, classFile.RuntimeVisibleTypeAnnotations, ref constantPool, ref inUse); + foreach (ClassFile.Method method in classFile.Methods) + { + MarkConstantPoolUsage(classFile, method.RuntimeVisibleTypeAnnotations, ref constantPool, ref inUse); + } + foreach (ClassFile.Field field in classFile.Fields) + { + MarkConstantPoolUsage(classFile, field.RuntimeVisibleTypeAnnotations, ref constantPool, ref inUse); + } + if (constantPool != null) + { + // to save space, we clear out the items that aren't used by the RuntimeVisibleTypeAnnotations and + // use an RLE for the empty slots + AttributeHelper.SetConstantPoolAttribute(typeBuilder, ConstantPoolAttribute.Compress(constantPool, inUse)); + } + } + + private static void MarkConstantPoolUsage(ClassFile classFile, byte[] runtimeVisibleTypeAnnotations, ref object[] constantPool, ref bool[] inUse) + { + if (runtimeVisibleTypeAnnotations != null) + { + if (constantPool == null) + { + constantPool = classFile.GetConstantPool(); + inUse = new bool[constantPool.Length]; + } + try + { + BigEndianBinaryReader br = new BigEndianBinaryReader(runtimeVisibleTypeAnnotations, 0, runtimeVisibleTypeAnnotations.Length); + ushort num_annotations = br.ReadUInt16(); + for (int i = 0; i < num_annotations; i++) + { + MarkConstantPoolUsageForTypeAnnotation(br, inUse); + } + return; + } + catch (ClassFormatError) + { + } + catch (IndexOutOfRangeException) + { + } + // if we fail to parse the annotations (e.g. due to a malformed attribute), we simply keep all the constant pool entries + for (int i = 0; i < inUse.Length; i++) + { + inUse[i] = true; + } + } + } + + private static void MarkConstantPoolUsageForTypeAnnotation(BigEndianBinaryReader br, bool[] inUse) + { + switch (br.ReadByte()) // target_type + { + case 0x00: + case 0x01: + br.ReadByte(); // type_parameter_index + break; + case 0x10: + br.ReadUInt16(); // supertype_index + break; + case 0x11: + case 0x12: + br.ReadByte(); // type_parameter_index + br.ReadByte(); // bound_index + break; + case 0x13: + case 0x14: + case 0x15: + // empty_target + break; + case 0x16: + br.ReadByte(); // formal_parameter_index + break; + case 0x17: + br.ReadUInt16(); // throws_type_index + break; + default: + throw new ClassFormatError(""); + } + byte path_length = br.ReadByte(); + for (int i = 0; i < path_length; i++) + { + br.ReadByte(); // type_path_kind + br.ReadByte(); // type_argument_index + } + MarkConstantPoolUsageForAnnotation(br, inUse); + } + + private static void MarkConstantPoolUsageForAnnotation(BigEndianBinaryReader br, bool[] inUse) + { + ushort type_index = br.ReadUInt16(); + inUse[type_index] = true; + ushort num_components = br.ReadUInt16(); + for (int i = 0; i < num_components; i++) + { + ushort component_name_index = br.ReadUInt16(); + inUse[component_name_index] = true; + MarkConstantPoolUsageForAnnotationComponentValue(br, inUse); + } + } + + private static void MarkConstantPoolUsageForAnnotationComponentValue(BigEndianBinaryReader br, bool[] inUse) + { + switch ((char)br.ReadByte()) // tag + { + case 'B': + case 'C': + case 'D': + case 'F': + case 'I': + case 'J': + case 'S': + case 'Z': + case 's': + case 'c': + inUse[br.ReadUInt16()] = true; + break; + case 'e': + inUse[br.ReadUInt16()] = true; + inUse[br.ReadUInt16()] = true; + break; + case '@': + MarkConstantPoolUsageForAnnotation(br, inUse); + break; + case '[': + ushort num_values = br.ReadUInt16(); + for (int i = 0; i < num_values; i++) + { + MarkConstantPoolUsageForAnnotationComponentValue(br, inUse); + } + break; + default: + throw new ClassFormatError(""); + } + } + + private bool EmitInterlockedCompareAndSet(MethodWrapper method, string fieldName, CodeEmitter ilGenerator) + { + if (method.ReturnType != PrimitiveTypeWrapper.BOOLEAN) + { + return false; + } + TypeWrapper[] parameters = method.GetParameters(); + TypeWrapper target; + int firstValueIndex; + if (method.IsStatic) + { + if (parameters.Length != 3) + { + return false; + } + target = parameters[0]; + firstValueIndex = 1; + } + else + { + if (parameters.Length != 2) + { + return false; + } + target = method.DeclaringType; + firstValueIndex = 0; + } + if (target.IsUnloadable || target.IsPrimitive || target.IsNonPrimitiveValueType || target.IsGhost) + { + return false; + } + TypeWrapper fieldType = parameters[firstValueIndex]; + if (fieldType != parameters[firstValueIndex + 1]) + { + return false; + } + if (fieldType.IsUnloadable || fieldType.IsNonPrimitiveValueType || fieldType.IsGhost) + { + return false; + } + if (fieldType.IsPrimitive && fieldType != PrimitiveTypeWrapper.LONG && fieldType != PrimitiveTypeWrapper.INT) + { + return false; + } + FieldWrapper casField = null; + foreach (FieldWrapper fw in target.GetFields()) + { + if (fw.Name == fieldName) + { + if (casField != null) + { + return false; + } + casField = fw; + } + } + if (casField == null) + { + return false; + } + if (casField.IsStatic) + { + return false; + } + if (casField.FieldTypeWrapper != fieldType) + { + return false; + } + if (casField.IsPropertyAccessor) + { + return false; + } + if (casField.DeclaringType.TypeAsBaseType == typeBuilder.DeclaringType) + { + // allow access to fields in outer class + } + else if (!casField.IsAccessibleFrom(casField.DeclaringType, wrapper, casField.DeclaringType)) + { + return false; + } + casField.Link(); + FieldInfo fi = casField.GetField(); + if (fi == null) + { + return false; + } + ilGenerator.EmitLdarg(0); + ilGenerator.Emit(OpCodes.Ldflda, fi); + ilGenerator.EmitLdarg(2); + ilGenerator.EmitLdarg(1); + if (fieldType == PrimitiveTypeWrapper.LONG) + { + ilGenerator.Emit(OpCodes.Call, InterlockedMethods.CompareExchangeInt64); + } + else if (fieldType == PrimitiveTypeWrapper.INT) + { + ilGenerator.Emit(OpCodes.Call, InterlockedMethods.CompareExchangeInt32); + } + else + { + ilGenerator.Emit(OpCodes.Call, AtomicReferenceFieldUpdaterEmitter.MakeCompareExchange(casField.FieldTypeWrapper.TypeAsSignatureType)); + } + ilGenerator.EmitLdarg(1); + ilGenerator.Emit(OpCodes.Ceq); + ilGenerator.Emit(OpCodes.Ret); + return true; + } +#endif + + private void AddMethodParameterInfo(ClassFile.Method m, MethodWrapper mw, MethodBuilder mb, out string[] parameterNames) + { + parameterNames = null; + ParameterBuilder[] parameterBuilders = null; + if (wrapper.GetClassLoader().EmitDebugInfo +#if STATIC_COMPILER + || (classFile.IsPublic && (m.IsPublic || m.IsProtected)) + || (m.MethodParameters != null && !wrapper.GetClassLoader().NoParameterReflection) +#endif + ) + { + parameterNames = new string[mw.GetParameters().Length]; + GetParameterNamesFromMP(m, parameterNames); +#if STATIC_COMPILER + if (m.MethodParameters == null) +#endif + { + GetParameterNamesFromLVT(m, parameterNames); + GetParameterNamesFromSig(m.Signature, parameterNames); + } +#if STATIC_COMPILER + wrapper.GetParameterNamesFromXml(m.Name, m.Signature, parameterNames); +#endif + parameterBuilders = GetParameterBuilders(mb, parameterNames.Length, parameterNames); + } +#if STATIC_COMPILER + if ((m.Modifiers & Modifiers.VarArgs) != 0 && !mw.HasCallerID) + { + if (parameterBuilders == null) + { + parameterBuilders = GetParameterBuilders(mb, mw.GetParameters().Length, null); + } + if (parameterBuilders.Length > 0) + { + AttributeHelper.SetParamArrayAttribute(parameterBuilders[parameterBuilders.Length - 1]); + } + } + wrapper.AddXmlMapParameterAttributes(mb, classFile.Name, m.Name, m.Signature, ref parameterBuilders); +#endif + if (m.ParameterAnnotations != null) + { + if (parameterBuilders == null) + { + parameterBuilders = GetParameterBuilders(mb, mw.GetParameters().Length, null); + } + object[][] defs = m.ParameterAnnotations; + for (int j = 0; j < defs.Length; j++) + { + foreach (object[] def in defs[j]) + { + Annotation annotation = Annotation.Load(wrapper, def); + if (annotation != null) + { + annotation.Apply(wrapper.GetClassLoader(), parameterBuilders[j], def); + } + } + } + } + } + +#if STATIC_COMPILER + private void AddImplementsAttribute() + { + TypeWrapper[] interfaces = wrapper.Interfaces; + if (wrapper.BaseTypeWrapper == CoreClasses.java.lang.Object.Wrapper) + { + // We special case classes extending java.lang.Object to optimize the metadata encoding + // for anonymous classes that implement an interface. + Type[] actualInterfaces = typeBuilder.GetInterfaces(); + if (actualInterfaces.Length == 0) + { + return; + } + else if (actualInterfaces.Length == 1 + && interfaces.Length == 1 + && !interfaces[0].IsRemapped + && interfaces[0].TypeAsBaseType == actualInterfaces[0]) + { + // We extend java.lang.Object and implement only a single (non-remapped) interface, + // in this case we can omit the ImplementAttribute since the runtime will be able + // to reliable reproduce the "list" of implemented interfaces. + return; + } + } + else if (interfaces.Length == 0) + { + return; + } + AttributeHelper.SetImplementsAttribute(typeBuilder, interfaces); + } + + private TypeBuilder DefineNestedInteropType(string name) + { + CompilerClassLoader ccl = wrapper.classLoader; + while (!ccl.ReserveName(classFile.Name + "$" + name)) + { + name += "_"; + } + TypeBuilder tb = typeBuilder.DefineNestedType(name, TypeAttributes.Class | TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.Abstract); + RegisterNestedTypeBuilder(tb); + AttributeHelper.HideFromJava(tb); + return tb; + } + + private void AddInterfaceFieldsInterop(FieldWrapper[] fields) + { + if (classFile.IsInterface && classFile.IsPublic && !wrapper.IsGhost && classFile.Fields.Length > 0 && wrapper.classLoader.WorkaroundInterfaceFields) + { + TypeBuilder tbFields = DefineNestedInteropType(NestedTypeName.Fields); + CodeEmitter ilgenClinit = null; + for (int i = 0; i < classFile.Fields.Length; i++) + { + ClassFile.Field f = classFile.Fields[i]; + if (f.ConstantValue != null) + { + FieldAttributes attribs = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal; + FieldBuilder fb = tbFields.DefineField(f.Name, fields[i].FieldTypeWrapper.TypeAsSignatureType, attribs); + fb.SetConstant(f.ConstantValue); + } + else + { + FieldAttributes attribs = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.InitOnly; + FieldBuilder fb = tbFields.DefineField(f.Name, fields[i].FieldTypeWrapper.TypeAsPublicSignatureType, attribs); + if (ilgenClinit == null) + { + ilgenClinit = CodeEmitter.Create(ReflectUtil.DefineTypeInitializer(tbFields, wrapper.classLoader)); + } + wrapper.GetFieldWrapper(f.Name, f.Signature).EmitGet(ilgenClinit); + ilgenClinit.Emit(OpCodes.Stsfld, fb); + } + } + if (ilgenClinit != null) + { + ilgenClinit.Emit(OpCodes.Ret); + ilgenClinit.DoEmit(); + } + } + } + + private void AddInterfaceMethodsInterop(MethodWrapper[] methods) + { + if (classFile.IsInterface && classFile.IsPublic && classFile.MajorVersion >= 52 && !wrapper.IsGhost && methods.Length > 0 && wrapper.classLoader.WorkaroundInterfaceStaticMethods) + { + TypeBuilder tbMethods = null; + foreach (MethodWrapper mw in methods) + { + if (mw.IsStatic && mw.IsPublic && mw.Name != StringConstants.CLINIT && ParametersAreAccessible(mw)) + { + if (tbMethods == null) + { + tbMethods = DefineNestedInteropType(NestedTypeName.Methods); + } + MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(wrapper.GetClassLoader().GetTypeWrapperFactory(), tbMethods, mw.Name, MethodAttributes.Public | MethodAttributes.Static, null, true); + CodeEmitter ilgen = CodeEmitter.Create(mb); + TypeWrapper[] parameters = mw.GetParameters(); + for (int i = 0; i < parameters.Length; i++) + { + ilgen.EmitLdarg(i); + if (!parameters[i].IsUnloadable && !parameters[i].IsPublic) + { + parameters[i].EmitCheckcast(ilgen); + } + } + mw.EmitCall(ilgen); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + } + } + } + + private void CreateDefaultMethodInterop(ref TypeBuilder tbDefaultMethods, MethodBuilder defaultMethod, MethodWrapper mw) + { + if (!ParametersAreAccessible(mw)) + { + return; + } + if (tbDefaultMethods == null) + { + tbDefaultMethods = DefineNestedInteropType(NestedTypeName.DefaultMethods); + } + MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(wrapper.GetClassLoader().GetTypeWrapperFactory(), tbDefaultMethods, mw.Name, MethodAttributes.Public | MethodAttributes.Static, wrapper.TypeAsSignatureType, true); + CodeEmitter ilgen = CodeEmitter.Create(mb); + if (wrapper.IsGhost) + { + ilgen.EmitLdarga(0); + ilgen.Emit(OpCodes.Ldfld, wrapper.GhostRefField); + ilgen.EmitNullCheck(); + ilgen.EmitLdarga(0); + } + else + { + ilgen.EmitLdarg(0); + ilgen.Emit(OpCodes.Dup); + ilgen.EmitNullCheck(); + } + TypeWrapper[] parameters = mw.GetParameters(); + for (int i = 0; i < parameters.Length; i++) + { + ilgen.EmitLdarg(i + 1); + if (!parameters[i].IsUnloadable && !parameters[i].IsPublic) + { + parameters[i].EmitCheckcast(ilgen); + } + } + ilgen.Emit(OpCodes.Call, defaultMethod); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } +#endif + + private void AddInheritedDefaultInterfaceMethods(MethodWrapper[] methods) + { + // look at the miranda methods to see if we inherit any default interface methods + for (int i = classFile.Methods.Length; i < methods.Length; i++) + { + if (methods[i].IsMirandaMethod) + { + MirandaMethodWrapper mmw = (MirandaMethodWrapper)methods[i]; + if (mmw.Error == null && !mmw.BaseMethod.IsAbstract) + { + // we inherited a default interface method, so we need to forward the miranda method to the default method + MethodBuilder mb = (MethodBuilder)mmw.GetMethod(); + if (classFile.IsInterface) + { + // if we're an interface with a default miranda method, we need to create a new default method that forwards to the original + mb = methods[i].GetDefineMethodHelper().DefineMethod(wrapper.GetClassLoader().GetTypeWrapperFactory(), + typeBuilder, NamePrefix.DefaultMethod + mb.Name, MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, typeBuilder, false); + } + EmitCallDefaultInterfaceMethod(mb, mmw.BaseMethod); + } + } + } + } + + internal static void EmitCallDefaultInterfaceMethod(MethodBuilder mb, MethodWrapper defaultMethod) + { + CodeEmitter ilgen = CodeEmitter.Create(mb); + if (defaultMethod.DeclaringType.IsGhost) + { + CodeEmitterLocal local = ilgen.DeclareLocal(defaultMethod.DeclaringType.TypeAsSignatureType); + ilgen.Emit(OpCodes.Ldloca, local); + ilgen.EmitLdarg(0); + ilgen.Emit(OpCodes.Stfld, defaultMethod.DeclaringType.GhostRefField); + ilgen.Emit(OpCodes.Ldloca, local); + } + else + { + ilgen.EmitLdarg(0); + } + for (int j = 0, count = defaultMethod.GetParameters().Length; j < count; j++) + { + ilgen.EmitLdarg(j + 1); + } + ilgen.Emit(OpCodes.Call, DefaultInterfaceMethodWrapper.GetImpl(defaultMethod)); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + +#if STATIC_COMPILER + private void AddAccessStubs() + { + /* + * There are two types of access stubs: + * + * Type 1 These are required when a public class extends a non-public class. + * In that case we need access stubs for all public and protected members + * of the non-public base classes. + * + * Type 2 When a public class exposes a member that contains a non-public type in + * its signature, we need an access stub for that member (where we convert + * the non-public type in the signature to the first public base type). + * Additionally, when a public or protected final field is compiled + * without -strictfinalfieldsemantics, a the field will be wrapper with a + * read-only property. + * + * Note that type 1 access stubs may also need the type 2 signature type widening + * if the signature contains non-public types. + * + * Type 1 access stubs are always required, because the JVM allow access to these + * members via the derived class while the CLR doesn't. Historically, we've exposed + * these access stubs in such a way that they are also consumable from other .NET + * languages (when feasible), so we'll continue to do that for back compat. + * + * Type 2 access stubs are only required by the CLR when running on CLR v4 and the + * caller assembly is security transparent code (level 2). We also want the access + * stubs to allow other .NET languages (e.g. C#) to consume broken APIs that + * (accidentally) expose these members. + */ + AddType2FieldAccessStubs(); + AddType1FieldAccessStubs(wrapper); + if (!wrapper.IsInterface) + { + int id = 0; + AddType2MethodAccessStubs(ref id); + AddType1MethodAccessStubs(ref id); + } + } + + private void AddType1FieldAccessStubs(TypeWrapper tw) + { + do + { + if (!tw.IsPublic) + { + foreach (FieldWrapper fw in tw.GetFields()) + { + if ((fw.IsPublic || (fw.IsProtected && !wrapper.IsFinal)) + && wrapper.GetFieldWrapper(fw.Name, fw.Signature) == fw) + { + GenerateAccessStub(fw, true); + } + } + } + foreach (TypeWrapper iface in tw.Interfaces) + { + AddType1FieldAccessStubs(iface); + } + tw = tw.BaseTypeWrapper; + } while (tw != null && !tw.IsPublic); + } + + private void AddType2FieldAccessStubs() + { + foreach (FieldWrapper fw in wrapper.GetFields()) + { + if (wrapper.NeedsType2AccessStub(fw)) + { + GenerateAccessStub(fw, false); + } + } + } + + private void GenerateAccessStub(FieldWrapper fw, bool type1) + { + if (fw is ConstantFieldWrapper) + { + // constants cannot have a type 2 access stub, because constant types are always public + Debug.Assert(type1); + + FieldAttributes attribs = fw.IsPublic ? FieldAttributes.Public : FieldAttributes.FamORAssem; + attribs |= FieldAttributes.Static | FieldAttributes.Literal; + // we attach the AccessStub custom modifier because the C# compiler prefers fields without custom modifiers + // so if this class defines a field with the same name, that will be preferred over this one by the C# compiler + FieldBuilder fb = typeBuilder.DefineField(fw.Name, fw.FieldTypeWrapper.TypeAsSignatureType, null, new Type[] { JVM.LoadType(typeof(IKVM.Attributes.AccessStub)) }, attribs); + AttributeHelper.HideFromReflection(fb); + fb.SetConstant(((ConstantFieldWrapper)fw).GetConstantValue()); + } + else + { + Type propType = fw.FieldTypeWrapper.TypeAsPublicSignatureType; + Type[] modopt = wrapper.GetModOpt(fw.FieldTypeWrapper, true); + PropertyBuilder pb = typeBuilder.DefineProperty(fw.Name, PropertyAttributes.None, propType, null, modopt, Type.EmptyTypes, null, null); + if (type1) + { + AttributeHelper.HideFromReflection(pb); + } + else + { + AttributeHelper.SetModifiers(pb, fw.Modifiers, fw.IsInternal); + } + MethodAttributes attribs = fw.IsPublic ? MethodAttributes.Public : MethodAttributes.FamORAssem; + attribs |= MethodAttributes.HideBySig | MethodAttributes.SpecialName; + if (fw.IsStatic) + { + attribs |= MethodAttributes.Static; + } + // we append the IKVM.Attributes.AccessStub type to the modopt array for use in the property accessor method signature + // to make sure they never conflict with any user defined methhods + Type[] modopt2 = ArrayUtil.Concat(modopt, JVM.LoadType(typeof(IKVM.Attributes.AccessStub))); + MethodBuilder getter = typeBuilder.DefineMethod("get_" + fw.Name, attribs, CallingConventions.Standard, propType, null, modopt2, Type.EmptyTypes, null, null); + AttributeHelper.HideFromJava(getter); + pb.SetGetMethod(getter); + CodeEmitter ilgen = CodeEmitter.Create(getter); + if (!fw.IsStatic) + { + ilgen.Emit(OpCodes.Ldarg_0); + } + fw.EmitGet(ilgen); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + if (!fw.IsFinal || (!fw.IsStatic && !type1)) + { + if (fw.IsFinal) + { + // we need to generate a (private) setter for final fields for reflection and serialization + attribs &= ~MethodAttributes.MemberAccessMask; + attribs |= MethodAttributes.Private; + } + MethodBuilder setter = typeBuilder.DefineMethod("set_" + fw.Name, attribs, CallingConventions.Standard, null, null, null, new Type[] { propType }, null, new Type[][] { modopt2 }); + AttributeHelper.HideFromJava(setter); + pb.SetSetMethod(setter); + ilgen = CodeEmitter.Create(setter); + ilgen.Emit(OpCodes.Ldarg_0); + if (!fw.IsStatic) + { + ilgen.Emit(OpCodes.Ldarg_1); + } + // we don't do a DynamicCast if fw.FieldTypeWrapper is unloadable, because for normal unloadable fields we don't enfore the type either + if (propType != fw.FieldTypeWrapper.TypeAsSignatureType) + { + ilgen.Emit(OpCodes.Castclass, fw.FieldTypeWrapper.TypeAsSignatureType); + } + fw.EmitSet(ilgen); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + } + } + + private void AddType1MethodAccessStubs(ref int id) + { + for (TypeWrapper tw = wrapper.BaseTypeWrapper; tw != null && !tw.IsPublic; tw = tw.BaseTypeWrapper) + { + foreach (MethodWrapper mw in tw.GetMethods()) + { + if ((mw.IsPublic || (mw.IsProtected && !wrapper.IsFinal)) + && (!mw.IsAbstract || wrapper.IsAbstract) + && mw.Name != StringConstants.INIT + && wrapper.GetMethodWrapper(mw.Name, mw.Signature, true) == mw + && ParametersAreAccessible(mw)) + { + GenerateAccessStub(id, mw, true, true); + if (!mw.IsStatic && !mw.IsFinal && !mw.IsAbstract && !wrapper.IsFinal) + { + GenerateAccessStub(id, mw, false, true); + } + id++; + } + } + } + } + + private void AddType2MethodAccessStubs(ref int id) + { + foreach (MethodWrapper mw in wrapper.GetMethods()) + { + if (mw.HasNonPublicTypeInSignature + && (mw.IsPublic || (mw.IsProtected && !wrapper.IsFinal)) + && ParametersAreAccessible(mw)) + { + GenerateAccessStub(id, mw, true, false); + if (!mw.IsStatic && !mw.IsFinal && !mw.IsAbstract && mw.Name != StringConstants.INIT && !wrapper.IsFinal) + { + GenerateAccessStub(id, mw, false, false); + } + id++; + } + } + } + + private void GenerateAccessStub(int id, MethodWrapper mw, bool virt, bool type1) + { + Debug.Assert(!mw.HasCallerID); + MethodAttributes stubattribs = mw.IsPublic && virt ? MethodAttributes.Public : MethodAttributes.FamORAssem; + stubattribs |= MethodAttributes.HideBySig; + if (mw.IsStatic) + { + stubattribs |= MethodAttributes.Static; + } + TypeWrapper[] parameters = mw.GetParameters(); + Type[] realParameterTypes = new Type[parameters.Length]; + Type[] parameterTypes = new Type[parameters.Length]; + Type[][] modopt = new Type[parameters.Length][]; + for (int i = 0; i < parameters.Length; i++) + { + realParameterTypes[i] = parameters[i].TypeAsSignatureType; + parameterTypes[i] = parameters[i].TypeAsPublicSignatureType; + modopt[i] = wrapper.GetModOpt(parameters[i], true); + } + Type returnType = mw.ReturnType.TypeAsPublicSignatureType; + Type[] modoptReturnType = ArrayUtil.Concat(wrapper.GetModOpt(mw.ReturnType, true), JVM.LoadType(typeof(IKVM.Attributes.AccessStub))); + string name; + if (mw.Name == StringConstants.INIT) + { + name = ConstructorInfo.ConstructorName; + stubattribs |= MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; + } + else + { + name = virt + ? (mw.Modifiers & Modifiers.Bridge) == 0 ? mw.Name : NamePrefix.Bridge + mw.Name + : NamePrefix.NonVirtual + id; + } + MethodBuilder mb = typeBuilder.DefineMethod(name, stubattribs, CallingConventions.Standard, returnType, null, modoptReturnType, parameterTypes, null, modopt); + if (virt && type1) + { + AttributeHelper.HideFromReflection(mb); + AttributeHelper.SetNameSig(mb, NamePrefix.AccessStub + id + "|" + mw.Name, mw.Signature); + } + else + { + AttributeHelper.HideFromJava(mb); + if (!type1) + { + AttributeHelper.SetNameSig(mb, mw.Name, mw.Signature); + } + } + CodeEmitter ilgen = CodeEmitter.Create(mb); + int argpos = 0; + if (!mw.IsStatic) + { + ilgen.EmitLdarg(argpos++); + } + for (int i = 0; i < parameterTypes.Length; i++) + { + ilgen.EmitLdarg(argpos++); + // we don't need to do a DynamicCast if for unloadables, because the method itself will already do that + if (parameterTypes[i] != realParameterTypes[i]) + { + ilgen.Emit(OpCodes.Castclass, realParameterTypes[i]); + } + } + if (mw.IsStatic || !virt || mw.Name == StringConstants.INIT) + { + mw.EmitCall(ilgen); + } + else + { + mw.EmitCallvirt(ilgen); + } + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + + private bool ParametersAreAccessible(MethodWrapper mw) + { + foreach (TypeWrapper tw in mw.GetParameters()) + { + if (!tw.IsAccessibleFrom(wrapper)) + { + return false; + } + } + return true; + } +#endif // STATIC_COMPILER + + private void ImplementInterfaceMethodStubs(Dictionary doneSet, TypeWrapper interfaceTypeWrapper, bool baseClassInterface) + { + Debug.Assert(interfaceTypeWrapper.IsInterface); + + // make sure we don't do the same method twice + if (doneSet.ContainsKey(interfaceTypeWrapper)) + { + return; + } + doneSet.Add(interfaceTypeWrapper, interfaceTypeWrapper); + foreach (MethodWrapper method in interfaceTypeWrapper.GetMethods()) + { + if (!method.IsStatic && method.IsPublic && !method.IsDynamicOnly) + { + ImplementInterfaceMethodStubImpl(method, baseClassInterface); + } + } + TypeWrapper[] interfaces = interfaceTypeWrapper.Interfaces; + for (int i = 0; i < interfaces.Length; i++) + { + ImplementInterfaceMethodStubs(doneSet, interfaces[i], baseClassInterface); + } + } + + private void ImplementInterfaceMethodStubImpl(MethodWrapper ifmethod, bool baseClassInterface) + { + // we're mangling the name to prevent subclasses from accidentally overriding this method and to + // prevent clashes with overloaded method stubs that are erased to the same signature (e.g. unloadable types and ghost arrays) + // HACK the signature and name are the wrong way around to work around a C++/CLI bug (apparantely it looks looks at the last n + // characters of the method name, or something bizarre like that) + // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=234167 + string mangledName = ifmethod.DeclaringType.Name + "/" + ifmethod.Signature + ifmethod.Name; + MethodWrapper mce = null; + TypeWrapper lookup = wrapper; + while (lookup != null) + { + mce = lookup.GetMethodWrapper(ifmethod.Name, ifmethod.Signature, true); + if (mce == null || !mce.IsStatic) + { + break; + } + lookup = mce.DeclaringType.BaseTypeWrapper; + } + if (mce != null) + { + Debug.Assert(!mce.HasCallerID); + if (mce.DeclaringType != wrapper) + { + // check the loader constraints + bool error = false; + if (mce.ReturnType != ifmethod.ReturnType && !mce.ReturnType.IsUnloadable && !ifmethod.ReturnType.IsUnloadable) + { + error = true; + } + TypeWrapper[] mceparams = mce.GetParameters(); + TypeWrapper[] ifparams = ifmethod.GetParameters(); + for (int i = 0; i < mceparams.Length; i++) + { + if (mceparams[i] != ifparams[i] && !mceparams[i].IsUnloadable && !ifparams[i].IsUnloadable) + { + error = true; + break; + } + } + if (error) + { + MethodBuilder mb = DefineInterfaceStubMethod(mangledName, ifmethod); + AttributeHelper.HideFromJava(mb); + CodeEmitter ilgen = CodeEmitter.Create(mb); + ilgen.EmitThrow("java.lang.LinkageError", wrapper.Name + "." + ifmethod.Name + ifmethod.Signature); + ilgen.DoEmit(); + typeBuilder.DefineMethodOverride(mb, (MethodInfo)ifmethod.GetMethod()); + return; + } + } + if (!mce.IsPublic && !mce.IsInternal) + { + // NOTE according to the ECMA spec it isn't legal for a privatescope method to be virtual, but this works and + // it makes sense, so I hope the spec is wrong + // UPDATE unfortunately, according to Serge Lidin the spec is correct, and it is not allowed to have virtual privatescope + // methods. Sigh! So I have to use private methods and mangle the name + MethodBuilder mb = DefineInterfaceStubMethod(NamePrefix.Incomplete + mangledName, ifmethod); + AttributeHelper.HideFromJava(mb); + CodeEmitter ilgen = CodeEmitter.Create(mb); + ilgen.EmitThrow("java.lang.IllegalAccessError", wrapper.Name + "." + ifmethod.Name + ifmethod.Signature); + ilgen.DoEmit(); + typeBuilder.DefineMethodOverride(mb, (MethodInfo)ifmethod.GetMethod()); + wrapper.SetHasIncompleteInterfaceImplementation(); + } + else if (mce.GetMethod() == null || mce.RealName != ifmethod.RealName || mce.IsInternal || !ReflectUtil.IsSameAssembly(mce.DeclaringType.TypeAsTBD, typeBuilder) || CheckRequireOverrideStub(mce, ifmethod)) + { + // NOTE methods inherited from base classes in a different assembly do *not* automatically implement + // interface methods, so we have to generate a stub here that doesn't do anything but call the base + // implementation + wrapper.GenerateOverrideStub(typeBuilder, ifmethod, null, mce); + } + else if (baseClassInterface && mce.DeclaringType == wrapper) + { + typeBuilder.DefineMethodOverride((MethodInfo)mce.GetMethod(), (MethodInfo)ifmethod.GetMethod()); + } + } + else + { + if (!wrapper.IsAbstract || (!baseClassInterface && wrapper.GetMethodWrapper(ifmethod.Name, ifmethod.Signature, false) != null)) + { + // the type doesn't implement the interface method and isn't abstract either. The JVM allows this, but the CLR doesn't, + // so we have to create a stub method that throws an AbstractMethodError + MethodBuilder mb = DefineInterfaceStubMethod(NamePrefix.Incomplete + mangledName, ifmethod); + AttributeHelper.HideFromJava(mb); + CodeEmitter ilgen = CodeEmitter.Create(mb); + ilgen.EmitThrow("java.lang.AbstractMethodError", wrapper.Name + "." + ifmethod.Name + ifmethod.Signature); + ilgen.DoEmit(); + typeBuilder.DefineMethodOverride(mb, (MethodInfo)ifmethod.GetMethod()); + wrapper.SetHasIncompleteInterfaceImplementation(); + wrapper.EmitLevel4Warning(HardError.AbstractMethodError, wrapper.Name + "." + ifmethod.Name + ifmethod.Signature); + } + } + } + + private MethodBuilder DefineInterfaceStubMethod(string name, MethodWrapper mw) + { + return mw.GetDefineMethodHelper().DefineMethod(wrapper, typeBuilder, name, MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final); + } + + private static class BakedTypeCleanupHack + { +#if NET_4_0 || STATIC_COMPILER + internal static void Process(DynamicTypeWrapper wrapper) { } +#else + private static readonly FieldInfo m_methodBuilder = typeof(ConstructorBuilder).GetField("m_methodBuilder", BindingFlags.Instance | BindingFlags.NonPublic); + private static readonly FieldInfo[] methodBuilderFields = GetFieldList(typeof(MethodBuilder), new string[] + { + "m_ilGenerator", + "m_ubBody", + "m_RVAFixups", + "m_mdMethodFixups", + "m_localSignature", + "m_localSymInfo", + "m_exceptions", + "m_parameterTypes", + "m_retParam", + "m_returnType", + "m_signature" + }); + private static readonly FieldInfo[] fieldBuilderFields = GetFieldList(typeof(FieldBuilder), new string[] + { + "m_data", + "m_fieldType", + }); + + private static bool IsSupportedVersion + { + get + { + return Environment.Version.Major == 2 && Environment.Version.Minor == 0 && Environment.Version.Build == 50727 && Environment.Version.Revision == 4016; + } + } + + [SecurityCritical] + [SecurityTreatAsSafe] + private static FieldInfo[] GetFieldList(Type type, string[] list) + { + if (JVM.SafeGetEnvironmentVariable("IKVM_DISABLE_TYPEBUILDER_HACK") != null || !IsSupportedVersion) + { + return null; + } + if (!SecurityManager.IsGranted(new SecurityPermission(SecurityPermissionFlag.Assertion)) || + !SecurityManager.IsGranted(new ReflectionPermission(ReflectionPermissionFlag.MemberAccess))) + { + return null; + } + FieldInfo[] fields = new FieldInfo[list.Length]; + for (int i = 0; i < list.Length; i++) + { + fields[i] = type.GetField(list[i], BindingFlags.Instance | BindingFlags.NonPublic); + if (fields[i] == null) + { + return null; + } + } + return fields; + } + + [SecurityCritical] + [SecurityTreatAsSafe] + internal static void Process(DynamicTypeWrapper wrapper) + { + if (m_methodBuilder != null && methodBuilderFields != null && fieldBuilderFields != null) + { + foreach (MethodWrapper mw in wrapper.GetMethods()) + { + MethodBuilder mb = mw.GetMethod() as MethodBuilder; + if (mb == null) + { + ConstructorBuilder cb = mw.GetMethod() as ConstructorBuilder; + if (cb != null) + { + new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert(); + mb = (MethodBuilder)m_methodBuilder.GetValue(cb); + CodeAccessPermission.RevertAssert(); + } + } + if (mb != null) + { + new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert(); + foreach (FieldInfo fi in methodBuilderFields) + { + fi.SetValue(mb, null); + } + CodeAccessPermission.RevertAssert(); + } + } + foreach (FieldWrapper fw in wrapper.GetFields()) + { + FieldBuilder fb = fw.GetField() as FieldBuilder; + if (fb != null) + { + new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert(); + foreach (FieldInfo fi in fieldBuilderFields) + { + fi.SetValue(fb, null); + } + CodeAccessPermission.RevertAssert(); + } + } + } + } +#endif // NET_4_0 + } + +#if !STATIC_COMPILER + internal static class JniProxyBuilder + { + private readonly static ModuleBuilder mod; + private static int count; + + static JniProxyBuilder() + { + mod = DynamicClassLoader.CreateJniProxyModuleBuilder(); + CustomAttributeBuilder cab = new CustomAttributeBuilder(JVM.LoadType(typeof(JavaModuleAttribute)).GetConstructor(Type.EmptyTypes), new object[0]); + mod.SetCustomAttribute(cab); + } + + internal static void Generate(DynamicTypeWrapper.FinishContext context, CodeEmitter ilGenerator, DynamicTypeWrapper wrapper, MethodWrapper mw, TypeBuilder typeBuilder, ClassFile classFile, ClassFile.Method m, TypeWrapper[] args) + { + TypeBuilder tb = mod.DefineType("__" + System.Threading.Interlocked.Increment(ref count), TypeAttributes.Public | TypeAttributes.Class); + int instance = m.IsStatic ? 0 : 1; + Type[] argTypes = new Type[args.Length + instance + 1]; + if (instance != 0) + { + argTypes[0] = typeof(object); + } + for (int i = 0; i < args.Length; i++) + { + // NOTE we take a shortcut here by assuming that all "special" types (i.e. ghost or value types) + // are public and so we can get away with replacing all other types with object. + argTypes[i + instance] = !args[i].IsUnloadable && (args[i].IsPrimitive || args[i].IsGhost || args[i].IsNonPrimitiveValueType) ? args[i].TypeAsSignatureType : typeof(object); + } + argTypes[argTypes.Length - 1] = CoreClasses.ikvm.@internal.CallerID.Wrapper.TypeAsSignatureType; + Type retType = !mw.ReturnType.IsUnloadable && (mw.ReturnType.IsPrimitive || mw.ReturnType.IsGhost || mw.ReturnType.IsNonPrimitiveValueType) ? mw.ReturnType.TypeAsSignatureType : typeof(object); + MethodBuilder mb = tb.DefineMethod("method", MethodAttributes.Public | MethodAttributes.Static, retType, argTypes); + AttributeHelper.HideFromJava(mb); + CodeEmitter ilgen = CodeEmitter.Create(mb); + JniBuilder.Generate(context, ilgen, wrapper, mw, tb, classFile, m, args, true); + ilgen.DoEmit(); + tb.CreateType(); + for (int i = 0; i < argTypes.Length - 1; i++) + { + ilGenerator.EmitLdarg(i); + } + context.EmitCallerID(ilGenerator, m.IsLambdaFormCompiled); + ilGenerator.Emit(OpCodes.Call, mb); + if (!mw.ReturnType.IsUnloadable && !mw.ReturnType.IsPrimitive && !mw.ReturnType.IsGhost && !mw.ReturnType.IsNonPrimitiveValueType) + { + ilGenerator.Emit(OpCodes.Castclass, mw.ReturnType.TypeAsSignatureType); + } + ilGenerator.Emit(OpCodes.Ret); + } + } +#endif // !STATIC_COMPILER + + private static class JniBuilder + { +#if STATIC_COMPILER + private static readonly Type localRefStructType = StaticCompiler.GetRuntimeType("IKVM.Runtime.JNI+Frame"); +#elif FIRST_PASS + private static readonly Type localRefStructType = null; +#else + private static readonly Type localRefStructType = JVM.LoadType(typeof(IKVM.Runtime.JNI.Frame)); +#endif + private static readonly MethodInfo jniFuncPtrMethod = localRefStructType.GetMethod("GetFuncPtr"); + private static readonly MethodInfo enterLocalRefStruct = localRefStructType.GetMethod("Enter"); + private static readonly MethodInfo leaveLocalRefStruct = localRefStructType.GetMethod("Leave"); + private static readonly MethodInfo makeLocalRef = localRefStructType.GetMethod("MakeLocalRef"); + private static readonly MethodInfo unwrapLocalRef = localRefStructType.GetMethod("UnwrapLocalRef"); + private static readonly MethodInfo writeLine = JVM.Import(typeof(Console)).GetMethod("WriteLine", new Type[] { Types.Object }); + private static readonly MethodInfo monitorEnter = JVM.Import(typeof(System.Threading.Monitor)).GetMethod("Enter", new Type[] { Types.Object }); + private static readonly MethodInfo monitorExit = JVM.Import(typeof(System.Threading.Monitor)).GetMethod("Exit", new Type[] { Types.Object }); + + internal static void Generate(DynamicTypeWrapper.FinishContext context, CodeEmitter ilGenerator, DynamicTypeWrapper wrapper, MethodWrapper mw, TypeBuilder typeBuilder, ClassFile classFile, ClassFile.Method m, TypeWrapper[] args, bool thruProxy) + { + CodeEmitterLocal syncObject = null; + if (m.IsSynchronized && m.IsStatic) + { + wrapper.EmitClassLiteral(ilGenerator); + ilGenerator.Emit(OpCodes.Dup); + syncObject = ilGenerator.DeclareLocal(Types.Object); + ilGenerator.Emit(OpCodes.Stloc, syncObject); + ilGenerator.Emit(OpCodes.Call, monitorEnter); + ilGenerator.BeginExceptionBlock(); + } + string sig = m.Signature.Replace('.', '/'); + // TODO use/unify JNI.METHOD_PTR_FIELD_PREFIX + FieldBuilder methodPtr = typeBuilder.DefineField("__" + m.Name + sig, Types.IntPtr, FieldAttributes.Static | FieldAttributes.PrivateScope); + CodeEmitterLocal localRefStruct = ilGenerator.DeclareLocal(localRefStructType); + ilGenerator.Emit(OpCodes.Ldloca, localRefStruct); + ilGenerator.Emit(OpCodes.Initobj, localRefStructType); + ilGenerator.Emit(OpCodes.Ldsfld, methodPtr); + CodeEmitterLabel oklabel = ilGenerator.DefineLabel(); + ilGenerator.EmitBrtrue(oklabel); + if (thruProxy) + { + ilGenerator.EmitLdarg(args.Length + (mw.IsStatic ? 0 : 1)); + } + else + { + context.EmitCallerID(ilGenerator, m.IsLambdaFormCompiled); + } + ilGenerator.Emit(OpCodes.Ldstr, classFile.Name.Replace('.', '/')); + ilGenerator.Emit(OpCodes.Ldstr, m.Name); + ilGenerator.Emit(OpCodes.Ldstr, sig); + ilGenerator.Emit(OpCodes.Call, jniFuncPtrMethod); + ilGenerator.Emit(OpCodes.Stsfld, methodPtr); + ilGenerator.MarkLabel(oklabel); + ilGenerator.Emit(OpCodes.Ldloca, localRefStruct); + if (thruProxy) + { + ilGenerator.EmitLdarg(args.Length + (mw.IsStatic ? 0 : 1)); + } + else + { + context.EmitCallerID(ilGenerator, m.IsLambdaFormCompiled); + } + ilGenerator.Emit(OpCodes.Call, enterLocalRefStruct); + CodeEmitterLocal jnienv = ilGenerator.DeclareLocal(Types.IntPtr); + ilGenerator.Emit(OpCodes.Stloc, jnienv); + ilGenerator.BeginExceptionBlock(); + TypeWrapper retTypeWrapper = mw.ReturnType; + if (retTypeWrapper.IsUnloadable || !retTypeWrapper.IsPrimitive) + { + // this one is for use after we return from "calli" + ilGenerator.Emit(OpCodes.Ldloca, localRefStruct); + } + ilGenerator.Emit(OpCodes.Ldloc, jnienv); + Type[] modargs = new Type[args.Length + 2]; + modargs[0] = Types.IntPtr; + modargs[1] = Types.IntPtr; + for (int i = 0; i < args.Length; i++) + { + modargs[i + 2] = args[i].TypeAsSignatureType; + } + int add = 0; + if (!m.IsStatic) + { + ilGenerator.Emit(OpCodes.Ldloca, localRefStruct); + ilGenerator.Emit(OpCodes.Ldarg_0); + ilGenerator.Emit(OpCodes.Call, makeLocalRef); + add = 1; + } + else + { + ilGenerator.Emit(OpCodes.Ldloca, localRefStruct); + wrapper.EmitClassLiteral(ilGenerator); + ilGenerator.Emit(OpCodes.Call, makeLocalRef); + } + for (int j = 0; j < args.Length; j++) + { + if (args[j].IsUnloadable || !args[j].IsPrimitive) + { + ilGenerator.Emit(OpCodes.Ldloca, localRefStruct); + if (!args[j].IsUnloadable && args[j].IsNonPrimitiveValueType) + { + ilGenerator.EmitLdarg(j + add); + args[j].EmitBox(ilGenerator); + } + else if (!args[j].IsUnloadable && args[j].IsGhost) + { + ilGenerator.EmitLdarga(j + add); + ilGenerator.Emit(OpCodes.Ldfld, args[j].GhostRefField); + } + else + { + ilGenerator.EmitLdarg(j + add); + } + ilGenerator.Emit(OpCodes.Call, makeLocalRef); + modargs[j + 2] = Types.IntPtr; + } + else + { + ilGenerator.EmitLdarg(j + add); + } + } + ilGenerator.Emit(OpCodes.Ldsfld, methodPtr); + Type realRetType; + if (retTypeWrapper == PrimitiveTypeWrapper.BOOLEAN) + { + realRetType = Types.Byte; + } + else if (retTypeWrapper.IsPrimitive) + { + realRetType = retTypeWrapper.TypeAsSignatureType; + } + else + { + realRetType = Types.IntPtr; + } + ilGenerator.EmitCalli(OpCodes.Calli, System.Runtime.InteropServices.CallingConvention.StdCall, realRetType, modargs); + CodeEmitterLocal retValue = null; + if (retTypeWrapper != PrimitiveTypeWrapper.VOID) + { + if (retTypeWrapper.IsUnloadable) + { + ilGenerator.Emit(OpCodes.Call, unwrapLocalRef); + } + else if (!retTypeWrapper.IsPrimitive) + { + ilGenerator.Emit(OpCodes.Call, unwrapLocalRef); + if (retTypeWrapper.IsNonPrimitiveValueType) + { + retTypeWrapper.EmitUnbox(ilGenerator); + } + else if (retTypeWrapper.IsGhost) + { + CodeEmitterLocal ghost = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsSignatureType); + CodeEmitterLocal obj = ilGenerator.DeclareLocal(Types.Object); + ilGenerator.Emit(OpCodes.Stloc, obj); + ilGenerator.Emit(OpCodes.Ldloca, ghost); + ilGenerator.Emit(OpCodes.Ldloc, obj); + ilGenerator.Emit(OpCodes.Stfld, retTypeWrapper.GhostRefField); + ilGenerator.Emit(OpCodes.Ldloc, ghost); + } + else + { + ilGenerator.Emit(OpCodes.Castclass, retTypeWrapper.TypeAsTBD); + } + } + retValue = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsSignatureType); + ilGenerator.Emit(OpCodes.Stloc, retValue); + } + CodeEmitterLabel retLabel = ilGenerator.DefineLabel(); + ilGenerator.EmitLeave(retLabel); + ilGenerator.BeginCatchBlock(Types.Object); + ilGenerator.Emit(OpCodes.Ldstr, "*** exception in native code ***"); + ilGenerator.Emit(OpCodes.Call, writeLine); + ilGenerator.Emit(OpCodes.Call, writeLine); + ilGenerator.Emit(OpCodes.Rethrow); + ilGenerator.BeginFinallyBlock(); + ilGenerator.Emit(OpCodes.Ldloca, localRefStruct); + ilGenerator.Emit(OpCodes.Call, leaveLocalRefStruct); + ilGenerator.Emit(OpCodes.Endfinally); + ilGenerator.EndExceptionBlock(); + if (m.IsSynchronized && m.IsStatic) + { + ilGenerator.BeginFinallyBlock(); + ilGenerator.Emit(OpCodes.Ldloc, syncObject); + ilGenerator.Emit(OpCodes.Call, monitorExit); + ilGenerator.Emit(OpCodes.Endfinally); + ilGenerator.EndExceptionBlock(); + } + ilGenerator.MarkLabel(retLabel); + if (retTypeWrapper != PrimitiveTypeWrapper.VOID) + { + ilGenerator.Emit(OpCodes.Ldloc, retValue); + } + ilGenerator.Emit(OpCodes.Ret); + } + } + + private static class TraceHelper + { +#if STATIC_COMPILER + private readonly static MethodInfo methodIsTracedMethod = JVM.LoadType(typeof(Tracer)).GetMethod("IsTracedMethod"); +#endif + private readonly static MethodInfo methodMethodInfo = JVM.LoadType(typeof(Tracer)).GetMethod("MethodInfo"); + + internal static void EmitMethodTrace(CodeEmitter ilgen, string tracemessage) + { + if (Tracer.IsTracedMethod(tracemessage)) + { + CodeEmitterLabel label = ilgen.DefineLabel(); +#if STATIC_COMPILER + // TODO this should be a boolean field test instead of a call to Tracer.IsTracedMessage + ilgen.Emit(OpCodes.Ldstr, tracemessage); + ilgen.Emit(OpCodes.Call, methodIsTracedMethod); + ilgen.EmitBrfalse(label); +#endif + ilgen.Emit(OpCodes.Ldstr, tracemessage); + ilgen.Emit(OpCodes.Call, methodMethodInfo); + ilgen.MarkLabel(label); + } + } + } + +#if STATIC_COMPILER + private void EmitCallerIDStub(MethodWrapper mw, string[] parameterNames) + { + // we don't need to support custom modifiers, because there aren't any callerid methods that have parameter types that require a custom modifier + TypeWrapper[] parameters = mw.GetParameters(); + Type[] parameterTypes = new Type[parameters.Length]; + for (int i = 0; i < parameterTypes.Length; i++) + { + parameterTypes[i] = parameters[i].TypeAsSignatureType; + } + MethodAttributes attribs = MethodAttributes.HideBySig; + int argcount = parameterTypes.Length; + if (mw.IsStatic) + { + attribs |= MethodAttributes.Static; + } + else + { + argcount++; + } + if (mw.IsPublic) + { + attribs |= MethodAttributes.Public; + } + else if (mw.IsProtected) + { + attribs |= MethodAttributes.FamORAssem; + } + else if (mw.IsPrivate) + { + attribs |= MethodAttributes.Private; + } + else + { + attribs |= MethodAttributes.Assembly; + } + MethodBuilder mb = typeBuilder.DefineMethod(mw.Name, attribs, mw.ReturnType.TypeAsSignatureType, parameterTypes); + AttributeHelper.HideFromJava(mb); + mb.SetImplementationFlags(MethodImplAttributes.NoInlining); + CodeEmitter ilgen = CodeEmitter.Create(mb); + for (int i = 0; i < argcount; i++) + { + if (parameterNames != null && (mw.IsStatic || i > 0)) + { + ParameterBuilder pb = mb.DefineParameter(mw.IsStatic ? i + 1 : i, ParameterAttributes.None, parameterNames[mw.IsStatic ? i : i - 1]); + if (i == argcount - 1 && (mw.Modifiers & Modifiers.VarArgs) != 0) + { + AttributeHelper.SetParamArrayAttribute(pb); + } + } + ilgen.EmitLdarg(i); + } + ilgen.Emit(OpCodes.Ldc_I4_1); + ilgen.Emit(OpCodes.Ldc_I4_0); + ilgen.Emit(OpCodes.Newobj, JVM.Import(typeof(StackFrame)).GetConstructor(new Type[] { Types.Int32, Types.Boolean })); + MethodWrapper callerID = CoreClasses.ikvm.@internal.CallerID.Wrapper.GetMethodWrapper("create", "(Lcli.System.Diagnostics.StackFrame;)Likvm.internal.CallerID;", false); + callerID.Link(); + callerID.EmitCall(ilgen); + if (mw.IsStatic) + { + mw.EmitCall(ilgen); + } + else + { + mw.EmitCallvirt(ilgen); + } + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } +#endif // STATIC_COMPILER + + private void ImplementInterfaces(TypeWrapper[] interfaces, List interfaceList) + { + foreach (TypeWrapper iface in interfaces) + { + if (!interfaceList.Contains(iface)) + { + interfaceList.Add(iface); + if (!iface.IsAccessibleFrom(wrapper)) + { + continue; + } + // NOTE we're using TypeAsBaseType for the interfaces! + typeBuilder.AddInterfaceImplementation(iface.TypeAsBaseType); +#if STATIC_COMPILER + if (!wrapper.IsInterface) + { + // look for "magic" interfaces that imply a .NET interface + if (iface.GetClassLoader() == CoreClasses.java.lang.Object.Wrapper.GetClassLoader()) + { + if (iface.Name == "java.lang.Iterable" + && !wrapper.ImplementsInterface(ClassLoaderWrapper.GetWrapperFromType(JVM.Import(typeof(System.Collections.IEnumerable))))) + { + TypeWrapper enumeratorType = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedNameFast("ikvm.lang.IterableEnumerator"); + if (enumeratorType != null) + { + typeBuilder.AddInterfaceImplementation(JVM.Import(typeof(System.Collections.IEnumerable))); + // FXBUG we're using the same method name as the C# compiler here because both the .NET and Mono implementations of Xml serialization depend on this method name + MethodBuilder mb = typeBuilder.DefineMethod("System.Collections.IEnumerable.GetEnumerator", MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final | MethodAttributes.SpecialName, JVM.Import(typeof(System.Collections.IEnumerator)), Type.EmptyTypes); + AttributeHelper.HideFromJava(mb); + typeBuilder.DefineMethodOverride(mb, JVM.Import(typeof(System.Collections.IEnumerable)).GetMethod("GetEnumerator")); + CodeEmitter ilgen = CodeEmitter.Create(mb); + ilgen.Emit(OpCodes.Ldarg_0); + MethodWrapper mw = enumeratorType.GetMethodWrapper("", "(Ljava.lang.Iterable;)V", false); + mw.Link(); + mw.EmitNewobj(ilgen); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + } + } + // if we implement a ghost interface, add an implicit conversion to the ghost reference value type + if (iface.IsGhost && wrapper.IsPublic) + { + MethodBuilder mb = typeBuilder.DefineMethod("op_Implicit", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, iface.TypeAsSignatureType, new Type[] { wrapper.TypeAsSignatureType }); + AttributeHelper.HideFromJava(mb); + CodeEmitter ilgen = CodeEmitter.Create(mb); + CodeEmitterLocal local = ilgen.DeclareLocal(iface.TypeAsSignatureType); + ilgen.Emit(OpCodes.Ldloca, local); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Stfld, iface.GhostRefField); + ilgen.Emit(OpCodes.Ldloca, local); + ilgen.Emit(OpCodes.Ldobj, iface.TypeAsSignatureType); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + } +#endif // STATIC_COMPILER + // NOTE we're recursively "implementing" all interfaces that we inherit from the interfaces we implement. + // The C# compiler also does this and the Compact Framework requires it. + ImplementInterfaces(iface.Interfaces, interfaceList); + } + } + } + + private void AddUnsupportedAbstractMethods() + { + foreach (MethodBase mb in wrapper.BaseTypeWrapper.TypeAsBaseType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) + { + if (DotNetTypeWrapper.IsUnsupportedAbstractMethod(mb)) + { + GenerateUnsupportedAbstractMethodStub(mb); + } + } + Dictionary h = new Dictionary(); + TypeWrapper tw = wrapper; + while (tw != null) + { + foreach (TypeWrapper iface in tw.Interfaces) + { + foreach (MethodBase mb in iface.TypeAsBaseType.GetMethods(BindingFlags.Public | BindingFlags.Instance)) + { + if (!h.ContainsKey(mb)) + { + h.Add(mb, mb); + if (DotNetTypeWrapper.IsUnsupportedAbstractMethod(mb)) + { + GenerateUnsupportedAbstractMethodStub(mb); + } + } + } + } + tw = tw.BaseTypeWrapper; + } + } + + private void GenerateUnsupportedAbstractMethodStub(MethodBase mb) + { + ParameterInfo[] parameters = mb.GetParameters(); + Type[] parameterTypes = new Type[parameters.Length]; + for (int i = 0; i < parameters.Length; i++) + { + parameterTypes[i] = parameters[i].ParameterType; + } + MethodAttributes attr = MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Private; + MethodBuilder m = typeBuilder.DefineMethod("__" + mb.DeclaringType.FullName + "/" + mb.Name, attr, ((MethodInfo)mb).ReturnType, parameterTypes); + if (mb.IsGenericMethodDefinition) + { + CopyGenericArguments(mb, m); + } + CodeEmitter ilgen = CodeEmitter.Create(m); + ilgen.EmitThrow("java.lang.AbstractMethodError", "Method " + mb.DeclaringType.FullName + "." + mb.Name + " is unsupported by IKVM."); + ilgen.DoEmit(); + typeBuilder.DefineMethodOverride(m, (MethodInfo)mb); + } + + private static void CopyGenericArguments(MethodBase mi, MethodBuilder mb) + { + Type[] genericParameters = mi.GetGenericArguments(); + string[] genParamNames = new string[genericParameters.Length]; + for (int i = 0; i < genParamNames.Length; i++) + { + genParamNames[i] = genericParameters[i].Name; + } + GenericTypeParameterBuilder[] genParamBuilders = mb.DefineGenericParameters(genParamNames); + for (int i = 0; i < genParamBuilders.Length; i++) + { + // NOTE apparently we don't need to set the interface constraints + // (and if we do, it fails for some reason) + if (genericParameters[i].BaseType != Types.Object) + { + genParamBuilders[i].SetBaseTypeConstraint(genericParameters[i].BaseType); + } + genParamBuilders[i].SetGenericParameterAttributes(genericParameters[i].GenericParameterAttributes); + } + } + + private void CompileConstructorBody(FinishContext context, CodeEmitter ilGenerator, int methodIndex) + { + MethodWrapper[] methods = wrapper.GetMethods(); + ClassFile.Method m = classFile.Methods[methodIndex]; + TraceHelper.EmitMethodTrace(ilGenerator, classFile.Name + "." + m.Name + m.Signature); +#if STATIC_COMPILER + // do we have an implementation in map.xml? + if (wrapper.EmitMapXmlMethodPrologueAndOrBody(ilGenerator, classFile, m)) + { + ilGenerator.DoEmit(); + return; + } +#endif + bool nonLeaf = false; + Compiler.Compile(context, host, wrapper, methods[methodIndex], classFile, m, ilGenerator, ref nonLeaf); + ilGenerator.DoEmit(); +#if STATIC_COMPILER + ilGenerator.EmitLineNumberTable((MethodBuilder)methods[methodIndex].GetMethod()); +#else // STATIC_COMPILER + byte[] linenumbers = ilGenerator.GetLineNumberTable(); + if (linenumbers != null) + { + if (wrapper.lineNumberTables == null) + { + wrapper.lineNumberTables = new byte[methods.Length][]; + } + wrapper.lineNumberTables[methodIndex] = linenumbers; + } +#endif // STATIC_COMPILER + } + + private static bool IsCompatibleArgList(TypeWrapper[] caller, TypeWrapper[] callee) + { + if (caller.Length == callee.Length) + { + for (int i = 0; i < caller.Length; i++) + { + if (caller[i].IsUnloadable || callee[i].IsUnloadable) + { + return false; + } + if (!caller[i].IsAssignableTo(callee[i])) + { + return false; + } + } + return true; + } + return false; + } + + private void EmitCallerIDInitialization(CodeEmitter ilGenerator, FieldInfo callerIDField) + { + TypeWrapper tw = CoreClasses.ikvm.@internal.CallerID.Wrapper; + if (tw.InternalsVisibleTo(wrapper)) + { + MethodWrapper create = tw.GetMethodWrapper("create", "(Lcli.System.RuntimeTypeHandle;)Likvm.internal.CallerID;", false); + ilGenerator.Emit(OpCodes.Ldtoken, this.typeBuilder); + create.Link(); + create.EmitCall(ilGenerator); + } + else + { + RegisterNestedTypeBuilder(EmitCreateCallerID(typeBuilder, ilGenerator)); + } + ilGenerator.Emit(OpCodes.Stsfld, callerIDField); + } + + internal static TypeBuilder EmitCreateCallerID(TypeBuilder typeBuilder, CodeEmitter ilGenerator) + { + TypeWrapper tw = CoreClasses.ikvm.@internal.CallerID.Wrapper; + TypeBuilder typeCallerID = typeBuilder.DefineNestedType(NestedTypeName.CallerID, TypeAttributes.Sealed | TypeAttributes.NestedPrivate, tw.TypeAsBaseType); + MethodBuilder cb = ReflectUtil.DefineConstructor(typeCallerID, MethodAttributes.Assembly, null); + CodeEmitter ctorIlgen = CodeEmitter.Create(cb); + ctorIlgen.Emit(OpCodes.Ldarg_0); + MethodWrapper mw = tw.GetMethodWrapper("", "()V", false); + mw.Link(); + mw.EmitCall(ctorIlgen); + ctorIlgen.Emit(OpCodes.Ret); + ctorIlgen.DoEmit(); + ilGenerator.Emit(OpCodes.Newobj, cb); + return typeCallerID; + } + + private void EmitConstantValueInitialization(FieldWrapper[] fields, CodeEmitter ilGenerator) + { + ClassFile.Field[] flds = classFile.Fields; + for (int i = 0; i < flds.Length; i++) + { + ClassFile.Field f = flds[i]; + if (f.IsStatic && !f.IsFinal) + { + object constant = f.ConstantValue; + if (constant != null) + { + if (constant is int) + { + ilGenerator.EmitLdc_I4((int)constant); + } + else if (constant is bool) + { + ilGenerator.EmitLdc_I4((bool)constant ? 1 : 0); + } + else if (constant is byte) + { + ilGenerator.EmitLdc_I4((byte)constant); + } + else if (constant is char) + { + ilGenerator.EmitLdc_I4((char)constant); + } + else if (constant is short) + { + ilGenerator.EmitLdc_I4((short)constant); + } + else if (constant is long) + { + ilGenerator.EmitLdc_I8((long)constant); + } + else if (constant is double) + { + ilGenerator.EmitLdc_R8((double)constant); + } + else if (constant is float) + { + ilGenerator.EmitLdc_R4((float)constant); + } + else if (constant is string) + { + ilGenerator.Emit(OpCodes.Ldstr, (string)constant); + } + else + { + throw new InvalidOperationException(); + } + fields[i].EmitSet(ilGenerator); + } + } + } + } + + internal MethodBuilder DefineThreadLocalType() + { + TypeWrapper threadLocal = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.IntrinsicThreadLocal"); + int id = nestedTypeBuilders == null ? 0 : nestedTypeBuilders.Count; + TypeBuilder tb = typeBuilder.DefineNestedType(NestedTypeName.ThreadLocal + id, TypeAttributes.NestedPrivate | TypeAttributes.Sealed, threadLocal.TypeAsBaseType); + FieldBuilder fb = tb.DefineField("field", Types.Object, FieldAttributes.Private | FieldAttributes.Static); + fb.SetCustomAttribute(new CustomAttributeBuilder(JVM.Import(typeof(ThreadStaticAttribute)).GetConstructor(Type.EmptyTypes), new object[0])); + MethodBuilder mbGet = tb.DefineMethod("get", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, Types.Object, Type.EmptyTypes); + ILGenerator ilgen = mbGet.GetILGenerator(); + ilgen.Emit(OpCodes.Ldsfld, fb); + ilgen.Emit(OpCodes.Ret); + MethodBuilder mbSet = tb.DefineMethod("set", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, null, new Type[] { Types.Object }); + ilgen = mbSet.GetILGenerator(); + ilgen.Emit(OpCodes.Ldarg_1); + ilgen.Emit(OpCodes.Stsfld, fb); + ilgen.Emit(OpCodes.Ret); + MethodBuilder cb = ReflectUtil.DefineConstructor(tb, MethodAttributes.Assembly, Type.EmptyTypes); + CodeEmitter ctorilgen = CodeEmitter.Create(cb); + ctorilgen.Emit(OpCodes.Ldarg_0); + MethodWrapper basector = threadLocal.GetMethodWrapper("", "()V", false); + basector.Link(); + basector.EmitCall(ctorilgen); + ctorilgen.Emit(OpCodes.Ret); + ctorilgen.DoEmit(); + RegisterNestedTypeBuilder(tb); + return cb; + } + + internal MethodBuilder GetAtomicReferenceFieldUpdater(FieldWrapper field) + { + if (arfuMap == null) + { + arfuMap = new Dictionary(); + } + MethodBuilder cb; + if (!arfuMap.TryGetValue(field, out cb)) + { + TypeWrapper arfuTypeWrapper = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.IntrinsicAtomicReferenceFieldUpdater"); + TypeBuilder tb = typeBuilder.DefineNestedType(NestedTypeName.AtomicReferenceFieldUpdater + arfuMap.Count, TypeAttributes.NestedPrivate | TypeAttributes.Sealed, arfuTypeWrapper.TypeAsBaseType); + AtomicReferenceFieldUpdaterEmitter.EmitImpl(tb, field.GetField()); + cb = ReflectUtil.DefineConstructor(tb, MethodAttributes.Assembly, Type.EmptyTypes); + arfuMap.Add(field, cb); + CodeEmitter ctorilgen = CodeEmitter.Create(cb); + ctorilgen.Emit(OpCodes.Ldarg_0); + MethodWrapper basector = arfuTypeWrapper.GetMethodWrapper("", "()V", false); + basector.Link(); + basector.EmitCall(ctorilgen); + ctorilgen.Emit(OpCodes.Ret); + ctorilgen.DoEmit(); + RegisterNestedTypeBuilder(tb); + } + return cb; + } + + internal TypeBuilder DefineIndyCallSiteType() + { + int id = nestedTypeBuilders == null ? 0 : nestedTypeBuilders.Count; + TypeBuilder tb = typeBuilder.DefineNestedType(NestedTypeName.IndyCallSite + id, TypeAttributes.NestedPrivate | TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit); + RegisterNestedTypeBuilder(tb); + return tb; + } + + internal TypeBuilder DefineMethodHandleConstantType(int index) + { + TypeBuilder tb = typeBuilder.DefineNestedType(NestedTypeName.MethodHandleConstant + index, TypeAttributes.NestedPrivate | TypeAttributes.Sealed | TypeAttributes.Abstract | TypeAttributes.BeforeFieldInit); ; + RegisterNestedTypeBuilder(tb); + return tb; + } + + internal TypeBuilder DefineMethodTypeConstantType(int index) + { + TypeBuilder tb = typeBuilder.DefineNestedType(NestedTypeName.MethodTypeConstant + index, TypeAttributes.NestedPrivate | TypeAttributes.Sealed | TypeAttributes.Abstract | TypeAttributes.BeforeFieldInit); + RegisterNestedTypeBuilder(tb); + return tb; + } + + // this is used to define intrinsified anonymous classes (in the Unsafe.defineAnonymousClass() sense) + internal TypeBuilder DefineAnonymousClass() + { + int id = nestedTypeBuilders == null ? 0 : nestedTypeBuilders.Count; + TypeBuilder tb = typeBuilder.DefineNestedType(NestedTypeName.IntrinsifiedAnonymousClass + id, TypeAttributes.NestedPrivate | TypeAttributes.Sealed | TypeAttributes.SpecialName | TypeAttributes.BeforeFieldInit); + RegisterNestedTypeBuilder(tb); + return tb; + } + + private MethodBuilder DefineHelperMethod(string name, Type returnType, Type[] parameterTypes) + { +#if STATIC_COMPILER + // FXBUG csc.exe doesn't like non-public methods in interfaces, so for public interfaces we move + // the helper methods into a nested type. + if (wrapper.IsPublic && wrapper.IsInterface && wrapper.classLoader.WorkaroundInterfacePrivateMethods) + { + if (interfaceHelperMethodsTypeBuilder == null) + { + interfaceHelperMethodsTypeBuilder = typeBuilder.DefineNestedType(NestedTypeName.InterfaceHelperMethods, TypeAttributes.NestedPrivate | TypeAttributes.Sealed | TypeAttributes.Abstract | TypeAttributes.BeforeFieldInit); + RegisterNestedTypeBuilder(interfaceHelperMethodsTypeBuilder); + } + return interfaceHelperMethodsTypeBuilder.DefineMethod(name, MethodAttributes.PrivateScope | MethodAttributes.Static, returnType, parameterTypes); + } +#endif + return typeBuilder.DefineMethod(name, MethodAttributes.PrivateScope | MethodAttributes.Static, returnType, parameterTypes); + } + + internal MethodBuilder DefineMethodHandleDispatchStub(Type returnType, Type[] parameterTypes) + { + return DefineHelperMethod("__<>MHC", returnType, parameterTypes); + } + + internal FieldBuilder DefineMethodHandleInvokeCacheField(Type fieldType) + { + return typeBuilder.DefineField("__<>invokeCache", fieldType, FieldAttributes.Static | FieldAttributes.PrivateScope); + } + + internal FieldBuilder DefineDynamicMethodHandleCacheField() + { + return typeBuilder.DefineField("__<>dynamicMethodHandleCache", CoreClasses.java.lang.invoke.MethodHandle.Wrapper.TypeAsSignatureType, FieldAttributes.Static | FieldAttributes.PrivateScope); + } + + internal FieldBuilder DefineDynamicMethodTypeCacheField() + { + return typeBuilder.DefineField("__<>dynamicMethodTypeCache", CoreClasses.java.lang.invoke.MethodType.Wrapper.TypeAsSignatureType, FieldAttributes.Static | FieldAttributes.PrivateScope); + } + + internal MethodBuilder DefineDelegateInvokeErrorStub(Type returnType, Type[] parameterTypes) + { + return DefineHelperMethod("__<>", returnType, parameterTypes); + } + + internal MethodInfo GetInvokeSpecialStub(MethodWrapper method) + { + if (invokespecialstubcache == null) + { + invokespecialstubcache = new Dictionary(); + } + MethodKey key = new MethodKey(method.DeclaringType.Name, method.Name, method.Signature); + MethodInfo mi; + if (!invokespecialstubcache.TryGetValue(key, out mi)) + { + DefineMethodHelper dmh = method.GetDefineMethodHelper(); + MethodBuilder stub = dmh.DefineMethod(wrapper, typeBuilder, "__<>", MethodAttributes.PrivateScope); + CodeEmitter ilgen = CodeEmitter.Create(stub); + ilgen.Emit(OpCodes.Ldarg_0); + for (int i = 1; i <= dmh.ParameterCount; i++) + { + ilgen.EmitLdarg(i); + } + method.EmitCall(ilgen); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + invokespecialstubcache[key] = stub; + mi = stub; + } + return mi; + } + +#if !STATIC_COMPILER + internal void EmitLiveObjectLoad(CodeEmitter ilgen, object value) + { + if (liveObjects == null) + { + liveObjects = new List(); + } + FieldInfo fi = TypeBuilder.GetField(typeof(IKVM.Runtime.LiveObjectHolder<>).MakeGenericType(typeBuilder), typeof(IKVM.Runtime.LiveObjectHolder<>).GetField("values", BindingFlags.Static | BindingFlags.Public)); + ilgen.Emit(OpCodes.Ldsfld, fi); + ilgen.EmitLdc_I4(liveObjects.Count); + ilgen.Emit(OpCodes.Ldelem_Ref); + liveObjects.Add(value); + } +#endif + } + + private static bool CheckRequireOverrideStub(MethodWrapper mw1, MethodWrapper mw2) + { + // TODO this is too late to generate LinkageErrors so we need to figure this out earlier + if (!TypesMatchForOverride(mw1.ReturnType, mw2.ReturnType)) + { + return true; + } + TypeWrapper[] args1 = mw1.GetParameters(); + TypeWrapper[] args2 = mw2.GetParameters(); + for (int i = 0; i < args1.Length; i++) + { + if (!TypesMatchForOverride(args1[i], args2[i])) + { + return true; + } + } + return false; + } + + private static bool TypesMatchForOverride(TypeWrapper tw1, TypeWrapper tw2) + { + if (tw1 == tw2) + { + return true; + } + else if (tw1.IsUnloadable && tw2.IsUnloadable) + { + return ((UnloadableTypeWrapper)tw1).CustomModifier == ((UnloadableTypeWrapper)tw2).CustomModifier; + } + else + { + return false; + } + } + + private void GenerateOverrideStub(TypeBuilder typeBuilder, MethodWrapper baseMethod, MethodInfo target, MethodWrapper targetMethod) + { + Debug.Assert(!baseMethod.HasCallerID); + + MethodBuilder overrideStub = baseMethod.GetDefineMethodHelper().DefineMethod(this, typeBuilder, "__" + baseMethod.DeclaringType.Name + "::" + baseMethod.Name, MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final); + typeBuilder.DefineMethodOverride(overrideStub, (MethodInfo)baseMethod.GetMethod()); + + TypeWrapper[] stubargs = baseMethod.GetParameters(); + TypeWrapper[] targetArgs = targetMethod.GetParameters(); + CodeEmitter ilgen = CodeEmitter.Create(overrideStub); + ilgen.Emit(OpCodes.Ldarg_0); + for (int i = 0; i < targetArgs.Length; i++) + { + ilgen.EmitLdarg(i + 1); + ConvertStubArg(stubargs[i], targetArgs[i], ilgen); + } + if (target != null) + { + ilgen.Emit(OpCodes.Callvirt, target); + } + else + { + targetMethod.EmitCallvirt(ilgen); + } + ConvertStubArg(targetMethod.ReturnType, baseMethod.ReturnType, ilgen); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + + private static void ConvertStubArg(TypeWrapper src, TypeWrapper dst, CodeEmitter ilgen) + { + if (src != dst) + { + if (dst.IsUnloadable) + { + if (!src.IsUnloadable && (src.IsGhost || src.IsNonPrimitiveValueType)) + { + src.EmitConvSignatureTypeToStackType(ilgen); + } + } + else if (dst.IsGhost || dst.IsNonPrimitiveValueType) + { + dst.EmitConvStackTypeToSignatureType(ilgen, null); + } + else + { + dst.EmitCheckcast(ilgen); + } + } + } + + private static void GetParameterNamesFromMP(ClassFile.Method m, string[] parameterNames) + { + MethodParametersEntry[] methodParameters = m.MethodParameters; + if (methodParameters != null) + { + for (int i = 0, count = Math.Min(parameterNames.Length, methodParameters.Length); i < count; i++) + { + if (parameterNames[i] == null) + { + parameterNames[i] = methodParameters[i].name; + } + } + } + } + + protected static void GetParameterNamesFromLVT(ClassFile.Method m, string[] parameterNames) + { + ClassFile.Method.LocalVariableTableEntry[] localVars = m.LocalVariableTableAttribute; + if (localVars != null) + { + for (int i = m.IsStatic ? 0 : 1, pos = 0; i < m.ArgMap.Length; i++) + { + // skip double & long fillers + if (m.ArgMap[i] != -1) + { + if (parameterNames[pos] == null) + { + for (int j = 0; j < localVars.Length; j++) + { + if (localVars[j].index == i) + { + parameterNames[pos] = localVars[j].name; + break; + } + } + } + pos++; + } + } + } + } + + protected static void GetParameterNamesFromSig(string sig, string[] parameterNames) + { + List names = new List(); + for (int i = 1; sig[i] != ')'; i++) + { + if (sig[i] == 'L') + { + i++; + int end = sig.IndexOf(';', i); + names.Add(GetParameterName(sig.Substring(i, end - i))); + i = end; + } + else if (sig[i] == '[') + { + while (sig[++i] == '[') ; + if (sig[i] == 'L') + { + i++; + int end = sig.IndexOf(';', i); + names.Add(GetParameterName(sig.Substring(i, end - i)) + "arr"); + i = end; + } + else + { + switch (sig[i]) + { + case 'B': + case 'Z': + names.Add("barr"); + break; + case 'C': + names.Add("charr"); + break; + case 'S': + names.Add("sarr"); + break; + case 'I': + names.Add("iarr"); + break; + case 'J': + names.Add("larr"); + break; + case 'F': + names.Add("farr"); + break; + case 'D': + names.Add("darr"); + break; + } + } + } + else + { + switch (sig[i]) + { + case 'B': + case 'Z': + names.Add("b"); + break; + case 'C': + names.Add("ch"); + break; + case 'S': + names.Add("s"); + break; + case 'I': + names.Add("i"); + break; + case 'J': + names.Add("l"); + break; + case 'F': + names.Add("f"); + break; + case 'D': + names.Add("d"); + break; + } + } + } + for (int i = 0; i < parameterNames.Length; i++) + { + if (parameterNames[i] == null) + { + parameterNames[i] = names[i]; + } + } + } + + protected static ParameterBuilder[] GetParameterBuilders(MethodBuilder mb, int parameterCount, string[] parameterNames) + { + ParameterBuilder[] parameterBuilders = new ParameterBuilder[parameterCount]; + Dictionary clashes = null; + for (int i = 0; i < parameterBuilders.Length; i++) + { + string name = null; + if (parameterNames != null && parameterNames[i] != null) + { + name = parameterNames[i]; + if (Array.IndexOf(parameterNames, name, i + 1) >= 0 || (clashes != null && clashes.ContainsKey(name))) + { + if (clashes == null) + { + clashes = new Dictionary(); + } + int clash = 1; + if (clashes.ContainsKey(name)) + { + clash = clashes[name] + 1; + } + clashes[name] = clash; + name += clash; + } + } + parameterBuilders[i] = mb.DefineParameter(i + 1, ParameterAttributes.None, name); + } + return parameterBuilders; + } + + private static string GetParameterName(string type) + { + if (type == "java.lang.String") + { + return "str"; + } + else if (type == "java.lang.Object") + { + return "obj"; + } + else + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + for (int i = type.LastIndexOf('.') + 1; i < type.Length; i++) + { + if (char.IsUpper(type, i)) + { + sb.Append(char.ToLower(type[i])); + } + } + return sb.ToString(); + } + } + +#if STATIC_COMPILER + protected abstract void AddMapXmlFields(ref FieldWrapper[] fields); + protected abstract bool EmitMapXmlMethodPrologueAndOrBody(CodeEmitter ilgen, ClassFile f, ClassFile.Method m); + protected abstract void EmitMapXmlMetadata(TypeBuilder typeBuilder, ClassFile classFile, FieldWrapper[] fields, MethodWrapper[] methods); + protected abstract MethodBuilder DefineGhostMethod(TypeBuilder typeBuilder, string name, MethodAttributes attribs, MethodWrapper mw); + protected abstract void FinishGhost(TypeBuilder typeBuilder, MethodWrapper[] methods); + protected abstract void FinishGhostStep2(); + protected abstract TypeBuilder DefineGhostType(string mangledTypeName, TypeAttributes typeAttribs); +#endif // STATIC_COMPILER + + private bool IsPInvokeMethod(ClassFile.Method m) + { +#if STATIC_COMPILER + Dictionary mapxml = classLoader.GetMapXmlClasses(); + if (mapxml != null) + { + IKVM.Internal.MapXml.Class clazz; + if (mapxml.TryGetValue(this.Name, out clazz) && clazz.Methods != null) + { + foreach (IKVM.Internal.MapXml.Method method in clazz.Methods) + { + if (method.Name == m.Name && method.Sig == m.Signature) + { + if (method.Attributes != null) + { + foreach (IKVM.Internal.MapXml.Attribute attr in method.Attributes) + { + if (StaticCompiler.GetType(classLoader, attr.Type) == JVM.Import(typeof(System.Runtime.InteropServices.DllImportAttribute))) + { + return true; + } + } + } + break; + } + } + } + } +#elif CLASSGC + // TODO PInvoke is not supported in RunAndCollect assemblies, + if (JVM.classUnloading) + { + return false; + } +#endif + if (m.Annotations != null) + { + foreach (object[] annot in m.Annotations) + { + if ("Lcli/System/Runtime/InteropServices/DllImportAttribute$Annotation;".Equals(annot[1])) + { + return true; + } + } + } + return false; + } + + internal override MethodBase LinkMethod(MethodWrapper mw) + { + mw.AssertLinked(); + return impl.LinkMethod(mw); + } + + internal override FieldInfo LinkField(FieldWrapper fw) + { + fw.AssertLinked(); + return impl.LinkField(fw); + } + + internal override void EmitRunClassConstructor(CodeEmitter ilgen) + { + impl.EmitRunClassConstructor(ilgen); + } + + internal override string GetGenericSignature() + { + return impl.GetGenericSignature(); + } + + internal override string GetGenericMethodSignature(MethodWrapper mw) + { + MethodWrapper[] methods = GetMethods(); + for (int i = 0; i < methods.Length; i++) + { + if (methods[i] == mw) + { + return impl.GetGenericMethodSignature(i); + } + } + Debug.Fail("Unreachable code"); + return null; + } + + internal override string GetGenericFieldSignature(FieldWrapper fw) + { + FieldWrapper[] fields = GetFields(); + for (int i = 0; i < fields.Length; i++) + { + if (fields[i] == fw) + { + return impl.GetGenericFieldSignature(i); + } + } + Debug.Fail("Unreachable code"); + return null; + } + + internal override MethodParametersEntry[] GetMethodParameters(MethodWrapper mw) + { + MethodWrapper[] methods = GetMethods(); + for (int i = 0; i < methods.Length; i++) + { + if (methods[i] == mw) + { + return impl.GetMethodParameters(i); + } + } + Debug.Fail("Unreachable code"); + return null; + } + +#if !STATIC_COMPILER + internal override string[] GetEnclosingMethod() + { + return impl.GetEnclosingMethod(); + } + + internal override string GetSourceFileName() + { + return sourceFileName; + } + + private int GetMethodBaseToken(MethodBase mb) + { + MethodBuilder mbld = mb as MethodBuilder; + if (mbld != null) + { + return mbld.GetToken().Token; + } + return mb.MetadataToken; + } + + internal override int GetSourceLineNumber(MethodBase mb, int ilOffset) + { + if (lineNumberTables != null) + { + int token = GetMethodBaseToken(mb); + MethodWrapper[] methods = GetMethods(); + for (int i = 0; i < methods.Length; i++) + { + if (GetMethodBaseToken(methods[i].GetMethod()) == token) + { + if (lineNumberTables[i] != null) + { + return new LineNumberTableAttribute(lineNumberTables[i]).GetLineNumber(ilOffset); + } + break; + } + } + } + return -1; + } + + private object[] DecodeAnnotations(object[] definitions) + { + if (definitions == null) + { + return null; + } + java.lang.ClassLoader loader = GetClassLoader().GetJavaClassLoader(); + List annotations = new List(); + for (int i = 0; i < definitions.Length; i++) + { + object obj = JVM.NewAnnotation(loader, definitions[i]); + if (obj != null) + { + annotations.Add(obj); + } + } + return annotations.ToArray(); + } + + internal override object[] GetDeclaredAnnotations() + { + return DecodeAnnotations(impl.GetDeclaredAnnotations()); + } + + internal override object[] GetMethodAnnotations(MethodWrapper mw) + { + MethodWrapper[] methods = GetMethods(); + for (int i = 0; i < methods.Length; i++) + { + if (methods[i] == mw) + { + return DecodeAnnotations(impl.GetMethodAnnotations(i)); + } + } + Debug.Fail("Unreachable code"); + return null; + } + + internal override object[][] GetParameterAnnotations(MethodWrapper mw) + { + MethodWrapper[] methods = GetMethods(); + for (int i = 0; i < methods.Length; i++) + { + if (methods[i] == mw) + { + object[][] annotations = impl.GetParameterAnnotations(i); + if (annotations != null) + { + object[][] objs = new object[annotations.Length][]; + for (int j = 0; j < annotations.Length; j++) + { + objs[j] = DecodeAnnotations(annotations[j]); + } + return objs; + } + return null; + } + } + Debug.Fail("Unreachable code"); + return null; + } + + internal override object[] GetFieldAnnotations(FieldWrapper fw) + { + FieldWrapper[] fields = GetFields(); + for (int i = 0; i < fields.Length; i++) + { + if (fields[i] == fw) + { + return DecodeAnnotations(impl.GetFieldAnnotations(i)); + } + } + Debug.Fail("Unreachable code"); + return null; + } + + internal override object GetAnnotationDefault(MethodWrapper mw) + { + MethodWrapper[] methods = GetMethods(); + for (int i = 0; i < methods.Length; i++) + { + if (methods[i] == mw) + { + object defVal = impl.GetMethodDefaultValue(i); + if (defVal != null) + { + return JVM.NewAnnotationElementValue(mw.DeclaringType.GetClassLoader().GetJavaClassLoader(), mw.ReturnType.ClassObject, defVal); + } + return null; + } + } + Debug.Fail("Unreachable code"); + return null; + } + private Type GetBaseTypeForDefineType() + { + return BaseTypeWrapper.TypeAsBaseType; + } +#endif + +#if STATIC_COMPILER + protected virtual Type GetBaseTypeForDefineType() + { + return BaseTypeWrapper.TypeAsBaseType; + } + + internal virtual MethodWrapper[] GetReplacedMethodsFor(MethodWrapper mw) + { + return null; + } +#endif // STATIC_COMPILER + + internal override MethodBase GetSerializationConstructor() + { + return automagicSerializationCtor; + } + + private Type[] GetModOpt(TypeWrapper tw, bool mustBePublic) + { + return GetModOpt(GetClassLoader().GetTypeWrapperFactory(), tw, mustBePublic); + } + + internal static Type[] GetModOpt(TypeWrapperFactory context, TypeWrapper tw, bool mustBePublic) + { + Type[] modopt = Type.EmptyTypes; + if (tw.IsUnloadable) + { + if (((UnloadableTypeWrapper)tw).MissingType == null) + { + modopt = new Type[] { ((UnloadableTypeWrapper)tw).GetCustomModifier(context) }; + } + } + else + { + TypeWrapper tw1 = tw.IsArray ? tw.GetUltimateElementTypeWrapper() : tw; + if (tw1.IsErasedOrBoxedPrimitiveOrRemapped || tw.IsGhostArray || (mustBePublic && !tw1.IsPublic)) + { + // FXBUG Ref.Emit refuses arrays in custom modifiers, so we add an array type for each dimension + modopt = new Type[tw.ArrayRank + 1]; + modopt[0] = GetModOptHelper(tw1); + for (int i = 1; i < modopt.Length; i++) + { + modopt[i] = Types.Array; + } + } + } + return modopt; + } + + private static Type GetModOptHelper(TypeWrapper tw) + { + Debug.Assert(!tw.IsUnloadable); + if (tw.IsArray) + { + return ArrayTypeWrapper.MakeArrayType(GetModOptHelper(tw.GetUltimateElementTypeWrapper()), tw.ArrayRank); + } + else if (tw.IsGhost) + { + return tw.TypeAsTBD; + } + else + { + return tw.TypeAsBaseType; + } + } + +#if STATIC_COMPILER + private bool NeedsType2AccessStub(FieldWrapper fw) + { + Debug.Assert(this.IsPublic && fw.DeclaringType == this); + return fw.IsType2FinalField + || (fw.HasNonPublicTypeInSignature + && (fw.IsPublic || (fw.IsProtected && !this.IsFinal)) + && (fw.FieldTypeWrapper.IsUnloadable || fw.FieldTypeWrapper.IsAccessibleFrom(this) || fw.FieldTypeWrapper.InternalsVisibleTo(this))); + } +#endif + + internal static bool RequiresDynamicReflectionCallerClass(string classFile, string method, string signature) + { + return (classFile == "java.lang.ClassLoader" && method == "getParent" && signature == "()Ljava.lang.ClassLoader;") + || (classFile == "java.lang.Thread" && method == "getContextClassLoader" && signature == "()Ljava.lang.ClassLoader;") + || (classFile == "java.io.ObjectStreamField" && method == "getType" && signature == "()Ljava.lang.Class;") + || (classFile == "javax.sql.rowset.serial.SerialJavaObject" && method == "getFields" && signature == "()[Ljava.lang.reflect.Field;") + ; + } + + + internal override object[] GetConstantPool() + { + return impl.GetConstantPool(); + } + + internal override byte[] GetRawTypeAnnotations() + { + return impl.GetRawTypeAnnotations(); + } + + internal override byte[] GetMethodRawTypeAnnotations(MethodWrapper mw) + { + return impl.GetMethodRawTypeAnnotations(Array.IndexOf(GetMethods(), mw)); + } + + internal override byte[] GetFieldRawTypeAnnotations(FieldWrapper fw) + { + return impl.GetFieldRawTypeAnnotations(Array.IndexOf(GetFields(), fw)); + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal override TypeWrapper Host + { + get { return impl.Host; } + } +#endif + + [Conditional("STATIC_COMPILER")] + internal void EmitLevel4Warning(HardError error, string message) + { +#if STATIC_COMPILER + if (GetClassLoader().WarningLevelHigh) + { + switch (error) + { + case HardError.AbstractMethodError: + GetClassLoader().IssueMessage(Message.EmittedAbstractMethodError, this.Name, message); + break; + case HardError.IncompatibleClassChangeError: + GetClassLoader().IssueMessage(Message.EmittedIncompatibleClassChangeError, this.Name, message); + break; + default: + throw new InvalidOperationException(); + } + } +#endif + } + } + + sealed class DefineMethodHelper + { + private readonly MethodWrapper mw; + + internal DefineMethodHelper(MethodWrapper mw) + { + this.mw = mw; + } + + internal int ParameterCount + { + get { return mw.GetParameters().Length + (mw.HasCallerID ? 1 : 0); } + } + + internal MethodBuilder DefineMethod(DynamicTypeWrapper context, TypeBuilder tb, string name, MethodAttributes attribs) + { + return DefineMethod(context.GetClassLoader().GetTypeWrapperFactory(), tb, name, attribs, null, false); + } + + internal MethodBuilder DefineMethod(TypeWrapperFactory context, TypeBuilder tb, string name, MethodAttributes attribs) + { + return DefineMethod(context, tb, name, attribs, null, false); + } + + internal MethodBuilder DefineMethod(TypeWrapperFactory context, TypeBuilder tb, string name, MethodAttributes attribs, Type firstParameter, bool mustBePublic) + { + // we add optional modifiers to make the signature unique + int firstParam = firstParameter == null ? 0 : 1; + TypeWrapper[] parameters = mw.GetParameters(); + Type[] parameterTypes = new Type[parameters.Length + (mw.HasCallerID ? 1 : 0) + firstParam]; + Type[][] modopt = new Type[parameterTypes.Length][]; + if (firstParameter != null) + { + parameterTypes[0] = firstParameter; + modopt[0] = Type.EmptyTypes; + } + for (int i = 0; i < parameters.Length; i++) + { + parameterTypes[i + firstParam] = mustBePublic + ? parameters[i].TypeAsPublicSignatureType + : parameters[i].TypeAsSignatureType; + modopt[i + firstParam] = DynamicTypeWrapper.GetModOpt(context, parameters[i], mustBePublic); + } + if (mw.HasCallerID) + { + parameterTypes[parameterTypes.Length - 1] = CoreClasses.ikvm.@internal.CallerID.Wrapper.TypeAsSignatureType; + } + Type returnType = mustBePublic + ? mw.ReturnType.TypeAsPublicSignatureType + : mw.ReturnType.TypeAsSignatureType; + Type[] modoptReturnType = DynamicTypeWrapper.GetModOpt(context, mw.ReturnType, mustBePublic); + return tb.DefineMethod(name, attribs, CallingConventions.Standard, returnType, null, modoptReturnType, parameterTypes, null, modopt); + } + + internal MethodBuilder DefineConstructor(DynamicTypeWrapper context, TypeBuilder tb, MethodAttributes attribs) + { + return DefineConstructor(context.GetClassLoader().GetTypeWrapperFactory(), tb, attribs); + } + + internal MethodBuilder DefineConstructor(TypeWrapperFactory context, TypeBuilder tb, MethodAttributes attribs) + { + return DefineMethod(context, tb, ConstructorInfo.ConstructorName, attribs | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName); + } + } + +#if !STATIC_COMPILER + sealed class DynamicCallerIDProvider + { + // this object acts as a capability that is passed to trusted code to allow the DynamicCallerID() + // method to be public without giving untrusted code the ability to forge a CallerID token + internal static readonly DynamicCallerIDProvider Instance = new DynamicCallerIDProvider(); + + private DynamicCallerIDProvider() { } + + internal ikvm.@internal.CallerID GetCallerID() + { + for (int i = 0; ; ) + { + MethodBase method = new StackFrame(i++, false).GetMethod(); + if (method == null) + { +#if !FIRST_PASS + return ikvm.@internal.CallerID.create(null, null); +#endif + } + if (Java_sun_reflect_Reflection.IsHideFromStackWalk(method)) + { + continue; + } + TypeWrapper caller = ClassLoaderWrapper.GetWrapperFromType(method.DeclaringType); + return CreateCallerID(caller.Host ?? caller); + } + } + + internal static ikvm.@internal.CallerID CreateCallerID(TypeWrapper tw) + { +#if FIRST_PASS + return null; +#else + return ikvm.@internal.CallerID.create(tw.ClassObject, tw.GetClassLoader().GetJavaClassLoader()); +#endif + } + } +#endif +} diff --git a/runtime/ExceptionHelper.cs b/runtime/ExceptionHelper.cs new file mode 100644 index 0000000..ff40d16 --- /dev/null +++ b/runtime/ExceptionHelper.cs @@ -0,0 +1,918 @@ +/* + Copyright (C) 2002-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Diagnostics; +using System.Runtime.Serialization; +using System.Security; +using IKVM.Attributes; +using IKVM.Internal; +using IDictionary = System.Collections.IDictionary; +using Interlocked = System.Threading.Interlocked; +using MethodBase = System.Reflection.MethodBase; +using ObjectInputStream = java.io.ObjectInputStream; +using ObjectOutputStream = java.io.ObjectOutputStream; +using ObjectStreamField = java.io.ObjectStreamField; +using StackTraceElement = java.lang.StackTraceElement; +#if !FIRST_PASS +using Throwable = java.lang.Throwable; +#endif + +namespace IKVM.Internal +{ + static class ExceptionHelper + { + private static readonly Dictionary failedTypes = new Dictionary(); + private static readonly Key EXCEPTION_DATA_KEY = new Key(); + private static readonly Exception NOT_REMAPPED = new Exception(); + private static readonly Exception[] EMPTY_THROWABLE_ARRAY = new Exception[0]; + private static readonly bool cleanStackTrace = JVM.SafeGetEnvironmentVariable("IKVM_DISABLE_STACKTRACE_CLEANING") == null; +#if !FIRST_PASS + private static readonly ikvm.@internal.WeakIdentityMap exceptions = new ikvm.@internal.WeakIdentityMap(); + + static ExceptionHelper() + { + // make sure the exceptions map continues to work during AppDomain finalization + GC.SuppressFinalize(exceptions); + } + + [Serializable] + internal sealed class ExceptionInfoHelper + { + [NonSerialized] + private StackTrace tracePart1; + [NonSerialized] + private StackTrace tracePart2; + private StackTraceElement[] stackTrace; + + internal ExceptionInfoHelper(StackTraceElement[] stackTrace) + { + this.stackTrace = stackTrace; + } + + internal ExceptionInfoHelper(StackTrace tracePart1, StackTrace tracePart2) + { + this.tracePart1 = tracePart1; + this.tracePart2 = tracePart2; + } + + [HideFromJava] + internal ExceptionInfoHelper(Exception x, bool captureAdditionalStackTrace) + { + tracePart1 = new StackTrace(x, true); + if (captureAdditionalStackTrace) + { + tracePart2 = new StackTrace(true); + } + } + + [OnSerializing] + private void OnSerializing(StreamingContext context) + { + // make sure the stack trace is computed before serializing + get_StackTrace(null); + } + + private static bool IsPrivateScope(MethodBase mb) + { + return (mb.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope; + } + + internal StackTraceElement[] get_StackTrace(Exception t) + { + lock (this) + { + if (stackTrace == null) + { + List list = new List(); + if (tracePart1 != null) + { + int skip1 = 0; + if (cleanStackTrace && t is java.lang.NullPointerException && tracePart1.FrameCount > 0) + { + // HACK if a NullPointerException originated inside an instancehelper method, + // we assume that the reference the method was called on was really the one that was null, + // so we filter it. + if (tracePart1.GetFrame(0).GetMethod().Name.StartsWith("instancehelper_") && + !GetMethodName(tracePart1.GetFrame(0).GetMethod()).StartsWith("instancehelper_")) + { + skip1 = 1; + } + } + Append(list, tracePart1, skip1, false); + } + if (tracePart2 != null && tracePart2.FrameCount > 0) + { + int skip = 0; + if (cleanStackTrace) + { + // If fillInStackTrace was called (either directly or from the constructor), + // filter out fillInStackTrace and the following constructor frames. + if (tracePart1 == null) + { + MethodBase mb = tracePart2.GetFrame(skip).GetMethod(); + if (mb.DeclaringType == typeof(Throwable) && mb.Name.EndsWith("fillInStackTrace", StringComparison.Ordinal)) + { + skip++; + while (tracePart2.FrameCount > skip) + { + mb = tracePart2.GetFrame(skip).GetMethod(); + if (mb.DeclaringType != typeof(Throwable) || !mb.Name.EndsWith("fillInStackTrace", StringComparison.Ordinal)) + { + break; + } + skip++; + } + while (tracePart2.FrameCount > skip) + { + mb = tracePart2.GetFrame(skip).GetMethod(); + if (mb.Name != ".ctor" || !mb.DeclaringType.IsInstanceOfType(t)) + { + break; + } + skip++; + } + } + } + else + { + // Skip java.lang.Throwable.__ and other mapping methods, because we need to be able to remove the frame + // that called map (if it is the same as where the exception was caught). + while (tracePart2.FrameCount > skip && IsHideFromJava(tracePart2.GetFrame(skip).GetMethod())) + { + skip++; + } + if (tracePart1.FrameCount > 0 && + tracePart2.FrameCount > skip && + tracePart1.GetFrame(tracePart1.FrameCount - 1).GetMethod() == tracePart2.GetFrame(skip).GetMethod()) + { + // skip the caller of the map method + skip++; + } + } + } + Append(list, tracePart2, skip, true); + } + if (cleanStackTrace && list.Count > 0) + { + StackTraceElement elem = list[list.Count - 1]; + if (elem.getClassName() == "java.lang.reflect.Method") + { + list.RemoveAt(list.Count - 1); + } + } + tracePart1 = null; + tracePart2 = null; + this.stackTrace = list.ToArray(); + } + } + return (StackTraceElement[])stackTrace.Clone(); + } + + internal static void Append(List stackTrace, StackTrace st, int skip, bool isLast) + { + for (int i = skip; i < st.FrameCount; i++) + { + StackFrame frame = st.GetFrame(i); + MethodBase m = frame.GetMethod(); + if (m == null) + { + continue; + } + Type type = m.DeclaringType; + if (cleanStackTrace && + (type == null + || typeof(MethodBase).IsAssignableFrom(type) + || type == typeof(RuntimeMethodHandle) + || (type == typeof(Throwable) && m.Name == "instancehelper_fillInStackTrace") + || (m.Name == "ToJava" && typeof(RetargetableJavaException).IsAssignableFrom(type)) + || IsHideFromJava(m) + || IsPrivateScope(m))) // NOTE we assume that privatescope methods are always stubs that we should exclude + { + continue; + } + int lineNumber = frame.GetFileLineNumber(); + if (lineNumber == 0) + { + lineNumber = GetLineNumber(frame); + } + string fileName = frame.GetFileName(); + if (fileName != null) + { + try + { + fileName = new System.IO.FileInfo(fileName).Name; + } + catch + { + // Mono returns "" for frame.GetFileName() and the FileInfo constructor + // doesn't like that + fileName = null; + } + } + if (fileName == null) + { + fileName = GetFileName(frame); + } + stackTrace.Add(new StackTraceElement(getClassNameFromType(type), GetMethodName(m), fileName, IsNative(m) ? -2 : lineNumber)); + } + if (cleanStackTrace && isLast) + { + while (stackTrace.Count > 0 && stackTrace[stackTrace.Count - 1].getClassName().StartsWith("cli.System.Threading.", StringComparison.Ordinal)) + { + stackTrace.RemoveAt(stackTrace.Count - 1); + } + } + } + } +#endif + + [Serializable] + private sealed class Key : ISerializable + { + [Serializable] + private sealed class Helper : IObjectReference + { + [SecurityCritical] + public Object GetRealObject(StreamingContext context) + { + return EXCEPTION_DATA_KEY; + } + } + + [SecurityCritical] + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + info.SetType(typeof(Helper)); + } + } + + private static bool IsNative(MethodBase m) + { + object[] methodFlagAttribs = m.GetCustomAttributes(typeof(ModifiersAttribute), false); + if(methodFlagAttribs.Length == 1) + { + ModifiersAttribute modifiersAttrib = (ModifiersAttribute)methodFlagAttribs[0]; + return (modifiersAttrib.Modifiers & Modifiers.Native) != 0; + } + return false; + } + + private static string GetMethodName(MethodBase mb) + { + object[] attr = mb.GetCustomAttributes(typeof(NameSigAttribute), false); + if(attr.Length == 1) + { + return ((NameSigAttribute)attr[0]).Name; + } + else if(mb.Name == ".ctor") + { + return ""; + } + else if(mb.Name == ".cctor") + { + return ""; + } + else if(mb.Name.StartsWith(NamePrefix.DefaultMethod, StringComparison.Ordinal)) + { + return mb.Name.Substring(NamePrefix.DefaultMethod.Length); + } + else if(mb.Name.StartsWith(NamePrefix.Bridge, StringComparison.Ordinal)) + { + return mb.Name.Substring(NamePrefix.Bridge.Length); + } + else if(mb.IsSpecialName) + { + return UnicodeUtil.UnescapeInvalidSurrogates(mb.Name); + } + else + { + return mb.Name; + } + } + + private static bool IsHideFromJava(MethodBase mb) + { +#if FIRST_PASS + return false; +#else + return (Java_sun_reflect_Reflection.GetHideFromJavaFlags(mb) & HideFromJavaFlags.StackTrace) != 0 + || (mb.DeclaringType == typeof(ikvm.runtime.Util) && mb.Name == "mapException"); +#endif + } + + private static string getClassNameFromType(Type type) + { + if(type == null) + { + return ""; + } + if(ClassLoaderWrapper.IsRemappedType(type)) + { + return DotNetTypeWrapper.GetName(type); + } + TypeWrapper tw = ClassLoaderWrapper.GetWrapperFromType(type); + if(tw != null) + { + if(tw.IsPrimitive) + { + return DotNetTypeWrapper.GetName(type); + } +#if !FIRST_PASS + if(tw.IsUnsafeAnonymous) + { + return tw.ClassObject.getName(); + } +#endif + return tw.Name; + } + return type.FullName; + } + + private static int GetLineNumber(StackFrame frame) + { + int ilOffset = frame.GetILOffset(); + if(ilOffset != StackFrame.OFFSET_UNKNOWN) + { + MethodBase mb = frame.GetMethod(); + if(mb != null && mb.DeclaringType != null) + { + if(ClassLoaderWrapper.IsRemappedType(mb.DeclaringType)) + { + return -1; + } + TypeWrapper tw = ClassLoaderWrapper.GetWrapperFromType(mb.DeclaringType); + if(tw != null) + { + return tw.GetSourceLineNumber(mb, ilOffset); + } + } + } + return -1; + } + + private static string GetFileName(StackFrame frame) + { + MethodBase mb = frame.GetMethod(); + if(mb != null && mb.DeclaringType != null) + { + if(ClassLoaderWrapper.IsRemappedType(mb.DeclaringType)) + { + return null; + } + TypeWrapper tw = ClassLoaderWrapper.GetWrapperFromType(mb.DeclaringType); + if(tw != null) + { + return tw.GetSourceFileName(); + } + } + return null; + } + + // called from map.xml + internal static ObjectStreamField[] getPersistentFields() + { +#if FIRST_PASS + return null; +#else + return new ObjectStreamField[] { + new ObjectStreamField("detailMessage", typeof(global::java.lang.String)), + new ObjectStreamField("cause", typeof(global::java.lang.Throwable)), + new ObjectStreamField("stackTrace", typeof(global::java.lang.StackTraceElement[])), + new ObjectStreamField("suppressedExceptions", typeof(global::java.util.List)) + }; +#endif + } + + internal static void writeObject(Exception x, ObjectOutputStream s) + { +#if !FIRST_PASS + lock (x) + { + ObjectOutputStream.PutField fields = s.putFields(); + Throwable _thisJava = x as Throwable; + if (_thisJava == null) + { + fields.put("detailMessage", x.Message); + fields.put("cause", x.InnerException); + // suppressed exceptions are not supported on CLR exceptions + fields.put("suppressedExceptions", null); + fields.put("stackTrace", getOurStackTrace(x)); + } + else + { + fields.put("detailMessage", _thisJava.detailMessage); + fields.put("cause", _thisJava.cause); + fields.put("suppressedExceptions", _thisJava.suppressedExceptions); + getOurStackTrace(x); + fields.put("stackTrace", _thisJava.stackTrace ?? java.lang.ThrowableHelper.SentinelHolder.STACK_TRACE_SENTINEL); + } + s.writeFields(); + } +#endif + } + + internal static void readObject(Exception x, ObjectInputStream s) + { +#if !FIRST_PASS + lock (x) + { + // when you serialize a .NET exception it gets replaced by a com.sun.xml.internal.ws.developer.ServerSideException, + // so we know that Exception is always a Throwable + Throwable _this = (Throwable)x; + + // this the equivalent of s.defaultReadObject(); + ObjectInputStream.GetField fields = s.readFields(); + object detailMessage = fields.get("detailMessage", null); + object cause = fields.get("cause", null); + ConstructorInfo ctor = typeof(Throwable).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(string), typeof(Exception), typeof(bool), typeof(bool) }, null); + if (cause == _this) + { + ctor.Invoke(_this, new object[] { detailMessage, null, false, false }); + _this.cause = _this; + } + else + { + ctor.Invoke(_this, new object[] { detailMessage, cause, false, false }); + } + _this.stackTrace = (StackTraceElement[])fields.get("stackTrace", null); + _this.suppressedExceptions = (java.util.List)fields.get("suppressedExceptions", null); + + // this is where the rest of the Throwable.readObject() code starts + if (_this.suppressedExceptions != null) + { + java.util.List suppressed = null; + if (_this.suppressedExceptions.isEmpty()) + { + suppressed = Throwable.SUPPRESSED_SENTINEL; + } + else + { + suppressed = new java.util.ArrayList(1); + for (int i = 0; i < _this.suppressedExceptions.size(); i++) + { + Exception entry = (Exception)_this.suppressedExceptions.get(i); + if (entry == null) + { + throw new java.lang.NullPointerException("Cannot suppress a null exception."); + } + if (entry == _this) + { + throw new java.lang.IllegalArgumentException("Self-suppression not permitted"); + } + suppressed.add(entry); + } + } + _this.suppressedExceptions = suppressed; + } + + if (_this.stackTrace != null) + { + if (_this.stackTrace.Length == 0) + { + _this.stackTrace = new StackTraceElement[0]; + } + else if (_this.stackTrace.Length == 1 + && java.lang.ThrowableHelper.SentinelHolder.STACK_TRACE_ELEMENT_SENTINEL.equals(_this.stackTrace[0])) + { + _this.stackTrace = null; + } + else + { + foreach (StackTraceElement elem in _this.stackTrace) + { + if (elem == null) + { + throw new java.lang.NullPointerException("null StackTraceElement in serial stream. "); + } + } + } + } + else + { + _this.stackTrace = new StackTraceElement[0]; + } + } +#endif + } + + internal static string FilterMessage(string message) + { + return message ?? ""; + } + + internal static string GetMessageFromCause(Exception cause) + { +#if FIRST_PASS + return null; +#else + if (cause == null) + { + return ""; + } + return ikvm.extensions.ExtensionMethods.toString(cause); +#endif + } + + internal static string getLocalizedMessage(Exception x) + { +#if FIRST_PASS + return null; +#else + return ikvm.extensions.ExtensionMethods.getMessage(x); +#endif + } + + internal static string toString(Exception x) + { +#if FIRST_PASS + return null; +#else + string message = ikvm.extensions.ExtensionMethods.getLocalizedMessage(x); + if (message == null) + { + return ikvm.extensions.ExtensionMethods.getClass(x).getName(); + } + return ikvm.extensions.ExtensionMethods.getClass(x).getName() + ": " + message; +#endif + } + + internal static Exception getCause(Exception _this) + { +#if FIRST_PASS + return null; +#else + lock (_this) + { + Exception cause = ((Throwable)_this).cause; + return cause == _this ? null : cause; + } +#endif + } + + internal static void checkInitCause(Exception _this, Exception _this_cause, Exception cause) + { +#if !FIRST_PASS + if (_this_cause != _this) + { + throw new java.lang.IllegalStateException("Can't overwrite cause with " + java.util.Objects.toString(cause, "a null"), _this); + } + if (cause == _this) + { + throw new java.lang.IllegalArgumentException("Self-causation not permitted", _this); + } +#endif + } + + internal static void addSuppressed(Exception _this, Exception x) + { +#if !FIRST_PASS + lock (_this) + { + if (_this == x) + { + throw new java.lang.IllegalArgumentException("Self-suppression not permitted", x); + } + if (x == null) + { + throw new java.lang.NullPointerException("Cannot suppress a null exception."); + } + Throwable _thisJava = _this as Throwable; + if (_thisJava == null) + { + // we ignore suppressed exceptions for non-Java exceptions + } + else + { + if (_thisJava.suppressedExceptions == null) + { + return; + } + if (_thisJava.suppressedExceptions == Throwable.SUPPRESSED_SENTINEL) + { + _thisJava.suppressedExceptions = new java.util.ArrayList(); + } + _thisJava.suppressedExceptions.add(x); + } + } +#endif + } + + internal static Exception[] getSuppressed(Exception _this) + { +#if FIRST_PASS + return null; +#else + lock (_this) + { + Throwable _thisJava = _this as Throwable; + if (_thisJava == null) + { + // we ignore suppressed exceptions for non-Java exceptions + return EMPTY_THROWABLE_ARRAY; + } + else + { + if (_thisJava.suppressedExceptions == Throwable.SUPPRESSED_SENTINEL + || _thisJava.suppressedExceptions == null) + { + return EMPTY_THROWABLE_ARRAY; + } + return (Exception[])_thisJava.suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY); + } + } +#endif + } + + internal static int getStackTraceDepth(Exception _this) + { + return getOurStackTrace(_this).Length; + } + + internal static StackTraceElement getStackTraceElement(Exception _this, int index) + { + return getOurStackTrace(_this)[index]; + } + + internal static StackTraceElement[] getOurStackTrace(Exception x) + { +#if FIRST_PASS + return null; +#else + Throwable _this = x as Throwable; + if (_this == null) + { + lock (x) + { + ExceptionInfoHelper eih = null; + IDictionary data = x.Data; + if (data != null && !data.IsReadOnly) + { + lock (data.SyncRoot) + { + eih = (ExceptionInfoHelper)data[EXCEPTION_DATA_KEY]; + } + } + if (eih == null) + { + return Throwable.UNASSIGNED_STACK; + } + return eih.get_StackTrace(x); + } + } + else + { + lock (_this) + { + if (_this.stackTrace == Throwable.UNASSIGNED_STACK + || (_this.stackTrace == null && (_this.tracePart1 != null || _this.tracePart2 != null))) + { + ExceptionInfoHelper eih = new ExceptionInfoHelper(_this.tracePart1, _this.tracePart2); + _this.stackTrace = eih.get_StackTrace(x); + _this.tracePart1 = null; + _this.tracePart2 = null; + } + } + return _this.stackTrace ?? Throwable.UNASSIGNED_STACK; + } +#endif + } + + internal static void setStackTrace(Exception x, StackTraceElement[] stackTrace) + { +#if !FIRST_PASS + StackTraceElement[] copy = (StackTraceElement[])stackTrace.Clone(); + for (int i = 0; i < copy.Length; i++) + { + if (copy[i] == null) + { + throw new java.lang.NullPointerException(); + } + } + SetStackTraceImpl(x, copy); +#endif + } + + private static void SetStackTraceImpl(Exception x, StackTraceElement[] stackTrace) + { +#if !FIRST_PASS + Throwable _this = x as Throwable; + if (_this == null) + { + ExceptionInfoHelper eih = new ExceptionInfoHelper(stackTrace); + IDictionary data = x.Data; + if (data != null && !data.IsReadOnly) + { + lock (data.SyncRoot) + { + data[EXCEPTION_DATA_KEY] = eih; + } + } + } + else + { + lock (_this) + { + if (_this.stackTrace == null && _this.tracePart1 == null && _this.tracePart2 == null) + { + return; + } + _this.stackTrace = stackTrace; + } + } +#endif + } + + // this method is *only* for .NET exceptions (i.e. types not derived from java.lang.Throwable) + [HideFromJava] + internal static void fillInStackTrace(Exception x) + { +#if !FIRST_PASS + lock (x) + { + ExceptionInfoHelper eih = new ExceptionInfoHelper(null, new StackTrace(true)); + IDictionary data = x.Data; + if (data != null && !data.IsReadOnly) + { + lock (data.SyncRoot) + { + data[EXCEPTION_DATA_KEY] = eih; + } + } + } +#endif + } + + // this method is *only* for .NET exceptions (i.e. types not derived from java.lang.Throwable) + internal static void FixateException(Exception x) + { +#if !FIRST_PASS + exceptions.put(x, NOT_REMAPPED); +#endif + } + + internal static Exception UnmapException(Exception x) + { +#if FIRST_PASS + return null; +#else + if (x is Throwable) + { + Exception org = Interlocked.Exchange(ref ((Throwable)x).original, null); + if (org != null) + { + exceptions.put(org, x); + x = org; + } + } + return x; +#endif + } + + [HideFromJava] + private static Exception MapTypeInitializeException(TypeInitializationException t, Type handler) + { +#if FIRST_PASS + return null; +#else + bool wrapped = false; + Exception r = MapException(t.InnerException, true, false); + if (!(r is java.lang.Error)) + { + r = new java.lang.ExceptionInInitializerError(r); + wrapped = true; + } + string type = t.TypeName; + if (failedTypes.ContainsKey(type)) + { + r = new java.lang.NoClassDefFoundError("Could not initialize class " + type); + wrapped = true; + } + if (handler != null && !handler.IsInstanceOfType(r)) + { + return null; + } + failedTypes[type] = type; + if (wrapped) + { + // transplant the stack trace + ((Throwable)r).setStackTrace(new ExceptionInfoHelper(t, true).get_StackTrace(t)); + } + return r; +#endif + } + + private static bool IsInstanceOfType(Exception t, bool remap) + where T : Exception + { +#if FIRST_PASS + return false; +#else + if (!remap && typeof(T) == typeof(Exception)) + { + return !(t is Throwable); + } + return t is T; +#endif + } + + [HideFromJava] + internal static T MapException(Exception x, bool remap, bool unused) + where T : Exception + { +#if FIRST_PASS + return null; +#else + Exception org = x; + bool nonJavaException = !(x is Throwable); + if (nonJavaException && remap) + { + if (x is TypeInitializationException) + { + return (T)MapTypeInitializeException((TypeInitializationException)x, typeof(T)); + } + object obj = exceptions.get(x); + Exception remapped = (Exception)obj; + if (remapped == null) + { + remapped = Throwable.__mapImpl(x); + if (remapped == x) + { + exceptions.put(x, NOT_REMAPPED); + } + else + { + exceptions.put(x, remapped); + x = remapped; + } + } + else if (remapped != NOT_REMAPPED) + { + x = remapped; + } + } + + if (IsInstanceOfType(x, remap)) + { + Throwable t = x as Throwable; + if (t != null) + { + if (!unused && t.tracePart1 == null && t.tracePart2 == null && t.stackTrace == Throwable.UNASSIGNED_STACK) + { + t.tracePart1 = new StackTrace(org, true); + t.tracePart2 = new StackTrace(true); + } + if (t != org) + { + t.original = org; + exceptions.remove(org); + } + } + else + { + IDictionary data = x.Data; + if (data != null && !data.IsReadOnly) + { + lock (data.SyncRoot) + { + if (!data.Contains(EXCEPTION_DATA_KEY)) + { + data.Add(EXCEPTION_DATA_KEY, new ExceptionInfoHelper(x, true)); + } + } + } + } + + if (nonJavaException && !remap) + { + exceptions.put(x, NOT_REMAPPED); + } + return (T)x; + } + return null; +#endif + } + } +} diff --git a/runtime/IKVM.Runtime.8.csproj b/runtime/IKVM.Runtime.8.csproj new file mode 100644 index 0000000..adee8e3 --- /dev/null +++ b/runtime/IKVM.Runtime.8.csproj @@ -0,0 +1,203 @@ + + + Local + 9.0.30729 + 2.0 + {F5C7B588-0403-4AF2-A4DE-5697DE21BC2C} + Debug + AnyCPU + + + + + IKVM.Runtime + + + JScript + Grid + IE50 + false + Library + + + OnBuildSuccess + + + + + + + 2.0 + + + bin\Debug\ + false + 285212672 + false + + + TRACE;DEBUG;EMITTERS + + + true + 4096 + false + + + false + false + false + false + 4 + full + prompt + + + + False + ..\bin\IKVM.OpenJDK.Core.dll + + + False + ..\bin\IKVM.OpenJDK.Management.dll + + + False + ..\bin\IKVM.OpenJDK.Misc.dll + + + False + ..\bin\IKVM.OpenJDK.Util.dll + + + False + .\IKVM.Runtime.JNI.dll + + + System + + + + + + + Code + + + + Code + + + + + Code + + + Code + + + + Code + + + Code + + + Code + + + Code + + + Code + + + + Code + + + Code + + + + Code + + + + + Code + + + + + + + + + + + + + + + + Code + + + + + + Code + + + + + + + + + + + + + + + + + + + + + + + Code + + + + + + + + + Code + + + + Code + + + Code + + + + Code + + + + + + + + + + \ No newline at end of file diff --git a/runtime/IKVM.Runtime.JNI.8.csproj b/runtime/IKVM.Runtime.JNI.8.csproj new file mode 100644 index 0000000..1b0bec6 --- /dev/null +++ b/runtime/IKVM.Runtime.JNI.8.csproj @@ -0,0 +1,84 @@ + + + Local + 9.0.30729 + 2.0 + {CEA4FEC4-1D24-4004-908E-F86C8D7AC772} + Debug + AnyCPU + + + + + IKVM.Runtime.JNI + + + JScript + Grid + IE50 + false + Library + + + OnBuildSuccess + + + + + + + 2.0 + + + bin\Debug\ + true + 285212672 + false + + + TRACE;DEBUG;WHIDBEY;OPENJDK + + + true + 4096 + false + + + false + false + false + false + 4 + full + prompt + + + + False + ..\bin\IKVM.OpenJDK.Core.dll + + + False + .\IKVM.Runtime.dll + + + System + + + + + Code + + + + Code + + + + + + + + + + \ No newline at end of file diff --git a/runtime/JavaException.cs b/runtime/JavaException.cs new file mode 100644 index 0000000..5392fd5 --- /dev/null +++ b/runtime/JavaException.cs @@ -0,0 +1,233 @@ +/* + Copyright (C) 2002-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Reflection; +using IKVM.Internal; + +abstract class RetargetableJavaException : ApplicationException +{ + internal RetargetableJavaException(string msg) : base(msg) + { + } + + internal RetargetableJavaException(string msg, Exception x) : base(msg, x) + { + } + + internal static string Format(string s, object[] args) + { + if (args == null || args.Length == 0) + { + return s; + } + return String.Format(s, args); + } + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + internal abstract Exception ToJava(); +#elif FIRST_PASS + internal virtual Exception ToJava() + { + return null; + } +#endif +} + +// NOTE this is not a Java exception, but instead it wraps a Java exception that +// was thrown by a class loader. It is used so ClassFile.LoadClassHelper() can catch +// Java exceptions and turn them into UnloadableTypeWrappers without inadvertantly +// hiding exceptions caused by coding errors in the IKVM code. +sealed class ClassLoadingException : RetargetableJavaException +{ + internal ClassLoadingException(Exception x, string className) + : base(className, x) + { + } + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + internal override Exception ToJava() + { + if (!(InnerException is java.lang.Error) && !(InnerException is java.lang.RuntimeException)) + { + return new java.lang.NoClassDefFoundError(Message.Replace('.', '/')).initCause(InnerException); + } + return InnerException; + } +#endif +} + +class LinkageError : RetargetableJavaException +{ + internal LinkageError(string msg) : base(msg) + { + } + + internal LinkageError(string msg, Exception x) : base(msg, x) + { + } + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + internal override Exception ToJava() + { + return new java.lang.LinkageError(Message); + } +#endif +} + +sealed class VerifyError : LinkageError +{ + internal VerifyError() : base("") + { + } + + internal VerifyError(string msg) : base(msg) + { + } + + internal VerifyError(string msg, Exception x) : base(msg, x) + { + } + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + internal override Exception ToJava() + { + return new java.lang.VerifyError(Message); + } +#endif +} + +sealed class ClassNotFoundException : RetargetableJavaException +{ + internal ClassNotFoundException(string name) : base(name) + { + } + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + internal override Exception ToJava() + { + return new java.lang.NoClassDefFoundError(Message); + } +#endif +} + +sealed class ClassCircularityError : LinkageError +{ + internal ClassCircularityError(string msg) : base(msg) + { + } + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + internal override Exception ToJava() + { + return new java.lang.ClassCircularityError(Message); + } +#endif +} + +sealed class NoClassDefFoundError : LinkageError +{ + internal NoClassDefFoundError(string msg) : base(msg) + { + } + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + internal override Exception ToJava() + { + return new java.lang.NoClassDefFoundError(Message); + } +#endif +} + +class IncompatibleClassChangeError : LinkageError +{ + internal IncompatibleClassChangeError(string msg) : base(msg) + { + } + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + internal override Exception ToJava() + { + return new java.lang.IncompatibleClassChangeError(Message); + } +#endif +} + +sealed class IllegalAccessError : IncompatibleClassChangeError +{ + internal IllegalAccessError(string msg) : base(msg) + { + } + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + internal override Exception ToJava() + { + return new java.lang.IllegalAccessError(Message); + } +#endif +} + +class ClassFormatError : LinkageError +{ + internal ClassFormatError(string msg, params object[] p) + : base(Format(msg, p)) + { + } + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + internal override Exception ToJava() + { + return new java.lang.ClassFormatError(Message); + } +#endif +} + +sealed class UnsupportedClassVersionError : ClassFormatError +{ + internal UnsupportedClassVersionError(string msg) + : base(msg) + { + } + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + internal override Exception ToJava() + { + return new java.lang.UnsupportedClassVersionError(Message); + } +#endif +} + +sealed class JavaSecurityException : RetargetableJavaException +{ + internal JavaSecurityException(string msg) + : base(msg) + { + } + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + internal override Exception ToJava() + { + return new java.lang.SecurityException(Message); + } +#endif +} diff --git a/runtime/JniAssemblyInfo.cs b/runtime/JniAssemblyInfo.cs new file mode 100644 index 0000000..6d7576a --- /dev/null +++ b/runtime/JniAssemblyInfo.cs @@ -0,0 +1,34 @@ +/* + Copyright (C) 2002-2008 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("IKVM.NET Runtime JNI Layer")] +[assembly: AssemblyDescription("JVM for Mono and .NET")] + +#if SIGNCODE +[assembly: InternalsVisibleTo("IKVM.Runtime, PublicKey=0024000004800000940000000602000000240000525341310004000001000100DD6B140E5209CAE3D1C710030021EF589D0F00D05ACA8771101A7E99E10EE063E66040DF96E6F842F717BFC5B62D2EC2B62CEB0282E4649790DACB424DB29B68ADC7EAEAB0356FCE04702379F84400B8427EDBB33DAB8720B9F16A42E2CDB87F885EF413DBC4229F2BD157C9B8DC2CD14866DEC5F31C764BFB9394CC3C60E6C0")] +#else +[assembly: InternalsVisibleTo("IKVM.Runtime")] +#endif diff --git a/runtime/JniAssemblyInfo.cs.in b/runtime/JniAssemblyInfo.cs.in new file mode 100644 index 0000000..248c9bb --- /dev/null +++ b/runtime/JniAssemblyInfo.cs.in @@ -0,0 +1,34 @@ +/* + Copyright (C) 2002-2008 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("IKVM.NET Runtime JNI Layer")] +[assembly: AssemblyDescription("JVM for Mono and .NET")] + +#if SIGNCODE +[assembly: InternalsVisibleTo("IKVM.Runtime, PublicKey=@PUBLICKEY@")] +#else +[assembly: InternalsVisibleTo("IKVM.Runtime")] +#endif diff --git a/runtime/JniInterface.cs b/runtime/JniInterface.cs new file mode 100644 index 0000000..9c0ae75 --- /dev/null +++ b/runtime/JniInterface.cs @@ -0,0 +1,3790 @@ +/* + Copyright (C) 2002-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using System.Reflection; +using System.Runtime.InteropServices; +using IKVM.Internal; + +// Java type JNI aliases +using jboolean = System.SByte; +using jbyte = System.SByte; +using jchar = System.UInt16; +using jshort = System.Int16; +using jint = System.Int32; +using jsize = System.Int32; +using jlong = System.Int64; +using jfloat = System.Single; +using jdouble = System.Double; +using jobject = System.IntPtr; +using jstring = System.IntPtr; +using jclass = System.IntPtr; +using jarray = System.IntPtr; +using jobjectArray = System.IntPtr; +using jbooleanArray = System.IntPtr; +using jbyteArray = System.IntPtr; +using jcharArray = System.IntPtr; +using jshortArray = System.IntPtr; +using jintArray = System.IntPtr; +using jlongArray = System.IntPtr; +using jfloatArray = System.IntPtr; +using jdoubleArray = System.IntPtr; +using jthrowable = System.IntPtr; +using jweak = System.IntPtr; +using jmethodID = System.IntPtr; +using jfieldID = System.IntPtr; + +namespace IKVM.Runtime +{ + [StructLayout(LayoutKind.Sequential)] + unsafe struct JavaVMOption + { + internal byte* optionString; + internal void* extraInfo; + } + + [StructLayout(LayoutKind.Sequential)] + unsafe struct JavaVMInitArgs + { + internal jint version; + internal jint nOptions; + internal JavaVMOption* options; + internal jboolean ignoreUnrecognized; + } + + public unsafe sealed class JNI + { + internal static volatile bool jvmCreated; + internal static volatile bool jvmDestroyed; + internal const string METHOD_PTR_FIELD_PREFIX = "__"; + + internal static bool IsSupportedJniVersion(jint version) + { + return version == JNIEnv.JNI_VERSION_1_1 + || version == JNIEnv.JNI_VERSION_1_2 + || version == JNIEnv.JNI_VERSION_1_4 + || version == JNIEnv.JNI_VERSION_1_6 + || version == JNIEnv.JNI_VERSION_1_8 + ; + } + + public static int CreateJavaVM(void* ppvm, void* ppenv, void* args) + { + JavaVMInitArgs* pInitArgs = (JavaVMInitArgs*)args; + // we don't support the JDK 1.1 JavaVMInitArgs + if(!IsSupportedJniVersion(pInitArgs->version) || pInitArgs->version == JNIEnv.JNI_VERSION_1_1) + { + return JNIEnv.JNI_EVERSION; + } + if(jvmCreated) + { + return JNIEnv.JNI_ERR; + } + System.Collections.Hashtable props = new System.Collections.Hashtable(); + for(int i = 0; i < pInitArgs->nOptions; i++) + { + string option = JNIEnv.StringFromOEM(pInitArgs->options[i].optionString); + if(option.StartsWith("-D")) + { + int idx = option.IndexOf('=', 2); + props[option.Substring(2, idx - 2)] = option.Substring(idx + 1); + } + else if(option.StartsWith("-verbose")) + { + // ignore + } + else if(option == "vfprintf" || option == "exit" || option == "abort") + { + // not supported + } + else if(pInitArgs->ignoreUnrecognized == JNIEnv.JNI_FALSE) + { + return JNIEnv.JNI_ERR; + } + } + + ikvm.runtime.Startup.setProperties(props); + + // initialize the class library + java.lang.Thread.currentThread(); + + *((void**)ppvm) = JavaVM.pJavaVM; + return JavaVM.AttachCurrentThread(JavaVM.pJavaVM, (void**)ppenv, null); + } + + public static int GetDefaultJavaVMInitArgs(void* vm_args) + { + // This is only used for JDK 1.1 JavaVMInitArgs, and we don't support those. + return JNIEnv.JNI_ERR; + } + + public static int GetCreatedJavaVMs(void* ppvmBuf, int bufLen, int* nVMs) + { + if(jvmCreated) + { + if(bufLen >= 1) + { + *((void**)ppvmBuf) = JavaVM.pJavaVM; + } + if(nVMs != null) + { + *nVMs = 1; + } + } + else if(nVMs != null) + { + *nVMs = 0; + } + return JNIEnv.JNI_OK; + } + + public struct Frame + { + private JNIEnv.ManagedJNIEnv env; + private JNIEnv.ManagedJNIEnv.FrameState prevFrameState; + + internal ClassLoaderWrapper Enter(ClassLoaderWrapper loader) + { + Enter((ikvm.@internal.CallerID)null); + ClassLoaderWrapper prev = env.classLoader; + env.classLoader = loader; + return prev; + } + + internal void Leave(ClassLoaderWrapper prev) + { + env.classLoader = prev; + Leave(); + } + + public IntPtr Enter(ikvm.@internal.CallerID callerID) + { + env = TlsHack.ManagedJNIEnv; + if(env == null) + { + env = JNIEnv.CreateJNIEnv()->GetManagedJNIEnv(); + } + prevFrameState = env.Enter(callerID); + return (IntPtr)(void*)env.pJNIEnv; + } + + public void Leave() + { + Exception x = env.Leave(prevFrameState); + if(x != null) + { + throw x; + } + } + + public static IntPtr GetFuncPtr(ikvm.@internal.CallerID callerID, string clazz, string name, string sig) + { + ClassLoaderWrapper loader = ClassLoaderWrapper.FromCallerID(callerID); + int sp = 0; + for(int i = 1; sig[i] != ')'; i++) + { + switch(sig[i]) + { + case '[': + sp += IntPtr.Size; + while(sig[++i] == '['); + if(sig[i] == 'L') + { + while(sig[++i] != ';'); + } + break; + case 'L': + sp += IntPtr.Size; + while(sig[++i] != ';'); + break; + case 'J': + case 'D': + sp += 8; + break; + case 'F': + case 'I': + case 'C': + case 'Z': + case 'S': + case 'B': + sp += 4; + break; + default: + Debug.Assert(false); + break; + } + } + string mangledClass = JniMangle(clazz); + string mangledName = JniMangle(name); + string mangledSig = JniMangle(sig.Substring(1, sig.IndexOf(')') - 1)); + string shortMethodName = String.Format("Java_{0}_{1}", mangledClass, mangledName); + string longMethodName = String.Format("Java_{0}_{1}__{2}", mangledClass, mangledName, mangledSig); + Tracer.Info(Tracer.Jni, "Linking native method: {0}.{1}{2}, class loader = {3}, short = {4}, long = {5}, args = {6}", + clazz, name, sig, loader, shortMethodName, longMethodName, sp + 2 * IntPtr.Size); + lock(JniHelper.JniLock) + { + foreach(IntPtr p in loader.GetNativeLibraries()) + { + IntPtr pfunc = NativeLibrary.GetProcAddress(p, shortMethodName, sp + 2 * IntPtr.Size); + if(pfunc != IntPtr.Zero) + { + Tracer.Info(Tracer.Jni, "Native method {0}.{1}{2} found in library 0x{3:X} (short)", clazz, name, sig, p.ToInt64()); + return pfunc; + } + pfunc = NativeLibrary.GetProcAddress(p, longMethodName, sp + 2 * IntPtr.Size); + if(pfunc != IntPtr.Zero) + { + Tracer.Info(Tracer.Jni, "Native method {0}.{1}{2} found in library 0x{3:X} (long)", clazz, name, sig, p.ToInt64()); + return pfunc; + } + } + } + string msg = string.Format("{0}.{1}{2}", clazz, name, sig); + Tracer.Error(Tracer.Jni, "UnsatisfiedLinkError: {0}", msg); + throw new java.lang.UnsatisfiedLinkError(msg); + } + + private static string JniMangle(string name) + { + StringBuilder sb = new StringBuilder(); + foreach(char c in name) + { + if(c == '/') + { + sb.Append('_'); + } + else if(c == '_') + { + sb.Append("_1"); + } + else if(c == ';') + { + sb.Append("_2"); + } + else if(c == '[') + { + sb.Append("_3"); + } + else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) + { + sb.Append(c); + } + else + { + sb.Append(String.Format("_0{0:x4}", (int)c)); + } + } + return sb.ToString(); + } + + public IntPtr MakeLocalRef(object obj) + { + return env.MakeLocalRef(obj); + } + + // NOTE this method has the wrong name, it should unwrap *any* jobject reference type (local and global) + public object UnwrapLocalRef(IntPtr p) + { + return JNIEnv.UnwrapRef(env, p); + } + } + } + + abstract unsafe class NativeLibrary + { + private NativeLibrary() { } + private static readonly NativeLibrary impl; + + static NativeLibrary() + { + try + { + if (Environment.OSVersion.Platform == PlatformID.Win32NT) + { + if (IntPtr.Size == 4) + { + impl = new Win32_x86(); + } + else + { + impl = new Win32_x64(); + } + // call a method to trigger the native library load + // (if this fails, we fall back to the classic native library) + impl._MarshalDelegate(null); + } + else + { + impl = new Classic(); + } + } + catch (DllNotFoundException) + { + impl = new Classic(); + } + catch (BadImageFormatException) + { + impl = new Classic(); + } + } + + private sealed class Win32_x86 : NativeLibrary + { + private const string library = "ikvm-native-win32-x86"; + + [DllImport(library, SetLastError = true)] + private static extern IntPtr ikvm_LoadLibrary(string filename); + [DllImport(library)] + private static extern void ikvm_FreeLibrary(IntPtr handle); + [DllImport(library)] + private static extern IntPtr ikvm_GetProcAddress(IntPtr handle, string name, int argc); + [DllImport(library)] + private static extern int ikvm_CallOnLoad(IntPtr method, void* jvm, void* reserved); + [DllImport(library)] + private static extern void** ikvm_GetJNIEnvVTable(); + [DllImport(library)] + private static extern void* ikvm_MarshalDelegate(Delegate d); + + protected override IntPtr _LoadLibrary(string filename) + { + return ikvm_LoadLibrary(filename); + } + + protected override void _FreeLibrary(IntPtr handle) + { + ikvm_FreeLibrary(handle); + } + + protected override IntPtr _GetProcAddress(IntPtr handle, string name, int argc) + { + return ikvm_GetProcAddress(handle, name, argc); + } + + protected override int _CallOnLoad(IntPtr method, void* jvm, void* reserved) + { + return ikvm_CallOnLoad(method, jvm, reserved); + } + + protected override void** _GetJNIEnvVTable() + { + return ikvm_GetJNIEnvVTable(); + } + + protected override void* _MarshalDelegate(Delegate d) + { + return ikvm_MarshalDelegate(d); + } + } + + private sealed class Win32_x64 : NativeLibrary + { + private const string library = "ikvm-native-win32-x64"; + + [DllImport(library, SetLastError = true)] + private static extern IntPtr ikvm_LoadLibrary(string filename); + [DllImport(library)] + private static extern void ikvm_FreeLibrary(IntPtr handle); + [DllImport(library)] + private static extern IntPtr ikvm_GetProcAddress(IntPtr handle, string name, int argc); + [DllImport(library)] + private static extern int ikvm_CallOnLoad(IntPtr method, void* jvm, void* reserved); + [DllImport(library)] + private static extern void** ikvm_GetJNIEnvVTable(); + [DllImport(library)] + private static extern void* ikvm_MarshalDelegate(Delegate d); + + protected override IntPtr _LoadLibrary(string filename) + { + return ikvm_LoadLibrary(filename); + } + + protected override void _FreeLibrary(IntPtr handle) + { + ikvm_FreeLibrary(handle); + } + + protected override IntPtr _GetProcAddress(IntPtr handle, string name, int argc) + { + return ikvm_GetProcAddress(handle, name, argc); + } + + protected override int _CallOnLoad(IntPtr method, void* jvm, void* reserved) + { + return ikvm_CallOnLoad(method, jvm, reserved); + } + + protected override void** _GetJNIEnvVTable() + { + return ikvm_GetJNIEnvVTable(); + } + + protected override void* _MarshalDelegate(Delegate d) + { + return ikvm_MarshalDelegate(d); + } + } + + private sealed class Classic : NativeLibrary + { + private const string library = "ikvm-native"; + + [DllImport(library, SetLastError = true)] + private static extern IntPtr ikvm_LoadLibrary(string filename); + [DllImport(library)] + private static extern void ikvm_FreeLibrary(IntPtr handle); + [DllImport(library)] + private static extern IntPtr ikvm_GetProcAddress(IntPtr handle, string name, int argc); + [DllImport(library)] + private static extern int ikvm_CallOnLoad(IntPtr method, void* jvm, void* reserved); + [DllImport(library)] + private static extern void** ikvm_GetJNIEnvVTable(); + [DllImport(library)] + private static extern void* ikvm_MarshalDelegate(Delegate d); + + protected override IntPtr _LoadLibrary(string filename) + { + return ikvm_LoadLibrary(filename); + } + + protected override void _FreeLibrary(IntPtr handle) + { + ikvm_FreeLibrary(handle); + } + + protected override IntPtr _GetProcAddress(IntPtr handle, string name, int argc) + { + return ikvm_GetProcAddress(handle, name, argc); + } + + protected override int _CallOnLoad(IntPtr method, void* jvm, void* reserved) + { + return ikvm_CallOnLoad(method, jvm, reserved); + } + + protected override void** _GetJNIEnvVTable() + { + return ikvm_GetJNIEnvVTable(); + } + + protected override void* _MarshalDelegate(Delegate d) + { + return ikvm_MarshalDelegate(d); + } + } + + protected abstract IntPtr _LoadLibrary(string filename); + protected abstract void _FreeLibrary(IntPtr handle); + protected abstract IntPtr _GetProcAddress(IntPtr handle, string name, int argc); + protected abstract int _CallOnLoad(IntPtr method, void* jvm, void* reserved); + protected abstract void** _GetJNIEnvVTable(); + protected abstract void* _MarshalDelegate(Delegate d); + + internal static IntPtr LoadLibrary(string filename) + { + return impl._LoadLibrary(filename); + } + + internal static void FreeLibrary(IntPtr handle) + { + impl._FreeLibrary(handle); + } + + internal static IntPtr GetProcAddress(IntPtr handle, string name, int argc) + { + return impl._GetProcAddress(handle, name, argc); + } + + internal static int CallOnLoad(IntPtr method, void* jvm, void* reserved) + { + return impl._CallOnLoad(method, jvm, reserved); + } + + internal static void** GetJNIEnvVTable() + { + return impl._GetJNIEnvVTable(); + } + + internal static void* MarshalDelegate(Delegate d) + { + return impl._MarshalDelegate(d); + } + } + + sealed class JniHelper + { + private static List nativeLibraries = new List(); + internal static readonly object JniLock = new object(); + + // MONOBUG with mcs we can't pass ClassLoaderWrapper from IKVM.Runtime.dll to IKVM.Runtime.JNI.dll + internal unsafe static long LoadLibrary(string filename, object loader) + { + return LoadLibrary(filename, (ClassLoaderWrapper)loader); + } + + // MONOBUG with mcs we can't pass ClassLoaderWrapper from IKVM.Runtime.dll to IKVM.Runtime.JNI.dll + internal static void UnloadLibrary(long handle, object loader) + { + UnloadLibrary(handle, (ClassLoaderWrapper)loader); + } + + private unsafe static long LoadLibrary(string filename, ClassLoaderWrapper loader) + { + Tracer.Info(Tracer.Jni, "loadLibrary: {0}, class loader: {1}", filename, loader); + lock(JniLock) + { + IntPtr p = NativeLibrary.LoadLibrary(filename); + if(p == IntPtr.Zero) + { + Tracer.Info(Tracer.Jni, "Failed to load library: path = '{0}', error = {1}, message = {2}", filename, + Marshal.GetLastWin32Error(), new System.ComponentModel.Win32Exception().Message); + return 0; + } + try + { + foreach(IntPtr tmp in loader.GetNativeLibraries()) + { + if(tmp == p) + { + // the library was already loaded by the current class loader, + // no need to do anything + NativeLibrary.FreeLibrary(p); + Tracer.Warning(Tracer.Jni, "Library was already loaded: {0}", filename); + return p.ToInt64(); + } + } + if(nativeLibraries.Contains(p)) + { + string msg = string.Format("Native library {0} already loaded in another classloader", filename); + Tracer.Error(Tracer.Jni, "UnsatisfiedLinkError: {0}", msg); + throw new java.lang.UnsatisfiedLinkError(msg); + } + Tracer.Info(Tracer.Jni, "Library loaded: {0}, handle = 0x{1:X}", filename, p.ToInt64()); + IntPtr onload = NativeLibrary.GetProcAddress(p, "JNI_OnLoad", IntPtr.Size * 2); + if(onload != IntPtr.Zero) + { + Tracer.Info(Tracer.Jni, "Calling JNI_OnLoad on: {0}", filename); + JNI.Frame f = new JNI.Frame(); + int version; + ClassLoaderWrapper prevLoader = f.Enter(loader); + try + { + // TODO on Whidbey we should be able to use Marshal.GetDelegateForFunctionPointer to call OnLoad + version = NativeLibrary.CallOnLoad(onload, JavaVM.pJavaVM, null); + Tracer.Info(Tracer.Jni, "JNI_OnLoad returned: 0x{0:X8}", version); + } + finally + { + f.Leave(prevLoader); + } + if(!JNI.IsSupportedJniVersion(version)) + { + string msg = string.Format("Unsupported JNI version 0x{0:X} required by {1}", version, filename); + Tracer.Error(Tracer.Jni, "UnsatisfiedLinkError: {0}", msg); + throw new java.lang.UnsatisfiedLinkError(msg); + } + } + nativeLibraries.Add(p); + loader.RegisterNativeLibrary(p); + return p.ToInt64(); + } + catch + { + NativeLibrary.FreeLibrary(p); + throw; + } + } + } + + private unsafe static void UnloadLibrary(long handle, ClassLoaderWrapper loader) + { + lock (JniLock) + { + Tracer.Info(Tracer.Jni, "Unloading library: handle = 0x{0:X}, class loader = {1}", handle, loader); + IntPtr p = (IntPtr)handle; + IntPtr onunload = NativeLibrary.GetProcAddress(p, "JNI_OnUnload", IntPtr.Size * 2); + if (onunload != IntPtr.Zero) + { + Tracer.Info(Tracer.Jni, "Calling JNI_OnUnload on: handle = 0x{0:X}", handle); + JNI.Frame f = new JNI.Frame(); + ClassLoaderWrapper prevLoader = f.Enter(loader); + try + { + // TODO on Whidbey we should be able to use Marshal.GetDelegateForFunctionPointer to call OnLoad + NativeLibrary.CallOnLoad(onunload, JavaVM.pJavaVM, null); + } + finally + { + f.Leave(prevLoader); + } + } + nativeLibraries.Remove(p); + loader.UnregisterNativeLibrary(p); + NativeLibrary.FreeLibrary((IntPtr)handle); + } + } + } + + static class GlobalRefs + { + internal static System.Collections.ArrayList globalRefs = new System.Collections.ArrayList(); + internal static readonly object weakRefLock = new object(); + internal static GCHandle[] weakRefs = new GCHandle[16]; + + internal static object Unwrap(int i) + { + i = -i; + if ((i & (1 << 30)) != 0) + { + lock (GlobalRefs.weakRefLock) + { + return GlobalRefs.weakRefs[i - (1 << 30)].Target; + } + } + else + { + lock (GlobalRefs.globalRefs) + { + return GlobalRefs.globalRefs[i - 1]; + } + } + } + } + + unsafe class VtableBuilder + { + delegate int pf_int_IntPtr(JNIEnv* pEnv, IntPtr p); + delegate IntPtr pf_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p); + delegate void pf_void_IntPtr(JNIEnv* pEnv, IntPtr p); + delegate IntPtr pf_IntPtr(JNIEnv* pEnv); + delegate void pf_void(JNIEnv* pEnv); + delegate sbyte pf_sbyte(JNIEnv* pEnv); + delegate IntPtr pf_IntPtr_pbyte(JNIEnv* pEnv, byte* p); + delegate int pf_int(JNIEnv* pEnv); + delegate IntPtr pf_IntPtr_pbyte_IntPtr_psbyte_IntPtr(JNIEnv* pEnv, byte* p1, IntPtr p2, sbyte* p3, int p4); + delegate IntPtr pf_IntPtr_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2); + delegate jchar* pf_pjchar_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2); + delegate void pf_void_IntPtr_pvoid_int(JNIEnv* pEnv, IntPtr p1, void* p2, int p3); + delegate void* pf_pvoid_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2); + delegate int pf_int_IntPtr_pbyte(JNIEnv* pEnv, IntPtr p1, byte* p2); + delegate void pf_void_pbyte(JNIEnv* pEnv, byte* p1); + delegate IntPtr pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv* pEnv, IntPtr p1, byte* p2, byte* p3); + delegate int pf_int_IntPtr_pJNINativeMethod_int(JNIEnv* pEnv, IntPtr p1, JNIEnv.JNINativeMethod* p2, int p3); + delegate int pf_int_ppJavaVM(JNIEnv* pEnv, JavaVM** ppJavaVM); + delegate sbyte pf_sbyte_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2); + delegate short pf_short_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2); + delegate ushort pf_ushort_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2); + delegate int pf_int_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2); + delegate long pf_long_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2); + delegate float pf_float_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2); + delegate double pf_double_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2); + delegate void pf_void_IntPtr_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3); + delegate void pf_void_IntPtr_IntPtr_sbyte(JNIEnv* pEnv, IntPtr p1, IntPtr p2, sbyte p3); + delegate void pf_void_IntPtr_IntPtr_short(JNIEnv* pEnv, IntPtr p1, IntPtr p2, short p3); + delegate void pf_void_IntPtr_IntPtr_ushort(JNIEnv* pEnv, IntPtr p1, IntPtr p2, ushort p3); + delegate void pf_void_IntPtr_IntPtr_int(JNIEnv* pEnv, IntPtr p1, IntPtr p2, int p3); + delegate void pf_void_IntPtr_IntPtr_long(JNIEnv* pEnv, IntPtr p1, IntPtr p2, long p3); + delegate void pf_void_IntPtr_IntPtr_float(JNIEnv* pEnv, IntPtr p1, IntPtr p2, float p3); + delegate void pf_void_IntPtr_IntPtr_double(JNIEnv* pEnv, IntPtr p1, IntPtr p2, double p3); + delegate IntPtr pf_IntPtr_pjchar_int(JNIEnv* pEnv, jchar* p1, int p2); + delegate void pf_void_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2); + delegate void pf_void_IntPtr_pjchar(JNIEnv* pEnv, IntPtr p1, jchar* p2); + delegate IntPtr pf_IntPtr_int_IntPtr_IntPtr(JNIEnv* pEnv, int p1, IntPtr p2, IntPtr p3); + delegate IntPtr pf_IntPtr_IntPtr_int(JNIEnv* pEnv, IntPtr p1, int p2); + delegate void pf_void_IntPtr_int_IntPtr(JNIEnv* pEnv, IntPtr p1, int p2, IntPtr p3); + delegate IntPtr pf_IntPtr_int(JNIEnv* pEnv, int p1); + delegate void pf_void_IntPtr_int_int_IntPtr(JNIEnv* pEnv, IntPtr p1, int p2, int p3, IntPtr p4); + delegate IntPtr pf_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3); + delegate sbyte pf_sbyte_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3); + delegate short pf_short_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3); + delegate ushort pf_ushort_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3); + delegate int pf_int_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3); + delegate long pf_long_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3); + delegate float pf_float_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3); + delegate double pf_double_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3); + delegate void pf_void_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3); + delegate IntPtr pf_IntPtr_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4); + delegate sbyte pf_sbyte_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4); + delegate ushort pf_ushort_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4); + delegate short pf_short_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4); + delegate int pf_int_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4); + delegate long pf_long_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4); + delegate float pf_float_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4); + delegate double pf_double_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4); + delegate void pf_void_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4); + delegate byte* pf_pbyte_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2); + delegate void pf_void_IntPtr_pbyte(JNIEnv* pEnv, IntPtr p1, byte* p2); + delegate jboolean* pf_pjboolean_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2); + delegate jbyte* pf_pjbyte_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2); + delegate jshort* pf_pjshort_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2); + delegate jint* pf_pjint_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2); + delegate jlong* pf_pjlong_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2); + delegate jfloat* pf_pjfloat_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2); + delegate jdouble* pf_pjdouble_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2); + delegate void pf_void_IntPtr_pjboolean_int(JNIEnv* pEnv, IntPtr p1, jboolean* p2, int p3); + delegate void pf_void_IntPtr_pjbyte_int(JNIEnv* pEnv, IntPtr p1, jbyte* p2, int p3); + delegate void pf_void_IntPtr_pjchar_int(JNIEnv* pEnv, IntPtr p1, jchar* p2, int p3); + delegate void pf_void_IntPtr_pjshort_int(JNIEnv* pEnv, IntPtr p1, jshort* p2, int p3); + delegate void pf_void_IntPtr_pjint_int(JNIEnv* pEnv, IntPtr p1, jint* p2, int p3); + delegate void pf_void_IntPtr_pjlong_int(JNIEnv* pEnv, IntPtr p1, jlong* p2, int p3); + delegate void pf_void_IntPtr_pjfloat_int(JNIEnv* pEnv, IntPtr p1, jfloat* p2, int p3); + delegate void pf_void_IntPtr_pjdouble_int(JNIEnv* pEnv, IntPtr p1, jdouble* p2, int p3); + delegate int pf_int_int(JNIEnv* pEnv, int p1); + delegate IntPtr pf_IntPtr_IntPtr_long(JNIEnv* pEnv, IntPtr p1, long p2); + delegate long pf_long_IntPtr(JNIEnv* pEnv, IntPtr p1); + delegate IntPtr pf_IntPtr_IntPtr_IntPtr_sbyte(JNIEnv* pEnv, IntPtr p1, IntPtr p2, sbyte p3); + + internal static void* vtable; + + static VtableBuilder() + { + JNI.jvmCreated = true; + // JNIEnv + void** pmcpp = NativeLibrary.GetJNIEnvVTable(); + void** p = (void**)JniMem.Alloc(IntPtr.Size * vtableDelegates.Length); + for(int i = 0; i < vtableDelegates.Length; i++) + { + if(vtableDelegates[i] != null) + { + // TODO on Whidbey we can use Marshal.GetFunctionPointerForDelegate + p[i] = NativeLibrary.MarshalDelegate(vtableDelegates[i]); + } + else + { + p[i] = pmcpp[i]; + } + } + vtable = p; + } + + static Delegate[] vtableDelegates = + { + new pf_int_IntPtr_pbyte(JNIEnv.GetMethodArgs), //virtual void JNICALL reserved0(); + null, //virtual void JNICALL reserved1(); + null, //virtual void JNICALL reserved2(); + null, //virtual void JNICALL reserved3(); + + new pf_int(JNIEnv.GetVersion), //virtual jint JNICALL GetVersion(); + + new pf_IntPtr_pbyte_IntPtr_psbyte_IntPtr(JNIEnv.DefineClass), //virtual jclass JNICALL DefineClass(const char *name, jobject loader, const jbyte *buf, jsize len); + new pf_IntPtr_pbyte(JNIEnv.FindClass), //virtual jclass JNICALL FindClass(const char *name); + + new pf_IntPtr_IntPtr(JNIEnv.FromReflectedMethod), //virtual jmethodID JNICALL FromReflectedMethod(jobject method); + new pf_IntPtr_IntPtr(JNIEnv.FromReflectedField), //virtual jfieldID JNICALL FromReflectedField(jobject field); + new pf_IntPtr_IntPtr_IntPtr_sbyte(JNIEnv.ToReflectedMethod), //virtual jobject JNICALL ToReflectedMethod(jclass clazz, jmethodID methodID, jboolean isStatic); + + new pf_IntPtr_IntPtr(JNIEnv.GetSuperclass), //virtual jclass JNICALL GetSuperclass(jclass sub); + new pf_sbyte_IntPtr_IntPtr(JNIEnv.IsAssignableFrom), //virtual jboolean JNICALL IsAssignableFrom(jclass sub, jclass sup); + + new pf_IntPtr_IntPtr_IntPtr_sbyte(JNIEnv.ToReflectedField), //virtual jobject JNICALL ToReflectedField(jclass clazz, jfieldID fieldID, jboolean isStatic); + + new pf_int_IntPtr(JNIEnv.Throw), //virtual jint JNICALL Throw(jthrowable obj); + new pf_int_IntPtr_pbyte(JNIEnv.ThrowNew), //virtual jint JNICALL ThrowNew(jclass clazz, const char *msg); + new pf_IntPtr(JNIEnv.ExceptionOccurred), //virtual jthrowable JNICALL ExceptionOccurred(); + new pf_void(JNIEnv.ExceptionDescribe), //virtual void JNICALL ExceptionDescribe(); + new pf_void(JNIEnv.ExceptionClear), //virtual void JNICALL ExceptionClear(); + new pf_void_pbyte(JNIEnv.FatalError), //virtual void JNICALL FatalError(const char *msg); + + new pf_int_int(JNIEnv.PushLocalFrame), //virtual jint JNICALL PushLocalFrame(jint capacity); + new pf_IntPtr_IntPtr(JNIEnv.PopLocalFrame), //virtual jobject JNICALL PopLocalFrame(jobject result); + + new pf_IntPtr_IntPtr(JNIEnv.NewGlobalRef), //virtual jobject JNICALL NewGlobalRef(jobject lobj); + new pf_void_IntPtr(JNIEnv.DeleteGlobalRef), //virtual void JNICALL DeleteGlobalRef(jobject gref); + new pf_void_IntPtr(JNIEnv.DeleteLocalRef), //virtual void JNICALL DeleteLocalRef(jobject obj); + new pf_sbyte_IntPtr_IntPtr(JNIEnv.IsSameObject), //virtual jboolean JNICALL IsSameObject(jobject obj1, jobject obj2); + + new pf_IntPtr_IntPtr(JNIEnv.NewLocalRef), //virtual jobject JNICALL NewLocalRef(jobject ref); + new pf_int_int(JNIEnv.EnsureLocalCapacity), //virtual jint JNICALL EnsureLocalCapacity(jint capacity); + + new pf_IntPtr_IntPtr(JNIEnv.AllocObject), //virtual jobject JNICALL AllocObject(jclass clazz); + null, //virtual jobject JNICALL NewObject(jclass clazz, jmethodID methodID, ...); + null, //virtual jobject JNICALL NewObjectV(jclass clazz, jmethodID methodID, va_list args); + new pf_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.NewObjectA), //virtual jobject JNICALL NewObjectA(jclass clazz, jmethodID methodID, jvalue *args); + + new pf_IntPtr_IntPtr(JNIEnv.GetObjectClass), //virtual jclass JNICALL GetObjectClass(jobject obj); + new pf_sbyte_IntPtr_IntPtr(JNIEnv.IsInstanceOf), //virtual jboolean JNICALL IsInstanceOf(jobject obj, jclass clazz); + + new pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv.GetMethodID), //virtual jmethodID JNICALL GetMethodID(jclass clazz, const char *name, const char *sig); + + null, //virtual jobject JNICALL CallObjectMethod(jobject obj, jmethodID methodID, ...); + null, //virtual jobject JNICALL CallObjectMethodV(jobject obj, jmethodID methodID, va_list args); + new pf_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallObjectMethodA), //virtual jobject JNICALL CallObjectMethodA(jobject obj, jmethodID methodID, jvalue * args); + + null, //virtual jboolean JNICALL CallBooleanMethod(jobject obj, jmethodID methodID, ...); + null, //virtual jboolean JNICALL CallBooleanMethodV(jobject obj, jmethodID methodID, va_list args); + new pf_sbyte_IntPtr_IntPtr_pjvalue(JNIEnv.CallBooleanMethodA), //virtual jboolean JNICALL CallBooleanMethodA(jobject obj, jmethodID methodID, jvalue * args); + + null, //virtual jbyte JNICALL CallByteMethod(jobject obj, jmethodID methodID, ...); + null, //virtual jbyte JNICALL CallByteMethodV(jobject obj, jmethodID methodID, va_list args); + new pf_sbyte_IntPtr_IntPtr_pjvalue(JNIEnv.CallByteMethodA), //virtual jbyte JNICALL CallByteMethodA(jobject obj, jmethodID methodID, jvalue *args); + + null, //virtual jchar JNICALL CallCharMethod(jobject obj, jmethodID methodID, ...); + null, //virtual jchar JNICALL CallCharMethodV(jobject obj, jmethodID methodID, va_list args); + new pf_ushort_IntPtr_IntPtr_pjvalue(JNIEnv.CallCharMethodA), //virtual jchar JNICALL CallCharMethodA(jobject obj, jmethodID methodID, jvalue *args); + + null, //virtual jshort JNICALL CallShortMethod(jobject obj, jmethodID methodID, ...); + null, //virtual jshort JNICALL CallShortMethodV(jobject obj, jmethodID methodID, va_list args); + new pf_short_IntPtr_IntPtr_pjvalue(JNIEnv.CallShortMethodA), //virtual jshort JNICALL CallShortMethodA(jobject obj, jmethodID methodID, jvalue *args); + + null, //virtual jint JNICALL CallIntMethod(jobject obj, jmethodID methodID, ...); + null, //virtual jint JNICALL CallIntMethodV(jobject obj, jmethodID methodID, va_list args); + new pf_int_IntPtr_IntPtr_pjvalue(JNIEnv.CallIntMethodA), //virtual jint JNICALL CallIntMethodA(jobject obj, jmethodID methodID, jvalue *args); + + null, //virtual jlong JNICALL CallLongMethod(jobject obj, jmethodID methodID, ...); + null, //virtual jlong JNICALL CallLongMethodV(jobject obj, jmethodID methodID, va_list args); + new pf_long_IntPtr_IntPtr_pjvalue(JNIEnv.CallLongMethodA), //virtual jlong JNICALL CallLongMethodA(jobject obj, jmethodID methodID, jvalue *args); + + null, //virtual jfloat JNICALL CallFloatMethod(jobject obj, jmethodID methodID, ...); + null, //virtual jfloat JNICALL CallFloatMethodV(jobject obj, jmethodID methodID, va_list args); + new pf_float_IntPtr_IntPtr_pjvalue(JNIEnv.CallFloatMethodA), //virtual jfloat JNICALL CallFloatMethodA(jobject obj, jmethodID methodID, jvalue *args); + + null, //virtual jdouble JNICALL CallDoubleMethod(jobject obj, jmethodID methodID, ...); + null, //virtual jdouble JNICALL CallDoubleMethodV(jobject obj, jmethodID methodID, va_list args); + new pf_double_IntPtr_IntPtr_pjvalue(JNIEnv.CallDoubleMethodA), //virtual jdouble JNICALL CallDoubleMethodA(jobject obj, jmethodID methodID, jvalue *args); + + null, //virtual void JNICALL CallVoidMethod(jobject obj, jmethodID methodID, ...); + null, //virtual void JNICALL CallVoidMethodV(jobject obj, jmethodID methodID, va_list args); + new pf_void_IntPtr_IntPtr_pjvalue(JNIEnv.CallVoidMethodA), //virtual void JNICALL CallVoidMethodA(jobject obj, jmethodID methodID, jvalue * args); + + null, //virtual jobject JNICALL CallNonvirtualObjectMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + null, //virtual jobject JNICALL CallNonvirtualObjectMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + new pf_IntPtr_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualObjectMethodA), //virtual jobject JNICALL CallNonvirtualObjectMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args); + + null, //virtual jboolean JNICALL CallNonvirtualBooleanMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + null, //virtual jboolean JNICALL CallNonvirtualBooleanMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + new pf_sbyte_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualBooleanMethodA), //virtual jboolean JNICALL CallNonvirtualBooleanMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args); + + null, //virtual jbyte JNICALL CallNonvirtualByteMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + null, //virtual jbyte JNICALL CallNonvirtualByteMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + new pf_sbyte_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualByteMethodA), //virtual jbyte JNICALL CallNonvirtualByteMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jchar JNICALL CallNonvirtualCharMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + null, //virtual jchar JNICALL CallNonvirtualCharMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + new pf_ushort_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualCharMethodA), //virtual jchar JNICALL CallNonvirtualCharMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jshort JNICALL CallNonvirtualShortMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + null, //virtual jshort JNICALL CallNonvirtualShortMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + new pf_short_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualShortMethodA), //virtual jshort JNICALL CallNonvirtualShortMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jint JNICALL CallNonvirtualIntMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + null, //virtual jint JNICALL CallNonvirtualIntMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + new pf_int_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualIntMethodA), //virtual jint JNICALL CallNonvirtualIntMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jlong JNICALL CallNonvirtualLongMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + null, //virtual jlong JNICALL CallNonvirtualLongMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + new pf_long_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualLongMethodA), //virtual jlong JNICALL CallNonvirtualLongMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jfloat JNICALL CallNonvirtualFloatMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + null, //virtual jfloat JNICALL CallNonvirtualFloatMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + new pf_float_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualFloatMethodA), //virtual jfloat JNICALL CallNonvirtualFloatMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jdouble JNICALL CallNonvirtualDoubleMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + null, //virtual jdouble JNICALL CallNonvirtualDoubleMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + new pf_double_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualDoubleMethodA), //virtual jdouble JNICALL CallNonvirtualDoubleMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual void JNICALL CallNonvirtualVoidMethod(jobject obj, jclass clazz, jmethodID methodID, ...); + null, //virtual void JNICALL CallNonvirtualVoidMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args); + new pf_void_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualVoidMethodA), //virtual void JNICALL CallNonvirtualVoidMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args); + + new pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv.GetFieldID), //virtual jfieldID JNICALL GetFieldID(jclass clazz, const char *name, const char *sig); + + new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetObjectField), //virtual jobject JNICALL GetObjectField(jobject obj, jfieldID fieldID); + new pf_sbyte_IntPtr_IntPtr(JNIEnv.GetBooleanField), //virtual jboolean JNICALL GetBooleanField(jobject obj, jfieldID fieldID); + new pf_sbyte_IntPtr_IntPtr(JNIEnv.GetByteField), //virtual jbyte JNICALL GetByteField(jobject obj, jfieldID fieldID); + new pf_ushort_IntPtr_IntPtr(JNIEnv.GetCharField), //virtual jchar JNICALL GetCharField(jobject obj, jfieldID fieldID); + new pf_short_IntPtr_IntPtr(JNIEnv.GetShortField), //virtual jshort JNICALL GetShortField(jobject obj, jfieldID fieldID); + new pf_int_IntPtr_IntPtr(JNIEnv.GetIntField), //virtual jint JNICALL GetIntField(jobject obj, jfieldID fieldID); + new pf_long_IntPtr_IntPtr(JNIEnv.GetLongField), //virtual jlong JNICALL GetLongField(jobject obj, jfieldID fieldID); + new pf_float_IntPtr_IntPtr(JNIEnv.GetFloatField), //virtual jfloat JNICALL GetFloatField(jobject obj, jfieldID fieldID); + new pf_double_IntPtr_IntPtr(JNIEnv.GetDoubleField), //virtual jdouble JNICALL GetDoubleField(jobject obj, jfieldID fieldID); + + new pf_void_IntPtr_IntPtr_IntPtr(JNIEnv.SetObjectField), //virtual void JNICALL SetObjectField(jobject obj, jfieldID fieldID, jobject val); + new pf_void_IntPtr_IntPtr_sbyte(JNIEnv.SetBooleanField), //virtual void JNICALL SetBooleanField(jobject obj, jfieldID fieldID, jboolean val); + new pf_void_IntPtr_IntPtr_sbyte(JNIEnv.SetByteField), //virtual void JNICALL SetByteField(jobject obj, jfieldID fieldID, jbyte val); + new pf_void_IntPtr_IntPtr_ushort(JNIEnv.SetCharField), //virtual void JNICALL SetCharField(jobject obj, jfieldID fieldID, jchar val); + new pf_void_IntPtr_IntPtr_short(JNIEnv.SetShortField), //virtual void JNICALL SetShortField(jobject obj, jfieldID fieldID, jshort val); + new pf_void_IntPtr_IntPtr_int(JNIEnv.SetIntField), //virtual void JNICALL SetIntField(jobject obj, jfieldID fieldID, jint val); + new pf_void_IntPtr_IntPtr_long(JNIEnv.SetLongField), //virtual void JNICALL SetLongField(jobject obj, jfieldID fieldID, jlong val); + new pf_void_IntPtr_IntPtr_float(JNIEnv.SetFloatField), //virtual void JNICALL SetFloatField(jobject obj, jfieldID fieldID, jfloat val); + new pf_void_IntPtr_IntPtr_double(JNIEnv.SetDoubleField), //virtual void JNICALL SetDoubleField(jobject obj, jfieldID fieldID, jdouble val); + + new pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv.GetStaticMethodID), //virtual jmethodID JNICALL GetStaticMethodID(jclass clazz, const char *name, const char *sig); + + null, //virtual jobject JNICALL CallStaticObjectMethod(jclass clazz, jmethodID methodID, ...); + null, //virtual jobject JNICALL CallStaticObjectMethodV(jclass clazz, jmethodID methodID, va_list args); + new pf_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticObjectMethodA), //virtual jobject JNICALL CallStaticObjectMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jboolean JNICALL CallStaticBooleanMethod(jclass clazz, jmethodID methodID, ...); + null, //virtual jboolean JNICALL CallStaticBooleanMethodV(jclass clazz, jmethodID methodID, va_list args); + new pf_sbyte_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticBooleanMethodA), //virtual jboolean JNICALL CallStaticBooleanMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jbyte JNICALL CallStaticByteMethod(jclass clazz, jmethodID methodID, ...); + null, //virtual jbyte JNICALL CallStaticByteMethodV(jclass clazz, jmethodID methodID, va_list args); + new pf_sbyte_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticByteMethodA), //virtual jbyte JNICALL CallStaticByteMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jchar JNICALL CallStaticCharMethod(jclass clazz, jmethodID methodID, ...); + null, //virtual jchar JNICALL CallStaticCharMethodV(jclass clazz, jmethodID methodID, va_list args); + new pf_ushort_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticCharMethodA), //virtual jchar JNICALL CallStaticCharMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jshort JNICALL CallStaticShortMethod(jclass clazz, jmethodID methodID, ...); + null, //virtual jshort JNICALL CallStaticShortMethodV(jclass clazz, jmethodID methodID, va_list args); + new pf_short_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticShortMethodA), //virtual jshort JNICALL CallStaticShortMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jint JNICALL CallStaticIntMethod(jclass clazz, jmethodID methodID, ...); + null, //virtual jint JNICALL CallStaticIntMethodV(jclass clazz, jmethodID methodID, va_list args); + new pf_int_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticIntMethodA), //virtual jint JNICALL CallStaticIntMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jlong JNICALL CallStaticLongMethod(jclass clazz, jmethodID methodID, ...); + null, //virtual jlong JNICALL CallStaticLongMethodV(jclass clazz, jmethodID methodID, va_list args); + new pf_long_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticLongMethodA), //virtual jlong JNICALL CallStaticLongMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jfloat JNICALL CallStaticFloatMethod(jclass clazz, jmethodID methodID, ...); + null, //virtual jfloat JNICALL CallStaticFloatMethodV(jclass clazz, jmethodID methodID, va_list args); + new pf_float_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticFloatMethodA), //virtual jfloat JNICALL CallStaticFloatMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual jdouble JNICALL CallStaticDoubleMethod(jclass clazz, jmethodID methodID, ...); + null, //virtual jdouble JNICALL CallStaticDoubleMethodV(jclass clazz, jmethodID methodID, va_list args); + new pf_double_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticDoubleMethodA), //virtual jdouble JNICALL CallStaticDoubleMethodA(jclass clazz, jmethodID methodID, jvalue *args); + + null, //virtual void JNICALL CallStaticVoidMethod(jclass cls, jmethodID methodID, ...); + null, //virtual void JNICALL CallStaticVoidMethodV(jclass cls, jmethodID methodID, va_list args); + new pf_void_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticVoidMethodA), //virtual void JNICALL CallStaticVoidMethodA(jclass cls, jmethodID methodID, jvalue * args); + + new pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv.GetStaticFieldID), //virtual jfieldID JNICALL GetStaticFieldID(jclass clazz, const char *name, const char *sig); + + new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetStaticObjectField), //virtual jobject JNICALL GetObjectField(jobject obj, jfieldID fieldID); + new pf_sbyte_IntPtr_IntPtr(JNIEnv.GetStaticBooleanField), //virtual jboolean JNICALL GetBooleanField(jobject obj, jfieldID fieldID); + new pf_sbyte_IntPtr_IntPtr(JNIEnv.GetStaticByteField), //virtual jbyte JNICALL GetByteField(jobject obj, jfieldID fieldID); + new pf_ushort_IntPtr_IntPtr(JNIEnv.GetStaticCharField), //virtual jchar JNICALL GetCharField(jobject obj, jfieldID fieldID); + new pf_short_IntPtr_IntPtr(JNIEnv.GetStaticShortField), //virtual jshort JNICALL GetShortField(jobject obj, jfieldID fieldID); + new pf_int_IntPtr_IntPtr(JNIEnv.GetStaticIntField), //virtual jint JNICALL GetIntField(jobject obj, jfieldID fieldID); + new pf_long_IntPtr_IntPtr(JNIEnv.GetStaticLongField), //virtual jlong JNICALL GetLongField(jobject obj, jfieldID fieldID); + new pf_float_IntPtr_IntPtr(JNIEnv.GetStaticFloatField), //virtual jfloat JNICALL GetFloatField(jobject obj, jfieldID fieldID); + new pf_double_IntPtr_IntPtr(JNIEnv.GetStaticDoubleField), //virtual jdouble JNICALL GetDoubleField(jobject obj, jfieldID fieldID); + + new pf_void_IntPtr_IntPtr_IntPtr(JNIEnv.SetStaticObjectField), //virtual void JNICALL SetObjectField(jobject obj, jfieldID fieldID, jobject val); + new pf_void_IntPtr_IntPtr_sbyte(JNIEnv.SetStaticBooleanField), //virtual void JNICALL SetBooleanField(jobject obj, jfieldID fieldID, jboolean val); + new pf_void_IntPtr_IntPtr_sbyte(JNIEnv.SetStaticByteField), //virtual void JNICALL SetByteField(jobject obj, jfieldID fieldID, jbyte val); + new pf_void_IntPtr_IntPtr_ushort(JNIEnv.SetStaticCharField), //virtual void JNICALL SetCharField(jobject obj, jfieldID fieldID, jchar val); + new pf_void_IntPtr_IntPtr_short(JNIEnv.SetStaticShortField), //virtual void JNICALL SetShortField(jobject obj, jfieldID fieldID, jshort val); + new pf_void_IntPtr_IntPtr_int(JNIEnv.SetStaticIntField), //virtual void JNICALL SetIntField(jobject obj, jfieldID fieldID, jint val); + new pf_void_IntPtr_IntPtr_long(JNIEnv.SetStaticLongField), //virtual void JNICALL SetLongField(jobject obj, jfieldID fieldID, jlong val); + new pf_void_IntPtr_IntPtr_float(JNIEnv.SetStaticFloatField), //virtual void JNICALL SetFloatField(jobject obj, jfieldID fieldID, jfloat val); + new pf_void_IntPtr_IntPtr_double(JNIEnv.SetStaticDoubleField), //virtual void JNICALL SetDoubleField(jobject obj, jfieldID fieldID, jdouble val); + + new pf_IntPtr_pjchar_int(JNIEnv.NewString), //virtual jstring JNICALL NewString(const jchar *unicode, jsize len); + new pf_int_IntPtr(JNIEnv.GetStringLength), //virtual jsize JNICALL GetStringLength(jstring str); + new pf_pjchar_IntPtr_pjboolean(JNIEnv.GetStringChars), //virtual const jchar *JNICALL GetStringChars(jstring str, jboolean *isCopy); + new pf_void_IntPtr_pjchar(JNIEnv.ReleaseStringChars), //virtual void JNICALL ReleaseStringChars(jstring str, const jchar *chars); + + new pf_IntPtr_pbyte(JNIEnv.NewStringUTF), //virtual jstring JNICALL NewStringUTF(const char *utf); + new pf_int_IntPtr(JNIEnv.GetStringUTFLength), //virtual jsize JNICALL GetStringUTFLength(jstring str); + new pf_pbyte_IntPtr_pjboolean(JNIEnv.GetStringUTFChars), //virtual const char* JNICALL GetStringUTFChars(jstring str, jboolean *isCopy); + new pf_void_IntPtr_pbyte(JNIEnv.ReleaseStringUTFChars), //virtual void JNICALL ReleaseStringUTFChars(jstring str, const char* chars); + + new pf_int_IntPtr(JNIEnv.GetArrayLength), //virtual jsize JNICALL GetArrayLength(jarray array); + + new pf_IntPtr_int_IntPtr_IntPtr(JNIEnv.NewObjectArray), //virtual jobjectArray JNICALL NewObjectArray(jsize len, jclass clazz, jobject init); + new pf_IntPtr_IntPtr_int(JNIEnv.GetObjectArrayElement), //virtual jobject JNICALL GetObjectArrayElement(jobjectArray array, jsize index); + new pf_void_IntPtr_int_IntPtr(JNIEnv.SetObjectArrayElement), //virtual void JNICALL SetObjectArrayElement(jobjectArray array, jsize index, jobject val); + + new pf_IntPtr_int(JNIEnv.NewBooleanArray), //virtual jbooleanArray JNICALL NewBooleanArray(jsize len); + new pf_IntPtr_int(JNIEnv.NewByteArray), //virtual jbyteArray JNICALL NewByteArray(jsize len); + new pf_IntPtr_int(JNIEnv.NewCharArray), //virtual jcharArray JNICALL NewCharArray(jsize len); + new pf_IntPtr_int(JNIEnv.NewShortArray), //virtual jshortArray JNICALL NewShortArray(jsize len); + new pf_IntPtr_int(JNIEnv.NewIntArray), //virtual jintArray JNICALL NewIntArray(jsize len); + new pf_IntPtr_int(JNIEnv.NewLongArray), //virtual jlongArray JNICALL NewLongArray(jsize len); + new pf_IntPtr_int(JNIEnv.NewFloatArray), //virtual jfloatArray JNICALL NewFloatArray(jsize len); + new pf_IntPtr_int(JNIEnv.NewDoubleArray), //virtual jdoubleArray JNICALL NewDoubleArray(jsize len); + + new pf_pjboolean_IntPtr_pjboolean(JNIEnv.GetBooleanArrayElements), //virtual jboolean * JNICALL GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy); + new pf_pjbyte_IntPtr_pjboolean(JNIEnv.GetByteArrayElements), //virtual jbyte * JNICALL GetByteArrayElements(jbyteArray array, jboolean *isCopy); + new pf_pjchar_IntPtr_pjboolean(JNIEnv.GetCharArrayElements), //virtual jchar * JNICALL GetCharArrayElements(jcharArray array, jboolean *isCopy); + new pf_pjshort_IntPtr_pjboolean(JNIEnv.GetShortArrayElements), //virtual jshort * JNICALL GetShortArrayElements(jshortArray array, jboolean *isCopy); + new pf_pjint_IntPtr_pjboolean(JNIEnv.GetIntArrayElements), //virtual jint * JNICALL GetIntArrayElements(jintArray array, jboolean *isCopy); + new pf_pjlong_IntPtr_pjboolean(JNIEnv.GetLongArrayElements), //virtual jlong * JNICALL GetLongArrayElements(jlongArray array, jboolean *isCopy); + new pf_pjfloat_IntPtr_pjboolean(JNIEnv.GetFloatArrayElements), //virtual jfloat * JNICALL GetFloatArrayElements(jfloatArray array, jboolean *isCopy); + new pf_pjdouble_IntPtr_pjboolean(JNIEnv.GetDoubleArrayElements), //virtual jdouble * JNICALL GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy); + + new pf_void_IntPtr_pjboolean_int(JNIEnv.ReleaseBooleanArrayElements), //virtual void JNICALL ReleaseBooleanArrayElements(jbooleanArray array, jboolean *elems, jint mode); + new pf_void_IntPtr_pjbyte_int(JNIEnv.ReleaseByteArrayElements), //virtual void JNICALL ReleaseByteArrayElements(jbyteArray array, jbyte *elems, jint mode); + new pf_void_IntPtr_pjchar_int(JNIEnv.ReleaseCharArrayElements), //virtual void JNICALL ReleaseCharArrayElements(jcharArray array, jchar *elems, jint mode); + new pf_void_IntPtr_pjshort_int(JNIEnv.ReleaseShortArrayElements), //virtual void JNICALL ReleaseShortArrayElements(jshortArray array, jshort *elems, jint mode); + new pf_void_IntPtr_pjint_int(JNIEnv.ReleaseIntArrayElements), //virtual void JNICALL ReleaseIntArrayElements(jintArray array, jint *elems, jint mode); + new pf_void_IntPtr_pjlong_int(JNIEnv.ReleaseLongArrayElements), //virtual void JNICALL ReleaseLongArrayElements(jlongArray array, jlong *elems, jint mode); + new pf_void_IntPtr_pjfloat_int(JNIEnv.ReleaseFloatArrayElements), //virtual void JNICALL ReleaseFloatArrayElements(jfloatArray array, jfloat *elems, jint mode); + new pf_void_IntPtr_pjdouble_int(JNIEnv.ReleaseDoubleArrayElements), //virtual void JNICALL ReleaseDoubleArrayElements(jdoubleArray array, jdouble *elems, jint mode); + + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetBooleanArrayRegion), //virtual void JNICALL GetBooleanArrayRegion(jbooleanArray array, jsize start, jsize l, jboolean *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetByteArrayRegion), //virtual void JNICALL GetByteArrayRegion(jbyteArray array, jsize start, jsize len, jbyte *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetCharArrayRegion), //virtual void JNICALL GetCharArrayRegion(jcharArray array, jsize start, jsize len, jchar *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetShortArrayRegion), //virtual void JNICALL GetShortArrayRegion(jshortArray array, jsize start, jsize len, jshort *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetIntArrayRegion), //virtual void JNICALL GetIntArrayRegion(jintArray array, jsize start, jsize len, jint *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetLongArrayRegion), //virtual void JNICALL GetLongArrayRegion(jlongArray array, jsize start, jsize len, jlong *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetFloatArrayRegion), //virtual void JNICALL GetFloatArrayRegion(jfloatArray array, jsize start, jsize len, jfloat *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetDoubleArrayRegion), //virtual void JNICALL GetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, jdouble *buf); + + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetBooleanArrayRegion), //virtual void JNICALL SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize l, jboolean *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetByteArrayRegion), //virtual void JNICALL SetByteArrayRegion(jbyteArray array, jsize start, jsize len, jbyte *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetCharArrayRegion), //virtual void JNICALL SetCharArrayRegion(jcharArray array, jsize start, jsize len, jchar *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetShortArrayRegion), //virtual void JNICALL SetShortArrayRegion(jshortArray array, jsize start, jsize len, jshort *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetIntArrayRegion), //virtual void JNICALL SetIntArrayRegion(jintArray array, jsize start, jsize len, jint *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetLongArrayRegion), //virtual void JNICALL SetLongArrayRegion(jlongArray array, jsize start, jsize len, jlong *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetFloatArrayRegion), //virtual void JNICALL SetFloatArrayRegion(jfloatArray array, jsize start, jsize len, jfloat *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetDoubleArrayRegion), //virtual void JNICALL SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, jdouble *buf); + + new pf_int_IntPtr_pJNINativeMethod_int(JNIEnv.RegisterNatives), //virtual jint JNICALL RegisterNatives(jclass clazz, const JNINativeMethod *methods, jint nMethods); + new pf_int_IntPtr(JNIEnv.UnregisterNatives), //virtual jint JNICALL UnregisterNatives(jclass clazz); + + new pf_int_IntPtr(JNIEnv.MonitorEnter), //virtual jint JNICALL MonitorEnter(jobject obj); + new pf_int_IntPtr(JNIEnv.MonitorExit), //virtual jint JNICALL MonitorExit(jobject obj); + + new pf_int_ppJavaVM(JNIEnv.GetJavaVM), //virtual jint JNICALL GetJavaVM(JavaVM **vm); + + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetStringRegion), //virtual void JNICALL GetStringRegion(jstring str, jsize start, jsize len, jchar *buf); + new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetStringUTFRegion), //virtual void JNICALL GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf); + + new pf_pvoid_IntPtr_pjboolean(JNIEnv.GetPrimitiveArrayCritical), //virtual void* JNICALL GetPrimitiveArrayCritical(jarray array, jboolean *isCopy); + new pf_void_IntPtr_pvoid_int(JNIEnv.ReleasePrimitiveArrayCritical), //virtual void JNICALL ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode); + + new pf_pjchar_IntPtr_pjboolean(JNIEnv.GetStringCritical), //virtual const jchar* JNICALL GetStringCritical(jstring string, jboolean *isCopy); + new pf_void_IntPtr_pjchar(JNIEnv.ReleaseStringCritical), //virtual void JNICALL ReleaseStringCritical(jstring string, const jchar *cstring); + + new pf_IntPtr_IntPtr(JNIEnv.NewWeakGlobalRef), //virtual jweak JNICALL NewWeakGlobalRef(jobject obj); + new pf_void_IntPtr(JNIEnv.DeleteWeakGlobalRef), //virtual void JNICALL DeleteWeakGlobalRef(jweak ref); + + new pf_sbyte(JNIEnv.ExceptionCheck), //virtual jboolean JNICALL ExceptionCheck(); + + new pf_IntPtr_IntPtr_long(JNIEnv.NewDirectByteBuffer), //virtual jobject JNICALL NewDirectByteBuffer(void* address, jlong capacity); + new pf_IntPtr_IntPtr(JNIEnv.GetDirectBufferAddress), //virtual void* JNICALL GetDirectBufferAddress(jobject buf); + new pf_long_IntPtr(JNIEnv.GetDirectBufferCapacity), //virtual jlong JNICALL GetDirectBufferCapacity(jobject buf); + + new pf_int_IntPtr(JNIEnv.GetObjectRefType) // virtual jobjectRefType GetObjectRefType(jobject obj); + }; + } + + [StructLayout(LayoutKind.Sequential)] + unsafe struct JavaVMAttachArgs + { + internal jint version; + internal byte* name; + internal jobject group; + } + + [StructLayout(LayoutKind.Sequential)] + unsafe struct JavaVM + { + internal static JavaVM* pJavaVM; + void** vtable; + void* firstVtableEntry; + delegate int pf_int(JavaVM* pJVM); + delegate int pf_int_ppvoid_pvoid(JavaVM* pJVM, void** p1, void* p2); + delegate int pf_int_ppvoid_int(JavaVM* pJVM, void** p1, int p2); + + static Delegate[] vtableDelegates = + { + null, + null, + null, + new pf_int(DestroyJavaVM), + new pf_int_ppvoid_pvoid(AttachCurrentThread), + new pf_int(DetachCurrentThread), + new pf_int_ppvoid_int(GetEnv), + new pf_int_ppvoid_pvoid(AttachCurrentThreadAsDaemon) + }; + + static JavaVM() + { + JNI.jvmCreated = true; + pJavaVM = (JavaVM*)(void*)JniMem.Alloc(IntPtr.Size * (1 + vtableDelegates.Length)); + pJavaVM->vtable = &pJavaVM->firstVtableEntry; + for(int i = 0; i < vtableDelegates.Length; i++) + { + pJavaVM->vtable[i] = NativeLibrary.MarshalDelegate(vtableDelegates[i]); + } + } + + internal static jint DestroyJavaVM(JavaVM* pJVM) + { + if(JNI.jvmDestroyed) + { + return JNIEnv.JNI_ERR; + } + JNI.jvmDestroyed = true; + Java_java_lang_Thread.WaitUntilLastJniThread(); + return JNIEnv.JNI_OK; + } + + internal static jint AttachCurrentThread(JavaVM* pJVM, void **penv, void *args) + { + return AttachCurrentThreadImpl(pJVM, penv, (JavaVMAttachArgs*)args, false); + } + + internal static jint AttachCurrentThreadImpl(JavaVM* pJVM, void** penv, JavaVMAttachArgs* pAttachArgs, bool asDaemon) + { + if(pAttachArgs != null) + { + if(!JNI.IsSupportedJniVersion(pAttachArgs->version) || pAttachArgs->version == JNIEnv.JNI_VERSION_1_1) + { + *penv = null; + return JNIEnv.JNI_EVERSION; + } + } + JNIEnv.ManagedJNIEnv env = TlsHack.ManagedJNIEnv; + if(env != null) + { + *penv = env.pJNIEnv; + return JNIEnv.JNI_OK; + } + // NOTE if we're here, it is *very* likely that the thread was created by native code and not by managed code, + // but it's not impossible that the thread started life as a managed thread and if it did the changes to the + // thread we're making are somewhat dubious. + System.Threading.Thread.CurrentThread.IsBackground = asDaemon; + if(pAttachArgs != null) + { + if(pAttachArgs->name != null && System.Threading.Thread.CurrentThread.Name == null) + { + try + { + System.Threading.Thread.CurrentThread.Name = JNIEnv.StringFromUTF8(pAttachArgs->name); + } + catch(InvalidOperationException) + { + // someone beat us to it... + } + } + object threadGroup = GlobalRefs.Unwrap(pAttachArgs->group.ToInt32()); + if(threadGroup != null) + { + Java_java_lang_Thread.AttachThreadFromJni(threadGroup); + } + } + *penv = JNIEnv.CreateJNIEnv(); + return JNIEnv.JNI_OK; + } + + internal static jint DetachCurrentThread(JavaVM* pJVM) + { + if(TlsHack.ManagedJNIEnv == null) + { + // the JDK allows detaching from an already detached thread + return JNIEnv.JNI_OK; + } + // TODO if we set Thread.IsBackground to false when we attached, now might be a good time to set it back to true. + JNIEnv.FreeJNIEnv(); + Java_ikvm_runtime_Startup.jniDetach(); + return JNIEnv.JNI_OK; + } + + internal static jint GetEnv(JavaVM* pJVM, void **penv, jint version) + { + if(JNI.IsSupportedJniVersion(version)) + { + JNIEnv.ManagedJNIEnv env = TlsHack.ManagedJNIEnv; + if(env != null) + { + *penv = env.pJNIEnv; + return JNIEnv.JNI_OK; + } + *penv = null; + return JNIEnv.JNI_EDETACHED; + } + *penv = null; + return JNIEnv.JNI_EVERSION; + } + + internal static jint AttachCurrentThreadAsDaemon(JavaVM* pJVM, void **penv, void *args) + { + return AttachCurrentThreadImpl(pJVM, penv, (JavaVMAttachArgs*)args, true); + } + } + + [StructLayout(LayoutKind.Sequential)] + unsafe struct JNIEnv + { + internal const int JNI_OK = 0; + internal const int JNI_ERR = -1; + internal const int JNI_EDETACHED = -2; + internal const int JNI_EVERSION = -3; + internal const int JNI_COMMIT = 1; + internal const int JNI_ABORT = 2; + internal const int JNI_VERSION_1_1 = 0x00010001; + internal const int JNI_VERSION_1_2 = 0x00010002; + internal const int JNI_VERSION_1_4 = 0x00010004; + internal const int JNI_VERSION_1_6 = 0x00010006; + internal const int JNI_VERSION_1_8 = 0x00010008; + internal const int JNIInvalidRefType = 0; + internal const int JNILocalRefType = 1; + internal const int JNIGlobalRefType = 2; + internal const int JNIWeakGlobalRefType = 3; + internal const sbyte JNI_TRUE = 1; + internal const sbyte JNI_FALSE = 0; + private void* vtable; + private GCHandle managedJNIEnv; + private GCHandle* pinHandles; + private int pinHandleMaxCount; + private int pinHandleInUseCount; + + static JNIEnv() + { + // we set the field here so that IKVM.Runtime.dll doesn't have to load us if we're not otherwise needed + Java_java_lang_SecurityManager.jniAssembly = typeof(JNIEnv).Assembly; + } + + internal ManagedJNIEnv GetManagedJNIEnv() + { + return (ManagedJNIEnv)managedJNIEnv.Target; + } + + internal sealed class ManagedJNIEnv + { + // NOTE the initial bucket size must be a power of two < LOCAL_REF_MAX_BUCKET_SIZE, + // because each time we grow it, we double the size and it must eventually reach + // exactly LOCAL_REF_MAX_BUCKET_SIZE + private const int LOCAL_REF_INITIAL_BUCKET_SIZE = 32; + private const int LOCAL_REF_SHIFT = 10; + private const int LOCAL_REF_MAX_BUCKET_SIZE = (1 << LOCAL_REF_SHIFT); + private const int LOCAL_REF_MASK = (LOCAL_REF_MAX_BUCKET_SIZE - 1); + internal readonly JNIEnv* pJNIEnv; + internal ClassLoaderWrapper classLoader; + internal ikvm.@internal.CallerID callerID; + private object[][] localRefs; + private int localRefSlot; + private int localRefIndex; + private object[] active; + internal Exception pendingException; + + internal ManagedJNIEnv() + { + pJNIEnv = (JNIEnv*)JniMem.Alloc(sizeof(JNIEnv)); + localRefs = new object[32][]; + active = localRefs[0] = new object[LOCAL_REF_INITIAL_BUCKET_SIZE]; + // stuff something in the first entry to make sure we don't hand out a zero handle + // (a zero handle corresponds to a null reference) + active[0] = ""; + localRefIndex = 1; + } + + ~ManagedJNIEnv() + { + // NOTE don't clean up when we're being unloaded (we'll get cleaned up anyway and because + // of the unorderedness of the finalization process native code could still be run after + // we run). + // NOTE when we're not the default AppDomain and we're being unloaded, + // we're leaking the JNIEnv (but since JNI outside of the default AppDomain isn't currently supported, + // I can live with that). + if(!Environment.HasShutdownStarted) + { + if(pJNIEnv->managedJNIEnv.IsAllocated) + { + pJNIEnv->managedJNIEnv.Free(); + } + for(int i = 0; i < pJNIEnv->pinHandleMaxCount; i++) + { + if(pJNIEnv->pinHandles[i].IsAllocated) + { + pJNIEnv->pinHandles[i].Free(); + } + } + JniMem.Free((IntPtr)(void*)pJNIEnv); + } + } + + internal struct FrameState + { + internal readonly ikvm.@internal.CallerID callerID; + internal readonly int localRefSlot; + internal readonly int localRefIndex; + + internal FrameState(ikvm.@internal.CallerID callerID, int localRefSlot, int localRefIndex) + { + this.callerID = callerID; + this.localRefSlot = localRefSlot; + this.localRefIndex = localRefIndex; + } + } + + internal FrameState Enter(ikvm.@internal.CallerID newCallerID) + { + FrameState prev = new FrameState(callerID, localRefSlot, localRefIndex); + this.callerID = newCallerID; + localRefSlot++; + if (localRefSlot >= localRefs.Length) + { + object[][] tmp = new object[localRefs.Length * 2][]; + Array.Copy(localRefs, 0, tmp, 0, localRefs.Length); + localRefs = tmp; + } + localRefIndex = 0; + active = localRefs[localRefSlot]; + if (active == null) + { + active = localRefs[localRefSlot] = new object[LOCAL_REF_INITIAL_BUCKET_SIZE]; + } + return prev; + } + + internal Exception Leave(FrameState prev) + { + // on the current (.NET 2.0 SP2) x86 JIT an explicit for loop is faster than Array.Clear() up to about 100 elements + for (int i = 0; i < localRefIndex; i++) + { + active[i] = null; + } + while (--localRefSlot != prev.localRefSlot) + { + if (localRefs[localRefSlot] != null) + { + if (localRefs[localRefSlot].Length == LOCAL_REF_MAX_BUCKET_SIZE) + { + // if the bucket is totally allocated, we're assuming a leaky method so we throw the bucket away + localRefs[localRefSlot] = null; + } + else + { + Array.Clear(localRefs[localRefSlot], 0, localRefs[localRefSlot].Length); + } + } + } + active = localRefs[localRefSlot]; + this.localRefIndex = prev.localRefIndex; + this.callerID = prev.callerID; + Exception x = pendingException; + pendingException = null; + return x; + } + + internal jobject MakeLocalRef(object obj) + { + if (obj == null) + { + return IntPtr.Zero; + } + + int index; + if (localRefIndex == active.Length) + { + index = FindFreeIndex(); + } + else + { + index = localRefIndex++; + } + active[index] = obj; + return (IntPtr)((localRefSlot << LOCAL_REF_SHIFT) + index); + } + + private int FindFreeIndex() + { + for (int i = 0; i < active.Length; i++) + { + if (active[i] == null) + { + while (localRefIndex - 1 > i && active[localRefIndex - 1] == null) + { + localRefIndex--; + } + return i; + } + } + GrowActiveSlot(); + return localRefIndex++; + } + + private void GrowActiveSlot() + { + if (active.Length < LOCAL_REF_MAX_BUCKET_SIZE) + { + object[] tmp = new object[active.Length * 2]; + Array.Copy(active, tmp, active.Length); + active = localRefs[localRefSlot] = tmp; + return; + } + // if we get here, we're in a native method that most likely is leaking locals refs, + // so we're going to allocate a new bucket and increment localRefSlot, this means that + // any slots that become available in the previous bucket are not going to be reused, + // but since we're assuming that the method is leaking anyway, that isn't a problem + // (it's never a correctness issue, just a resource consumption issue) + localRefSlot++; + localRefIndex = 0; + if (localRefSlot == localRefs.Length) + { + object[][] tmp = new object[localRefSlot * 2][]; + Array.Copy(localRefs, 0, tmp, 0, localRefSlot); + localRefs = tmp; + } + active = localRefs[localRefSlot]; + if (active == null) + { + active = localRefs[localRefSlot] = new object[LOCAL_REF_MAX_BUCKET_SIZE]; + } + } + + internal object UnwrapLocalRef(int i) + { + return localRefs[i >> LOCAL_REF_SHIFT][i & LOCAL_REF_MASK]; + } + + internal int PushLocalFrame(jint capacity) + { + localRefSlot += 2; + if (localRefSlot >= localRefs.Length) + { + object[][] tmp = new object[localRefs.Length * 2][]; + Array.Copy(localRefs, 0, tmp, 0, localRefs.Length); + localRefs = tmp; + } + // we use a null slot to mark the fact that we used PushLocalFrame + localRefs[localRefSlot - 1] = null; + if (localRefs[localRefSlot] == null) + { + // we can't use capacity directly, because the array length must be a power of two + // and it can't be bigger than LOCAL_REF_MAX_BUCKET_SIZE + int r = 1; + capacity = Math.Min(capacity, LOCAL_REF_MAX_BUCKET_SIZE); + while (r < capacity) + { + r *= 2; + } + localRefs[localRefSlot] = new object[r]; + } + localRefIndex = 0; + active = localRefs[localRefSlot]; + return JNI_OK; + } + + internal jobject PopLocalFrame(object res) + { + while (localRefs[localRefSlot] != null) + { + localRefs[localRefSlot] = null; + localRefSlot--; + } + localRefSlot--; + localRefIndex = localRefs[localRefSlot].Length; + active = localRefs[localRefSlot]; + return MakeLocalRef(res); + } + + internal void DeleteLocalRef(jobject obj) + { + int i = obj.ToInt32(); + if (i > 0) + { + localRefs[i >> LOCAL_REF_SHIFT][i & LOCAL_REF_MASK] = null; + return; + } + if (i < 0) + { + Debug.Assert(false, "bogus localref in DeleteLocalRef"); + } + } + } + + internal static JNIEnv* CreateJNIEnv() + { + ManagedJNIEnv env = new ManagedJNIEnv(); + TlsHack.ManagedJNIEnv = env; + JNIEnv* pJNIEnv = env.pJNIEnv; + pJNIEnv->vtable = VtableBuilder.vtable; + pJNIEnv->managedJNIEnv = GCHandle.Alloc(env, GCHandleType.WeakTrackResurrection); + pJNIEnv->pinHandles = null; + pJNIEnv->pinHandleMaxCount = 0; + pJNIEnv->pinHandleInUseCount = 0; + return pJNIEnv; + } + + internal static void FreeJNIEnv() + { + TlsHack.ManagedJNIEnv = null; + } + + internal static string StringFromOEM(byte* psz) + { + for(int i = 0;; i++) + { + if(psz[i] == 0) + { + int oem = System.Globalization.CultureInfo.CurrentCulture.TextInfo.OEMCodePage; + return new String((sbyte*)psz, 0, i, Encoding.GetEncoding(oem)); + } + } + } + + internal static string StringFromUTF8(byte* psz) + { + // Sun's modified UTF8 encoding is not compatible with System.Text.Encoding.UTF8, + // so we need to roll our own + int len = 0; + bool hasNonAscii = false; + while(psz[len] != 0) + { + hasNonAscii |= psz[len] >= 128; + len++; + } + if(!hasNonAscii) + { + // optimize the common case of 7-bit ASCII + return new String((sbyte*)psz); + } + StringBuilder sb = new StringBuilder(len); + for(int i = 0; i < len; i++) + { + int c = *psz++; + int char2, char3; + switch(c >> 4) + { + case 12: + case 13: + char2 = *psz++; + i++; + c = (((c & 0x1F) << 6) | (char2 & 0x3F)); + break; + case 14: + char2 = *psz++; + char3 = *psz++; + i++; + i++; + c = ((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | (char3 & 0x3F); + break; + } + sb.Append((char)c); + } + return sb.ToString(); + } + + private static int StringUTF8Length(string s) + { + int len = 0; + for(int i = 0; i < s.Length; i++) + { + char ch = s[i]; + if((ch != 0) && (ch <= 0x7F)) + { + len++; + } + else if(ch <= 0x7FF) + { + len += 2; + } + else + { + len += 3; + } + } + return len; + } + + internal static jint GetMethodArgs(JNIEnv* pEnv, IntPtr method, byte* sig) + { + TypeWrapper[] argTypes = MethodWrapper.FromCookie(method).GetParameters(); + for (int i = 0; i < argTypes.Length; i++) + { + TypeWrapper tw = argTypes[i]; + if (tw.IsPrimitive) + { + sig[i] = (byte)tw.SigName[0]; + } + else + { + sig[i] = (byte)'L'; + } + } + return argTypes.Length; + } + + internal static jint GetVersion(JNIEnv* pEnv) + { + return JNI_VERSION_1_8; + } + + internal static jclass DefineClass(JNIEnv* pEnv, byte* name, jobject loader, jbyte* pbuf, jint length) + { + try + { + byte[] buf = new byte[length]; + Marshal.Copy((IntPtr)(void*)pbuf, buf, 0, length); + // TODO what should the protection domain be? + // NOTE I'm assuming name is platform encoded (as opposed to UTF-8), but the Sun JVM only seems to work for ASCII. + global::java.lang.ClassLoader classLoader = (global::java.lang.ClassLoader)pEnv->UnwrapRef(loader); + return pEnv->MakeLocalRef(Java_java_lang_ClassLoader.defineClass0(classLoader, name != null ? StringFromOEM(name) : null, buf, 0, buf.Length, null)); + } + catch(Exception x) + { + SetPendingException(pEnv, x); + return IntPtr.Zero; + } + } + + private static ClassLoaderWrapper FindNativeMethodClassLoader(JNIEnv* pEnv) + { + ManagedJNIEnv env = pEnv->GetManagedJNIEnv(); + if(env.callerID != null) + { + return ClassLoaderWrapper.FromCallerID(env.callerID); + } + if(env.classLoader != null) + { + return env.classLoader; + } + return ClassLoaderWrapper.GetClassLoaderWrapper(java.lang.ClassLoader.getSystemClassLoader()); + } + + internal static jclass FindClass(JNIEnv* pEnv, byte* pszName) + { + try + { + string name = StringFromOEM(pszName); + // don't allow dotted names! + if(name.IndexOf('.') >= 0) + { + SetPendingException(pEnv, new java.lang.NoClassDefFoundError(name)); + return IntPtr.Zero; + } + // spec doesn't say it, but Sun allows signature format class names (but not for primitives) + if(name.StartsWith("L") && name.EndsWith(";")) + { + name = name.Substring(1, name.Length - 2); + } + TypeWrapper wrapper = FindNativeMethodClassLoader(pEnv).LoadClassByDottedNameFast(name.Replace('/', '.')); + if(wrapper == null) + { + SetPendingException(pEnv, new java.lang.NoClassDefFoundError(name)); + return IntPtr.Zero; + } + wrapper.Finish(); + // spec doesn't say it, but Sun runs the static initializer + wrapper.RunClassInit(); + return pEnv->MakeLocalRef(wrapper.ClassObject); + } + catch(Exception x) + { + if(x is RetargetableJavaException) + { + x = ((RetargetableJavaException)x).ToJava(); + } + SetPendingException(pEnv, x); + return IntPtr.Zero; + } + } + + internal static jmethodID FromReflectedMethod(JNIEnv* pEnv, jobject method) + { + return MethodWrapper.FromExecutable((java.lang.reflect.Executable)pEnv->UnwrapRef(method)).Cookie; + } + + internal static jfieldID FromReflectedField(JNIEnv* pEnv, jobject field) + { + return FieldWrapper.FromField((java.lang.reflect.Field)pEnv->UnwrapRef(field)).Cookie; + } + + internal static jobject ToReflectedMethod(JNIEnv* pEnv, jclass clazz_ignored, jmethodID method, jboolean isStatic) + { + return pEnv->MakeLocalRef(MethodWrapper.FromCookie(method).ToMethodOrConstructor(true)); + } + + internal static jclass GetSuperclass(JNIEnv* pEnv, jclass sub) + { + TypeWrapper wrapper = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(sub)).BaseTypeWrapper; + return pEnv->MakeLocalRef(wrapper == null ? null : wrapper.ClassObject); + } + + internal static jboolean IsAssignableFrom(JNIEnv* pEnv, jclass sub, jclass super) + { + TypeWrapper w1 = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(sub)); + TypeWrapper w2 = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(super)); + return w1.IsAssignableTo(w2) ? JNI_TRUE : JNI_FALSE; + } + + internal static jobject ToReflectedField(JNIEnv* pEnv, jclass clazz_ignored, jfieldID field, jboolean isStatic) + { + return pEnv->MakeLocalRef(FieldWrapper.FromCookie(field).ToField(true)); + } + + private static void SetPendingException(JNIEnv* pEnv, Exception x) + { + pEnv->GetManagedJNIEnv().pendingException = ikvm.runtime.Util.mapException(x); + } + + internal static jint Throw(JNIEnv* pEnv, jthrowable throwable) + { + ManagedJNIEnv env = pEnv->GetManagedJNIEnv(); + Exception x = UnwrapRef(env, throwable) as Exception; + if (x != null) + { + env.pendingException = x; + } + return JNI_OK; + } + + internal static jint ThrowNew(JNIEnv* pEnv, jclass clazz, byte* msg) + { + ManagedJNIEnv env = pEnv->GetManagedJNIEnv(); + TypeWrapper wrapper = TypeWrapper.FromClass((java.lang.Class)UnwrapRef(env, clazz)); + MethodWrapper mw = wrapper.GetMethodWrapper("", msg == null ? "()V" : "(Ljava.lang.String;)V", false); + if(mw != null) + { + jint rc; + Exception exception; + try + { + wrapper.Finish(); + java.lang.reflect.Constructor cons = (java.lang.reflect.Constructor)mw.ToMethodOrConstructor(false); + exception = (Exception)cons.newInstance(msg == null ? new object[0] : new object[] { StringFromOEM(msg) }, env.callerID); + rc = JNI_OK; + } + catch(RetargetableJavaException x) + { + exception = x.ToJava(); + rc = JNI_ERR; + } + catch(Exception x) + { + exception = x; + rc = JNI_ERR; + } + SetPendingException(pEnv, exception); + return rc; + } + else + { + SetPendingException(pEnv, new java.lang.NoSuchMethodError("(Ljava.lang.String;)V")); + return JNI_ERR; + } + } + + internal static jthrowable ExceptionOccurred(JNIEnv* pEnv) + { + ManagedJNIEnv env = pEnv->GetManagedJNIEnv(); + return pEnv->MakeLocalRef(env.pendingException); + } + + internal static void ExceptionDescribe(JNIEnv* pEnv) + { + ManagedJNIEnv env = pEnv->GetManagedJNIEnv(); + Exception x = env.pendingException; + if(x != null) + { + env.pendingException = null; + try + { + ikvm.extensions.ExtensionMethods.printStackTrace(x); + } + catch(Exception ex) + { + Debug.Assert(false, ex.ToString()); + } + } + } + + internal static void ExceptionClear(JNIEnv* pEnv) + { + ManagedJNIEnv env = pEnv->GetManagedJNIEnv(); + env.pendingException = null; + } + + internal static void FatalError(JNIEnv* pEnv, byte* msg) + { + Console.Error.WriteLine("FATAL ERROR in native method: {0}", msg == null ? "(null)" : StringFromOEM(msg)); + Console.Error.WriteLine(new StackTrace(1, true)); + Environment.Exit(1); + } + + internal static jint PushLocalFrame(JNIEnv* pEnv, jint capacity) + { + return pEnv->GetManagedJNIEnv().PushLocalFrame(capacity); + } + + internal static jobject PopLocalFrame(JNIEnv* pEnv, jobject result) + { + ManagedJNIEnv env = pEnv->GetManagedJNIEnv(); + return env.PopLocalFrame(UnwrapRef(env, result)); + } + + internal static jobject NewGlobalRef(JNIEnv* pEnv, jobject obj) + { + object o = pEnv->UnwrapRef(obj); + if(o == null) + { + return IntPtr.Zero; + } + lock(GlobalRefs.globalRefs) + { + int index = GlobalRefs.globalRefs.IndexOf(null); + if(index >= 0) + { + GlobalRefs.globalRefs[index] = o; + } + else + { + index = GlobalRefs.globalRefs.Add(o); + } + return (IntPtr)(-(index + 1)); + } + } + + internal static void DeleteGlobalRef(JNIEnv* pEnv, jobject obj) + { + int i = obj.ToInt32(); + if(i < 0) + { + lock(GlobalRefs.globalRefs) + { + GlobalRefs.globalRefs[(-i) - 1] = null; + } + return; + } + if(i > 0) + { + Debug.Assert(false, "Local ref passed to DeleteGlobalRef"); + } + } + + internal static void DeleteLocalRef(JNIEnv* pEnv, jobject obj) + { + pEnv->GetManagedJNIEnv().DeleteLocalRef(obj); + } + + internal static jboolean IsSameObject(JNIEnv* pEnv, jobject obj1, jobject obj2) + { + return pEnv->UnwrapRef(obj1) == pEnv->UnwrapRef(obj2) ? JNI_TRUE : JNI_FALSE; + } + + internal static jobject NewLocalRef(JNIEnv* pEnv, jobject obj) + { + return pEnv->MakeLocalRef(pEnv->UnwrapRef(obj)); + } + + internal static jint EnsureLocalCapacity(JNIEnv* pEnv, jint capacity) + { + // since we can dynamically grow the local ref table, we'll just return success for any number + return JNI_OK; + } + + internal static jobject AllocObject(JNIEnv* pEnv, jclass clazz) + { + return AllocObjectImpl(pEnv, TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz))); + } + + private static jobject AllocObjectImpl(JNIEnv* pEnv, TypeWrapper wrapper) + { + try + { + if(wrapper.IsAbstract) + { + SetPendingException(pEnv, new java.lang.InstantiationException(wrapper.Name)); + return IntPtr.Zero; + } + wrapper.Finish(); + return pEnv->MakeLocalRef(System.Runtime.Serialization.FormatterServices.GetUninitializedObject(wrapper.TypeAsBaseType)); + } + catch(RetargetableJavaException x) + { + SetPendingException(pEnv, x.ToJava()); + return IntPtr.Zero; + } + catch(Exception x) + { + SetPendingException(pEnv, x); + return IntPtr.Zero; + } + } + + [StructLayout(LayoutKind.Explicit)] + internal struct jvalue + { + [FieldOffset(0)] + public jboolean z; + [FieldOffset(0)] + public jbyte b; + [FieldOffset(0)] + public jchar c; + [FieldOffset(0)] + public jshort s; + [FieldOffset(0)] + public jint i; + [FieldOffset(0)] + public jlong j; + [FieldOffset(0)] + public jfloat f; + [FieldOffset(0)] + public jdouble d; + [FieldOffset(0)] + public jobject l; + } + + private static object InvokeHelper(JNIEnv* pEnv, jobject objHandle, jmethodID methodID, jvalue* pArgs, bool nonVirtual) + { + ManagedJNIEnv env = pEnv->GetManagedJNIEnv(); + object obj = UnwrapRef(env, objHandle); + MethodWrapper mw = MethodWrapper.FromCookie(methodID); + mw.Link(); + mw.ResolveMethod(); + TypeWrapper[] argTypes = mw.GetParameters(); + object[] args = new object[argTypes.Length + (mw.HasCallerID ? 1 : 0)]; + for (int i = 0; i < argTypes.Length; i++) + { + TypeWrapper type = argTypes[i]; + if (type == PrimitiveTypeWrapper.BOOLEAN) + args[i] = pArgs[i].z != JNI_FALSE; + else if (type == PrimitiveTypeWrapper.BYTE) + args[i] = (byte)pArgs[i].b; + else if (type == PrimitiveTypeWrapper.CHAR) + args[i] = (char)pArgs[i].c; + else if (type == PrimitiveTypeWrapper.SHORT) + args[i] = pArgs[i].s; + else if (type == PrimitiveTypeWrapper.INT) + args[i] = pArgs[i].i; + else if (type == PrimitiveTypeWrapper.LONG) + args[i] = pArgs[i].j; + else if (type == PrimitiveTypeWrapper.FLOAT) + args[i] = pArgs[i].f; + else if (type == PrimitiveTypeWrapper.DOUBLE) + args[i] = pArgs[i].d; + else + args[i] = argTypes[i].GhostWrap(UnwrapRef(env, pArgs[i].l)); + } + if (mw.HasCallerID) + { + args[args.Length - 1] = env.callerID; + } + try + { + if (nonVirtual && mw.RequiresNonVirtualDispatcher) + { + return InvokeNonVirtual(env, mw, obj, args); + } + if (mw.IsConstructor) + { + if (obj == null) + { + return mw.CreateInstance(args); + } + else + { + MethodBase mb = mw.GetMethod(); + if (mb.IsStatic) + { + // we're dealing with a constructor on a remapped type, if obj is supplied, it means + // that we should call the constructor on an already existing instance, but that isn't + // possible with remapped types + throw new NotSupportedException(string.Format("Remapped type {0} doesn't support constructor invocation on an existing instance", mw.DeclaringType.Name)); + } + else if (!mb.DeclaringType.IsInstanceOfType(obj)) + { + // we're trying to initialize an existing instance of a remapped type + throw new NotSupportedException("Unable to partially construct object of type " + obj.GetType().FullName + " to type " + mb.DeclaringType.FullName); + } + } + } + return mw.Invoke(obj, args); + } + catch (Exception x) + { + SetPendingException(pEnv, ikvm.runtime.Util.mapException(x)); + return null; + } + } + + private static object InvokeNonVirtual(ManagedJNIEnv env, MethodWrapper mw, object obj, object[] argarray) + { + if (mw.HasCallerID || mw.IsDynamicOnly) + { + throw new NotSupportedException(); + } + if (mw.DeclaringType.IsRemapped && !mw.DeclaringType.TypeAsBaseType.IsInstanceOfType(obj)) + { + return mw.InvokeNonvirtualRemapped(obj, argarray); + } + else + { + Delegate del = (Delegate)Activator.CreateInstance(mw.GetDelegateType(), + new object[] { obj, mw.GetMethod().MethodHandle.GetFunctionPointer() }); + try + { + return del.DynamicInvoke(argarray); + } + catch (TargetInvocationException x) + { + throw ikvm.runtime.Util.mapException(x.InnerException); + } + } + } + + internal static jobject NewObjectA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args) + { + TypeWrapper wrapper = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz)); + if(!wrapper.IsAbstract && wrapper.TypeAsBaseType.IsAbstract) + { + // static newinstance helper method + return pEnv->MakeLocalRef(InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false)); + } + jobject obj = AllocObjectImpl(pEnv, wrapper); + if(obj != IntPtr.Zero) + { + InvokeHelper(pEnv, obj, methodID, args, false); + if(ExceptionCheck(pEnv) == JNI_TRUE) + { + DeleteLocalRef(pEnv, obj); + obj = IntPtr.Zero; + } + } + return obj; + } + + internal static jclass GetObjectClass(JNIEnv* pEnv, jobject obj) + { + return pEnv->MakeLocalRef(IKVM.NativeCode.ikvm.runtime.Util.getClassFromObject(pEnv->UnwrapRef(obj))); + } + + internal static jboolean IsInstanceOf(JNIEnv* pEnv, jobject obj, jclass clazz) + { + // NOTE if clazz is an interface, this is still the right thing to do + // (i.e. if the object implements the interface, we return true) + java.lang.Class objClass = IKVM.NativeCode.ikvm.runtime.Util.getClassFromObject(pEnv->UnwrapRef(obj)); + TypeWrapper w1 = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz)); + TypeWrapper w2 = TypeWrapper.FromClass(objClass); + return w2.IsAssignableTo(w1) ? JNI_TRUE : JNI_FALSE; + } + + private static MethodWrapper GetMethodImpl(TypeWrapper tw, string name, string sig) + { + for(;;) + { + MethodWrapper mw = tw.GetMethodWrapper(name, sig, true); + if(mw == null || !mw.IsHideFromReflection) + { + return mw; + } + tw = mw.DeclaringType.BaseTypeWrapper; + if(tw == null) + { + return null; + } + } + } + + private static void AppendInterfaces(List list, IList add) + { + foreach (TypeWrapper iface in add) + { + if (!list.Contains(iface)) + { + list.Add(iface); + } + } + } + + private static List TransitiveInterfaces(TypeWrapper tw) + { + List list = new List(); + if (tw.BaseTypeWrapper != null) + { + AppendInterfaces(list, TransitiveInterfaces(tw.BaseTypeWrapper)); + } + foreach (TypeWrapper iface in tw.Interfaces) + { + AppendInterfaces(list, TransitiveInterfaces(iface)); + } + AppendInterfaces(list, tw.Interfaces); + return list; + } + + private static MethodWrapper GetInterfaceMethodImpl(TypeWrapper tw, string name, string sig) + { + foreach (TypeWrapper iface in TransitiveInterfaces(tw)) + { + MethodWrapper mw = iface.GetMethodWrapper(name, sig, false); + if (mw != null && !mw.IsHideFromReflection) + { + return mw; + } + } + return null; + } + + private static jmethodID FindMethodID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig, bool isstatic) + { + try + { + TypeWrapper wrapper = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz)); + wrapper.Finish(); + // if name == NULL, the JDK returns the constructor + string methodname = (IntPtr)name == IntPtr.Zero ? "" : StringFromUTF8(name); + string methodsig = StringFromUTF8(sig); + MethodWrapper mw = null; + // don't allow dotted names! + if(methodsig.IndexOf('.') < 0) + { + methodsig = methodsig.Replace('/', '.'); + if(methodname == "" || methodname == "") + { + mw = wrapper.GetMethodWrapper(methodname, methodsig, false); + } + else + { + mw = GetMethodImpl(wrapper, methodname, methodsig); + if(mw == null) + { + mw = GetInterfaceMethodImpl(wrapper, methodname, methodsig); + } + } + } + if(mw != null && mw.IsStatic == isstatic) + { + mw.Link(); + return mw.Cookie; + } + SetPendingException(pEnv, new java.lang.NoSuchMethodError(string.Format("{0}{1}", methodname, methodsig))); + } + catch(RetargetableJavaException x) + { + SetPendingException(pEnv, x.ToJava()); + } + catch(Exception x) + { + SetPendingException(pEnv, x); + } + return IntPtr.Zero; + } + + internal static jmethodID GetMethodID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig) + { + return FindMethodID(pEnv, clazz, name, sig, false); + } + + internal static jobject CallObjectMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args) + { + return pEnv->MakeLocalRef(InvokeHelper(pEnv, obj, methodID, args, false)); + } + + internal static jboolean CallBooleanMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, false); + if(o != null) + { + return ((bool)o) ? JNI_TRUE : JNI_FALSE; + } + return JNI_FALSE; + } + + internal static jbyte CallByteMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, false); + if(o != null) + { + return (jbyte)(byte)o; + } + return 0; + } + + internal static jchar CallCharMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, false); + if(o != null) + { + return (jchar)(char)o; + } + return 0; + } + + internal static jshort CallShortMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, false); + if(o != null) + { + return (jshort)(short)o; + } + return 0; + } + + internal static jint CallIntMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, false); + if(o != null) + { + return (jint)(int)o; + } + return 0; + } + + internal static jlong CallLongMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, false); + if(o != null) + { + return (jlong)(long)o; + } + return 0; + } + + internal static jfloat CallFloatMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, false); + if(o != null) + { + return (jfloat)(float)o; + } + return 0; + } + + internal static jdouble CallDoubleMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, false); + if(o != null) + { + return (jdouble)(double)o; + } + return 0; + } + + internal static void CallVoidMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args) + { + InvokeHelper(pEnv, obj, methodID, args, false); + } + + internal static jobject CallNonvirtualObjectMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args) + { + return pEnv->MakeLocalRef(InvokeHelper(pEnv, obj, methodID, args, true)); + } + + internal static jboolean CallNonvirtualBooleanMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, true); + if(o != null) + { + return ((bool)o) ? JNI_TRUE : JNI_FALSE; + } + return JNI_FALSE; + } + + internal static jbyte CallNonvirtualByteMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, true); + if(o != null) + { + return (jbyte)(byte)o; + } + return 0; + } + + internal static jchar CallNonvirtualCharMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, true); + if(o != null) + { + return (jchar)(char)o; + } + return 0; + } + + internal static jshort CallNonvirtualShortMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, true); + if(o != null) + { + return (jshort)(short)o; + } + return 0; + } + + internal static jint CallNonvirtualIntMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, true); + if(o != null) + { + return (jint)(int)o; + } + return 0; + } + + internal static jlong CallNonvirtualLongMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, true); + if(o != null) + { + return (jlong)(long)o; + } + return 0; + } + + internal static jfloat CallNonvirtualFloatMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, true); + if(o != null) + { + return (jfloat)(float)o; + } + return 0; + } + + internal static jdouble CallNonvirtualDoubleMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args) + { + object o = InvokeHelper(pEnv, obj, methodID, args, true); + if(o != null) + { + return (jdouble)(double)o; + } + return 0; + } + + internal static void CallNonvirtualVoidMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args) + { + InvokeHelper(pEnv, obj, methodID, args, true); + } + + private static FieldWrapper GetFieldImpl(TypeWrapper tw, string name, string sig) + { + for(;;) + { + FieldWrapper fw = tw.GetFieldWrapper(name, sig); + if(fw == null || !fw.IsHideFromReflection) + { + return fw; + } + tw = fw.DeclaringType.BaseTypeWrapper; + if(tw == null) + { + return null; + } + } + } + + private static jfieldID FindFieldID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig, bool isstatic) + { + try + { + TypeWrapper wrapper = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz)); + wrapper.Finish(); + string fieldsig = StringFromUTF8(sig); + // don't allow dotted names! + if(fieldsig.IndexOf('.') < 0) + { + FieldWrapper fw = GetFieldImpl(wrapper, StringFromUTF8(name), fieldsig.Replace('/', '.')); + if(fw != null) + { + if(fw.IsStatic == isstatic) + { + return fw.Cookie; + } + } + } + SetPendingException(pEnv, new java.lang.NoSuchFieldError((isstatic ? "Static" : "Instance") + " field '" + StringFromUTF8(name) + "' with signature '" + fieldsig + "' not found in class '" + wrapper.Name + "'")); + } + catch(RetargetableJavaException x) + { + SetPendingException(pEnv, x.ToJava()); + } + catch(Exception x) + { + SetPendingException(pEnv, x); + } + return IntPtr.Zero; + } + + internal static jfieldID GetFieldID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig) + { + return FindFieldID(pEnv, clazz, name, sig, false); + } + + private static sun.reflect.FieldAccessor GetFieldAccessor(jfieldID cookie) + { + return (sun.reflect.FieldAccessor)FieldWrapper.FromCookie(cookie).GetFieldAccessorJNI(); + } + + internal static jobject GetObjectField(JNIEnv* pEnv, jobject obj, jfieldID fieldID) + { + return pEnv->MakeLocalRef(GetFieldAccessor(fieldID).get(pEnv->UnwrapRef(obj))); + } + + internal static jboolean GetBooleanField(JNIEnv* pEnv, jobject obj, jfieldID fieldID) + { + return GetFieldAccessor(fieldID).getBoolean(pEnv->UnwrapRef(obj)) ? JNI_TRUE : JNI_FALSE; + } + + internal static jbyte GetByteField(JNIEnv* pEnv, jobject obj, jfieldID fieldID) + { + return (jbyte)GetFieldAccessor(fieldID).getByte(pEnv->UnwrapRef(obj)); + } + + internal static jchar GetCharField(JNIEnv* pEnv, jobject obj, jfieldID fieldID) + { + return (jchar)GetFieldAccessor(fieldID).getChar(pEnv->UnwrapRef(obj)); + } + + internal static jshort GetShortField(JNIEnv* pEnv, jobject obj, jfieldID fieldID) + { + return (jshort)GetFieldAccessor(fieldID).getShort(pEnv->UnwrapRef(obj)); + } + + internal static jint GetIntField(JNIEnv* pEnv, jobject obj, jfieldID fieldID) + { + return (jint)GetFieldAccessor(fieldID).getInt(pEnv->UnwrapRef(obj)); + } + + internal static jlong GetLongField(JNIEnv* pEnv, jobject obj, jfieldID fieldID) + { + return (jlong)GetFieldAccessor(fieldID).getLong(pEnv->UnwrapRef(obj)); + } + + internal static jfloat GetFloatField(JNIEnv* pEnv, jobject obj, jfieldID fieldID) + { + return (jfloat)GetFieldAccessor(fieldID).getFloat(pEnv->UnwrapRef(obj)); + } + + internal static jdouble GetDoubleField(JNIEnv* pEnv, jobject obj, jfieldID fieldID) + { + return (jdouble)GetFieldAccessor(fieldID).getDouble(pEnv->UnwrapRef(obj)); + } + + internal static void SetObjectField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jobject val) + { + GetFieldAccessor(fieldID).set(pEnv->UnwrapRef(obj), pEnv->UnwrapRef(val)); + } + + internal static void SetBooleanField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jboolean val) + { + GetFieldAccessor(fieldID).setBoolean(pEnv->UnwrapRef(obj), val != JNI_FALSE); + } + + internal static void SetByteField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jbyte val) + { + GetFieldAccessor(fieldID).setByte(pEnv->UnwrapRef(obj), (byte)val); + } + + internal static void SetCharField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jchar val) + { + GetFieldAccessor(fieldID).setChar(pEnv->UnwrapRef(obj), (char)val); + } + + internal static void SetShortField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jshort val) + { + GetFieldAccessor(fieldID).setShort(pEnv->UnwrapRef(obj), (short)val); + } + + internal static void SetIntField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jint val) + { + GetFieldAccessor(fieldID).setInt(pEnv->UnwrapRef(obj), (int)val); + } + + internal static void SetLongField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jlong val) + { + GetFieldAccessor(fieldID).setLong(pEnv->UnwrapRef(obj), (long)val); + } + + internal static void SetFloatField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jfloat val) + { + GetFieldAccessor(fieldID).setFloat(pEnv->UnwrapRef(obj), (float)val); + } + + internal static void SetDoubleField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jdouble val) + { + GetFieldAccessor(fieldID).setDouble(pEnv->UnwrapRef(obj), (double)val); + } + + internal static jmethodID GetStaticMethodID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig) + { + return FindMethodID(pEnv, clazz, name, sig, true); + } + + internal static jobject CallStaticObjectMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args) + { + return pEnv->MakeLocalRef(InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false)); + } + + internal static jboolean CallStaticBooleanMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args) + { + object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false); + if(o != null) + { + return ((bool)o) ? JNI_TRUE : JNI_FALSE; + } + return JNI_FALSE; + } + + internal static jbyte CallStaticByteMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args) + { + object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false); + if(o != null) + { + return (jbyte)(byte)o; + } + return 0; + } + + internal static jchar CallStaticCharMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args) + { + object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false); + if(o != null) + { + return (jchar)(char)o; + } + return 0; + } + + internal static jshort CallStaticShortMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args) + { + object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false); + if(o != null) + { + return (jshort)(short)o; + } + return 0; + } + + internal static jint CallStaticIntMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args) + { + object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false); + if(o != null) + { + return (jint)(int)o; + } + return 0; + } + + internal static jlong CallStaticLongMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args) + { + object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false); + if(o != null) + { + return (jlong)(long)o; + } + return 0; + } + + internal static jfloat CallStaticFloatMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args) + { + object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false); + if(o != null) + { + return (jfloat)(float)o; + } + return 0; + } + + internal static jdouble CallStaticDoubleMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args) + { + object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false); + if(o != null) + { + return (jdouble)(double)o; + } + return 0; + } + + internal static void CallStaticVoidMethodA(JNIEnv* pEnv, jclass cls, jmethodID methodID, jvalue * args) + { + InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false); + } + + internal static jfieldID GetStaticFieldID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig) + { + return FindFieldID(pEnv, clazz, name, sig, true); + } + + internal static jobject GetStaticObjectField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID) + { + return pEnv->MakeLocalRef(GetFieldAccessor(fieldID).get(null)); + } + + internal static jboolean GetStaticBooleanField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID) + { + return GetFieldAccessor(fieldID).getBoolean(null) ? JNI_TRUE : JNI_FALSE; + } + + internal static jbyte GetStaticByteField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID) + { + return (jbyte)GetFieldAccessor(fieldID).getByte(null); + } + + internal static jchar GetStaticCharField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID) + { + return (jchar)GetFieldAccessor(fieldID).getChar(null); + } + + internal static jshort GetStaticShortField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID) + { + return (jshort)GetFieldAccessor(fieldID).getShort(null); + } + + internal static jint GetStaticIntField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID) + { + return (jint)GetFieldAccessor(fieldID).getInt(null); + } + + internal static jlong GetStaticLongField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID) + { + return (jlong)GetFieldAccessor(fieldID).getLong(null); + } + + internal static jfloat GetStaticFloatField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID) + { + return (jfloat)GetFieldAccessor(fieldID).getFloat(null); + } + + internal static jdouble GetStaticDoubleField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID) + { + return (jdouble)GetFieldAccessor(fieldID).getDouble(null); + } + + internal static void SetStaticObjectField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jobject val) + { + GetFieldAccessor(fieldID).set(null, pEnv->UnwrapRef(val)); + } + + internal static void SetStaticBooleanField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jboolean val) + { + GetFieldAccessor(fieldID).setBoolean(null, val != JNI_FALSE); + } + + internal static void SetStaticByteField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jbyte val) + { + GetFieldAccessor(fieldID).setByte(null, (byte)val); + } + + internal static void SetStaticCharField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jchar val) + { + GetFieldAccessor(fieldID).setChar(null, (char)val); + } + + internal static void SetStaticShortField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jshort val) + { + GetFieldAccessor(fieldID).setShort(null, (short)val); + } + + internal static void SetStaticIntField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jint val) + { + GetFieldAccessor(fieldID).setInt(null, (int)val); + } + + internal static void SetStaticLongField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jlong val) + { + GetFieldAccessor(fieldID).setLong(null, (long)val); + } + + internal static void SetStaticFloatField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jfloat val) + { + GetFieldAccessor(fieldID).setFloat(null, (float)val); + } + + internal static void SetStaticDoubleField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jdouble val) + { + GetFieldAccessor(fieldID).setDouble(null, (double)val); + } + + internal static jstring NewString(JNIEnv* pEnv, jchar* unicode, int len) + { + return pEnv->MakeLocalRef(new String((char*)unicode, 0, len)); + } + + internal static jint GetStringLength(JNIEnv* pEnv, jstring str) + { + return ((string)pEnv->UnwrapRef(str)).Length; + } + + internal static jchar* GetStringChars(JNIEnv* pEnv, jstring str, jboolean* isCopy) + { + string s = (string)pEnv->UnwrapRef(str); + if(isCopy != null) + { + *isCopy = JNI_TRUE; + } + return (jchar*)(void*)Marshal.StringToHGlobalUni(s); + } + + internal static void ReleaseStringChars(JNIEnv* pEnv, jstring str, jchar* chars) + { + Marshal.FreeHGlobal((IntPtr)(void*)chars); + } + + internal static jobject NewStringUTF(JNIEnv* pEnv, byte* psz) + { + if (psz == null) + { + // The JNI spec does not explicitly allow a null pointer, but the JDK accepts it + return IntPtr.Zero; + } + return pEnv->MakeLocalRef(StringFromUTF8(psz)); + } + + internal static jint GetStringUTFLength(JNIEnv* pEnv, jstring str) + { + return StringUTF8Length((string)pEnv->UnwrapRef(str)); + } + + internal static byte* GetStringUTFChars(JNIEnv* pEnv, jstring str, jboolean* isCopy) + { + string s = (string)pEnv->UnwrapRef(str); + byte* buf = (byte*)JniMem.Alloc(StringUTF8Length(s) + 1); + int j = 0; + for(int i = 0; i < s.Length; i++) + { + char ch = s[i]; + if((ch != 0) && (ch <= 0x7F)) + { + buf[j++] = (byte)ch; + } + else if(ch <= 0x7FF) + { + buf[j++] = (byte)((ch >> 6) | 0xC0); + buf[j++] = (byte)((ch & 0x3F) | 0x80); + } + else + { + buf[j++] = (byte)((ch >> 12) | 0xE0); + buf[j++] = (byte)(((ch >> 6) & 0x3F) | 0x80); + buf[j++] = (byte)((ch & 0x3F) | 0x80); + } + } + buf[j] = 0; + if(isCopy != null) + { + *isCopy = JNI_TRUE; + } + return buf; + } + + internal static void ReleaseStringUTFChars(JNIEnv* pEnv, jstring str, byte* chars) + { + JniMem.Free((IntPtr)(void*)chars); + } + + internal static jsize GetArrayLength(JNIEnv* pEnv, jarray array) + { + return ((Array)pEnv->UnwrapRef(array)).Length; + } + + internal static jobject NewObjectArray(JNIEnv* pEnv, jsize len, jclass clazz, jobject init) + { + try + { + // we want to support (non-primitive) value types so we can't cast to object[] + Array array = Array.CreateInstance(TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz)).TypeAsArrayType, len); + object o = pEnv->UnwrapRef(init); + if(o != null) + { + for(int i = 0; i < array.Length; i++) + { + array.SetValue(o, i); + } + } + return pEnv->MakeLocalRef(array); + } + catch(ArgumentOutOfRangeException) + { + SetPendingException(pEnv, new java.lang.NegativeArraySizeException()); + return IntPtr.Zero; + } + catch(Exception x) + { + SetPendingException(pEnv, x); + return IntPtr.Zero; + } + } + + internal static jobject GetObjectArrayElement(JNIEnv* pEnv, jarray array, jsize index) + { + try + { + // we want to support (non-primitive) value types so we can't cast to object[] + return pEnv->MakeLocalRef(((Array)pEnv->UnwrapRef(array)).GetValue(index)); + } + catch(IndexOutOfRangeException) + { + SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException()); + return IntPtr.Zero; + } + } + + internal static void SetObjectArrayElement(JNIEnv* pEnv, jarray array, jsize index, jobject val) + { + try + { + // we want to support (non-primitive) value types so we can't cast to object[] + ((Array)pEnv->UnwrapRef(array)).SetValue(pEnv->UnwrapRef(val), index); + } + catch(IndexOutOfRangeException) + { + SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException()); + } + } + + internal static jbooleanArray NewBooleanArray(JNIEnv* pEnv, jsize len) + { + try + { + return pEnv->MakeLocalRef(new bool[len]); + } + catch(Exception x) + { + SetPendingException(pEnv, x); + return IntPtr.Zero; + } + } + + internal static jbyteArray NewByteArray(JNIEnv* pEnv, jsize len) + { + try + { + return pEnv->MakeLocalRef(new byte[len]); + } + catch(Exception x) + { + SetPendingException(pEnv, x); + return IntPtr.Zero; + } + } + + internal static jcharArray NewCharArray(JNIEnv* pEnv, jsize len) + { + try + { + return pEnv->MakeLocalRef(new char[len]); + } + catch(Exception x) + { + SetPendingException(pEnv, x); + return IntPtr.Zero; + } + } + + internal static jshortArray NewShortArray(JNIEnv* pEnv, jsize len) + { + try + { + return pEnv->MakeLocalRef(new short[len]); + } + catch(Exception x) + { + SetPendingException(pEnv, x); + return IntPtr.Zero; + } + } + + internal static jintArray NewIntArray(JNIEnv* pEnv, jsize len) + { + try + { + return pEnv->MakeLocalRef(new int[len]); + } + catch(Exception x) + { + SetPendingException(pEnv, x); + return IntPtr.Zero; + } + } + + internal static jlongArray NewLongArray(JNIEnv* pEnv, jsize len) + { + try + { + return pEnv->MakeLocalRef(new long[len]); + } + catch(Exception x) + { + SetPendingException(pEnv, x); + return IntPtr.Zero; + } + } + + internal static jfloatArray NewFloatArray(JNIEnv* pEnv, jsize len) + { + try + { + return pEnv->MakeLocalRef(new float[len]); + } + catch(Exception x) + { + SetPendingException(pEnv, x); + return IntPtr.Zero; + } + } + + internal static jdoubleArray NewDoubleArray(JNIEnv* pEnv, jsize len) + { + try + { + return pEnv->MakeLocalRef(new double[len]); + } + catch(Exception x) + { + SetPendingException(pEnv, x); + return IntPtr.Zero; + } + } + + internal static jboolean* GetBooleanArrayElements(JNIEnv* pEnv, jbooleanArray array, jboolean* isCopy) + { + bool[] b = (bool[])pEnv->UnwrapRef(array); + jboolean* p = (jboolean*)(void*)JniMem.Alloc(b.Length * 1); + for(int i = 0; i < b.Length; i++) + { + p[i] = b[i] ? JNI_TRUE : JNI_FALSE; + } + if(isCopy != null) + { + *isCopy = JNI_TRUE; + } + return p; + } + + internal static jbyte* GetByteArrayElements(JNIEnv* pEnv, jbyteArray array, jboolean* isCopy) + { + byte[] b = (byte[])pEnv->UnwrapRef(array); + jbyte* p = (jbyte*)(void*)JniMem.Alloc(b.Length * 1); + for(int i = 0; i < b.Length; i++) + { + p[i] = (jbyte)b[i]; + } + if(isCopy != null) + { + *isCopy = JNI_TRUE; + } + return p; + } + + internal static jchar* GetCharArrayElements(JNIEnv* pEnv, jcharArray array, jboolean* isCopy) + { + char[] b = (char[])pEnv->UnwrapRef(array); + IntPtr buf = JniMem.Alloc(b.Length * 2); + Marshal.Copy(b, 0, buf, b.Length); + if(isCopy != null) + { + *isCopy = JNI_TRUE; + } + return (jchar*)(void*)buf; + } + + internal static jshort* GetShortArrayElements(JNIEnv* pEnv, jshortArray array, jboolean* isCopy) + { + short[] b = (short[])pEnv->UnwrapRef(array); + IntPtr buf = JniMem.Alloc(b.Length * 2); + Marshal.Copy(b, 0, buf, b.Length); + if(isCopy != null) + { + *isCopy = JNI_TRUE; + } + return (jshort*)(void*)buf; + } + + internal static jint* GetIntArrayElements(JNIEnv* pEnv, jintArray array, jboolean* isCopy) + { + int[] b = (int[])pEnv->UnwrapRef(array); + IntPtr buf = JniMem.Alloc(b.Length * 4); + Marshal.Copy(b, 0, buf, b.Length); + if(isCopy != null) + { + *isCopy = JNI_TRUE; + } + return (jint*)(void*)buf; + } + + internal static jlong* GetLongArrayElements(JNIEnv* pEnv, jlongArray array, jboolean* isCopy) + { + long[] b = (long[])pEnv->UnwrapRef(array); + IntPtr buf = JniMem.Alloc(b.Length * 8); + Marshal.Copy(b, 0, buf, b.Length); + if(isCopy != null) + { + *isCopy = JNI_TRUE; + } + return (jlong*)(void*)buf; + } + + internal static jfloat* GetFloatArrayElements(JNIEnv* pEnv, jfloatArray array, jboolean* isCopy) + { + float[] b = (float[])pEnv->UnwrapRef(array); + IntPtr buf = JniMem.Alloc(b.Length * 4); + Marshal.Copy(b, 0, buf, b.Length); + if(isCopy != null) + { + *isCopy = JNI_TRUE; + } + return (jfloat*)(void*)buf; + } + + internal static jdouble* GetDoubleArrayElements(JNIEnv* pEnv, jdoubleArray array, jboolean* isCopy) + { + double[] b = (double[])pEnv->UnwrapRef(array); + IntPtr buf = JniMem.Alloc(b.Length * 8); + Marshal.Copy(b, 0, buf, b.Length); + if(isCopy != null) + { + *isCopy = JNI_TRUE; + } + return (jdouble*)(void*)buf; + } + + internal static void ReleaseBooleanArrayElements(JNIEnv* pEnv, jbooleanArray array, jboolean* elems, jint mode) + { + if(mode == 0 || mode == JNI_COMMIT) + { + bool[] b = (bool[])pEnv->UnwrapRef(array); + for(int i = 0; i < b.Length; i++) + { + b[i] = elems[i] != JNI_FALSE; + } + } + if(mode == 0 || mode == JNI_ABORT) + { + JniMem.Free((IntPtr)(void*)elems); + } + } + + internal static void ReleaseByteArrayElements(JNIEnv* pEnv, jbyteArray array, jbyte* elems, jint mode) + { + if(mode == 0 || mode == JNI_COMMIT) + { + byte[] b = (byte[])pEnv->UnwrapRef(array); + for(int i = 0; i < b.Length; i++) + { + b[i] = (byte)elems[i]; + } + } + if(mode == 0 || mode == JNI_ABORT) + { + JniMem.Free((IntPtr)(void*)elems); + } + } + + internal static void ReleaseCharArrayElements(JNIEnv* pEnv, jcharArray array, jchar* elems, jint mode) + { + if(mode == 0 || mode == JNI_COMMIT) + { + char[] b = (char[])pEnv->UnwrapRef(array); + Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length); + } + if(mode == 0 || mode == JNI_ABORT) + { + JniMem.Free((IntPtr)(void*)elems); + } + } + + internal static void ReleaseShortArrayElements(JNIEnv* pEnv, jshortArray array, jshort* elems, jint mode) + { + if(mode == 0 || mode == JNI_COMMIT) + { + short[] b = (short[])pEnv->UnwrapRef(array); + Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length); + } + if(mode == 0 || mode == JNI_ABORT) + { + JniMem.Free((IntPtr)(void*)elems); + } + } + + internal static void ReleaseIntArrayElements(JNIEnv* pEnv, jintArray array, jint* elems, jint mode) + { + if(mode == 0 || mode == JNI_COMMIT) + { + int[] b = (int[])pEnv->UnwrapRef(array); + Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length); + } + if(mode == 0 || mode == JNI_ABORT) + { + JniMem.Free((IntPtr)(void*)elems); + } + } + + internal static void ReleaseLongArrayElements(JNIEnv* pEnv, jlongArray array, jlong* elems, jint mode) + { + if(mode == 0 || mode == JNI_COMMIT) + { + long[] b = (long[])pEnv->UnwrapRef(array); + Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length); + } + if(mode == 0 || mode == JNI_ABORT) + { + JniMem.Free((IntPtr)(void*)elems); + } + } + + internal static void ReleaseFloatArrayElements(JNIEnv* pEnv, jfloatArray array, jfloat* elems, jint mode) + { + if(mode == 0 || mode == JNI_COMMIT) + { + float[] b = (float[])pEnv->UnwrapRef(array); + Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length); + } + if(mode == 0 || mode == JNI_ABORT) + { + JniMem.Free((IntPtr)(void*)elems); + } + } + + internal static void ReleaseDoubleArrayElements(JNIEnv* pEnv, jdoubleArray array, jdouble* elems, jint mode) + { + if(mode == 0 || mode == JNI_COMMIT) + { + double[] b = (double[])pEnv->UnwrapRef(array); + Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length); + } + if(mode == 0 || mode == JNI_ABORT) + { + JniMem.Free((IntPtr)(void*)elems); + } + } + + internal static void GetBooleanArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + try + { + bool[] b = (bool[])pEnv->UnwrapRef(array); + sbyte* p = (sbyte*)(void*)buf; + for(int i = 0; i < len; i++) + { + *p++ = b[start + i] ? JNI_TRUE : JNI_FALSE; + } + } + catch(IndexOutOfRangeException) + { + SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException()); + } + } + + internal static void GetByteArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + try + { + byte[] b = (byte[])pEnv->UnwrapRef(array); + byte* p = (byte*)(void*)buf; + for(int i = 0; i < len; i++) + { + *p++ = b[start + i]; + } + } + catch(IndexOutOfRangeException) + { + SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException()); + } + } + + internal static void GetCharArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + try + { + char[] b = (char[])pEnv->UnwrapRef(array); + Marshal.Copy(b, start, buf, len); + } + catch(ArgumentOutOfRangeException) + { + SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException()); + } + } + + internal static void GetShortArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + try + { + short[] b = (short[])pEnv->UnwrapRef(array); + Marshal.Copy(b, start, buf, len); + } + catch(ArgumentOutOfRangeException) + { + SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException()); + } + } + + internal static void GetIntArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + try + { + int[] b = (int[])pEnv->UnwrapRef(array); + Marshal.Copy(b, start, buf, len); + } + catch(ArgumentOutOfRangeException) + { + SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException()); + } + } + + internal static void GetLongArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + try + { + long[] b = (long[])pEnv->UnwrapRef(array); + Marshal.Copy(b, start, buf, len); + } + catch(ArgumentOutOfRangeException) + { + SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException()); + } + } + + internal static void GetFloatArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + try + { + float[] b = (float[])pEnv->UnwrapRef(array); + Marshal.Copy(b, start, buf, len); + } + catch(ArgumentOutOfRangeException) + { + SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException()); + } + } + + internal static void GetDoubleArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + try + { + double[] b = (double[])pEnv->UnwrapRef(array); + Marshal.Copy(b, start, buf, len); + } + catch(ArgumentOutOfRangeException) + { + SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException()); + } + } + + internal static void SetBooleanArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + try + { + bool[] b = (bool[])pEnv->UnwrapRef(array); + sbyte* p = (sbyte*)(void*)buf; + for(int i = 0; i < len; i++) + { + b[start + i] = *p++ != JNI_FALSE; + } + } + catch(IndexOutOfRangeException) + { + SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException()); + } + } + + internal static void SetByteArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + try + { + byte[] b = (byte[])pEnv->UnwrapRef(array); + byte* p = (byte*)(void*)buf; + for(int i = 0; i < len; i++) + { + b[start + i] = *p++; + } + } + catch(IndexOutOfRangeException) + { + SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException()); + } + } + + internal static void SetCharArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + try + { + char[] b = (char[])pEnv->UnwrapRef(array); + Marshal.Copy(buf, b, start, len); + } + catch(ArgumentOutOfRangeException) + { + SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException()); + } + } + + internal static void SetShortArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + try + { + short[] b = (short[])pEnv->UnwrapRef(array); + Marshal.Copy(buf, b, start, len); + } + catch(ArgumentOutOfRangeException) + { + SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException()); + } + } + + internal static void SetIntArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + try + { + int[] b = (int[])pEnv->UnwrapRef(array); + Marshal.Copy(buf, b, start, len); + } + catch(ArgumentOutOfRangeException) + { + SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException()); + } + } + + internal static void SetLongArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + try + { + long[] b = (long[])pEnv->UnwrapRef(array); + Marshal.Copy(buf, b, start, len); + } + catch(ArgumentOutOfRangeException) + { + SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException()); + } + } + + internal static void SetFloatArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + try + { + float[] b = (float[])pEnv->UnwrapRef(array); + Marshal.Copy(buf, b, start, len); + } + catch(ArgumentOutOfRangeException) + { + SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException()); + } + } + + internal static void SetDoubleArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf) + { + try + { + double[] b = (double[])pEnv->UnwrapRef(array); + Marshal.Copy(buf, b, start, len); + } + catch(ArgumentOutOfRangeException) + { + SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException()); + } + } + + [StructLayout(LayoutKind.Sequential)] + unsafe internal struct JNINativeMethod + { + public byte* name; + public byte* signature; + public void* fnPtr; + } + + internal static int RegisterNatives(JNIEnv* pEnv, IntPtr clazz, JNINativeMethod* methods, int nMethods) + { + try + { + TypeWrapper wrapper = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz)); + wrapper.Finish(); + for(int i = 0; i < nMethods; i++) + { + string methodName = StringFromUTF8(methods[i].name); + string methodSig = StringFromUTF8(methods[i].signature); + Tracer.Info(Tracer.Jni, "Registering native method: {0}.{1}{2}, fnPtr = 0x{3:X}", wrapper.Name, methodName, methodSig, ((IntPtr)methods[i].fnPtr).ToInt64()); + FieldInfo fi = null; + // don't allow dotted names! + if(methodSig.IndexOf('.') < 0) + { + // TODO this won't work when we're putting the JNI methods in jniproxy.dll + fi = wrapper.TypeAsTBD.GetField(JNI.METHOD_PTR_FIELD_PREFIX + methodName + methodSig, BindingFlags.Static | BindingFlags.NonPublic); + } + if(fi == null) + { + Tracer.Error(Tracer.Jni, "Failed to register native method: {0}.{1}{2}", wrapper.Name, methodName, methodSig); + SetPendingException(pEnv, new java.lang.NoSuchMethodError(methodName)); + return JNI_ERR; + } + fi.SetValue(null, (IntPtr)methods[i].fnPtr); + } + return JNI_OK; + } + catch(RetargetableJavaException x) + { + SetPendingException(pEnv, x.ToJava()); + return JNI_ERR; + } + catch(Exception x) + { + SetPendingException(pEnv, x); + return JNI_ERR; + } + } + + internal static int UnregisterNatives(JNIEnv* pEnv, IntPtr clazz) + { + try + { + TypeWrapper wrapper = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz)); + wrapper.Finish(); + // TODO this won't work when we're putting the JNI methods in jniproxy.dll + foreach(FieldInfo fi in wrapper.TypeAsTBD.GetFields(BindingFlags.Static | BindingFlags.NonPublic)) + { + string name = fi.Name; + if(name.StartsWith(JNI.METHOD_PTR_FIELD_PREFIX)) + { + Tracer.Info(Tracer.Jni, "Unregistering native method: {0}.{1}", wrapper.Name, name.Substring(JNI.METHOD_PTR_FIELD_PREFIX.Length)); + fi.SetValue(null, IntPtr.Zero); + } + } + return JNI_OK; + } + catch(RetargetableJavaException x) + { + SetPendingException(pEnv, x.ToJava()); + return JNI_ERR; + } + catch(Exception x) + { + SetPendingException(pEnv, x); + return JNI_ERR; + } + } + + internal static int MonitorEnter(JNIEnv* pEnv, IntPtr obj) + { + try + { + // on .NET 4.0 Monitor.Enter has been marked obsolete, + // but in this case the alternative adds no value +#pragma warning disable 618 + System.Threading.Monitor.Enter(pEnv->UnwrapRef(obj)); +#pragma warning restore 618 + return JNI_OK; + } + catch(Exception x) + { + SetPendingException(pEnv, x); + return JNI_ERR; + } + } + + internal static int MonitorExit(JNIEnv* pEnv, IntPtr obj) + { + try + { + System.Threading.Monitor.Exit(pEnv->UnwrapRef(obj)); + return JNI_OK; + } + catch(Exception x) + { + SetPendingException(pEnv, x); + return JNI_ERR; + } + } + + internal static int GetJavaVM(JNIEnv* pEnv, JavaVM **ppJavaVM) + { + *ppJavaVM = JavaVM.pJavaVM; + return JNI_OK; + } + + internal static void GetStringRegion(JNIEnv* pEnv, IntPtr str, int start, int len, IntPtr buf) + { + string s = (string)pEnv->UnwrapRef(str); + if(s != null) + { + if(start < 0 || start > s.Length || s.Length - start < len) + { + SetPendingException(pEnv, new java.lang.StringIndexOutOfBoundsException()); + return; + } + else + { + char* p = (char*)(void*)buf; + // TODO isn't there a managed memcpy? + for(int i = 0; i < len; i++) + { + *p++ = s[start + i]; + } + return; + } + } + else + { + SetPendingException(pEnv, new java.lang.NullPointerException()); + } + } + + internal static void GetStringUTFRegion(JNIEnv* pEnv, IntPtr str, int start, int len, IntPtr buf) + { + string s = (string)pEnv->UnwrapRef(str); + if(s != null) + { + if(start < 0 || start > s.Length || s.Length - start < len) + { + SetPendingException(pEnv, new java.lang.StringIndexOutOfBoundsException()); + return; + } + else + { + byte* p = (byte*)(void*)buf; + for(int i = 0; i < len; i++) + { + char ch = s[start + i]; + if((ch != 0) && (ch <= 0x7F)) + { + *p++ = (byte)ch; + } + else if(ch <= 0x7FF) + { + *p++ = (byte)((ch >> 6) | 0xC0); + *p++ = (byte)((ch & 0x3F) | 0x80); + } + else + { + *p++ = (byte)((ch >> 12) | 0xE0); + *p++ = (byte)(((ch >> 6) & 0x3F) | 0x80); + *p++ = (byte)((ch & 0x3F) | 0x80); + } + } + return; + } + } + else + { + SetPendingException(pEnv, new java.lang.NullPointerException()); + } + } + + private void* PinObject(object obj) + { + if(pinHandleInUseCount == pinHandleMaxCount) + { + int newCount = pinHandleMaxCount + 32; + GCHandle* pNew = (GCHandle*)JniMem.Alloc(sizeof(GCHandle) * newCount); + for(int i = 0; i < pinHandleMaxCount; i++) + { + pNew[i] = pinHandles[i]; + } + for(int i = pinHandleMaxCount; i < newCount; i++) + { + pNew[i] = new GCHandle(); + } + JniMem.Free((IntPtr)pinHandles); + pinHandles = pNew; + pinHandleMaxCount = newCount; + } + int index = pinHandleInUseCount++; + if(!pinHandles[index].IsAllocated) + { + pinHandles[index] = GCHandle.Alloc(null, GCHandleType.Pinned); + } + pinHandles[index].Target = obj; + return (void*)pinHandles[index].AddrOfPinnedObject(); + } + + private void UnpinObject(object obj) + { + for(int i = 0; i < pinHandleInUseCount; i++) + { + if(pinHandles[i].Target == obj) + { + pinHandles[i].Target = pinHandles[--pinHandleInUseCount].Target; + pinHandles[pinHandleInUseCount].Target = null; + return; + } + } + } + + internal static void* GetPrimitiveArrayCritical(JNIEnv* pEnv, jarray array, jboolean* isCopy) + { + if(isCopy != null) + { + *isCopy = JNI_FALSE; + } + return pEnv->PinObject(pEnv->UnwrapRef(array)); + } + + internal static void ReleasePrimitiveArrayCritical(JNIEnv* pEnv, jarray array, void* carray, jint mode) + { + pEnv->UnpinObject(pEnv->UnwrapRef(array)); + } + + internal static jchar* GetStringCritical(JNIEnv* pEnv, jstring str, jboolean* isCopy) + { + if(isCopy != null) + { + *isCopy = JNI_FALSE; + } + return (jchar*)pEnv->PinObject(pEnv->UnwrapRef(str)); + } + + internal static void ReleaseStringCritical(JNIEnv* pEnv, jstring str, jchar* cstring) + { + pEnv->UnpinObject(pEnv->UnwrapRef(str)); + } + + internal static jweak NewWeakGlobalRef(JNIEnv* pEnv, jobject obj) + { + object o = pEnv->UnwrapRef(obj); + if(o == null) + { + return IntPtr.Zero; + } + lock(GlobalRefs.weakRefLock) + { + for(int i = 0; i < GlobalRefs.weakRefs.Length; i++) + { + if(!GlobalRefs.weakRefs[i].IsAllocated) + { + GlobalRefs.weakRefs[i] = GCHandle.Alloc(o, GCHandleType.WeakTrackResurrection); + return (IntPtr)(- (i | (1 << 30))); + } + } + int len = GlobalRefs.weakRefs.Length; + GCHandle[] tmp = new GCHandle[len * 2]; + Array.Copy(GlobalRefs.weakRefs, 0, tmp, 0, len); + tmp[len] = GCHandle.Alloc(o, GCHandleType.WeakTrackResurrection); + GlobalRefs.weakRefs = tmp; + return (IntPtr)(- (len | (1 << 30))); + } + } + + internal static void DeleteWeakGlobalRef(JNIEnv* pEnv, jweak obj) + { + int i = obj.ToInt32(); + if(i < 0) + { + i = -i; + i -= (1 << 30); + lock(GlobalRefs.weakRefLock) + { + GlobalRefs.weakRefs[i].Free(); + } + } + if(i > 0) + { + Debug.Assert(false, "local ref passed to DeleteWeakGlobalRef"); + } + } + + internal static jboolean ExceptionCheck(JNIEnv* pEnv) + { + ManagedJNIEnv env = pEnv->GetManagedJNIEnv(); + return env.pendingException != null ? JNI_TRUE : JNI_FALSE; + } + + internal static jobject NewDirectByteBuffer(JNIEnv* pEnv, IntPtr address, jlong capacity) + { + try + { + if(capacity < 0 || capacity > int.MaxValue) + { + SetPendingException(pEnv, new java.lang.IllegalArgumentException("capacity")); + return IntPtr.Zero; + } + return pEnv->MakeLocalRef(JVM.NewDirectByteBuffer(address.ToInt64(), (int)capacity)); + } + catch(Exception x) + { + SetPendingException(pEnv, ikvm.runtime.Util.mapException(x)); + return IntPtr.Zero; + } + } + + internal static IntPtr GetDirectBufferAddress(JNIEnv* pEnv, jobject buf) + { + try + { + return (IntPtr)((sun.nio.ch.DirectBuffer)pEnv->UnwrapRef(buf)).address(); + } + catch(Exception x) + { + SetPendingException(pEnv, ikvm.runtime.Util.mapException(x)); + return IntPtr.Zero; + } + } + + internal static jlong GetDirectBufferCapacity(JNIEnv* pEnv, jobject buf) + { + try + { + return (jlong)(long)((java.nio.Buffer)pEnv->UnwrapRef(buf)).capacity(); + } + catch(Exception x) + { + SetPendingException(pEnv, ikvm.runtime.Util.mapException(x)); + return 0; + } + } + + internal static int GetObjectRefType(JNIEnv* pEnv, jobject obj) + { + int i = obj.ToInt32(); + if(i >= 0) + { + return JNILocalRefType; + } + i = -i; + if((i & (1 << 30)) != 0) + { + return JNIWeakGlobalRefType; + } + else + { + return JNIGlobalRefType; + } + } + + internal IntPtr MakeLocalRef(object obj) + { + return GetManagedJNIEnv().MakeLocalRef(obj); + } + + internal object UnwrapRef(IntPtr o) + { + int i = o.ToInt32(); + if(i > 0) + { + return GetManagedJNIEnv().UnwrapLocalRef(i); + } + if(i < 0) + { + return GlobalRefs.Unwrap(i); + } + return null; + } + + internal static object UnwrapRef(ManagedJNIEnv env, IntPtr o) + { + int i = o.ToInt32(); + if(i > 0) + { + return env.UnwrapLocalRef(i); + } + if(i < 0) + { + return GlobalRefs.Unwrap(i); + } + return null; + } + } + + static class JniMem + { + internal static IntPtr Alloc(int cb) + { + return Marshal.AllocHGlobal(cb); + } + + internal static void Free(IntPtr p) + { + Marshal.FreeHGlobal(p); + } + } + + static class TlsHack + { + [ThreadStatic] + internal static JNIEnv.ManagedJNIEnv ManagedJNIEnv; + } +} diff --git a/runtime/JsrInliner.cs b/runtime/JsrInliner.cs new file mode 100644 index 0000000..cea7484 --- /dev/null +++ b/runtime/JsrInliner.cs @@ -0,0 +1,2062 @@ +/* + Copyright (C) 2002-2010 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using InstructionFlags = IKVM.Internal.ClassFile.Method.InstructionFlags; + +namespace IKVM.Internal +{ + sealed class JsrInliner + { + private ClassFile.Method.Instruction[] codeCopy; + private int codeLength; + private InstructionFlags[] flags; + private readonly ClassFile.Method m; + private readonly JsrMethodAnalyzer ma; + + internal static void InlineJsrs(ClassLoaderWrapper classLoader, MethodWrapper mw, ClassFile classFile, ClassFile.Method m) + { + JsrInliner inliner; + do + { + ClassFile.Method.Instruction[] codeCopy = (ClassFile.Method.Instruction[])m.Instructions.Clone(); + InstructionFlags[] flags = new InstructionFlags[codeCopy.Length]; + JsrMethodAnalyzer ma = new JsrMethodAnalyzer(mw, classFile, m, classLoader, flags); + inliner = new JsrInliner(codeCopy, flags, m, ma); + } while (inliner.InlineJsrs()); + } + + private JsrInliner(ClassFile.Method.Instruction[] codeCopy, InstructionFlags[] flags, ClassFile.Method m, JsrMethodAnalyzer ma) + { + this.codeCopy = codeCopy; + codeLength = codeCopy.Length; + this.flags = flags; + this.m = m; + this.ma = ma; + } + + private void Add(ClassFile.Method.Instruction instr) + { + if (codeLength == codeCopy.Length) + { + Array.Resize(ref codeCopy, codeLength * 2); + Array.Resize(ref flags, codeLength * 2); + } + codeCopy[codeLength++] = instr; + } + + private bool InlineJsrs() + { + bool hasJsrs = false; + List subs = new List(); + int len = codeLength; + for (int i = 0; i < len; i++) + { + // note that we're also (needlessly) processing the subroutines here, but that shouldn't be a problem (just a minor waste of cpu) + // because the code is unreachable anyway + if ((flags[i] & InstructionFlags.Reachable) != 0 && m.Instructions[i].NormalizedOpCode == NormalizedByteCode.__jsr) + { + int subroutineId = m.Instructions[i].TargetIndex; + codeCopy[i].PatchOpCode(NormalizedByteCode.__goto, codeLength); + SubroutineCall sub = new SubroutineCall(this, subroutineId, i + 1); + hasJsrs |= sub.InlineSubroutine(); + subs.Add(sub); + } + } + List exceptions = new List(m.ExceptionTable); + foreach (SubroutineCall sub in subs) + { + sub.DoExceptions(m.ExceptionTable, exceptions); + } + m.ExceptionTable = exceptions.ToArray(); + ClassFile.Method.Instruction instr = new ClassFile.Method.Instruction(); + instr.SetTermNop(0xFFFF); + Add(instr); + Array.Resize(ref codeCopy, codeLength); + + m.Instructions = codeCopy; + return hasJsrs; + } + + private sealed class SubroutineCall + { + private readonly JsrInliner inliner; + private readonly int subroutineIndex; + private readonly int returnIndex; + private readonly int[] branchMap; + private readonly int baseIndex; + private int endIndex; + + internal SubroutineCall(JsrInliner inliner, int subroutineIndex, int returnIndex) + { + this.inliner = inliner; + this.subroutineIndex = subroutineIndex; + this.returnIndex = returnIndex; + baseIndex = inliner.codeLength; + branchMap = new int[inliner.m.Instructions.Length]; + for (int i = 0; i < branchMap.Length; i++) + { + branchMap[i] = i; + } + } + + private void Emit(ClassFile.Method.Instruction instr) + { + inliner.Add(instr); + } + + private void EmitGoto(int targetIndex) + { + ClassFile.Method.Instruction instr = new ClassFile.Method.Instruction(); + instr.PatchOpCode(NormalizedByteCode.__goto, targetIndex); + instr.SetPC(-1); + Emit(instr); + } + + internal bool InlineSubroutine() + { + bool hasJsrs = false; + // start with a pre-amble to load a dummy return address on the stack and to branch to the subroutine + { + // TODO consider exception handling around these instructions + ClassFile.Method.Instruction instr = new ClassFile.Method.Instruction(); + instr.PatchOpCode(NormalizedByteCode.__aconst_null); + instr.SetPC(inliner.m.Instructions[subroutineIndex].PC); + Emit(instr); + EmitGoto(subroutineIndex); + } + + bool fallThru = false; + for (int instructionIndex = 0; instructionIndex < inliner.m.Instructions.Length; instructionIndex++) + { + if ((inliner.flags[instructionIndex] & InstructionFlags.Reachable) != 0 + && inliner.ma.IsSubroutineActive(instructionIndex, subroutineIndex)) + { + fallThru = false; + branchMap[instructionIndex] = inliner.codeLength; + switch (inliner.m.Instructions[instructionIndex].NormalizedOpCode) + { + case NormalizedByteCode.__tableswitch: + case NormalizedByteCode.__lookupswitch: + case NormalizedByteCode.__ireturn: + case NormalizedByteCode.__lreturn: + case NormalizedByteCode.__freturn: + case NormalizedByteCode.__dreturn: + case NormalizedByteCode.__areturn: + case NormalizedByteCode.__return: + case NormalizedByteCode.__athrow: + case NormalizedByteCode.__goto: + Emit(inliner.m.Instructions[instructionIndex]); + break; + case NormalizedByteCode.__jsr: + hasJsrs = true; + goto default; + case NormalizedByteCode.__ret: + { + int subid = inliner.ma.GetLocalTypeWrapper(instructionIndex, inliner.m.Instructions[instructionIndex].TargetIndex).SubroutineIndex; + if (subid == subroutineIndex) + { + EmitGoto(returnIndex); + } + else + { + Emit(inliner.m.Instructions[instructionIndex]); + } + break; + } + default: + fallThru = true; + Emit(inliner.m.Instructions[instructionIndex]); + break; + } + } + else if (fallThru) + { + EmitGoto(instructionIndex); + } + } + + endIndex = inliner.codeLength; + DoFixups(); + return hasJsrs; + } + + private void DoFixups() + { + for (int instructionIndex = baseIndex; instructionIndex < endIndex; instructionIndex++) + { + switch (inliner.codeCopy[instructionIndex].NormalizedOpCode) + { + case NormalizedByteCode.__lookupswitch: + case NormalizedByteCode.__tableswitch: + { + int[] targets = new int[inliner.codeCopy[instructionIndex].SwitchEntryCount]; + for (int i = 0; i < targets.Length; i++) + { + targets[i] = branchMap[inliner.codeCopy[instructionIndex].GetSwitchTargetIndex(i)]; + } + inliner.codeCopy[instructionIndex].SetSwitchTargets(targets); + inliner.codeCopy[instructionIndex].DefaultTarget = branchMap[inliner.codeCopy[instructionIndex].DefaultTarget]; + } + break; + case NormalizedByteCode.__ifeq: + case NormalizedByteCode.__ifne: + case NormalizedByteCode.__iflt: + case NormalizedByteCode.__ifge: + case NormalizedByteCode.__ifgt: + case NormalizedByteCode.__ifle: + case NormalizedByteCode.__if_icmpeq: + case NormalizedByteCode.__if_icmpne: + case NormalizedByteCode.__if_icmplt: + case NormalizedByteCode.__if_icmpge: + case NormalizedByteCode.__if_icmpgt: + case NormalizedByteCode.__if_icmple: + case NormalizedByteCode.__if_acmpeq: + case NormalizedByteCode.__if_acmpne: + case NormalizedByteCode.__ifnull: + case NormalizedByteCode.__ifnonnull: + case NormalizedByteCode.__goto: + case NormalizedByteCode.__jsr: + inliner.codeCopy[instructionIndex].TargetIndex = branchMap[inliner.codeCopy[instructionIndex].TargetIndex]; + break; + } + } + } + + private int MapExceptionStartEnd(int index) + { + while (branchMap[index] < baseIndex) + { + index++; + if (index == branchMap.Length) + { + return endIndex; + } + } + return branchMap[index]; + } + + internal void DoExceptions(ClassFile.Method.ExceptionTableEntry[] table, List newExceptions) + { + foreach (ClassFile.Method.ExceptionTableEntry entry in table) + { + int start = MapExceptionStartEnd(entry.startIndex); + int end = MapExceptionStartEnd(entry.endIndex); + if (start != end) + { + ClassFile.Method.ExceptionTableEntry newEntry = new ClassFile.Method.ExceptionTableEntry(start, end, branchMap[entry.handlerIndex], entry.catch_type, entry.ordinal); + newExceptions.Add(newEntry); + } + } + } + } + + class SimpleType + { + internal static readonly SimpleType Invalid = null; + internal static readonly SimpleType Primitive = new SimpleType(); + internal static readonly SimpleType WidePrimitive = new SimpleType(); + internal static readonly SimpleType Object = new SimpleType(); + internal static readonly SimpleType[] EmptyArray = new SimpleType[0]; + + private SimpleType() { } + + internal bool IsPrimitive + { + get + { + return this == SimpleType.Primitive + || this == SimpleType.WidePrimitive; + } + } + + internal bool IsWidePrimitive + { + get + { + return this == SimpleType.WidePrimitive; + } + } + + private sealed class ReturnAddressType : SimpleType + { + internal readonly int subroutineIndex; + + internal ReturnAddressType(int subroutineIndex) + { + this.subroutineIndex = subroutineIndex; + } + } + + internal static SimpleType MakeRet(int subroutineIndex) + { + return new ReturnAddressType(subroutineIndex); + } + + internal static bool IsRet(SimpleType w) + { + return w is ReturnAddressType; + } + + internal int SubroutineIndex + { + get + { + return ((ReturnAddressType)this).subroutineIndex; + } + } + } + + sealed class JsrMethodAnalyzer + { + private ClassFile classFile; + private InstructionState[] state; + private List[] callsites; + private List[] returnsites; + + internal JsrMethodAnalyzer(MethodWrapper mw, ClassFile classFile, ClassFile.Method method, ClassLoaderWrapper classLoader, InstructionFlags[] flags) + { + if (method.VerifyError != null) + { + throw new VerifyError(method.VerifyError); + } + + this.classFile = classFile; + state = new InstructionState[method.Instructions.Length]; + callsites = new List[method.Instructions.Length]; + returnsites = new List[method.Instructions.Length]; + + // because types have to have identity, the subroutine return address types are cached here + Dictionary returnAddressTypes = new Dictionary(); + + try + { + // ensure that exception blocks and handlers start and end at instruction boundaries + for (int i = 0; i < method.ExceptionTable.Length; i++) + { + int start = method.ExceptionTable[i].startIndex; + int end = method.ExceptionTable[i].endIndex; + int handler = method.ExceptionTable[i].handlerIndex; + if (start >= end || start == -1 || end == -1 || handler <= 0) + { + throw new IndexOutOfRangeException(); + } + } + } + catch (IndexOutOfRangeException) + { + throw new ClassFormatError(string.Format("Illegal exception table (class: {0}, method: {1}, signature: {2}", classFile.Name, method.Name, method.Signature)); + } + + // start by computing the initial state, the stack is empty and the locals contain the arguments + state[0] = new InstructionState(method.MaxLocals, method.MaxStack); + SimpleType thisType; + int firstNonArgLocalIndex = 0; + if (!method.IsStatic) + { + thisType = SimpleType.Object; + state[0].SetLocalType(firstNonArgLocalIndex++, thisType, -1); + } + else + { + thisType = null; + } + TypeWrapper[] argTypeWrappers = mw.GetParameters(); + for (int i = 0; i < argTypeWrappers.Length; i++) + { + TypeWrapper tw = argTypeWrappers[i]; + SimpleType type; + if (tw.IsWidePrimitive) + { + type = SimpleType.WidePrimitive; + } + else if (tw.IsPrimitive) + { + type = SimpleType.Primitive; + } + else + { + type = SimpleType.Object; + } + state[0].SetLocalType(firstNonArgLocalIndex++, type, -1); + if (type.IsWidePrimitive) + { + firstNonArgLocalIndex++; + } + } + SimpleType[] argumentsByLocalIndex = new SimpleType[firstNonArgLocalIndex]; + for (int i = 0; i < argumentsByLocalIndex.Length; i++) + { + argumentsByLocalIndex[i] = state[0].GetLocalTypeEx(i); + } + InstructionState s = state[0].Copy(); + bool done = false; + ClassFile.Method.Instruction[] instructions = method.Instructions; + while (!done) + { + done = true; + for (int i = 0; i < instructions.Length; i++) + { + if (state[i] != null && state[i].changed) + { + try + { + //Console.WriteLine(method.Instructions[i].PC + ": " + method.Instructions[i].OpCode.ToString()); + done = false; + state[i].changed = false; + // mark the exception handlers reachable from this instruction + for (int j = 0; j < method.ExceptionTable.Length; j++) + { + if (method.ExceptionTable[j].startIndex <= i && i < method.ExceptionTable[j].endIndex) + { + MergeExceptionHandler(method.ExceptionTable[j].handlerIndex, state[i]); + } + } + state[i].CopyTo(s); + ClassFile.Method.Instruction instr = instructions[i]; + switch (instr.NormalizedOpCode) + { + case NormalizedByteCode.__aload: + { + SimpleType type = s.GetLocalType(instr.NormalizedArg1); + if (type == SimpleType.Invalid || type.IsPrimitive) + { + throw new VerifyError("Object reference expected"); + } + s.PushType(type); + break; + } + case NormalizedByteCode.__astore: + s.SetLocalType(instr.NormalizedArg1, s.PopObjectType(), i); + break; + case NormalizedByteCode.__aconst_null: + s.PushObject(); + break; + case NormalizedByteCode.__aaload: + s.PopPrimitive(); + s.PopObjectType(); + s.PushObject(); + break; + case NormalizedByteCode.__aastore: + s.PopObjectType(); + s.PopPrimitive(); + s.PopObjectType(); + break; + case NormalizedByteCode.__baload: + s.PopPrimitive(); + s.PopObjectType(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__bastore: + s.PopPrimitive(); + s.PopPrimitive(); + s.PopObjectType(); + break; + case NormalizedByteCode.__caload: + s.PopPrimitive(); + s.PopObjectType(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__castore: + s.PopPrimitive(); + s.PopPrimitive(); + s.PopObjectType(); + break; + case NormalizedByteCode.__saload: + s.PopPrimitive(); + s.PopObjectType(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__sastore: + s.PopPrimitive(); + s.PopPrimitive(); + s.PopObjectType(); + break; + case NormalizedByteCode.__iaload: + s.PopPrimitive(); + s.PopObjectType(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__iastore: + s.PopPrimitive(); + s.PopPrimitive(); + s.PopObjectType(); + break; + case NormalizedByteCode.__laload: + s.PopPrimitive(); + s.PopObjectType(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__lastore: + s.PopWidePrimitive(); + s.PopPrimitive(); + s.PopObjectType(); + break; + case NormalizedByteCode.__daload: + s.PopPrimitive(); + s.PopObjectType(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__dastore: + s.PopWidePrimitive(); + s.PopPrimitive(); + s.PopObjectType(); + break; + case NormalizedByteCode.__faload: + s.PopPrimitive(); + s.PopObjectType(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__fastore: + s.PopPrimitive(); + s.PopPrimitive(); + s.PopObjectType(); + break; + case NormalizedByteCode.__arraylength: + s.PopObjectType(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__iconst: + s.PushPrimitive(); + break; + case NormalizedByteCode.__if_icmpeq: + case NormalizedByteCode.__if_icmpne: + case NormalizedByteCode.__if_icmplt: + case NormalizedByteCode.__if_icmpge: + case NormalizedByteCode.__if_icmpgt: + case NormalizedByteCode.__if_icmple: + s.PopPrimitive(); + s.PopPrimitive(); + break; + case NormalizedByteCode.__ifeq: + case NormalizedByteCode.__ifge: + case NormalizedByteCode.__ifgt: + case NormalizedByteCode.__ifle: + case NormalizedByteCode.__iflt: + case NormalizedByteCode.__ifne: + s.PopPrimitive(); + break; + case NormalizedByteCode.__ifnonnull: + case NormalizedByteCode.__ifnull: + s.PopObjectType(); + break; + case NormalizedByteCode.__if_acmpeq: + case NormalizedByteCode.__if_acmpne: + s.PopObjectType(); + s.PopObjectType(); + break; + case NormalizedByteCode.__getstatic: + s.PushType(GetFieldref(instr.Arg1).Signature); + break; + case NormalizedByteCode.__putstatic: + s.PopType(GetFieldref(instr.Arg1).Signature); + break; + case NormalizedByteCode.__getfield: + s.PopObjectType(); + s.PushType(GetFieldref(instr.Arg1).Signature); + break; + case NormalizedByteCode.__putfield: + s.PopType(GetFieldref(instr.Arg1).Signature); + s.PopObjectType(); + break; + case NormalizedByteCode.__ldc: + { + switch (GetConstantPoolConstantType(instr.Arg1)) + { + case ClassFile.ConstantType.Double: + s.PushWidePrimitive(); + break; + case ClassFile.ConstantType.Float: + s.PushPrimitive(); + break; + case ClassFile.ConstantType.Integer: + s.PushPrimitive(); + break; + case ClassFile.ConstantType.Long: + s.PushWidePrimitive(); + break; + case ClassFile.ConstantType.String: + case ClassFile.ConstantType.Class: + s.PushObject(); + break; + default: + // NOTE this is not a VerifyError, because it cannot happen (unless we have + // a bug in ClassFile.GetConstantPoolConstantType) + throw new InvalidOperationException(); + } + break; + } + case NormalizedByteCode.__invokevirtual: + case NormalizedByteCode.__invokespecial: + case NormalizedByteCode.__invokeinterface: + case NormalizedByteCode.__invokestatic: + { + ClassFile.ConstantPoolItemMI cpi = GetMethodref(instr.Arg1); + s.MultiPopAnyType(cpi.GetArgTypes().Length); + if (instr.NormalizedOpCode != NormalizedByteCode.__invokestatic) + { + s.PopType(); + } + string sig = cpi.Signature; + sig = sig.Substring(sig.IndexOf(')') + 1); + if (sig != "V") + { + s.PushType(sig); + } + break; + } + case NormalizedByteCode.__goto: + break; + case NormalizedByteCode.__istore: + s.PopPrimitive(); + s.SetLocalPrimitive(instr.NormalizedArg1, i); + break; + case NormalizedByteCode.__iload: + s.PushPrimitive(); + break; + case NormalizedByteCode.__ineg: + s.PopPrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__iadd: + case NormalizedByteCode.__isub: + case NormalizedByteCode.__imul: + case NormalizedByteCode.__idiv: + case NormalizedByteCode.__irem: + case NormalizedByteCode.__iand: + case NormalizedByteCode.__ior: + case NormalizedByteCode.__ixor: + case NormalizedByteCode.__ishl: + case NormalizedByteCode.__ishr: + case NormalizedByteCode.__iushr: + s.PopPrimitive(); + s.PopPrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__lneg: + s.PopWidePrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__ladd: + case NormalizedByteCode.__lsub: + case NormalizedByteCode.__lmul: + case NormalizedByteCode.__ldiv: + case NormalizedByteCode.__lrem: + case NormalizedByteCode.__land: + case NormalizedByteCode.__lor: + case NormalizedByteCode.__lxor: + s.PopWidePrimitive(); + s.PopWidePrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__lshl: + case NormalizedByteCode.__lshr: + case NormalizedByteCode.__lushr: + s.PopPrimitive(); + s.PopWidePrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__fneg: + s.PopPrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__fadd: + case NormalizedByteCode.__fsub: + case NormalizedByteCode.__fmul: + case NormalizedByteCode.__fdiv: + case NormalizedByteCode.__frem: + s.PopPrimitive(); + s.PopPrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__dneg: + s.PopWidePrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__dadd: + case NormalizedByteCode.__dsub: + case NormalizedByteCode.__dmul: + case NormalizedByteCode.__ddiv: + case NormalizedByteCode.__drem: + s.PopWidePrimitive(); + s.PopWidePrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__new: + s.PushObject(); + break; + case NormalizedByteCode.__multianewarray: + { + if (instr.Arg2 < 1) + { + throw new VerifyError("Illegal dimension argument"); + } + for (int j = 0; j < instr.Arg2; j++) + { + s.PopPrimitive(); + } + s.PushObject(); + break; + } + case NormalizedByteCode.__anewarray: + s.PopPrimitive(); + s.PushObject(); + break; + case NormalizedByteCode.__newarray: + s.PopPrimitive(); + s.PushObject(); + break; + case NormalizedByteCode.__swap: + { + SimpleType t1 = s.PopType(); + SimpleType t2 = s.PopType(); + s.PushType(t1); + s.PushType(t2); + break; + } + case NormalizedByteCode.__dup: + { + SimpleType t = s.PopType(); + s.PushType(t); + s.PushType(t); + break; + } + case NormalizedByteCode.__dup2: + { + SimpleType t = s.PopAnyType(); + if (t.IsWidePrimitive) + { + s.PushType(t); + s.PushType(t); + } + else + { + SimpleType t2 = s.PopType(); + s.PushType(t2); + s.PushType(t); + s.PushType(t2); + s.PushType(t); + } + break; + } + case NormalizedByteCode.__dup_x1: + { + SimpleType value1 = s.PopType(); + SimpleType value2 = s.PopType(); + s.PushType(value1); + s.PushType(value2); + s.PushType(value1); + break; + } + case NormalizedByteCode.__dup2_x1: + { + SimpleType value1 = s.PopAnyType(); + if (value1.IsWidePrimitive) + { + SimpleType value2 = s.PopType(); + s.PushType(value1); + s.PushType(value2); + s.PushType(value1); + } + else + { + SimpleType value2 = s.PopType(); + SimpleType value3 = s.PopType(); + s.PushType(value2); + s.PushType(value1); + s.PushType(value3); + s.PushType(value2); + s.PushType(value1); + } + break; + } + case NormalizedByteCode.__dup_x2: + { + SimpleType value1 = s.PopType(); + SimpleType value2 = s.PopAnyType(); + if (value2.IsWidePrimitive) + { + s.PushType(value1); + s.PushType(value2); + s.PushType(value1); + } + else + { + SimpleType value3 = s.PopType(); + s.PushType(value1); + s.PushType(value3); + s.PushType(value2); + s.PushType(value1); + } + break; + } + case NormalizedByteCode.__dup2_x2: + { + SimpleType value1 = s.PopAnyType(); + if (value1.IsWidePrimitive) + { + SimpleType value2 = s.PopAnyType(); + if (value2.IsWidePrimitive) + { + // Form 4 + s.PushType(value1); + s.PushType(value2); + s.PushType(value1); + } + else + { + // Form 2 + SimpleType value3 = s.PopType(); + s.PushType(value1); + s.PushType(value3); + s.PushType(value2); + s.PushType(value1); + } + } + else + { + SimpleType value2 = s.PopType(); + SimpleType value3 = s.PopAnyType(); + if (value3.IsWidePrimitive) + { + // Form 3 + s.PushType(value2); + s.PushType(value1); + s.PushType(value3); + s.PushType(value2); + s.PushType(value1); + } + else + { + // Form 4 + SimpleType value4 = s.PopType(); + s.PushType(value2); + s.PushType(value1); + s.PushType(value4); + s.PushType(value3); + s.PushType(value2); + s.PushType(value1); + } + } + break; + } + case NormalizedByteCode.__pop: + s.PopType(); + break; + case NormalizedByteCode.__pop2: + { + SimpleType type = s.PopAnyType(); + if (!type.IsWidePrimitive) + { + s.PopType(); + } + break; + } + case NormalizedByteCode.__monitorenter: + case NormalizedByteCode.__monitorexit: + s.PopObjectType(); + break; + case NormalizedByteCode.__return: + break; + case NormalizedByteCode.__areturn: + s.PopObjectType(); + break; + case NormalizedByteCode.__ireturn: + s.PopPrimitive(); + break; + case NormalizedByteCode.__lreturn: + s.PopWidePrimitive(); + break; + case NormalizedByteCode.__freturn: + s.PopPrimitive(); + break; + case NormalizedByteCode.__dreturn: + s.PopWidePrimitive(); + break; + case NormalizedByteCode.__fload: + s.PushPrimitive(); + break; + case NormalizedByteCode.__fstore: + s.PopPrimitive(); + s.SetLocalPrimitive(instr.NormalizedArg1, i); + break; + case NormalizedByteCode.__dload: + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__dstore: + s.PopWidePrimitive(); + s.SetLocalWidePrimitive(instr.NormalizedArg1, i); + break; + case NormalizedByteCode.__lload: + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__lstore: + s.PopWidePrimitive(); + s.SetLocalWidePrimitive(instr.NormalizedArg1, i); + break; + case NormalizedByteCode.__lconst_0: + case NormalizedByteCode.__lconst_1: + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__fconst_0: + case NormalizedByteCode.__fconst_1: + case NormalizedByteCode.__fconst_2: + s.PushPrimitive(); + break; + case NormalizedByteCode.__dconst_0: + case NormalizedByteCode.__dconst_1: + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__lcmp: + s.PopWidePrimitive(); + s.PopWidePrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__fcmpl: + case NormalizedByteCode.__fcmpg: + s.PopPrimitive(); + s.PopPrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__dcmpl: + case NormalizedByteCode.__dcmpg: + s.PopWidePrimitive(); + s.PopWidePrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__checkcast: + s.PopObjectType(); + s.PushObject(); + break; + case NormalizedByteCode.__instanceof: + s.PopObjectType(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__iinc: + break; + case NormalizedByteCode.__athrow: + s.PopObjectType(); + break; + case NormalizedByteCode.__tableswitch: + case NormalizedByteCode.__lookupswitch: + s.PopPrimitive(); + break; + case NormalizedByteCode.__i2b: + s.PopPrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__i2c: + s.PopPrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__i2s: + s.PopPrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__i2l: + s.PopPrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__i2f: + s.PopPrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__i2d: + s.PopPrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__l2i: + s.PopWidePrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__l2f: + s.PopWidePrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__l2d: + s.PopWidePrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__f2i: + s.PopPrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__f2l: + s.PopPrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__f2d: + s.PopPrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__d2i: + s.PopWidePrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__d2f: + s.PopWidePrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__d2l: + s.PopWidePrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__jsr: + // TODO make sure we're not calling a subroutine we're already in + break; + case NormalizedByteCode.__ret: + { + // TODO if we're returning from a higher level subroutine, invalidate + // all the intermediate return addresses + int subroutineIndex = s.GetLocalRet(instr.Arg1); + s.CheckSubroutineActive(subroutineIndex); + break; + } + case NormalizedByteCode.__nop: + if (i + 1 == instructions.Length) + { + throw new VerifyError("Falling off the end of the code"); + } + break; + case NormalizedByteCode.__invokedynamic: + // it is impossible to have a valid invokedynamic in a pre-7.0 class file + throw new VerifyError("Illegal type in constant pool"); + default: + throw new NotImplementedException(instr.NormalizedOpCode.ToString()); + } + if (s.GetStackHeight() > method.MaxStack) + { + throw new VerifyError("Stack size too large"); + } + for (int j = 0; j < method.ExceptionTable.Length; j++) + { + if (method.ExceptionTable[j].endIndex == i + 1) + { + MergeExceptionHandler(method.ExceptionTable[j].handlerIndex, s); + } + } + try + { + // another big switch to handle the opcode targets + switch (instr.NormalizedOpCode) + { + case NormalizedByteCode.__tableswitch: + case NormalizedByteCode.__lookupswitch: + for (int j = 0; j < instr.SwitchEntryCount; j++) + { + state[instr.GetSwitchTargetIndex(j)] += s; + } + state[instr.DefaultTarget] += s; + break; + case NormalizedByteCode.__ifeq: + case NormalizedByteCode.__ifne: + case NormalizedByteCode.__iflt: + case NormalizedByteCode.__ifge: + case NormalizedByteCode.__ifgt: + case NormalizedByteCode.__ifle: + case NormalizedByteCode.__if_icmpeq: + case NormalizedByteCode.__if_icmpne: + case NormalizedByteCode.__if_icmplt: + case NormalizedByteCode.__if_icmpge: + case NormalizedByteCode.__if_icmpgt: + case NormalizedByteCode.__if_icmple: + case NormalizedByteCode.__if_acmpeq: + case NormalizedByteCode.__if_acmpne: + case NormalizedByteCode.__ifnull: + case NormalizedByteCode.__ifnonnull: + state[i + 1] += s; + state[instr.TargetIndex] += s; + break; + case NormalizedByteCode.__goto: + state[instr.TargetIndex] += s; + break; + case NormalizedByteCode.__jsr: + { + int index = instr.TargetIndex; + s.SetSubroutineId(index); + SimpleType retAddressType; + if (!returnAddressTypes.TryGetValue(index, out retAddressType)) + { + retAddressType = SimpleType.MakeRet(index); + returnAddressTypes[index] = retAddressType; + } + s.PushType(retAddressType); + state[index] += s; + List returns = GetReturnSites(i); + if (returns != null) + { + foreach (int returnIndex in returns) + { + state[i + 1] = InstructionState.MergeSubroutineReturn(state[i + 1], s, state[returnIndex], state[returnIndex].GetLocalsModified(index)); + } + } + AddCallSite(index, i); + break; + } + case NormalizedByteCode.__ret: + { + // HACK if the ret is processed before all of the jsr instructions to this subroutine + // we wouldn't be able to properly merge, so that is why we track the number of callsites + // for each subroutine instruction (see Instruction.AddCallSite()) + int subroutineIndex = s.GetLocalRet(instr.Arg1); + int[] cs = GetCallSites(subroutineIndex); + bool[] locals_modified = s.GetLocalsModified(subroutineIndex); + for (int j = 0; j < cs.Length; j++) + { + AddReturnSite(cs[j], i); + state[cs[j] + 1] = InstructionState.MergeSubroutineReturn(state[cs[j] + 1], state[cs[j]], s, locals_modified); + } + break; + } + case NormalizedByteCode.__ireturn: + case NormalizedByteCode.__lreturn: + case NormalizedByteCode.__freturn: + case NormalizedByteCode.__dreturn: + case NormalizedByteCode.__areturn: + case NormalizedByteCode.__return: + case NormalizedByteCode.__athrow: + break; + default: + state[i + 1] += s; + break; + } + } + catch (IndexOutOfRangeException) + { + // we're going to assume that this always means that we have an invalid branch target + // NOTE because PcIndexMap returns -1 for illegal PCs (in the middle of an instruction) and + // we always use that value as an index into the state array, any invalid PC will result + // in an IndexOutOfRangeException + throw new VerifyError("Illegal target of jump or branch"); + } + } + catch (VerifyError x) + { + string opcode = instructions[i].NormalizedOpCode.ToString(); + if (opcode.StartsWith("__")) + { + opcode = opcode.Substring(2); + } + throw new VerifyError(string.Format("{5} (class: {0}, method: {1}, signature: {2}, offset: {3}, instruction: {4})", + classFile.Name, method.Name, method.Signature, instructions[i].PC, opcode, x.Message), x); + } + } + } + } + + // Now we do another pass to compute reachability + done = false; + flags[0] |= InstructionFlags.Reachable; + while (!done) + { + done = true; + bool didJsrOrRet = false; + for (int i = 0; i < instructions.Length; i++) + { + if ((flags[i] & (InstructionFlags.Reachable | InstructionFlags.Processed)) == InstructionFlags.Reachable) + { + done = false; + flags[i] |= InstructionFlags.Processed; + // mark the exception handlers reachable from this instruction + for (int j = 0; j < method.ExceptionTable.Length; j++) + { + if (method.ExceptionTable[j].startIndex <= i && i < method.ExceptionTable[j].endIndex) + { + flags[method.ExceptionTable[j].handlerIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; + } + } + // mark the successor instructions + switch (instructions[i].NormalizedOpCode) + { + case NormalizedByteCode.__tableswitch: + case NormalizedByteCode.__lookupswitch: + { + bool hasbackbranch = false; + for (int j = 0; j < instructions[i].SwitchEntryCount; j++) + { + hasbackbranch |= instructions[i].GetSwitchTargetIndex(j) < i; + flags[instructions[i].GetSwitchTargetIndex(j)] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; + } + hasbackbranch |= instructions[i].DefaultTarget < i; + flags[instructions[i].DefaultTarget] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; + break; + } + case NormalizedByteCode.__goto: + flags[instructions[i].TargetIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; + break; + case NormalizedByteCode.__ifeq: + case NormalizedByteCode.__ifne: + case NormalizedByteCode.__iflt: + case NormalizedByteCode.__ifge: + case NormalizedByteCode.__ifgt: + case NormalizedByteCode.__ifle: + case NormalizedByteCode.__if_icmpeq: + case NormalizedByteCode.__if_icmpne: + case NormalizedByteCode.__if_icmplt: + case NormalizedByteCode.__if_icmpge: + case NormalizedByteCode.__if_icmpgt: + case NormalizedByteCode.__if_icmple: + case NormalizedByteCode.__if_acmpeq: + case NormalizedByteCode.__if_acmpne: + case NormalizedByteCode.__ifnull: + case NormalizedByteCode.__ifnonnull: + flags[instructions[i].TargetIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; + flags[i + 1] |= InstructionFlags.Reachable; + break; + case NormalizedByteCode.__jsr: + flags[instructions[i].TargetIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; + // Note that we don't mark the next instruction as reachable, + // because that depends on the corresponding ret actually being + // reachable. We handle this in the loop below. + didJsrOrRet = true; + break; + case NormalizedByteCode.__ret: + // Note that we can't handle ret here, because we might encounter the ret + // before having seen all the corresponding jsr instructions, so we can't + // update all the call sites. + // We handle ret in the loop below. + didJsrOrRet = true; + break; + case NormalizedByteCode.__ireturn: + case NormalizedByteCode.__lreturn: + case NormalizedByteCode.__freturn: + case NormalizedByteCode.__dreturn: + case NormalizedByteCode.__areturn: + case NormalizedByteCode.__return: + case NormalizedByteCode.__athrow: + break; + default: + flags[i + 1] |= InstructionFlags.Reachable; + break; + } + } + } + if (didJsrOrRet) + { + for (int i = 0; i < instructions.Length; i++) + { + if (instructions[i].NormalizedOpCode == NormalizedByteCode.__ret + && (flags[i] & InstructionFlags.Reachable) != 0) + { + int subroutineIndex = state[i].GetLocalRet(instructions[i].Arg1); + int[] cs = GetCallSites(subroutineIndex); + for (int j = 0; j < cs.Length; j++) + { + if ((flags[cs[j]] & InstructionFlags.Reachable) != 0) + { + flags[cs[j] + 1] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; + } + } + } + } + } + } + } + + private void MergeExceptionHandler(int handlerIndex, InstructionState curr) + { + // NOTE this used to be CopyLocalsAndSubroutines, but it doesn't (always) make + // sense to copy the subroutine state + // TODO figure out if there are circumstances under which it does make sense + // to copy the active subroutine state + // UPDATE subroutines must be copied as well, but I think I now have a better + // understanding of subroutine merges, so the problems that triggered the previous + // change here hopefully won't arise anymore + InstructionState ex = curr.CopyLocalsAndSubroutines(); + ex.PushObject(); + state[handlerIndex] += ex; + } + + private ClassFile.ConstantPoolItemMI GetMethodref(int index) + { + try + { + ClassFile.ConstantPoolItemMI item = classFile.GetMethodref(index); + if (item != null) + { + return item; + } + } + catch (InvalidCastException) + { + } + catch (IndexOutOfRangeException) + { + } + throw new VerifyError("Illegal constant pool index"); + } + + private ClassFile.ConstantPoolItemFieldref GetFieldref(int index) + { + try + { + ClassFile.ConstantPoolItemFieldref item = classFile.GetFieldref(index); + if (item != null) + { + return item; + } + } + catch (InvalidCastException) + { + } + catch (IndexOutOfRangeException) + { + } + throw new VerifyError("Illegal constant pool index"); + } + + private ClassFile.ConstantType GetConstantPoolConstantType(int index) + { + try + { + return classFile.GetConstantPoolConstantType(index); + } + catch (IndexOutOfRangeException) + { + // constant pool index out of range + } + catch (InvalidOperationException) + { + // specified constant pool entry doesn't contain a constant + } + catch (NullReferenceException) + { + // specified constant pool entry is empty (entry 0 or the filler following a wide entry) + } + throw new VerifyError("Illegal constant pool index"); + } + + private void AddReturnSite(int callSiteIndex, int returnSiteIndex) + { + if (returnsites[callSiteIndex] == null) + { + returnsites[callSiteIndex] = new List(); + } + List l = returnsites[callSiteIndex]; + if (l.IndexOf(returnSiteIndex) == -1) + { + state[callSiteIndex].changed = true; + l.Add(returnSiteIndex); + } + } + + private List GetReturnSites(int callSiteIndex) + { + return returnsites[callSiteIndex]; + } + + private void AddCallSite(int subroutineIndex, int callSiteIndex) + { + if (callsites[subroutineIndex] == null) + { + callsites[subroutineIndex] = new List(); + } + List l = callsites[subroutineIndex]; + if (l.IndexOf(callSiteIndex) == -1) + { + l.Add(callSiteIndex); + state[subroutineIndex].AddCallSite(); + } + } + + private int[] GetCallSites(int subroutineIndex) + { + return callsites[subroutineIndex].ToArray(); + } + + internal SimpleType GetLocalTypeWrapper(int index, int local) + { + return state[index].GetLocalTypeEx(local); + } + + internal bool IsSubroutineActive(int instructionIndex, int subroutineIndex) + { + return state[instructionIndex].IsSubroutineActive(subroutineIndex); + } + + sealed class Subroutine + { + private int subroutineIndex; + private bool[] localsModified; + + private Subroutine(int subroutineIndex, bool[] localsModified) + { + this.subroutineIndex = subroutineIndex; + this.localsModified = localsModified; + } + + internal Subroutine(int subroutineIndex, int maxLocals) + { + this.subroutineIndex = subroutineIndex; + localsModified = new bool[maxLocals]; + } + + internal int SubroutineIndex + { + get + { + return subroutineIndex; + } + } + + internal bool[] LocalsModified + { + get + { + return localsModified; + } + } + + internal void SetLocalModified(int local) + { + localsModified[local] = true; + } + + internal Subroutine Copy() + { + return new Subroutine(subroutineIndex, (bool[])localsModified.Clone()); + } + } + + sealed class InstructionState + { + private SimpleType[] stack; + private int stackSize; + private int stackEnd; + private SimpleType[] locals; + private List subroutines; + private int callsites; + internal bool changed = true; + private enum ShareFlags : byte + { + None = 0, + Stack = 1, + Locals = 2, + Subroutines = 4, + All = Stack | Locals | Subroutines + } + private ShareFlags flags; + + private InstructionState(SimpleType[] stack, int stackSize, int stackEnd, SimpleType[] locals, List subroutines, int callsites) + { + this.flags = ShareFlags.All; + this.stack = stack; + this.stackSize = stackSize; + this.stackEnd = stackEnd; + this.locals = locals; + this.subroutines = subroutines; + this.callsites = callsites; + } + + internal InstructionState(int maxLocals, int maxStack) + { + this.flags = ShareFlags.None; + this.stack = new SimpleType[maxStack]; + this.stackEnd = maxStack; + this.locals = new SimpleType[maxLocals]; + } + + internal InstructionState Copy() + { + return new InstructionState(stack, stackSize, stackEnd, locals, subroutines, callsites); + } + + internal void CopyTo(InstructionState target) + { + target.flags = ShareFlags.All; + target.stack = stack; + target.stackSize = stackSize; + target.stackEnd = stackEnd; + target.locals = locals; + target.subroutines = subroutines; + target.callsites = callsites; + target.changed = true; + } + + internal InstructionState CopyLocalsAndSubroutines() + { + InstructionState copy = new InstructionState(new SimpleType[stack.Length], 0, stack.Length, locals, subroutines, callsites); + copy.flags &= ~ShareFlags.Stack; + return copy; + } + + private static List CopySubroutines(List l) + { + if (l == null) + { + return null; + } + List n = new List(l.Count); + foreach (Subroutine s in l) + { + n.Add(s.Copy()); + } + return n; + } + + private void MergeSubroutineHelper(InstructionState s2) + { + if (subroutines == null || s2.subroutines == null) + { + if (subroutines != null) + { + subroutines = null; + changed = true; + } + } + else + { + SubroutinesCopyOnWrite(); + List ss1 = subroutines; + subroutines = new List(); + foreach (Subroutine ss2 in s2.subroutines) + { + foreach (Subroutine ss in ss1) + { + if (ss.SubroutineIndex == ss2.SubroutineIndex) + { + subroutines.Add(ss); + for (int i = 0; i < ss.LocalsModified.Length; i++) + { + if (ss2.LocalsModified[i] && !ss.LocalsModified[i]) + { + ss.LocalsModified[i] = true; + changed = true; + } + } + } + } + } + if (ss1.Count != subroutines.Count) + { + changed = true; + } + } + + if (s2.callsites > callsites) + { + //Console.WriteLine("s2.callsites = {0}, callsites = {1}", s2.callsites, callsites); + callsites = s2.callsites; + changed = true; + } + } + + internal static InstructionState MergeSubroutineReturn(InstructionState jsrSuccessor, InstructionState jsr, InstructionState ret, bool[] locals_modified) + { + InstructionState next = ret.Copy(); + next.LocalsCopyOnWrite(); + for (int i = 0; i < locals_modified.Length; i++) + { + if (!locals_modified[i]) + { + next.locals[i] = jsr.locals[i]; + } + } + next.flags |= ShareFlags.Subroutines; + next.subroutines = jsr.subroutines; + next.callsites = jsr.callsites; + return jsrSuccessor + next; + } + + public static InstructionState operator+(InstructionState s1, InstructionState s2) + { + if (s1 == null) + { + return s2.Copy(); + } + if (s1.stackSize != s2.stackSize || s1.stackEnd != s2.stackEnd) + { + throw new VerifyError(string.Format("Inconsistent stack height: {0} != {1}", + s1.stackSize + s1.stack.Length - s1.stackEnd, + s2.stackSize + s2.stack.Length - s2.stackEnd)); + } + InstructionState s = s1.Copy(); + s.changed = s1.changed; + for (int i = 0; i < s.stackSize; i++) + { + SimpleType type = s.stack[i]; + SimpleType type2 = s2.stack[i]; + if (type == type2) + { + // perfect match, nothing to do + } + else if (!type.IsPrimitive) + { + SimpleType baseType = InstructionState.FindCommonBaseType(type, type2); + if (baseType == SimpleType.Invalid) + { + if (SimpleType.IsRet(type) && SimpleType.IsRet(type2)) + { + // if we never return from a subroutine, it is legal to merge to subroutine flows + // (this is from the Mauve test subr.pass.mergeok) + } + else + { + throw new VerifyError(string.Format("cannot merge {0} and {1}", type, type2)); + } + } + if (type != baseType) + { + s.StackCopyOnWrite(); + s.stack[i] = baseType; + s.changed = true; + } + } + else + { + throw new VerifyError(string.Format("cannot merge {0} and {1}", type, type2)); + } + } + for (int i = 0; i < s.locals.Length; i++) + { + SimpleType type = s.locals[i]; + SimpleType type2 = s2.locals[i]; + SimpleType baseType = InstructionState.FindCommonBaseType(type, type2); + if (type != baseType) + { + s.LocalsCopyOnWrite(); + s.locals[i] = baseType; + s.changed = true; + } + } + s.MergeSubroutineHelper(s2); + return s; + } + + internal void AddCallSite() + { + callsites++; + changed = true; + } + + internal void SetSubroutineId(int subroutineIndex) + { + SubroutinesCopyOnWrite(); + if (subroutines == null) + { + subroutines = new List(); + } + else + { + foreach (Subroutine s in subroutines) + { + if (s.SubroutineIndex == subroutineIndex) + { + // subroutines cannot recursivly call themselves + throw new VerifyError("subroutines cannot recurse"); + } + } + } + subroutines.Add(new Subroutine(subroutineIndex, locals.Length)); + } + + internal bool[] GetLocalsModified(int subroutineIndex) + { + if (subroutines != null) + { + foreach (Subroutine s in subroutines) + { + if (s.SubroutineIndex == subroutineIndex) + { + return s.LocalsModified; + } + } + } + throw new VerifyError("return from wrong subroutine"); + } + + internal bool IsSubroutineActive(int subroutineIndex) + { + if (subroutines != null) + { + foreach (Subroutine s in subroutines) + { + if (s.SubroutineIndex == subroutineIndex) + { + return true; + } + } + } + return false; + } + + internal void CheckSubroutineActive(int subroutineIndex) + { + if (!IsSubroutineActive(subroutineIndex)) + { + throw new VerifyError("inactive subroutine"); + } + } + + internal static SimpleType FindCommonBaseType(SimpleType type1, SimpleType type2) + { + if (type1 == type2) + { + return type1; + } + if (type1 == SimpleType.Object) + { + return type2; + } + if (type2 == SimpleType.Object) + { + return type1; + } + if (type1 == SimpleType.Invalid || type2 == SimpleType.Invalid) + { + return SimpleType.Invalid; + } + if (type1.IsPrimitive || type2.IsPrimitive) + { + return SimpleType.Invalid; + } + if (SimpleType.IsRet(type1) || SimpleType.IsRet(type2)) + { + return SimpleType.Invalid; + } + return SimpleType.Object; + } + + private void SetLocal1(int index, SimpleType type) + { + try + { + LocalsCopyOnWrite(); + SubroutinesCopyOnWrite(); + if (index > 0 && locals[index - 1] != SimpleType.Invalid && locals[index - 1].IsWidePrimitive) + { + locals[index - 1] = SimpleType.Invalid; + if (subroutines != null) + { + foreach (Subroutine s in subroutines) + { + s.SetLocalModified(index - 1); + } + } + } + locals[index] = type; + if (subroutines != null) + { + foreach (Subroutine s in subroutines) + { + s.SetLocalModified(index); + } + } + } + catch (IndexOutOfRangeException) + { + throw new VerifyError("Illegal local variable number"); + } + } + + private void SetLocal2(int index, SimpleType type) + { + try + { + LocalsCopyOnWrite(); + SubroutinesCopyOnWrite(); + if (index > 0 && locals[index - 1] != SimpleType.Invalid && locals[index - 1].IsWidePrimitive) + { + locals[index - 1] = SimpleType.Invalid; + if (subroutines != null) + { + foreach (Subroutine s in subroutines) + { + s.SetLocalModified(index - 1); + } + } + } + locals[index] = type; + locals[index + 1] = SimpleType.Invalid; + if (subroutines != null) + { + foreach (Subroutine s in subroutines) + { + s.SetLocalModified(index); + s.SetLocalModified(index + 1); + } + } + } + catch (IndexOutOfRangeException) + { + throw new VerifyError("Illegal local variable number"); + } + } + + internal void SetLocalPrimitive(int index, int instructionIndex) + { + SetLocal1(index, SimpleType.Primitive); + } + + internal void SetLocalWidePrimitive(int index, int instructionIndex) + { + SetLocal2(index, SimpleType.WidePrimitive); + } + + internal SimpleType GetLocalType(int index) + { + try + { + return locals[index]; + } + catch (IndexOutOfRangeException) + { + throw new VerifyError("Illegal local variable number"); + } + } + + // this is used by the compiler (indirectly, through MethodAnalyzer.GetLocalTypeWrapper), + // we've already verified the code so we know we won't run outside the array boundary, + // and we don't need to record the fact that we're reading the local. + internal SimpleType GetLocalTypeEx(int index) + { + return locals[index]; + } + + internal int GetLocalRet(int index) + { + SimpleType type = GetLocalType(index); + if (SimpleType.IsRet(type)) + { + return type.SubroutineIndex; + } + throw new VerifyError("incorrect local type, not ret"); + } + + internal void SetLocalType(int index, SimpleType type, int instructionIndex) + { + if (type.IsWidePrimitive) + { + SetLocalWidePrimitive(index, instructionIndex); + } + else + { + SetLocal1(index, type); + } + } + + internal void PushType(string signature) + { + switch (signature[0]) + { + case 'J': + case 'D': + PushWidePrimitive(); + break; + case '[': + case 'L': + PushObject(); + break; + default: + PushPrimitive(); + break; + } + } + + internal void PushWidePrimitive() + { + PushType(SimpleType.WidePrimitive); + } + + internal void PushPrimitive() + { + PushType(SimpleType.Primitive); + } + + internal void PushObject() + { + PushType(SimpleType.Object); + } + + // object reference or a subroutine return address + internal SimpleType PopObjectType() + { + SimpleType type = PopType(); + if (type.IsPrimitive) + { + throw new VerifyError("Expected object reference on stack"); + } + return type; + } + + internal void MultiPopAnyType(int count) + { + while (count-- != 0) + { + PopAnyType(); + } + } + + internal SimpleType PopAnyType() + { + if (stackSize == 0) + { + throw new VerifyError("Unable to pop operand off an empty stack"); + } + SimpleType type = stack[--stackSize]; + if (type.IsWidePrimitive) + { + stackEnd++; + } + return type; + } + + // NOTE this can *not* be used to pop double or long + internal SimpleType PopType() + { + SimpleType type = PopAnyType(); + if (type.IsWidePrimitive) + { + throw new VerifyError("Attempt to split long or double on the stack"); + } + return type; + } + + internal void PopPrimitive() + { + if (!PopType().IsPrimitive) + { + throw new VerifyError("Primitive type expected on stack"); + } + } + + internal void PopWidePrimitive() + { + SimpleType type = PopAnyType(); + if (type != SimpleType.WidePrimitive) + { + throw new VerifyError("Wide primitive type expected on stack"); + } + } + + internal void PopType(string signature) + { + switch (signature[0]) + { + case 'J': + case 'D': + PopWidePrimitive(); + break; + case '[': + case 'L': + PopObjectType(); + break; + default: + PopPrimitive(); + break; + } + } + + internal int GetStackHeight() + { + return stackSize; + } + + internal void PushType(SimpleType type) + { + if (type.IsWidePrimitive) + { + stackEnd--; + } + if (stackSize >= stackEnd) + { + throw new VerifyError("Stack overflow"); + } + StackCopyOnWrite(); + stack[stackSize++] = type; + } + + private void StackCopyOnWrite() + { + if ((flags & ShareFlags.Stack) != 0) + { + flags &= ~ShareFlags.Stack; + stack = (SimpleType[])stack.Clone(); + } + } + + private void LocalsCopyOnWrite() + { + if ((flags & ShareFlags.Locals) != 0) + { + flags &= ~ShareFlags.Locals; + locals = (SimpleType[])locals.Clone(); + } + } + + private void SubroutinesCopyOnWrite() + { + if ((flags & ShareFlags.Subroutines) != 0) + { + flags &= ~ShareFlags.Subroutines; + subroutines = CopySubroutines(subroutines); + } + } + + internal void DumpLocals() + { + Console.Write("// "); + string sep = ""; + for (int i = 0; i < locals.Length; i++) + { + Console.Write(sep); + Console.Write(locals[i]); + sep = ", "; + } + Console.WriteLine(); + } + + internal void DumpStack() + { + Console.Write("// "); + string sep = ""; + for (int i = 0; i < stackSize; i++) + { + Console.Write(sep); + Console.Write(stack[i]); + sep = ", "; + } + Console.WriteLine(); + } + + internal void DumpSubroutines() + { + Console.Write("// subs: "); + string sep = ""; + if (subroutines != null) + { + for (int i = 0; i < subroutines.Count; i++) + { + Console.Write(sep); + Console.Write(((Subroutine)subroutines[i]).SubroutineIndex); + sep = ", "; + } + } + Console.WriteLine(); + } + } + } + } +} diff --git a/runtime/LambdaMetafactory.cs b/runtime/LambdaMetafactory.cs new file mode 100644 index 0000000..b62b3dd --- /dev/null +++ b/runtime/LambdaMetafactory.cs @@ -0,0 +1,1030 @@ +/* + Copyright (C) 2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Diagnostics; +#if STATIC_COMPILER +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace IKVM.Internal +{ + sealed class LambdaMetafactory + { + private MethodBuilder ctor; + + internal static bool Emit(DynamicTypeWrapper.FinishContext context, ClassFile classFile, int constantPoolIndex, ClassFile.ConstantPoolItemInvokeDynamic cpi, CodeEmitter ilgen) + { + ClassFile.BootstrapMethod bsm = classFile.GetBootstrapMethod(cpi.BootstrapMethod); + if (!IsLambdaMetafactory(classFile, bsm) && !IsLambdaAltMetafactory(classFile, bsm)) + { + return false; + } + LambdaMetafactory lmf = context.GetValue(constantPoolIndex); + if (lmf.ctor == null && !lmf.EmitImpl(context, classFile, cpi, bsm, ilgen)) + { +#if STATIC_COMPILER + if (context.TypeWrapper.GetClassLoader().DisableDynamicBinding) + { + StaticCompiler.IssueMessage(Message.UnableToCreateLambdaFactory); + } +#endif + return false; + } + ilgen.Emit(OpCodes.Newobj, lmf.ctor); + // the CLR verification rules about type merging mean we have to explicitly cast to the interface type here + ilgen.Emit(OpCodes.Castclass, cpi.GetRetType().TypeAsBaseType); + return true; + } + + private bool EmitImpl(DynamicTypeWrapper.FinishContext context, ClassFile classFile, ClassFile.ConstantPoolItemInvokeDynamic cpi, ClassFile.BootstrapMethod bsm, CodeEmitter ilgen) + { + if (HasUnloadable(cpi)) + { + Fail("cpi has unloadable"); + return false; + } + bool serializable = false; + TypeWrapper[] markers = TypeWrapper.EmptyArray; + ClassFile.ConstantPoolItemMethodType[] bridges = null; + if (bsm.ArgumentCount > 3) + { + AltFlags flags = (AltFlags)classFile.GetConstantPoolConstantInteger(bsm.GetArgument(3)); + serializable = (flags & AltFlags.Serializable) != 0; + int argpos = 4; + if ((flags & AltFlags.Markers) != 0) + { + markers = new TypeWrapper[classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++))]; + for (int i = 0; i < markers.Length; i++) + { + if ((markers[i] = classFile.GetConstantPoolClassType(bsm.GetArgument(argpos++))).IsUnloadable) + { + Fail("unloadable marker"); + return false; + } + } + } + if ((flags & AltFlags.Bridges) != 0) + { + bridges = new ClassFile.ConstantPoolItemMethodType[classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++))]; + for (int i = 0; i < bridges.Length; i++) + { + bridges[i] = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(argpos++)); + if (HasUnloadable(bridges[i])) + { + Fail("unloadable bridge"); + return false; + } + } + } + } + ClassFile.ConstantPoolItemMethodType samMethodType = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(0)); + ClassFile.ConstantPoolItemMethodHandle implMethod = classFile.GetConstantPoolConstantMethodHandle(bsm.GetArgument(1)); + ClassFile.ConstantPoolItemMethodType instantiatedMethodType = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(2)); + if (HasUnloadable(samMethodType) + || HasUnloadable((ClassFile.ConstantPoolItemMI)implMethod.MemberConstantPoolItem) + || HasUnloadable(instantiatedMethodType)) + { + Fail("bsm args has unloadable"); + return false; + } + TypeWrapper interfaceType = cpi.GetRetType(); + MethodWrapper[] methodList; + if (!CheckSupportedInterfaces(context.TypeWrapper, interfaceType, markers, bridges, out methodList)) + { + Fail("unsupported interface"); + return false; + } + if (serializable && Array.Exists(methodList, delegate(MethodWrapper mw) { return mw.Name == "writeReplace" && mw.Signature == "()Ljava.lang.Object;"; })) + { + Fail("writeReplace"); + return false; + } + if (!IsSupportedImplMethod(implMethod, context.TypeWrapper, cpi.GetArgTypes(), instantiatedMethodType)) + { + Fail("implMethod " + implMethod.MemberConstantPoolItem.Class + "::" + implMethod.MemberConstantPoolItem.Name + implMethod.MemberConstantPoolItem.Signature); + return false; + } + TypeWrapper[] implParameters = GetImplParameters(implMethod); + CheckConstraints(instantiatedMethodType, samMethodType, cpi.GetArgTypes(), implParameters); + if (bridges != null) + { + foreach (ClassFile.ConstantPoolItemMethodType bridge in bridges) + { + if (bridge.Signature == samMethodType.Signature) + { + Fail("bridge signature matches sam"); + return false; + } + if (!CheckConstraints(instantiatedMethodType, bridge, cpi.GetArgTypes(), implParameters)) + { + Fail("bridge constraints"); + return false; + } + } + } + if (instantiatedMethodType.GetRetType() != PrimitiveTypeWrapper.VOID) + { + TypeWrapper Rt = instantiatedMethodType.GetRetType(); + TypeWrapper Ra = GetImplReturnType(implMethod); + if (Ra == PrimitiveTypeWrapper.VOID || !IsAdaptable(Ra, Rt, true)) + { + Fail("The return type Rt is void, or the return type Ra is not void and is adaptable to Rt"); + return false; + } + } + MethodWrapper interfaceMethod = null; + List methods = new List(); + foreach (MethodWrapper mw in methodList) + { + if (mw.Name == cpi.Name && mw.Signature == samMethodType.Signature) + { + interfaceMethod = mw; + methods.Add(mw); + } + else if (mw.IsAbstract && !IsObjectMethod(mw)) + { + methods.Add(mw); + } + } + if (interfaceMethod == null || !interfaceMethod.IsAbstract || IsObjectMethod(interfaceMethod) || !MatchSignatures(interfaceMethod, samMethodType)) + { + Fail("interfaceMethod"); + return false; + } + + TypeBuilder tb = context.DefineAnonymousClass(); + // we're not implementing the interfaces recursively (because we don't care about .NET Compact anymore), + // but should we decide to do that, we'd need to somehow communicate to AnonymousTypeWrapper what the 'real' interface is + tb.AddInterfaceImplementation(interfaceType.TypeAsBaseType); + if (serializable && Array.IndexOf(markers, CoreClasses.java.io.Serializable.Wrapper) == -1) + { + tb.AddInterfaceImplementation(CoreClasses.java.io.Serializable.Wrapper.TypeAsBaseType); + } + foreach (TypeWrapper marker in markers) + { + tb.AddInterfaceImplementation(marker.TypeAsBaseType); + } + ctor = CreateConstructorAndDispatch(context, cpi, tb, methods, implParameters, samMethodType, implMethod, instantiatedMethodType, serializable); + AddDefaultInterfaceMethods(context, methodList, tb); + return true; + } + + [Conditional("TRACE_LAMBDA_METAFACTORY")] + private static void Fail(string msg) + { + Console.WriteLine("Fail: " + msg); + } + + private static bool CheckConstraints(ClassFile.ConstantPoolItemMethodType instantiatedMethodType, ClassFile.ConstantPoolItemMethodType methodType, TypeWrapper[] args, TypeWrapper[] implParameters) + { + if (!IsSubTypeOf(instantiatedMethodType, methodType)) + { + Fail("instantiatedMethodType <= methodType"); + return false; + } + if (args.Length + methodType.GetArgTypes().Length != implParameters.Length) + { + Fail("K + N = M"); + return false; + } + for (int i = 0, K = args.Length; i < K; i++) + { + if (args[i] == implParameters[i]) + { + // ok + } + else if (args[i].IsPrimitive || implParameters[i].IsPrimitive || !args[i].IsSubTypeOf(implParameters[i])) + { + Fail("For i=1..K, Di = Ai"); + return false; + } + } + for (int i = 0, N = methodType.GetArgTypes().Length, k = args.Length; i < N; i++) + { + if (!IsAdaptable(instantiatedMethodType.GetArgTypes()[i], implParameters[i + k], false)) + { + Fail("For i=1..N, Ti is adaptable to Aj, where j=i+k"); + return false; + } + } + return true; + } + + private static TypeWrapper[] GetImplParameters(ClassFile.ConstantPoolItemMethodHandle implMethod) + { + MethodWrapper mw = (MethodWrapper)implMethod.Member; + TypeWrapper[] parameters = mw.GetParameters(); + if (mw.IsStatic || mw.IsConstructor) + { + return parameters; + } + return ArrayUtil.Concat(mw.DeclaringType, parameters); + } + + private static TypeWrapper GetImplReturnType(ClassFile.ConstantPoolItemMethodHandle implMethod) + { + return implMethod.Kind == ClassFile.RefKind.newInvokeSpecial + ? implMethod.Member.DeclaringType + : ((MethodWrapper)implMethod.Member).ReturnType; + } + + private static bool IsAdaptable(TypeWrapper Q, TypeWrapper S, bool isReturn) + { + if (Q == S) + { + return true; + } + + if (Q.IsPrimitive) + { + if (S.IsPrimitive) + { + // Q can be converted to S via a primitive widening conversion + switch (Q.SigName[0] | S.SigName[0] << 8) + { + case 'B' | 'S' << 8: + case 'B' | 'I' << 8: + case 'B' | 'J' << 8: + case 'B' | 'F' << 8: + case 'B' | 'D' << 8: + case 'S' | 'I' << 8: + case 'S' | 'J' << 8: + case 'S' | 'F' << 8: + case 'S' | 'D' << 8: + case 'C' | 'I' << 8: + case 'C' | 'J' << 8: + case 'C' | 'F' << 8: + case 'C' | 'D' << 8: + case 'I' | 'J' << 8: + case 'I' | 'F' << 8: + case 'I' | 'D' << 8: + case 'J' | 'F' << 8: + case 'J' | 'D' << 8: + case 'F' | 'D' << 8: + return true; + default: + return false; + } + } + else + { + // S is a supertype of the Wrapper(Q) + return GetWrapper(Q).IsAssignableTo(S); + } + } + else if (isReturn) + { + return true; + } + else + { + if (S.IsPrimitive) + { + // If Q is a primitive wrapper, check that Primitive(Q) can be widened to S + TypeWrapper primitive = GetPrimitiveFromWrapper(Q); + return primitive != null && IsAdaptable(primitive, S, isReturn); + } + else + { + // for parameter types: S is a supertype of Q + return Q.IsAssignableTo(S); + } + } + } + + private static TypeWrapper GetWrapper(TypeWrapper primitive) + { + Debug.Assert(primitive.IsPrimitive); + switch (primitive.SigName[0]) + { + case 'Z': + return ClassLoaderWrapper.LoadClassCritical("java.lang.Boolean"); + case 'B': + return ClassLoaderWrapper.LoadClassCritical("java.lang.Byte"); + case 'S': + return ClassLoaderWrapper.LoadClassCritical("java.lang.Short"); + case 'C': + return ClassLoaderWrapper.LoadClassCritical("java.lang.Character"); + case 'I': + return ClassLoaderWrapper.LoadClassCritical("java.lang.Integer"); + case 'J': + return ClassLoaderWrapper.LoadClassCritical("java.lang.Long"); + case 'F': + return ClassLoaderWrapper.LoadClassCritical("java.lang.Float"); + case 'D': + return ClassLoaderWrapper.LoadClassCritical("java.lang.Double"); + default: + throw new InvalidOperationException(); + } + } + + private static TypeWrapper GetPrimitiveFromWrapper(TypeWrapper wrapper) + { + switch (wrapper.Name) + { + case "java.lang.Boolean": + return PrimitiveTypeWrapper.BOOLEAN; + case "java.lang.Byte": + return PrimitiveTypeWrapper.BYTE; + case "java.lang.Short": + return PrimitiveTypeWrapper.SHORT; + case "java.lang.Character": + return PrimitiveTypeWrapper.CHAR; + case "java.lang.Integer": + return PrimitiveTypeWrapper.INT; + case "java.lang.Long": + return PrimitiveTypeWrapper.LONG; + case "java.lang.Float": + return PrimitiveTypeWrapper.FLOAT; + case "java.lang.Double": + return PrimitiveTypeWrapper.DOUBLE; + default: + return null; + } + } + + private static bool IsSubTypeOf(ClassFile.ConstantPoolItemMethodType instantiatedMethodType, ClassFile.ConstantPoolItemMethodType samMethodType) + { + TypeWrapper[] T = instantiatedMethodType.GetArgTypes(); + TypeWrapper[] U = samMethodType.GetArgTypes(); + if (T.Length != U.Length) + { + return false; + } + for (int i = 0; i < T.Length; i++) + { + if (!T[i].IsAssignableTo(U[i])) + { + return false; + } + } + TypeWrapper Rt = instantiatedMethodType.GetRetType(); + TypeWrapper Ru = samMethodType.GetRetType(); + return Rt.IsAssignableTo(Ru); + } + + private static MethodBuilder CreateConstructorAndDispatch(DynamicTypeWrapper.FinishContext context, ClassFile.ConstantPoolItemInvokeDynamic cpi, TypeBuilder tb, + List methods, TypeWrapper[] implParameters, ClassFile.ConstantPoolItemMethodType samMethodType, ClassFile.ConstantPoolItemMethodHandle implMethod, + ClassFile.ConstantPoolItemMethodType instantiatedMethodType, bool serializable) + { + TypeWrapper[] args = cpi.GetArgTypes(); + + // captured values + Type[] capturedTypes = new Type[args.Length]; + FieldBuilder[] capturedFields = new FieldBuilder[capturedTypes.Length]; + for (int i = 0; i < capturedTypes.Length; i++) + { + capturedTypes[i] = args[i].TypeAsSignatureType; + FieldAttributes attr = FieldAttributes.Private; + if (i > 0 || !args[0].IsGhost) + { + attr |= FieldAttributes.InitOnly; + } + capturedFields[i] = tb.DefineField("arg$" + (i + 1), capturedTypes[i], attr); + } + + // constructor + MethodBuilder ctor = ReflectUtil.DefineConstructor(tb, MethodAttributes.Assembly, capturedTypes); + CodeEmitter ilgen = CodeEmitter.Create(ctor); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Call, Types.Object.GetConstructor(Type.EmptyTypes)); + for (int i = 0; i < capturedTypes.Length; i++) + { + ilgen.EmitLdarg(0); + ilgen.EmitLdarg(i + 1); + ilgen.Emit(OpCodes.Stfld, capturedFields[i]); + } + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + + // dispatch methods + foreach (MethodWrapper mw in methods) + { + EmitDispatch(context, args, tb, mw, implParameters, implMethod, instantiatedMethodType, capturedFields); + } + + // writeReplace method + if (serializable) + { + MethodBuilder writeReplace = tb.DefineMethod("writeReplace", MethodAttributes.Private, Types.Object, Type.EmptyTypes); + ilgen = CodeEmitter.Create(writeReplace); + context.TypeWrapper.EmitClassLiteral(ilgen); + ilgen.Emit(OpCodes.Ldstr, cpi.GetRetType().Name.Replace('.', '/')); + ilgen.Emit(OpCodes.Ldstr, cpi.Name); + ilgen.Emit(OpCodes.Ldstr, samMethodType.Signature.Replace('.', '/')); + ilgen.EmitLdc_I4((int)implMethod.Kind); + ilgen.Emit(OpCodes.Ldstr, implMethod.Class.Replace('.', '/')); + ilgen.Emit(OpCodes.Ldstr, implMethod.Name); + ilgen.Emit(OpCodes.Ldstr, implMethod.Signature.Replace('.', '/')); + ilgen.Emit(OpCodes.Ldstr, instantiatedMethodType.Signature.Replace('.', '/')); + ilgen.EmitLdc_I4(capturedFields.Length); + ilgen.Emit(OpCodes.Newarr, Types.Object); + for (int i = 0; i < capturedFields.Length; i++) + { + ilgen.Emit(OpCodes.Dup); + ilgen.EmitLdc_I4(i); + ilgen.EmitLdarg(0); + ilgen.Emit(OpCodes.Ldfld, capturedFields[i]); + if (args[i].IsPrimitive) + { + Boxer.EmitBox(ilgen, args[i]); + } + else if (args[i].IsGhost) + { + args[i].EmitConvSignatureTypeToStackType(ilgen); + } + ilgen.Emit(OpCodes.Stelem, Types.Object); + } + MethodWrapper ctorSerializedLambda = ClassLoaderWrapper.LoadClassCritical("java.lang.invoke.SerializedLambda").GetMethodWrapper(StringConstants.INIT, + "(Ljava.lang.Class;Ljava.lang.String;Ljava.lang.String;Ljava.lang.String;ILjava.lang.String;Ljava.lang.String;Ljava.lang.String;Ljava.lang.String;[Ljava.lang.Object;)V", false); + ctorSerializedLambda.Link(); + ctorSerializedLambda.EmitNewobj(ilgen); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + + if (!context.TypeWrapper.GetClassLoader().NoAutomagicSerialization) + { + // add .NET serialization interop support + Serialization.MarkSerializable(tb); + Serialization.AddGetObjectData(tb); + } + } + + return ctor; + } + + private static void EmitDispatch(DynamicTypeWrapper.FinishContext context, TypeWrapper[] args, TypeBuilder tb, MethodWrapper interfaceMethod, TypeWrapper[] implParameters, + ClassFile.ConstantPoolItemMethodHandle implMethod, ClassFile.ConstantPoolItemMethodType instantiatedMethodType, FieldBuilder[] capturedFields) + { + MethodBuilder mb = interfaceMethod.GetDefineMethodHelper().DefineMethod(context.TypeWrapper, tb, interfaceMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final); + if (interfaceMethod.Name != interfaceMethod.RealName) + { + tb.DefineMethodOverride(mb, (MethodInfo)interfaceMethod.GetMethod()); + } + CodeEmitter ilgen = CodeEmitter.Create(mb); + for (int i = 0; i < capturedFields.Length; i++) + { + ilgen.EmitLdarg(0); + OpCode opc = OpCodes.Ldfld; + if (i == 0 && args[0].IsGhost) + { + switch (implMethod.Kind) + { + case ClassFile.RefKind.invokeInterface: + case ClassFile.RefKind.invokeVirtual: + case ClassFile.RefKind.invokeSpecial: + opc = OpCodes.Ldflda; + break; + } + } + ilgen.Emit(opc, capturedFields[i]); + } + for (int i = 0, count = interfaceMethod.GetParameters().Length, k = capturedFields.Length; i < count; i++) + { + ilgen.EmitLdarg(i + 1); + TypeWrapper Ui = interfaceMethod.GetParameters()[i]; + TypeWrapper Ti = instantiatedMethodType.GetArgTypes()[i]; + TypeWrapper Aj = implParameters[i + k]; + if (Ui == PrimitiveTypeWrapper.BYTE) + { + ilgen.Emit(OpCodes.Conv_I1); + } + if (Ti != Ui) + { + if (Ti.IsGhost) + { + Ti.EmitConvStackTypeToSignatureType(ilgen, Ui); + } + else if (Ui.IsGhost) + { + Ui.EmitConvSignatureTypeToStackType(ilgen); + } + else + { + Ti.EmitCheckcast(ilgen); + } + } + if (Ti != Aj) + { + if (Ti.IsPrimitive && !Aj.IsPrimitive) + { + Boxer.EmitBox(ilgen, Ti); + } + else if (!Ti.IsPrimitive && Aj.IsPrimitive) + { + TypeWrapper primitive = GetPrimitiveFromWrapper(Ti); + Boxer.EmitUnbox(ilgen, primitive, false); + if (primitive == PrimitiveTypeWrapper.BYTE) + { + ilgen.Emit(OpCodes.Conv_I1); + } + } + else if (Aj == PrimitiveTypeWrapper.LONG) + { + ilgen.Emit(OpCodes.Conv_I8); + } + else if (Aj == PrimitiveTypeWrapper.FLOAT) + { + ilgen.Emit(OpCodes.Conv_R4); + } + else if (Aj == PrimitiveTypeWrapper.DOUBLE) + { + ilgen.Emit(OpCodes.Conv_R8); + } + } + } + switch (implMethod.Kind) + { + case ClassFile.RefKind.invokeVirtual: + case ClassFile.RefKind.invokeInterface: + ((MethodWrapper)implMethod.Member).EmitCallvirt(ilgen); + break; + case ClassFile.RefKind.newInvokeSpecial: + ((MethodWrapper)implMethod.Member).EmitNewobj(ilgen); + break; + case ClassFile.RefKind.invokeStatic: + case ClassFile.RefKind.invokeSpecial: + ((MethodWrapper)implMethod.Member).EmitCall(ilgen); + break; + default: + throw new InvalidOperationException(); + } + TypeWrapper Ru = interfaceMethod.ReturnType; + TypeWrapper Ra = GetImplReturnType(implMethod); + TypeWrapper Rt = instantiatedMethodType.GetRetType(); + if (Ra == PrimitiveTypeWrapper.BYTE) + { + ilgen.Emit(OpCodes.Conv_I1); + } + if (Ra != Ru) + { + if (Ru == PrimitiveTypeWrapper.VOID) + { + ilgen.Emit(OpCodes.Pop); + } + else if (Ra.IsGhost) + { + Ra.EmitConvSignatureTypeToStackType(ilgen); + } + else if (Ru.IsGhost) + { + Ru.EmitConvStackTypeToSignatureType(ilgen, Ra); + } + } + if (Ra != Rt) + { + if (Rt.IsPrimitive) + { + if (Rt == PrimitiveTypeWrapper.VOID) + { + // already popped + } + else if (!Ra.IsPrimitive) + { + TypeWrapper primitive = GetPrimitiveFromWrapper(Ra); + if (primitive != null) + { + Boxer.EmitUnbox(ilgen, primitive, false); + } + else + { + // If Q is not a primitive wrapper, cast Q to the base Wrapper(S); for example Number for numeric types + EmitConvertingUnbox(ilgen, Rt); + } + } + else if (Rt == PrimitiveTypeWrapper.LONG) + { + ilgen.Emit(OpCodes.Conv_I8); + } + else if (Rt == PrimitiveTypeWrapper.FLOAT) + { + ilgen.Emit(OpCodes.Conv_R4); + } + else if (Rt == PrimitiveTypeWrapper.DOUBLE) + { + ilgen.Emit(OpCodes.Conv_R8); + } + } + else if (Ra.IsPrimitive) + { + Boxer.EmitBox(ilgen, GetPrimitiveFromWrapper(Rt)); + } + else + { + Rt.EmitCheckcast(ilgen); + } + } + ilgen.EmitTailCallPrevention(); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + + private static void EmitConvertingUnbox(CodeEmitter ilgen, TypeWrapper tw) + { + switch (tw.SigName[0]) + { + case 'Z': + case 'C': + Boxer.EmitUnbox(ilgen, tw, true); + break; + case 'B': + EmitUnboxNumber(ilgen, "byteValue", "()B"); + break; + case 'S': + EmitUnboxNumber(ilgen, "shortValue", "()S"); + break; + case 'I': + EmitUnboxNumber(ilgen, "intValue", "()I"); + break; + case 'J': + EmitUnboxNumber(ilgen, "longValue", "()J"); + break; + case 'F': + EmitUnboxNumber(ilgen, "floatValue", "()F"); + break; + case 'D': + EmitUnboxNumber(ilgen, "doubleValue", "()D"); + break; + default: + throw new InvalidOperationException(); + } + } + + private static void EmitUnboxNumber(CodeEmitter ilgen, string methodName, string methodSig) + { + TypeWrapper tw = ClassLoaderWrapper.LoadClassCritical("java.lang.Number"); + tw.EmitCheckcast(ilgen); + MethodWrapper mw = tw.GetMethodWrapper(methodName, methodSig, false); + mw.Link(); + mw.EmitCallvirt(ilgen); + } + + private static void AddDefaultInterfaceMethods(DynamicTypeWrapper.FinishContext context, MethodWrapper[] methodList, TypeBuilder tb) + { + // we use special name to hide these from Java reflection + const MethodAttributes attr = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final | MethodAttributes.SpecialName; + TypeWrapperFactory factory = context.TypeWrapper.GetClassLoader().GetTypeWrapperFactory(); + foreach (MethodWrapper mw in methodList) + { + if (!mw.IsAbstract) + { + MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(factory, tb, mw.Name, attr); + if (mw.Name != mw.RealName) + { + tb.DefineMethodOverride(mb, (MethodInfo)mw.GetMethod()); + } + DynamicTypeWrapper.FinishContext.EmitCallDefaultInterfaceMethod(mb, mw); + } + else if (IsObjectMethod(mw)) + { + MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(factory, tb, mw.Name, attr); + if (mw.Name != mw.RealName) + { + tb.DefineMethodOverride(mb, (MethodInfo)mw.GetMethod()); + } + CodeEmitter ilgen = CodeEmitter.Create(mb); + for (int i = 0, count = mw.GetParameters().Length; i <= count; i++) + { + ilgen.EmitLdarg(i); + } + CoreClasses.java.lang.Object.Wrapper.GetMethodWrapper(mw.Name, mw.Signature, false).EmitCallvirt(ilgen); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + } + } + + private static bool IsSupportedImplMethod(ClassFile.ConstantPoolItemMethodHandle implMethod, TypeWrapper caller, TypeWrapper[] captured, ClassFile.ConstantPoolItemMethodType instantiatedMethodType) + { + switch (implMethod.Kind) + { + case ClassFile.RefKind.invokeVirtual: + case ClassFile.RefKind.invokeInterface: + case ClassFile.RefKind.newInvokeSpecial: + case ClassFile.RefKind.invokeStatic: + case ClassFile.RefKind.invokeSpecial: + break; + default: + return false; + } + MethodWrapper mw = (MethodWrapper)implMethod.Member; + if (mw == null || mw.HasCallerID || DynamicTypeWrapper.RequiresDynamicReflectionCallerClass(mw.DeclaringType.Name, mw.Name, mw.Signature)) + { + return false; + } + TypeWrapper instance; + if (mw.IsConstructor) + { + instance = mw.DeclaringType; + } + else if (mw.IsStatic) + { + instance = null; + } + else + { + // if implMethod is an instance method, the type of the first captured value must be subtype of implMethod.DeclaringType + instance = captured.Length == 0 ? instantiatedMethodType.GetArgTypes()[0] : captured[0]; + if (!instance.IsAssignableTo(mw.DeclaringType)) + { + return false; + } + } + if (!mw.IsAccessibleFrom(mw.DeclaringType, caller, instance)) + { + return false; + } + mw.Link(); + return true; + } + + private static bool IsSupportedInterface(TypeWrapper tw, TypeWrapper caller) + { + return tw.IsInterface + && !tw.IsGhost + && tw.IsAccessibleFrom(caller) + && !Serialization.IsISerializable(tw); + } + + private static bool CheckSupportedInterfaces(TypeWrapper caller, TypeWrapper tw, TypeWrapper[] markers, ClassFile.ConstantPoolItemMethodType[] bridges, out MethodWrapper[] methodList) + { + // we don't need to check for unloadable, because we already did that while validating the invoke signature + if (!IsSupportedInterface(tw, caller)) + { + methodList = null; + return false; + } + Dictionary methods = new Dictionary(); + int abstractMethodCount = 0; + int bridgeMethodCount = 0; + if (GatherAllInterfaceMethods(tw, bridges, methods, ref abstractMethodCount, ref bridgeMethodCount) && abstractMethodCount == 1) + { + foreach (TypeWrapper marker in markers) + { + if (!IsSupportedInterface(marker, caller)) + { + methodList = null; + return false; + } + if (!GatherAllInterfaceMethods(marker, null, methods, ref abstractMethodCount, ref bridgeMethodCount) || abstractMethodCount != 1) + { + methodList = null; + return false; + } + } + if (bridges != null && bridgeMethodCount != bridges.Length) + { + methodList = null; + return false; + } + methodList = new MethodWrapper[methods.Count]; + methods.Values.CopyTo(methodList, 0); + return true; + } + methodList = null; + return false; + } + + private static bool GatherAllInterfaceMethods(TypeWrapper tw, ClassFile.ConstantPoolItemMethodType[] bridges, Dictionary methods, + ref int abstractMethodCount, ref int bridgeMethodCount) + { + foreach (MethodWrapper mw in tw.GetMethods()) + { + if (mw.IsVirtual) + { + MirandaMethodWrapper mmw = mw as MirandaMethodWrapper; + if (mmw != null) + { + if (mmw.Error != null) + { + return false; + } + continue; + } + MethodKey key = new MethodKey("", mw.Name, mw.Signature); + MethodWrapper current; + if (methods.TryGetValue(key, out current)) + { + if (!MatchSignatures(mw, current)) + { + // linkage error (or unloadable type) + return false; + } + } + else + { + methods.Add(key, mw); + if (mw.IsAbstract && !IsObjectMethod(mw)) + { + if (bridges != null && IsBridge(mw, bridges)) + { + bridgeMethodCount++; + } + else + { + abstractMethodCount++; + } + } + } + mw.Link(); + if (mw.GetMethod() == null) + { + return false; + } + if (current != null && mw.RealName != current.RealName) + { + return false; + } + } + } + foreach (TypeWrapper tw1 in tw.Interfaces) + { + if (!GatherAllInterfaceMethods(tw1, bridges, methods, ref abstractMethodCount, ref bridgeMethodCount)) + { + return false; + } + } + return true; + } + + private static bool IsBridge(MethodWrapper mw, ClassFile.ConstantPoolItemMethodType[] bridges) + { + foreach (ClassFile.ConstantPoolItemMethodType bridge in bridges) + { + if (bridge.Signature == mw.Signature) + { + return true; + } + } + return false; + } + + private static bool IsObjectMethod(MethodWrapper mw) + { + MethodWrapper objectMethod; + return (objectMethod = CoreClasses.java.lang.Object.Wrapper.GetMethodWrapper(mw.Name, mw.Signature, false)) != null + && objectMethod.IsPublic; + } + + private static bool MatchSignatures(MethodWrapper interfaceMethod, ClassFile.ConstantPoolItemMethodType samMethodType) + { + return interfaceMethod.ReturnType == samMethodType.GetRetType() + && MatchTypes(interfaceMethod.GetParameters(), samMethodType.GetArgTypes()); + } + + private static bool MatchSignatures(MethodWrapper mw1, MethodWrapper mw2) + { + return mw1.ReturnType == mw2.ReturnType + && MatchTypes(mw1.GetParameters(), mw2.GetParameters()); + } + + private static bool MatchTypes(TypeWrapper[] ar1, TypeWrapper[] ar2) + { + if (ar1.Length != ar2.Length) + { + return false; + } + for (int i = 0; i < ar1.Length; i++) + { + if (ar1[i] != ar2[i]) + { + return false; + } + } + return true; + } + + private static bool IsLambdaMetafactory(ClassFile classFile, ClassFile.BootstrapMethod bsm) + { + ClassFile.ConstantPoolItemMethodHandle mh; + return bsm.ArgumentCount == 3 + && classFile.GetConstantPoolConstantType(bsm.GetArgument(0)) == ClassFile.ConstantType.MethodType + && classFile.GetConstantPoolConstantType(bsm.GetArgument(1)) == ClassFile.ConstantType.MethodHandle + && classFile.GetConstantPoolConstantType(bsm.GetArgument(2)) == ClassFile.ConstantType.MethodType + && (mh = classFile.GetConstantPoolConstantMethodHandle(bsm.BootstrapMethodIndex)).Kind == ClassFile.RefKind.invokeStatic + && mh.Member != null + && IsLambdaMetafactory(mh.Member); + } + + private static bool IsLambdaMetafactory(MemberWrapper mw) + { + return mw.Name == "metafactory" + && mw.Signature == "(Ljava.lang.invoke.MethodHandles$Lookup;Ljava.lang.String;Ljava.lang.invoke.MethodType;Ljava.lang.invoke.MethodType;Ljava.lang.invoke.MethodHandle;Ljava.lang.invoke.MethodType;)Ljava.lang.invoke.CallSite;" + && mw.DeclaringType.Name == "java.lang.invoke.LambdaMetafactory"; + } + + [Flags] + enum AltFlags + { + Serializable = 1, + Markers = 2, + Bridges = 4, + Mask = Serializable | Markers | Bridges + } + + private static bool IsLambdaAltMetafactory(ClassFile classFile, ClassFile.BootstrapMethod bsm) + { + ClassFile.ConstantPoolItemMethodHandle mh; + AltFlags flags; + int argpos = 4; + return bsm.ArgumentCount >= 4 + && (mh = classFile.GetConstantPoolConstantMethodHandle(bsm.BootstrapMethodIndex)).Kind == ClassFile.RefKind.invokeStatic + && mh.Member != null + && IsLambdaAltMetafactory(mh.Member) + && classFile.GetConstantPoolConstantType(bsm.GetArgument(0)) == ClassFile.ConstantType.MethodType + && classFile.GetConstantPoolConstantType(bsm.GetArgument(1)) == ClassFile.ConstantType.MethodHandle + && classFile.GetConstantPoolConstantType(bsm.GetArgument(2)) == ClassFile.ConstantType.MethodType + && classFile.GetConstantPoolConstantType(bsm.GetArgument(3)) == ClassFile.ConstantType.Integer + && ((flags = (AltFlags)classFile.GetConstantPoolConstantInteger(bsm.GetArgument(3))) & ~AltFlags.Mask) == 0 + && ((flags & AltFlags.Markers) == 0 || CheckOptionalArgs(classFile, bsm, ClassFile.ConstantType.Class, ref argpos)) + && ((flags & AltFlags.Bridges) == 0 || CheckOptionalArgs(classFile, bsm, ClassFile.ConstantType.MethodType, ref argpos)) + && argpos == bsm.ArgumentCount; + } + + private static bool IsLambdaAltMetafactory(MemberWrapper mw) + { + return mw.Name == "altMetafactory" + && mw.Signature == "(Ljava.lang.invoke.MethodHandles$Lookup;Ljava.lang.String;Ljava.lang.invoke.MethodType;[Ljava.lang.Object;)Ljava.lang.invoke.CallSite;" + && mw.DeclaringType.Name == "java.lang.invoke.LambdaMetafactory"; + } + + private static bool CheckOptionalArgs(ClassFile classFile, ClassFile.BootstrapMethod bsm, ClassFile.ConstantType type, ref int argpos) + { + if (bsm.ArgumentCount - argpos < 1) + { + return false; + } + if (classFile.GetConstantPoolConstantType(bsm.GetArgument(argpos)) != ClassFile.ConstantType.Integer) + { + return false; + } + int count = classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++)); + if (count < 0 || bsm.ArgumentCount - argpos < count) + { + return false; + } + for (int i = 0; i < count; i++) + { + if (classFile.GetConstantPoolConstantType(bsm.GetArgument(argpos++)) != type) + { + return false; + } + } + return true; + } + + private static bool HasUnloadable(ClassFile.ConstantPoolItemInvokeDynamic cpi) + { + return HasUnloadable(cpi.GetArgTypes()) || cpi.GetRetType().IsUnloadable; + } + + private static bool HasUnloadable(ClassFile.ConstantPoolItemMethodType cpi) + { + return HasUnloadable(cpi.GetArgTypes()) || cpi.GetRetType().IsUnloadable; + } + + private static bool HasUnloadable(ClassFile.ConstantPoolItemMI cpi) + { + return HasUnloadable(cpi.GetArgTypes()) || cpi.GetRetType().IsUnloadable; + } + + private static bool HasUnloadable(TypeWrapper[] wrappers) + { + foreach (TypeWrapper tw in wrappers) + { + if (tw.IsUnloadable) + { + return true; + } + } + return false; + } + } +} diff --git a/runtime/LocalVars.cs b/runtime/LocalVars.cs new file mode 100644 index 0000000..f12f3ee --- /dev/null +++ b/runtime/LocalVars.cs @@ -0,0 +1,640 @@ +/* + Copyright (C) 2002-2010 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.IO; +using System.Collections.Generic; +using System.Diagnostics; +#if STATIC_COMPILER +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; +#else +using System.Reflection.Emit; +#endif +using IKVM.Internal; +using InstructionFlags = IKVM.Internal.ClassFile.Method.InstructionFlags; +using ExceptionTableEntry = IKVM.Internal.ClassFile.Method.ExceptionTableEntry; + +sealed class LocalVar +{ + internal bool isArg; + internal int local; + internal TypeWrapper type; + internal CodeEmitterLocal builder; + // used to emit debugging info, only available if ClassLoaderWrapper.EmitDebugInfo is true + internal string name; + internal int start_pc; + internal int end_pc; +} + +struct LocalVarInfo +{ + private readonly LocalVar[/*instructionIndex*/] localVars; + private readonly LocalVar[/*instructionIndex*/][/*localIndex*/] invokespecialLocalVars; + private readonly LocalVar[/*index*/] allLocalVars; + + internal LocalVarInfo(CodeInfo ma, ClassFile classFile, ClassFile.Method method, UntangledExceptionTable exceptions, MethodWrapper mw, ClassLoaderWrapper classLoader) + { + Dictionary[] localStoreReaders = FindLocalVariables(ma, mw, classFile, method); + + // now that we've done the code flow analysis, we can do a liveness analysis on the local variables + ClassFile.Method.Instruction[] instructions = method.Instructions; + Dictionary localByStoreSite = new Dictionary(); + List locals = new List(); + for (int i = 0; i < localStoreReaders.Length; i++) + { + if (localStoreReaders[i] != null) + { + VisitLocalLoads(ma, method, locals, localByStoreSite, localStoreReaders[i], i, classLoader.EmitDebugInfo); + } + } + Dictionary forwarders = new Dictionary(); + if (classLoader.EmitDebugInfo) + { + InstructionFlags[] flags = MethodAnalyzer.ComputePartialReachability(ma, method.Instructions, exceptions, 0, false); + // if we're emitting debug info, we need to keep dead stores as well... + for (int i = 0; i < instructions.Length; i++) + { + if ((flags[i] & InstructionFlags.Reachable) != 0 + && IsStoreLocal(instructions[i].NormalizedOpCode)) + { + if (!localByStoreSite.ContainsKey(MakeKey(i, instructions[i].NormalizedArg1))) + { + LocalVar v = new LocalVar(); + v.local = instructions[i].NormalizedArg1; + v.type = ma.GetStackTypeWrapper(i, 0); + FindLvtEntry(v, method, i); + locals.Add(v); + localByStoreSite.Add(MakeKey(i, v.local), v); + } + } + } + // to make the debugging experience better, we have to trust the + // LocalVariableTable (unless it's clearly bogus) and merge locals + // together that are the same according to the LVT + for (int i = 0; i < locals.Count - 1; i++) + { + for (int j = i + 1; j < locals.Count; j++) + { + LocalVar v1 = (LocalVar)locals[i]; + LocalVar v2 = (LocalVar)locals[j]; + if (v1.name != null && v1.name == v2.name && v1.start_pc == v2.start_pc && v1.end_pc == v2.end_pc) + { + // we can only merge if the resulting type is valid (this protects against incorrect + // LVT data, but is also needed for constructors, where the uninitialized this is a different + // type from the initialized this) + TypeWrapper tw = InstructionState.FindCommonBaseType(v1.type, v2.type); + if (tw != VerifierTypeWrapper.Invalid) + { + v1.isArg |= v2.isArg; + v1.type = tw; + forwarders.Add(v2, v1); + locals.RemoveAt(j); + j--; + } + } + } + } + } + else + { + for (int i = 0; i < locals.Count - 1; i++) + { + for (int j = i + 1; j < locals.Count; j++) + { + LocalVar v1 = (LocalVar)locals[i]; + LocalVar v2 = (LocalVar)locals[j]; + // if the two locals are the same, we merge them, this is a small + // optimization, it should *not* be required for correctness. + if (v1.local == v2.local && v1.type == v2.type) + { + v1.isArg |= v2.isArg; + forwarders.Add(v2, v1); + locals.RemoveAt(j); + j--; + } + } + } + } + invokespecialLocalVars = new LocalVar[instructions.Length][]; + localVars = new LocalVar[instructions.Length]; + for (int i = 0; i < localVars.Length; i++) + { + LocalVar v = null; + if (localStoreReaders[i] != null) + { + Debug.Assert(IsLoadLocal(instructions[i].NormalizedOpCode)); + // lame way to look up the local variable for a load + // (by indirecting through a corresponding store) + foreach (int store in localStoreReaders[i].Keys) + { + v = localByStoreSite[MakeKey(store, instructions[i].NormalizedArg1)]; + break; + } + } + else + { + if (instructions[i].NormalizedOpCode == NormalizedByteCode.__invokespecial || instructions[i].NormalizedOpCode == NormalizedByteCode.__dynamic_invokespecial) + { + invokespecialLocalVars[i] = new LocalVar[method.MaxLocals]; + for (int j = 0; j < invokespecialLocalVars[i].Length; j++) + { + localByStoreSite.TryGetValue(MakeKey(i, j), out invokespecialLocalVars[i][j]); + } + } + else + { + localByStoreSite.TryGetValue(MakeKey(i, instructions[i].NormalizedArg1), out v); + } + } + if (v != null) + { + LocalVar fwd; + if (forwarders.TryGetValue(v, out fwd)) + { + v = fwd; + } + localVars[i] = v; + } + } + this.allLocalVars = locals.ToArray(); + } + + private static void FindLvtEntry(LocalVar lv, ClassFile.Method method, int instructionIndex) + { + ClassFile.Method.LocalVariableTableEntry[] lvt = method.LocalVariableTableAttribute; + if (lvt != null) + { + int pc = method.Instructions[instructionIndex].PC; + int nextPC = method.Instructions[instructionIndex + 1].PC; + bool isStore = IsStoreLocal(method.Instructions[instructionIndex].NormalizedOpCode); + foreach (ClassFile.Method.LocalVariableTableEntry e in lvt) + { + // TODO validate the contents of the LVT entry + if (e.index == lv.local && + (e.start_pc <= pc || (e.start_pc == nextPC && isStore)) && + e.start_pc + e.length > pc) + { + lv.name = e.name; + lv.start_pc = e.start_pc; + lv.end_pc = e.start_pc + e.length; + break; + } + } + } + } + + // NOTE for dead stores, this returns null + internal LocalVar GetLocalVar(int instructionIndex) + { + return localVars[instructionIndex]; + } + + internal LocalVar[] GetLocalVarsForInvokeSpecial(int instructionIndex) + { + return invokespecialLocalVars[instructionIndex]; + } + + internal LocalVar[] GetAllLocalVars() + { + return allLocalVars; + } + + private static bool IsLoadLocal(NormalizedByteCode bc) + { + return bc == NormalizedByteCode.__aload || + bc == NormalizedByteCode.__iload || + bc == NormalizedByteCode.__lload || + bc == NormalizedByteCode.__fload || + bc == NormalizedByteCode.__dload || + bc == NormalizedByteCode.__iinc || + bc == NormalizedByteCode.__ret; + } + + private static bool IsStoreLocal(NormalizedByteCode bc) + { + return bc == NormalizedByteCode.__astore || + bc == NormalizedByteCode.__istore || + bc == NormalizedByteCode.__lstore || + bc == NormalizedByteCode.__fstore || + bc == NormalizedByteCode.__dstore; + } + + struct FindLocalVarState + { + internal bool changed; + internal FindLocalVarStoreSite[] sites; + + internal void Store(int instructionIndex, int localIndex) + { + if (sites[localIndex].Count == 1 && sites[localIndex][0] == instructionIndex) + { + return; + } + sites = (FindLocalVarStoreSite[])sites.Clone(); + sites[localIndex] = new FindLocalVarStoreSite(); + sites[localIndex].Add(instructionIndex); + } + + internal void Merge(FindLocalVarState state) + { + if (sites == null) + { + sites = state.sites; + changed = true; + } + else + { + bool dirty = true; + for (int i = 0; i < sites.Length; i++) + { + for (int j = 0; j < state.sites[i].Count; j++) + { + if (!sites[i].Contains(state.sites[i][j])) + { + if (dirty) + { + dirty = false; + sites = (FindLocalVarStoreSite[])sites.Clone(); + } + sites[i].Add(state.sites[i][j]); + changed = true; + } + } + } + } + } + + internal FindLocalVarState Copy() + { + FindLocalVarState copy = new FindLocalVarState(); + copy.sites = sites; + return copy; + } + + public override string ToString() + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + if (sites != null) + { + foreach (FindLocalVarStoreSite site in sites) + { + sb.Append('['); + for (int i = 0; i < site.Count; i++) + { + sb.AppendFormat("{0}, ", site[i]); + } + sb.Append(']'); + } + } + return sb.ToString(); + } + } + + struct FindLocalVarStoreSite + { + private int[] data; + + internal bool Contains(int instructionIndex) + { + if (data != null) + { + for (int i = 0; i < data.Length; i++) + { + if (data[i] == instructionIndex) + { + return true; + } + } + } + return false; + } + + internal void Add(int instructionIndex) + { + if (data == null) + { + data = new int[] { instructionIndex }; + } + else + { + data = ArrayUtil.Concat(data, instructionIndex); + } + } + + internal int this[int index] + { + get { return data[index]; } + } + + internal int Count + { + get { return data == null ? 0 : data.Length; } + } + } + + private static Dictionary[] FindLocalVariables(CodeInfo codeInfo, MethodWrapper mw, ClassFile classFile, ClassFile.Method method) + { + FindLocalVarState[] state = new FindLocalVarState[method.Instructions.Length]; + state[0].changed = true; + state[0].sites = new FindLocalVarStoreSite[method.MaxLocals]; + TypeWrapper[] parameters = mw.GetParameters(); + int argpos = 0; + if (!mw.IsStatic) + { + state[0].sites[argpos++].Add(-1); + } + for (int i = 0; i < parameters.Length; i++) + { + state[0].sites[argpos++].Add(-1); + if (parameters[i].IsWidePrimitive) + { + argpos++; + } + } + return FindLocalVariablesImpl(codeInfo, classFile, method, state); + } + + private static Dictionary[] FindLocalVariablesImpl(CodeInfo codeInfo, ClassFile classFile, ClassFile.Method method, FindLocalVarState[] state) + { + ClassFile.Method.Instruction[] instructions = method.Instructions; + ExceptionTableEntry[] exceptions = method.ExceptionTable; + int maxLocals = method.MaxLocals; + Dictionary[] localStoreReaders = new Dictionary[instructions.Length]; + bool done = false; + + while (!done) + { + done = true; + for (int i = 0; i < instructions.Length; i++) + { + if (state[i].changed) + { + done = false; + state[i].changed = false; + + FindLocalVarState curr = state[i].Copy(); + + for (int j = 0; j < exceptions.Length; j++) + { + if (exceptions[j].startIndex <= i && i < exceptions[j].endIndex) + { + state[exceptions[j].handlerIndex].Merge(curr); + } + } + + if (IsLoadLocal(instructions[i].NormalizedOpCode) + && (instructions[i].NormalizedOpCode != NormalizedByteCode.__aload || !VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(i + 1, 0)))) + { + if (localStoreReaders[i] == null) + { + localStoreReaders[i] = new Dictionary(); + } + for (int j = 0; j < curr.sites[instructions[i].NormalizedArg1].Count; j++) + { + localStoreReaders[i][curr.sites[instructions[i].NormalizedArg1][j]] = ""; + } + } + + if (IsStoreLocal(instructions[i].NormalizedOpCode) + && (instructions[i].NormalizedOpCode != NormalizedByteCode.__astore || !VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(i, 0)))) + { + curr.Store(i, instructions[i].NormalizedArg1); + // if this is a store at the end of an exception block, + // we need to propagate the new state to the exception handler + for (int j = 0; j < exceptions.Length; j++) + { + if (exceptions[j].endIndex == i + 1) + { + state[exceptions[j].handlerIndex].Merge(curr); + } + } + } + + if (instructions[i].NormalizedOpCode == NormalizedByteCode.__invokespecial) + { + ClassFile.ConstantPoolItemMI cpi = classFile.GetMethodref(instructions[i].Arg1); + if (ReferenceEquals(cpi.Name, StringConstants.INIT)) + { + TypeWrapper type = codeInfo.GetRawStackTypeWrapper(i, cpi.GetArgTypes().Length); + // after we've invoked the constructor, the uninitialized references + // are now initialized + if (type == VerifierTypeWrapper.UninitializedThis + || VerifierTypeWrapper.IsNew(type)) + { + for (int j = 0; j < maxLocals; j++) + { + if (codeInfo.GetLocalTypeWrapper(i, j) == type) + { + curr.Store(i, j); + } + } + } + } + } + else if (instructions[i].NormalizedOpCode == NormalizedByteCode.__goto_finally) + { + int handler = instructions[i].HandlerIndex; + + // Normally a store at the end of a try block doesn't affect the handler block, + // but in the case of a finally handler it does, so we need to make sure that + // we merge here in case the try block ended with a store. + state[handler].Merge(curr); + + // Now we recursively analyse the handler and afterwards merge the endfault locations back to us + FindLocalVarState[] handlerState = new FindLocalVarState[instructions.Length]; + handlerState[handler].Merge(curr); + curr = new FindLocalVarState(); + FindLocalVariablesImpl(codeInfo, classFile, method, handlerState); + + // Merge back to the target of our __goto_finally + for (int j = 0; j < handlerState.Length; j++) + { + if (instructions[j].NormalizedOpCode == NormalizedByteCode.__athrow + && codeInfo.HasState(j) + && VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(j, 0)) + && ((VerifierTypeWrapper)codeInfo.GetRawStackTypeWrapper(j, 0)).Index == handler) + { + curr.Merge(handlerState[j]); + } + } + } + + switch (ByteCodeMetaData.GetFlowControl(instructions[i].NormalizedOpCode)) + { + case ByteCodeFlowControl.Switch: + { + for (int j = 0; j < instructions[i].SwitchEntryCount; j++) + { + state[instructions[i].GetSwitchTargetIndex(j)].Merge(curr); + } + state[instructions[i].DefaultTarget].Merge(curr); + break; + } + case ByteCodeFlowControl.Branch: + state[instructions[i].TargetIndex].Merge(curr); + break; + case ByteCodeFlowControl.CondBranch: + state[instructions[i].TargetIndex].Merge(curr); + state[i + 1].Merge(curr); + break; + case ByteCodeFlowControl.Return: + case ByteCodeFlowControl.Throw: + break; + case ByteCodeFlowControl.Next: + state[i + 1].Merge(curr); + break; + default: + throw new InvalidOperationException(); + } + } + } + } + return localStoreReaders; + } + + private static void VisitLocalLoads(CodeInfo codeInfo, ClassFile.Method method, List locals, Dictionary localByStoreSite, Dictionary storeSites, int instructionIndex, bool debug) + { + Debug.Assert(IsLoadLocal(method.Instructions[instructionIndex].NormalizedOpCode)); + LocalVar local = null; + TypeWrapper type = VerifierTypeWrapper.Null; + int localIndex = method.Instructions[instructionIndex].NormalizedArg1; + bool isArg = false; + foreach (int store in storeSites.Keys) + { + if (store == -1) + { + // it's a method argument, it has no initial store, but the type is simply the parameter type + type = InstructionState.FindCommonBaseType(type, codeInfo.GetLocalTypeWrapper(0, localIndex)); + isArg = true; + } + else + { + if (method.Instructions[store].NormalizedOpCode == NormalizedByteCode.__invokespecial) + { + type = InstructionState.FindCommonBaseType(type, codeInfo.GetLocalTypeWrapper(store + 1, localIndex)); + } + else if (method.Instructions[store].NormalizedOpCode == NormalizedByteCode.__static_error) + { + // it's an __invokespecial that turned into a __static_error + // (since a __static_error doesn't continue, we don't need to set type) + } + else + { + Debug.Assert(IsStoreLocal(method.Instructions[store].NormalizedOpCode)); + type = InstructionState.FindCommonBaseType(type, codeInfo.GetStackTypeWrapper(store, 0)); + } + } + // we can't have an invalid type, because that would have failed verification earlier + Debug.Assert(type != VerifierTypeWrapper.Invalid); + + LocalVar l; + if (localByStoreSite.TryGetValue(MakeKey(store, localIndex), out l)) + { + if (local == null) + { + local = l; + } + else if (local != l) + { + // If we've already defined a LocalVar and we find another one, then we merge them + // together. + // This happens for the following code fragment: + // + // int i = -1; + // try { i = 0; for(; ; ) System.out.println(i); } catch(Exception x) {} + // try { i = 0; for(; ; ) System.out.println(i); } catch(Exception x) {} + // System.out.println(i); + // + local = MergeLocals(locals, localByStoreSite, local, l); + } + } + } + if (local == null) + { + local = new LocalVar(); + local.local = localIndex; + if (VerifierTypeWrapper.IsThis(type)) + { + local.type = ((VerifierTypeWrapper)type).UnderlyingType; + } + else + { + local.type = type; + } + local.isArg = isArg; + if (debug) + { + FindLvtEntry(local, method, instructionIndex); + } + locals.Add(local); + } + else + { + local.isArg |= isArg; + local.type = InstructionState.FindCommonBaseType(local.type, type); + Debug.Assert(local.type != VerifierTypeWrapper.Invalid); + } + foreach (int store in storeSites.Keys) + { + LocalVar v; + if (!localByStoreSite.TryGetValue(MakeKey(store, localIndex), out v)) + { + localByStoreSite[MakeKey(store, localIndex)] = local; + } + else if (v != local) + { + local = MergeLocals(locals, localByStoreSite, local, v); + } + } + } + + private static long MakeKey(int i, int j) + { + return (((long)(uint)i) << 32) + (uint)j; + } + + private static LocalVar MergeLocals(List locals, Dictionary localByStoreSite, LocalVar l1, LocalVar l2) + { + Debug.Assert(l1 != l2); + Debug.Assert(l1.local == l2.local); + for (int i = 0; i < locals.Count; i++) + { + if (locals[i] == l2) + { + locals.RemoveAt(i); + i--; + } + } + Dictionary temp = new Dictionary(localByStoreSite); + localByStoreSite.Clear(); + foreach (KeyValuePair kv in temp) + { + localByStoreSite[kv.Key] = kv.Value == l2 ? l1 : kv.Value; + } + l1.isArg |= l2.isArg; + l1.type = InstructionState.FindCommonBaseType(l1.type, l2.type); + Debug.Assert(l1.type != VerifierTypeWrapper.Invalid); + return l1; + } +} diff --git a/runtime/MemberWrapper.cs b/runtime/MemberWrapper.cs new file mode 100644 index 0000000..58f0411 --- /dev/null +++ b/runtime/MemberWrapper.cs @@ -0,0 +1,2163 @@ +/* + Copyright (C) 2002-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +#if STATIC_COMPILER || STUB_GENERATOR +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif +using System.Diagnostics; +using IKVM.Attributes; +using System.Threading; +using System.Runtime.InteropServices; + +namespace IKVM.Internal +{ + [Flags] + enum MemberFlags : short + { + None = 0, + HideFromReflection = 1, + ExplicitOverride = 2, + MirandaMethod = 8, + AccessStub = 16, + InternalAccess = 32, // member has "internal" access (@ikvm.lang.Internal) + PropertyAccessor = 64, + Intrinsic = 128, + CallerID = 256, + NonPublicTypeInSignature = 512, // this flag is only available after linking and is not set for access stubs + DelegateInvokeWithByRefParameter = 1024, + Type2FinalField = 2048, + NoOp = 4096, // empty static initializer + } + + abstract class MemberWrapper + { + private HandleWrapper handle; + private readonly TypeWrapper declaringType; + protected readonly Modifiers modifiers; + private MemberFlags flags; + private readonly string name; + private readonly string sig; + + private sealed class HandleWrapper + { + internal readonly IntPtr Value; + + [System.Security.SecurityCritical] + internal HandleWrapper(MemberWrapper obj) + { + Value = (IntPtr)GCHandle.Alloc(obj, GCHandleType.WeakTrackResurrection); + } + +#if CLASSGC + [System.Security.SecuritySafeCritical] + ~HandleWrapper() + { + if (!Environment.HasShutdownStarted) + { + GCHandle h = (GCHandle)Value; + if (h.Target == null) + { + h.Free(); + } + else + { + GC.ReRegisterForFinalize(this); + } + } + } +#endif + } + + protected MemberWrapper(TypeWrapper declaringType, string name, string sig, Modifiers modifiers, MemberFlags flags) + { + Debug.Assert(declaringType != null); + this.declaringType = declaringType; + this.name = String.Intern(name); + this.sig = String.Intern(sig); + this.modifiers = modifiers; + this.flags = flags; + } + + internal IntPtr Cookie + { + [System.Security.SecurityCritical] + get + { + lock(this) + { + if(handle == null) + { + handle = new HandleWrapper(this); + } + } + return handle.Value; + } + } + + [System.Security.SecurityCritical] + internal static MemberWrapper FromCookieImpl(IntPtr cookie) + { + return (MemberWrapper)GCHandle.FromIntPtr(cookie).Target; + } + + internal TypeWrapper DeclaringType + { + get + { + return declaringType; + } + } + + internal string Name + { + get + { + return name; + } + } + + internal string Signature + { + get + { + return sig; + } + } + + internal bool IsAccessibleFrom(TypeWrapper referencedType, TypeWrapper caller, TypeWrapper instance) + { + if(referencedType.IsAccessibleFrom(caller)) + { + return ( + caller == DeclaringType || + IsPublicOrProtectedMemberAccessible(caller, instance) || + (IsInternal && DeclaringType.InternalsVisibleTo(caller)) || + (!IsPrivate && DeclaringType.IsPackageAccessibleFrom(caller))) + // The JVM supports accessing members that have non-public types in their signature from another package, + // but the CLI doesn't. It would be nice if we worked around that by emitting extra accessors, but for now + // we'll simply disallow such access across assemblies (unless the appropriate InternalsVisibleToAttribute exists). + && (!(HasNonPublicTypeInSignature || IsType2FinalField) || InPracticeInternalsVisibleTo(caller)); + } + return false; + } + + private bool IsPublicOrProtectedMemberAccessible(TypeWrapper caller, TypeWrapper instance) + { + if (IsPublic || (IsProtected && caller.IsSubTypeOf(DeclaringType) && (IsStatic || instance.IsUnloadable || instance.IsSubTypeOf(caller)))) + { + return DeclaringType.IsPublic || InPracticeInternalsVisibleTo(caller); + } + return false; + } + + private bool InPracticeInternalsVisibleTo(TypeWrapper caller) + { +#if !STATIC_COMPILER + if (DeclaringType.TypeAsTBD.Assembly.Equals(caller.TypeAsTBD.Assembly)) + { + // both the caller and the declaring type are in the same assembly + // so we know that the internals are visible + // (this handles the case where we're running in dynamic mode) + return true; + } +#endif +#if CLASSGC + if (DeclaringType.IsDynamic) + { + // if we are dynamic, we can just become friends with the caller + DeclaringType.GetClassLoader().GetTypeWrapperFactory().AddInternalsVisibleTo(caller.TypeAsTBD.Assembly); + return true; + } +#endif + return DeclaringType.InternalsVisibleTo(caller); + } + + internal bool IsHideFromReflection + { + get + { + return (flags & MemberFlags.HideFromReflection) != 0; + } + } + + internal bool IsExplicitOverride + { + get + { + return (flags & MemberFlags.ExplicitOverride) != 0; + } + } + + internal bool IsMirandaMethod + { + get + { + return (flags & MemberFlags.MirandaMethod) != 0; + } + } + + internal bool IsAccessStub + { + get + { + return (flags & MemberFlags.AccessStub) != 0; + } + } + + internal bool IsPropertyAccessor + { + get + { + return (flags & MemberFlags.PropertyAccessor) != 0; + } + set + { + // this is unsynchronized, so it may only be called during the JavaTypeImpl constructor + if(value) + { + flags |= MemberFlags.PropertyAccessor; + } + else + { + flags &= ~MemberFlags.PropertyAccessor; + } + } + } + + internal bool IsIntrinsic + { + get + { + return (flags & MemberFlags.Intrinsic) != 0; + } + } + + protected void SetIntrinsicFlag() + { + flags |= MemberFlags.Intrinsic; + } + + protected void SetNonPublicTypeInSignatureFlag() + { + flags |= MemberFlags.NonPublicTypeInSignature; + } + + internal bool HasNonPublicTypeInSignature + { + get { return (flags & MemberFlags.NonPublicTypeInSignature) != 0; } + } + + protected void SetType2FinalField() + { + flags |= MemberFlags.Type2FinalField; + } + + internal bool IsType2FinalField + { + get { return (flags & MemberFlags.Type2FinalField) != 0; } + } + + internal bool HasCallerID + { + get + { + return (flags & MemberFlags.CallerID) != 0; + } + } + + internal bool IsDelegateInvokeWithByRefParameter + { + get { return (flags & MemberFlags.DelegateInvokeWithByRefParameter) != 0; } + } + + internal bool IsNoOp + { + get { return (flags & MemberFlags.NoOp) != 0; } + } + + internal Modifiers Modifiers + { + get + { + return modifiers; + } + } + + internal bool IsStatic + { + get + { + return (modifiers & Modifiers.Static) != 0; + } + } + + internal bool IsInternal + { + get + { + return (flags & MemberFlags.InternalAccess) != 0; + } + } + + internal bool IsPublic + { + get + { + return (modifiers & Modifiers.Public) != 0; + } + } + + internal bool IsPrivate + { + get + { + return (modifiers & Modifiers.Private) != 0; + } + } + + internal bool IsProtected + { + get + { + return (modifiers & Modifiers.Protected) != 0; + } + } + + internal bool IsFinal + { + get + { + return (modifiers & Modifiers.Final) != 0; + } + } + } + + abstract class MethodWrapper : MemberWrapper + { +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + private volatile java.lang.reflect.Executable reflectionMethod; +#endif + internal static readonly MethodWrapper[] EmptyArray = new MethodWrapper[0]; + private MethodBase method; + private string[] declaredExceptions; + private TypeWrapper returnTypeWrapper; + private TypeWrapper[] parameterTypeWrappers; + +#if EMITTERS + internal virtual void EmitCall(CodeEmitter ilgen) + { + throw new InvalidOperationException(); + } + + internal virtual void EmitCallvirt(CodeEmitter ilgen) + { + throw new InvalidOperationException(); + } + + internal virtual void EmitCallvirtReflect(CodeEmitter ilgen) + { + EmitCallvirt(ilgen); + } + + internal virtual void EmitNewobj(CodeEmitter ilgen) + { + throw new InvalidOperationException(); + } + + internal virtual bool EmitIntrinsic(EmitIntrinsicContext context) + { + return Intrinsics.Emit(context); + } +#endif // EMITTERS + + internal virtual bool IsDynamicOnly + { + get + { + return false; + } + } + + internal MethodWrapper(TypeWrapper declaringType, string name, string sig, MethodBase method, TypeWrapper returnType, TypeWrapper[] parameterTypes, Modifiers modifiers, MemberFlags flags) + : base(declaringType, name, sig, modifiers, flags) + { + Profiler.Count("MethodWrapper"); + this.method = method; + Debug.Assert(((returnType == null) == (parameterTypes == null)) || (returnType == PrimitiveTypeWrapper.VOID)); + this.returnTypeWrapper = returnType; + this.parameterTypeWrappers = parameterTypes; + if (Intrinsics.IsIntrinsic(this)) + { + SetIntrinsicFlag(); + } + UpdateNonPublicTypeInSignatureFlag(); + } + + private void UpdateNonPublicTypeInSignatureFlag() + { + if ((IsPublic || IsProtected) && (returnTypeWrapper != null && parameterTypeWrappers != null) && !(this is AccessStubMethodWrapper) && !(this is AccessStubConstructorMethodWrapper)) + { + if (!returnTypeWrapper.IsPublic && !returnTypeWrapper.IsUnloadable) + { + SetNonPublicTypeInSignatureFlag(); + } + else + { + foreach (TypeWrapper tw in parameterTypeWrappers) + { + if (!tw.IsPublic && !tw.IsUnloadable) + { + SetNonPublicTypeInSignatureFlag(); + break; + } + } + } + } + } + + internal void SetDeclaredExceptions(string[] exceptions) + { + if(exceptions == null) + { + exceptions = new string[0]; + } + this.declaredExceptions = (string[])exceptions.Clone(); + } + + internal string[] GetDeclaredExceptions() + { + return declaredExceptions; + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal java.lang.reflect.Executable ToMethodOrConstructor(bool copy) + { +#if FIRST_PASS + return null; +#else + java.lang.reflect.Executable method = reflectionMethod; + if (method == null) + { + Link(); + ClassLoaderWrapper loader = this.DeclaringType.GetClassLoader(); + TypeWrapper[] argTypes = GetParameters(); + java.lang.Class[] parameterTypes = new java.lang.Class[argTypes.Length]; + for (int i = 0; i < argTypes.Length; i++) + { + parameterTypes[i] = argTypes[i].EnsureLoadable(loader).ClassObject; + } + java.lang.Class[] checkedExceptions = GetExceptions(); + if (this.IsConstructor) + { + method = new java.lang.reflect.Constructor( + this.DeclaringType.ClassObject, + parameterTypes, + checkedExceptions, + (int)this.Modifiers | (this.IsInternal ? 0x40000000 : 0), + Array.IndexOf(this.DeclaringType.GetMethods(), this), + this.DeclaringType.GetGenericMethodSignature(this), + null, + null + ); + } + else + { + method = new java.lang.reflect.Method( + this.DeclaringType.ClassObject, + this.Name, + parameterTypes, + this.ReturnType.EnsureLoadable(loader).ClassObject, + checkedExceptions, + (int)this.Modifiers | (this.IsInternal ? 0x40000000 : 0), + Array.IndexOf(this.DeclaringType.GetMethods(), this), + this.DeclaringType.GetGenericMethodSignature(this), + null, + null, + null + ); + } + lock (this) + { + if (reflectionMethod == null) + { + reflectionMethod = method; + } + else + { + method = reflectionMethod; + } + } + } + if (copy) + { + java.lang.reflect.Constructor ctor = method as java.lang.reflect.Constructor; + if (ctor != null) + { + return ctor.copy(); + } + return ((java.lang.reflect.Method)method).copy(); + } + return method; +#endif + } + +#if !FIRST_PASS + private java.lang.Class[] GetExceptions() + { + string[] classes = declaredExceptions; + Type[] types = Type.EmptyTypes; + if (classes == null) + { + // NOTE if method is a MethodBuilder, GetCustomAttributes doesn't work (and if + // the method had any declared exceptions, the declaredExceptions field would have + // been set) + if (method != null && !(method is MethodBuilder)) + { + ThrowsAttribute attr = AttributeHelper.GetThrows(method); + if (attr != null) + { + classes = attr.classes; + types = attr.types; + } + } + } + if (classes != null) + { + java.lang.Class[] array = new java.lang.Class[classes.Length]; + for (int i = 0; i < classes.Length; i++) + { + array[i] = this.DeclaringType.GetClassLoader().LoadClassByDottedName(classes[i]).ClassObject; + } + return array; + } + else + { + java.lang.Class[] array = new java.lang.Class[types.Length]; + for (int i = 0; i < types.Length; i++) + { + array[i] = types[i]; + } + return array; + } + } +#endif // !FIRST_PASS + + internal static MethodWrapper FromExecutable(java.lang.reflect.Executable executable) + { +#if FIRST_PASS + return null; +#else + return TypeWrapper.FromClass(executable.getDeclaringClass()).GetMethods()[executable._slot()]; +#endif + } +#endif // !STATIC_COMPILER && !STUB_GENERATOR + + [System.Security.SecurityCritical] + internal static MethodWrapper FromCookie(IntPtr cookie) + { + return (MethodWrapper)FromCookieImpl(cookie); + } + + internal bool IsLinked + { + get + { + return parameterTypeWrappers != null; + } + } + + internal void Link() + { + Link(LoadMode.Link); + } + + internal void Link(LoadMode mode) + { + lock(this) + { + if(parameterTypeWrappers != null) + { + return; + } + } + ClassLoaderWrapper loader = this.DeclaringType.GetClassLoader(); + TypeWrapper ret = loader.RetTypeWrapperFromSig(Signature, mode); + TypeWrapper[] parameters = loader.ArgTypeWrapperListFromSig(Signature, mode); + lock(this) + { + try + { + // critical code in the finally block to avoid Thread.Abort interrupting the thread + } + finally + { + if(parameterTypeWrappers == null) + { + Debug.Assert(returnTypeWrapper == null || returnTypeWrapper == PrimitiveTypeWrapper.VOID); + returnTypeWrapper = ret; + parameterTypeWrappers = parameters; + UpdateNonPublicTypeInSignatureFlag(); + if(method == null) + { + try + { + DoLinkMethod(); + } + catch + { + // HACK if linking fails, we unlink to make sure + // that the next link attempt will fail again + returnTypeWrapper = null; + parameterTypeWrappers = null; + throw; + } + } + } + } + } + } + + protected virtual void DoLinkMethod() + { + method = this.DeclaringType.LinkMethod(this); + } + + [Conditional("DEBUG")] + internal void AssertLinked() + { + if(!(parameterTypeWrappers != null && returnTypeWrapper != null)) + { + Tracer.Error(Tracer.Runtime, "AssertLinked failed: " + this.DeclaringType.Name + "::" + this.Name + this.Signature); + } + Debug.Assert(parameterTypeWrappers != null && returnTypeWrapper != null, this.DeclaringType.Name + "::" + this.Name + this.Signature); + } + + internal TypeWrapper ReturnType + { + get + { + AssertLinked(); + return returnTypeWrapper; + } + } + + internal TypeWrapper[] GetParameters() + { + AssertLinked(); + return parameterTypeWrappers; + } + +#if !STUB_GENERATOR + internal DefineMethodHelper GetDefineMethodHelper() + { + return new DefineMethodHelper(this); + } +#endif + + internal Type ReturnTypeForDefineMethod + { + get + { + return ReturnType.TypeAsSignatureType; + } + } + + internal Type[] GetParametersForDefineMethod() + { + TypeWrapper[] wrappers = GetParameters(); + int len = wrappers.Length; + if(HasCallerID) + { + len++; + } + Type[] temp = new Type[len]; + for(int i = 0; i < wrappers.Length; i++) + { + temp[i] = wrappers[i].TypeAsSignatureType; + } + if(HasCallerID) + { + temp[len - 1] = CoreClasses.ikvm.@internal.CallerID.Wrapper.TypeAsSignatureType; + } + return temp; + } + + // we expose the underlying MethodBase object, + // for Java types, this is the method that contains the compiled Java bytecode + // for remapped types, this is the mbCore method (not the helper) + // Note that for some artificial methods (notably wrap() in enums), method is null + internal MethodBase GetMethod() + { + AssertLinked(); + return method; + } + + internal string RealName + { + get + { + AssertLinked(); + return method.Name; + } + } + + internal bool IsAbstract + { + get + { + return (Modifiers & Modifiers.Abstract) != 0; + } + } + + internal bool RequiresNonVirtualDispatcher + { + get + { + return !IsConstructor + && !IsStatic + && !IsPrivate + && !IsAbstract + && !IsFinal + && !DeclaringType.IsFinal; + } + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal Type GetDelegateType() + { + TypeWrapper[] paramTypes = GetParameters(); + if (paramTypes.Length > MethodHandleUtil.MaxArity) + { + Type type = DeclaringType.TypeAsBaseType.Assembly.GetType( + ReturnType == PrimitiveTypeWrapper.VOID ? "__<>NVIV`" + paramTypes.Length : "__<>NVI`" + (paramTypes.Length + 1)); + if (type == null) + { + type = DeclaringType.GetClassLoader().GetTypeWrapperFactory().DefineDelegate(paramTypes.Length, ReturnType == PrimitiveTypeWrapper.VOID); + } + Type[] types = new Type[paramTypes.Length + (ReturnType == PrimitiveTypeWrapper.VOID ? 0 : 1)]; + for (int i = 0; i < paramTypes.Length; i++) + { + types[i] = paramTypes[i].TypeAsSignatureType; + } + if (ReturnType != PrimitiveTypeWrapper.VOID) + { + types[types.Length - 1] = ReturnType.TypeAsSignatureType; + } + return type.MakeGenericType(types); + } + return MethodHandleUtil.CreateMemberWrapperDelegateType(paramTypes, ReturnType); + } + + internal void ResolveMethod() + { +#if !FIRST_PASS + // if we've still got the builder object, we need to replace it with the real thing before we can call it + MethodBuilder mb = method as MethodBuilder; + if (mb != null) + { + method = mb.Module.ResolveMethod(mb.GetToken().Token); + } +#endif + } + + [HideFromJava] + internal virtual object InvokeNonvirtualRemapped(object obj, object[] args) + { + throw new InvalidOperationException(); + } + + [HideFromJava] + protected static object InvokeAndUnwrapException(MethodBase mb, object obj, object[] args) + { +#if FIRST_PASS + return null; +#else + try + { + return mb.Invoke(obj, args); + } + catch (TargetInvocationException x) + { + throw ikvm.runtime.Util.mapException(x.InnerException); + } +#endif + } + + [HideFromJava] + internal virtual object Invoke(object obj, object[] args) + { + return InvokeAndUnwrapException(method, obj, args); + } + + [HideFromJava] + internal virtual object CreateInstance(object[] args) + { +#if FIRST_PASS + return null; +#else + try + { + return ((ConstructorInfo)method).Invoke(args); + } + catch (TargetInvocationException x) + { + throw ikvm.runtime.Util.mapException(x.InnerException); + } +#endif + } +#endif // !STATIC_COMPILER && !STUB_GENERATOR + + internal static OpCode SimpleOpCodeToOpCode(SimpleOpCode opc) + { + switch(opc) + { + case SimpleOpCode.Call: + return OpCodes.Call; + case SimpleOpCode.Callvirt: + return OpCodes.Callvirt; + case SimpleOpCode.Newobj: + return OpCodes.Newobj; + default: + throw new InvalidOperationException(); + } + } + + internal virtual bool IsOptionalAttributeAnnotationValue + { + get { return false; } + } + + internal bool IsConstructor + { + get { return (object)Name == (object)StringConstants.INIT; } + } + + internal bool IsClassInitializer + { + get { return (object)Name == (object)StringConstants.CLINIT; } + } + + internal bool IsVirtual + { + get + { + return (modifiers & (Modifiers.Static | Modifiers.Private)) == 0 + && !IsConstructor; + } + } + + internal bool IsFinalizeOrClone + { + get + { + return IsProtected + && (DeclaringType == CoreClasses.java.lang.Object.Wrapper || DeclaringType == CoreClasses.java.lang.Throwable.Wrapper) + && (Name == StringConstants.CLONE || Name == StringConstants.FINALIZE); + } + } + } + + abstract class SmartMethodWrapper : MethodWrapper + { + internal SmartMethodWrapper(TypeWrapper declaringType, string name, string sig, MethodBase method, TypeWrapper returnType, TypeWrapper[] parameterTypes, Modifiers modifiers, MemberFlags flags) + : base(declaringType, name, sig, method, returnType, parameterTypes, modifiers, flags) + { + } + +#if EMITTERS + internal sealed override void EmitCall(CodeEmitter ilgen) + { + AssertLinked(); + CallImpl(ilgen); + } + + protected virtual void CallImpl(CodeEmitter ilgen) + { + throw new InvalidOperationException(); + } + + internal sealed override void EmitCallvirt(CodeEmitter ilgen) + { + AssertLinked(); + if(DeclaringType.IsNonPrimitiveValueType) + { + // callvirt isn't allowed on a value type + // (we don't need to check for a null reference, because we're always dealing with an unboxed value) + CallImpl(ilgen); + } + else + { + CallvirtImpl(ilgen); + } + } + + protected virtual void CallvirtImpl(CodeEmitter ilgen) + { + throw new InvalidOperationException(); + } + + internal sealed override void EmitNewobj(CodeEmitter ilgen) + { + AssertLinked(); + NewobjImpl(ilgen); + if(DeclaringType.IsNonPrimitiveValueType) + { + DeclaringType.EmitBox(ilgen); + } + } + + protected virtual void NewobjImpl(CodeEmitter ilgen) + { + throw new InvalidOperationException(); + } +#endif // EMITTERS + } + + enum SimpleOpCode : byte + { + Call, + Callvirt, + Newobj + } + + sealed class SimpleCallMethodWrapper : MethodWrapper + { + private readonly SimpleOpCode call; + private readonly SimpleOpCode callvirt; + + internal SimpleCallMethodWrapper(TypeWrapper declaringType, string name, string sig, MethodInfo method, TypeWrapper returnType, TypeWrapper[] parameterTypes, Modifiers modifiers, MemberFlags flags, SimpleOpCode call, SimpleOpCode callvirt) + : base(declaringType, name, sig, method, returnType, parameterTypes, modifiers, flags) + { + this.call = call; + this.callvirt = callvirt; + } + +#if EMITTERS + internal override void EmitCall(CodeEmitter ilgen) + { + ilgen.Emit(SimpleOpCodeToOpCode(call), GetMethod()); + } + + internal override void EmitCallvirt(CodeEmitter ilgen) + { + ilgen.Emit(SimpleOpCodeToOpCode(callvirt), GetMethod()); + } +#endif // EMITTERS + } + + sealed class TypicalMethodWrapper : SmartMethodWrapper + { + internal TypicalMethodWrapper(TypeWrapper declaringType, string name, string sig, MethodBase method, TypeWrapper returnType, TypeWrapper[] parameterTypes, Modifiers modifiers, MemberFlags flags) + : base(declaringType, name, sig, method, returnType, parameterTypes, modifiers, flags) + { + } + +#if EMITTERS + protected override void CallImpl(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Call, GetMethod()); + } + + protected override void CallvirtImpl(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Callvirt, GetMethod()); + } + + protected override void NewobjImpl(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Newobj, GetMethod()); + } +#endif // EMITTERS + } + + abstract class MirandaMethodWrapper : SmartMethodWrapper + { + private readonly MethodWrapper ifmethod; + + private MirandaMethodWrapper(TypeWrapper declaringType, MethodWrapper ifmethod, Modifiers modifiers) + : base(declaringType, ifmethod.Name, ifmethod.Signature, null, null, null, modifiers, MemberFlags.HideFromReflection | MemberFlags.MirandaMethod) + { + this.ifmethod = ifmethod; + } + + private sealed class AbstractMirandaMethodWrapper : MirandaMethodWrapper + { + internal AbstractMirandaMethodWrapper(TypeWrapper declaringType, MethodWrapper ifmethod) + : base(declaringType, ifmethod, Modifiers.Public | Modifiers.Abstract) + { + } + } + + private sealed class DefaultMirandaMethodWrapper : MirandaMethodWrapper + { + internal DefaultMirandaMethodWrapper(TypeWrapper declaringType, MethodWrapper ifmethod) + : base(declaringType, ifmethod, Modifiers.Public) + { + } + } + + private sealed class ErrorMirandaMethodWrapper : MirandaMethodWrapper + { + private string error; + + internal ErrorMirandaMethodWrapper(TypeWrapper declaringType, MethodWrapper ifmethod, string error) + : base(declaringType, ifmethod, Modifiers.Public) + { + this.error = error; + } + + protected override MirandaMethodWrapper AddConflictError(MethodWrapper mw) + { + error += " " + mw.DeclaringType.Name + "." + mw.Name; + return this; + } + + internal override string Error + { + get { return error; } + } + } + + internal static MirandaMethodWrapper Create(TypeWrapper declaringType, MethodWrapper ifmethod) + { + DefaultMirandaMethodWrapper dmmw = ifmethod as DefaultMirandaMethodWrapper; + if (dmmw != null) + { + return new DefaultMirandaMethodWrapper(declaringType, dmmw.BaseMethod); + } + return ifmethod.IsAbstract + ? (MirandaMethodWrapper)new AbstractMirandaMethodWrapper(declaringType, ifmethod) + : (MirandaMethodWrapper)new DefaultMirandaMethodWrapper(declaringType, ifmethod); + } + + internal MirandaMethodWrapper Update(MethodWrapper mw) + { + if (ifmethod == mw) + { + // an interface can be implemented multiple times + return this; + } + else if (ifmethod.DeclaringType.ImplementsInterface(mw.DeclaringType)) + { + // we can override a base interface without problems + return this; + } + else if (mw.DeclaringType.ImplementsInterface(ifmethod.DeclaringType)) + { + return Create(DeclaringType, mw); + } + else if (!ifmethod.IsAbstract && !mw.IsAbstract) + { + return AddConflictError(mw); + } + else if (!ifmethod.IsAbstract && mw.IsAbstract) + { + return new ErrorMirandaMethodWrapper(DeclaringType, mw, DeclaringType.Name + "." + Name + Signature); + } + else + { + return this; + } + } + + protected virtual MirandaMethodWrapper AddConflictError(MethodWrapper mw) + { + return new ErrorMirandaMethodWrapper(DeclaringType, ifmethod, "Conflicting default methods:") + .AddConflictError(ifmethod) + .AddConflictError(mw); + } + + internal bool IsConflictError + { + get { return Error != null && Error.StartsWith("Conflicting default methods:"); } + } + + internal MethodWrapper BaseMethod + { + get { return ifmethod; } + } + + internal virtual string Error + { + get { return null; } + } + +#if EMITTERS + protected override void CallImpl(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Call, GetMethod()); + } + + protected override void CallvirtImpl(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Callvirt, GetMethod()); + } +#endif // EMITTERS + } + + sealed class GhostMethodWrapper : SmartMethodWrapper + { + private MethodInfo ghostMethod; + private MethodInfo defaultImpl; + + internal GhostMethodWrapper(TypeWrapper declaringType, string name, string sig, MethodBase method, MethodInfo ghostMethod, TypeWrapper returnType, TypeWrapper[] parameterTypes, Modifiers modifiers, MemberFlags flags) + : base(declaringType, name, sig, method, returnType, parameterTypes, modifiers, flags) + { + // make sure we weren't handed the ghostMethod in the wrapper value type + Debug.Assert(method == null || method.DeclaringType.IsInterface); + this.ghostMethod = ghostMethod; + } + +#if EMITTERS + protected override void CallImpl(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Call, defaultImpl); + } + + protected override void CallvirtImpl(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Call, ghostMethod); + } +#endif + +#if !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + [HideFromJava] + internal override object Invoke(object obj, object[] args) + { + return InvokeAndUnwrapException(ghostMethod, DeclaringType.GhostWrap(obj), args); + } +#endif + + internal void SetDefaultImpl(MethodInfo impl) + { + this.defaultImpl = impl; + } + + internal MethodInfo GetDefaultImpl() + { + return defaultImpl; + } + +#if STATIC_COMPILER + internal void SetGhostMethod(MethodBuilder mb) + { + this.ghostMethod = mb; + } + + internal MethodBuilder GetGhostMethod() + { + return (MethodBuilder)ghostMethod; + } +#endif + } + + sealed class AccessStubMethodWrapper : SmartMethodWrapper + { + private readonly MethodInfo stubVirtual; + private readonly MethodInfo stubNonVirtual; + + internal AccessStubMethodWrapper(TypeWrapper declaringType, string name, string sig, MethodInfo core, MethodInfo stubVirtual, MethodInfo stubNonVirtual, TypeWrapper returnType, TypeWrapper[] parameterTypes, Modifiers modifiers, MemberFlags flags) + : base(declaringType, name, sig, core, returnType, parameterTypes, modifiers, flags) + { + this.stubVirtual = stubVirtual; + this.stubNonVirtual = stubNonVirtual; + } + +#if EMITTERS + protected override void CallImpl(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Call, stubNonVirtual); + } + + protected override void CallvirtImpl(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Callvirt, stubVirtual); + } +#endif // EMITTERS + } + + sealed class AccessStubConstructorMethodWrapper : SmartMethodWrapper + { + private readonly ConstructorInfo stub; + + internal AccessStubConstructorMethodWrapper(TypeWrapper declaringType, string sig, ConstructorInfo core, ConstructorInfo stub, TypeWrapper[] parameterTypes, Modifiers modifiers, MemberFlags flags) + : base(declaringType, StringConstants.INIT, sig, core, PrimitiveTypeWrapper.VOID, parameterTypes, modifiers, flags) + { + this.stub = stub; + } + +#if EMITTERS + protected override void CallImpl(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Call, stub); + } + + protected override void NewobjImpl(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Newobj, stub); + } +#endif // EMITTERS + } + + sealed class DefaultInterfaceMethodWrapper : SmartMethodWrapper + { + private MethodInfo impl; + + internal DefaultInterfaceMethodWrapper(TypeWrapper declaringType, string name, string sig, MethodInfo ifmethod, MethodInfo impl, TypeWrapper returnType, TypeWrapper[] parameterTypes, Modifiers modifiers, MemberFlags flags) + : base(declaringType, name, sig, ifmethod, returnType, parameterTypes, modifiers, flags) + { + this.impl = impl; + } + + internal static MethodInfo GetImpl(MethodWrapper mw) + { + DefaultInterfaceMethodWrapper dimw = mw as DefaultInterfaceMethodWrapper; + if (dimw != null) + { + return dimw.impl; + } + else + { + return ((GhostMethodWrapper)mw).GetDefaultImpl(); + } + } + + internal static void SetImpl(MethodWrapper mw, MethodInfo impl) + { + DefaultInterfaceMethodWrapper dimw = mw as DefaultInterfaceMethodWrapper; + if (dimw != null) + { + dimw.impl = impl; + } + else + { + ((GhostMethodWrapper)mw).SetDefaultImpl(impl); + } + } + +#if EMITTERS + protected override void CallImpl(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Call, impl); + } + + protected override void CallvirtImpl(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Callvirt, GetMethod()); + } +#endif // EMITTERS + } + + sealed class PrivateInterfaceMethodWrapper : SmartMethodWrapper + { + internal PrivateInterfaceMethodWrapper(TypeWrapper declaringType, string name, string sig, MethodBase method, TypeWrapper returnType, TypeWrapper[] parameterTypes, Modifiers modifiers, MemberFlags flags) + : base(declaringType, name, sig, method, returnType, parameterTypes, modifiers, flags) + { + } + +#if EMITTERS + protected override void CallImpl(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Call, GetMethod()); + } + + protected override void CallvirtImpl(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Call, GetMethod()); + } +#endif // EMITTERS + } + + abstract class FieldWrapper : MemberWrapper + { +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + private volatile java.lang.reflect.Field reflectionField; + private sun.reflect.FieldAccessor jniAccessor; +#endif + internal static readonly FieldWrapper[] EmptyArray = new FieldWrapper[0]; + private FieldInfo field; + private TypeWrapper fieldType; + + internal FieldWrapper(TypeWrapper declaringType, TypeWrapper fieldType, string name, string sig, Modifiers modifiers, FieldInfo field, MemberFlags flags) + : base(declaringType, name, sig, modifiers, flags) + { + Debug.Assert(name != null); + Debug.Assert(sig != null); + this.fieldType = fieldType; + this.field = field; + UpdateNonPublicTypeInSignatureFlag(); +#if STATIC_COMPILER + if (IsFinal + && DeclaringType.IsPublic + && !DeclaringType.IsInterface + && (IsPublic || (IsProtected && !DeclaringType.IsFinal)) + && !DeclaringType.GetClassLoader().StrictFinalFieldSemantics + && DeclaringType.IsDynamic + && !(this is ConstantFieldWrapper) + && !(this is DynamicPropertyFieldWrapper)) + { + SetType2FinalField(); + } +#endif + } + + internal FieldWrapper(TypeWrapper declaringType, TypeWrapper fieldType, string name, string sig, ExModifiers modifiers, FieldInfo field) + : this(declaringType, fieldType, name, sig, modifiers.Modifiers, field, + (modifiers.IsInternal ? MemberFlags.InternalAccess : MemberFlags.None)) + { + } + + private void UpdateNonPublicTypeInSignatureFlag() + { + if ((IsPublic || IsProtected) && fieldType != null && !IsAccessStub) + { + if (!fieldType.IsPublic && !fieldType.IsUnloadable) + { + SetNonPublicTypeInSignatureFlag(); + } + } + } + + internal FieldInfo GetField() + { + AssertLinked(); + return field; + } + + [Conditional("DEBUG")] + internal void AssertLinked() + { + if(fieldType == null) + { + Tracer.Error(Tracer.Runtime, "AssertLinked failed: " + this.DeclaringType.Name + "::" + this.Name + " (" + this.Signature + ")"); + } + Debug.Assert(fieldType != null, this.DeclaringType.Name + "::" + this.Name + " (" + this.Signature+ ")"); + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal static FieldWrapper FromField(java.lang.reflect.Field field) + { +#if FIRST_PASS + return null; +#else + int slot = field._slot(); + if (slot == -1) + { + // it's a Field created by Unsafe.objectFieldOffset(Class,String) so we must resolve based on the name + foreach (FieldWrapper fw in TypeWrapper.FromClass(field.getDeclaringClass()).GetFields()) + { + if (fw.Name == field.getName()) + { + return fw; + } + } + } + return TypeWrapper.FromClass(field.getDeclaringClass()).GetFields()[slot]; +#endif + } + + internal object ToField(bool copy) + { + return ToField(copy, null); + } + + internal object ToField(bool copy, int? fieldIndex) + { +#if FIRST_PASS + return null; +#else + java.lang.reflect.Field field = reflectionField; + if (field == null) + { + const Modifiers ReflectionFieldModifiersMask = Modifiers.Public | Modifiers.Private | Modifiers.Protected | Modifiers.Static + | Modifiers.Final | Modifiers.Volatile | Modifiers.Transient | Modifiers.Synthetic | Modifiers.Enum; + Link(); + field = new java.lang.reflect.Field( + this.DeclaringType.ClassObject, + this.Name, + this.FieldTypeWrapper.EnsureLoadable(this.DeclaringType.GetClassLoader()).ClassObject, + (int)(this.Modifiers & ReflectionFieldModifiersMask) | (this.IsInternal ? 0x40000000 : 0), + fieldIndex ?? Array.IndexOf(this.DeclaringType.GetFields(), this), + this.DeclaringType.GetGenericFieldSignature(this), + null + ); + } + lock (this) + { + if (reflectionField == null) + { + reflectionField = field; + } + else + { + field = reflectionField; + } + } + if (copy) + { + field = field.copy(); + } + return field; +#endif // FIRST_PASS + } +#endif // !STATIC_COMPILER && !STUB_GENERATOR + + [System.Security.SecurityCritical] + internal static FieldWrapper FromCookie(IntPtr cookie) + { + return (FieldWrapper)FromCookieImpl(cookie); + } + + internal TypeWrapper FieldTypeWrapper + { + get + { + AssertLinked(); + return fieldType; + } + } + +#if EMITTERS + internal void EmitGet(CodeEmitter ilgen) + { + AssertLinked(); + EmitGetImpl(ilgen); + } + + protected abstract void EmitGetImpl(CodeEmitter ilgen); + + internal void EmitSet(CodeEmitter ilgen) + { + AssertLinked(); + EmitSetImpl(ilgen); + } + + protected abstract void EmitSetImpl(CodeEmitter ilgen); +#endif // EMITTERS + + +#if STATIC_COMPILER + internal bool IsLinked + { + get { return fieldType != null; } + } +#endif + + internal void Link() + { + Link(LoadMode.Link); + } + + internal void Link(LoadMode mode) + { + lock(this) + { + if(fieldType != null) + { + return; + } + } + TypeWrapper fld = this.DeclaringType.GetClassLoader().FieldTypeWrapperFromSig(Signature, mode); + lock(this) + { + try + { + // critical code in the finally block to avoid Thread.Abort interrupting the thread + } + finally + { + if(fieldType == null) + { + fieldType = fld; + UpdateNonPublicTypeInSignatureFlag(); + try + { + field = this.DeclaringType.LinkField(this); + } + catch + { + // HACK if linking fails, we unlink to make sure + // that the next link attempt will fail again + fieldType = null; + throw; + } + } + } + } + } + + internal bool IsVolatile + { + get + { + return (Modifiers & Modifiers.Volatile) != 0; + } + } + + internal bool IsSerialVersionUID + { + get + { + // a serialVersionUID field must be static and final to be recognized (see ObjectStreamClass.getDeclaredSUID()) + return (Modifiers & (Modifiers.Static | Modifiers.Final)) == (Modifiers.Static | Modifiers.Final) + && Name == "serialVersionUID" + && (FieldTypeWrapper == PrimitiveTypeWrapper.LONG + || FieldTypeWrapper == PrimitiveTypeWrapper.INT + || FieldTypeWrapper == PrimitiveTypeWrapper.CHAR + || FieldTypeWrapper == PrimitiveTypeWrapper.SHORT + || FieldTypeWrapper == PrimitiveTypeWrapper.BYTE); + } + } + + internal static FieldWrapper Create(TypeWrapper declaringType, TypeWrapper fieldType, FieldInfo fi, string name, string sig, ExModifiers modifiers) + { + // volatile long & double field accesses must be made atomic + if((modifiers.Modifiers & Modifiers.Volatile) != 0 && (sig == "J" || sig == "D")) + { + return new VolatileLongDoubleFieldWrapper(declaringType, fieldType, fi, name, sig, modifiers); + } + return new SimpleFieldWrapper(declaringType, fieldType, fi, name, sig, modifiers); + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal virtual void ResolveField() + { + FieldBuilder fb = field as FieldBuilder; + if(fb != null) + { + field = fb.Module.ResolveField(fb.GetToken().Token); + } + } + + internal object GetFieldAccessorJNI() + { +#if FIRST_PASS + return null; +#else + if (jniAccessor == null) + { + Interlocked.CompareExchange(ref jniAccessor, Java_sun_reflect_ReflectionFactory.NewFieldAccessorJNI(this), null); + } + return jniAccessor; +#endif + } + +#if !FIRST_PASS + internal abstract object GetValue(object obj); + internal abstract void SetValue(object obj, object value); +#endif +#endif // !STATIC_COMPILER && !STUB_GENERATOR + } + + sealed class SimpleFieldWrapper : FieldWrapper + { + internal SimpleFieldWrapper(TypeWrapper declaringType, TypeWrapper fieldType, FieldInfo fi, string name, string sig, ExModifiers modifiers) + : base(declaringType, fieldType, name, sig, modifiers, fi) + { + Debug.Assert(!(fieldType == PrimitiveTypeWrapper.DOUBLE || fieldType == PrimitiveTypeWrapper.LONG) || !IsVolatile); + } + +#if EMITTERS + protected override void EmitGetImpl(CodeEmitter ilgen) + { + if(!IsStatic && DeclaringType.IsNonPrimitiveValueType) + { + ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD); + } + if(IsVolatile) + { + ilgen.Emit(OpCodes.Volatile); + } + ilgen.Emit(IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld, GetField()); + } + + protected override void EmitSetImpl(CodeEmitter ilgen) + { + FieldInfo fi = GetField(); + if(!IsStatic && DeclaringType.IsNonPrimitiveValueType) + { + CodeEmitterLocal temp = ilgen.DeclareLocal(FieldTypeWrapper.TypeAsSignatureType); + ilgen.Emit(OpCodes.Stloc, temp); + ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD); + ilgen.Emit(OpCodes.Ldloc, temp); + } + if(IsVolatile) + { + ilgen.Emit(OpCodes.Volatile); + } + ilgen.Emit(IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, fi); + if(IsVolatile) + { + ilgen.EmitMemoryBarrier(); + } + } +#endif // EMITTERS + +#if !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + internal override object GetValue(object obj) + { + return GetField().GetValue(obj); + } + + internal override void SetValue(object obj, object value) + { + GetField().SetValue(obj, value); + } +#endif // !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + } + + sealed class VolatileLongDoubleFieldWrapper : FieldWrapper + { + internal VolatileLongDoubleFieldWrapper(TypeWrapper declaringType, TypeWrapper fieldType, FieldInfo fi, string name, string sig, ExModifiers modifiers) + : base(declaringType, fieldType, name, sig, modifiers, fi) + { + Debug.Assert(IsVolatile); + Debug.Assert(sig == "J" || sig == "D"); + } + +#if EMITTERS + protected override void EmitGetImpl(CodeEmitter ilgen) + { + FieldInfo fi = GetField(); + if(fi.IsStatic) + { + ilgen.Emit(OpCodes.Ldsflda, fi); + } + else + { + if(DeclaringType.IsNonPrimitiveValueType) + { + ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD); + } + ilgen.Emit(OpCodes.Ldflda, fi); + } + if(FieldTypeWrapper == PrimitiveTypeWrapper.DOUBLE) + { + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.volatileReadDouble); + } + else + { + Debug.Assert(FieldTypeWrapper == PrimitiveTypeWrapper.LONG); + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.volatileReadLong); + } + } + + protected override void EmitSetImpl(CodeEmitter ilgen) + { + FieldInfo fi = GetField(); + CodeEmitterLocal temp = ilgen.DeclareLocal(FieldTypeWrapper.TypeAsSignatureType); + ilgen.Emit(OpCodes.Stloc, temp); + if(fi.IsStatic) + { + ilgen.Emit(OpCodes.Ldsflda, fi); + } + else + { + if(DeclaringType.IsNonPrimitiveValueType) + { + ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD); + } + ilgen.Emit(OpCodes.Ldflda, fi); + } + ilgen.Emit(OpCodes.Ldloc, temp); + if(FieldTypeWrapper == PrimitiveTypeWrapper.DOUBLE) + { + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.volatileWriteDouble); + } + else + { + Debug.Assert(FieldTypeWrapper == PrimitiveTypeWrapper.LONG); + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.volatileWriteLong); + } + } +#endif // EMITTERS + +#if !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS +#if NO_REF_EMIT + internal static readonly object lockObject = new object(); +#endif + + internal override object GetValue(object obj) + { +#if NO_REF_EMIT + lock (lockObject) + { + return GetField().GetValue(obj); + } +#else + throw new InvalidOperationException(); +#endif + } + + internal override void SetValue(object obj, object value) + { +#if NO_REF_EMIT + lock (lockObject) + { + GetField().SetValue(obj, value); + } +#else + throw new InvalidOperationException(); +#endif + } +#endif // !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + } + +#if !STUB_GENERATOR + // this class represents a .NET property defined in Java with the ikvm.lang.Property annotation + sealed class DynamicPropertyFieldWrapper : FieldWrapper + { + private readonly MethodWrapper getter; + private readonly MethodWrapper setter; + private PropertyBuilder pb; + + private MethodWrapper GetMethod(string name, string sig, bool isstatic) + { + if(name != null) + { + MethodWrapper mw = this.DeclaringType.GetMethodWrapper(name, sig, false); + if(mw != null && mw.IsStatic == isstatic) + { + mw.IsPropertyAccessor = true; + return mw; + } + Tracer.Error(Tracer.Compiler, "Property '{0}' accessor '{1}' not found in class '{2}'", this.Name, name, this.DeclaringType.Name); + } + return null; + } + + internal DynamicPropertyFieldWrapper(TypeWrapper declaringType, ClassFile.Field fld) + : base(declaringType, null, fld.Name, fld.Signature, new ExModifiers(fld.Modifiers, fld.IsInternal), null) + { + getter = GetMethod(fld.PropertyGetter, "()" + fld.Signature, fld.IsStatic); + setter = GetMethod(fld.PropertySetter, "(" + fld.Signature + ")V", fld.IsStatic); + } + +#if !STATIC_COMPILER && !FIRST_PASS + internal override void ResolveField() + { + if (getter != null) + { + getter.ResolveMethod(); + } + if (setter != null) + { + setter.ResolveMethod(); + } + } +#endif + + internal PropertyBuilder GetPropertyBuilder() + { + AssertLinked(); + return pb; + } + + internal void DoLink(TypeBuilder tb) + { + if(getter != null) + { + getter.Link(); + } + if(setter != null) + { + setter.Link(); + } + pb = tb.DefineProperty(this.Name, PropertyAttributes.None, this.FieldTypeWrapper.TypeAsSignatureType, Type.EmptyTypes); + if(getter != null) + { + pb.SetGetMethod((MethodBuilder)getter.GetMethod()); + } + if(setter != null) + { + pb.SetSetMethod((MethodBuilder)setter.GetMethod()); + } +#if STATIC_COMPILER + AttributeHelper.SetModifiers(pb, this.Modifiers, this.IsInternal); +#endif + } + +#if EMITTERS + protected override void EmitGetImpl(CodeEmitter ilgen) + { + if(getter == null) + { + EmitThrowNoSuchMethodErrorForGetter(ilgen, this.FieldTypeWrapper, this); + } + else if(getter.IsStatic) + { + getter.EmitCall(ilgen); + } + else + { + getter.EmitCallvirt(ilgen); + } + } + + internal static void EmitThrowNoSuchMethodErrorForGetter(CodeEmitter ilgen, TypeWrapper type, MemberWrapper member) + { +#if STATIC_COMPILER + StaticCompiler.IssueMessage(Message.EmittedNoSuchMethodError, "", member.DeclaringType.Name + "." + member.Name + member.Signature); +#endif + // HACK the branch around the throw is to keep the verifier happy + CodeEmitterLabel label = ilgen.DefineLabel(); + ilgen.Emit(OpCodes.Ldc_I4_0); + ilgen.EmitBrtrue(label); + ilgen.EmitThrow("java.lang.NoSuchMethodError"); + ilgen.MarkLabel(label); + if (!member.IsStatic) + { + ilgen.Emit(OpCodes.Pop); + } + ilgen.Emit(OpCodes.Ldloc, ilgen.DeclareLocal(type.TypeAsLocalOrStackType)); + } + + protected override void EmitSetImpl(CodeEmitter ilgen) + { + if(setter == null) + { + if(this.IsFinal) + { + ilgen.Emit(OpCodes.Pop); + if(!this.IsStatic) + { + ilgen.Emit(OpCodes.Pop); + } + } + else + { + EmitThrowNoSuchMethodErrorForSetter(ilgen, this); + } + } + else if(setter.IsStatic) + { + setter.EmitCall(ilgen); + } + else + { + setter.EmitCallvirt(ilgen); + } + } + + internal static void EmitThrowNoSuchMethodErrorForSetter(CodeEmitter ilgen, MemberWrapper member) + { +#if STATIC_COMPILER + StaticCompiler.IssueMessage(Message.EmittedNoSuchMethodError, "", member.DeclaringType.Name + "." + member.Name + member.Signature); +#endif + // HACK the branch around the throw is to keep the verifier happy + CodeEmitterLabel label = ilgen.DefineLabel(); + ilgen.Emit(OpCodes.Ldc_I4_0); + ilgen.EmitBrtrue(label); + ilgen.EmitThrow("java.lang.NoSuchMethodError"); + ilgen.MarkLabel(label); + ilgen.Emit(OpCodes.Pop); + if (!member.IsStatic) + { + ilgen.Emit(OpCodes.Pop); + } + } +#endif // EMITTERS + +#if !STATIC_COMPILER && !FIRST_PASS + internal override object GetValue(object obj) + { + if (getter == null) + { + throw new java.lang.NoSuchMethodError(); + } + return getter.Invoke(obj, new object[0]); + } + + internal override void SetValue(object obj, object value) + { + if (setter == null) + { + throw new java.lang.NoSuchMethodError(); + } + setter.Invoke(obj, new object[] { value }); + } +#endif + } +#endif // !STUB_GENERATOR + + // this class represents a .NET property defined in Java with the ikvm.lang.Property annotation + sealed class CompiledPropertyFieldWrapper : FieldWrapper + { + private readonly PropertyInfo property; + + internal CompiledPropertyFieldWrapper(TypeWrapper declaringType, PropertyInfo property, ExModifiers modifiers) + : base(declaringType, ClassLoaderWrapper.GetWrapperFromType(property.PropertyType), property.Name, ClassLoaderWrapper.GetWrapperFromType(property.PropertyType).SigName, modifiers, null) + { + this.property = property; + } + +#if EMITTERS + protected override void EmitGetImpl(CodeEmitter ilgen) + { + MethodInfo getter = property.GetGetMethod(true); + if(getter == null) + { + DynamicPropertyFieldWrapper.EmitThrowNoSuchMethodErrorForGetter(ilgen, this.FieldTypeWrapper, this); + } + else if(getter.IsStatic) + { + ilgen.Emit(OpCodes.Call, getter); + } + else + { + ilgen.Emit(OpCodes.Callvirt, getter); + } + } + + protected override void EmitSetImpl(CodeEmitter ilgen) + { + MethodInfo setter = property.GetSetMethod(true); + if (setter == null) + { + if(this.IsFinal) + { + ilgen.Emit(OpCodes.Pop); + if(!this.IsStatic) + { + ilgen.Emit(OpCodes.Pop); + } + } + else + { + DynamicPropertyFieldWrapper.EmitThrowNoSuchMethodErrorForSetter(ilgen, this); + } + } + else if(setter.IsStatic) + { + ilgen.Emit(OpCodes.Call, setter); + } + else + { + ilgen.Emit(OpCodes.Callvirt, setter); + } + } +#endif // EMITTERS + +#if !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + internal override object GetValue(object obj) + { + MethodInfo getter = property.GetGetMethod(true); + if (getter == null) + { + throw new java.lang.NoSuchMethodError(); + } + return getter.Invoke(obj, new object[0]); + } + + internal override void SetValue(object obj, object value) + { + MethodInfo setter = property.GetSetMethod(true); + if (setter == null) + { + throw new java.lang.NoSuchMethodError(); + } + setter.Invoke(obj, new object[] { value }); + } +#endif + + internal PropertyInfo GetProperty() + { + return property; + } + } + + sealed class ConstantFieldWrapper : FieldWrapper + { + // NOTE this field wrapper can resprent a .NET enum, but in that case "constant" contains the raw constant value (i.e. the boxed underlying primitive value, not a boxed enum) + private object constant; + + internal ConstantFieldWrapper(TypeWrapper declaringType, TypeWrapper fieldType, string name, string sig, Modifiers modifiers, FieldInfo field, object constant, MemberFlags flags) + : base(declaringType, fieldType, name, sig, modifiers, field, flags) + { + Debug.Assert(IsStatic); + Debug.Assert(constant == null || constant.GetType().IsPrimitive || constant is string); + this.constant = constant; + } + +#if EMITTERS + protected override void EmitGetImpl(CodeEmitter ilgen) + { + // Reading a field should trigger the cctor, but since we're inlining the value + // we have to trigger it explicitly + DeclaringType.EmitRunClassConstructor(ilgen); + + // NOTE even though you're not supposed to access a constant static final (the compiler is supposed + // to inline them), we have to support it (because it does happen, e.g. if the field becomes final + // after the referencing class was compiled, or when we're accessing an unsigned primitive .NET field) + object v = GetConstantValue(); + if(v == null) + { + ilgen.Emit(OpCodes.Ldnull); + } + else if(constant is int || + constant is short || + constant is ushort || + constant is byte || + constant is sbyte || + constant is char || + constant is bool) + { + ilgen.EmitLdc_I4(((IConvertible)constant).ToInt32(null)); + } + else if(constant is string) + { + ilgen.Emit(OpCodes.Ldstr, (string)constant); + } + else if(constant is float) + { + ilgen.EmitLdc_R4((float)constant); + } + else if(constant is double) + { + ilgen.EmitLdc_R8((double)constant); + } + else if(constant is long) + { + ilgen.EmitLdc_I8((long)constant); + } + else if(constant is uint) + { + ilgen.EmitLdc_I4(unchecked((int)((IConvertible)constant).ToUInt32(null))); + } + else if(constant is ulong) + { + ilgen.EmitLdc_I8(unchecked((long)(ulong)constant)); + } + else + { + throw new InvalidOperationException(constant.GetType().FullName); + } + } + + protected override void EmitSetImpl(CodeEmitter ilgen) + { + // when constant static final fields are updated, the JIT normally doesn't see that (because the + // constant value is inlined), so we emulate that behavior by emitting a Pop + ilgen.Emit(OpCodes.Pop); + } +#endif // EMITTERS + + internal object GetConstantValue() + { + if(constant == null) + { + FieldInfo field = GetField(); + constant = field.GetRawConstantValue(); + } + return constant; + } + +#if !STUB_GENERATOR && !STATIC_COMPILER && !FIRST_PASS + internal override object GetValue(object obj) + { + FieldInfo field = GetField(); + return FieldTypeWrapper.IsPrimitive || field == null + ? GetConstantValue() + : field.GetValue(null); + } + + internal override void SetValue(object obj, object value) + { + } +#endif + } + + sealed class CompiledAccessStubFieldWrapper : FieldWrapper + { + private readonly MethodInfo getter; + private readonly MethodInfo setter; + + private static Modifiers GetModifiers(PropertyInfo property) + { + // NOTE we only support the subset of modifiers that is expected for "access stub" properties + MethodInfo getter = property.GetGetMethod(true); + Modifiers modifiers = getter.IsPublic ? Modifiers.Public : Modifiers.Protected; + if(!property.CanWrite) + { + modifiers |= Modifiers.Final; + } + if(getter.IsStatic) + { + modifiers |= Modifiers.Static; + } + return modifiers; + } + + // constructor for type 1 access stubs + internal CompiledAccessStubFieldWrapper(TypeWrapper wrapper, PropertyInfo property, TypeWrapper propertyType) + : this(wrapper, property, null, propertyType, GetModifiers(property), MemberFlags.HideFromReflection | MemberFlags.AccessStub) + { + } + + // constructor for type 2 access stubs + internal CompiledAccessStubFieldWrapper(TypeWrapper wrapper, PropertyInfo property, FieldInfo field, TypeWrapper propertyType) + : this(wrapper, property, field, propertyType, AttributeHelper.GetModifiersAttribute(property).Modifiers, MemberFlags.AccessStub) + { + } + + private CompiledAccessStubFieldWrapper(TypeWrapper wrapper, PropertyInfo property, FieldInfo field, TypeWrapper propertyType, Modifiers modifiers, MemberFlags flags) + : base(wrapper, propertyType, property.Name, propertyType.SigName, modifiers, field, flags) + { + this.getter = property.GetGetMethod(true); + this.setter = property.GetSetMethod(true); + } + +#if EMITTERS + protected override void EmitGetImpl(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Call, getter); + } + + protected override void EmitSetImpl(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Call, setter); + } +#endif // EMITTERS + +#if !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + internal override object GetValue(object obj) + { + // we can only be invoked on type 2 access stubs (because type 1 access stubs are HideFromReflection), so we know we have a field + return GetField().GetValue(obj); + } + + internal override void SetValue(object obj, object value) + { + // we can only be invoked on type 2 access stubs (because type 1 access stubs are HideFromReflection), so we know we have a field + GetField().SetValue(obj, value); + } +#endif // !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + } +} diff --git a/runtime/MethodHandleUtil.cs b/runtime/MethodHandleUtil.cs new file mode 100644 index 0000000..f452082 --- /dev/null +++ b/runtime/MethodHandleUtil.cs @@ -0,0 +1,209 @@ +/* + Copyright (C) 2011-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using IKVM.Internal; +#if STATIC_COMPILER +using Type = IKVM.Reflection.Type; +#endif + +static partial class MethodHandleUtil +{ + internal const int MaxArity = 8; + private static readonly Type typeofMHA; + private static readonly Type[] typeofMHV; + private static readonly Type[] typeofMH; + + static MethodHandleUtil() + { +#if STATIC_COMPILER + typeofMHA = StaticCompiler.GetRuntimeType("IKVM.Runtime.MHA`8"); + typeofMHV = new Type[] { + StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV"), + StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`1"), + StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`2"), + StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`3"), + StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`4"), + StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`5"), + StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`6"), + StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`7"), + StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`8"), + }; + typeofMH = new Type[] { + null, + StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`1"), + StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`2"), + StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`3"), + StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`4"), + StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`5"), + StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`6"), + StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`7"), + StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`8"), + StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`9"), + }; +#else + typeofMHA = typeof(IKVM.Runtime.MHA<,,,,,,,>); + typeofMHV = new Type[] { + typeof(IKVM.Runtime.MHV), + typeof(IKVM.Runtime.MHV<>), + typeof(IKVM.Runtime.MHV<,>), + typeof(IKVM.Runtime.MHV<,,>), + typeof(IKVM.Runtime.MHV<,,,>), + typeof(IKVM.Runtime.MHV<,,,,>), + typeof(IKVM.Runtime.MHV<,,,,,>), + typeof(IKVM.Runtime.MHV<,,,,,,>), + typeof(IKVM.Runtime.MHV<,,,,,,,>), + }; + typeofMH = new Type[] { + null, + typeof(IKVM.Runtime.MH<>), + typeof(IKVM.Runtime.MH<,>), + typeof(IKVM.Runtime.MH<,,>), + typeof(IKVM.Runtime.MH<,,,>), + typeof(IKVM.Runtime.MH<,,,,>), + typeof(IKVM.Runtime.MH<,,,,,>), + typeof(IKVM.Runtime.MH<,,,,,,>), + typeof(IKVM.Runtime.MH<,,,,,,,>), + typeof(IKVM.Runtime.MH<,,,,,,,,>), + }; +#endif + } + + internal static bool IsPackedArgsContainer(Type type) + { + return type.IsGenericType + && type.GetGenericTypeDefinition() == typeofMHA; + } + + internal static Type CreateMethodHandleDelegateType(TypeWrapper[] args, TypeWrapper ret) + { + Type[] typeArgs = new Type[args.Length]; + for (int i = 0; i < args.Length; i++) + { + typeArgs[i] = args[i].TypeAsSignatureType; + } + return CreateDelegateType(typeArgs, ret.TypeAsSignatureType); + } + + internal static Type CreateMemberWrapperDelegateType(TypeWrapper[] args, TypeWrapper ret) + { + Type[] typeArgs = new Type[args.Length]; + for (int i = 0; i < args.Length; i++) + { + typeArgs[i] = AsBasicType(args[i]); + } + return CreateDelegateType(typeArgs, AsBasicType(ret)); + } + + private static Type CreateDelegateType(Type[] types, Type retType) + { + if (types.Length == 0 && retType == Types.Void) + { + return typeofMHV[0]; + } + else if (types.Length > MaxArity) + { + int arity = types.Length; + int remainder = (arity - 8) % 7; + int count = (arity - 8) / 7; + if (remainder == 0) + { + remainder = 7; + count--; + } + Type last = typeofMHA.MakeGenericType(SubArray(types, types.Length - 8, 8)); + for (int i = 0; i < count; i++) + { + Type[] temp = SubArray(types, types.Length - 8 - 7 * (i + 1), 8); + temp[7] = last; + last = typeofMHA.MakeGenericType(temp); + } + types = SubArray(types, 0, remainder + 1); + types[remainder] = last; + } + if (retType == Types.Void) + { + return typeofMHV[types.Length].MakeGenericType(types); + } + else + { + types = ArrayUtil.Concat(types, retType); + return typeofMH[types.Length].MakeGenericType(types); + } + } + + private static Type[] SubArray(Type[] inArray, int start, int length) + { + Type[] outArray = new Type[length]; + Array.Copy(inArray, start, outArray, 0, length); + return outArray; + } + + internal static Type AsBasicType(TypeWrapper tw) + { + if (tw == PrimitiveTypeWrapper.BOOLEAN || tw == PrimitiveTypeWrapper.BYTE || tw == PrimitiveTypeWrapper.CHAR || tw == PrimitiveTypeWrapper.SHORT || tw == PrimitiveTypeWrapper.INT) + { + return Types.Int32; + } + else if (tw == PrimitiveTypeWrapper.LONG || tw == PrimitiveTypeWrapper.FLOAT || tw == PrimitiveTypeWrapper.DOUBLE || tw == PrimitiveTypeWrapper.VOID) + { + return tw.TypeAsSignatureType; + } + else + { + return Types.Object; + } + } + + internal static bool HasOnlyBasicTypes(TypeWrapper[] args, TypeWrapper ret) + { + foreach (TypeWrapper tw in args) + { + if (!IsBasicType(tw)) + { + return false; + } + } + return IsBasicType(ret); + } + + private static bool IsBasicType(TypeWrapper tw) + { + return tw == PrimitiveTypeWrapper.INT + || tw == PrimitiveTypeWrapper.LONG + || tw == PrimitiveTypeWrapper.FLOAT + || tw == PrimitiveTypeWrapper.DOUBLE + || tw == PrimitiveTypeWrapper.VOID + || tw == CoreClasses.java.lang.Object.Wrapper; + } + + internal static int SlotCount(TypeWrapper[] parameters) + { + int count = 0; + for (int i = 0; i < parameters.Length; i++) + { + count += parameters[i].IsWidePrimitive ? 2 : 1; + } + return count; + } +} diff --git a/runtime/PassiveWeakDictionary.cs b/runtime/PassiveWeakDictionary.cs new file mode 100644 index 0000000..da90e70 --- /dev/null +++ b/runtime/PassiveWeakDictionary.cs @@ -0,0 +1,257 @@ +/* + Copyright (C) 2008 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace IKVM.Internal +{ + /* + * This is a special purpose dictionary. It only keeps weak references to the keys, + * thereby making them eligable for GC at any time. + * + * However, it does not make any promises about cleaning up the values (hence "passive"). + * This class should only be used if memory consumption and lifetime of the values is of no consequence. + * + * Furthermore, the type also assumes that it needs to continue to work during AppDomain unload, + * meaning that it uses GC.SuppressFinalize() on the WeakReference objects it uses to prevent + * them from being finalized during AppDomain unload. + * As a consequence, if you want to dispose on object of this type prior to AppDomain unload, you *must* + * call Dispose() or you will leak GC handles. After calling Dispose() you should not call any other + * methods. + * + * This class is thread safe and TryGetValue is lock free. + * + */ + sealed class PassiveWeakDictionary + where TKey : class + where TValue : class + { + private volatile Bucket[] table = new Bucket[37]; + private int count; + private FreeNode freeList; + private int freeCount; + + internal void Dispose() + { + Bucket[] table = this.table; + for (int i = 0; i < table.Length; i++) + { + for (Bucket b = table[i]; b != null; b = b.Next) + { + GC.ReRegisterForFinalize(b.WeakRef); + } + } + for (FreeNode b = freeList; b != null; b = b.Next) + { + GC.ReRegisterForFinalize(b.WeakRef); + } + } + + internal void Add(TKey key, TValue value) + { + if (key == null) + throw new ArgumentNullException("key"); + + lock (this) + { + if (count > table.Length) + { + Rehash(); + } + int index = GetHashCode(key) % table.Length; + for (Bucket b = table[index]; b != null; b = b.Next) + { + if (b.Key == key) + { + throw new ArgumentException("Key already exists"); + } + } + table[index] = new Bucket(AllocWeakRef(key), value, table[index]); + count++; + } + } + + private WeakReference AllocWeakRef(TKey key) + { + WeakReference weakRef; + if (freeList != null) + { + weakRef = freeList.WeakRef; + freeList = freeList.Next; + freeCount--; + weakRef.Target = key; + } + else + { + weakRef = new WeakReference(key, true); + GC.SuppressFinalize(weakRef); + } + return weakRef; + } + + private static readonly int[] primes = { + 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169, + 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459, 536870923, 1073741827, 2147483647 }; + + private static int GetPrime(int count) + { + foreach (int p in primes) + { + if (p > count) + return p; + } + return count; + } + + private static int GetHashCode(TKey key) + { + return RuntimeHelpers.GetHashCode(key) & 0x7FFFFFFF; + } + + private void Rehash() + { + count = 0; + for (int i = 0; i < table.Length; i++) + { + for (Bucket b = table[i]; b != null; b = b.Next) + { + if (b.Key != null) + { + count++; + } + } + } + Bucket[] newTable = new Bucket[GetPrime(count * 2)]; + for (int i = 0; i < table.Length; i++) + { + for (Bucket b = table[i]; b != null; b = b.Next) + { + TKey key = b.Key; + if (key != null) + { + int index = GetHashCode(key) % newTable.Length; + WeakReference weakRef = AllocWeakRef(key); + newTable[index] = new Bucket(weakRef, b.Value, newTable[index]); + } + else + { + // don't cache an infinite amount, + // busy loop garbage allocation benchmarking shows that 8K is enough with current gen0 size + if (freeCount < 8192) + { + WeakReference weakRef = b.WeakRef; + b.Clear(); + freeList = new FreeNode(weakRef, freeList); + freeCount++; + } + else + { + GC.ReRegisterForFinalize(b.WeakRef); + b.Clear(); + } + } + } + } + this.table = newTable; + } + + internal bool TryGetValue(TKey key, out TValue value) + { + if (key == null) + throw new ArgumentNullException("key"); + + Bucket[] table = this.table; + int index = GetHashCode(key) % table.Length; + for (Bucket b = table[index]; b != null; b = b.Next) + { + if (b.Key == key) + { + value = b.Value; + return true; + } + } + value = null; + return false; + } + + private sealed class Bucket + { + private volatile WeakReference weakRef; + internal TValue Value; + internal readonly Bucket Next; + + internal Bucket(WeakReference weakRef, TValue value, Bucket next) + { + this.weakRef = weakRef; + this.Value = value; + this.Next = next; + } + + internal WeakReference WeakRef + { + get + { + return weakRef; + } + } + + internal TKey Key + { + get + { + WeakReference weakRef = this.weakRef; + if (weakRef != null) + { + TKey key = (TKey)weakRef.Target; + // this extra null check is to guard against the case where there was a GC and a Rehash and the weak ref was reused for another slot + // between the initial read of weakRef and accessing its Target property + if (this.weakRef != null) + { + return key; + } + } + return null; + } + } + + internal void Clear() + { + weakRef = null; + } + } + + private sealed class FreeNode + { + internal readonly WeakReference WeakRef; + internal readonly FreeNode Next; + + internal FreeNode(WeakReference weakRef, FreeNode next) + { + this.WeakRef = weakRef; + this.Next = next; + } + } + } +} diff --git a/runtime/ReflectUtil.cs b/runtime/ReflectUtil.cs new file mode 100644 index 0000000..2bdf099 --- /dev/null +++ b/runtime/ReflectUtil.cs @@ -0,0 +1,279 @@ +/* + Copyright (C) 2008-2012 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +#if STATIC_COMPILER || STUB_GENERATOR +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace IKVM.Internal +{ + static class ReflectUtil + { +#if !NET_4_0 && !STATIC_COMPILER && !STUB_GENERATOR + private static readonly bool clr_v4 = Environment.Version.Major >= 4; + private static Predicate get_IsDynamic; +#endif + + internal static bool IsSameAssembly(Type type1, Type type2) + { + return type1.Assembly.Equals(type2.Assembly); + } + + internal static bool IsFromAssembly(Type type, Assembly assembly) + { + return type.Assembly.Equals(assembly); + } + + internal static Assembly GetAssembly(Type type) + { + return type.Assembly; + } + + internal static bool IsDynamicAssembly(Assembly asm) + { +#if STATIC_COMPILER || STUB_GENERATOR + return false; +#elif NET_4_0 + return asm.IsDynamic; +#else + if (clr_v4) + { + // on .NET 4.0 dynamic assemblies have a non-AssemblyBuilder derived peer, so we have to call IsDynamic + if (get_IsDynamic == null) + { + get_IsDynamic = (Predicate)Delegate.CreateDelegate(typeof(Predicate), typeof(Assembly).GetMethod("get_IsDynamic")); + } + return get_IsDynamic(asm); + } + return asm is AssemblyBuilder; +#endif + } + + internal static bool IsReflectionOnly(Type type) + { + while (type.HasElementType) + { + type = type.GetElementType(); + } + Assembly asm = type.Assembly; + if (asm != null && asm.ReflectionOnly) + { + return true; + } + if (!type.IsGenericType || type.IsGenericTypeDefinition) + { + return false; + } + // we have a generic type instantiation, it might have ReflectionOnly type arguments + foreach (Type arg in type.GetGenericArguments()) + { + if (IsReflectionOnly(arg)) + { + return true; + } + } + return false; + } + + internal static bool ContainsTypeBuilder(Type type) + { + while (type.HasElementType) + { + type = type.GetElementType(); + } + if (!type.IsGenericType || type.IsGenericTypeDefinition) + { + return type is TypeBuilder; + } + foreach (Type arg in type.GetGenericArguments()) + { + if (ContainsTypeBuilder(arg)) + { + return true; + } + } + return type.GetGenericTypeDefinition() is TypeBuilder; + } + + internal static bool IsVector(Type type) + { +#if STATIC_COMPILER || STUB_GENERATOR + return type.__IsVector; +#else + // there's no API to distinguish an array of rank 1 from a vector, + // so we check if the type name ends in [], which indicates it's a vector + // (non-vectors will have [*] or [,]). + return type.IsArray && type.Name.EndsWith("[]"); +#endif + } + + internal static bool IsDynamicMethod(MethodInfo method) + { + // there's no way to distinguish a baked DynamicMethod from a RuntimeMethodInfo and + // on top of that Mono behaves completely different from .NET + try + { + // on Mono 2.10 the MetadataToken property returns zero instead of throwing InvalidOperationException + return method.MetadataToken == 0; + } + catch (InvalidOperationException) + { + return true; + } + } + + internal static MethodBuilder DefineTypeInitializer(TypeBuilder typeBuilder, ClassLoaderWrapper loader) + { + MethodAttributes attr = MethodAttributes.Static | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName; + if (typeBuilder.IsInterface && loader.WorkaroundInterfacePrivateMethods) + { + // LAMESPEC the ECMA spec says (part. I, sect. 8.5.3.2) that all interface members must be public, so we make + // the class constructor public. + // NOTE it turns out that on .NET 2.0 this isn't necessary anymore (neither Ref.Emit nor the CLR verifier complain about it), + // but the C# compiler still considers interfaces with non-public methods to be invalid, so to keep interop with C# we have + // to keep making the .cctor method public. + attr |= MethodAttributes.Public; + } + else + { + attr |= MethodAttributes.Private; + } + return typeBuilder.DefineMethod(ConstructorInfo.TypeConstructorName, attr, null, Type.EmptyTypes); + } + + internal static bool MatchNameAndPublicKeyToken(AssemblyName name1, AssemblyName name2) + { + return name1.Name.Equals(name2.Name, StringComparison.OrdinalIgnoreCase) + && CompareKeys(name1.GetPublicKeyToken(), name2.GetPublicKeyToken()); + } + + private static bool CompareKeys(byte[] b1, byte[] b2) + { + int len1 = b1 == null ? 0 : b1.Length; + int len2 = b2 == null ? 0 : b2.Length; + if (len1 != len2) + { + return false; + } + for (int i = 0; i < len1; i++) + { + if (b1[i] != b2[i]) + { + return false; + } + } + return true; + } + + internal static bool IsConstructor(MethodBase method) + { + return method.IsSpecialName && method.Name == ConstructorInfo.ConstructorName; + } + + internal static MethodBuilder DefineConstructor(TypeBuilder tb, MethodAttributes attribs, Type[] parameterTypes) + { + return tb.DefineMethod(ConstructorInfo.ConstructorName, attribs | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, null, parameterTypes); + } + + internal static bool CanOwnDynamicMethod(Type type) + { + return type != null + && !type.IsInterface + && !type.HasElementType + && !type.IsGenericTypeDefinition + && !type.IsGenericParameter; + } + + internal static bool MatchParameterInfos(ParameterInfo p1, ParameterInfo p2) + { + if (p1.ParameterType != p2.ParameterType) + { + return false; + } + if (!MatchTypes(p1.GetOptionalCustomModifiers(), p2.GetOptionalCustomModifiers())) + { + return false; + } + if (!MatchTypes(p1.GetRequiredCustomModifiers(), p2.GetRequiredCustomModifiers())) + { + return false; + } + return true; + } + + private static bool MatchTypes(Type[] t1, Type[] t2) + { + if (t1.Length == t2.Length) + { + for (int i = 0; i < t1.Length; i++) + { + if (t1[i] != t2[i]) + { + return false; + } + } + return true; + } + return false; + } + +#if STATIC_COMPILER + internal static Type GetMissingType(Type type) + { + while (type.HasElementType) + { + type = type.GetElementType(); + } + if (type.__IsMissing) + { + return type; + } + else if (type.__ContainsMissingType) + { + if (type.IsGenericType) + { + foreach (Type arg in type.GetGenericArguments()) + { + Type t1 = GetMissingType(arg); + if (t1.__IsMissing) + { + return t1; + } + } + } + throw new NotImplementedException(type.FullName); + } + else + { + return type; + } + } +#endif + } +} diff --git a/runtime/RuntimeHelperTypes.cs b/runtime/RuntimeHelperTypes.cs new file mode 100644 index 0000000..0e17164 --- /dev/null +++ b/runtime/RuntimeHelperTypes.cs @@ -0,0 +1,96 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +#if STATIC_COMPILER +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif +using System.Diagnostics; + +namespace IKVM.Internal +{ + static class RuntimeHelperTypes + { + private static Type classLiteralType; + private static FieldInfo classLiteralField; + + internal static FieldInfo GetClassLiteralField(Type type) + { + Debug.Assert(type != Types.Void); + if (classLiteralType == null) + { +#if STATIC_COMPILER + classLiteralType = JVM.CoreAssembly.GetType("ikvm.internal.ClassLiteral`1"); +#elif !FIRST_PASS + classLiteralType = typeof(ikvm.@internal.ClassLiteral<>); +#endif + } +#if !STATIC_COMPILER + if (!IsTypeBuilder(type)) + { + return classLiteralType.MakeGenericType(type).GetField("Value", BindingFlags.Public | BindingFlags.Static); + } +#endif + if (classLiteralField == null) + { + classLiteralField = classLiteralType.GetField("Value", BindingFlags.Public | BindingFlags.Static); + } + return TypeBuilder.GetField(classLiteralType.MakeGenericType(type), classLiteralField); + } + + private static bool IsTypeBuilder(Type type) + { + return type is TypeBuilder || (type.HasElementType && IsTypeBuilder(type.GetElementType())); + } + +#if STATIC_COMPILER + internal static void Create(CompilerClassLoader ccl) + { + EmitClassLiteral(ccl); + } + + private static void EmitClassLiteral(CompilerClassLoader ccl) + { + TypeBuilder tb = ccl.GetTypeWrapperFactory().ModuleBuilder.DefineType("ikvm.internal.ClassLiteral`1", TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Abstract | TypeAttributes.Class | TypeAttributes.BeforeFieldInit); + GenericTypeParameterBuilder typeParam = tb.DefineGenericParameters("T")[0]; + Type classType = CoreClasses.java.lang.Class.Wrapper.TypeAsSignatureType; + classLiteralField = tb.DefineField("Value", classType, FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.InitOnly); + CodeEmitter ilgen = CodeEmitter.Create(ReflectUtil.DefineTypeInitializer(tb, ccl)); + ilgen.Emit(OpCodes.Ldtoken, typeParam); + ilgen.Emit(OpCodes.Call, Types.Type.GetMethod("GetTypeFromHandle", new Type[] { Types.RuntimeTypeHandle })); + MethodWrapper mw = CoreClasses.java.lang.Class.Wrapper.GetMethodWrapper("", "(Lcli.System.Type;)V", false); + mw.Link(); + mw.EmitNewobj(ilgen); + ilgen.Emit(OpCodes.Stsfld, classLiteralField); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + classLiteralType = tb.CreateType(); + } +#endif + } +} diff --git a/runtime/Serialization.cs b/runtime/Serialization.cs new file mode 100644 index 0000000..024c12d --- /dev/null +++ b/runtime/Serialization.cs @@ -0,0 +1,264 @@ +/* + Copyright (C) 2009-2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Runtime.Serialization; +using System.Security; +using System.Security.Permissions; +#if STATIC_COMPILER +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace IKVM.Internal +{ + // This class deals with .NET serialization. When a class is Java serializable it will attempt to automagically make it .NET serializable. + static class Serialization + { + private static readonly CustomAttributeBuilder serializableAttribute = new CustomAttributeBuilder(JVM.Import(typeof(SerializableAttribute)).GetConstructor(Type.EmptyTypes), new object[0]); + private static readonly CustomAttributeBuilder securityCriticalAttribute = new CustomAttributeBuilder(JVM.Import(typeof(SecurityCriticalAttribute)).GetConstructor(Type.EmptyTypes), new object[0]); + private static readonly TypeWrapper iserializable = ClassLoaderWrapper.GetWrapperFromType(JVM.Import(typeof(ISerializable))); + private static readonly TypeWrapper iobjectreference = ClassLoaderWrapper.GetWrapperFromType(JVM.Import(typeof(IObjectReference))); + private static readonly TypeWrapper externalizable = ClassLoaderWrapper.LoadClassCritical("java.io.Externalizable"); + private static readonly PermissionSet psetSerializationFormatter; + + static Serialization() + { + psetSerializationFormatter = new PermissionSet(PermissionState.None); + psetSerializationFormatter.AddPermission(new SecurityPermission(SecurityPermissionFlag.SerializationFormatter)); + } + + internal static bool IsISerializable(TypeWrapper wrapper) + { + return wrapper == iserializable; + } + + private static bool IsSafeForAutomagicSerialization(TypeWrapper wrapper) + { + if (wrapper.TypeAsBaseType.IsSerializable) + { + return false; + } + if (wrapper.IsSubTypeOf(iserializable)) + { + return false; + } + if (wrapper.IsSubTypeOf(iobjectreference)) + { + return false; + } + if (wrapper.GetMethodWrapper("GetObjectData", "(Lcli.System.Runtime.Serialization.SerializationInfo;Lcli.System.Runtime.Serialization.StreamingContext;)V", false) != null) + { + return false; + } + if (wrapper.GetMethodWrapper("", "(Lcli.System.Runtime.Serialization.SerializationInfo;Lcli.System.Runtime.Serialization.StreamingContext;)V", false) != null) + { + return false; + } + return true; + } + + internal static MethodBuilder AddAutomagicSerialization(DynamicTypeWrapper wrapper, TypeBuilder typeBuilder) + { + MethodBuilder serializationCtor = null; + if ((wrapper.Modifiers & IKVM.Attributes.Modifiers.Enum) != 0) + { + MarkSerializable(typeBuilder); + } + else if (wrapper.IsSubTypeOf(CoreClasses.java.io.Serializable.Wrapper) && IsSafeForAutomagicSerialization(wrapper)) + { + if (wrapper.IsSubTypeOf(externalizable)) + { + MethodWrapper ctor = wrapper.GetMethodWrapper("", "()V", false); + if (ctor != null && ctor.IsPublic) + { + MarkSerializable(typeBuilder); + ctor.Link(); + serializationCtor = AddConstructor(typeBuilder, ctor, null, true); + if (!wrapper.BaseTypeWrapper.IsSubTypeOf(CoreClasses.java.io.Serializable.Wrapper)) + { + AddGetObjectData(typeBuilder); + } + if (wrapper.BaseTypeWrapper.GetMethodWrapper("readResolve", "()Ljava.lang.Object;", true) != null) + { + RemoveReadResolve(typeBuilder); + } + } + } + else if (wrapper.BaseTypeWrapper.IsSubTypeOf(CoreClasses.java.io.Serializable.Wrapper)) + { + MethodBase baseCtor = wrapper.GetBaseSerializationConstructor(); + if (baseCtor != null && (baseCtor.IsFamily || baseCtor.IsFamilyOrAssembly)) + { + MarkSerializable(typeBuilder); + serializationCtor = AddConstructor(typeBuilder, null, baseCtor, false); + AddReadResolve(wrapper, typeBuilder); + } + } + else + { + MethodWrapper baseCtor = wrapper.BaseTypeWrapper.GetMethodWrapper("", "()V", false); + if (baseCtor != null && baseCtor.IsAccessibleFrom(wrapper.BaseTypeWrapper, wrapper, wrapper)) + { + MarkSerializable(typeBuilder); + AddGetObjectData(typeBuilder); +#if STATIC_COMPILER + // because the base type can be a __WorkaroundBaseClass__, we may need to replace the constructor + baseCtor = ((AotTypeWrapper)wrapper).ReplaceMethodWrapper(baseCtor); +#endif + baseCtor.Link(); + serializationCtor = AddConstructor(typeBuilder, baseCtor, null, true); + AddReadResolve(wrapper, typeBuilder); + } + } + } + return serializationCtor; + } + + internal static MethodBuilder AddAutomagicSerializationToWorkaroundBaseClass(TypeBuilder typeBuilderWorkaroundBaseClass, MethodBase baseCtor) + { + if (typeBuilderWorkaroundBaseClass.BaseType.IsSerializable) + { + typeBuilderWorkaroundBaseClass.SetCustomAttribute(serializableAttribute); + if (baseCtor != null && (baseCtor.IsFamily || baseCtor.IsFamilyOrAssembly)) + { + return AddConstructor(typeBuilderWorkaroundBaseClass, null, baseCtor, false); + } + } + return null; + } + + internal static void MarkSerializable(TypeBuilder tb) + { + tb.SetCustomAttribute(serializableAttribute); + } + + internal static void AddGetObjectData(TypeBuilder tb) + { + string name = tb.IsSealed + ? "System.Runtime.Serialization.ISerializable.GetObjectData" + : "GetObjectData"; + MethodAttributes attr = tb.IsSealed + ? MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final + : MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.CheckAccessOnOverride; + tb.AddInterfaceImplementation(JVM.Import(typeof(ISerializable))); + MethodBuilder getObjectData = tb.DefineMethod(name, attr, null, + new Type[] { JVM.Import(typeof(SerializationInfo)), JVM.Import(typeof(StreamingContext)) }); + getObjectData.SetCustomAttribute(securityCriticalAttribute); + AttributeHelper.HideFromJava(getObjectData); + getObjectData.AddDeclarativeSecurity(SecurityAction.Demand, psetSerializationFormatter); + tb.DefineMethodOverride(getObjectData, JVM.Import(typeof(ISerializable)).GetMethod("GetObjectData")); + CodeEmitter ilgen = CodeEmitter.Create(getObjectData); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ldarg_1); + TypeWrapper serializationHelper = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.Serialization"); + MethodWrapper mw = serializationHelper.GetMethodWrapper("writeObject", "(Ljava.lang.Object;Lcli.System.Runtime.Serialization.SerializationInfo;)V", false); + mw.Link(); + mw.EmitCall(ilgen); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + + private static MethodBuilder AddConstructor(TypeBuilder tb, MethodWrapper defaultConstructor, MethodBase serializationConstructor, bool callReadObject) + { + MethodBuilder ctor = ReflectUtil.DefineConstructor(tb, MethodAttributes.Family, new Type[] { JVM.Import(typeof(SerializationInfo)), JVM.Import(typeof(StreamingContext)) }); + AttributeHelper.HideFromJava(ctor); + ctor.AddDeclarativeSecurity(SecurityAction.Demand, psetSerializationFormatter); + CodeEmitter ilgen = CodeEmitter.Create(ctor); + ilgen.Emit(OpCodes.Ldarg_0); + if (defaultConstructor != null) + { + defaultConstructor.EmitCall(ilgen); + } + else + { + ilgen.Emit(OpCodes.Ldarg_1); + ilgen.Emit(OpCodes.Ldarg_2); + ilgen.Emit(OpCodes.Call, serializationConstructor); + } + if (callReadObject) + { + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ldarg_1); + TypeWrapper serializationHelper = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.Serialization"); + MethodWrapper mw = serializationHelper.GetMethodWrapper("readObject", "(Ljava.lang.Object;Lcli.System.Runtime.Serialization.SerializationInfo;)V", false); + mw.Link(); + mw.EmitCall(ilgen); + } + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + return ctor; + } + + private static void AddReadResolve(DynamicTypeWrapper wrapper, TypeBuilder tb) + { + MethodWrapper mw = wrapper.GetMethodWrapper("readResolve", "()Ljava.lang.Object;", false); + if (mw != null && !wrapper.IsSubTypeOf(iobjectreference)) + { + tb.AddInterfaceImplementation(JVM.Import(typeof(IObjectReference))); + MethodBuilder getRealObject = tb.DefineMethod("IObjectReference.GetRealObject", MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final, + Types.Object, new Type[] { JVM.Import(typeof(StreamingContext)) }); + getRealObject.SetCustomAttribute(securityCriticalAttribute); + AttributeHelper.HideFromJava(getRealObject); + tb.DefineMethodOverride(getRealObject, JVM.Import(typeof(IObjectReference)).GetMethod("GetRealObject")); + CodeEmitter ilgen = CodeEmitter.Create(getRealObject); + mw.Link(); + if (!wrapper.IsFinal) + { + // readResolve is only applicable if it exists on the actual type of the object, so if we're a subclass don't call it + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Callvirt, Compiler.getTypeMethod); + ilgen.Emit(OpCodes.Ldtoken, wrapper.TypeAsBaseType); + ilgen.Emit(OpCodes.Call, Compiler.getTypeFromHandleMethod); + CodeEmitterLabel label = ilgen.DefineLabel(); + ilgen.EmitBeq(label); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ret); + ilgen.MarkLabel(label); + } + ilgen.Emit(OpCodes.Ldarg_0); + mw.EmitCall(ilgen); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + } + + private static void RemoveReadResolve(TypeBuilder tb) + { + tb.AddInterfaceImplementation(JVM.Import(typeof(IObjectReference))); + MethodBuilder getRealObject = tb.DefineMethod("IObjectReference.GetRealObject", MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final, + Types.Object, new Type[] { JVM.Import(typeof(StreamingContext)) }); + getRealObject.SetCustomAttribute(securityCriticalAttribute); + AttributeHelper.HideFromJava(getRealObject); + tb.DefineMethodOverride(getRealObject, JVM.Import(typeof(IObjectReference)).GetMethod("GetRealObject")); + CodeEmitter ilgen = CodeEmitter.Create(getRealObject); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + } +} diff --git a/runtime/TypeWrapper.cs b/runtime/TypeWrapper.cs new file mode 100644 index 0000000..1afb52f --- /dev/null +++ b/runtime/TypeWrapper.cs @@ -0,0 +1,5828 @@ +/* + Copyright (C) 2002-2015 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +#if STATIC_COMPILER || STUB_GENERATOR +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif +using System.Diagnostics; +using System.Security; +using System.Security.Permissions; +using IKVM.Attributes; + +namespace IKVM.Internal +{ + static class StringConstants + { + internal static readonly string CLINIT = string.Intern(""); + internal static readonly string INIT = string.Intern(""); + internal static readonly string SIG_VOID = string.Intern("()V"); + internal static readonly string FINALIZE = string.Intern("finalize"); + internal static readonly string CLONE = string.Intern("clone"); + } + + struct ExModifiers + { + internal readonly Modifiers Modifiers; + internal readonly bool IsInternal; + + internal ExModifiers(Modifiers modifiers, bool isInternal) + { + this.Modifiers = modifiers; + this.IsInternal = isInternal; + } + } + + struct MethodParametersEntry + { + internal static readonly MethodParametersEntry[] Malformed = new MethodParametersEntry[0]; + internal string name; + internal ushort flags; + } + + static class AttributeHelper + { +#if STATIC_COMPILER + private static CustomAttributeBuilder ghostInterfaceAttribute; + private static CustomAttributeBuilder deprecatedAttribute; + private static CustomAttributeBuilder editorBrowsableNever; + private static ConstructorInfo implementsAttribute; + private static ConstructorInfo throwsAttribute; + private static ConstructorInfo sourceFileAttribute; + private static ConstructorInfo lineNumberTableAttribute1; + private static ConstructorInfo lineNumberTableAttribute2; + private static ConstructorInfo enclosingMethodAttribute; + private static ConstructorInfo signatureAttribute; + private static ConstructorInfo methodParametersAttribute; + private static ConstructorInfo runtimeVisibleTypeAnnotationsAttribute; + private static ConstructorInfo constantPoolAttribute; + private static CustomAttributeBuilder paramArrayAttribute; + private static ConstructorInfo nonNestedInnerClassAttribute; + private static ConstructorInfo nonNestedOuterClassAttribute; + private static readonly Type typeofModifiers = JVM.LoadType(typeof(Modifiers)); + private static readonly Type typeofSourceFileAttribute = JVM.LoadType(typeof(SourceFileAttribute)); + private static readonly Type typeofLineNumberTableAttribute = JVM.LoadType(typeof(LineNumberTableAttribute)); +#endif // STATIC_COMPILER + private static readonly Type typeofRemappedClassAttribute = JVM.LoadType(typeof(RemappedClassAttribute)); + private static readonly Type typeofRemappedTypeAttribute = JVM.LoadType(typeof(RemappedTypeAttribute)); + private static readonly Type typeofModifiersAttribute = JVM.LoadType(typeof(ModifiersAttribute)); + private static readonly Type typeofRemappedInterfaceMethodAttribute = JVM.LoadType(typeof(RemappedInterfaceMethodAttribute)); + private static readonly Type typeofNameSigAttribute = JVM.LoadType(typeof(NameSigAttribute)); + private static readonly Type typeofJavaModuleAttribute = JVM.LoadType(typeof(JavaModuleAttribute)); + private static readonly Type typeofSignatureAttribute = JVM.LoadType(typeof(SignatureAttribute)); + private static readonly Type typeofInnerClassAttribute = JVM.LoadType(typeof(InnerClassAttribute)); + private static readonly Type typeofImplementsAttribute = JVM.LoadType(typeof(ImplementsAttribute)); + private static readonly Type typeofGhostInterfaceAttribute = JVM.LoadType(typeof(GhostInterfaceAttribute)); + private static readonly Type typeofExceptionIsUnsafeForMappingAttribute = JVM.LoadType(typeof(ExceptionIsUnsafeForMappingAttribute)); + private static readonly Type typeofThrowsAttribute = JVM.LoadType(typeof(ThrowsAttribute)); + private static readonly Type typeofHideFromJavaAttribute = JVM.LoadType(typeof(HideFromJavaAttribute)); + private static readonly Type typeofHideFromJavaFlags = JVM.LoadType(typeof(HideFromJavaFlags)); + private static readonly Type typeofNoPackagePrefixAttribute = JVM.LoadType(typeof(NoPackagePrefixAttribute)); + private static readonly Type typeofAnnotationAttributeAttribute = JVM.LoadType(typeof(AnnotationAttributeAttribute)); + private static readonly Type typeofNonNestedInnerClassAttribute = JVM.LoadType(typeof(NonNestedInnerClassAttribute)); + private static readonly Type typeofNonNestedOuterClassAttribute = JVM.LoadType(typeof(NonNestedOuterClassAttribute)); + private static readonly Type typeofEnclosingMethodAttribute = JVM.LoadType(typeof(EnclosingMethodAttribute)); + private static readonly Type typeofMethodParametersAttribute = JVM.LoadType(typeof(MethodParametersAttribute)); + private static readonly Type typeofRuntimeVisibleTypeAnnotationsAttribute = JVM.LoadType(typeof(RuntimeVisibleTypeAnnotationsAttribute)); + private static readonly Type typeofConstantPoolAttribute = JVM.LoadType(typeof(ConstantPoolAttribute)); + private static readonly CustomAttributeBuilder hideFromJavaAttribute = new CustomAttributeBuilder(typeofHideFromJavaAttribute.GetConstructor(Type.EmptyTypes), new object[0]); + private static readonly CustomAttributeBuilder hideFromReflection = new CustomAttributeBuilder(typeofHideFromJavaAttribute.GetConstructor(new Type[] { typeofHideFromJavaFlags }), new object[] { HideFromJavaFlags.Reflection | HideFromJavaFlags.StackTrace | HideFromJavaFlags.StackWalk }); + + // we don't want beforefieldinit + static AttributeHelper() { } + +#if STATIC_COMPILER + private static object ParseValue(ClassLoaderWrapper loader, TypeWrapper tw, string val) + { + if(tw == CoreClasses.java.lang.String.Wrapper) + { + return val; + } + else if(tw.IsUnloadable) + { + throw new FatalCompilerErrorException(Message.MapFileTypeNotFound, tw.Name); + } + else if(tw.TypeAsTBD.IsEnum) + { + return EnumHelper.Parse(tw.TypeAsTBD, val); + } + else if(tw.TypeAsTBD == Types.Type) + { + TypeWrapper valtw = loader.LoadClassByDottedNameFast(val); + if(valtw != null) + { + return valtw.TypeAsBaseType; + } + return StaticCompiler.Universe.GetType(val, true); + } + else if(tw == PrimitiveTypeWrapper.BOOLEAN) + { + return bool.Parse(val); + } + else if(tw == PrimitiveTypeWrapper.BYTE) + { + return (byte)sbyte.Parse(val); + } + else if(tw == PrimitiveTypeWrapper.CHAR) + { + return char.Parse(val); + } + else if(tw == PrimitiveTypeWrapper.SHORT) + { + return short.Parse(val); + } + else if(tw == PrimitiveTypeWrapper.INT) + { + return int.Parse(val); + } + else if(tw == PrimitiveTypeWrapper.FLOAT) + { + return float.Parse(val); + } + else if(tw == PrimitiveTypeWrapper.LONG) + { + return long.Parse(val); + } + else if(tw == PrimitiveTypeWrapper.DOUBLE) + { + return double.Parse(val); + } + else + { + throw new NotImplementedException(); + } + } + + internal static void SetCustomAttribute(ClassLoaderWrapper loader, TypeBuilder tb, IKVM.Internal.MapXml.Attribute attr) + { + bool declarativeSecurity; + CustomAttributeBuilder cab = CreateCustomAttribute(loader, attr, out declarativeSecurity); + if (declarativeSecurity) + { + tb.__AddDeclarativeSecurity(cab); + } + else + { + tb.SetCustomAttribute(cab); + } + } + + internal static void SetCustomAttribute(ClassLoaderWrapper loader, FieldBuilder fb, IKVM.Internal.MapXml.Attribute attr) + { + fb.SetCustomAttribute(CreateCustomAttribute(loader, attr)); + } + + internal static void SetCustomAttribute(ClassLoaderWrapper loader, ParameterBuilder pb, IKVM.Internal.MapXml.Attribute attr) + { + pb.SetCustomAttribute(CreateCustomAttribute(loader, attr)); + } + + internal static void SetCustomAttribute(ClassLoaderWrapper loader, MethodBuilder mb, IKVM.Internal.MapXml.Attribute attr) + { + bool declarativeSecurity; + CustomAttributeBuilder cab = CreateCustomAttribute(loader, attr, out declarativeSecurity); + if (declarativeSecurity) + { + mb.__AddDeclarativeSecurity(cab); + } + else + { + mb.SetCustomAttribute(CreateCustomAttribute(loader, attr)); + } + } + + internal static void SetCustomAttribute(ClassLoaderWrapper loader, PropertyBuilder pb, IKVM.Internal.MapXml.Attribute attr) + { + pb.SetCustomAttribute(CreateCustomAttribute(loader, attr)); + } + + internal static void SetCustomAttribute(ClassLoaderWrapper loader, AssemblyBuilder ab, IKVM.Internal.MapXml.Attribute attr) + { + ab.SetCustomAttribute(CreateCustomAttribute(loader, attr)); + } + + private static void GetAttributeArgsAndTypes(ClassLoaderWrapper loader, IKVM.Internal.MapXml.Attribute attr, out Type[] argTypes, out object[] args) + { + // TODO add error handling + TypeWrapper[] twargs = loader.ArgTypeWrapperListFromSig(attr.Sig, LoadMode.Link); + argTypes = new Type[twargs.Length]; + args = new object[argTypes.Length]; + for(int i = 0; i < twargs.Length; i++) + { + argTypes[i] = twargs[i].TypeAsSignatureType; + TypeWrapper tw = twargs[i]; + if(tw == CoreClasses.java.lang.Object.Wrapper) + { + tw = loader.FieldTypeWrapperFromSig(attr.Params[i].Sig, LoadMode.Link); + } + if(tw.IsArray) + { + Array arr = Array.CreateInstance(Type.__GetSystemType(Type.GetTypeCode(tw.ElementTypeWrapper.TypeAsArrayType)), attr.Params[i].Elements.Length); + for(int j = 0; j < arr.Length; j++) + { + arr.SetValue(ParseValue(loader, tw.ElementTypeWrapper, attr.Params[i].Elements[j].Value), j); + } + args[i] = arr; + } + else + { + args[i] = ParseValue(loader, tw, attr.Params[i].Value); + } + } + } + + private static CustomAttributeBuilder CreateCustomAttribute(ClassLoaderWrapper loader, IKVM.Internal.MapXml.Attribute attr) + { + bool ignore; + return CreateCustomAttribute(loader, attr, out ignore); + } + + private static CustomAttributeBuilder CreateCustomAttribute(ClassLoaderWrapper loader, IKVM.Internal.MapXml.Attribute attr, out bool isDeclarativeSecurity) + { + // TODO add error handling + Type[] argTypes; + object[] args; + GetAttributeArgsAndTypes(loader, attr, out argTypes, out args); + if(attr.Type != null) + { + Type t = StaticCompiler.GetTypeForMapXml(loader, attr.Type); + isDeclarativeSecurity = t.IsSubclassOf(Types.SecurityAttribute); + ConstructorInfo ci = t.GetConstructor(argTypes); + if(ci == null) + { + throw new InvalidOperationException(string.Format("Constructor missing: {0}::{1}", attr.Type, attr.Sig)); + } + PropertyInfo[] namedProperties; + object[] propertyValues; + if(attr.Properties != null) + { + namedProperties = new PropertyInfo[attr.Properties.Length]; + propertyValues = new object[attr.Properties.Length]; + for(int i = 0; i < namedProperties.Length; i++) + { + namedProperties[i] = t.GetProperty(attr.Properties[i].Name); + propertyValues[i] = ParseValue(loader, loader.FieldTypeWrapperFromSig(attr.Properties[i].Sig, LoadMode.Link), attr.Properties[i].Value); + } + } + else + { + namedProperties = new PropertyInfo[0]; + propertyValues = new object[0]; + } + FieldInfo[] namedFields; + object[] fieldValues; + if(attr.Fields != null) + { + namedFields = new FieldInfo[attr.Fields.Length]; + fieldValues = new object[attr.Fields.Length]; + for(int i = 0; i < namedFields.Length; i++) + { + namedFields[i] = t.GetField(attr.Fields[i].Name); + fieldValues[i] = ParseValue(loader, loader.FieldTypeWrapperFromSig(attr.Fields[i].Sig, LoadMode.Link), attr.Fields[i].Value); + } + } + else + { + namedFields = new FieldInfo[0]; + fieldValues = new object[0]; + } + return new CustomAttributeBuilder(ci, args, namedProperties, propertyValues, namedFields, fieldValues); + } + else + { + if(attr.Properties != null) + { + throw new NotImplementedException("Setting property values on Java attributes is not implemented"); + } + TypeWrapper t = loader.LoadClassByDottedName(attr.Class); + isDeclarativeSecurity = t.TypeAsBaseType.IsSubclassOf(Types.SecurityAttribute); + FieldInfo[] namedFields; + object[] fieldValues; + if(attr.Fields != null) + { + namedFields = new FieldInfo[attr.Fields.Length]; + fieldValues = new object[attr.Fields.Length]; + for(int i = 0; i < namedFields.Length; i++) + { + FieldWrapper fw = t.GetFieldWrapper(attr.Fields[i].Name, attr.Fields[i].Sig); + fw.Link(); + namedFields[i] = fw.GetField(); + fieldValues[i] = ParseValue(loader, loader.FieldTypeWrapperFromSig(attr.Fields[i].Sig, LoadMode.Link), attr.Fields[i].Value); + } + } + else + { + namedFields = new FieldInfo[0]; + fieldValues = new object[0]; + } + MethodWrapper mw = t.GetMethodWrapper("", attr.Sig, false); + if (mw == null) + { + throw new InvalidOperationException(string.Format("Constructor missing: {0}::{1}", attr.Class, attr.Sig)); + } + mw.Link(); + ConstructorInfo ci = (mw.GetMethod() as ConstructorInfo) ?? ((MethodInfo)mw.GetMethod()).__AsConstructorInfo(); + return new CustomAttributeBuilder(ci, args, namedFields, fieldValues); + } + } + + private static CustomAttributeBuilder GetEditorBrowsableNever() + { + if (editorBrowsableNever == null) + { + // to avoid having to load (and find) System.dll, we construct a symbolic CustomAttributeBuilder + AssemblyName name = Types.Object.Assembly.GetName(); + name.Name = "System"; + Universe u = StaticCompiler.Universe; + Type typeofEditorBrowsableAttribute = u.ResolveType(Types.Object.Assembly, "System.ComponentModel.EditorBrowsableAttribute, " + name.FullName); + Type typeofEditorBrowsableState = u.ResolveType(Types.Object.Assembly, "System.ComponentModel.EditorBrowsableState, " + name.FullName); + u.MissingTypeIsValueType += delegate(Type type) { return type == typeofEditorBrowsableState; }; + ConstructorInfo ctor = (ConstructorInfo)typeofEditorBrowsableAttribute.__CreateMissingMethod(ConstructorInfo.ConstructorName, + CallingConventions.Standard | CallingConventions.HasThis, null, default(CustomModifiers), new Type[] { typeofEditorBrowsableState }, null); + editorBrowsableNever = CustomAttributeBuilder.__FromBlob(ctor, new byte[] { 01, 00, 01, 00, 00, 00, 00, 00 }); + } + return editorBrowsableNever; + } + + internal static void SetEditorBrowsableNever(TypeBuilder tb) + { + tb.SetCustomAttribute(GetEditorBrowsableNever()); + } + + internal static void SetEditorBrowsableNever(MethodBuilder mb) + { + mb.SetCustomAttribute(GetEditorBrowsableNever()); + } + + internal static void SetEditorBrowsableNever(PropertyBuilder pb) + { + pb.SetCustomAttribute(GetEditorBrowsableNever()); + } + + internal static void SetDeprecatedAttribute(MethodBuilder mb) + { + if(deprecatedAttribute == null) + { + deprecatedAttribute = new CustomAttributeBuilder(JVM.Import(typeof(ObsoleteAttribute)).GetConstructor(Type.EmptyTypes), new object[0]); + } + mb.SetCustomAttribute(deprecatedAttribute); + } + + internal static void SetDeprecatedAttribute(TypeBuilder tb) + { + if(deprecatedAttribute == null) + { + deprecatedAttribute = new CustomAttributeBuilder(JVM.Import(typeof(ObsoleteAttribute)).GetConstructor(Type.EmptyTypes), new object[0]); + } + tb.SetCustomAttribute(deprecatedAttribute); + } + + internal static void SetDeprecatedAttribute(FieldBuilder fb) + { + if(deprecatedAttribute == null) + { + deprecatedAttribute = new CustomAttributeBuilder(JVM.Import(typeof(ObsoleteAttribute)).GetConstructor(Type.EmptyTypes), new object[0]); + } + fb.SetCustomAttribute(deprecatedAttribute); + } + + internal static void SetDeprecatedAttribute(PropertyBuilder pb) + { + if(deprecatedAttribute == null) + { + deprecatedAttribute = new CustomAttributeBuilder(JVM.Import(typeof(ObsoleteAttribute)).GetConstructor(Type.EmptyTypes), new object[0]); + } + pb.SetCustomAttribute(deprecatedAttribute); + } + + internal static void SetThrowsAttribute(MethodBuilder mb, string[] exceptions) + { + if(exceptions != null && exceptions.Length != 0) + { + if(throwsAttribute == null) + { + throwsAttribute = typeofThrowsAttribute.GetConstructor(new Type[] { JVM.Import(typeof(string[])) }); + } + exceptions = UnicodeUtil.EscapeInvalidSurrogates(exceptions); + mb.SetCustomAttribute(new CustomAttributeBuilder(throwsAttribute, new object[] { exceptions })); + } + } + + internal static void SetGhostInterface(TypeBuilder typeBuilder) + { + if(ghostInterfaceAttribute == null) + { + ghostInterfaceAttribute = new CustomAttributeBuilder(typeofGhostInterfaceAttribute.GetConstructor(Type.EmptyTypes), new object[0]); + } + typeBuilder.SetCustomAttribute(ghostInterfaceAttribute); + } + + internal static void SetNonNestedInnerClass(TypeBuilder typeBuilder, string className) + { + if(nonNestedInnerClassAttribute == null) + { + nonNestedInnerClassAttribute = typeofNonNestedInnerClassAttribute.GetConstructor(new Type[] { Types.String }); + } + typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(nonNestedInnerClassAttribute, + new object[] { UnicodeUtil.EscapeInvalidSurrogates(className) })); + } + + internal static void SetNonNestedOuterClass(TypeBuilder typeBuilder, string className) + { + if(nonNestedOuterClassAttribute == null) + { + nonNestedOuterClassAttribute = typeofNonNestedOuterClassAttribute.GetConstructor(new Type[] { Types.String }); + } + typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(nonNestedOuterClassAttribute, + new object[] { UnicodeUtil.EscapeInvalidSurrogates(className) })); + } +#endif // STATIC_COMPILER + + internal static void HideFromReflection(MethodBuilder mb) + { + mb.SetCustomAttribute(hideFromReflection); + } + + internal static void HideFromReflection(FieldBuilder fb) + { + fb.SetCustomAttribute(hideFromReflection); + } + + internal static void HideFromReflection(PropertyBuilder pb) + { + pb.SetCustomAttribute(hideFromReflection); + } + + internal static void HideFromJava(TypeBuilder typeBuilder) + { + typeBuilder.SetCustomAttribute(hideFromJavaAttribute); + } + + internal static void HideFromJava(MethodBuilder mb) + { + mb.SetCustomAttribute(hideFromJavaAttribute); + } + + internal static void HideFromJava(MethodBuilder mb, HideFromJavaFlags flags) + { + CustomAttributeBuilder cab = new CustomAttributeBuilder(typeofHideFromJavaAttribute.GetConstructor(new Type[] { typeofHideFromJavaFlags }), new object[] { flags }); + mb.SetCustomAttribute(cab); + } + + internal static void HideFromJava(FieldBuilder fb) + { + fb.SetCustomAttribute(hideFromJavaAttribute); + } + +#if STATIC_COMPILER + internal static void HideFromJava(PropertyBuilder pb) + { + pb.SetCustomAttribute(hideFromJavaAttribute); + } +#endif // STATIC_COMPILER + + internal static bool IsHideFromJava(Type type) + { + return type.IsDefined(typeofHideFromJavaAttribute, false) + || (type.IsNested && (type.DeclaringType.IsDefined(typeofHideFromJavaAttribute, false) || type.Name.StartsWith("__<", StringComparison.Ordinal))); + } + + internal static bool IsHideFromJava(MemberInfo mi) + { + return (GetHideFromJavaFlags(mi) & HideFromJavaFlags.Code) != 0; + } + + internal static HideFromJavaFlags GetHideFromJavaFlags(MemberInfo mi) + { + // NOTE all privatescope fields and methods are "hideFromJava" + // because Java cannot deal with the potential name clashes + FieldInfo fi = mi as FieldInfo; + if(fi != null && (fi.Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.PrivateScope) + { + return HideFromJavaFlags.All; + } + MethodBase mb = mi as MethodBase; + if(mb != null && (mb.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope) + { + return HideFromJavaFlags.All; + } + if (mi.Name.StartsWith("__<", StringComparison.Ordinal)) + { + return HideFromJavaFlags.All; + } +#if !STATIC_COMPILER && !STUB_GENERATOR + object[] attr = mi.GetCustomAttributes(typeofHideFromJavaAttribute, false); + if (attr.Length == 1) + { + return ((HideFromJavaAttribute)attr[0]).Flags; + } +#else + IList attr = CustomAttributeData.__GetCustomAttributes(mi, typeofHideFromJavaAttribute, false); + if(attr.Count == 1) + { + IList args = attr[0].ConstructorArguments; + if(args.Count == 1) + { + return (HideFromJavaFlags)args[0].Value; + } + return HideFromJavaFlags.All; + } +#endif + return HideFromJavaFlags.None; + } + +#if STATIC_COMPILER + internal static void SetImplementsAttribute(TypeBuilder typeBuilder, TypeWrapper[] ifaceWrappers) + { + string[] interfaces = new string[ifaceWrappers.Length]; + for(int i = 0; i < interfaces.Length; i++) + { + interfaces[i] = UnicodeUtil.EscapeInvalidSurrogates(ifaceWrappers[i].Name); + } + if(implementsAttribute == null) + { + implementsAttribute = typeofImplementsAttribute.GetConstructor(new Type[] { JVM.Import(typeof(string[])) }); + } + typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(implementsAttribute, new object[] { interfaces })); + } +#endif + + internal static bool IsGhostInterface(Type type) + { + return type.IsDefined(typeofGhostInterfaceAttribute, false); + } + + internal static bool IsRemappedType(Type type) + { + return type.IsDefined(typeofRemappedTypeAttribute, false); + } + + internal static bool IsExceptionIsUnsafeForMapping(Type type) + { + return type.IsDefined(typeofExceptionIsUnsafeForMappingAttribute, false); + } + + internal static ModifiersAttribute GetModifiersAttribute(MemberInfo member) + { +#if !STATIC_COMPILER && !STUB_GENERATOR + object[] attr = member.GetCustomAttributes(typeof(ModifiersAttribute), false); + return attr.Length == 1 ? (ModifiersAttribute)attr[0] : null; +#else + IList attr = CustomAttributeData.__GetCustomAttributes(member, typeofModifiersAttribute, false); + if(attr.Count == 1) + { + IList args = attr[0].ConstructorArguments; + if(args.Count == 2) + { + return new ModifiersAttribute((Modifiers)args[0].Value, (bool)args[1].Value); + } + return new ModifiersAttribute((Modifiers)args[0].Value); + } + return null; +#endif + } + + internal static ExModifiers GetModifiers(MethodBase mb, bool assemblyIsPrivate) + { + ModifiersAttribute attr = GetModifiersAttribute(mb); + if(attr != null) + { + return new ExModifiers(attr.Modifiers, attr.IsInternal); + } + Modifiers modifiers = 0; + if(mb.IsPublic) + { + modifiers |= Modifiers.Public; + } + else if(mb.IsPrivate) + { + modifiers |= Modifiers.Private; + } + else if(mb.IsFamily || mb.IsFamilyOrAssembly) + { + modifiers |= Modifiers.Protected; + } + else if(assemblyIsPrivate) + { + modifiers |= Modifiers.Private; + } + // NOTE Java doesn't support non-virtual methods, but we set the Final modifier for + // non-virtual methods to approximate the semantics + if((mb.IsFinal || (!mb.IsVirtual && ((modifiers & Modifiers.Private) == 0))) && !mb.IsStatic && !mb.IsConstructor) + { + modifiers |= Modifiers.Final; + } + if(mb.IsAbstract) + { + modifiers |= Modifiers.Abstract; + } + else + { + // Some .NET interfaces (like System._AppDomain) have synchronized methods, + // Java doesn't allow synchronized on an abstract methods, so we ignore it for + // abstract methods. + if((mb.GetMethodImplementationFlags() & MethodImplAttributes.Synchronized) != 0) + { + modifiers |= Modifiers.Synchronized; + } + } + if(mb.IsStatic) + { + modifiers |= Modifiers.Static; + } + if((mb.Attributes & MethodAttributes.PinvokeImpl) != 0) + { + modifiers |= Modifiers.Native; + } + ParameterInfo[] parameters = mb.GetParameters(); + if(parameters.Length > 0 && parameters[parameters.Length - 1].IsDefined(JVM.Import(typeof(ParamArrayAttribute)), false)) + { + modifiers |= Modifiers.VarArgs; + } + return new ExModifiers(modifiers, false); + } + + internal static ExModifiers GetModifiers(FieldInfo fi, bool assemblyIsPrivate) + { + ModifiersAttribute attr = GetModifiersAttribute(fi); + if(attr != null) + { + return new ExModifiers(attr.Modifiers, attr.IsInternal); + } + Modifiers modifiers = 0; + if(fi.IsPublic) + { + modifiers |= Modifiers.Public; + } + else if(fi.IsPrivate) + { + modifiers |= Modifiers.Private; + } + else if(fi.IsFamily || fi.IsFamilyOrAssembly) + { + modifiers |= Modifiers.Protected; + } + else if(assemblyIsPrivate) + { + modifiers |= Modifiers.Private; + } + if(fi.IsInitOnly || fi.IsLiteral) + { + modifiers |= Modifiers.Final; + } + if(fi.IsNotSerialized) + { + modifiers |= Modifiers.Transient; + } + if(fi.IsStatic) + { + modifiers |= Modifiers.Static; + } + if(Array.IndexOf(fi.GetRequiredCustomModifiers(), Types.IsVolatile) != -1) + { + modifiers |= Modifiers.Volatile; + } + return new ExModifiers(modifiers, false); + } + +#if STATIC_COMPILER + internal static void SetModifiers(MethodBuilder mb, Modifiers modifiers, bool isInternal) + { + CustomAttributeBuilder customAttributeBuilder; + if (isInternal) + { + customAttributeBuilder = new CustomAttributeBuilder(typeofModifiersAttribute.GetConstructor(new Type[] { typeofModifiers, Types.Boolean }), new object[] { modifiers, isInternal }); + } + else + { + customAttributeBuilder = new CustomAttributeBuilder(typeofModifiersAttribute.GetConstructor(new Type[] { typeofModifiers }), new object[] { modifiers }); + } + mb.SetCustomAttribute(customAttributeBuilder); + } + + internal static void SetModifiers(FieldBuilder fb, Modifiers modifiers, bool isInternal) + { + CustomAttributeBuilder customAttributeBuilder; + if (isInternal) + { + customAttributeBuilder = new CustomAttributeBuilder(typeofModifiersAttribute.GetConstructor(new Type[] { typeofModifiers, Types.Boolean }), new object[] { modifiers, isInternal }); + } + else + { + customAttributeBuilder = new CustomAttributeBuilder(typeofModifiersAttribute.GetConstructor(new Type[] { typeofModifiers }), new object[] { modifiers }); + } + fb.SetCustomAttribute(customAttributeBuilder); + } + + internal static void SetModifiers(PropertyBuilder pb, Modifiers modifiers, bool isInternal) + { + CustomAttributeBuilder customAttributeBuilder; + if (isInternal) + { + customAttributeBuilder = new CustomAttributeBuilder(typeofModifiersAttribute.GetConstructor(new Type[] { typeofModifiers, Types.Boolean }), new object[] { modifiers, isInternal }); + } + else + { + customAttributeBuilder = new CustomAttributeBuilder(typeofModifiersAttribute.GetConstructor(new Type[] { typeofModifiers }), new object[] { modifiers }); + } + pb.SetCustomAttribute(customAttributeBuilder); + } + + internal static void SetModifiers(TypeBuilder tb, Modifiers modifiers, bool isInternal) + { + CustomAttributeBuilder customAttributeBuilder; + if (isInternal) + { + customAttributeBuilder = new CustomAttributeBuilder(typeofModifiersAttribute.GetConstructor(new Type[] { typeofModifiers, Types.Boolean }), new object[] { modifiers, isInternal }); + } + else + { + customAttributeBuilder = new CustomAttributeBuilder(typeofModifiersAttribute.GetConstructor(new Type[] { typeofModifiers }), new object[] { modifiers }); + } + tb.SetCustomAttribute(customAttributeBuilder); + } + + internal static void SetNameSig(MethodBuilder mb, string name, string sig) + { + CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder(typeofNameSigAttribute.GetConstructor(new Type[] { Types.String, Types.String }), + new object[] { UnicodeUtil.EscapeInvalidSurrogates(name), UnicodeUtil.EscapeInvalidSurrogates(sig) }); + mb.SetCustomAttribute(customAttributeBuilder); + } + + internal static void SetInnerClass(TypeBuilder typeBuilder, string innerClass, Modifiers modifiers) + { + Type[] argTypes = new Type[] { Types.String, typeofModifiers }; + object[] args = new object[] { UnicodeUtil.EscapeInvalidSurrogates(innerClass), modifiers }; + ConstructorInfo ci = typeofInnerClassAttribute.GetConstructor(argTypes); + CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder(ci, args); + typeBuilder.SetCustomAttribute(customAttributeBuilder); + } + + internal static void SetSourceFile(TypeBuilder typeBuilder, string filename) + { + if(sourceFileAttribute == null) + { + sourceFileAttribute = typeofSourceFileAttribute.GetConstructor(new Type[] { Types.String }); + } + typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(sourceFileAttribute, new object[] { filename })); + } + + internal static void SetSourceFile(ModuleBuilder moduleBuilder, string filename) + { + if(sourceFileAttribute == null) + { + sourceFileAttribute = typeofSourceFileAttribute.GetConstructor(new Type[] { Types.String }); + } + moduleBuilder.SetCustomAttribute(new CustomAttributeBuilder(sourceFileAttribute, new object[] { filename })); + } + + internal static void SetLineNumberTable(MethodBuilder mb, IKVM.Attributes.LineNumberTableAttribute.LineNumberWriter writer) + { + object arg; + ConstructorInfo con; + if(writer.Count == 1) + { + if(lineNumberTableAttribute2 == null) + { + lineNumberTableAttribute2 = typeofLineNumberTableAttribute.GetConstructor(new Type[] { Types.UInt16 }); + } + con = lineNumberTableAttribute2; + arg = (ushort)writer.LineNo; + } + else + { + if(lineNumberTableAttribute1 == null) + { + lineNumberTableAttribute1 = typeofLineNumberTableAttribute.GetConstructor(new Type[] { JVM.Import(typeof(byte[])) }); + } + con = lineNumberTableAttribute1; + arg = writer.ToArray(); + } + mb.SetCustomAttribute(new CustomAttributeBuilder(con, new object[] { arg })); + } + + internal static void SetEnclosingMethodAttribute(TypeBuilder tb, string className, string methodName, string methodSig) + { + if(enclosingMethodAttribute == null) + { + enclosingMethodAttribute = typeofEnclosingMethodAttribute.GetConstructor(new Type[] { Types.String, Types.String, Types.String }); + } + tb.SetCustomAttribute(new CustomAttributeBuilder(enclosingMethodAttribute, + new object[] { UnicodeUtil.EscapeInvalidSurrogates(className), UnicodeUtil.EscapeInvalidSurrogates(methodName), UnicodeUtil.EscapeInvalidSurrogates(methodSig) })); + } + + internal static void SetSignatureAttribute(TypeBuilder tb, string signature) + { + if(signatureAttribute == null) + { + signatureAttribute = typeofSignatureAttribute.GetConstructor(new Type[] { Types.String }); + } + tb.SetCustomAttribute(new CustomAttributeBuilder(signatureAttribute, + new object[] { UnicodeUtil.EscapeInvalidSurrogates(signature) })); + } + + internal static void SetSignatureAttribute(FieldBuilder fb, string signature) + { + if(signatureAttribute == null) + { + signatureAttribute = typeofSignatureAttribute.GetConstructor(new Type[] { Types.String }); + } + fb.SetCustomAttribute(new CustomAttributeBuilder(signatureAttribute, + new object[] { UnicodeUtil.EscapeInvalidSurrogates(signature) })); + } + + internal static void SetSignatureAttribute(MethodBuilder mb, string signature) + { + if(signatureAttribute == null) + { + signatureAttribute = typeofSignatureAttribute.GetConstructor(new Type[] { Types.String }); + } + mb.SetCustomAttribute(new CustomAttributeBuilder(signatureAttribute, + new object[] { UnicodeUtil.EscapeInvalidSurrogates(signature) })); + } + + internal static void SetMethodParametersAttribute(MethodBuilder mb, Modifiers[] modifiers) + { + if(methodParametersAttribute == null) + { + methodParametersAttribute = typeofMethodParametersAttribute.GetConstructor(new Type[] { typeofModifiers.MakeArrayType() }); + } + mb.SetCustomAttribute(new CustomAttributeBuilder(methodParametersAttribute, new object[] { modifiers })); + } + + internal static void SetRuntimeVisibleTypeAnnotationsAttribute(TypeBuilder tb, byte[] data) + { + if(runtimeVisibleTypeAnnotationsAttribute == null) + { + runtimeVisibleTypeAnnotationsAttribute = typeofRuntimeVisibleTypeAnnotationsAttribute.GetConstructor(new Type[] { Types.Byte.MakeArrayType() }); + } + tb.SetCustomAttribute(new CustomAttributeBuilder(runtimeVisibleTypeAnnotationsAttribute, new object[] { data })); + } + + internal static void SetRuntimeVisibleTypeAnnotationsAttribute(FieldBuilder fb, byte[] data) + { + if(runtimeVisibleTypeAnnotationsAttribute == null) + { + runtimeVisibleTypeAnnotationsAttribute = typeofRuntimeVisibleTypeAnnotationsAttribute.GetConstructor(new Type[] { Types.Byte.MakeArrayType() }); + } + fb.SetCustomAttribute(new CustomAttributeBuilder(runtimeVisibleTypeAnnotationsAttribute, new object[] { data })); + } + + internal static void SetRuntimeVisibleTypeAnnotationsAttribute(MethodBuilder mb, byte[] data) + { + if(runtimeVisibleTypeAnnotationsAttribute == null) + { + runtimeVisibleTypeAnnotationsAttribute = typeofRuntimeVisibleTypeAnnotationsAttribute.GetConstructor(new Type[] { Types.Byte.MakeArrayType() }); + } + mb.SetCustomAttribute(new CustomAttributeBuilder(runtimeVisibleTypeAnnotationsAttribute, new object[] { data })); + } + + internal static void SetConstantPoolAttribute(TypeBuilder tb, object[] constantPool) + { + if(constantPoolAttribute == null) + { + constantPoolAttribute = typeofConstantPoolAttribute.GetConstructor(new Type[] { Types.Object.MakeArrayType() }); + } + tb.SetCustomAttribute(new CustomAttributeBuilder(constantPoolAttribute, new object[] { constantPool })); + } + + internal static void SetParamArrayAttribute(ParameterBuilder pb) + { + if(paramArrayAttribute == null) + { + paramArrayAttribute = new CustomAttributeBuilder(JVM.Import(typeof(ParamArrayAttribute)).GetConstructor(Type.EmptyTypes), new object[0]); + } + pb.SetCustomAttribute(paramArrayAttribute); + } +#endif // STATIC_COMPILER + + internal static NameSigAttribute GetNameSig(MemberInfo member) + { +#if !STATIC_COMPILER && !STUB_GENERATOR + object[] attr = member.GetCustomAttributes(typeof(NameSigAttribute), false); + return attr.Length == 1 ? (NameSigAttribute)attr[0] : null; +#else + foreach(CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(member, typeofNameSigAttribute, false)) + { + IList args = cad.ConstructorArguments; + return new NameSigAttribute((string)args[0].Value, (string)args[1].Value); + } + return null; +#endif + } + + internal static T[] DecodeArray(CustomAttributeTypedArgument arg) + { + IList elems = (IList)arg.Value; + T[] arr = new T[elems.Count]; + for(int i = 0; i < arr.Length; i++) + { + arr[i] = (T)elems[i].Value; + } + return arr; + } + + internal static ImplementsAttribute GetImplements(Type type) + { +#if !STATIC_COMPILER && !STUB_GENERATOR + object[] attribs = type.GetCustomAttributes(typeof(ImplementsAttribute), false); + return attribs.Length == 1 ? (ImplementsAttribute)attribs[0] : null; +#else + foreach(CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(type, typeofImplementsAttribute, false)) + { + IList args = cad.ConstructorArguments; + return new ImplementsAttribute(DecodeArray(args[0])); + } + return null; +#endif + } + + internal static ThrowsAttribute GetThrows(MethodBase mb) + { +#if !STATIC_COMPILER && !STUB_GENERATOR + object[] attribs = mb.GetCustomAttributes(typeof(ThrowsAttribute), false); + return attribs.Length == 1 ? (ThrowsAttribute)attribs[0] : null; +#else + foreach(CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(mb, typeofThrowsAttribute, false)) + { + IList args = cad.ConstructorArguments; + if (args[0].ArgumentType == Types.String.MakeArrayType()) + { + return new ThrowsAttribute(DecodeArray(args[0])); + } + else if (args[0].ArgumentType == Types.Type.MakeArrayType()) + { + return new ThrowsAttribute(DecodeArray(args[0])); + } + else + { + return new ThrowsAttribute((Type)args[0].Value); + } + } + return null; +#endif + } + + internal static string[] GetNonNestedInnerClasses(Type t) + { +#if !STATIC_COMPILER && !STUB_GENERATOR + object[] attribs = t.GetCustomAttributes(typeof(NonNestedInnerClassAttribute), false); + string[] classes = new string[attribs.Length]; + for (int i = 0; i < attribs.Length; i++) + { + classes[i] = ((NonNestedInnerClassAttribute)attribs[i]).InnerClassName; + } + return classes; +#else + List list = new List(); + foreach(CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(t, typeofNonNestedInnerClassAttribute, false)) + { + IList args = cad.ConstructorArguments; + list.Add(UnicodeUtil.UnescapeInvalidSurrogates((string)args[0].Value)); + } + return list.ToArray(); +#endif + } + + internal static string GetNonNestedOuterClasses(Type t) + { +#if !STATIC_COMPILER && !STUB_GENERATOR + object[] attribs = t.GetCustomAttributes(typeof(NonNestedOuterClassAttribute), false); + return attribs.Length == 1 ? ((NonNestedOuterClassAttribute)attribs[0]).OuterClassName : null; +#else + foreach(CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(t, typeofNonNestedOuterClassAttribute, false)) + { + IList args = cad.ConstructorArguments; + return UnicodeUtil.UnescapeInvalidSurrogates((string)args[0].Value); + } + return null; +#endif + } + + internal static SignatureAttribute GetSignature(MemberInfo member) + { +#if !STATIC_COMPILER && !STUB_GENERATOR + object[] attribs = member.GetCustomAttributes(typeof(SignatureAttribute), false); + return attribs.Length == 1 ? (SignatureAttribute)attribs[0] : null; +#else + foreach(CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(member, typeofSignatureAttribute, false)) + { + IList args = cad.ConstructorArguments; + return new SignatureAttribute((string)args[0].Value); + } + return null; +#endif + } + + internal static MethodParametersAttribute GetMethodParameters(MethodBase method) + { +#if !STATIC_COMPILER && !STUB_GENERATOR + object[] attribs = method.GetCustomAttributes(typeof(MethodParametersAttribute), false); + return attribs.Length == 1 ? (MethodParametersAttribute)attribs[0] : null; +#else + foreach(CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(method, typeofMethodParametersAttribute, false)) + { + IList args = cad.ConstructorArguments; + return new MethodParametersAttribute(DecodeArray(args[0])); + } + return null; +#endif + } + + internal static object[] GetConstantPool(Type type) + { +#if !STATIC_COMPILER && !STUB_GENERATOR + object[] attribs = type.GetCustomAttributes(typeof(ConstantPoolAttribute), false); + return attribs.Length == 1 ? ((ConstantPoolAttribute)attribs[0]).constantPool : null; +#else + foreach(CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(type, typeofConstantPoolAttribute, false)) + { + return ConstantPoolAttribute.Decompress(DecodeArray(cad.ConstructorArguments[0])); + } + return null; +#endif + } + + internal static byte[] GetRuntimeVisibleTypeAnnotations(MemberInfo member) + { +#if !STATIC_COMPILER && !STUB_GENERATOR + object[] attribs = member.GetCustomAttributes(typeof(RuntimeVisibleTypeAnnotationsAttribute), false); + return attribs.Length == 1 ? ((RuntimeVisibleTypeAnnotationsAttribute)attribs[0]).data : null; +#else + foreach(CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(member, typeofRuntimeVisibleTypeAnnotationsAttribute, false)) + { + return DecodeArray(cad.ConstructorArguments[0]); + } + return null; +#endif + } + + internal static InnerClassAttribute GetInnerClass(Type type) + { +#if !STATIC_COMPILER && !STUB_GENERATOR + object[] attribs = type.GetCustomAttributes(typeof(InnerClassAttribute), false); + return attribs.Length == 1 ? (InnerClassAttribute)attribs[0] : null; +#else + foreach(CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(type, typeofInnerClassAttribute, false)) + { + IList args = cad.ConstructorArguments; + return new InnerClassAttribute((string)args[0].Value, (Modifiers)args[1].Value); + } + return null; +#endif + } + + internal static RemappedInterfaceMethodAttribute[] GetRemappedInterfaceMethods(Type type) + { +#if !STATIC_COMPILER && !STUB_GENERATOR + object[] attr = type.GetCustomAttributes(typeof(RemappedInterfaceMethodAttribute), false); + RemappedInterfaceMethodAttribute[] attr1 = new RemappedInterfaceMethodAttribute[attr.Length]; + Array.Copy(attr, attr1, attr.Length); + return attr1; +#else + List attrs = new List(); + foreach(CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(type, typeofRemappedInterfaceMethodAttribute, false)) + { + IList args = cad.ConstructorArguments; + attrs.Add(new RemappedInterfaceMethodAttribute((string)args[0].Value, (string)args[1].Value, DecodeArray(args[2]))); + } + return attrs.ToArray(); +#endif + } + + internal static RemappedTypeAttribute GetRemappedType(Type type) + { +#if !STATIC_COMPILER && !STUB_GENERATOR + object[] attribs = type.GetCustomAttributes(typeof(RemappedTypeAttribute), false); + return attribs.Length == 1 ? (RemappedTypeAttribute)attribs[0] : null; +#else + foreach(CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(type, typeofRemappedTypeAttribute, false)) + { + IList args = cad.ConstructorArguments; + return new RemappedTypeAttribute((Type)args[0].Value); + } + return null; +#endif + } + + internal static RemappedClassAttribute[] GetRemappedClasses(Assembly coreAssembly) + { +#if !STATIC_COMPILER && !STUB_GENERATOR + object[] attr = coreAssembly.GetCustomAttributes(typeof(RemappedClassAttribute), false); + RemappedClassAttribute[] attr1 = new RemappedClassAttribute[attr.Length]; + Array.Copy(attr, attr1, attr.Length); + return attr1; +#else + List attrs = new List(); + foreach(CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(coreAssembly, typeofRemappedClassAttribute, false)) + { + IList args = cad.ConstructorArguments; + attrs.Add(new RemappedClassAttribute((string)args[0].Value, (Type)args[1].Value)); + } + return attrs.ToArray(); +#endif + } + + internal static string GetAnnotationAttributeType(Type type) + { +#if !STATIC_COMPILER && !STUB_GENERATOR + object[] attr = type.GetCustomAttributes(typeof(AnnotationAttributeAttribute), false); + if(attr.Length == 1) + { + return ((AnnotationAttributeAttribute)attr[0]).AttributeType; + } + return null; +#else + foreach(CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(type, typeofAnnotationAttributeAttribute, false)) + { + return UnicodeUtil.UnescapeInvalidSurrogates((string)cad.ConstructorArguments[0].Value); + } + return null; +#endif + } + + internal static AssemblyName[] GetInternalsVisibleToAttributes(Assembly assembly) + { + List list = new List(); + foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(assembly)) + { + if(cad.Constructor.DeclaringType == JVM.Import(typeof(System.Runtime.CompilerServices.InternalsVisibleToAttribute))) + { + try + { + list.Add(new AssemblyName((string)cad.ConstructorArguments[0].Value)); + } + catch + { + // HACK since there is no list of exception that the AssemblyName constructor can throw, we simply catch all + } + } + } + return list.ToArray(); + } + + internal static bool IsJavaModule(Module mod) + { + return mod.IsDefined(typeofJavaModuleAttribute, false); + } + + internal static object[] GetJavaModuleAttributes(Module mod) + { +#if !STATIC_COMPILER && !STUB_GENERATOR + return mod.GetCustomAttributes(typeofJavaModuleAttribute, false); +#else + List attrs = new List(); + foreach(CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(mod, typeofJavaModuleAttribute, false)) + { + IList args = cad.ConstructorArguments; + if(args.Count == 0) + { + attrs.Add(new JavaModuleAttribute()); + } + else + { + attrs.Add(new JavaModuleAttribute(DecodeArray(args[0]))); + } + } + return attrs.ToArray(); +#endif + } + + internal static bool IsNoPackagePrefix(Type type) + { + return type.IsDefined(typeofNoPackagePrefixAttribute, false) || type.Assembly.IsDefined(typeofNoPackagePrefixAttribute, false); + } + + internal static bool HasEnclosingMethodAttribute(Type type) + { + return type.IsDefined(typeofEnclosingMethodAttribute, false); + } + + internal static EnclosingMethodAttribute GetEnclosingMethodAttribute(Type type) + { +#if !STATIC_COMPILER && !STUB_GENERATOR + object[] attr = type.GetCustomAttributes(typeof(EnclosingMethodAttribute), false); + if (attr.Length == 1) + { + return ((EnclosingMethodAttribute)attr[0]).SetClassName(type); + } + return null; +#else + foreach (CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(type, typeofEnclosingMethodAttribute, false)) + { + return new EnclosingMethodAttribute((string)cad.ConstructorArguments[0].Value, (string)cad.ConstructorArguments[1].Value, (string)cad.ConstructorArguments[2].Value).SetClassName(type); + } + return null; +#endif + } + +#if STATIC_COMPILER + internal static void SetRemappedClass(AssemblyBuilder assemblyBuilder, string name, Type shadowType) + { + ConstructorInfo remappedClassAttribute = typeofRemappedClassAttribute.GetConstructor(new Type[] { Types.String, Types.Type }); + assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder(remappedClassAttribute, new object[] { name, shadowType })); + } + + internal static void SetRemappedType(TypeBuilder typeBuilder, Type shadowType) + { + ConstructorInfo remappedTypeAttribute = typeofRemappedTypeAttribute.GetConstructor(new Type[] { Types.Type }); + typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(remappedTypeAttribute, new object[] { shadowType })); + } + + internal static void SetRemappedInterfaceMethod(TypeBuilder typeBuilder, string name, string mappedTo, string[] throws) + { + CustomAttributeBuilder cab = new CustomAttributeBuilder(typeofRemappedInterfaceMethodAttribute.GetConstructor(new Type[] { Types.String, Types.String, Types.String.MakeArrayType() }), new object[] { name, mappedTo, throws }); + typeBuilder.SetCustomAttribute(cab); + } + + internal static void SetExceptionIsUnsafeForMapping(TypeBuilder typeBuilder) + { + CustomAttributeBuilder cab = new CustomAttributeBuilder(typeofExceptionIsUnsafeForMappingAttribute.GetConstructor(Type.EmptyTypes), new object[0]); + typeBuilder.SetCustomAttribute(cab); + } +#endif // STATIC_COMPILER + + internal static void SetRuntimeCompatibilityAttribute(AssemblyBuilder assemblyBuilder) + { + Type runtimeCompatibilityAttribute = JVM.Import(typeof(System.Runtime.CompilerServices.RuntimeCompatibilityAttribute)); + assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder( + runtimeCompatibilityAttribute.GetConstructor(Type.EmptyTypes), new object[0], + new PropertyInfo[] { runtimeCompatibilityAttribute.GetProperty("WrapNonExceptionThrows") }, new object[] { true }, + new FieldInfo[0], new object[0])); + } + + internal static void SetInternalsVisibleToAttribute(AssemblyBuilder assemblyBuilder, string assemblyName) + { + Type internalsVisibleToAttribute = JVM.Import(typeof(System.Runtime.CompilerServices.InternalsVisibleToAttribute)); + CustomAttributeBuilder cab = new CustomAttributeBuilder( + internalsVisibleToAttribute.GetConstructor(new Type[] { Types.String }), new object[] { assemblyName }); + assemblyBuilder.SetCustomAttribute(cab); + } + } + + static class EnumHelper + { + internal static Type GetUnderlyingType(Type enumType) + { +#if STATIC_COMPILER || STUB_GENERATOR + return enumType.GetEnumUnderlyingType(); +#else + return Enum.GetUnderlyingType(enumType); +#endif + } + +#if STATIC_COMPILER + internal static object Parse(Type type, string value) + { + object retval = null; + foreach (string str in value.Split(',')) + { + FieldInfo field = type.GetField(str.Trim(), BindingFlags.Public | BindingFlags.Static); + if (field == null) + { + throw new InvalidOperationException("Enum value '" + str + "' not found in " + type.FullName); + } + if (retval == null) + { + retval = field.GetRawConstantValue(); + } + else + { + retval = OrBoxedIntegrals(retval, field.GetRawConstantValue()); + } + } + return retval; + } +#endif + + // note that we only support the integer types that C# supports + // (the CLI also supports bool, char, IntPtr & UIntPtr) + internal static object OrBoxedIntegrals(object v1, object v2) + { + Debug.Assert(v1.GetType() == v2.GetType()); + if (v1 is ulong) + { + ulong l1 = (ulong)v1; + ulong l2 = (ulong)v2; + return l1 | l2; + } + else + { + long v = ((IConvertible)v1).ToInt64(null) | ((IConvertible)v2).ToInt64(null); + switch (Type.GetTypeCode(JVM.Import(v1.GetType()))) + { + case TypeCode.SByte: + return (sbyte)v; + case TypeCode.Byte: + return (byte)v; + case TypeCode.Int16: + return (short)v; + case TypeCode.UInt16: + return (ushort)v; + case TypeCode.Int32: + return (int)v; + case TypeCode.UInt32: + return (uint)v; + case TypeCode.Int64: + return (long)v; + default: + throw new InvalidOperationException(); + } + } + } + + // this method can be used to convert an enum value or its underlying value to a Java primitive + internal static object GetPrimitiveValue(Type underlyingType, object obj) + { + // Note that this method doesn't trust that obj is of the correct type, + // because it turns out there exist assemblies (e.g. gtk-sharp.dll) that + // have incorrectly typed enum constant values (e.g. int32 instead of uint32). + long value; + if (obj is ulong || (obj is Enum && underlyingType == Types.UInt64)) + { + value = unchecked((long)((IConvertible)obj).ToUInt64(null)); + } + else + { + value = ((IConvertible)obj).ToInt64(null); + } + if (underlyingType == Types.SByte || underlyingType == Types.Byte) + { + return unchecked((byte)value); + } + else if (underlyingType == Types.Int16 || underlyingType == Types.UInt16) + { + return unchecked((short)value); + } + else if (underlyingType == Types.Int32 || underlyingType == Types.UInt32) + { + return unchecked((int)value); + } + else if (underlyingType == Types.Int64 || underlyingType == Types.UInt64) + { + return value; + } + else + { + throw new InvalidOperationException(); + } + } + } + + static class TypeNameUtil + { + // note that MangleNestedTypeName() assumes that there are less than 16 special characters + private const string specialCharactersString = "\\+,[]*&\u0000"; + internal const string ProxiesContainer = "__"; + + internal static string ReplaceIllegalCharacters(string name) + { + name = UnicodeUtil.EscapeInvalidSurrogates(name); + // only the NUL character is illegal in CLR type names, so we replace it with a space + return name.Replace('\u0000', ' '); + } + + internal static string Unescape(string name) + { + int pos = name.IndexOf('\\'); + if (pos == -1) + { + return name; + } + System.Text.StringBuilder sb = new System.Text.StringBuilder(name.Length); + sb.Append(name, 0, pos); + for (int i = pos; i < name.Length; i++) + { + char c = name[i]; + if (c == '\\') + { + c = name[++i]; + } + sb.Append(c); + } + return sb.ToString(); + } + + internal static string MangleNestedTypeName(string name) + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + foreach (char c in name) + { + int index = specialCharactersString.IndexOf(c); + if (c == '.') + { + sb.Append("_"); + } + else if (c == '_') + { + sb.Append("^-"); + } + else if (index == -1) + { + sb.Append(c); + if (c == '^') + { + sb.Append(c); + } + } + else + { + sb.Append('^').AppendFormat("{0:X1}", index); + } + } + return sb.ToString(); + } + + internal static string UnmangleNestedTypeName(string name) + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + for (int i = 0; i < name.Length; i++) + { + char c = name[i]; + int index = specialCharactersString.IndexOf(c); + if (c == '_') + { + sb.Append('.'); + } + else if (c == '^') + { + c = name[++i]; + if (c == '-') + { + sb.Append('_'); + } + else if (c == '^') + { + sb.Append('^'); + } + else + { + sb.Append(specialCharactersString[c - '0']); + } + } + else + { + sb.Append(c); + } + } + return sb.ToString(); + } + + internal static string GetProxyNestedName(TypeWrapper[] interfaces) + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + foreach (TypeWrapper tw in interfaces) + { + sb.Append(tw.Name.Length).Append('|').Append(tw.Name); + } + return TypeNameUtil.MangleNestedTypeName(sb.ToString()); + } + + internal static string GetProxyName(TypeWrapper[] interfaces) + { + return ProxiesContainer + "+" + GetProxyNestedName(interfaces); + } + } + + static class ArrayUtil + { + internal static T[] Concat(X obj, T[] arr) + where X : T + { + T[] narr = new T[arr.Length + 1]; + narr[0] = obj; + Array.Copy(arr, 0, narr, 1, arr.Length); + return narr; + } + + internal static T[] Concat(T[] arr, X obj) + where X : T + { + Array.Resize(ref arr, arr.Length + 1); + arr[arr.Length - 1] = obj; + return arr; + } + + internal static T[] DropFirst(T[] arr) + { + T[] narr = new T[arr.Length - 1]; + Array.Copy(arr, 1, narr, 0, narr.Length); + return narr; + } + } + + static class UnicodeUtil + { + // We use part of the Supplementary Private Use Area-B to encode + // invalid surrogates. If we encounter either of these two + // markers, we always encode the surrogate (single or pair) + private const char HighSurrogatePrefix = '\uDBFF'; + private const char LowSurrogatePrefix = '\uDBFE'; + + // Identifiers in ECMA CLI metadata and strings in custom attribute blobs are encoded + // using UTF-8 and don't allow partial surrogates, so we have to "complete" them to + // produce valid Unicode and reverse the process when we read back the names. + internal static string EscapeInvalidSurrogates(string str) + { + if (str != null) + { + for (int i = 0; i < str.Length; i++) + { + char c = str[i]; + if (Char.IsLowSurrogate(c)) + { + str = str.Substring(0, i) + LowSurrogatePrefix + c + str.Substring(i + 1); + i++; + } + else if (Char.IsHighSurrogate(c)) + { + i++; + // always escape the markers + if (c == HighSurrogatePrefix || c == LowSurrogatePrefix || i == str.Length || !Char.IsLowSurrogate(str[i])) + { + str = str.Substring(0, i - 1) + HighSurrogatePrefix + (char)(c + 0x400) + str.Substring(i); + } + } + } + } + return str; + } + + internal static string UnescapeInvalidSurrogates(string str) + { + if (str != null) + { + for (int i = 0; i < str.Length; i++) + { + switch (str[i]) + { + case HighSurrogatePrefix: + str = str.Substring(0, i) + (char)(str[i + 1] - 0x400) + str.Substring(i + 2); + break; + case LowSurrogatePrefix: + str = str.Substring(0, i) + str[i + 1] + str.Substring(i + 2); + break; + } + } + } + return str; + } + + internal static string[] EscapeInvalidSurrogates(string[] str) + { + if (str != null) + { + for (int i = 0; i < str.Length; i++) + { + str[i] = EscapeInvalidSurrogates(str[i]); + } + } + return str; + } + + internal static string[] UnescapeInvalidSurrogates(string[] str) + { + if (str != null) + { + for (int i = 0; i < str.Length; i++) + { + str[i] = UnescapeInvalidSurrogates(str[i]); + } + } + return str; + } + } + + abstract class Annotation + { +#if STATIC_COMPILER + internal static Annotation LoadAssemblyCustomAttribute(ClassLoaderWrapper loader, object[] def) + { + Debug.Assert(def[0].Equals(AnnotationDefaultAttribute.TAG_ANNOTATION)); + string annotationClass = (string)def[1]; + if (ClassFile.IsValidFieldSig(annotationClass)) + { + try + { + return loader.RetTypeWrapperFromSig(annotationClass.Replace('/', '.'), LoadMode.LoadOrThrow).Annotation; + } + catch (RetargetableJavaException) + { + } + } + return null; + } +#endif + +#if !STUB_GENERATOR + // NOTE this method returns null if the type could not be found + // or if the type is not a Custom Attribute and we're not in the static compiler + internal static Annotation Load(TypeWrapper owner, object[] def) + { + Debug.Assert(def[0].Equals(AnnotationDefaultAttribute.TAG_ANNOTATION)); + string annotationClass = (string)def[1]; +#if !STATIC_COMPILER + if(!annotationClass.EndsWith("$Annotation;") + && !annotationClass.EndsWith("$Annotation$__ReturnValue;") + && !annotationClass.EndsWith("$Annotation$__Multiple;")) + { + // we don't want to try to load an annotation in dynamic mode, + // unless it is a .NET custom attribute (which can affect runtime behavior) + return null; + } +#endif + if (ClassFile.IsValidFieldSig(annotationClass)) + { + TypeWrapper tw = owner.GetClassLoader().RetTypeWrapperFromSig(annotationClass.Replace('/', '.'), LoadMode.Link); + // Java allows inaccessible annotations to be used, so when the annotation isn't visible + // we fall back to using the DynamicAnnotationAttribute. + if (!tw.IsUnloadable && tw.IsAccessibleFrom(owner)) + { + return tw.Annotation; + } + } + Tracer.Warning(Tracer.Compiler, "Unable to load annotation class {0}", annotationClass); +#if STATIC_COMPILER + return new CompiledTypeWrapper.CompiledAnnotation(StaticCompiler.GetRuntimeType("IKVM.Attributes.DynamicAnnotationAttribute")); +#else + return null; +#endif + } +#endif + + private static object LookupEnumValue(Type enumType, string value) + { + FieldInfo field = enumType.GetField(value, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); + if(field != null) + { + return field.GetRawConstantValue(); + } + // both __unspecified and missing values end up here + return EnumHelper.GetPrimitiveValue(EnumHelper.GetUnderlyingType(enumType), 0); + } + + protected static object ConvertValue(ClassLoaderWrapper loader, Type targetType, object obj) + { + if(targetType.IsEnum) + { + // TODO check the obj descriptor matches the type we expect + if(((object[])obj)[0].Equals(AnnotationDefaultAttribute.TAG_ARRAY)) + { + object[] arr = (object[])obj; + object value = null; + for(int i = 1; i < arr.Length; i++) + { + // TODO check the obj descriptor matches the type we expect + string s = ((object[])arr[i])[2].ToString(); + object newval = LookupEnumValue(targetType, s); + if (value == null) + { + value = newval; + } + else + { + value = EnumHelper.OrBoxedIntegrals(value, newval); + } + } + return value; + } + else + { + string s = ((object[])obj)[2].ToString(); + if(s == "__unspecified") + { + // TODO we should probably return null and handle that + } + return LookupEnumValue(targetType, s); + } + } + else if(targetType == Types.Type) + { + // TODO check the obj descriptor matches the type we expect + return loader.FieldTypeWrapperFromSig(((string)((object[])obj)[1]).Replace('/', '.'), LoadMode.LoadOrThrow).TypeAsTBD; + } + else if(targetType.IsArray) + { + // TODO check the obj descriptor matches the type we expect + object[] arr = (object[])obj; + Type elementType = targetType.GetElementType(); + object[] targetArray = new object[arr.Length - 1]; + for(int i = 1; i < arr.Length; i++) + { + targetArray[i - 1] = ConvertValue(loader, elementType, arr[i]); + } + return targetArray; + } + else + { + return obj; + } + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal static bool MakeDeclSecurity(Type type, object annotation, out SecurityAction action, out PermissionSet permSet) + { + ConstructorInfo ci = type.GetConstructor(new Type[] { typeof(SecurityAction) }); + if (ci == null) + { + // TODO should we support HostProtectionAttribute? (which has a no-arg constructor) + // TODO issue message? + action = 0; + permSet = null; + return false; + } + SecurityAttribute attr = null; + object[] arr = (object[])annotation; + for (int i = 2; i < arr.Length; i += 2) + { + string name = (string)arr[i]; + if (name == "value") + { + attr = (SecurityAttribute)ci.Invoke(new object[] { ConvertValue(null, typeof(SecurityAction), arr[i + 1]) }); + } + } + if (attr == null) + { + // TODO issue message? + action = 0; + permSet = null; + return false; + } + for (int i = 2; i < arr.Length; i += 2) + { + string name = (string)arr[i]; + if (name != "value") + { + PropertyInfo pi = type.GetProperty(name); + pi.SetValue(attr, ConvertValue(null, pi.PropertyType, arr[i + 1]), null); + } + } + action = attr.Action; + permSet = new PermissionSet(PermissionState.None); + permSet.AddPermission(attr.CreatePermission()); + return true; + } +#endif // !STATIC_COMPILER && !STUB_GENERATOR + + internal static bool HasRetentionPolicyRuntime(object[] annotations) + { + if(annotations != null) + { + foreach(object[] def in annotations) + { + if(def[1].Equals("Ljava/lang/annotation/Retention;")) + { + for(int i = 2; i < def.Length; i += 2) + { + if(def[i].Equals("value")) + { + object[] val = def[i + 1] as object[]; + if(val != null + && val.Length == 3 + && val[0].Equals(AnnotationDefaultAttribute.TAG_ENUM) + && val[1].Equals("Ljava/lang/annotation/RetentionPolicy;") + && val[2].Equals("RUNTIME")) + { + return true; + } + } + } + } + } + } + return false; + } + + internal static bool HasObsoleteAttribute(object[] annotations) + { + if (annotations != null) + { + foreach (object[] def in annotations) + { + if (def[1].Equals("Lcli/System/ObsoleteAttribute$Annotation;")) + { + return true; + } + } + } + return false; + } + + protected static object QualifyClassNames(ClassLoaderWrapper loader, object annotation) + { + bool copy = false; + object[] def = (object[])annotation; + for(int i = 3; i < def.Length; i += 2) + { + object[] val = def[i] as object[]; + if(val != null) + { + object[] newval = ValueQualifyClassNames(loader, val); + if(newval != val) + { + if(!copy) + { + copy = true; + object[] newdef = new object[def.Length]; + Array.Copy(def, newdef, def.Length); + def = newdef; + } + def[i] = newval; + } + } + } + return def; + } + + private static object[] ValueQualifyClassNames(ClassLoaderWrapper loader, object[] val) + { + if(val[0].Equals(AnnotationDefaultAttribute.TAG_ANNOTATION)) + { + return (object[])QualifyClassNames(loader, val); + } + else if(val[0].Equals(AnnotationDefaultAttribute.TAG_CLASS)) + { + string sig = (string)val[1]; + if(sig.StartsWith("L")) + { + TypeWrapper tw = loader.LoadClassByDottedNameFast(sig.Substring(1, sig.Length - 2).Replace('/', '.')); + if(tw != null) + { + return new object[] { AnnotationDefaultAttribute.TAG_CLASS, "L" + tw.TypeAsBaseType.AssemblyQualifiedName.Replace('.', '/') + ";" }; + } + } + return val; + } + else if(val[0].Equals(AnnotationDefaultAttribute.TAG_ENUM)) + { + string sig = (string)val[1]; + TypeWrapper tw = loader.LoadClassByDottedNameFast(sig.Substring(1, sig.Length - 2).Replace('/', '.')); + if(tw != null) + { + return new object[] { AnnotationDefaultAttribute.TAG_ENUM, "L" + tw.TypeAsBaseType.AssemblyQualifiedName.Replace('.', '/') + ";", val[2] }; + } + return val; + } + else if(val[0].Equals(AnnotationDefaultAttribute.TAG_ARRAY)) + { + bool copy = false; + for(int i = 1; i < val.Length; i++) + { + object[] nval = val[i] as object[]; + if(nval != null) + { + object newnval = ValueQualifyClassNames(loader, nval); + if(newnval != nval) + { + if(!copy) + { + copy = true; + object[] newval = new object[val.Length]; + Array.Copy(val, newval, val.Length); + val = newval; + } + val[i] = newnval; + } + } + } + return val; + } + else if(val[0].Equals(AnnotationDefaultAttribute.TAG_ERROR)) + { + return val; + } + else + { + throw new InvalidOperationException(); + } + } + + internal abstract void Apply(ClassLoaderWrapper loader, TypeBuilder tb, object annotation); + internal abstract void Apply(ClassLoaderWrapper loader, MethodBuilder mb, object annotation); + internal abstract void Apply(ClassLoaderWrapper loader, FieldBuilder fb, object annotation); + internal abstract void Apply(ClassLoaderWrapper loader, ParameterBuilder pb, object annotation); + internal abstract void Apply(ClassLoaderWrapper loader, AssemblyBuilder ab, object annotation); + internal abstract void Apply(ClassLoaderWrapper loader, PropertyBuilder pb, object annotation); + + internal virtual void ApplyReturnValue(ClassLoaderWrapper loader, MethodBuilder mb, ref ParameterBuilder pb, object annotation) + { + } + + internal abstract bool IsCustomAttribute { get; } + } + + [Flags] + enum TypeFlags : ushort + { + None = 0, + HasIncompleteInterfaceImplementation = 1, + InternalAccess = 2, + HasStaticInitializer = 4, + VerifyError = 8, + ClassFormatError = 16, + HasUnsupportedAbstractMethods = 32, + Anonymous = 64, + Linked = 128, + } + + static class NamePrefix + { + internal const string Type2AccessStubBackingField = "__<>"; + internal const string AccessStub = ""; + internal const string NonVirtual = ""; + internal const string Bridge = ""; + internal const string Incomplete = ""; + internal const string DefaultMethod = ""; + internal const string PrivateInterfaceInstanceMethod = ""; + } + + static class NestedTypeName + { + internal const string CallerID = "__"; + internal const string InterfaceHelperMethods = "__<>IHM"; + internal const string PrivateInterfaceMethods = "__<>PIM"; + + // interop types (mangled if necessary) + internal const string Fields = "__Fields"; + internal const string Methods = "__Methods"; + internal const string DefaultMethods = "__DefaultMethods"; + + // prefixes + internal const string ThreadLocal = "___"; + internal const string AtomicReferenceFieldUpdater = "___"; + internal const string IndyCallSite = "__<>IndyCS"; + internal const string MethodHandleConstant = "__<>MHC"; + internal const string MethodTypeConstant = "__<>MTC"; + internal const string IntrinsifiedAnonymousClass = "__<>Anon"; + } + + internal abstract class TypeWrapper + { + private static readonly object flagsLock = new object(); + private readonly string name; // java name (e.g. java.lang.Object) + private readonly Modifiers modifiers; + private TypeFlags flags; + private MethodWrapper[] methods; + private FieldWrapper[] fields; +#if !STATIC_COMPILER && !STUB_GENERATOR + private java.lang.Class classObject; +#endif + internal static readonly TypeWrapper[] EmptyArray = new TypeWrapper[0]; + internal const Modifiers UnloadableModifiersHack = Modifiers.Final | Modifiers.Interface | Modifiers.Private; + internal const Modifiers VerifierTypeModifiersHack = Modifiers.Final | Modifiers.Interface; + + internal TypeWrapper(TypeFlags flags, Modifiers modifiers, string name) + { + Profiler.Count("TypeWrapper"); + // class name should be dotted or null for primitives + Debug.Assert(name == null || name.IndexOf('/') < 0); + + this.flags = flags; + this.modifiers = modifiers; + this.name = name == null ? null : String.Intern(name); + } + +#if EMITTERS + internal void EmitClassLiteral(CodeEmitter ilgen) + { + Debug.Assert(!this.IsPrimitive); + + Type type = GetClassLiteralType(); + + // note that this has to be the same check as in LazyInitClass + if (!this.IsFastClassLiteralSafe || IsForbiddenTypeParameterType(type)) + { + int rank = 0; + while (ReflectUtil.IsVector(type)) + { + rank++; + type = type.GetElementType(); + } + if (rank == 0) + { + ilgen.Emit(OpCodes.Ldtoken, type); + Compiler.getClassFromTypeHandle.EmitCall(ilgen); + } + else + { + ilgen.Emit(OpCodes.Ldtoken, type); + ilgen.EmitLdc_I4(rank); + Compiler.getClassFromTypeHandle2.EmitCall(ilgen); + } + } + else + { + ilgen.Emit(OpCodes.Ldsfld, RuntimeHelperTypes.GetClassLiteralField(type)); + } + } +#endif // EMITTERS + + private Type GetClassLiteralType() + { + Debug.Assert(!this.IsPrimitive); + + TypeWrapper tw = this; + if (tw.IsGhostArray) + { + int rank = tw.ArrayRank; + while (tw.IsArray) + { + tw = tw.ElementTypeWrapper; + } + return ArrayTypeWrapper.MakeArrayType(tw.TypeAsTBD, rank); + } + else + { + return tw.IsRemapped ? tw.TypeAsBaseType : tw.TypeAsTBD; + } + } + + private static bool IsForbiddenTypeParameterType(Type type) + { + // these are the types that may not be used as a type argument when instantiating a generic type + return type == Types.Void + || type == JVM.Import(typeof(ArgIterator)) + || type == JVM.Import(typeof(RuntimeArgumentHandle)) + || type == JVM.Import(typeof(TypedReference)) + || type.ContainsGenericParameters + || type.IsByRef; + } + + internal virtual bool IsFastClassLiteralSafe + { + get { return false; } + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal void SetClassObject(java.lang.Class classObject) + { + this.classObject = classObject; + } + + internal java.lang.Class ClassObject + { + get + { + Debug.Assert(!IsUnloadable && !IsVerifierType); + if (classObject == null) + { + LazyInitClass(); + } + return classObject; + } + } + +#if !FIRST_PASS + private java.lang.Class GetPrimitiveClass() + { + if (this == PrimitiveTypeWrapper.BYTE) + { + return java.lang.Byte.TYPE; + } + else if (this == PrimitiveTypeWrapper.CHAR) + { + return java.lang.Character.TYPE; + } + else if (this == PrimitiveTypeWrapper.DOUBLE) + { + return java.lang.Double.TYPE; + } + else if (this == PrimitiveTypeWrapper.FLOAT) + { + return java.lang.Float.TYPE; + } + else if (this == PrimitiveTypeWrapper.INT) + { + return java.lang.Integer.TYPE; + } + else if (this == PrimitiveTypeWrapper.LONG) + { + return java.lang.Long.TYPE; + } + else if (this == PrimitiveTypeWrapper.SHORT) + { + return java.lang.Short.TYPE; + } + else if (this == PrimitiveTypeWrapper.BOOLEAN) + { + return java.lang.Boolean.TYPE; + } + else if (this == PrimitiveTypeWrapper.VOID) + { + return java.lang.Void.TYPE; + } + else + { + throw new InvalidOperationException(); + } + } +#endif + + private void LazyInitClass() + { + lock (this) + { + if (classObject == null) + { + // DynamicTypeWrapper should haved already had SetClassObject explicitly + Debug.Assert(!IsDynamic); +#if !FIRST_PASS + java.lang.Class clazz; + // note that this has to be the same check as in EmitClassLiteral + if (!this.IsFastClassLiteralSafe) + { + if (this.IsPrimitive) + { + clazz = GetPrimitiveClass(); + } + else + { + clazz = new java.lang.Class(null); + } + } + else + { + Type type = GetClassLiteralType(); + if (IsForbiddenTypeParameterType(type)) + { + clazz = new java.lang.Class(type); + } + else + { + clazz = (java.lang.Class)typeof(ikvm.@internal.ClassLiteral<>).MakeGenericType(type).GetField("Value").GetValue(null); + } + } +#if __MonoCS__ + SetTypeWrapperHack(clazz, this); +#else + clazz.typeWrapper = this; +#endif + // MONOBUG Interlocked.Exchange is broken on Mono, so we use CompareExchange + System.Threading.Interlocked.CompareExchange(ref classObject, clazz, null); +#endif + } + } + } + +#if __MonoCS__ + // MONOBUG this method is to work around an mcs bug + internal static void SetTypeWrapperHack(object clazz, TypeWrapper type) + { +#if !FIRST_PASS + typeof(java.lang.Class).GetField("typeWrapper", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(clazz, type); +#endif + } +#endif + +#if !FIRST_PASS + private static void ResolvePrimitiveTypeWrapperClasses() + { + // note that we're evaluating all ClassObject properties for the side effect + // (to initialize and associate the ClassObject with the TypeWrapper) + if (PrimitiveTypeWrapper.BYTE.ClassObject == null + || PrimitiveTypeWrapper.CHAR.ClassObject == null + || PrimitiveTypeWrapper.DOUBLE.ClassObject == null + || PrimitiveTypeWrapper.FLOAT.ClassObject == null + || PrimitiveTypeWrapper.INT.ClassObject == null + || PrimitiveTypeWrapper.LONG.ClassObject == null + || PrimitiveTypeWrapper.SHORT.ClassObject == null + || PrimitiveTypeWrapper.BOOLEAN.ClassObject == null + || PrimitiveTypeWrapper.VOID.ClassObject == null) + { + throw new InvalidOperationException(); + } + } +#endif + + internal static TypeWrapper FromClass(java.lang.Class clazz) + { +#if FIRST_PASS + return null; +#else + // MONOBUG redundant cast to workaround mcs bug + TypeWrapper tw = (TypeWrapper)(object)clazz.typeWrapper; + if(tw == null) + { + Type type = clazz.type; + if (type == null) + { + ResolvePrimitiveTypeWrapperClasses(); + return FromClass(clazz); + } + if (type == typeof(void) || type.IsPrimitive || ClassLoaderWrapper.IsRemappedType(type)) + { + tw = DotNetTypeWrapper.GetWrapperFromDotNetType(type); + } + else + { + tw = ClassLoaderWrapper.GetWrapperFromType(type); + } +#if __MonoCS__ + SetTypeWrapperHack(clazz, tw); +#else + clazz.typeWrapper = tw; +#endif + } + return tw; +#endif + } +#endif // !STATIC_COMPILER && !STUB_GENERATOR + + public override string ToString() + { + return GetType().Name + "[" + name + "]"; + } + + // For UnloadableTypeWrapper it tries to load the type through the specified loader + // and if that fails it throw a NoClassDefFoundError (not a java.lang.NoClassDefFoundError), + // for all other types this is a no-op. + internal virtual TypeWrapper EnsureLoadable(ClassLoaderWrapper loader) + { + return this; + } + + private void SetTypeFlag(TypeFlags flag) + { + // we use a global lock object, since the chance of contention is very small + lock (flagsLock) + { + flags |= flag; + } + } + + internal bool HasIncompleteInterfaceImplementation + { + get + { + TypeWrapper baseWrapper = this.BaseTypeWrapper; + return (flags & TypeFlags.HasIncompleteInterfaceImplementation) != 0 || (baseWrapper != null && baseWrapper.HasIncompleteInterfaceImplementation); + } + } + + internal void SetHasIncompleteInterfaceImplementation() + { + SetTypeFlag(TypeFlags.HasIncompleteInterfaceImplementation); + } + + internal bool HasUnsupportedAbstractMethods + { + get + { + foreach(TypeWrapper iface in this.Interfaces) + { + if(iface.HasUnsupportedAbstractMethods) + { + return true; + } + } + TypeWrapper baseWrapper = this.BaseTypeWrapper; + return (flags & TypeFlags.HasUnsupportedAbstractMethods) != 0 || (baseWrapper != null && baseWrapper.HasUnsupportedAbstractMethods); + } + } + + internal void SetHasUnsupportedAbstractMethods() + { + SetTypeFlag(TypeFlags.HasUnsupportedAbstractMethods); + } + + internal virtual bool HasStaticInitializer + { + get + { + return (flags & TypeFlags.HasStaticInitializer) != 0; + } + } + + internal void SetHasStaticInitializer() + { + SetTypeFlag(TypeFlags.HasStaticInitializer); + } + + internal bool HasVerifyError + { + get + { + return (flags & TypeFlags.VerifyError) != 0; + } + } + + internal void SetHasVerifyError() + { + SetTypeFlag(TypeFlags.VerifyError); + } + + internal bool HasClassFormatError + { + get + { + return (flags & TypeFlags.ClassFormatError) != 0; + } + } + + internal void SetHasClassFormatError() + { + SetTypeFlag(TypeFlags.ClassFormatError); + } + + internal virtual bool IsFakeTypeContainer + { + get + { + return false; + } + } + + internal virtual bool IsFakeNestedType + { + get + { + return false; + } + } + + // is this an anonymous class (in the sense of Unsafe.defineAnonymousClass(), not the JLS) + internal bool IsUnsafeAnonymous + { + get { return (flags & TypeFlags.Anonymous) != 0; } + } + + // a ghost is an interface that appears to be implemented by a .NET type + // (e.g. System.String (aka java.lang.String) appears to implement java.lang.CharSequence, + // so java.lang.CharSequence is a ghost) + internal virtual bool IsGhost + { + get + { + return false; + } + } + + // is this an array type of which the ultimate element type is a ghost? + internal bool IsGhostArray + { + get + { + return !IsUnloadable && IsArray && (ElementTypeWrapper.IsGhost || ElementTypeWrapper.IsGhostArray); + } + } + + internal virtual FieldInfo GhostRefField + { + get + { + throw new InvalidOperationException(); + } + } + + internal virtual bool IsRemapped + { + get + { + return false; + } + } + + internal bool IsArray + { + get + { + return name != null && name[0] == '['; + } + } + + // NOTE for non-array types this returns 0 + internal int ArrayRank + { + get + { + int i = 0; + if(name != null) + { + while(name[i] == '[') + { + i++; + } + } + return i; + } + } + + internal virtual TypeWrapper GetUltimateElementTypeWrapper() + { + throw new InvalidOperationException(); + } + + internal bool IsNonPrimitiveValueType + { + get + { + return this != VerifierTypeWrapper.Null && !IsPrimitive && !IsGhost && TypeAsTBD.IsValueType; + } + } + + internal bool IsPrimitive + { + get + { + return name == null; + } + } + + internal bool IsWidePrimitive + { + get + { + return this == PrimitiveTypeWrapper.LONG || this == PrimitiveTypeWrapper.DOUBLE; + } + } + + internal bool IsIntOnStackPrimitive + { + get + { + return name == null && + (this == PrimitiveTypeWrapper.BOOLEAN || + this == PrimitiveTypeWrapper.BYTE || + this == PrimitiveTypeWrapper.CHAR || + this == PrimitiveTypeWrapper.SHORT || + this == PrimitiveTypeWrapper.INT); + } + } + + private static bool IsJavaPrimitive(Type type) + { + return type == PrimitiveTypeWrapper.BOOLEAN.TypeAsTBD + || type == PrimitiveTypeWrapper.BYTE.TypeAsTBD + || type == PrimitiveTypeWrapper.CHAR.TypeAsTBD + || type == PrimitiveTypeWrapper.DOUBLE.TypeAsTBD + || type == PrimitiveTypeWrapper.FLOAT.TypeAsTBD + || type == PrimitiveTypeWrapper.INT.TypeAsTBD + || type == PrimitiveTypeWrapper.LONG.TypeAsTBD + || type == PrimitiveTypeWrapper.SHORT.TypeAsTBD + || type == PrimitiveTypeWrapper.VOID.TypeAsTBD; + } + + internal bool IsBoxedPrimitive + { + get + { + return !IsPrimitive && IsJavaPrimitive(TypeAsSignatureType); + } + } + + internal bool IsErasedOrBoxedPrimitiveOrRemapped + { + get + { + bool erased = IsUnloadable || IsGhostArray; + return erased || IsBoxedPrimitive || (IsRemapped && this is DotNetTypeWrapper); + } + } + + internal bool IsUnloadable + { + get + { + // NOTE we abuse modifiers to note unloadable classes + return modifiers == UnloadableModifiersHack; + } + } + + internal bool IsVerifierType + { + get + { + // NOTE we abuse modifiers to note verifier types + return modifiers == VerifierTypeModifiersHack; + } + } + + internal virtual bool IsMapUnsafeException + { + get + { + return false; + } + } + + internal Modifiers Modifiers + { + get + { + return modifiers; + } + } + + // since for inner classes, the modifiers returned by Class.getModifiers are different from the actual + // modifiers (as used by the VM access control mechanism), we have this additional property + internal virtual Modifiers ReflectiveModifiers + { + get + { + return modifiers; + } + } + + internal bool IsInternal + { + get + { + return (flags & TypeFlags.InternalAccess) != 0; + } + } + + internal bool IsPublic + { + get + { + return (modifiers & Modifiers.Public) != 0; + } + } + + internal bool IsAbstract + { + get + { + // interfaces don't need to marked abstract explicitly (and javac 1.1 didn't do it) + return (modifiers & (Modifiers.Abstract | Modifiers.Interface)) != 0; + } + } + + internal bool IsFinal + { + get + { + return (modifiers & Modifiers.Final) != 0; + } + } + + internal bool IsInterface + { + get + { + Debug.Assert(!IsUnloadable && !IsVerifierType); + return (modifiers & Modifiers.Interface) != 0; + } + } + + // this exists because interfaces and arrays of interfaces are treated specially + // by the verifier, interfaces don't have a common base (other than java.lang.Object) + // so any object reference or object array reference can be used where an interface + // or interface array reference is expected (the compiler will insert the required casts). + internal bool IsInterfaceOrInterfaceArray + { + get + { + TypeWrapper tw = this; + while(tw.IsArray) + { + tw = tw.ElementTypeWrapper; + } + return tw.IsInterface; + } + } + + internal abstract ClassLoaderWrapper GetClassLoader(); + + internal FieldWrapper GetFieldWrapper(string fieldName, string fieldSig) + { + foreach(FieldWrapper fw in GetFields()) + { + if(fw.Name == fieldName && fw.Signature == fieldSig) + { + return fw; + } + } + foreach(TypeWrapper iface in this.Interfaces) + { + FieldWrapper fw = iface.GetFieldWrapper(fieldName, fieldSig); + if(fw != null) + { + return fw; + } + } + TypeWrapper baseWrapper = this.BaseTypeWrapper; + if(baseWrapper != null) + { + return baseWrapper.GetFieldWrapper(fieldName, fieldSig); + } + return null; + } + + protected virtual void LazyPublishMembers() + { + if(methods == null) + { + methods = MethodWrapper.EmptyArray; + } + if(fields == null) + { + fields = FieldWrapper.EmptyArray; + } + } + + protected virtual void LazyPublishMethods() + { + LazyPublishMembers(); + } + + protected virtual void LazyPublishFields() + { + LazyPublishMembers(); + } + + internal MethodWrapper[] GetMethods() + { + if(methods == null) + { + lock(this) + { + if(methods == null) + { +#if STATIC_COMPILER + if(IsUnloadable || !CheckMissingBaseTypes(TypeAsBaseType)) + { + return methods = MethodWrapper.EmptyArray; + } +#endif + LazyPublishMethods(); + } + } + } + return methods; + } + + internal FieldWrapper[] GetFields() + { + if(fields == null) + { + lock(this) + { + if(fields == null) + { +#if STATIC_COMPILER + if(IsUnloadable || !CheckMissingBaseTypes(TypeAsBaseType)) + { + return fields = FieldWrapper.EmptyArray; + } +#endif + LazyPublishFields(); + } + } + } + return fields; + } + +#if STATIC_COMPILER + private static bool CheckMissingBaseTypes(Type type) + { + while (type != null) + { + if (type.__ContainsMissingType) + { + StaticCompiler.IssueMissingTypeMessage(type); + return false; + } + bool ok = true; + foreach (Type iface in type.__GetDeclaredInterfaces()) + { + ok &= CheckMissingBaseTypes(iface); + } + if (!ok) + { + return false; + } + type = type.BaseType; + } + return true; + } +#endif + + internal MethodWrapper GetMethodWrapper(string name, string sig, bool inherit) + { + // We need to get the methods before calling String.IsInterned, because getting them might cause the strings to be interned + MethodWrapper[] methods = GetMethods(); + // MemberWrapper interns the name and sig so we can use ref equality + // profiling has shown this to be more efficient + string _name = String.IsInterned(name); + string _sig = String.IsInterned(sig); + foreach(MethodWrapper mw in methods) + { + // NOTE we can use ref equality, because names and signatures are + // always interned by MemberWrapper + if(ReferenceEquals(mw.Name, _name) && ReferenceEquals(mw.Signature, _sig)) + { + return mw; + } + } + TypeWrapper baseWrapper = this.BaseTypeWrapper; + if(inherit && baseWrapper != null) + { + return baseWrapper.GetMethodWrapper(name, sig, inherit); + } + return null; + } + + internal MethodWrapper GetInterfaceMethod(string name, string sig) + { + MethodWrapper method = GetMethodWrapper(name, sig, false); + if (method != null) + { + return method; + } + TypeWrapper[] interfaces = Interfaces; + for (int i = 0; i < interfaces.Length; i++) + { + method = interfaces[i].GetInterfaceMethod(name, sig); + if (method != null) + { + return method; + } + } + return null; + } + + internal void SetMethods(MethodWrapper[] methods) + { + Debug.Assert(methods != null); + System.Threading.Thread.MemoryBarrier(); + this.methods = methods; + } + + internal void SetFields(FieldWrapper[] fields) + { + Debug.Assert(fields != null); + System.Threading.Thread.MemoryBarrier(); + this.fields = fields; + } + + internal string Name + { + get + { + return name; + } + } + + // the name of the type as it appears in a Java signature string (e.g. "Ljava.lang.Object;" or "I") + internal virtual string SigName + { + get + { + return "L" + this.Name + ";"; + } + } + + // returns true iff wrapper is allowed to access us + internal bool IsAccessibleFrom(TypeWrapper wrapper) + { + return IsPublic + || (IsInternal && InternalsVisibleTo(wrapper)) + || IsPackageAccessibleFrom(wrapper); + } + + internal bool InternalsVisibleTo(TypeWrapper wrapper) + { + return GetClassLoader().InternalsVisibleToImpl(this, wrapper); + } + + internal virtual bool IsPackageAccessibleFrom(TypeWrapper wrapper) + { + if (MatchingPackageNames(name, wrapper.name)) + { +#if STATIC_COMPILER + CompilerClassLoader ccl = GetClassLoader() as CompilerClassLoader; + if (ccl != null) + { + // this is a hack for multi target -sharedclassloader compilation + // (during compilation we have multiple CompilerClassLoader instances to represent the single shared runtime class loader) + return ccl.IsEquivalentTo(wrapper.GetClassLoader()); + } +#endif + return GetClassLoader() == wrapper.GetClassLoader(); + } + else + { + return false; + } + } + + private static bool MatchingPackageNames(string name1, string name2) + { + int index1 = name1.LastIndexOf('.'); + int index2 = name2.LastIndexOf('.'); + if (index1 == -1 && index2 == -1) + { + return true; + } + // for array types we need to skip the brackets + int skip1 = 0; + int skip2 = 0; + while (name1[skip1] == '[') + { + skip1++; + } + while (name2[skip2] == '[') + { + skip2++; + } + if (skip1 > 0) + { + // skip over the L that follows the brackets + skip1++; + } + if (skip2 > 0) + { + // skip over the L that follows the brackets + skip2++; + } + if ((index1 - skip1) != (index2 - skip2)) + { + return false; + } + return String.CompareOrdinal(name1, skip1, name2, skip2, index1 - skip1) == 0; + } + + internal abstract Type TypeAsTBD + { + get; + } + + internal Type TypeAsSignatureType + { + get + { + if(IsUnloadable) + { + return ((UnloadableTypeWrapper)this).MissingType ?? Types.Object; + } + if(IsGhostArray) + { + return ArrayTypeWrapper.MakeArrayType(Types.Object, ArrayRank); + } + return TypeAsTBD; + } + } + + internal Type TypeAsPublicSignatureType + { + get + { + return (IsPublic ? this : GetPublicBaseTypeWrapper()).TypeAsSignatureType; + } + } + + internal virtual Type TypeAsBaseType + { + get + { + return TypeAsTBD; + } + } + + internal Type TypeAsLocalOrStackType + { + get + { + if(IsUnloadable || IsGhost) + { + return Types.Object; + } + if(IsNonPrimitiveValueType) + { + // return either System.ValueType or System.Enum + return TypeAsTBD.BaseType; + } + if(IsGhostArray) + { + return ArrayTypeWrapper.MakeArrayType(Types.Object, ArrayRank); + } + return TypeAsTBD; + } + } + + /** Use this if the type is used as an array or array element */ + internal Type TypeAsArrayType + { + get + { + if(IsUnloadable || IsGhost) + { + return Types.Object; + } + if(IsGhostArray) + { + return ArrayTypeWrapper.MakeArrayType(Types.Object, ArrayRank); + } + return TypeAsTBD; + } + } + + internal Type TypeAsExceptionType + { + get + { + if(IsUnloadable) + { + return Types.Exception; + } + return TypeAsTBD; + } + } + + internal abstract TypeWrapper BaseTypeWrapper + { + get; + } + + internal TypeWrapper ElementTypeWrapper + { + get + { + Debug.Assert(!this.IsUnloadable); + Debug.Assert(this == VerifierTypeWrapper.Null || this.IsArray); + + if(this == VerifierTypeWrapper.Null) + { + return VerifierTypeWrapper.Null; + } + + // TODO consider caching the element type + switch(name[1]) + { + case '[': + // NOTE this call to LoadClassByDottedNameFast can never fail and will not trigger a class load + // (because the ultimate element type was already loaded when this type was created) + return GetClassLoader().LoadClassByDottedNameFast(name.Substring(1)); + case 'L': + // NOTE this call to LoadClassByDottedNameFast can never fail and will not trigger a class load + // (because the ultimate element type was already loaded when this type was created) + return GetClassLoader().LoadClassByDottedNameFast(name.Substring(2, name.Length - 3)); + case 'Z': + return PrimitiveTypeWrapper.BOOLEAN; + case 'B': + return PrimitiveTypeWrapper.BYTE; + case 'S': + return PrimitiveTypeWrapper.SHORT; + case 'C': + return PrimitiveTypeWrapper.CHAR; + case 'I': + return PrimitiveTypeWrapper.INT; + case 'J': + return PrimitiveTypeWrapper.LONG; + case 'F': + return PrimitiveTypeWrapper.FLOAT; + case 'D': + return PrimitiveTypeWrapper.DOUBLE; + default: + throw new InvalidOperationException(name); + } + } + } + + internal TypeWrapper MakeArrayType(int rank) + { + Debug.Assert(rank != 0); + // NOTE this call to LoadClassByDottedNameFast can never fail and will not trigger a class load + return GetClassLoader().LoadClassByDottedNameFast(new String('[', rank) + this.SigName); + } + + internal bool ImplementsInterface(TypeWrapper interfaceWrapper) + { + TypeWrapper typeWrapper = this; + while(typeWrapper != null) + { + TypeWrapper[] interfaces = typeWrapper.Interfaces; + for(int i = 0; i < interfaces.Length; i++) + { + if(interfaces[i] == interfaceWrapper) + { + return true; + } + if(interfaces[i].ImplementsInterface(interfaceWrapper)) + { + return true; + } + } + typeWrapper = typeWrapper.BaseTypeWrapper; + } + return false; + } + + internal bool IsSubTypeOf(TypeWrapper baseType) + { + // make sure IsSubTypeOf isn't used on primitives + Debug.Assert(!this.IsPrimitive); + Debug.Assert(!baseType.IsPrimitive); + // can't be used on Unloadable + Debug.Assert(!this.IsUnloadable); + Debug.Assert(!baseType.IsUnloadable); + + if(baseType.IsInterface) + { + if(baseType == this) + { + return true; + } + return ImplementsInterface(baseType); + } + // NOTE this isn't just an optimization, it is also required when this is an interface + if(baseType == CoreClasses.java.lang.Object.Wrapper) + { + return true; + } + TypeWrapper subType = this; + while(subType != baseType) + { + subType = subType.BaseTypeWrapper; + if(subType == null) + { + return false; + } + } + return true; + } + + internal bool IsAssignableTo(TypeWrapper wrapper) + { + if(this == wrapper) + { + return true; + } + if(this.IsPrimitive || wrapper.IsPrimitive) + { + return false; + } + if(this == VerifierTypeWrapper.Null) + { + return true; + } + if(wrapper.IsInterface) + { + return ImplementsInterface(wrapper); + } + int rank1 = this.ArrayRank; + int rank2 = wrapper.ArrayRank; + if(rank1 > 0 && rank2 > 0) + { + rank1--; + rank2--; + TypeWrapper elem1 = this.ElementTypeWrapper; + TypeWrapper elem2 = wrapper.ElementTypeWrapper; + while(rank1 != 0 && rank2 != 0) + { + elem1 = elem1.ElementTypeWrapper; + elem2 = elem2.ElementTypeWrapper; + rank1--; + rank2--; + } + if(elem1.IsPrimitive || elem2.IsPrimitive) + { + return false; + } + return (!elem1.IsNonPrimitiveValueType && elem1.IsSubTypeOf(elem2)); + } + return this.IsSubTypeOf(wrapper); + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal bool IsInstance(object obj) + { + if(obj != null) + { + TypeWrapper thisWrapper = this; + TypeWrapper objWrapper = IKVM.NativeCode.ikvm.runtime.Util.GetTypeWrapperFromObject(obj); + return objWrapper.IsAssignableTo(thisWrapper); + } + return false; + } +#endif + + internal virtual TypeWrapper[] Interfaces + { + get { return EmptyArray; } + } + + // NOTE this property can only be called for finished types! + internal virtual TypeWrapper[] InnerClasses + { + get { return EmptyArray; } + } + + // NOTE this property can only be called for finished types! + internal virtual TypeWrapper DeclaringTypeWrapper + { + get { return null; } + } + + internal virtual void Finish() + { + } + + internal void LinkAll() + { + if ((flags & TypeFlags.Linked) == 0) + { + TypeWrapper tw = BaseTypeWrapper; + if (tw != null) + { + tw.LinkAll(); + } + foreach (TypeWrapper iface in Interfaces) + { + iface.LinkAll(); + } + foreach (MethodWrapper mw in GetMethods()) + { + mw.Link(); + } + foreach (FieldWrapper fw in GetFields()) + { + fw.Link(); + } + SetTypeFlag(TypeFlags.Linked); + } + } + +#if !STATIC_COMPILER + [Conditional("DEBUG")] + internal static void AssertFinished(Type type) + { + if(type != null) + { + while(type.HasElementType) + { + type = type.GetElementType(); + } + Debug.Assert(!(type is TypeBuilder)); + } + } +#endif + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal void RunClassInit() + { + Type t = IsRemapped ? TypeAsBaseType : TypeAsTBD; + if(t != null) + { + System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(t.TypeHandle); + } + } +#endif + +#if EMITTERS + internal void EmitUnbox(CodeEmitter ilgen) + { + Debug.Assert(this.IsNonPrimitiveValueType); + + ilgen.EmitUnboxSpecial(this.TypeAsTBD); + } + + internal void EmitBox(CodeEmitter ilgen) + { + Debug.Assert(this.IsNonPrimitiveValueType); + + ilgen.Emit(OpCodes.Box, this.TypeAsTBD); + } + + internal void EmitConvSignatureTypeToStackType(CodeEmitter ilgen) + { + if(IsUnloadable) + { + } + else if(this == PrimitiveTypeWrapper.BYTE) + { + ilgen.Emit(OpCodes.Conv_I1); + } + else if(IsNonPrimitiveValueType) + { + EmitBox(ilgen); + } + else if(IsGhost) + { + CodeEmitterLocal local = ilgen.DeclareLocal(TypeAsSignatureType); + ilgen.Emit(OpCodes.Stloc, local); + ilgen.Emit(OpCodes.Ldloca, local); + ilgen.Emit(OpCodes.Ldfld, GhostRefField); + } + } + + // NOTE sourceType is optional and only used for interfaces, + // it is *not* used to automatically downcast + internal void EmitConvStackTypeToSignatureType(CodeEmitter ilgen, TypeWrapper sourceType) + { + if(!IsUnloadable) + { + if(IsGhost) + { + CodeEmitterLocal local1 = ilgen.DeclareLocal(TypeAsLocalOrStackType); + ilgen.Emit(OpCodes.Stloc, local1); + CodeEmitterLocal local2 = ilgen.DeclareLocal(TypeAsSignatureType); + ilgen.Emit(OpCodes.Ldloca, local2); + ilgen.Emit(OpCodes.Ldloc, local1); + ilgen.Emit(OpCodes.Stfld, GhostRefField); + ilgen.Emit(OpCodes.Ldloca, local2); + ilgen.Emit(OpCodes.Ldobj, TypeAsSignatureType); + } + // because of the way interface merging works, any reference is valid + // for any interface reference + else if(IsInterfaceOrInterfaceArray && (sourceType == null || sourceType.IsUnloadable || !sourceType.IsAssignableTo(this))) + { + ilgen.EmitAssertType(TypeAsTBD); + Profiler.Count("InterfaceDownCast"); + } + else if(IsNonPrimitiveValueType) + { + EmitUnbox(ilgen); + } + else if(sourceType != null && sourceType.IsUnloadable) + { + ilgen.Emit(OpCodes.Castclass, TypeAsSignatureType); + } + } + } + + internal virtual void EmitCheckcast(CodeEmitter ilgen) + { + if(IsGhost) + { + ilgen.Emit(OpCodes.Dup); + // TODO make sure we get the right "Cast" method and cache it + // NOTE for dynamic ghosts we don't end up here because AotTypeWrapper overrides this method, + // so we're safe to call GetMethod on TypeAsTBD (because it has to be a compiled type, if we're here) + ilgen.Emit(OpCodes.Call, TypeAsTBD.GetMethod("Cast")); + ilgen.Emit(OpCodes.Pop); + } + else if(IsGhostArray) + { + ilgen.Emit(OpCodes.Dup); + // TODO make sure we get the right "CastArray" method and cache it + // NOTE for dynamic ghosts we don't end up here because AotTypeWrapper overrides this method, + // so we're safe to call GetMethod on TypeAsTBD (because it has to be a compiled type, if we're here) + TypeWrapper tw = this; + int rank = 0; + while(tw.IsArray) + { + rank++; + tw = tw.ElementTypeWrapper; + } + ilgen.EmitLdc_I4(rank); + ilgen.Emit(OpCodes.Call, tw.TypeAsTBD.GetMethod("CastArray")); + ilgen.Emit(OpCodes.Castclass, ArrayTypeWrapper.MakeArrayType(Types.Object, rank)); + } + else + { + ilgen.EmitCastclass(TypeAsTBD); + } + } + + internal virtual void EmitInstanceOf(CodeEmitter ilgen) + { + if(IsGhost) + { + // TODO make sure we get the right "IsInstance" method and cache it + // NOTE for dynamic ghosts we don't end up here because DynamicTypeWrapper overrides this method, + // so we're safe to call GetMethod on TypeAsTBD (because it has to be a compiled type, if we're here) + ilgen.Emit(OpCodes.Call, TypeAsTBD.GetMethod("IsInstance")); + } + else if(IsGhostArray) + { + // TODO make sure we get the right "IsInstanceArray" method and cache it + // NOTE for dynamic ghosts we don't end up here because DynamicTypeWrapper overrides this method, + // so we're safe to call GetMethod on TypeAsTBD (because it has to be a compiled type, if we're here) + TypeWrapper tw = this; + int rank = 0; + while(tw.IsArray) + { + rank++; + tw = tw.ElementTypeWrapper; + } + ilgen.EmitLdc_I4(rank); + ilgen.Emit(OpCodes.Call, tw.TypeAsTBD.GetMethod("IsInstanceArray")); + } + else + { + ilgen.Emit_instanceof(TypeAsTBD); + } + } +#endif // EMITTERS + + // NOTE don't call this method, call MethodWrapper.Link instead + internal virtual MethodBase LinkMethod(MethodWrapper mw) + { + return mw.GetMethod(); + } + + // NOTE don't call this method, call FieldWrapper.Link instead + internal virtual FieldInfo LinkField(FieldWrapper fw) + { + return fw.GetField(); + } + +#if EMITTERS + internal virtual void EmitRunClassConstructor(CodeEmitter ilgen) + { + } +#endif // EMITTERS + + internal virtual string GetGenericSignature() + { + return null; + } + + internal virtual string GetGenericMethodSignature(MethodWrapper mw) + { + return null; + } + + internal virtual string GetGenericFieldSignature(FieldWrapper fw) + { + return null; + } + + internal virtual MethodParametersEntry[] GetMethodParameters(MethodWrapper mw) + { + return null; + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal virtual string[] GetEnclosingMethod() + { + return null; + } + + internal virtual object[] GetDeclaredAnnotations() + { + return null; + } + + internal virtual object[] GetMethodAnnotations(MethodWrapper mw) + { + return null; + } + + internal virtual object[][] GetParameterAnnotations(MethodWrapper mw) + { + return null; + } + + internal virtual object[] GetFieldAnnotations(FieldWrapper fw) + { + return null; + } + + internal virtual string GetSourceFileName() + { + return null; + } + + internal virtual int GetSourceLineNumber(MethodBase mb, int ilOffset) + { + return -1; + } + + internal virtual object GetAnnotationDefault(MethodWrapper mw) + { + MethodBase mb = mw.GetMethod(); + if(mb != null) + { + object[] attr = mb.GetCustomAttributes(typeof(AnnotationDefaultAttribute), false); + if(attr.Length == 1) + { + return JVM.NewAnnotationElementValue(mw.DeclaringType.GetClassLoader().GetJavaClassLoader(), mw.ReturnType.ClassObject, ((AnnotationDefaultAttribute)attr[0]).Value); + } + } + return null; + } +#endif // !STATIC_COMPILER && !STUB_GENERATOR + + internal virtual Annotation Annotation + { + get + { + return null; + } + } + + internal virtual Type EnumType + { + get + { + return null; + } + } + + private static Type[] GetInterfaces(Type type) + { +#if STATIC_COMPILER || STUB_GENERATOR + List list = new List(); + for (; type != null && !type.__IsMissing; type = type.BaseType) + { + AddInterfaces(list, type); + } + return list.ToArray(); +#else + return type.GetInterfaces(); +#endif + } + +#if STATIC_COMPILER || STUB_GENERATOR + private static void AddInterfaces(List list, Type type) + { + foreach (Type iface in type.__GetDeclaredInterfaces()) + { + if (!list.Contains(iface)) + { + list.Add(iface); + if (!iface.__IsMissing) + { + AddInterfaces(list, iface); + } + } + } + } +#endif + + protected static TypeWrapper[] GetImplementedInterfacesAsTypeWrappers(Type type) + { + Type[] interfaceTypes = GetInterfaces(type); + TypeWrapper[] interfaces = new TypeWrapper[interfaceTypes.Length]; + for (int i = 0; i < interfaceTypes.Length; i++) + { + Type decl = interfaceTypes[i].DeclaringType; + if (decl != null && AttributeHelper.IsGhostInterface(decl)) + { + // we have to return the declaring type for ghost interfaces + interfaces[i] = ClassLoaderWrapper.GetWrapperFromType(decl); + } + else + { + interfaces[i] = ClassLoaderWrapper.GetWrapperFromType(interfaceTypes[i]); + } + } + for (int i = 0; i < interfaceTypes.Length; i++) + { + if (interfaces[i].IsRemapped) + { + // for remapped interfaces, we also return the original interface (Java types will ignore it, if it isn't listed in the ImplementsAttribute) + TypeWrapper twRemapped = interfaces[i]; + TypeWrapper tw = DotNetTypeWrapper.GetWrapperFromDotNetType(interfaceTypes[i]); + interfaces[i] = tw; + if (Array.IndexOf(interfaces, twRemapped) == -1) + { + interfaces = ArrayUtil.Concat(interfaces, twRemapped); + } + } + } + return interfaces; + } + + internal TypeWrapper GetPublicBaseTypeWrapper() + { + Debug.Assert(!this.IsPublic); + if (this.IsUnloadable || this.IsInterface) + { + return CoreClasses.java.lang.Object.Wrapper; + } + for (TypeWrapper tw = this; ; tw = tw.BaseTypeWrapper) + { + if (tw.IsPublic) + { + return tw; + } + } + } + +#if !STUB_GENERATOR + // return the constructor used for automagic .NET serialization + internal virtual MethodBase GetSerializationConstructor() + { + return this.TypeAsBaseType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { + JVM.Import(typeof(System.Runtime.Serialization.SerializationInfo)), JVM.Import(typeof(System.Runtime.Serialization.StreamingContext)) }, null); + } + + internal virtual MethodBase GetBaseSerializationConstructor() + { + return BaseTypeWrapper.GetSerializationConstructor(); + } +#endif + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal virtual object GhostWrap(object obj) + { + return obj; + } + + internal virtual object GhostUnwrap(object obj) + { + return obj; + } +#endif + + internal bool IsDynamic + { +#if STUB_GENERATOR + get { return false; } +#else + get { return this is DynamicTypeWrapper; } +#endif + } + + internal virtual object[] GetConstantPool() + { + return null; + } + + internal virtual byte[] GetRawTypeAnnotations() + { + return null; + } + + internal virtual byte[] GetMethodRawTypeAnnotations(MethodWrapper mw) + { + return null; + } + + internal virtual byte[] GetFieldRawTypeAnnotations(FieldWrapper fw) + { + return null; + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal virtual TypeWrapper Host + { + get { return null; } + } +#endif + } + + sealed class UnloadableTypeWrapper : TypeWrapper + { + internal const string ContainerTypeName = "__"; + private readonly Type missingType; + private Type customModifier; + + internal UnloadableTypeWrapper(string name) + : base(TypeFlags.None, TypeWrapper.UnloadableModifiersHack, name) + { + } + + internal UnloadableTypeWrapper(Type missingType) + : this(missingType.FullName) // TODO demangle and re-mangle appropriately + { + this.missingType = missingType; + } + + internal UnloadableTypeWrapper(string name, Type customModifier) + : this(name) + { + this.customModifier = customModifier; + } + + internal override TypeWrapper BaseTypeWrapper + { + get { return null; } + } + + internal override ClassLoaderWrapper GetClassLoader() + { + return null; + } + + internal override TypeWrapper EnsureLoadable(ClassLoaderWrapper loader) + { + TypeWrapper tw = loader.LoadClassByDottedNameFast(this.Name); + if(tw == null) + { + throw new NoClassDefFoundError(this.Name); + } + return tw; + } + + internal override string SigName + { + get + { + string name = Name; + if(name.StartsWith("[")) + { + return name; + } + return "L" + name + ";"; + } + } + + protected override void LazyPublishMembers() + { + throw new InvalidOperationException("LazyPublishMembers called on UnloadableTypeWrapper: " + Name); + } + + internal override Type TypeAsTBD + { + get + { + throw new InvalidOperationException("get_Type called on UnloadableTypeWrapper: " + Name); + } + } + + internal override TypeWrapper[] Interfaces + { + get + { +#if STATIC_COMPILER + if (missingType != null) + { + StaticCompiler.IssueMissingTypeMessage(missingType); + return TypeWrapper.EmptyArray; + } +#endif + throw new InvalidOperationException("get_Interfaces called on UnloadableTypeWrapper: " + Name); + } + } + + internal override TypeWrapper[] InnerClasses + { + get + { + throw new InvalidOperationException("get_InnerClasses called on UnloadableTypeWrapper: " + Name); + } + } + + internal override TypeWrapper DeclaringTypeWrapper + { + get + { + throw new InvalidOperationException("get_DeclaringTypeWrapper called on UnloadableTypeWrapper: " + Name); + } + } + + internal override void Finish() + { + throw new InvalidOperationException("Finish called on UnloadableTypeWrapper: " + Name); + } + + internal Type MissingType + { + get { return missingType; } + } + + internal Type CustomModifier + { + get { return customModifier; } + } + + internal void SetCustomModifier(Type type) + { + this.customModifier = type; + } + +#if EMITTERS + internal Type GetCustomModifier(TypeWrapperFactory context) + { + // we don't need to lock, because we're only supposed to be called while holding the finish lock + return customModifier ?? (customModifier = context.DefineUnloadable(this.Name)); + } + + internal override void EmitCheckcast(CodeEmitter ilgen) + { + throw new InvalidOperationException("EmitCheckcast called on UnloadableTypeWrapper: " + Name); + } + + internal override void EmitInstanceOf(CodeEmitter ilgen) + { + throw new InvalidOperationException("EmitInstanceOf called on UnloadableTypeWrapper: " + Name); + } +#endif // EMITTERS + } + + sealed class PrimitiveTypeWrapper : TypeWrapper + { + internal static readonly PrimitiveTypeWrapper BYTE = new PrimitiveTypeWrapper(Types.Byte, "B"); + internal static readonly PrimitiveTypeWrapper CHAR = new PrimitiveTypeWrapper(Types.Char, "C"); + internal static readonly PrimitiveTypeWrapper DOUBLE = new PrimitiveTypeWrapper(Types.Double, "D"); + internal static readonly PrimitiveTypeWrapper FLOAT = new PrimitiveTypeWrapper(Types.Single, "F"); + internal static readonly PrimitiveTypeWrapper INT = new PrimitiveTypeWrapper(Types.Int32, "I"); + internal static readonly PrimitiveTypeWrapper LONG = new PrimitiveTypeWrapper(Types.Int64, "J"); + internal static readonly PrimitiveTypeWrapper SHORT = new PrimitiveTypeWrapper(Types.Int16, "S"); + internal static readonly PrimitiveTypeWrapper BOOLEAN = new PrimitiveTypeWrapper(Types.Boolean, "Z"); + internal static readonly PrimitiveTypeWrapper VOID = new PrimitiveTypeWrapper(Types.Void, "V"); + + private readonly Type type; + private readonly string sigName; + + private PrimitiveTypeWrapper(Type type, string sigName) + : base(TypeFlags.None, Modifiers.Public | Modifiers.Abstract | Modifiers.Final, null) + { + this.type = type; + this.sigName = sigName; + } + + internal override TypeWrapper BaseTypeWrapper + { + get { return null; } + } + + internal static bool IsPrimitiveType(Type type) + { + return type == BYTE.type + || type == CHAR.type + || type == DOUBLE.type + || type == FLOAT.type + || type == INT.type + || type == LONG.type + || type == SHORT.type + || type == BOOLEAN.type + || type == VOID.type; + } + + internal override string SigName + { + get + { + return sigName; + } + } + + internal override ClassLoaderWrapper GetClassLoader() + { + return ClassLoaderWrapper.GetBootstrapClassLoader(); + } + + internal override Type TypeAsTBD + { + get + { + return type; + } + } + + public override string ToString() + { + return "PrimitiveTypeWrapper[" + sigName + "]"; + } + } + + class CompiledTypeWrapper : TypeWrapper + { + private readonly Type type; + private TypeWrapper baseTypeWrapper = VerifierTypeWrapper.Null; + private volatile TypeWrapper[] interfaces; + private MethodInfo clinitMethod; + private volatile bool clinitMethodSet; + private Modifiers reflectiveModifiers; + + internal static CompiledTypeWrapper newInstance(string name, Type type) + { + // TODO since ghost and remapped types can only exist in the core library assembly, we probably + // should be able to remove the Type.IsDefined() tests in most cases + if(type.IsValueType && AttributeHelper.IsGhostInterface(type)) + { + return new CompiledGhostTypeWrapper(name, type); + } + else if(AttributeHelper.IsRemappedType(type)) + { + return new CompiledRemappedTypeWrapper(name, type); + } + else + { + return new CompiledTypeWrapper(name, type); + } + } + + private sealed class CompiledRemappedTypeWrapper : CompiledTypeWrapper + { + private readonly Type remappedType; + + internal CompiledRemappedTypeWrapper(string name, Type type) + : base(name, type) + { + RemappedTypeAttribute attr = AttributeHelper.GetRemappedType(type); + if(attr == null) + { + throw new InvalidOperationException(); + } + remappedType = attr.Type; + } + + internal override Type TypeAsTBD + { + get + { + return remappedType; + } + } + + internal override bool IsRemapped + { + get + { + return true; + } + } + + protected override void LazyPublishMethods() + { + List list = new List(); + const BindingFlags bindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance; + foreach(ConstructorInfo ctor in type.GetConstructors(bindingFlags)) + { + AddMethod(list, ctor); + } + foreach(MethodInfo method in type.GetMethods(bindingFlags)) + { + AddMethod(list, method); + } + // if we're a remapped interface, we need to get the methods from the real interface + if(remappedType.IsInterface) + { + Type nestedHelper = type.GetNestedType("__Helper", BindingFlags.Public | BindingFlags.Static); + foreach(RemappedInterfaceMethodAttribute m in AttributeHelper.GetRemappedInterfaceMethods(type)) + { + MethodInfo method = remappedType.GetMethod(m.MappedTo); + MethodInfo mbHelper = method; + ExModifiers modifiers = AttributeHelper.GetModifiers(method, false); + string name; + string sig; + TypeWrapper retType; + TypeWrapper[] paramTypes; + MemberFlags flags = MemberFlags.None; + GetNameSigFromMethodBase(method, out name, out sig, out retType, out paramTypes, ref flags); + if(nestedHelper != null) + { + mbHelper = nestedHelper.GetMethod(m.Name); + if(mbHelper == null) + { + mbHelper = method; + } + } + MethodWrapper mw = new CompiledRemappedMethodWrapper(this, m.Name, sig, method, retType, paramTypes, modifiers, false, mbHelper, null); + mw.SetDeclaredExceptions(m.Throws); + list.Add(mw); + } + } + SetMethods(list.ToArray()); + } + + private void AddMethod(List list, MethodBase method) + { + HideFromJavaFlags flags = AttributeHelper.GetHideFromJavaFlags(method); + if((flags & HideFromJavaFlags.Code) == 0 + && (remappedType.IsSealed || !method.Name.StartsWith("instancehelper_")) + && (!remappedType.IsSealed || method.IsStatic)) + { + list.Add(CreateRemappedMethodWrapper(method, flags)); + } + } + + protected override void LazyPublishFields() + { + List list = new List(); + FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + foreach(FieldInfo field in fields) + { + HideFromJavaFlags hideFromJavaFlags = AttributeHelper.GetHideFromJavaFlags(field); + if((hideFromJavaFlags & HideFromJavaFlags.Code) == 0) + { + list.Add(CreateFieldWrapper(field, hideFromJavaFlags)); + } + } + SetFields(list.ToArray()); + } + + private MethodWrapper CreateRemappedMethodWrapper(MethodBase mb, HideFromJavaFlags hideFromJavaflags) + { + ExModifiers modifiers = AttributeHelper.GetModifiers(mb, false); + string name; + string sig; + TypeWrapper retType; + TypeWrapper[] paramTypes; + MemberFlags flags = MemberFlags.None; + GetNameSigFromMethodBase(mb, out name, out sig, out retType, out paramTypes, ref flags); + MethodInfo mbHelper = mb as MethodInfo; + bool hideFromReflection = mbHelper != null && (hideFromJavaflags & HideFromJavaFlags.Reflection) != 0; + MethodInfo mbNonvirtualHelper = null; + if(!mb.IsStatic && !mb.IsConstructor) + { + ParameterInfo[] parameters = mb.GetParameters(); + Type[] argTypes = new Type[parameters.Length + 1]; + argTypes[0] = remappedType; + for(int i = 0; i < parameters.Length; i++) + { + argTypes[i + 1] = parameters[i].ParameterType; + } + MethodInfo helper = type.GetMethod("instancehelper_" + mb.Name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, null, argTypes, null); + if(helper != null) + { + mbHelper = helper; + } + mbNonvirtualHelper = type.GetMethod("nonvirtualhelper/" + mb.Name, BindingFlags.NonPublic | BindingFlags.Static, null, argTypes, null); + } + return new CompiledRemappedMethodWrapper(this, name, sig, mb, retType, paramTypes, modifiers, hideFromReflection, mbHelper, mbNonvirtualHelper); + } + } + + private sealed class CompiledGhostTypeWrapper : CompiledTypeWrapper + { + private volatile FieldInfo ghostRefField; + private volatile Type typeAsBaseType; + + internal CompiledGhostTypeWrapper(string name, Type type) + : base(name, type) + { + } + + internal override Type TypeAsBaseType + { + get + { + if(typeAsBaseType == null) + { + typeAsBaseType = type.GetNestedType("__Interface"); + } + return typeAsBaseType; + } + } + + internal override FieldInfo GhostRefField + { + get + { + if(ghostRefField == null) + { + ghostRefField = type.GetField("__"); + } + return ghostRefField; + } + } + + internal override bool IsGhost + { + get + { + return true; + } + } + +#if !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS + internal override object GhostWrap(object obj) + { + return type.GetMethod("Cast").Invoke(null, new object[] { obj }); + } + + internal override object GhostUnwrap(object obj) + { + return type.GetMethod("ToObject").Invoke(obj, new object[0]); + } +#endif + } + + internal static string GetName(Type type) + { + Debug.Assert(!type.HasElementType); + Debug.Assert(!type.IsGenericType); + Debug.Assert(AttributeHelper.IsJavaModule(type.Module)); + + // look for our custom attribute, that contains the real name of the type (for inner classes) + InnerClassAttribute attr = AttributeHelper.GetInnerClass(type); + if(attr != null) + { + string name = attr.InnerClassName; + if(name != null) + { + return name; + } + } + if(type.DeclaringType != null) + { + return GetName(type.DeclaringType) + "$" + TypeNameUtil.Unescape(type.Name); + } + return TypeNameUtil.Unescape(type.FullName); + } + + private static TypeWrapper GetBaseTypeWrapper(Type type) + { + if(type.IsInterface || AttributeHelper.IsGhostInterface(type)) + { + return null; + } + else if(type.BaseType == null) + { + // System.Object must appear to be derived from java.lang.Object + return CoreClasses.java.lang.Object.Wrapper; + } + else + { + RemappedTypeAttribute attr = AttributeHelper.GetRemappedType(type); + if(attr != null) + { + if(attr.Type == Types.Object) + { + return null; + } + else + { + return CoreClasses.java.lang.Object.Wrapper; + } + } + else if(ClassLoaderWrapper.IsRemappedType(type.BaseType)) + { + // if we directly extend System.Object or System.Exception, the base class must be cli.System.Object or cli.System.Exception + return DotNetTypeWrapper.GetWrapperFromDotNetType(type.BaseType); + } + TypeWrapper tw = null; + while(tw == null) + { + type = type.BaseType; + tw = ClassLoaderWrapper.GetWrapperFromType(type); + } + return tw; + } + } + + private CompiledTypeWrapper(ExModifiers exmod, string name) + : base(exmod.IsInternal ? TypeFlags.InternalAccess : TypeFlags.None, exmod.Modifiers, name) + { + } + + private CompiledTypeWrapper(string name, Type type) + : this(GetModifiers(type), name) + { + Debug.Assert(!(type is TypeBuilder)); + Debug.Assert(!type.Name.EndsWith("[]")); + + this.type = type; + } + + internal override TypeWrapper BaseTypeWrapper + { + get + { + if (baseTypeWrapper != VerifierTypeWrapper.Null) + { + return baseTypeWrapper; + } + return baseTypeWrapper = GetBaseTypeWrapper(type); + } + } + + internal override ClassLoaderWrapper GetClassLoader() + { + return AssemblyClassLoader.FromAssembly(type.Assembly); + } + + private static ExModifiers GetModifiers(Type type) + { + ModifiersAttribute attr = AttributeHelper.GetModifiersAttribute(type); + if(attr != null) + { + return new ExModifiers(attr.Modifiers, attr.IsInternal); + } + // only returns public, protected, private, final, static, abstract and interface (as per + // the documentation of Class.getModifiers()) + Modifiers modifiers = 0; + if(type.IsPublic || type.IsNestedPublic) + { + modifiers |= Modifiers.Public; + } + if(type.IsSealed) + { + modifiers |= Modifiers.Final; + } + if(type.IsAbstract) + { + modifiers |= Modifiers.Abstract; + } + if(type.IsInterface) + { + modifiers |= Modifiers.Interface; + } + else + { + modifiers |= Modifiers.Super; + } + return new ExModifiers(modifiers, false); + } + + internal override bool HasStaticInitializer + { + get + { + if(!clinitMethodSet) + { + try + { + clinitMethod = type.GetMethod("__", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); + } +#if STATIC_COMPILER + catch (IKVM.Reflection.MissingMemberException) { } +#endif + finally { } + clinitMethodSet = true; + } + return clinitMethod != null; + } + } + + internal override TypeWrapper[] Interfaces + { + get + { + if(interfaces == null) + { + interfaces = GetInterfaces(); + } + return interfaces; + } + } + + private TypeWrapper[] GetInterfaces() + { + // NOTE instead of getting the interfaces list from Type, we use a custom + // attribute to list the implemented interfaces, because Java reflection only + // reports the interfaces *directly* implemented by the type, not the inherited + // interfaces. This is significant for serialVersionUID calculation (for example). + ImplementsAttribute attr = AttributeHelper.GetImplements(type); + if (attr == null) + { + if (BaseTypeWrapper == CoreClasses.java.lang.Object.Wrapper) + { + return GetImplementedInterfacesAsTypeWrappers(type); + } + return TypeWrapper.EmptyArray; + } + string[] interfaceNames = attr.Interfaces; + TypeWrapper[] interfaceWrappers = new TypeWrapper[interfaceNames.Length]; + if (this.IsRemapped) + { + for (int i = 0; i < interfaceWrappers.Length; i++) + { + interfaceWrappers[i] = ClassLoaderWrapper.LoadClassCritical(interfaceNames[i]); + } + } + else + { + TypeWrapper[] typeWrappers = GetImplementedInterfacesAsTypeWrappers(type); + for (int i = 0; i < interfaceWrappers.Length; i++) + { + for (int j = 0; j < typeWrappers.Length; j++) + { + if (typeWrappers[j].Name == interfaceNames[i]) + { + interfaceWrappers[i] = typeWrappers[j]; + break; + } + } + if (interfaceWrappers[i] == null) + { +#if STATIC_COMPILER + throw new FatalCompilerErrorException(Message.UnableToResolveInterface, interfaceNames[i], this); +#else + JVM.CriticalFailure("Unable to resolve interface " + interfaceNames[i] + " on type " + this, null); +#endif + } + } + } + return interfaceWrappers; + } + + private static bool IsNestedTypeAnonymousOrLocalClass(Type type) + { + switch (type.Attributes & (TypeAttributes.SpecialName | TypeAttributes.VisibilityMask)) + { + case TypeAttributes.SpecialName | TypeAttributes.NestedPublic: + case TypeAttributes.SpecialName | TypeAttributes.NestedAssembly: + return AttributeHelper.HasEnclosingMethodAttribute(type); + default: + return false; + } + } + + private static bool IsAnnotationAttribute(Type type) + { + return type.Name.EndsWith("Attribute", StringComparison.Ordinal) + && type.IsClass + && type.BaseType.FullName == "ikvm.internal.AnnotationAttributeBase"; + } + + internal override TypeWrapper[] InnerClasses + { + get + { + List wrappers = new List(); + foreach(Type nested in type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)) + { + if(IsAnnotationAttribute(nested)) + { + // HACK it's the custom attribute we generated for a corresponding annotation, so we shouldn't surface it as an inner classes + // (we can't put a HideFromJavaAttribute on it, because we do want the class to be visible as a $Proxy) + } + else if(IsNestedTypeAnonymousOrLocalClass(nested)) + { + // anonymous and local classes are not reported as inner classes + } + else if(AttributeHelper.IsHideFromJava(nested)) + { + // ignore + } + else + { + wrappers.Add(ClassLoaderWrapper.GetWrapperFromType(nested)); + } + } + foreach(string s in AttributeHelper.GetNonNestedInnerClasses(type)) + { + wrappers.Add(GetClassLoader().LoadClassByDottedName(s)); + } + return wrappers.ToArray(); + } + } + + internal override TypeWrapper DeclaringTypeWrapper + { + get + { + if(IsNestedTypeAnonymousOrLocalClass(type)) + { + return null; + } + Type declaringType = type.DeclaringType; + if(declaringType != null) + { + return ClassLoaderWrapper.GetWrapperFromType(declaringType); + } + string decl = AttributeHelper.GetNonNestedOuterClasses(type); + if(decl != null) + { + return GetClassLoader().LoadClassByDottedName(decl); + } + return null; + } + } + + // returns true iff name is of the form "...$" + private static bool IsAnonymousClassName(string name) + { + int index = name.LastIndexOf('$') + 1; + if (index > 1 && index < name.Length) + { + while (index < name.Length) + { + if ("0123456789".IndexOf(name[index++]) == -1) + { + return false; + } + } + return true; + } + return false; + } + + // This method uses some heuristics to predict the reflective modifiers and if the prediction matches + // we can avoid storing the InnerClassesAttribute to record the modifiers. + // The heuristics are based on javac from Java 7. + internal static Modifiers PredictReflectiveModifiers(TypeWrapper tw) + { + Modifiers modifiers = Modifiers.Static | (tw.Modifiers & (Modifiers.Public | Modifiers.Abstract | Modifiers.Interface)); + // javac marks anonymous classes as final, but the InnerClasses attribute access_flags does not have the ACC_FINAL flag set + if (tw.IsFinal && !IsAnonymousClassName(tw.Name)) + { + modifiers |= Modifiers.Final; + } + // javac uses the this$0 field to store the outer instance reference for non-static inner classes + foreach (FieldWrapper fw in tw.GetFields()) + { + if (fw.Name == "this$0") + { + modifiers &= ~Modifiers.Static; + break; + } + } + return modifiers; + } + + internal override Modifiers ReflectiveModifiers + { + get + { + if (reflectiveModifiers == 0) + { + Modifiers mods; + InnerClassAttribute attr = AttributeHelper.GetInnerClass(type); + if (attr != null) + { + // the mask comes from RECOGNIZED_INNER_CLASS_MODIFIERS in src/hotspot/share/vm/classfile/classFileParser.cpp + // (minus ACC_SUPER) + mods = attr.Modifiers & (Modifiers)0x761F; + } + else if (type.DeclaringType != null) + { + mods = PredictReflectiveModifiers(this); + } + else + { + // the mask comes from JVM_RECOGNIZED_CLASS_MODIFIERS in src/hotspot/share/vm/prims/jvm.h + // (minus ACC_SUPER) + mods = Modifiers & (Modifiers)0x7611; + } + if (IsInterface) + { + mods |= Modifiers.Abstract; + } + reflectiveModifiers = mods; + } + return reflectiveModifiers; + } + } + + internal override Type TypeAsBaseType + { + get + { + return type; + } + } + + private void SigTypePatchUp(string sigtype, ref TypeWrapper type) + { + if(sigtype != type.SigName) + { + // if type is an array, we know that it is a ghost array, because arrays of unloadable are compiled + // as object (not as arrays of object) + if(type.IsArray) + { + type = GetClassLoader().FieldTypeWrapperFromSig(sigtype, LoadMode.LoadOrThrow); + } + else if(type.IsPrimitive) + { + type = DotNetTypeWrapper.GetWrapperFromDotNetType(type.TypeAsTBD); + if(sigtype != type.SigName) + { + throw new InvalidOperationException(); + } + } + else if(type.IsNonPrimitiveValueType) + { + // this can't happen and even if it does happen we cannot return + // UnloadableTypeWrapper because that would result in incorrect code + // being generated + throw new InvalidOperationException(); + } + else + { + if(sigtype[0] == 'L') + { + sigtype = sigtype.Substring(1, sigtype.Length - 2); + } + try + { + TypeWrapper tw = GetClassLoader().LoadClassByDottedNameFast(sigtype); + if(tw != null && tw.IsRemapped) + { + type = tw; + return; + } + } + catch(RetargetableJavaException) + { + } + type = new UnloadableTypeWrapper(sigtype); + } + } + } + + private static void ParseSig(string sig, out string[] sigparam, out string sigret) + { + List list = new List(); + int pos = 1; + for(;;) + { + switch(sig[pos]) + { + case 'L': + { + int end = sig.IndexOf(';', pos) + 1; + list.Add(sig.Substring(pos, end - pos)); + pos = end; + break; + } + case '[': + { + int skip = 1; + while(sig[pos + skip] == '[') skip++; + if(sig[pos + skip] == 'L') + { + int end = sig.IndexOf(';', pos) + 1; + list.Add(sig.Substring(pos, end - pos)); + pos = end; + } + else + { + skip++; + list.Add(sig.Substring(pos, skip)); + pos += skip; + } + break; + } + case ')': + sigparam = list.ToArray(); + sigret = sig.Substring(pos + 1); + return; + default: + list.Add(sig.Substring(pos, 1)); + pos++; + break; + } + } + } + + private static bool IsCallerID(Type type) + { +#if STUB_GENERATOR + return type.FullName == "ikvm.internal.CallerID"; +#else + return type == CoreClasses.ikvm.@internal.CallerID.Wrapper.TypeAsSignatureType; +#endif + } + + private static bool IsCallerSensitive(MethodBase mb) + { +#if FIRST_PASS + return false; +#elif STATIC_COMPILER || STUB_GENERATOR + foreach (CustomAttributeData cad in mb.GetCustomAttributesData()) + { + if (cad.AttributeType.FullName == "sun.reflect.CallerSensitiveAttribute") + { + return true; + } + } + return false; +#else + return mb.IsDefined(typeof(sun.reflect.CallerSensitiveAttribute), false); +#endif + } + + private void GetNameSigFromMethodBase(MethodBase method, out string name, out string sig, out TypeWrapper retType, out TypeWrapper[] paramTypes, ref MemberFlags flags) + { + retType = method is ConstructorInfo ? PrimitiveTypeWrapper.VOID : GetParameterTypeWrapper(((MethodInfo)method).ReturnParameter); + ParameterInfo[] parameters = method.GetParameters(); + int len = parameters.Length; + if(len > 0 + && IsCallerID(parameters[len - 1].ParameterType) + && GetClassLoader() == ClassLoaderWrapper.GetBootstrapClassLoader() + && IsCallerSensitive(method)) + { + len--; + flags |= MemberFlags.CallerID; + } + paramTypes = new TypeWrapper[len]; + for(int i = 0; i < len; i++) + { + paramTypes[i] = GetParameterTypeWrapper(parameters[i]); + } + NameSigAttribute attr = AttributeHelper.GetNameSig(method); + if(attr != null) + { + name = attr.Name; + sig = attr.Sig; + string[] sigparams; + string sigret; + ParseSig(sig, out sigparams, out sigret); + // HACK newhelper methods have a return type, but it should be void + if(name == "") + { + retType = PrimitiveTypeWrapper.VOID; + } + SigTypePatchUp(sigret, ref retType); + // if we have a remapped method, the paramTypes array contains an additional entry for "this" so we have + // to remove that + if(paramTypes.Length == sigparams.Length + 1) + { + paramTypes = ArrayUtil.DropFirst(paramTypes); + } + Debug.Assert(sigparams.Length == paramTypes.Length); + for(int i = 0; i < sigparams.Length; i++) + { + SigTypePatchUp(sigparams[i], ref paramTypes[i]); + } + } + else + { + if(method is ConstructorInfo) + { + name = method.IsStatic ? "" : ""; + } + else + { + name = method.Name; + if(name.StartsWith(NamePrefix.Bridge, StringComparison.Ordinal)) + { + name = name.Substring(NamePrefix.Bridge.Length); + } + if(method.IsSpecialName) + { + name = UnicodeUtil.UnescapeInvalidSurrogates(name); + } + } + if(method.IsSpecialName && method.Name.StartsWith(NamePrefix.DefaultMethod, StringComparison.Ordinal)) + { + paramTypes = ArrayUtil.DropFirst(paramTypes); + } + System.Text.StringBuilder sb = new System.Text.StringBuilder("("); + foreach(TypeWrapper tw in paramTypes) + { + sb.Append(tw.SigName); + } + sb.Append(")"); + sb.Append(retType.SigName); + sig = sb.ToString(); + } + } + + private sealed class DelegateConstructorMethodWrapper : MethodWrapper + { + private readonly ConstructorInfo constructor; + private MethodInfo invoke; + + private DelegateConstructorMethodWrapper(TypeWrapper tw, TypeWrapper iface, ExModifiers mods) + : base(tw, StringConstants.INIT, "(" + iface.SigName + ")V", null, PrimitiveTypeWrapper.VOID, new TypeWrapper[] { iface }, mods.Modifiers, mods.IsInternal ? MemberFlags.InternalAccess : MemberFlags.None) + { + } + + internal DelegateConstructorMethodWrapper(TypeWrapper tw, MethodBase method) + : this(tw, tw.GetClassLoader().LoadClassByDottedName(tw.Name + DotNetTypeWrapper.DelegateInterfaceSuffix), AttributeHelper.GetModifiers(method, false)) + { + constructor = (ConstructorInfo)method; + } + + protected override void DoLinkMethod() + { + MethodWrapper mw = GetParameters()[0].GetMethods()[0]; + mw.Link(); + invoke = (MethodInfo)mw.GetMethod(); + } + +#if EMITTERS + internal override void EmitNewobj(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Dup); + ilgen.Emit(OpCodes.Ldvirtftn, invoke); + ilgen.Emit(OpCodes.Newobj, constructor); + } +#endif // EMITTERS + } + + protected override void LazyPublishMethods() + { + bool isDelegate = type.BaseType == Types.MulticastDelegate; + List methods = new List(); + const BindingFlags flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance; + foreach(ConstructorInfo ctor in type.GetConstructors(flags)) + { + HideFromJavaFlags hideFromJavaFlags = AttributeHelper.GetHideFromJavaFlags(ctor); + if (isDelegate && !ctor.IsStatic && (hideFromJavaFlags & HideFromJavaFlags.Code) == 0) + { + methods.Add(new DelegateConstructorMethodWrapper(this, ctor)); + } + else + { + AddMethodOrConstructor(ctor, hideFromJavaFlags, methods); + } + } + AddMethods(type.GetMethods(flags), methods); + if (type.IsInterface && (type.IsPublic || type.IsNestedPublic)) + { + Type privateInterfaceMethods = type.GetNestedType(NestedTypeName.PrivateInterfaceMethods, BindingFlags.NonPublic); + if (privateInterfaceMethods != null) + { + AddMethods(privateInterfaceMethods.GetMethods(flags), methods); + } + } + SetMethods(methods.ToArray()); + } + + private void AddMethods(MethodInfo[] add, List methods) + { + foreach (MethodInfo method in add) + { + AddMethodOrConstructor(method, AttributeHelper.GetHideFromJavaFlags(method), methods); + } + } + + private void AddMethodOrConstructor(MethodBase method, HideFromJavaFlags hideFromJavaFlags, List methods) + { + if((hideFromJavaFlags & HideFromJavaFlags.Code) != 0) + { + if(method.Name.StartsWith(NamePrefix.Incomplete, StringComparison.Ordinal)) + { + SetHasIncompleteInterfaceImplementation(); + } + } + else + { + if(method.IsSpecialName && (method.Name.StartsWith("__<", StringComparison.Ordinal) || method.Name.StartsWith(NamePrefix.DefaultMethod, StringComparison.Ordinal))) + { + // skip + } + else + { + string name; + string sig; + TypeWrapper retType; + TypeWrapper[] paramTypes; + MethodInfo mi = method as MethodInfo; + bool hideFromReflection = mi != null && (hideFromJavaFlags & HideFromJavaFlags.Reflection) != 0; + MemberFlags flags = hideFromReflection ? MemberFlags.HideFromReflection : MemberFlags.None; + GetNameSigFromMethodBase(method, out name, out sig, out retType, out paramTypes, ref flags); + ExModifiers mods = AttributeHelper.GetModifiers(method, false); + if(mods.IsInternal) + { + flags |= MemberFlags.InternalAccess; + } + if(hideFromReflection && name.StartsWith(NamePrefix.AccessStub, StringComparison.Ordinal)) + { + int id = Int32.Parse(name.Substring(NamePrefix.AccessStub.Length, name.IndexOf('|', NamePrefix.AccessStub.Length) - NamePrefix.AccessStub.Length)); + name = name.Substring(name.IndexOf('|', NamePrefix.AccessStub.Length) + 1); + flags |= MemberFlags.AccessStub; + MethodInfo nonvirt = type.GetMethod(NamePrefix.NonVirtual + id, BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.Instance); + methods.Add(new AccessStubMethodWrapper(this, name, sig, mi, mi, nonvirt ?? mi, retType, paramTypes, mods.Modifiers & ~Modifiers.Final, flags)); + return; + } + MethodInfo impl; + MethodWrapper mw; + if (IsGhost && (mods.Modifiers & (Modifiers.Static | Modifiers.Private)) == 0) + { + Type[] types = new Type[paramTypes.Length]; + for (int i = 0; i < types.Length; i++) + { + types[i] = paramTypes[i].TypeAsSignatureType; + } + MethodInfo ifmethod = TypeAsBaseType.GetMethod(method.Name, types); + mw = new GhostMethodWrapper(this, name, sig, ifmethod, (MethodInfo)method, retType, paramTypes, mods.Modifiers, flags); + if (!mw.IsAbstract) + { + ((GhostMethodWrapper)mw).SetDefaultImpl(TypeAsSignatureType.GetMethod(NamePrefix.DefaultMethod + method.Name, types)); + } + } + else if (method.IsSpecialName && method.Name.StartsWith(NamePrefix.PrivateInterfaceInstanceMethod, StringComparison.Ordinal)) + { + mw = new PrivateInterfaceMethodWrapper(this, name, sig, method, retType, paramTypes, mods.Modifiers, flags); + } + else if (IsInterface && method.IsAbstract && (mods.Modifiers & Modifiers.Abstract) == 0 && (impl = GetDefaultInterfaceMethodImpl(mi, sig)) != null) + { + mw = new DefaultInterfaceMethodWrapper(this, name, sig, mi, impl, retType, paramTypes, mods.Modifiers, flags); + } + else + { + mw = new TypicalMethodWrapper(this, name, sig, method, retType, paramTypes, mods.Modifiers, flags); + } + if (mw.HasNonPublicTypeInSignature) + { + if (mi != null) + { + MethodInfo stubVirt; + MethodInfo stubNonVirt; + if (GetType2AccessStubs(name, sig, out stubVirt, out stubNonVirt)) + { + mw = new AccessStubMethodWrapper(this, name, sig, mi, stubVirt, stubNonVirt ?? stubVirt, retType, paramTypes, mw.Modifiers, flags); + } + } + else + { + ConstructorInfo stub; + if (GetType2AccessStub(sig, out stub)) + { + mw = new AccessStubConstructorMethodWrapper(this, sig, (ConstructorInfo)method, stub, paramTypes, mw.Modifiers, flags); + } + } + } + methods.Add(mw); + } + } + } + + private MethodInfo GetDefaultInterfaceMethodImpl(MethodInfo method, string expectedSig) + { + foreach (MethodInfo candidate in method.DeclaringType.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly)) + { + if (candidate.IsSpecialName + && candidate.Name.StartsWith(NamePrefix.DefaultMethod, StringComparison.Ordinal) + && candidate.Name.Length == method.Name.Length + NamePrefix.DefaultMethod.Length + && candidate.Name.EndsWith(method.Name, StringComparison.Ordinal)) + { + string name; + string sig; + TypeWrapper retType; + TypeWrapper[] paramTypes; + MemberFlags flags = MemberFlags.None; + GetNameSigFromMethodBase(candidate, out name, out sig, out retType, out paramTypes, ref flags); + if (sig == expectedSig) + { + return candidate; + } + } + } + return null; + } + + private bool GetType2AccessStubs(string name, string sig, out MethodInfo stubVirt, out MethodInfo stubNonVirt) + { + stubVirt = null; + stubNonVirt = null; + const BindingFlags flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance; + foreach (MethodInfo method in type.GetMethods(flags)) + { + if (AttributeHelper.IsHideFromJava(method)) + { + NameSigAttribute attr = AttributeHelper.GetNameSig(method); + if (attr != null && attr.Name == name && attr.Sig == sig) + { + if (method.Name.StartsWith(NamePrefix.NonVirtual, StringComparison.Ordinal)) + { + stubNonVirt = method; + } + else + { + stubVirt = method; + } + } + } + } + return stubVirt != null; + } + + private bool GetType2AccessStub(string sig, out ConstructorInfo stub) + { + stub = null; + const BindingFlags flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; + foreach (ConstructorInfo ctor in type.GetConstructors(flags)) + { + if (AttributeHelper.IsHideFromJava(ctor)) + { + NameSigAttribute attr = AttributeHelper.GetNameSig(ctor); + if (attr != null && attr.Sig == sig) + { + stub = ctor; + } + } + } + return stub != null; + } + + private static int SortFieldByToken(FieldInfo field1, FieldInfo field2) + { + return field1.MetadataToken.CompareTo(field2.MetadataToken); + } + + protected override void LazyPublishFields() + { + List fields = new List(); + const BindingFlags flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance; + FieldInfo[] rawfields = type.GetFields(flags); + Array.Sort(rawfields, SortFieldByToken); + // FXBUG on .NET 3.5 and Mono Type.GetProperties() will not return "duplicate" properties (i.e. that have the same name and type, but differ in custom modifiers). + // .NET 4.0 works as expected. We don't have a workaround, because that would require name mangling again and this situation is very unlikely anyway. + PropertyInfo[] properties = type.GetProperties(flags); + foreach(FieldInfo field in rawfields) + { + HideFromJavaFlags hideFromJavaFlags = AttributeHelper.GetHideFromJavaFlags(field); + if((hideFromJavaFlags & HideFromJavaFlags.Code) != 0) + { + if(field.Name.StartsWith(NamePrefix.Type2AccessStubBackingField, StringComparison.Ordinal)) + { + TypeWrapper tw = GetFieldTypeWrapper(field); + string name = field.Name.Substring(NamePrefix.Type2AccessStubBackingField.Length); + for(int i = 0; i < properties.Length; i++) + { + if(properties[i] != null + && name == properties[i].Name + && MatchTypes(tw, GetPropertyTypeWrapper(properties[i]))) + { + fields.Add(new CompiledAccessStubFieldWrapper(this, properties[i], field, tw)); + properties[i] = null; + break; + } + } + } + } + else + { + if(field.IsSpecialName && field.Name.StartsWith("__<", StringComparison.Ordinal)) + { + // skip + } + else + { + fields.Add(CreateFieldWrapper(field, hideFromJavaFlags)); + } + } + } + foreach(PropertyInfo property in properties) + { + if(property != null) + { + AddPropertyFieldWrapper(fields, property, null); + } + } + SetFields(fields.ToArray()); + } + + private static bool MatchTypes(TypeWrapper tw1, TypeWrapper tw2) + { + return tw1 == tw2 || (tw1.IsUnloadable && tw2.IsUnloadable && tw1.Name == tw2.Name); + } + + private void AddPropertyFieldWrapper(List fields, PropertyInfo property, FieldInfo field) + { + // NOTE explictly defined properties (in map.xml) are decorated with HideFromJava, + // so we don't need to worry about them here + HideFromJavaFlags hideFromJavaFlags = AttributeHelper.GetHideFromJavaFlags(property); + if((hideFromJavaFlags & HideFromJavaFlags.Code) == 0) + { + // is it a type 1 access stub? + if((hideFromJavaFlags & HideFromJavaFlags.Reflection) != 0) + { + fields.Add(new CompiledAccessStubFieldWrapper(this, property, GetPropertyTypeWrapper(property))); + } + else + { + // It must be an explicit property + // (defined in Java source by an @ikvm.lang.Property annotation) + ModifiersAttribute mods = AttributeHelper.GetModifiersAttribute(property); + fields.Add(new CompiledPropertyFieldWrapper(this, property, new ExModifiers(mods.Modifiers, mods.IsInternal))); + } + } + } + + private sealed class CompiledRemappedMethodWrapper : SmartMethodWrapper + { + private readonly MethodInfo mbHelper; +#if !STATIC_COMPILER + private readonly MethodInfo mbNonvirtualHelper; +#endif + + internal CompiledRemappedMethodWrapper(TypeWrapper declaringType, string name, string sig, MethodBase method, TypeWrapper returnType, TypeWrapper[] parameterTypes, ExModifiers modifiers, bool hideFromReflection, MethodInfo mbHelper, MethodInfo mbNonvirtualHelper) + : base(declaringType, name, sig, method, returnType, parameterTypes, modifiers.Modifiers, + (modifiers.IsInternal ? MemberFlags.InternalAccess : MemberFlags.None) | (hideFromReflection ? MemberFlags.HideFromReflection : MemberFlags.None)) + { + this.mbHelper = mbHelper; +#if !STATIC_COMPILER + this.mbNonvirtualHelper = mbNonvirtualHelper; +#endif + } + +#if EMITTERS + protected override void CallImpl(CodeEmitter ilgen) + { + MethodBase mb = GetMethod(); + MethodInfo mi = mb as MethodInfo; + if(mi != null) + { + if(!IsStatic && IsFinal) + { + // When calling a final instance method on a remapped type from a class derived from a .NET class (i.e. a cli.System.Object or cli.System.Exception derived base class) + // then we can't call the java.lang.Object or java.lang.Throwable methods and we have to go through the instancehelper_ method. Note that since the method + // is final, this won't affect the semantics. + CallvirtImpl(ilgen); + } + else + { + ilgen.Emit(OpCodes.Call, mi); + } + } + else + { + ilgen.Emit(OpCodes.Call, mb); + } + } + + protected override void CallvirtImpl(CodeEmitter ilgen) + { + Debug.Assert(!mbHelper.IsStatic || mbHelper.Name.StartsWith("instancehelper_") || mbHelper.DeclaringType.Name == "__Helper"); + if(mbHelper.IsPublic) + { + ilgen.Emit(mbHelper.IsStatic ? OpCodes.Call : OpCodes.Callvirt, mbHelper); + } + else + { + // HACK the helper is not public, this means that we're dealing with finalize or clone + ilgen.Emit(OpCodes.Callvirt, GetMethod()); + } + } + + protected override void NewobjImpl(CodeEmitter ilgen) + { + MethodBase mb = GetMethod(); + MethodInfo mi = mb as MethodInfo; + if(mi != null) + { + Debug.Assert(mi.Name == "newhelper"); + ilgen.Emit(OpCodes.Call, mi); + } + else + { + ilgen.Emit(OpCodes.Newobj, mb); + } + } +#endif // EMITTERS + +#if !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + [HideFromJava] + internal override object Invoke(object obj, object[] args) + { + MethodBase mb = mbHelper != null ? mbHelper : GetMethod(); + if (mb.IsStatic && !IsStatic) + { + args = ArrayUtil.Concat(obj, args); + obj = null; + } + return InvokeAndUnwrapException(mb, obj, args); + } + + [HideFromJava] + internal override object CreateInstance(object[] args) + { + MethodBase mb = mbHelper != null ? mbHelper : GetMethod(); + if (mb.IsStatic) + { + return InvokeAndUnwrapException(mb, null, args); + } + return base.CreateInstance(args); + } + + [HideFromJava] + internal override object InvokeNonvirtualRemapped(object obj, object[] args) + { + MethodInfo mi = mbNonvirtualHelper; + if (mi == null) + { + mi = mbHelper; + } + return mi.Invoke(null, ArrayUtil.Concat(obj, args)); + } +#endif // !STATIC_COMPILER && !FIRST_PASS && !STUB_GENERATOR + +#if EMITTERS + internal override void EmitCallvirtReflect(CodeEmitter ilgen) + { + MethodBase mb = mbHelper != null ? mbHelper : GetMethod(); + ilgen.Emit(mb.IsStatic ? OpCodes.Call : OpCodes.Callvirt, mb); + } +#endif // EMITTERS + + internal string GetGenericSignature() + { + SignatureAttribute attr = AttributeHelper.GetSignature(mbHelper != null ? mbHelper : GetMethod()); + if(attr != null) + { + return attr.Signature; + } + return null; + } + } + + private static TypeWrapper TypeWrapperFromModOpt(Type[] modopt) + { + int rank = 0; + TypeWrapper tw = null; + foreach (Type type in modopt) + { + if (type == JVM.LoadType(typeof(IKVM.Attributes.AccessStub))) + { + // ignore + } + else if (type == Types.Array) + { + rank++; + } + else if (type == Types.Void || type.IsPrimitive || ClassLoaderWrapper.IsRemappedType(type)) + { + tw = DotNetTypeWrapper.GetWrapperFromDotNetType(type); + } + else if (type.DeclaringType != null && type.DeclaringType.FullName == UnloadableTypeWrapper.ContainerTypeName) + { + tw = new UnloadableTypeWrapper(TypeNameUtil.UnmangleNestedTypeName(type.Name), type); + } + else + { + tw = ClassLoaderWrapper.GetWrapperFromType(type); + } + } + if (rank != 0) + { + tw = tw.MakeArrayType(rank); + } + return tw; + } + + private static TypeWrapper GetPropertyTypeWrapper(PropertyInfo property) + { + return TypeWrapperFromModOpt(property.GetOptionalCustomModifiers()) + ?? ClassLoaderWrapper.GetWrapperFromType(property.PropertyType); + } + + internal static TypeWrapper GetFieldTypeWrapper(FieldInfo field) + { + return TypeWrapperFromModOpt(field.GetOptionalCustomModifiers()) + ?? ClassLoaderWrapper.GetWrapperFromType(field.FieldType); + } + + internal static TypeWrapper GetParameterTypeWrapper(ParameterInfo param) + { + TypeWrapper tw = TypeWrapperFromModOpt(param.GetOptionalCustomModifiers()); + if (tw != null) + { + return tw; + } + Type parameterType = param.ParameterType; + if (parameterType.IsByRef) + { + // we only support ByRef parameters for automatically generated delegate invoke stubs + parameterType = parameterType.GetElementType().MakeArrayType(); + } + return ClassLoaderWrapper.GetWrapperFromType(parameterType); + } + + private FieldWrapper CreateFieldWrapper(FieldInfo field, HideFromJavaFlags hideFromJavaFlags) + { + ExModifiers modifiers = AttributeHelper.GetModifiers(field, false); + TypeWrapper type = GetFieldTypeWrapper(field); + string name = field.Name; + + if(field.IsSpecialName) + { + name = UnicodeUtil.UnescapeInvalidSurrogates(name); + } + + if(field.IsLiteral) + { + MemberFlags flags = MemberFlags.None; + if((hideFromJavaFlags & HideFromJavaFlags.Reflection) != 0) + { + flags |= MemberFlags.HideFromReflection; + } + if(modifiers.IsInternal) + { + flags |= MemberFlags.InternalAccess; + } + return new ConstantFieldWrapper(this, type, name, type.SigName, modifiers.Modifiers, field, null, flags); + } + else + { + return FieldWrapper.Create(this, type, field, name, type.SigName, modifiers); + } + } + + internal override Type TypeAsTBD + { + get + { + return type; + } + } + + internal override bool IsMapUnsafeException + { + get + { + return AttributeHelper.IsExceptionIsUnsafeForMapping(type); + } + } + +#if EMITTERS + internal override void EmitRunClassConstructor(CodeEmitter ilgen) + { + if(HasStaticInitializer) + { + ilgen.Emit(OpCodes.Call, clinitMethod); + } + } +#endif // EMITTERS + + internal override string GetGenericSignature() + { + SignatureAttribute attr = AttributeHelper.GetSignature(type); + if(attr != null) + { + return attr.Signature; + } + return null; + } + + internal override string GetGenericMethodSignature(MethodWrapper mw) + { + if(mw is CompiledRemappedMethodWrapper) + { + return ((CompiledRemappedMethodWrapper)mw).GetGenericSignature(); + } + MethodBase mb = mw.GetMethod(); + if(mb != null) + { + SignatureAttribute attr = AttributeHelper.GetSignature(mb); + if(attr != null) + { + return attr.Signature; + } + } + return null; + } + + internal override string GetGenericFieldSignature(FieldWrapper fw) + { + FieldInfo fi = fw.GetField(); + if(fi != null) + { + SignatureAttribute attr = AttributeHelper.GetSignature(fi); + if(attr != null) + { + return attr.Signature; + } + } + return null; + } + + internal override MethodParametersEntry[] GetMethodParameters(MethodWrapper mw) + { + MethodBase mb = mw.GetMethod(); + if (mb == null) + { + // delegate constructor + return null; + } + MethodParametersAttribute attr = AttributeHelper.GetMethodParameters(mb); + if (attr == null) + { + return null; + } + if (attr.IsMalformed) + { + return MethodParametersEntry.Malformed; + } + ParameterInfo[] parameters = mb.GetParameters(); + MethodParametersEntry[] mp = new MethodParametersEntry[attr.Modifiers.Length]; + for (int i = 0; i < mp.Length; i++) + { + mp[i].name = i < parameters.Length ? parameters[i].Name : null; + mp[i].flags = (ushort)attr.Modifiers[i]; + } + return mp; + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal override string[] GetEnclosingMethod() + { + EnclosingMethodAttribute enc = AttributeHelper.GetEnclosingMethodAttribute(type); + if (enc != null) + { + return new string[] { enc.ClassName, enc.MethodName, enc.MethodSignature }; + } + return null; + } + + internal override object[] GetDeclaredAnnotations() + { + return type.GetCustomAttributes(false); + } + + internal override object[] GetMethodAnnotations(MethodWrapper mw) + { + MethodBase mb = mw.GetMethod(); + if(mb == null) + { + // delegate constructor + return null; + } + return mb.GetCustomAttributes(false); + } + + internal override object[][] GetParameterAnnotations(MethodWrapper mw) + { + MethodBase mb = mw.GetMethod(); + if(mb == null) + { + // delegate constructor + return null; + } + ParameterInfo[] parameters = mb.GetParameters(); + int skip = 0; + if(mb.IsStatic && !mw.IsStatic && mw.Name != "") + { + skip = 1; + } + int skipEnd = 0; + if(mw.HasCallerID) + { + skipEnd = 1; + } + object[][] attribs = new object[parameters.Length - skip - skipEnd][]; + for(int i = skip; i < parameters.Length - skipEnd; i++) + { + attribs[i - skip] = parameters[i].GetCustomAttributes(false); + } + return attribs; + } + + internal override object[] GetFieldAnnotations(FieldWrapper fw) + { + FieldInfo field = fw.GetField(); + if(field != null) + { + return field.GetCustomAttributes(false); + } + CompiledPropertyFieldWrapper prop = fw as CompiledPropertyFieldWrapper; + if(prop != null) + { + return prop.GetProperty().GetCustomAttributes(false); + } + return new object[0]; + } +#endif + + internal sealed class CompiledAnnotation : Annotation + { + private readonly ConstructorInfo constructor; + + internal CompiledAnnotation(Type type) + { + constructor = type.GetConstructor(new Type[] { JVM.Import(typeof(object[])) }); + } + + private CustomAttributeBuilder MakeCustomAttributeBuilder(ClassLoaderWrapper loader, object annotation) + { + return new CustomAttributeBuilder(constructor, new object[] { AnnotationDefaultAttribute.Escape(QualifyClassNames(loader, annotation)) }); + } + + internal override void Apply(ClassLoaderWrapper loader, TypeBuilder tb, object annotation) + { + tb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + + internal override void Apply(ClassLoaderWrapper loader, MethodBuilder mb, object annotation) + { + mb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + + internal override void Apply(ClassLoaderWrapper loader, FieldBuilder fb, object annotation) + { + fb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + + internal override void Apply(ClassLoaderWrapper loader, ParameterBuilder pb, object annotation) + { + pb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + + internal override void Apply(ClassLoaderWrapper loader, AssemblyBuilder ab, object annotation) + { + ab.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + + internal override void Apply(ClassLoaderWrapper loader, PropertyBuilder pb, object annotation) + { + pb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + + internal override bool IsCustomAttribute + { + get { return false; } + } + } + + internal override Annotation Annotation + { + get + { + string annotationAttribute = AttributeHelper.GetAnnotationAttributeType(type); + if(annotationAttribute != null) + { + return new CompiledAnnotation(type.Assembly.GetType(annotationAttribute, true)); + } + return null; + } + } + + internal override Type EnumType + { + get + { + if((this.Modifiers & Modifiers.Enum) != 0) + { + return type.GetNestedType("__Enum"); + } + return null; + } + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + internal override string GetSourceFileName() + { + object[] attr = type.GetCustomAttributes(typeof(SourceFileAttribute), false); + if(attr.Length == 1) + { + return ((SourceFileAttribute)attr[0]).SourceFile; + } + if(DeclaringTypeWrapper != null) + { + return DeclaringTypeWrapper.GetSourceFileName(); + } + if(IsNestedTypeAnonymousOrLocalClass(type)) + { + return ClassLoaderWrapper.GetWrapperFromType(type.DeclaringType).GetSourceFileName(); + } + if(type.Module.IsDefined(typeof(SourceFileAttribute), false)) + { + return type.Name + ".java"; + } + return null; + } + + internal override int GetSourceLineNumber(MethodBase mb, int ilOffset) + { + object[] attr = mb.GetCustomAttributes(typeof(LineNumberTableAttribute), false); + if(attr.Length == 1) + { + return ((LineNumberTableAttribute)attr[0]).GetLineNumber(ilOffset); + } + return -1; + } +#endif + + internal override bool IsFastClassLiteralSafe + { + get { return true; } + } + + internal override object[] GetConstantPool() + { + return AttributeHelper.GetConstantPool(type); + } + + internal override byte[] GetRawTypeAnnotations() + { + return AttributeHelper.GetRuntimeVisibleTypeAnnotations(type); + } + + internal override byte[] GetMethodRawTypeAnnotations(MethodWrapper mw) + { + MethodBase mb = mw.GetMethod(); + return mb == null ? null : AttributeHelper.GetRuntimeVisibleTypeAnnotations(mb); + } + + internal override byte[] GetFieldRawTypeAnnotations(FieldWrapper fw) + { + FieldInfo fi = fw.GetField(); + return fi == null ? null : AttributeHelper.GetRuntimeVisibleTypeAnnotations(fi); + } + } + + sealed class ArrayTypeWrapper : TypeWrapper + { + private static volatile TypeWrapper[] interfaces; + private static volatile MethodInfo clone; + private readonly TypeWrapper ultimateElementTypeWrapper; + private Type arrayType; + private bool finished; + + internal ArrayTypeWrapper(TypeWrapper ultimateElementTypeWrapper, string name) + : base(ultimateElementTypeWrapper.IsInternal ? TypeFlags.InternalAccess : TypeFlags.None, + Modifiers.Final | Modifiers.Abstract | (ultimateElementTypeWrapper.Modifiers & Modifiers.Public), name) + { + Debug.Assert(!ultimateElementTypeWrapper.IsArray); + this.ultimateElementTypeWrapper = ultimateElementTypeWrapper; + } + + internal override TypeWrapper BaseTypeWrapper + { + get { return CoreClasses.java.lang.Object.Wrapper; } + } + + internal override ClassLoaderWrapper GetClassLoader() + { + return ultimateElementTypeWrapper.GetClassLoader(); + } + + internal static MethodInfo CloneMethod + { + get + { + if(clone == null) + { + clone = Types.Array.GetMethod("Clone", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null); + } + return clone; + } + } + + protected override void LazyPublishMembers() + { + MethodWrapper mw = new SimpleCallMethodWrapper(this, "clone", "()Ljava.lang.Object;", CloneMethod, CoreClasses.java.lang.Object.Wrapper, TypeWrapper.EmptyArray, Modifiers.Public, MemberFlags.HideFromReflection, SimpleOpCode.Callvirt, SimpleOpCode.Callvirt); + mw.Link(); + SetMethods(new MethodWrapper[] { mw }); + SetFields(FieldWrapper.EmptyArray); + } + + internal override Modifiers ReflectiveModifiers + { + get + { + return Modifiers.Final | Modifiers.Abstract | (ultimateElementTypeWrapper.ReflectiveModifiers & Modifiers.AccessMask); + } + } + + internal override string SigName + { + get + { + // for arrays the signature name is the same as the normal name + return Name; + } + } + + internal override TypeWrapper[] Interfaces + { + get + { + if(interfaces == null) + { + TypeWrapper[] tw = new TypeWrapper[2]; + tw[0] = CoreClasses.java.lang.Cloneable.Wrapper; + tw[1] = CoreClasses.java.io.Serializable.Wrapper; + interfaces = tw; + } + return interfaces; + } + } + + internal override Type TypeAsTBD + { + get + { + while (arrayType == null) + { + bool prevFinished = finished; + Type type = MakeArrayType(ultimateElementTypeWrapper.TypeAsArrayType, this.ArrayRank); + if (prevFinished) + { + // We were already finished prior to the call to MakeArrayType, so we can safely + // set arrayType to the finished type. + // Note that this takes advantage of the fact that once we've been finished, + // we can never become unfinished. + arrayType = type; + } + else + { + lock (this) + { + // To prevent a race with Finish, we can only set arrayType in this case + // (inside the locked region) if we've not already finished. If we have + // finished, we need to rerun MakeArrayType on the now finished element type. + // Note that there is a benign race left, because it is possible that another + // thread finishes right after we've set arrayType and exited the locked + // region. This is not problem, because TypeAsTBD is only guaranteed to + // return a finished type *after* Finish has been called. + if (!finished) + { + arrayType = type; + } + } + } + } + return arrayType; + } + } + + internal override void Finish() + { + if (!finished) + { + ultimateElementTypeWrapper.Finish(); + lock (this) + { + // Now that we've finished the element type, we must clear arrayType, + // because it may still refer to a TypeBuilder. Note that we have to + // do this atomically with setting "finished", to prevent a race + // with TypeAsTBD. + finished = true; + arrayType = null; + } + } + } + + internal override bool IsFastClassLiteralSafe + { + // here we have to deal with the somewhat strange fact that in Java you cannot represent primitive type class literals, + // but you can represent arrays of primitive types as a class literal + get { return ultimateElementTypeWrapper.IsFastClassLiteralSafe || ultimateElementTypeWrapper.IsPrimitive; } + } + + internal override TypeWrapper GetUltimateElementTypeWrapper() + { + return ultimateElementTypeWrapper; + } + + internal static Type MakeArrayType(Type type, int dims) + { + // NOTE this is not just an optimization, but it is also required to + // make sure that ReflectionOnly types stay ReflectionOnly types + // (in particular instantiations of generic types from mscorlib that + // have ReflectionOnly type parameters). + for(int i = 0; i < dims; i++) + { + type = type.MakeArrayType(); + } + return type; + } + } + + // this is a container for the special verifier TypeWrappers + sealed class VerifierTypeWrapper : TypeWrapper + { + // the TypeWrapper constructor interns the name, so we have to pre-intern here to make sure we have the same string object + // (if it has only been interned previously) + private static readonly string This = string.Intern("this"); + private static readonly string New = string.Intern("new"); + private static readonly string Fault = string.Intern(""); + internal static readonly TypeWrapper Invalid = null; + internal static readonly TypeWrapper Null = new VerifierTypeWrapper("null", 0, null, null); + internal static readonly TypeWrapper UninitializedThis = new VerifierTypeWrapper("uninitialized-this", 0, null, null); + internal static readonly TypeWrapper Unloadable = new UnloadableTypeWrapper(""); + internal static readonly TypeWrapper ExtendedFloat = new VerifierTypeWrapper("", 0, null, null); + internal static readonly TypeWrapper ExtendedDouble = new VerifierTypeWrapper("", 0, null, null); + + private readonly int index; + private readonly TypeWrapper underlyingType; + private readonly MethodAnalyzer methodAnalyzer; + +#if STUB_GENERATOR + internal class MethodAnalyzer + { + internal void ClearFaultBlockException(int dummy) { } + } +#endif + + public override string ToString() + { + return GetType().Name + "[" + Name + "," + index + "," + underlyingType + "]"; + } + + internal static TypeWrapper MakeNew(TypeWrapper type, int bytecodeIndex) + { + return new VerifierTypeWrapper(New, bytecodeIndex, type, null); + } + + internal static TypeWrapper MakeFaultBlockException(MethodAnalyzer ma, int handlerIndex) + { + return new VerifierTypeWrapper(Fault, handlerIndex, null, ma); + } + + // NOTE the "this" type is special, it can only exist in local[0] and on the stack + // as soon as the type on the stack is merged or popped it turns into its underlying type. + // It exists to capture the verification rules for non-virtual base class method invocation in .NET 2.0, + // which requires that the invocation is done on a "this" reference that was directly loaded onto the + // stack (using ldarg_0). + internal static TypeWrapper MakeThis(TypeWrapper type) + { + return new VerifierTypeWrapper(This, 0, type, null); + } + + internal static bool IsNotPresentOnStack(TypeWrapper w) + { + return IsNew(w) || IsFaultBlockException(w); + } + + internal static bool IsNew(TypeWrapper w) + { + return w != null && w.IsVerifierType && ReferenceEquals(w.Name, New); + } + + internal static bool IsFaultBlockException(TypeWrapper w) + { + return w != null && w.IsVerifierType && ReferenceEquals(w.Name, Fault); + } + + internal static bool IsNullOrUnloadable(TypeWrapper w) + { + return w == Null || w.IsUnloadable; + } + + internal static bool IsThis(TypeWrapper w) + { + return w != null && w.IsVerifierType && ReferenceEquals(w.Name, This); + } + + internal static void ClearFaultBlockException(TypeWrapper w) + { + VerifierTypeWrapper vtw = (VerifierTypeWrapper)w; + vtw.methodAnalyzer.ClearFaultBlockException(vtw.Index); + } + + internal int Index + { + get + { + return index; + } + } + + internal TypeWrapper UnderlyingType + { + get + { + return underlyingType; + } + } + + private VerifierTypeWrapper(string name, int index, TypeWrapper underlyingType, MethodAnalyzer methodAnalyzer) + : base(TypeFlags.None, TypeWrapper.VerifierTypeModifiersHack, name) + { + this.index = index; + this.underlyingType = underlyingType; + this.methodAnalyzer = methodAnalyzer; + } + + internal override TypeWrapper BaseTypeWrapper + { + get { return null; } + } + + internal override ClassLoaderWrapper GetClassLoader() + { + return null; + } + + protected override void LazyPublishMembers() + { + throw new InvalidOperationException("LazyPublishMembers called on " + this); + } + + internal override Type TypeAsTBD + { + get + { + throw new InvalidOperationException("get_Type called on " + this); + } + } + + internal override TypeWrapper[] Interfaces + { + get + { + throw new InvalidOperationException("get_Interfaces called on " + this); + } + } + + internal override TypeWrapper[] InnerClasses + { + get + { + throw new InvalidOperationException("get_InnerClasses called on " + this); + } + } + + internal override TypeWrapper DeclaringTypeWrapper + { + get + { + throw new InvalidOperationException("get_DeclaringTypeWrapper called on " + this); + } + } + + internal override void Finish() + { + throw new InvalidOperationException("Finish called on " + this); + } + } + +#if !STATIC_COMPILER && !STUB_GENERATOR + // this represents an intrinsified anonymous class (currently used only by LambdaMetafactory) + sealed class AnonymousTypeWrapper : TypeWrapper + { + private readonly Type type; + + internal AnonymousTypeWrapper(Type type) + : base(TypeFlags.Anonymous, Modifiers.Final | Modifiers.Synthetic, GetName(type)) + { + this.type = type; + } + + internal static bool IsAnonymous(Type type) + { + return type.IsSpecialName + && type.Name.StartsWith(NestedTypeName.IntrinsifiedAnonymousClass, StringComparison.Ordinal) + && AttributeHelper.IsJavaModule(type.Module); + } + + private static string GetName(Type type) + { + return ClassLoaderWrapper.GetWrapperFromType(type.DeclaringType).Name + + type.Name.Replace(NestedTypeName.IntrinsifiedAnonymousClass, "$$Lambda$"); + } + + internal override ClassLoaderWrapper GetClassLoader() + { + return ClassLoaderWrapper.GetWrapperFromType(type.DeclaringType).GetClassLoader(); + } + + internal override Type TypeAsTBD + { + get { return type; } + } + + internal override TypeWrapper BaseTypeWrapper + { + get { return CoreClasses.java.lang.Object.Wrapper; } + } + + internal override TypeWrapper[] Interfaces + { + get + { + TypeWrapper[] interfaces = GetImplementedInterfacesAsTypeWrappers(type); + if (type.IsSerializable) + { + // we have to remove the System.Runtime.Serialization.ISerializable interface + List list = new List(interfaces); + list.RemoveAll(Serialization.IsISerializable); + return list.ToArray(); + } + return interfaces; + } + } + + protected override void LazyPublishMembers() + { + List methods = new List(); + foreach (MethodInfo mi in type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)) + { + if (mi.IsSpecialName) + { + // we use special name to hide default methods + } + else if (mi.IsPublic) + { + TypeWrapper returnType; + TypeWrapper[] parameterTypes; + string signature; + GetSig(mi, out returnType, out parameterTypes, out signature); + methods.Add(new TypicalMethodWrapper(this, mi.Name, signature, mi, returnType, parameterTypes, Modifiers.Public, MemberFlags.None)); + } + else if (mi.Name == "writeReplace") + { + methods.Add(new TypicalMethodWrapper(this, "writeReplace", "()Ljava.lang.Object;", mi, CoreClasses.java.lang.Object.Wrapper, TypeWrapper.EmptyArray, + Modifiers.Private | Modifiers.Final, MemberFlags.None)); + } + } + SetMethods(methods.ToArray()); + List fields = new List(); + foreach (FieldInfo fi in type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)) + { + TypeWrapper fieldType = CompiledTypeWrapper.GetFieldTypeWrapper(fi); + fields.Add(new SimpleFieldWrapper(this, fieldType, fi, fi.Name, fieldType.SigName, new ExModifiers(Modifiers.Private | Modifiers.Final, false))); + } + SetFields(fields.ToArray()); + } + + private void GetSig(MethodInfo mi, out TypeWrapper returnType, out TypeWrapper[] parameterTypes, out string signature) + { + returnType = CompiledTypeWrapper.GetParameterTypeWrapper(mi.ReturnParameter); + ParameterInfo[] parameters = mi.GetParameters(); + parameterTypes = new TypeWrapper[parameters.Length]; + System.Text.StringBuilder sb = new System.Text.StringBuilder("("); + for (int i = 0; i < parameters.Length; i++) + { + parameterTypes[i] = CompiledTypeWrapper.GetParameterTypeWrapper(parameters[i]); + sb.Append(parameterTypes[i].SigName); + } + sb.Append(')'); + sb.Append(returnType.SigName); + signature = sb.ToString(); + } + } +#endif // !STATIC_COMPILER && !STUB_GENERATOR +} diff --git a/runtime/Types.cs b/runtime/Types.cs new file mode 100644 index 0000000..b30dc6f --- /dev/null +++ b/runtime/Types.cs @@ -0,0 +1,66 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +#if STATIC_COMPILER || STUB_GENERATOR +using Type = IKVM.Reflection.Type; +#endif + +namespace IKVM.Internal +{ + static class Types + { + internal static readonly Type Object = JVM.Import(typeof(System.Object)); + internal static readonly Type ValueType = JVM.Import(typeof(System.ValueType)); + internal static readonly Type Enum = JVM.Import(typeof(System.Enum)); + internal static readonly Type Type = JVM.Import(typeof(System.Type)); + internal static readonly Type String = JVM.Import(typeof(System.String)); + internal static readonly Type Exception = JVM.Import(typeof(System.Exception)); + internal static readonly Type Array = JVM.Import(typeof(System.Array)); + internal static readonly Type Attribute = JVM.Import(typeof(System.Attribute)); + internal static readonly Type Delegate = JVM.Import(typeof(System.Delegate)); + internal static readonly Type MulticastDelegate = JVM.Import(typeof(System.MulticastDelegate)); + internal static readonly Type RuntimeTypeHandle = JVM.Import(typeof(System.RuntimeTypeHandle)); + + internal static readonly Type IntPtr = JVM.Import(typeof(System.IntPtr)); + internal static readonly Type Void = JVM.Import(typeof(void)); + internal static readonly Type Boolean = JVM.Import(typeof(System.Boolean)); + internal static readonly Type Byte = JVM.Import(typeof(System.Byte)); + internal static readonly Type SByte = JVM.Import(typeof(System.SByte)); + internal static readonly Type Char = JVM.Import(typeof(System.Char)); + internal static readonly Type Int16 = JVM.Import(typeof(System.Int16)); + internal static readonly Type UInt16 = JVM.Import(typeof(System.UInt16)); + internal static readonly Type Int32 = JVM.Import(typeof(System.Int32)); + internal static readonly Type UInt32 = JVM.Import(typeof(System.UInt32)); + internal static readonly Type Int64 = JVM.Import(typeof(System.Int64)); + internal static readonly Type UInt64 = JVM.Import(typeof(System.UInt64)); + internal static readonly Type Single = JVM.Import(typeof(System.Single)); + internal static readonly Type Double = JVM.Import(typeof(System.Double)); + + internal static readonly Type IsVolatile = JVM.Import(typeof(System.Runtime.CompilerServices.IsVolatile)); + internal static readonly Type SecurityAttribute = JVM.Import(typeof(System.Security.Permissions.SecurityAttribute)); + + // we want deterministics initialization + static Types() { } + } +} diff --git a/runtime/atomic.cs b/runtime/atomic.cs new file mode 100644 index 0000000..cb9d261 --- /dev/null +++ b/runtime/atomic.cs @@ -0,0 +1,158 @@ +/* + Copyright (C) 2007-2011 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +using System; +using System.Collections.Generic; +#if STATIC_COMPILER +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif +using IKVM.Internal; +using InstructionFlags = IKVM.Internal.ClassFile.Method.InstructionFlags; + +static class AtomicReferenceFieldUpdaterEmitter +{ + internal static bool Emit(DynamicTypeWrapper.FinishContext context, TypeWrapper wrapper, CodeEmitter ilgen, ClassFile classFile, int i, ClassFile.Method.Instruction[] code, InstructionFlags[] flags) + { + if (i >= 3 + && (flags[i - 0] & InstructionFlags.BranchTarget) == 0 + && (flags[i - 1] & InstructionFlags.BranchTarget) == 0 + && (flags[i - 2] & InstructionFlags.BranchTarget) == 0 + && (flags[i - 3] & InstructionFlags.BranchTarget) == 0 + && code[i - 1].NormalizedOpCode == NormalizedByteCode.__ldc_nothrow + && code[i - 2].NormalizedOpCode == NormalizedByteCode.__ldc + && code[i - 3].NormalizedOpCode == NormalizedByteCode.__ldc) + { + // we now have a structural match, now we need to make sure that the argument values are what we expect + TypeWrapper tclass = classFile.GetConstantPoolClassType(code[i - 3].Arg1); + TypeWrapper vclass = classFile.GetConstantPoolClassType(code[i - 2].Arg1); + string fieldName = classFile.GetConstantPoolConstantString(code[i - 1].Arg1); + if (tclass == wrapper && !vclass.IsUnloadable && !vclass.IsPrimitive && !vclass.IsNonPrimitiveValueType) + { + FieldWrapper field = wrapper.GetFieldWrapper(fieldName, vclass.SigName); + if (field != null && !field.IsStatic && field.IsVolatile && field.DeclaringType == wrapper && field.FieldTypeWrapper == vclass) + { + // everything matches up, now call the actual emitter + ilgen.Emit(OpCodes.Pop); + ilgen.Emit(OpCodes.Pop); + ilgen.Emit(OpCodes.Pop); + ilgen.Emit(OpCodes.Newobj, context.GetAtomicReferenceFieldUpdater(field)); + return true; + } + } + } + return false; + } + + internal static void EmitImpl(TypeBuilder tb, FieldInfo field) + { + EmitCompareAndSet("compareAndSet", tb, field); + EmitGet(tb, field); + EmitSet("set", tb, field); + } + + private static void EmitCompareAndSet(string name, TypeBuilder tb, FieldInfo field) + { + MethodBuilder compareAndSet = tb.DefineMethod(name, MethodAttributes.Public | MethodAttributes.Virtual, Types.Boolean, new Type[] { Types.Object, Types.Object, Types.Object }); + ILGenerator ilgen = compareAndSet.GetILGenerator(); + ilgen.Emit(OpCodes.Ldarg_1); + ilgen.Emit(OpCodes.Castclass, field.DeclaringType); + ilgen.Emit(OpCodes.Ldflda, field); + ilgen.Emit(OpCodes.Ldarg_3); + ilgen.Emit(OpCodes.Castclass, field.FieldType); + ilgen.Emit(OpCodes.Ldarg_2); + ilgen.Emit(OpCodes.Castclass, field.FieldType); + ilgen.Emit(OpCodes.Call, MakeCompareExchange(field.FieldType)); + ilgen.Emit(OpCodes.Ldarg_2); + ilgen.Emit(OpCodes.Ceq); + ilgen.Emit(OpCodes.Ret); + } + + internal static MethodInfo MakeCompareExchange(Type type) + { + return InterlockedMethods.CompareExchangeOfT.MakeGenericMethod(type); + } + + private static void EmitGet(TypeBuilder tb, FieldInfo field) + { + MethodBuilder get = tb.DefineMethod("get", MethodAttributes.Public | MethodAttributes.Virtual, Types.Object, new Type[] { Types.Object }); + ILGenerator ilgen = get.GetILGenerator(); + ilgen.Emit(OpCodes.Ldarg_1); + ilgen.Emit(OpCodes.Castclass, field.DeclaringType); + ilgen.Emit(OpCodes.Volatile); + ilgen.Emit(OpCodes.Ldfld, field); + ilgen.Emit(OpCodes.Ret); + } + + private static void EmitSet(string name, TypeBuilder tb, FieldInfo field) + { + MethodBuilder set = tb.DefineMethod(name, MethodAttributes.Public | MethodAttributes.Virtual, Types.Void, new Type[] { Types.Object, Types.Object }); + CodeEmitter ilgen = CodeEmitter.Create(set); + ilgen.Emit(OpCodes.Ldarg_1); + ilgen.Emit(OpCodes.Castclass, field.DeclaringType); + ilgen.Emit(OpCodes.Ldarg_2); + ilgen.Emit(OpCodes.Castclass, field.FieldType); + ilgen.Emit(OpCodes.Volatile); + ilgen.Emit(OpCodes.Stfld, field); + ilgen.EmitMemoryBarrier(); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } +} + +static class InterlockedMethods +{ + internal static readonly MethodInfo AddInt32; + internal static readonly MethodInfo CompareExchangeInt32; + internal static readonly MethodInfo CompareExchangeInt64; + internal static readonly MethodInfo CompareExchangeOfT; + internal static readonly MethodInfo ExchangeOfT; + + static InterlockedMethods() + { + Type type = JVM.Import(typeof(System.Threading.Interlocked)); + AddInt32 = type.GetMethod("Add", new Type[] { Types.Int32.MakeByRefType(), Types.Int32 }); + CompareExchangeInt32 = type.GetMethod("CompareExchange", new Type[] { Types.Int32.MakeByRefType(), Types.Int32, Types.Int32 }); + CompareExchangeInt64 = type.GetMethod("CompareExchange", new Type[] { Types.Int64.MakeByRefType(), Types.Int64, Types.Int64 }); + foreach (MethodInfo m in type.GetMethods()) + { + if (m.IsGenericMethodDefinition) + { + switch (m.Name) + { + case "CompareExchange": + CompareExchangeOfT = m; + break; + case "Exchange": + ExchangeOfT = m; + break; + } + } + } + } +} diff --git a/runtime/attributes.cs b/runtime/attributes.cs new file mode 100644 index 0000000..78ab40b --- /dev/null +++ b/runtime/attributes.cs @@ -0,0 +1,1010 @@ +/* + Copyright (C) 2002-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using IKVM.Internal; +#if STATIC_COMPILER || STUB_GENERATOR +using IKVM.Reflection; +using Type = IKVM.Reflection.Type; +#else +using System.Reflection; +#endif + +namespace IKVM.Attributes +{ + [AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Delegate)] + public sealed class SourceFileAttribute : Attribute + { + private string file; + + public SourceFileAttribute(string file) + { + this.file = file; + } + + public string SourceFile + { + get + { + return file; + } + } + } + + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor)] + public sealed class LineNumberTableAttribute : Attribute + { + private byte[] table; + + public LineNumberTableAttribute(ushort lineno) + { + LineNumberWriter w = new LineNumberWriter(1); + w.AddMapping(0, lineno); + table = w.ToArray(); + } + + public LineNumberTableAttribute(byte[] table) + { + this.table = table; + } + + public sealed class LineNumberWriter + { + private System.IO.MemoryStream stream; + private int prevILOffset; + private int prevLineNum; + private int count; + + public LineNumberWriter(int estimatedCount) + { + stream = new System.IO.MemoryStream(estimatedCount * 2); + } + + public void AddMapping(int ilOffset, int linenumber) + { + if(count == 0) + { + if(ilOffset == 0 && linenumber != 0) + { + prevLineNum = linenumber; + count++; + WritePackedInteger(linenumber - (64 + 50)); + return; + } + else + { + prevLineNum = linenumber & ~3; + WritePackedInteger(((-prevLineNum / 4) - (64 + 50))); + } + } + bool pc_overflow; + bool lineno_overflow; + byte lead; + int deltaPC = ilOffset - prevILOffset; + if(deltaPC >= 0 && deltaPC < 31) + { + lead = (byte)deltaPC; + pc_overflow = false; + } + else + { + lead = (byte)31; + pc_overflow = true; + } + int deltaLineNo = linenumber - prevLineNum; + const int bias = 2; + if(deltaLineNo >= -bias && deltaLineNo < 7 - bias) + { + lead |= (byte)((deltaLineNo + bias) << 5); + lineno_overflow = false; + } + else + { + lead |= (byte)(7 << 5); + lineno_overflow = true; + } + stream.WriteByte(lead); + if(pc_overflow) + { + WritePackedInteger(deltaPC - (64 + 31)); + } + if(lineno_overflow) + { + WritePackedInteger(deltaLineNo); + } + prevILOffset = ilOffset; + prevLineNum = linenumber; + count++; + } + + public int Count + { + get + { + return count; + } + } + + public int LineNo + { + get + { + return prevLineNum; + } + } + + public byte[] ToArray() + { + return stream.ToArray(); + } + + /* + * packed integer format: + * ---------------------- + * + * First byte: + * 00 - 7F Single byte integer (-64 - 63) + * 80 - BF Double byte integer (-8192 - 8191) + * C0 - DF Triple byte integer (-1048576 - 1048576) + * E0 - FE Reserved + * FF Five byte integer + */ + private void WritePackedInteger(int val) + { + if(val >= -64 && val < 64) + { + val += 64; + stream.WriteByte((byte)val); + } + else if(val >= -8192 && val < 8192) + { + val += 8192; + stream.WriteByte((byte)(0x80 + (val >> 8))); + stream.WriteByte((byte)val); + } + else if(val >= -1048576 && val < 1048576) + { + val += 1048576; + stream.WriteByte((byte)(0xC0 + (val >> 16))); + stream.WriteByte((byte)(val >> 8)); + stream.WriteByte((byte)val); + } + else + { + stream.WriteByte(0xFF); + stream.WriteByte((byte)(val >> 24)); + stream.WriteByte((byte)(val >> 16)); + stream.WriteByte((byte)(val >> 8)); + stream.WriteByte((byte)(val >> 0)); + } + } + } + + private int ReadPackedInteger(ref int position) + { + byte b = table[position++]; + if(b < 128) + { + return b - 64; + } + else if((b & 0xC0) == 0x80) + { + return ((b & 0x7F) << 8) + table[position++] - 8192; + } + else if((b & 0xE0) == 0xC0) + { + int val = ((b & 0x3F) << 16); + val += (table[position++] << 8); + val += table[position++]; + return val - 1048576; + } + else if(b == 0xFF) + { + int val = table[position++] << 24; + val += table[position++] << 16; + val += table[position++] << 8; + val += table[position++] << 0; + return val; + } + else + { + throw new InvalidProgramException(); + } + } + + public int GetLineNumber(int ilOffset) + { + int i = 0; + int prevILOffset = 0; + int prevLineNum = ReadPackedInteger(ref i) + (64 + 50); + int line; + if(prevLineNum > 0) + { + line = prevLineNum; + } + else + { + prevLineNum = 4 * -prevLineNum; + line = -1; + } + while(i < table.Length) + { + byte lead = table[i++]; + int deltaPC = lead & 31; + int deltaLineNo = (lead >> 5) - 2; + if(deltaPC == 31) + { + deltaPC = ReadPackedInteger(ref i) + (64 + 31); + } + if(deltaLineNo == 5) + { + deltaLineNo = ReadPackedInteger(ref i); + } + int currILOffset = prevILOffset + deltaPC; + if(currILOffset > ilOffset) + { + return line; + } + line = prevLineNum + deltaLineNo; + prevILOffset = currILOffset; + prevLineNum = line; + } + return line; + } + } + + [AttributeUsage(AttributeTargets.Class)] + public sealed class ExceptionIsUnsafeForMappingAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Interface)] + public sealed class RemappedInterfaceMethodAttribute : Attribute + { + private string name; + private string mappedTo; + private string[] throws; + + public RemappedInterfaceMethodAttribute(string name, string mappedTo, string[] throws) + { + this.name = name; + this.mappedTo = mappedTo; + this.throws = throws; + } + + public string Name + { + get + { + return name; + } + } + + public string MappedTo + { + get + { + return mappedTo; + } + } + + public string[] Throws + { + get + { + return throws; + } + } + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class RemappedClassAttribute : Attribute + { + private string name; + private Type remappedType; + +#if STUB_GENERATOR + public RemappedClassAttribute(string name, System.Type remappedType) + { + } +#endif + + public RemappedClassAttribute(string name, Type remappedType) + { + this.name = name; + this.remappedType = remappedType; + } + + public string Name + { + get + { + return name; + } + } + + public Type RemappedType + { + get + { + return remappedType; + } + } + } + + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] + public sealed class RemappedTypeAttribute : Attribute + { + private Type type; + +#if STUB_GENERATOR + public RemappedTypeAttribute(System.Type type) + { + } +#endif + + public RemappedTypeAttribute(Type type) + { + this.type = type; + } + + public Type Type + { + get + { + return type; + } + } + } + + [AttributeUsage(AttributeTargets.Module)] + public sealed class JavaModuleAttribute : Attribute + { + private string[] classMap; + private string[] jars; + + public JavaModuleAttribute() + { + } + + public JavaModuleAttribute(string[] classMap) + { + this.classMap = UnicodeUtil.UnescapeInvalidSurrogates(classMap); + } + + public string[] GetClassMap() + { + return classMap; + } + + public string[] Jars + { + get { return jars; } + set { jars = value; } + } + } + + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Assembly)] + public sealed class NoPackagePrefixAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Struct)] + public sealed class GhostInterfaceAttribute : Attribute + { + } + + // Whenever the VM or compiler generates a helper class/method/field, it should be marked + // with this custom attribute, so that it can be hidden from Java. + [AttributeUsage(AttributeTargets.All)] + public sealed class HideFromJavaAttribute : Attribute + { + private readonly HideFromJavaFlags flags; + + public HideFromJavaAttribute() + { + flags = HideFromJavaFlags.All; + } + + public HideFromJavaAttribute(HideFromJavaFlags flags) + { + this.flags = flags; + } + + public HideFromJavaFlags Flags + { + get { return flags; } + } + } + + [Flags] + public enum HideFromJavaFlags : byte + { + All = Code | Reflection | StackWalk | StackTrace, + None = 0, + Code = 1, + Reflection = 2, + StackWalk = 4, // used for LambdaForm$Compiled + StackTrace = 8, // used for LambdaForm$Hidden + } + + [Flags] + public enum Modifiers : ushort + { + Public = 0x0001, + Private = 0x0002, + Protected = 0x0004, + Static = 0x0008, + Final = 0x0010, + Super = 0x0020, + Synchronized = 0x0020, + Volatile = 0x0040, + Bridge = 0x0040, + Transient = 0x0080, + VarArgs = 0x0080, + Native = 0x0100, + Interface = 0x0200, + Abstract = 0x0400, + Strictfp = 0x0800, + Synthetic = 0x1000, + Annotation = 0x2000, + Enum = 0x4000, + + // Masks + AccessMask = Public | Private | Protected + } + + [AttributeUsage(AttributeTargets.All)] + public sealed class ModifiersAttribute : Attribute + { + private Modifiers modifiers; + private bool isInternal; + + public ModifiersAttribute(Modifiers modifiers) + { + this.modifiers = modifiers; + } + + public ModifiersAttribute(Modifiers modifiers, bool isInternal) + { + this.modifiers = modifiers; + this.isInternal = isInternal; + } + + public bool IsInternal + { + get + { + return isInternal; + } + } + + public Modifiers Modifiers + { + get + { + return modifiers; + } + } + } + + [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Field)] + public sealed class NameSigAttribute : Attribute + { + private string name; + private string sig; + + public NameSigAttribute(string name, string sig) + { + this.name = UnicodeUtil.UnescapeInvalidSurrogates(name); + this.sig = UnicodeUtil.UnescapeInvalidSurrogates(sig); + } + + public string Name + { + get + { + return name; + } + } + + public string Sig + { + get + { + return sig; + } + } + } + + [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method)] + public sealed class ThrowsAttribute : Attribute + { + internal string[] classes; + internal Type[] types; + + // this constructor is used by ikvmc, the other constructors are for use in other .NET languages + public ThrowsAttribute(string[] classes) + { + this.classes = UnicodeUtil.UnescapeInvalidSurrogates(classes); + } + + public ThrowsAttribute(Type type) + : this(new Type[] { type }) + { + } + + public ThrowsAttribute(params Type[] types) + { + this.types = types; + } + + // dotted Java class names (e.g. java.lang.Throwable) + [Obsolete] + public string[] Classes + { + get + { + return classes; + } + } + } + + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] + public sealed class ImplementsAttribute : Attribute + { + private string[] interfaces; + + // NOTE this is not CLS compliant, so maybe we should have a couple of overloads + public ImplementsAttribute(string[] interfaces) + { + this.interfaces = UnicodeUtil.UnescapeInvalidSurrogates(interfaces); + } + + public string[] Interfaces + { + get + { + return interfaces; + } + } + } + + // NOTE this attribute is also used by annotation attribute classes, + // to give them a different name in the Java world ($Proxy[Annotation]). + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] + public sealed class InnerClassAttribute : Attribute + { + private string innerClassName; + private Modifiers modifiers; + + public InnerClassAttribute(string innerClassName, Modifiers modifiers) + { + this.innerClassName = UnicodeUtil.UnescapeInvalidSurrogates(innerClassName); + this.modifiers = modifiers; + } + + public string InnerClassName + { + get + { + return innerClassName; + } + } + + public Modifiers Modifiers + { + get + { + return modifiers; + } + } + } + + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true)] + public sealed class NonNestedInnerClassAttribute : Attribute + { + private string innerClassName; + + public NonNestedInnerClassAttribute(string innerClassName) + { + this.innerClassName = UnicodeUtil.UnescapeInvalidSurrogates(innerClassName); + } + + public string InnerClassName + { + get + { + return innerClassName; + } + } + } + + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] + public sealed class NonNestedOuterClassAttribute : Attribute + { + private string outerClassName; + + public NonNestedOuterClassAttribute(string outerClassName) + { + this.outerClassName = UnicodeUtil.UnescapeInvalidSurrogates(outerClassName); + } + + public string OuterClassName + { + get + { + return outerClassName; + } + } + } + + [AttributeUsage(AttributeTargets.Assembly)] + public sealed class CustomAssemblyClassLoaderAttribute : Attribute + { + private Type type; + + public CustomAssemblyClassLoaderAttribute(Type type) + { + this.type = type; + } + + public Type Type + { + get + { + return type; + } + } + } + + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Field)] + public sealed class SignatureAttribute : Attribute + { + private string signature; + + public SignatureAttribute(string signature) + { + this.signature = UnicodeUtil.UnescapeInvalidSurrogates(signature); + } + + public string Signature + { + get + { + return signature; + } + } + } + + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] + public sealed class EnclosingMethodAttribute : Attribute + { + private string className; + private string methodName; + private string methodSig; + + public EnclosingMethodAttribute(string className, string methodName, string methodSig) + { + this.className = UnicodeUtil.UnescapeInvalidSurrogates(className); + this.methodName = UnicodeUtil.UnescapeInvalidSurrogates(methodName); + this.methodSig = UnicodeUtil.UnescapeInvalidSurrogates(methodSig); + } + + internal EnclosingMethodAttribute SetClassName(Type type) + { + if (className == null) + { + className = IKVM.Internal.ClassLoaderWrapper.GetWrapperFromType(type.DeclaringType).Name; + } + return this; + } + + public string ClassName + { + get + { + return className; + } + } + + public string MethodName + { + get + { + return methodName; + } + } + + public string MethodSignature + { + get + { + return methodSig; + } + } + } + + [AttributeUsage(AttributeTargets.Method)] + public sealed class AnnotationDefaultAttribute : Attribute + { + public const byte TAG_ENUM = (byte)'e'; + public const byte TAG_CLASS = (byte)'c'; + public const byte TAG_ANNOTATION = (byte)'@'; + public const byte TAG_ARRAY = (byte)'['; + public const byte TAG_ERROR = (byte)'?'; + private object defaultValue; + + // element_value encoding: + // primitives: + // boxed values + // string: + // string + // enum: + // new object[] { (byte)'e', "", "" } + // class: + // new object[] { (byte)'c', "" } + // annotation: + // new object[] { (byte)'@', "", ("name", (element_value))* } + // array: + // new object[] { (byte)'[', (element_value)* } + // error: + // new object[] { (byte)'?', "", "" } + public AnnotationDefaultAttribute(object defaultValue) + { + this.defaultValue = Unescape(defaultValue); + } + + public object Value + { + get + { + return defaultValue; + } + } + + internal static object Escape(object obj) + { + return EscapeOrUnescape(obj, true); + } + + internal static object Unescape(object obj) + { + return EscapeOrUnescape(obj, false); + } + + private static object EscapeOrUnescape(object obj, bool escape) + { + string str = obj as string; + if (str != null) + { + return escape + ? UnicodeUtil.EscapeInvalidSurrogates(str) + : UnicodeUtil.UnescapeInvalidSurrogates(str); + } + object[] arr = obj as object[]; + if (arr != null) + { + for (int i = 0; i < arr.Length; i++) + { + arr[i] = EscapeOrUnescape(arr[i], escape); + } + } + return obj; + } + } + + [AttributeUsage(AttributeTargets.Interface)] + public sealed class AnnotationAttributeAttribute : Attribute + { + private string attributeType; + + public AnnotationAttributeAttribute(string attributeType) + { + this.attributeType = UnicodeUtil.UnescapeInvalidSurrogates(attributeType); + } + + public string AttributeType + { + get + { + return attributeType; + } + } + } + + [AttributeUsage(AttributeTargets.Module, AllowMultiple = true)] + public sealed class PackageListAttribute : Attribute + { + internal string jar; + internal string[] packages; + + public PackageListAttribute(string jar, string[] packages) + { + this.jar = jar; + this.packages = UnicodeUtil.UnescapeInvalidSurrogates(packages); + } + + public string[] GetPackages() + { + return packages; + } + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class JavaResourceAttribute : Attribute + { + private readonly string javaName; + private readonly string resourceName; + + public JavaResourceAttribute(string javaName, string resourceName) + { + this.javaName = javaName; + this.resourceName = resourceName; + } + + public string JavaName + { + get { return javaName; } + } + + public string ResourceName + { + get { return resourceName; } + } + } + + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Parameter, AllowMultiple = false)] + public sealed class DynamicAnnotationAttribute : Attribute + { + private readonly object[] definition; + + public DynamicAnnotationAttribute(object[] definition) + { + this.definition = (object[])AnnotationDefaultAttribute.Unescape(definition); + } + + public object[] Definition + { + get { return definition; } + } + } + + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor)] + public sealed class MethodParametersAttribute : Attribute + { + private readonly Modifiers[] modifiers; + + public MethodParametersAttribute(Modifiers[] modifiers) + { + this.modifiers = modifiers; + } + + public Modifiers[] Modifiers + { + get { return modifiers; } + } + + public bool IsMalformed + { + get { return modifiers == null; } + } + } + + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] + public sealed class ConstantPoolAttribute : Attribute + { + internal readonly object[] constantPool; + + public ConstantPoolAttribute(object[] constantPool) + { + this.constantPool = Decompress(constantPool); + } + + internal static object[] Decompress(object[] constantPool) + { + List list = new List(); + foreach (object obj in constantPool) + { + int emptySlots = obj as byte? ?? obj as ushort? ?? 0; + if (emptySlots == 0) + { + list.Add(Unescape(obj)); + } + else + { + for (int i = 0; i < emptySlots; i++) + { + list.Add(null); + } + } + } + return list.ToArray(); + } + + private static object Unescape(object obj) + { + string str = obj as string; + if (str != null) + { + obj = UnicodeUtil.UnescapeInvalidSurrogates(str); + } + return obj; + } + + internal static object[] Compress(object[] constantPool, bool[] inUse) + { + int length = constantPool.Length; + while (!inUse[length - 1]) + { + length--; + } + int write = 0; + for (int read = 0; read < length; read++) + { + int start = read; + while (!inUse[read]) + { + read++; + } + int emptySlots = read - start; + if (emptySlots > 255) + { + constantPool[write++] = (ushort)emptySlots; + } + else if (emptySlots > 0) + { + constantPool[write++] = (byte)emptySlots; + } + constantPool[write++] = Escape(constantPool[read]); + } + Array.Resize(ref constantPool, write); + return constantPool; + } + + private static object Escape(object obj) + { + string str = obj as string; + if (str != null) + { + obj = UnicodeUtil.EscapeInvalidSurrogates(str); + } + return obj; + } + } + + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Field)] + public sealed class RuntimeVisibleTypeAnnotationsAttribute : Attribute + { + internal readonly byte[] data; + + public RuntimeVisibleTypeAnnotationsAttribute(byte[] data) + { + this.data = data; + } + } + + // used in custom modifier for access stubs + public static class AccessStub { } +} diff --git a/runtime/common.cs b/runtime/common.cs new file mode 100644 index 0000000..74db684 --- /dev/null +++ b/runtime/common.cs @@ -0,0 +1,631 @@ +/* + Copyright (C) 2002-2015 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using IKVM.Attributes; +using IKVM.Runtime; +using IKVM.Internal; +using AssemblyClassLoader_ = IKVM.Internal.AssemblyClassLoader; +using jlClass = java.lang.Class; +#if !FIRST_PASS +using NegativeArraySizeException = java.lang.NegativeArraySizeException; +using IllegalArgumentException = java.lang.IllegalArgumentException; +using IllegalAccessException = java.lang.IllegalAccessException; +using NumberFormatException = java.lang.NumberFormatException; +using jlNoClassDefFoundError = java.lang.NoClassDefFoundError; +using jlrConstructor = java.lang.reflect.Constructor; +using jlrField = java.lang.reflect.Field; +#endif + +namespace IKVM.NativeCode.gnu.java.net.protocol.ikvmres +{ + static class Handler + { + public static byte[] GenerateStub(jlClass c) + { + MemoryStream mem = new MemoryStream(); +#if !FIRST_PASS + bool includeNonPublicInterfaces = !"true".Equals(global::java.lang.Props.props.getProperty("ikvm.stubgen.skipNonPublicInterfaces"), StringComparison.OrdinalIgnoreCase); + IKVM.StubGen.StubGenerator.WriteClass(mem, TypeWrapper.FromClass(c), includeNonPublicInterfaces, false, false, true); +#endif + return mem.ToArray(); + } + + public static Stream ReadResourceFromAssemblyImpl(Assembly asm, string resource) + { + // chop off the leading slash + resource = resource.Substring(1); + string mangledName = JVM.MangleResourceName(resource); + ManifestResourceInfo info = asm.GetManifestResourceInfo(mangledName); + if(info != null && info.FileName != null) + { + return asm.GetManifestResourceStream(mangledName); + } + Stream s = asm.GetManifestResourceStream(mangledName); + if(s == null) + { + Tracer.Warning(Tracer.ClassLoading, "Resource \"{0}\" not found in {1}", resource, asm.FullName); + throw new FileNotFoundException("resource " + resource + " not found in assembly " + asm.FullName); + } + switch (s.ReadByte()) + { + case 0: + Tracer.Info(Tracer.ClassLoading, "Reading resource \"{0}\" from {1}", resource, asm.FullName); + return s; + case 1: + Tracer.Info(Tracer.ClassLoading, "Reading compressed resource \"{0}\" from {1}", resource, asm.FullName); + return new System.IO.Compression.DeflateStream(s, System.IO.Compression.CompressionMode.Decompress, false); + default: + Tracer.Error(Tracer.ClassLoading, "Resource \"{0}\" in {1} has an unsupported encoding", resource, asm.FullName); + throw new IOException("Unsupported resource encoding for resource " + resource + " found in assembly " + asm.FullName); + } + } + + public static object LoadClassFromAssembly(Assembly asm, string className) + { + TypeWrapper tw = AssemblyClassLoader.FromAssembly(asm).LoadClassByDottedNameFast(className); + if(tw != null) + { + return tw.ClassObject; + } + return null; + } + + public static Assembly LoadAssembly(string name) + { + return Assembly.Load(name); + } + + public static global::java.lang.ClassLoader GetGenericClassLoaderById(int id) + { + return ClassLoaderWrapper.GetGenericClassLoaderById(id).GetJavaClassLoader(); + } + } +} + +namespace IKVM.NativeCode.java.lang +{ + static class VMSystemProperties + { + public static string getVirtualFileSystemRoot() + { + return VirtualFileSystem.RootPath; + } + + public static string getBootClassPath() + { + return VirtualFileSystem.GetAssemblyClassesPath(JVM.CoreAssembly); + } + + public static string getStdoutEncoding() + { + return IsWindowsConsole(true) ? GetConsoleEncoding() : null; + } + + public static string getStderrEncoding() + { + return IsWindowsConsole(false) ? GetConsoleEncoding() : null; + } + + public static FileVersionInfo getKernel32FileVersionInfo() + { + try + { + foreach (ProcessModule module in Process.GetCurrentProcess().Modules) + { + if (string.Compare(module.ModuleName, "kernel32.dll", StringComparison.OrdinalIgnoreCase) == 0) + { + return module.FileVersionInfo; + } + } + } + catch + { + } + return null; + } + + private static bool IsWindowsConsole(bool stdout) + { + if (Environment.OSVersion.Platform != PlatformID.Win32NT) + { + return false; + } + // these properties are available starting with .NET 4.5 + PropertyInfo pi = typeof(Console).GetProperty(stdout ? "IsOutputRedirected" : "IsErrorRedirected"); + if (pi != null) + { + return !(bool)pi.GetValue(null, null); + } + const int STD_OUTPUT_HANDLE = -11; + const int STD_ERROR_HANDLE = -12; + IntPtr handle = GetStdHandle(stdout ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE); + if (handle == IntPtr.Zero) + { + return false; + } + const int FILE_TYPE_CHAR = 2; + return GetFileType(handle) == FILE_TYPE_CHAR; + } + + private static string GetConsoleEncoding() + { + int codepage = Console.InputEncoding.CodePage; + return codepage >= 847 && codepage <= 950 + ? "ms" + codepage + : "cp" + codepage; + } + + [DllImport("kernel32")] + private static extern int GetFileType(IntPtr hFile); + + [DllImport("kernel32")] + private static extern IntPtr GetStdHandle(int nStdHandle); + } +} + +namespace IKVM.NativeCode.ikvm.@internal +{ + static class CallerID + { + public static jlClass GetClass(object obj) + { + return ClassLoaderWrapper.GetWrapperFromType(obj.GetType().DeclaringType).ClassObject; + } + + public static global::java.lang.ClassLoader GetClassLoader(object obj) + { + return ClassLoaderWrapper.GetWrapperFromType(obj.GetType().DeclaringType).GetClassLoader().GetJavaClassLoader(); + } + + public static global::java.lang.ClassLoader GetAssemblyClassLoader(Assembly asm) + { + return AssemblyClassLoader.FromAssembly(asm).GetJavaClassLoader(); + } + } + + static class AnnotationAttributeBase + { + public static object[] unescapeInvalidSurrogates(object[] def) + { + return (object[])AnnotationDefaultAttribute.Unescape(def); + } + + public static object newAnnotationInvocationHandler(jlClass type, object memberValues) + { +#if FIRST_PASS + return null; +#else + return new global::sun.reflect.annotation.AnnotationInvocationHandler(type, (global::java.util.Map)memberValues); +#endif + } + + public static object newAnnotationTypeMismatchExceptionProxy(string msg) + { +#if FIRST_PASS + return null; +#else + return new global::sun.reflect.annotation.AnnotationTypeMismatchExceptionProxy(msg); +#endif + } + } +} + +namespace IKVM.NativeCode.ikvm.runtime +{ + static class AssemblyClassLoader + { + public static void setWrapper(global::java.lang.ClassLoader _this, Assembly assembly) + { + ClassLoaderWrapper.SetWrapperForClassLoader(_this, IKVM.Internal.AssemblyClassLoader.FromAssembly(assembly)); + } + + public static global::java.lang.Class loadClass(global::java.lang.ClassLoader _this, string name, bool resolve) + { +#if FIRST_PASS + return null; +#else + try + { + if (!global::java.lang.ClassLoader.checkName(name)) + { + throw new ClassNotFoundException(name); + } + AssemblyClassLoader_ wrapper = (AssemblyClassLoader_)ClassLoaderWrapper.GetClassLoaderWrapper(_this); + TypeWrapper tw = wrapper.LoadClass(name); + if (tw == null) + { + Tracer.Info(Tracer.ClassLoading, "Failed to load class \"{0}\" from {1}", name, _this); + global::java.lang.Throwable.suppressFillInStackTrace = true; + throw new global::java.lang.ClassNotFoundException(name); + } + Tracer.Info(Tracer.ClassLoading, "Loaded class \"{0}\" from {1}", name, _this); + return tw.ClassObject; + } + catch (ClassNotFoundException x) + { + Tracer.Info(Tracer.ClassLoading, "Failed to load class \"{0}\" from {1}", name, _this); + throw new global::java.lang.ClassNotFoundException(x.Message); + } + catch (ClassLoadingException x) + { + Tracer.Info(Tracer.ClassLoading, "Failed to load class \"{0}\" from {1}", name, _this); + throw x.InnerException; + } + catch (RetargetableJavaException x) + { + Tracer.Info(Tracer.ClassLoading, "Failed to load class \"{0}\" from {1}", name, _this); + throw x.ToJava(); + } +#endif + } + + public static global::java.net.URL getResource(global::java.lang.ClassLoader _this, string name) + { +#if !FIRST_PASS + AssemblyClassLoader_ wrapper = (AssemblyClassLoader_)ClassLoaderWrapper.GetClassLoaderWrapper(_this); + foreach (global::java.net.URL url in wrapper.GetResources(name)) + { + return url; + } +#endif + return null; + } + + public static global::java.util.Enumeration getResources(global::java.lang.ClassLoader _this, string name) + { +#if FIRST_PASS + return null; +#else + return new global::ikvm.runtime.EnumerationWrapper(((AssemblyClassLoader_)ClassLoaderWrapper.GetClassLoaderWrapper(_this)).GetResources(name)); +#endif + } + + public static global::java.net.URL findResource(global::java.lang.ClassLoader _this, string name) + { +#if !FIRST_PASS + AssemblyClassLoader_ wrapper = (AssemblyClassLoader_)ClassLoaderWrapper.GetClassLoaderWrapper(_this); + foreach (global::java.net.URL url in wrapper.FindResources(name)) + { + return url; + } +#endif + return null; + } + + public static global::java.util.Enumeration findResources(global::java.lang.ClassLoader _this, string name) + { +#if FIRST_PASS + return null; +#else + return new global::ikvm.runtime.EnumerationWrapper(((AssemblyClassLoader_)ClassLoaderWrapper.GetClassLoaderWrapper(_this)).FindResources(name)); +#endif + } + +#if !FIRST_PASS + private static global::java.net.URL GetCodeBase(Assembly assembly) + { + try + { + return new global::java.net.URL(assembly.CodeBase); + } + catch (NotSupportedException) + { + } + catch (global::java.net.MalformedURLException) + { + } + return null; + } + + private static string GetAttributeValue(global::java.util.jar.Attributes.Name name, global::java.util.jar.Attributes first, global::java.util.jar.Attributes second) + { + string result = null; + if (first != null) + { + result = first.getValue(name); + } + if (second != null && result == null) + { + result = second.getValue(name); + } + return result; + } +#endif + + public static void lazyDefinePackages(global::java.lang.ClassLoader _this) + { +#if !FIRST_PASS + AssemblyClassLoader_ wrapper = (AssemblyClassLoader_)ClassLoaderWrapper.GetClassLoaderWrapper(_this); + global::java.net.URL sealBase = GetCodeBase(wrapper.MainAssembly); + foreach (KeyValuePair packages in wrapper.GetPackageInfo()) + { + global::java.util.jar.Manifest manifest = null; + global::java.util.jar.Attributes attr = null; + if (packages.Key != null) + { + global::java.util.jar.JarFile jarFile = new global::java.util.jar.JarFile(VirtualFileSystem.GetAssemblyResourcesPath(wrapper.MainAssembly) + packages.Key); + manifest = jarFile.getManifest(); + } + if (manifest != null) + { + attr = manifest.getMainAttributes(); + } + foreach (string name in packages.Value) + { + if (_this.getPackage(name) == null) + { + global::java.util.jar.Attributes entryAttr = null; + if (manifest != null) + { + entryAttr = manifest.getAttributes(name.Replace('.', '/') + '/'); + } + _this.definePackage(name, + GetAttributeValue(global::java.util.jar.Attributes.Name.SPECIFICATION_TITLE, entryAttr, attr), + GetAttributeValue(global::java.util.jar.Attributes.Name.SPECIFICATION_VERSION, entryAttr, attr), + GetAttributeValue(global::java.util.jar.Attributes.Name.SPECIFICATION_VENDOR, entryAttr, attr), + GetAttributeValue(global::java.util.jar.Attributes.Name.IMPLEMENTATION_TITLE, entryAttr, attr), + GetAttributeValue(global::java.util.jar.Attributes.Name.IMPLEMENTATION_VERSION, entryAttr, attr), + GetAttributeValue(global::java.util.jar.Attributes.Name.IMPLEMENTATION_VENDOR, entryAttr, attr), + "true".Equals(GetAttributeValue(global::java.util.jar.Attributes.Name.SEALED, entryAttr, attr), StringComparison.OrdinalIgnoreCase) ? sealBase : null); + } + } + } +#endif + } + + public static string toString(global::java.lang.ClassLoader _this) + { + return ((AssemblyClassLoader_)ClassLoaderWrapper.GetClassLoaderWrapper(_this)).MainAssembly.FullName; + } + + public static global::java.lang.ClassLoader getAssemblyClassLoader(Assembly asm) + { + // note that we don't do a security check here, because if you have the Assembly object, + // you can already get at all the types in it. + return AssemblyClassLoader_.FromAssembly(asm).GetJavaClassLoader(); + } + } + + static class AppDomainAssemblyClassLoader + { + public static object loadClassFromAssembly(Assembly asm, string className) + { + if(ReflectUtil.IsDynamicAssembly(asm)) + { + return null; + } + TypeWrapper tw = IKVM.Internal.AssemblyClassLoader.FromAssembly(asm).DoLoad(className); + return tw != null ? tw.ClassObject : null; + } + + private static IEnumerable FindResources(string name) + { + List done = new List(); + foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) + { + if (!ReflectUtil.IsDynamicAssembly(asm)) + { + IKVM.Internal.AssemblyClassLoader acl = IKVM.Internal.AssemblyClassLoader.FromAssembly(asm); + if (!done.Contains(acl)) + { + done.Add(acl); + foreach (global::java.net.URL url in acl.FindResources(name)) + { + yield return url; + } + } + } + } + } + + public static global::java.net.URL findResource(object thisObj, string name) + { + foreach (global::java.net.URL url in FindResources(name)) + { + return url; + } + return null; + } + + public static void getResources(global::java.util.Vector v, string name) + { +#if !FIRST_PASS + foreach (global::java.net.URL url in FindResources(name)) + { + if (url != null && !v.contains(url)) + { + v.add(url); + } + } +#endif + } + } + + static class GenericClassLoader + { + public static string toString(global::java.lang.ClassLoader _this) + { + return ((GenericClassLoaderWrapper)ClassLoaderWrapper.GetClassLoaderWrapper(_this)).GetName(); + } + + public static global::java.util.Enumeration getResources(global::java.lang.ClassLoader _this, string name) + { + return ((GenericClassLoaderWrapper)ClassLoaderWrapper.GetClassLoaderWrapper(_this)).GetResources(name); + } + + public static global::java.net.URL findResource(global::java.lang.ClassLoader _this, string name) + { + return ((GenericClassLoaderWrapper)ClassLoaderWrapper.GetClassLoaderWrapper(_this)).FindResource(name); + } + } + + static class Util + { + public static jlClass getClassFromObject(object o) + { + return GetTypeWrapperFromObject(o).ClassObject; + } + + internal static TypeWrapper GetTypeWrapperFromObject(object o) + { + TypeWrapper ghostType = GhostTag.GetTag(o); + if(ghostType != null) + { + return ghostType; + } + Type t = o.GetType(); + if(t.IsPrimitive || (ClassLoaderWrapper.IsRemappedType(t) && !t.IsSealed)) + { + return DotNetTypeWrapper.GetWrapperFromDotNetType(t); + } + for(; ; ) + { + TypeWrapper tw = ClassLoaderWrapper.GetWrapperFromType(t); + // if GetWrapperFromType returns null (or if tw.IsAbstract), that + // must mean that the Type of the object is an implementation helper class + // (e.g. an AtomicReferenceFieldUpdater or ThreadLocal instrinsic subclass) + if(tw != null && (!tw.IsAbstract || tw.IsArray)) + { + return tw; + } + t = t.BaseType; + } + } + + public static jlClass getClassFromTypeHandle(RuntimeTypeHandle handle) + { + Type t = Type.GetTypeFromHandle(handle); + if(t.IsPrimitive || ClassLoaderWrapper.IsRemappedType(t) || t == typeof(void)) + { + return DotNetTypeWrapper.GetWrapperFromDotNetType(t).ClassObject; + } + if(!IsVisibleAsClass(t)) + { + return null; + } + TypeWrapper tw = ClassLoaderWrapper.GetWrapperFromType(t); + if(tw != null) + { + return tw.ClassObject; + } + return null; + } + + public static jlClass getClassFromTypeHandle(RuntimeTypeHandle handle, int rank) + { + Type t = Type.GetTypeFromHandle(handle); + if(t.IsPrimitive || ClassLoaderWrapper.IsRemappedType(t) || t == typeof(void)) + { + return DotNetTypeWrapper.GetWrapperFromDotNetType(t).MakeArrayType(rank).ClassObject; + } + if(!IsVisibleAsClass(t)) + { + return null; + } + TypeWrapper tw = ClassLoaderWrapper.GetWrapperFromType(t); + if(tw != null) + { + return tw.MakeArrayType(rank).ClassObject; + } + return null; + } + + public static jlClass getFriendlyClassFromType(Type type) + { + int rank = 0; + while(ReflectUtil.IsVector(type)) + { + type = type.GetElementType(); + rank++; + } + if(type.DeclaringType != null + && AttributeHelper.IsGhostInterface(type.DeclaringType)) + { + type = type.DeclaringType; + } + if(!IsVisibleAsClass(type)) + { + return null; + } + TypeWrapper wrapper = ClassLoaderWrapper.GetWrapperFromType(type); + if(wrapper == null) + { + return null; + } + if(rank > 0) + { + wrapper = wrapper.MakeArrayType(rank); + } + return wrapper.ClassObject; + } + + private static bool IsVisibleAsClass(Type type) + { + while (type.HasElementType) + { + if (type.IsPointer || type.IsByRef) + { + return false; + } + type = type.GetElementType(); + } + if (type.ContainsGenericParameters && !type.IsGenericTypeDefinition) + { + return false; + } + System.Reflection.Emit.TypeBuilder tb = type as System.Reflection.Emit.TypeBuilder; + if (tb != null && !tb.IsCreated()) + { + return false; + } + return true; + } + + public static Type getInstanceTypeFromClass(jlClass clazz) + { + TypeWrapper wrapper = TypeWrapper.FromClass(clazz); + if(wrapper.IsRemapped && wrapper.IsFinal) + { + return wrapper.TypeAsTBD; + } + return wrapper.TypeAsBaseType; + } + + [HideFromJava] + public static Exception mapException(Exception x) + { + return ExceptionHelper.MapException(x, true, false); + } + + public static Exception unmapException(Exception x) + { + return ExceptionHelper.UnmapException(x); + } + } +} diff --git a/runtime/compiler.cs b/runtime/compiler.cs new file mode 100644 index 0000000..08c2bc3 --- /dev/null +++ b/runtime/compiler.cs @@ -0,0 +1,4215 @@ +/* + Copyright (C) 2002-2015 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +#if STATIC_COMPILER +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif +using System.Diagnostics; +using System.Diagnostics.SymbolStore; +using IKVM.Attributes; +using IKVM.Internal; + +using ExceptionTableEntry = IKVM.Internal.ClassFile.Method.ExceptionTableEntry; +using LocalVariableTableEntry = IKVM.Internal.ClassFile.Method.LocalVariableTableEntry; +using Instruction = IKVM.Internal.ClassFile.Method.Instruction; +using InstructionFlags = IKVM.Internal.ClassFile.Method.InstructionFlags; + +static class ByteCodeHelperMethods +{ + internal static readonly MethodInfo multianewarray; + internal static readonly MethodInfo multianewarray_ghost; + internal static readonly MethodInfo anewarray_ghost; + internal static readonly MethodInfo f2i; + internal static readonly MethodInfo d2i; + internal static readonly MethodInfo f2l; + internal static readonly MethodInfo d2l; + internal static readonly MethodInfo arraycopy_fast; + internal static readonly MethodInfo arraycopy_primitive_8; + internal static readonly MethodInfo arraycopy_primitive_4; + internal static readonly MethodInfo arraycopy_primitive_2; + internal static readonly MethodInfo arraycopy_primitive_1; + internal static readonly MethodInfo arraycopy; + internal static readonly MethodInfo DynamicCast; + internal static readonly MethodInfo DynamicAaload; + internal static readonly MethodInfo DynamicAastore; + internal static readonly MethodInfo DynamicClassLiteral; + internal static readonly MethodInfo DynamicMultianewarray; + internal static readonly MethodInfo DynamicNewarray; + internal static readonly MethodInfo DynamicNewCheckOnly; + internal static readonly MethodInfo DynamicCreateDelegate; + internal static readonly MethodInfo DynamicLoadMethodType; + internal static readonly MethodInfo DynamicLoadMethodHandle; + internal static readonly MethodInfo DynamicBinderMemberLookup; + internal static readonly MethodInfo DynamicMapException; + internal static readonly MethodInfo DynamicCallerID; + internal static readonly MethodInfo DynamicLinkIndyCallSite; + internal static readonly MethodInfo DynamicEraseInvokeExact; + internal static readonly MethodInfo VerboseCastFailure; + internal static readonly MethodInfo SkipFinalizer; + internal static readonly MethodInfo DynamicInstanceOf; + internal static readonly MethodInfo volatileReadDouble; + internal static readonly MethodInfo volatileReadLong; + internal static readonly MethodInfo volatileWriteDouble; + internal static readonly MethodInfo volatileWriteLong; + internal static readonly MethodInfo mapException; + internal static readonly MethodInfo GetDelegateForInvokeExact; + internal static readonly MethodInfo GetDelegateForInvoke; + internal static readonly MethodInfo GetDelegateForInvokeBasic; + internal static readonly MethodInfo LoadMethodType; + internal static readonly MethodInfo LinkIndyCallSite; + + static ByteCodeHelperMethods() + { +#if STATIC_COMPILER + Type typeofByteCodeHelper = StaticCompiler.GetRuntimeType("IKVM.Runtime.ByteCodeHelper"); +#else + Type typeofByteCodeHelper = typeof(IKVM.Runtime.ByteCodeHelper); +#endif + multianewarray = GetHelper(typeofByteCodeHelper, "multianewarray"); + multianewarray_ghost = GetHelper(typeofByteCodeHelper, "multianewarray_ghost"); + anewarray_ghost = GetHelper(typeofByteCodeHelper, "anewarray_ghost"); + f2i = GetHelper(typeofByteCodeHelper, "f2i"); + d2i = GetHelper(typeofByteCodeHelper, "d2i"); + f2l = GetHelper(typeofByteCodeHelper, "f2l"); + d2l = GetHelper(typeofByteCodeHelper, "d2l"); + arraycopy_fast = GetHelper(typeofByteCodeHelper, "arraycopy_fast"); + arraycopy_primitive_8 = GetHelper(typeofByteCodeHelper, "arraycopy_primitive_8"); + arraycopy_primitive_4 = GetHelper(typeofByteCodeHelper, "arraycopy_primitive_4"); + arraycopy_primitive_2 = GetHelper(typeofByteCodeHelper, "arraycopy_primitive_2"); + arraycopy_primitive_1 = GetHelper(typeofByteCodeHelper, "arraycopy_primitive_1"); + arraycopy = GetHelper(typeofByteCodeHelper, "arraycopy"); + DynamicCast = GetHelper(typeofByteCodeHelper, "DynamicCast"); + DynamicAaload = GetHelper(typeofByteCodeHelper, "DynamicAaload"); + DynamicAastore = GetHelper(typeofByteCodeHelper, "DynamicAastore"); + DynamicClassLiteral = GetHelper(typeofByteCodeHelper, "DynamicClassLiteral"); + DynamicMultianewarray = GetHelper(typeofByteCodeHelper, "DynamicMultianewarray"); + DynamicNewarray = GetHelper(typeofByteCodeHelper, "DynamicNewarray"); + DynamicNewCheckOnly = GetHelper(typeofByteCodeHelper, "DynamicNewCheckOnly"); + DynamicCreateDelegate = GetHelper(typeofByteCodeHelper, "DynamicCreateDelegate"); + DynamicLoadMethodType = GetHelper(typeofByteCodeHelper, "DynamicLoadMethodType"); + DynamicLoadMethodHandle = GetHelper(typeofByteCodeHelper, "DynamicLoadMethodHandle"); + DynamicBinderMemberLookup = GetHelper(typeofByteCodeHelper, "DynamicBinderMemberLookup"); + DynamicMapException = GetHelper(typeofByteCodeHelper, "DynamicMapException"); + DynamicCallerID = GetHelper(typeofByteCodeHelper, "DynamicCallerID"); + DynamicLinkIndyCallSite = GetHelper(typeofByteCodeHelper, "DynamicLinkIndyCallSite"); + DynamicEraseInvokeExact = GetHelper(typeofByteCodeHelper, "DynamicEraseInvokeExact"); + VerboseCastFailure = GetHelper(typeofByteCodeHelper, "VerboseCastFailure"); + SkipFinalizer = GetHelper(typeofByteCodeHelper, "SkipFinalizer"); + DynamicInstanceOf = GetHelper(typeofByteCodeHelper, "DynamicInstanceOf"); + volatileReadDouble = GetHelper(typeofByteCodeHelper, "VolatileRead", new Type[] { Types.Double.MakeByRefType() }); + volatileReadLong = GetHelper(typeofByteCodeHelper, "VolatileRead", new Type[] { Types.Int64.MakeByRefType() }); + volatileWriteDouble = GetHelper(typeofByteCodeHelper, "VolatileWrite", new Type[] { Types.Double.MakeByRefType(), Types.Double }); + volatileWriteLong = GetHelper(typeofByteCodeHelper, "VolatileWrite", new Type[] { Types.Int64.MakeByRefType(), Types.Int64 }); + mapException = GetHelper(typeofByteCodeHelper, "MapException"); + GetDelegateForInvokeExact = GetHelper(typeofByteCodeHelper, "GetDelegateForInvokeExact"); + GetDelegateForInvoke = GetHelper(typeofByteCodeHelper, "GetDelegateForInvoke"); + GetDelegateForInvokeBasic = GetHelper(typeofByteCodeHelper, "GetDelegateForInvokeBasic"); + LoadMethodType = GetHelper(typeofByteCodeHelper, "LoadMethodType"); + LinkIndyCallSite = GetHelper(typeofByteCodeHelper, "LinkIndyCallSite"); + } + + private static MethodInfo GetHelper(Type type, string method) + { + return GetHelper(type, method, null); + } + + private static MethodInfo GetHelper(Type type, string method, Type[] parameters) + { + MethodInfo mi = parameters == null ? type.GetMethod(method) : type.GetMethod(method, parameters); +#if STATIC_COMPILER + if (mi == null) + { + throw new FatalCompilerErrorException(Message.RuntimeMethodMissing, method); + } +#endif + return mi; + } +} + +struct MethodKey : IEquatable +{ + private readonly string className; + private readonly string methodName; + private readonly string methodSig; + + internal MethodKey(string className, string methodName, string methodSig) + { + this.className = className; + this.methodName = methodName; + this.methodSig = methodSig; + } + + public bool Equals(MethodKey other) + { + return className == other.className && methodName == other.methodName && methodSig == other.methodSig; + } + + public override int GetHashCode() + { + return className.GetHashCode() ^ methodName.GetHashCode() ^ methodSig.GetHashCode(); + } +} + +static partial class MethodHandleUtil +{ + internal static void EmitCallDelegateInvokeMethod(CodeEmitter ilgen, Type delegateType) + { + if (delegateType.IsGenericType) + { + // MONOBUG we don't look at the invoke method directly here, because Mono doesn't support GetParameters() on a builder instantiation + Type[] typeArgs = delegateType.GetGenericArguments(); + if (IsPackedArgsContainer(typeArgs[typeArgs.Length - 1])) + { + WrapArgs(ilgen, typeArgs[typeArgs.Length - 1]); + } + else if (typeArgs.Length > 2 && IsPackedArgsContainer(typeArgs[typeArgs.Length - 2])) + { + WrapArgs(ilgen, typeArgs[typeArgs.Length - 2]); + } + } + ilgen.Emit(OpCodes.Callvirt, GetDelegateInvokeMethod(delegateType)); + } + + private static void WrapArgs(CodeEmitter ilgen, Type type) + { + Type last = type.GetGenericArguments()[MaxArity - 1]; + if (IsPackedArgsContainer(last)) + { + WrapArgs(ilgen, last); + } + ilgen.Emit(OpCodes.Newobj, GetDelegateOrPackedArgsConstructor(type)); + } + + internal static MethodInfo GetDelegateInvokeMethod(Type delegateType) + { + if (ReflectUtil.ContainsTypeBuilder(delegateType)) + { + return TypeBuilder.GetMethod(delegateType, delegateType.GetGenericTypeDefinition().GetMethod("Invoke")); + } + else + { + return delegateType.GetMethod("Invoke"); + } + } + + internal static ConstructorInfo GetDelegateConstructor(Type delegateType) + { + return GetDelegateOrPackedArgsConstructor(delegateType); + } + + private static ConstructorInfo GetDelegateOrPackedArgsConstructor(Type type) + { + if (ReflectUtil.ContainsTypeBuilder(type)) + { + return TypeBuilder.GetConstructor(type, type.GetGenericTypeDefinition().GetConstructors()[0]); + } + else + { + return type.GetConstructors()[0]; + } + } + + // for delegate types used for "ldc " we don't want ghost arrays to be erased + internal static Type CreateDelegateTypeForLoadConstant(TypeWrapper[] args, TypeWrapper ret) + { + Type[] typeArgs = new Type[args.Length]; + for (int i = 0; i < args.Length; i++) + { + typeArgs[i] = TypeWrapperToTypeForLoadConstant(args[i]); + } + return CreateDelegateType(typeArgs, TypeWrapperToTypeForLoadConstant(ret)); + } + + private static Type TypeWrapperToTypeForLoadConstant(TypeWrapper tw) + { + if (tw.IsGhostArray) + { + int dims = tw.ArrayRank; + while (tw.IsArray) + { + tw = tw.ElementTypeWrapper; + } + return ArrayTypeWrapper.MakeArrayType(tw.TypeAsSignatureType, dims); + } + else + { + return tw.TypeAsSignatureType; + } + } +} + +sealed class Compiler +{ + internal static readonly MethodInfo unmapExceptionMethod; + private static readonly MethodInfo fixateExceptionMethod; + private static readonly MethodInfo suppressFillInStackTraceMethod; + internal static readonly MethodInfo getTypeFromHandleMethod; + internal static readonly MethodInfo getTypeMethod; + private static readonly MethodInfo keepAliveMethod; + internal static readonly MethodWrapper getClassFromTypeHandle; + internal static readonly MethodWrapper getClassFromTypeHandle2; + private readonly DynamicTypeWrapper.FinishContext context; + private readonly DynamicTypeWrapper clazz; + private readonly MethodWrapper mw; + private readonly ClassFile classFile; + private readonly ClassFile.Method m; + private readonly CodeEmitter ilGenerator; + private readonly CodeInfo ma; + private readonly UntangledExceptionTable exceptions; + private readonly List harderrors; + private readonly LocalVarInfo localVars; + private bool nonleaf; + private readonly bool debug; + private readonly bool keepAlive; + private readonly bool strictfp; + private readonly bool emitLineNumbers; + private int[] scopeBegin; + private int[] scopeClose; +#if STATIC_COMPILER + private readonly MethodWrapper[] replacedMethodWrappers; +#endif + + static Compiler() + { + getTypeFromHandleMethod = Types.Type.GetMethod("GetTypeFromHandle", BindingFlags.Static | BindingFlags.Public, null, new Type[] { Types.RuntimeTypeHandle }, null); + getTypeMethod = Types.Object.GetMethod("GetType", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null); + keepAliveMethod = JVM.Import(typeof(System.GC)).GetMethod("KeepAlive", BindingFlags.Static | BindingFlags.Public, null, new Type[] { Types.Object }, null); + // HACK we need to special case core compilation, because the __ methods are HideFromJava + if(CoreClasses.java.lang.Throwable.Wrapper.TypeAsBaseType is TypeBuilder) + { + MethodWrapper mw; + mw = CoreClasses.java.lang.Throwable.Wrapper.GetMethodWrapper("__", "()V", false); + mw.Link(); + suppressFillInStackTraceMethod = (MethodInfo)mw.GetMethod(); + mw = CoreClasses.java.lang.Throwable.Wrapper.GetMethodWrapper("__", "(Ljava.lang.Throwable;)Ljava.lang.Throwable;", false); + mw.Link(); + unmapExceptionMethod = (MethodInfo)mw.GetMethod(); + mw = CoreClasses.java.lang.Throwable.Wrapper.GetMethodWrapper("__", "(Ljava.lang.Throwable;)Ljava.lang.Throwable;", false); + mw.Link(); + fixateExceptionMethod = (MethodInfo)mw.GetMethod(); + } + else + { + suppressFillInStackTraceMethod = CoreClasses.java.lang.Throwable.Wrapper.TypeAsBaseType.GetMethod("__", Type.EmptyTypes); + unmapExceptionMethod = CoreClasses.java.lang.Throwable.Wrapper.TypeAsBaseType.GetMethod("__", new Type[] { Types.Exception }); + fixateExceptionMethod = CoreClasses.java.lang.Throwable.Wrapper.TypeAsBaseType.GetMethod("__", new Type[] { Types.Exception }); + } + getClassFromTypeHandle = ClassLoaderWrapper.LoadClassCritical("ikvm.runtime.Util").GetMethodWrapper("getClassFromTypeHandle", "(Lcli.System.RuntimeTypeHandle;)Ljava.lang.Class;", false); + getClassFromTypeHandle.Link(); + getClassFromTypeHandle2 = ClassLoaderWrapper.LoadClassCritical("ikvm.runtime.Util").GetMethodWrapper("getClassFromTypeHandle", "(Lcli.System.RuntimeTypeHandle;I)Ljava.lang.Class;", false); + getClassFromTypeHandle2.Link(); + } + + private Compiler(DynamicTypeWrapper.FinishContext context, TypeWrapper host, DynamicTypeWrapper clazz, MethodWrapper mw, ClassFile classFile, ClassFile.Method m, CodeEmitter ilGenerator, ClassLoaderWrapper classLoader) + { + this.context = context; + this.clazz = clazz; + this.mw = mw; + this.classFile = classFile; + this.m = m; + this.ilGenerator = ilGenerator; + this.debug = classLoader.EmitDebugInfo; + this.strictfp = m.IsStrictfp; + if(mw.IsConstructor) + { + MethodWrapper finalize = clazz.GetMethodWrapper(StringConstants.FINALIZE, StringConstants.SIG_VOID, true); + keepAlive = finalize != null && finalize.DeclaringType != CoreClasses.java.lang.Object.Wrapper && finalize.DeclaringType != CoreClasses.cli.System.Object.Wrapper && finalize.DeclaringType != CoreClasses.java.lang.Throwable.Wrapper && finalize.DeclaringType != CoreClasses.cli.System.Exception.Wrapper; + } +#if STATIC_COMPILER + replacedMethodWrappers = clazz.GetReplacedMethodsFor(mw); +#endif + + TypeWrapper[] args = mw.GetParameters(); + for(int i = 0; i < args.Length; i++) + { + if(args[i].IsUnloadable) + { + ilGenerator.EmitLdarg(i + (m.IsStatic ? 0 : 1)); + EmitDynamicCast(args[i]); + ilGenerator.Emit(OpCodes.Pop); + } + } + + Profiler.Enter("MethodAnalyzer"); + try + { + if(classFile.MajorVersion < 51 && m.HasJsr) + { + JsrInliner.InlineJsrs(classLoader, mw, classFile, m); + } + MethodAnalyzer verifier = new MethodAnalyzer(host, clazz, mw, classFile, m, classLoader); + exceptions = MethodAnalyzer.UntangleExceptionBlocks(classFile, m); + ma = verifier.GetCodeInfoAndErrors(exceptions, out harderrors); + localVars = new LocalVarInfo(ma, classFile, m, exceptions, mw, classLoader); + } + finally + { + Profiler.Leave("MethodAnalyzer"); + } + + if (m.LineNumberTableAttribute != null) + { + if (classLoader.EmitDebugInfo) + { + emitLineNumbers = true; + } + else if (classLoader.EmitStackTraceInfo) + { + InstructionFlags[] flags = ComputePartialReachability(0, false); + for (int i = 0; i < m.Instructions.Length; i++) + { + if ((flags[i] & InstructionFlags.Reachable) == 0) + { + // skip unreachable instructions + } + else if (m.Instructions[i].NormalizedOpCode == NormalizedByteCode.__getfield + && VerifierTypeWrapper.IsThis(ma.GetRawStackTypeWrapper(i, 0))) + { + // loading a field from the current object cannot throw + } + else if (m.Instructions[i].NormalizedOpCode == NormalizedByteCode.__putfield + && VerifierTypeWrapper.IsThis(ma.GetRawStackTypeWrapper(i, 1))) + { + // storing a field in the current object cannot throw + } + else if (m.Instructions[i].NormalizedOpCode == NormalizedByteCode.__getstatic + && classFile.GetFieldref(m.Instructions[i].Arg1).GetClassType() == clazz) + { + // loading a field from the current class cannot throw + } + else if (m.Instructions[i].NormalizedOpCode == NormalizedByteCode.__putstatic + && classFile.GetFieldref(m.Instructions[i].Arg1).GetClassType() == clazz) + { + // storing a field to the current class cannot throw + } + else if (ByteCodeMetaData.CanThrowException(m.Instructions[i].NormalizedOpCode)) + { + emitLineNumbers = true; + break; + } + } + } + } + + LocalVar[] locals = localVars.GetAllLocalVars(); + foreach(LocalVar v in locals) + { + if(v.isArg) + { + int arg = m.ArgMap[v.local]; + TypeWrapper tw; + if(m.IsStatic) + { + tw = args[arg]; + } + else if(arg == 0) + { + continue; + } + else + { + tw = args[arg - 1]; + } + if(!tw.IsUnloadable && + (v.type != tw || tw.TypeAsLocalOrStackType != tw.TypeAsSignatureType)) + { + v.builder = ilGenerator.DeclareLocal(GetLocalBuilderType(v.type)); + if(debug && v.name != null) + { + v.builder.SetLocalSymInfo(v.name); + } + v.isArg = false; + ilGenerator.EmitLdarg(arg); + tw.EmitConvSignatureTypeToStackType(ilGenerator); + ilGenerator.Emit(OpCodes.Stloc, v.builder); + } + } + } + + // if we're emitting debugging information, we need to use scopes for local variables + if(debug) + { + SetupLocalVariableScopes(); + } + + Workaroundx64JitBug(args); + } + + // workaround for x64 JIT bug + // https://connect.microsoft.com/VisualStudio/feedback/details/636466/variable-is-not-incrementing-in-c-release-x64#details + // (see also https://sourceforge.net/mailarchive/message.php?msg_id=28250469) + private void Workaroundx64JitBug(TypeWrapper[] args) + { + if(args.Length > (m.IsStatic ? 4 : 3) && m.ExceptionTable.Length != 0) + { + bool[] workarounds = null; + InstructionFlags[] flags = ComputePartialReachability(0, false); + for(int i = 0; i < m.Instructions.Length; i++) + { + if((flags[i] & InstructionFlags.Reachable) == 0) + { + // skip unreachable instructions + } + else + { + switch(m.Instructions[i].NormalizedOpCode) + { + case NormalizedByteCode.__iinc: + case NormalizedByteCode.__astore: + case NormalizedByteCode.__istore: + case NormalizedByteCode.__lstore: + case NormalizedByteCode.__fstore: + case NormalizedByteCode.__dstore: + int arg = m.IsStatic ? m.Instructions[i].Arg1 : m.Instructions[i].Arg1 - 1; + if(arg >= 3 && arg < args.Length) + { + if(workarounds == null) + { + workarounds = new bool[args.Length + 1]; + } + workarounds[m.Instructions[i].Arg1] = true; + } + break; + } + } + } + if(workarounds != null) + { + for(int i = 0; i < workarounds.Length; i++) + { + if(workarounds[i]) + { + // TODO prevent this from getting optimized away + ilGenerator.EmitLdarga(i); + ilGenerator.Emit(OpCodes.Pop); + } + } + } + } + } + + private void SetupLocalVariableScopes() + { + LocalVariableTableEntry[] lvt = m.LocalVariableTableAttribute; + if(lvt != null) + { + scopeBegin = new int[m.Instructions.Length]; + scopeClose = new int[m.Instructions.Length]; + + // FXBUG make sure we always have an outer scope + // (otherwise LocalBuilder.SetLocalSymInfo() might throw an IndexOutOfRangeException) + // fix for bug 2881954. + scopeBegin[0]++; + scopeClose[m.Instructions.Length - 1]++; + + for (int i = 0; i < lvt.Length; i++) + { + int startIndex = SafeFindPcIndex(lvt[i].start_pc); + int endIndex = SafeFindPcIndex(lvt[i].start_pc + lvt[i].length); + if(startIndex != -1 && endIndex != -1 && startIndex < endIndex) + { + if(startIndex > 0) + { + // NOTE javac (correctly) sets start_pc of the LVT entry to the instruction + // following the store that first initializes the local, so we have to + // detect that case and adjust our local scope (because we'll be creating + // the local when we encounter the first store). + LocalVar v = localVars.GetLocalVar(startIndex - 1); + if(v != null && v.local == lvt[i].index) + { + startIndex--; + } + } + scopeBegin[startIndex]++; + scopeClose[endIndex]++; + } + } + } + } + + private int SafeFindPcIndex(int pc) + { + for(int i = 0; i < m.Instructions.Length; i++) + { + if(m.Instructions[i].PC >= pc) + { + return i; + } + } + return -1; + } + + private sealed class ReturnCookie + { + private readonly CodeEmitterLabel stub; + private readonly CodeEmitterLocal local; + + internal ReturnCookie(CodeEmitterLabel stub, CodeEmitterLocal local) + { + this.stub = stub; + this.local = local; + } + + internal void EmitRet(CodeEmitter ilgen) + { + ilgen.MarkLabel(stub); + if(local != null) + { + ilgen.Emit(OpCodes.Ldloc, local); + } + ilgen.Emit(OpCodes.Ret); + } + } + + private sealed class BranchCookie + { + // NOTE Stub gets used for both the push stub (inside the exception block) as well as the pop stub (outside the block) + internal CodeEmitterLabel Stub; + internal CodeEmitterLabel TargetLabel; + internal bool ContentOnStack; + internal readonly int TargetIndex; + internal DupHelper dh; + + internal BranchCookie(Compiler compiler, int stackHeight, int targetIndex) + { + this.Stub = compiler.ilGenerator.DefineLabel(); + this.TargetIndex = targetIndex; + this.dh = new DupHelper(compiler, stackHeight); + } + + internal BranchCookie(CodeEmitterLabel label, int targetIndex) + { + this.Stub = label; + this.TargetIndex = targetIndex; + } + } + + private struct DupHelper + { + private enum StackType : byte + { + Null, + New, + This, + UnitializedThis, + FaultBlockException, + Other + } + private readonly Compiler compiler; + private readonly StackType[] types; + private readonly CodeEmitterLocal[] locals; + + internal DupHelper(Compiler compiler, int count) + { + this.compiler = compiler; + types = new StackType[count]; + locals = new CodeEmitterLocal[count]; + } + + internal void Release() + { + foreach (CodeEmitterLocal lb in locals) + { + if(lb != null) + { + compiler.ilGenerator.ReleaseTempLocal(lb); + } + } + } + + internal int Count + { + get + { + return types.Length; + } + } + + internal void SetType(int i, TypeWrapper type) + { + if(type == VerifierTypeWrapper.Null) + { + types[i] = StackType.Null; + } + else if(VerifierTypeWrapper.IsNew(type)) + { + // new objects aren't really there on the stack + types[i] = StackType.New; + } + else if(VerifierTypeWrapper.IsThis(type)) + { + types[i] = StackType.This; + } + else if(type == VerifierTypeWrapper.UninitializedThis) + { + // uninitialized references cannot be stored in a local, but we can reload them + types[i] = StackType.UnitializedThis; + } + else if (VerifierTypeWrapper.IsFaultBlockException(type)) + { + types[i] = StackType.FaultBlockException; + } + else + { + types[i] = StackType.Other; + locals[i] = compiler.ilGenerator.AllocTempLocal(compiler.GetLocalBuilderType(type)); + } + } + + internal void Load(int i) + { + switch(types[i]) + { + case StackType.Null: + compiler.ilGenerator.Emit(OpCodes.Ldnull); + break; + case StackType.New: + case StackType.FaultBlockException: + // objects aren't really there on the stack + break; + case StackType.This: + case StackType.UnitializedThis: + compiler.ilGenerator.Emit(OpCodes.Ldarg_0); + break; + case StackType.Other: + compiler.ilGenerator.Emit(OpCodes.Ldloc, locals[i]); + break; + default: + throw new InvalidOperationException(); + } + } + + internal void Store(int i) + { + switch(types[i]) + { + case StackType.Null: + case StackType.This: + case StackType.UnitializedThis: + compiler.ilGenerator.Emit(OpCodes.Pop); + break; + case StackType.New: + case StackType.FaultBlockException: + // objects aren't really there on the stack + break; + case StackType.Other: + compiler.ilGenerator.Emit(OpCodes.Stloc, locals[i]); + break; + default: + throw new InvalidOperationException(); + } + } + } + + internal static void Compile(DynamicTypeWrapper.FinishContext context, TypeWrapper host, DynamicTypeWrapper clazz, MethodWrapper mw, ClassFile classFile, ClassFile.Method m, CodeEmitter ilGenerator, ref bool nonleaf) + { + ClassLoaderWrapper classLoader = clazz.GetClassLoader(); + if(classLoader.EmitDebugInfo) + { + if(classFile.SourcePath != null) + { + ilGenerator.DefineSymbolDocument(classLoader.GetTypeWrapperFactory().ModuleBuilder, classFile.SourcePath, SymLanguageType.Java, Guid.Empty, SymDocumentType.Text); + // the very first instruction in the method must have an associated line number, to be able + // to step into the method in Visual Studio .NET + ClassFile.Method.LineNumberTableEntry[] table = m.LineNumberTableAttribute; + if(table != null) + { + int firstPC = int.MaxValue; + int firstLine = -1; + for(int i = 0; i < table.Length; i++) + { + if(table[i].start_pc < firstPC && table[i].line_number != 0) + { + firstLine = table[i].line_number; + firstPC = table[i].start_pc; + } + } + if(firstLine > 0) + { + ilGenerator.SetLineNumber((ushort)firstLine); + } + } + } + } + Compiler c; + try + { + Profiler.Enter("new Compiler"); + try + { + c = new Compiler(context, host, clazz, mw, classFile, m, ilGenerator, classLoader); + } + finally + { + Profiler.Leave("new Compiler"); + } + } + catch(VerifyError x) + { +#if STATIC_COMPILER + classLoader.IssueMessage(Message.EmittedVerificationError, classFile.Name + "." + m.Name + m.Signature, x.Message); +#endif + Tracer.Error(Tracer.Verifier, x.ToString()); + clazz.SetHasVerifyError(); + // because in Java the method is only verified if it is actually called, + // we generate code here to throw the VerificationError + ilGenerator.EmitThrow("java.lang.VerifyError", x.Message); + return; + } + catch(ClassFormatError x) + { +#if STATIC_COMPILER + classLoader.IssueMessage(Message.EmittedClassFormatError, classFile.Name + "." + m.Name + m.Signature, x.Message); +#endif + Tracer.Error(Tracer.Verifier, x.ToString()); + clazz.SetHasClassFormatError(); + ilGenerator.EmitThrow("java.lang.ClassFormatError", x.Message); + return; + } + Profiler.Enter("Compile"); + try + { + if(m.IsSynchronized && m.IsStatic) + { + clazz.EmitClassLiteral(ilGenerator); + ilGenerator.Emit(OpCodes.Dup); + CodeEmitterLocal monitor = ilGenerator.DeclareLocal(Types.Object); + ilGenerator.Emit(OpCodes.Stloc, monitor); + ilGenerator.EmitMonitorEnter(); + ilGenerator.BeginExceptionBlock(); + Block b = new Block(c, 0, int.MaxValue, -1, new List(), true); + c.Compile(b, 0); + b.Leave(); + ilGenerator.BeginFinallyBlock(); + ilGenerator.Emit(OpCodes.Ldloc, monitor); + ilGenerator.EmitMonitorExit(); + ilGenerator.Emit(OpCodes.Endfinally); + ilGenerator.EndExceptionBlock(); + b.LeaveStubs(new Block(c, 0, int.MaxValue, -1, null, false)); + } + else + { + Block b = new Block(c, 0, int.MaxValue, -1, null, false); + c.Compile(b, 0); + b.Leave(); + } + nonleaf = c.nonleaf; + } + finally + { + Profiler.Leave("Compile"); + } + } + + private sealed class Block + { + private readonly Compiler compiler; + private readonly CodeEmitter ilgen; + private readonly int beginIndex; + private readonly int endIndex; + private readonly int exceptionIndex; + private List exits; + private readonly bool nested; + private readonly object[] labels; + + internal Block(Compiler compiler, int beginIndex, int endIndex, int exceptionIndex, List exits, bool nested) + { + this.compiler = compiler; + this.ilgen = compiler.ilGenerator; + this.beginIndex = beginIndex; + this.endIndex = endIndex; + this.exceptionIndex = exceptionIndex; + this.exits = exits; + this.nested = nested; + labels = new object[compiler.m.Instructions.Length]; + } + + internal int EndIndex + { + get + { + return endIndex; + } + } + + internal int ExceptionIndex + { + get + { + return exceptionIndex; + } + } + + internal void SetBackwardBranchLabel(int instructionIndex, BranchCookie bc) + { + // NOTE we're overwriting the label that is already there + labels[instructionIndex] = bc.Stub; + if(exits == null) + { + exits = new List(); + } + exits.Add(bc); + } + + internal CodeEmitterLabel GetLabel(int targetIndex) + { + if(IsInRange(targetIndex)) + { + CodeEmitterLabel l = (CodeEmitterLabel)labels[targetIndex]; + if(l == null) + { + l = ilgen.DefineLabel(); + labels[targetIndex] = l; + } + return l; + } + else + { + BranchCookie l = (BranchCookie)labels[targetIndex]; + if(l == null) + { + // if we're branching out of the current exception block, we need to indirect this thru a stub + // that saves the stack and uses leave to leave the exception block (to another stub that recovers + // the stack) + int stackHeight = compiler.ma.GetStackHeight(targetIndex); + BranchCookie bc = new BranchCookie(compiler, stackHeight, targetIndex); + bc.ContentOnStack = true; + for(int i = 0; i < stackHeight; i++) + { + bc.dh.SetType(i, compiler.ma.GetRawStackTypeWrapper(targetIndex, i)); + } + exits.Add(bc); + l = bc; + labels[targetIndex] = l; + } + return l.Stub; + } + } + + internal bool HasLabel(int instructionIndex) + { + return labels[instructionIndex] != null; + } + + internal void MarkLabel(int instructionIndex) + { + object label = labels[instructionIndex]; + if(label == null) + { + CodeEmitterLabel l = ilgen.DefineLabel(); + ilgen.MarkLabel(l); + labels[instructionIndex] = l; + } + else + { + ilgen.MarkLabel((CodeEmitterLabel)label); + } + } + + internal bool IsInRange(int index) + { + return beginIndex <= index && index < endIndex; + } + + internal void Leave() + { + if(exits != null) + { + for(int i = 0; i < exits.Count; i++) + { + object exit = exits[i]; + BranchCookie bc = exit as BranchCookie; + if(bc != null && bc.ContentOnStack) + { + bc.ContentOnStack = false; + int stack = bc.dh.Count; + // HACK this is unreachable code, but we make sure that + // forward pass verification always yields a valid stack + // (this is required for unreachable leave stubs that are + // generated for unreachable code that follows an + // embedded exception emitted by the compiler for invalid + // code (e.g. NoSuchFieldError)) + for(int n = stack - 1; n >= 0; n--) + { + bc.dh.Load(n); + } + ilgen.MarkLabel(bc.Stub); + for(int n = 0; n < stack; n++) + { + bc.dh.Store(n); + } + if(bc.TargetIndex == -1) + { + ilgen.EmitBr(bc.TargetLabel); + } + else + { + bc.Stub = ilgen.DefineLabel(); + ilgen.EmitLeave(bc.Stub); + } + } + } + } + } + + internal void LeaveStubs(Block newBlock) + { + if(exits != null) + { + for(int i = 0; i < exits.Count; i++) + { + object exit = exits[i]; + ReturnCookie rc = exit as ReturnCookie; + if(rc != null) + { + if(newBlock.IsNested) + { + newBlock.exits.Add(rc); + } + else + { + rc.EmitRet(ilgen); + } + } + else + { + BranchCookie bc = exit as BranchCookie; + if(bc != null && bc.TargetIndex != -1) + { + Debug.Assert(!bc.ContentOnStack); + // if the target is within the new block, we handle it, otherwise we + // defer the cookie to our caller + if(newBlock.IsInRange(bc.TargetIndex)) + { + bc.ContentOnStack = true; + ilgen.MarkLabel(bc.Stub); + int stack = bc.dh.Count; + for(int n = stack - 1; n >= 0; n--) + { + bc.dh.Load(n); + } + ilgen.EmitBr(newBlock.GetLabel(bc.TargetIndex)); + } + else + { + newBlock.exits.Add(bc); + } + } + } + } + } + } + + internal void AddExitHack(object bc) + { + exits.Add(bc); + } + + internal bool IsNested + { + get + { + return nested; + } + } + } + + private void Compile(Block block, int startIndex) + { + InstructionFlags[] flags = ComputePartialReachability(startIndex, true); + ExceptionTableEntry[] exceptions = GetExceptionTableFor(flags); + int exceptionIndex = 0; + Instruction[] code = m.Instructions; + Stack blockStack = new Stack(); + bool instructionIsForwardReachable = true; + if(startIndex != 0) + { + for(int i = 0; i < flags.Length; i++) + { + if((flags[i] & InstructionFlags.Reachable) != 0) + { + if(i < startIndex) + { + instructionIsForwardReachable = false; + ilGenerator.EmitBr(block.GetLabel(startIndex)); + } + break; + } + } + } + for(int i = 0; i < code.Length; i++) + { + Instruction instr = code[i]; + + if (scopeBegin != null) + { + for(int j = scopeClose[i]; j > 0; j--) + { + ilGenerator.EndScope(); + } + for(int j = scopeBegin[i]; j > 0; j--) + { + ilGenerator.BeginScope(); + } + } + + // if we've left the current exception block, do the exit processing + while(block.EndIndex == i) + { + block.Leave(); + + ExceptionTableEntry exc = exceptions[block.ExceptionIndex]; + + Block prevBlock = block; + block = blockStack.Pop(); + + exceptionIndex = block.ExceptionIndex + 1; + // skip over exception handlers that are no longer relevant + for(; exceptionIndex < exceptions.Length && exceptions[exceptionIndex].endIndex <= i; exceptionIndex++) + { + } + + int handlerIndex = exc.handlerIndex; + + if(exc.catch_type == 0 && VerifierTypeWrapper.IsFaultBlockException(ma.GetRawStackTypeWrapper(handlerIndex, 0))) + { + if(exc.isFinally) + { + ilGenerator.BeginFinallyBlock(); + } + else + { + ilGenerator.BeginFaultBlock(); + } + Block b = new Block(this, 0, block.EndIndex, -1, null, false); + Compile(b, handlerIndex); + b.Leave(); + ilGenerator.EndExceptionBlock(); + } + else + { + TypeWrapper exceptionTypeWrapper; + bool remap; + if(exc.catch_type == 0) + { + exceptionTypeWrapper = CoreClasses.java.lang.Throwable.Wrapper; + remap = true; + } + else + { + exceptionTypeWrapper = classFile.GetConstantPoolClassType(exc.catch_type); + remap = exceptionTypeWrapper.IsUnloadable || !exceptionTypeWrapper.IsSubTypeOf(CoreClasses.cli.System.Exception.Wrapper); + } + Type excType = exceptionTypeWrapper.TypeAsExceptionType; + bool mapSafe = !exceptionTypeWrapper.IsUnloadable && !exceptionTypeWrapper.IsMapUnsafeException && !exceptionTypeWrapper.IsRemapped; + if(mapSafe) + { + ilGenerator.BeginCatchBlock(excType); + } + else + { + ilGenerator.BeginCatchBlock(Types.Exception); + } + BranchCookie bc = new BranchCookie(this, 1, exc.handlerIndex); + prevBlock.AddExitHack(bc); + Instruction handlerInstr = code[handlerIndex]; + bool unusedException = (handlerInstr.NormalizedOpCode == NormalizedByteCode.__pop || + (handlerInstr.NormalizedOpCode == NormalizedByteCode.__astore && + localVars.GetLocalVar(handlerIndex) == null)); + int mapFlags = unusedException ? 2 : 0; + if(mapSafe && unusedException) + { + // we don't need to do anything with the exception + } + else if(mapSafe) + { + ilGenerator.EmitLdc_I4(mapFlags | 1); + ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.mapException.MakeGenericMethod(excType)); + } + else if(exceptionTypeWrapper == CoreClasses.java.lang.Throwable.Wrapper) + { + ilGenerator.EmitLdc_I4(mapFlags); + ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.mapException.MakeGenericMethod(Types.Exception)); + } + else + { + ilGenerator.EmitLdc_I4(mapFlags | (remap ? 0 : 1)); + if(exceptionTypeWrapper.IsUnloadable) + { + Profiler.Count("EmitDynamicExceptionHandler"); + EmitDynamicClassLiteral(exceptionTypeWrapper); + ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicMapException); + } + else + { + ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.mapException.MakeGenericMethod(excType)); + } + if(!unusedException) + { + ilGenerator.Emit(OpCodes.Dup); + } + CodeEmitterLabel leave = ilGenerator.DefineLabel(); + ilGenerator.EmitBrtrue(leave); + ilGenerator.Emit(OpCodes.Rethrow); + ilGenerator.MarkLabel(leave); + } + if(unusedException) + { + // we must still have an item on the stack, even though it isn't used! + bc.dh.SetType(0, VerifierTypeWrapper.Null); + } + else + { + bc.dh.SetType(0, exceptionTypeWrapper); + bc.dh.Store(0); + } + ilGenerator.EmitLeave(bc.Stub); + ilGenerator.EndExceptionBlock(); + } + prevBlock.LeaveStubs(block); + } + + if((flags[i] & InstructionFlags.Reachable) == 0) + { + // skip any unreachable instructions + continue; + } + + // if there was a forward branch to this instruction, it is forward reachable + instructionIsForwardReachable |= block.HasLabel(i); + + if(block.HasLabel(i) || (flags[i] & InstructionFlags.BranchTarget) != 0) + { + block.MarkLabel(i); + } + + // if the instruction is only backward reachable, ECMA says it must have an empty stack, + // so we move the stack to locals + if(!instructionIsForwardReachable) + { + int stackHeight = ma.GetStackHeight(i); + if(stackHeight != 0) + { + BranchCookie bc = new BranchCookie(this, stackHeight, -1); + bc.ContentOnStack = true; + bc.TargetLabel = ilGenerator.DefineLabel(); + ilGenerator.MarkLabel(bc.TargetLabel); + for(int j = 0; j < stackHeight; j++) + { + bc.dh.SetType(j, ma.GetRawStackTypeWrapper(i, j)); + } + for(int j = stackHeight - 1; j >= 0; j--) + { + bc.dh.Load(j); + } + block.SetBackwardBranchLabel(i, bc); + } + } + + // if we're entering an exception block, we need to setup the exception block and + // transfer the stack into it + // Note that an exception block that *starts* at an unreachable instruction, + // is completely unreachable, because it is impossible to branch into an exception block. + for(; exceptionIndex < exceptions.Length && exceptions[exceptionIndex].startIndex == i; exceptionIndex++) + { + int stackHeight = ma.GetStackHeight(i); + if(stackHeight != 0) + { + DupHelper dh = new DupHelper(this, stackHeight); + for(int k = 0; k < stackHeight; k++) + { + dh.SetType(k, ma.GetRawStackTypeWrapper(i, k)); + dh.Store(k); + } + ilGenerator.BeginExceptionBlock(); + for(int k = stackHeight - 1; k >= 0; k--) + { + dh.Load(k); + } + dh.Release(); + } + else + { + ilGenerator.BeginExceptionBlock(); + } + blockStack.Push(block); + block = new Block(this, exceptions[exceptionIndex].startIndex, exceptions[exceptionIndex].endIndex, exceptionIndex, new List(), true); + block.MarkLabel(i); + } + + if(emitLineNumbers) + { + ClassFile.Method.LineNumberTableEntry[] table = m.LineNumberTableAttribute; + for (int j = 0; j < table.Length; j++) + { + if(table[j].start_pc == code[i].PC && table[j].line_number != 0) + { + ilGenerator.SetLineNumber(table[j].line_number); + break; + } + } + } + + if(keepAlive) + { + // JSR 133 specifies that a finalizer cannot run while the constructor is still in progress. + // This code attempts to implement that by adding calls to GC.KeepAlive(this) before return, + // backward branches and throw instructions. I don't think it is perfect, you may be able to + // fool it by calling a trivial method that loops forever which the CLR JIT will then inline + // and see that control flow doesn't continue and hence the lifetime of "this" will be + // shorter than the constructor. + switch(ByteCodeMetaData.GetFlowControl(instr.NormalizedOpCode)) + { + case ByteCodeFlowControl.Return: + ilGenerator.Emit(OpCodes.Ldarg_0); + ilGenerator.Emit(OpCodes.Call, keepAliveMethod); + break; + case ByteCodeFlowControl.Branch: + case ByteCodeFlowControl.CondBranch: + if(instr.TargetIndex <= i) + { + ilGenerator.Emit(OpCodes.Ldarg_0); + ilGenerator.Emit(OpCodes.Call, keepAliveMethod); + } + break; + case ByteCodeFlowControl.Throw: + case ByteCodeFlowControl.Switch: + if(ma.GetLocalTypeWrapper(i, 0) != VerifierTypeWrapper.UninitializedThis) + { + ilGenerator.Emit(OpCodes.Ldarg_0); + ilGenerator.Emit(OpCodes.Call, keepAliveMethod); + } + break; + } + } + + switch(instr.NormalizedOpCode) + { + case NormalizedByteCode.__getstatic: + { + ClassFile.ConstantPoolItemFieldref cpi = classFile.GetFieldref(instr.Arg1); + if(cpi.GetClassType() != clazz) + { + // we may trigger a static initializer, which is equivalent to a call + nonleaf = true; + } + FieldWrapper field = cpi.GetField(); + field.EmitGet(ilGenerator); + field.FieldTypeWrapper.EmitConvSignatureTypeToStackType(ilGenerator); + break; + } + case NormalizedByteCode.__getfield: + { + ClassFile.ConstantPoolItemFieldref cpi = classFile.GetFieldref(instr.Arg1); + FieldWrapper field = cpi.GetField(); + if (ma.GetStackTypeWrapper(i, 0).IsUnloadable) + { + if (field.IsProtected) + { + // downcast receiver to our type + clazz.EmitCheckcast(ilGenerator); + } + else + { + // downcast receiver to field declaring type + field.DeclaringType.EmitCheckcast(ilGenerator); + } + } + field.EmitGet(ilGenerator); + field.FieldTypeWrapper.EmitConvSignatureTypeToStackType(ilGenerator); + break; + } + case NormalizedByteCode.__putstatic: + { + ClassFile.ConstantPoolItemFieldref cpi = classFile.GetFieldref(instr.Arg1); + if(cpi.GetClassType() != clazz) + { + // we may trigger a static initializer, which is equivalent to a call + nonleaf = true; + } + FieldWrapper field = cpi.GetField(); + TypeWrapper tw = field.FieldTypeWrapper; + tw.EmitConvStackTypeToSignatureType(ilGenerator, ma.GetStackTypeWrapper(i, 0)); + if(strictfp) + { + // no need to convert + } + else if(tw == PrimitiveTypeWrapper.DOUBLE) + { + ilGenerator.Emit(OpCodes.Conv_R8); + } + field.EmitSet(ilGenerator); + break; + } + case NormalizedByteCode.__putfield: + { + ClassFile.ConstantPoolItemFieldref cpi = classFile.GetFieldref(instr.Arg1); + FieldWrapper field = cpi.GetField(); + TypeWrapper tw = field.FieldTypeWrapper; + if (ma.GetStackTypeWrapper(i, 1).IsUnloadable) + { + CodeEmitterLocal temp = ilGenerator.UnsafeAllocTempLocal(tw.TypeAsLocalOrStackType); + ilGenerator.Emit(OpCodes.Stloc, temp); + if (field.IsProtected) + { + // downcast receiver to our type + clazz.EmitCheckcast(ilGenerator); + } + else + { + // downcast receiver to field declaring type + field.DeclaringType.EmitCheckcast(ilGenerator); + } + ilGenerator.Emit(OpCodes.Ldloc, temp); + } + tw.EmitConvStackTypeToSignatureType(ilGenerator, ma.GetStackTypeWrapper(i, 0)); + if(strictfp) + { + // no need to convert + } + else if(tw == PrimitiveTypeWrapper.DOUBLE) + { + ilGenerator.Emit(OpCodes.Conv_R8); + } + field.EmitSet(ilGenerator); + break; + } + case NormalizedByteCode.__dynamic_getstatic: + case NormalizedByteCode.__dynamic_putstatic: + case NormalizedByteCode.__dynamic_getfield: + case NormalizedByteCode.__dynamic_putfield: + nonleaf = true; + DynamicGetPutField(instr, i); + break; + case NormalizedByteCode.__aconst_null: + ilGenerator.Emit(OpCodes.Ldnull); + break; + case NormalizedByteCode.__iconst: + ilGenerator.EmitLdc_I4(instr.NormalizedArg1); + break; + case NormalizedByteCode.__lconst_0: + ilGenerator.EmitLdc_I8(0L); + break; + case NormalizedByteCode.__lconst_1: + ilGenerator.EmitLdc_I8(1L); + break; + case NormalizedByteCode.__fconst_0: + case NormalizedByteCode.__dconst_0: + // floats are stored as native size on the stack, so both R4 and R8 are the same + ilGenerator.EmitLdc_R4(0.0f); + break; + case NormalizedByteCode.__fconst_1: + case NormalizedByteCode.__dconst_1: + // floats are stored as native size on the stack, so both R4 and R8 are the same + ilGenerator.EmitLdc_R4(1.0f); + break; + case NormalizedByteCode.__fconst_2: + ilGenerator.EmitLdc_R4(2.0f); + break; + case NormalizedByteCode.__ldc_nothrow: + case NormalizedByteCode.__ldc: + EmitLoadConstant(ilGenerator, instr.Arg1); + break; + case NormalizedByteCode.__invokedynamic: + { + ClassFile.ConstantPoolItemInvokeDynamic cpi = classFile.GetInvokeDynamic(instr.Arg1); + CastInterfaceArgs(null, cpi.GetArgTypes(), i, false); + if (!LambdaMetafactory.Emit(context, classFile, instr.Arg1, cpi, ilGenerator)) + { + EmitInvokeDynamic(cpi); + EmitReturnTypeConversion(cpi.GetRetType()); + } + nonleaf = true; + break; + } + case NormalizedByteCode.__dynamic_invokestatic: + case NormalizedByteCode.__privileged_invokestatic: + case NormalizedByteCode.__invokestatic: + case NormalizedByteCode.__methodhandle_link: + { + MethodWrapper method = GetMethodCallEmitter(instr.NormalizedOpCode, instr.Arg1); + if(method.IsIntrinsic && method.EmitIntrinsic(new EmitIntrinsicContext(method, context, ilGenerator, ma, i, mw, classFile, code, flags))) + { + break; + } + // if the stack values don't match the argument types (for interface argument types) + // we must emit code to cast the stack value to the interface type + CastInterfaceArgs(method.DeclaringType, method.GetParameters(), i, false); + if(method.HasCallerID) + { + context.EmitCallerID(ilGenerator, m.IsLambdaFormCompiled); + } + method.EmitCall(ilGenerator); + EmitReturnTypeConversion(method.ReturnType); + nonleaf = true; + break; + } + case NormalizedByteCode.__dynamic_invokeinterface: + case NormalizedByteCode.__dynamic_invokevirtual: + case NormalizedByteCode.__dynamic_invokespecial: + case NormalizedByteCode.__privileged_invokevirtual: + case NormalizedByteCode.__privileged_invokespecial: + case NormalizedByteCode.__invokevirtual: + case NormalizedByteCode.__invokeinterface: + case NormalizedByteCode.__invokespecial: + case NormalizedByteCode.__methodhandle_invoke: + { + bool isinvokespecial = instr.NormalizedOpCode == NormalizedByteCode.__invokespecial + || instr.NormalizedOpCode == NormalizedByteCode.__dynamic_invokespecial + || instr.NormalizedOpCode == NormalizedByteCode.__privileged_invokespecial; + MethodWrapper method = GetMethodCallEmitter(instr.NormalizedOpCode, instr.Arg1); + int argcount = method.GetParameters().Length; + TypeWrapper type = ma.GetRawStackTypeWrapper(i, argcount); + TypeWrapper thisType = ComputeThisType(type, method, instr.NormalizedOpCode); + + EmitIntrinsicContext eic = new EmitIntrinsicContext(method, context, ilGenerator, ma, i, mw, classFile, code, flags); + if(method.IsIntrinsic && method.EmitIntrinsic(eic)) + { + nonleaf |= eic.NonLeaf; + break; + } + + nonleaf = true; + + // HACK this code is duplicated in java.lang.invoke.cs + if(method.IsFinalizeOrClone) + { + // HACK we may need to redirect finalize or clone from java.lang.Object/Throwable + // to a more specific base type. + if(thisType.IsAssignableTo(CoreClasses.cli.System.Object.Wrapper)) + { + method = CoreClasses.cli.System.Object.Wrapper.GetMethodWrapper(method.Name, method.Signature, true); + } + else if(thisType.IsAssignableTo(CoreClasses.cli.System.Exception.Wrapper)) + { + method = CoreClasses.cli.System.Exception.Wrapper.GetMethodWrapper(method.Name, method.Signature, true); + } + else if(thisType.IsAssignableTo(CoreClasses.java.lang.Throwable.Wrapper)) + { + method = CoreClasses.java.lang.Throwable.Wrapper.GetMethodWrapper(method.Name, method.Signature, true); + } + } + + // if the stack values don't match the argument types (for interface argument types) + // we must emit code to cast the stack value to the interface type + if(isinvokespecial && method.IsConstructor && VerifierTypeWrapper.IsNew(type)) + { + CastInterfaceArgs(method.DeclaringType, method.GetParameters(), i, false); + } + else + { + // the this reference is included in the argument list because it may also need to be cast + TypeWrapper[] methodArgs = method.GetParameters(); + TypeWrapper[] args = new TypeWrapper[methodArgs.Length + 1]; + methodArgs.CopyTo(args, 1); + if(instr.NormalizedOpCode == NormalizedByteCode.__invokeinterface) + { + args[0] = method.DeclaringType; + } + else + { + args[0] = thisType; + } + CastInterfaceArgs(method.DeclaringType, args, i, true); + } + + if(isinvokespecial && method.IsConstructor) + { + if(VerifierTypeWrapper.IsNew(type)) + { + // we have to construct a list of all the unitialized references to the object + // we're about to create on the stack, so that we can reconstruct the stack after + // the "newobj" instruction + int trivcount = 0; + bool nontrivial = false; + bool[] stackfix = new bool[ma.GetStackHeight(i) - (argcount + 1)]; + for(int j = 0; j < stackfix.Length; j++) + { + if(ma.GetRawStackTypeWrapper(i, argcount + 1 + j) == type) + { + stackfix[j] = true; + if(trivcount == j) + { + trivcount++; + } + else + { + // if there is other stuff on the stack between the new object + // references, we need to do more work to construct the proper stack + // layout after the newobj instruction + nontrivial = true; + } + } + } + for(int j = 0; !nontrivial && j < m.MaxLocals; j++) + { + if(ma.GetLocalTypeWrapper(i, j) == type) + { + nontrivial = true; + } + } + if(!thisType.IsUnloadable && thisType.IsSubTypeOf(CoreClasses.java.lang.Throwable.Wrapper)) + { + // if the next instruction is an athrow and the exception type + // doesn't override fillInStackTrace, we can suppress the call + // to fillInStackTrace from the constructor (and this is + // a huge perf win) + // NOTE we also can't call suppressFillInStackTrace for non-Java + // exceptions (because then the suppress flag won't be cleared), + // but this case is handled by the "is fillInStackTrace overridden?" + // test, because cli.System.Exception overrides fillInStackTrace. + if(code[i + 1].NormalizedOpCode == NormalizedByteCode.__athrow) + { + if(thisType.GetMethodWrapper("fillInStackTrace", "()Ljava.lang.Throwable;", true).DeclaringType == CoreClasses.java.lang.Throwable.Wrapper) + { + ilGenerator.Emit(OpCodes.Call, suppressFillInStackTraceMethod); + } + if((flags[i + 1] & InstructionFlags.BranchTarget) == 0) + { + code[i + 1].PatchOpCode(NormalizedByteCode.__athrow_no_unmap); + } + } + } + method.EmitNewobj(ilGenerator); + if(!thisType.IsUnloadable && thisType.IsSubTypeOf(CoreClasses.cli.System.Exception.Wrapper)) + { + // we call Throwable.__() to disable remapping the exception + ilGenerator.Emit(OpCodes.Call, fixateExceptionMethod); + } + if(nontrivial) + { + // this could be done a little more efficiently, but since in practice this + // code never runs (for code compiled from Java source) it doesn't + // really matter + CodeEmitterLocal newobj = ilGenerator.DeclareLocal(GetLocalBuilderType(thisType)); + ilGenerator.Emit(OpCodes.Stloc, newobj); + CodeEmitterLocal[] tempstack = new CodeEmitterLocal[stackfix.Length]; + for(int j = 0; j < stackfix.Length; j++) + { + if(!stackfix[j]) + { + TypeWrapper stacktype = ma.GetStackTypeWrapper(i, argcount + 1 + j); + // it could be another new object reference (not from current invokespecial + // instruction) + if(stacktype == VerifierTypeWrapper.Null) + { + // NOTE we abuse the newobj local as a cookie to signal null! + tempstack[j] = newobj; + ilGenerator.Emit(OpCodes.Pop); + } + else if(!VerifierTypeWrapper.IsNotPresentOnStack(stacktype)) + { + CodeEmitterLocal lb = ilGenerator.DeclareLocal(GetLocalBuilderType(stacktype)); + ilGenerator.Emit(OpCodes.Stloc, lb); + tempstack[j] = lb; + } + } + } + for(int j = stackfix.Length - 1; j >= 0; j--) + { + if(stackfix[j]) + { + ilGenerator.Emit(OpCodes.Ldloc, newobj); + } + else if(tempstack[j] != null) + { + // NOTE we abuse the newobj local as a cookie to signal null! + if(tempstack[j] == newobj) + { + ilGenerator.Emit(OpCodes.Ldnull); + } + else + { + ilGenerator.Emit(OpCodes.Ldloc, tempstack[j]); + } + } + } + LocalVar[] locals = localVars.GetLocalVarsForInvokeSpecial(i); + for(int j = 0; j < locals.Length; j++) + { + if(locals[j] != null) + { + if(locals[j].builder == null) + { + // for invokespecial the resulting type can never be null + locals[j].builder = ilGenerator.DeclareLocal(GetLocalBuilderType(locals[j].type)); + } + ilGenerator.Emit(OpCodes.Ldloc, newobj); + ilGenerator.Emit(OpCodes.Stloc, locals[j].builder); + } + } + } + else + { + if(trivcount == 0) + { + ilGenerator.Emit(OpCodes.Pop); + } + else + { + for(int j = 1; j < trivcount; j++) + { + ilGenerator.Emit(OpCodes.Dup); + } + } + } + } + else + { + Debug.Assert(type == VerifierTypeWrapper.UninitializedThis); + method.EmitCall(ilGenerator); + LocalVar[] locals = localVars.GetLocalVarsForInvokeSpecial(i); + for(int j = 0; j < locals.Length; j++) + { + if(locals[j] != null) + { + if(locals[j].builder == null) + { + // for invokespecial the resulting type can never be null + locals[j].builder = ilGenerator.DeclareLocal(GetLocalBuilderType(locals[j].type)); + } + ilGenerator.Emit(OpCodes.Ldarg_0); + ilGenerator.Emit(OpCodes.Stloc, locals[j].builder); + } + } + } + } + else + { + if(method.HasCallerID) + { + context.EmitCallerID(ilGenerator, m.IsLambdaFormCompiled); + } + + if(isinvokespecial) + { + if(VerifierTypeWrapper.IsThis(type)) + { + method.EmitCall(ilGenerator); + } + else if(method.IsPrivate) + { + // if the method is private, we can get away with a callvirt (and not generate the stub) + method.EmitCallvirt(ilGenerator); + } + else if(instr.NormalizedOpCode == NormalizedByteCode.__privileged_invokespecial) + { + method.EmitCall(ilGenerator); + } + else + { + ilGenerator.Emit(OpCodes.Callvirt, context.GetInvokeSpecialStub(method)); + } + } + else + { + // NOTE this check is written somewhat pessimistically, because we need to + // take remapped types into account. For example, Throwable.getClass() "overrides" + // the final Object.getClass() method and we don't want to call Object.getClass() + // on a Throwable instance, because that would yield unverifiable code (java.lang.Throwable + // extends System.Exception instead of java.lang.Object in the .NET type system). + if(VerifierTypeWrapper.IsThis(type) + && (method.IsFinal || clazz.IsFinal) + && clazz.GetMethodWrapper(method.Name, method.Signature, true) == method) + { + // we're calling a method on our own instance that can't possibly be overriden, + // so we don't need to use callvirt + method.EmitCall(ilGenerator); + } + else + { + method.EmitCallvirt(ilGenerator); + } + } + EmitReturnTypeConversion(method.ReturnType); + } + break; + } + case NormalizedByteCode.__clone_array: + ilGenerator.Emit(OpCodes.Callvirt, ArrayTypeWrapper.CloneMethod); + break; + case NormalizedByteCode.__return: + case NormalizedByteCode.__areturn: + case NormalizedByteCode.__ireturn: + case NormalizedByteCode.__lreturn: + case NormalizedByteCode.__freturn: + case NormalizedByteCode.__dreturn: + { + if(block.IsNested) + { + // if we're inside an exception block, copy TOS to local, emit "leave" and push item onto our "todo" list + CodeEmitterLocal local = null; + if(instr.NormalizedOpCode != NormalizedByteCode.__return) + { + TypeWrapper retTypeWrapper = mw.ReturnType; + retTypeWrapper.EmitConvStackTypeToSignatureType(ilGenerator, ma.GetStackTypeWrapper(i, 0)); + local = ilGenerator.UnsafeAllocTempLocal(retTypeWrapper.TypeAsSignatureType); + ilGenerator.Emit(OpCodes.Stloc, local); + } + CodeEmitterLabel label = ilGenerator.DefineLabel(); + // NOTE leave automatically discards any junk that may be on the stack + ilGenerator.EmitLeave(label); + block.AddExitHack(new ReturnCookie(label, local)); + } + else + { + // HACK the x64 JIT is lame and optimizes calls before ret into a tail call + // and this makes the method disappear from the call stack, so we try to thwart that + // by inserting some bogus instructions between the call and the return. + // Note that this optimization doesn't appear to happen if the method has exception handlers, + // so in that case we don't do anything. + bool x64hack = false; +#if !NET_4_0 + if(exceptions.Length == 0 && i > 0) + { + int k = i - 1; + while(k > 0 && code[k].NormalizedOpCode == NormalizedByteCode.__nop) + { + k--; + } + switch(code[k].NormalizedOpCode) + { + case NormalizedByteCode.__invokeinterface: + case NormalizedByteCode.__invokespecial: + case NormalizedByteCode.__invokestatic: + case NormalizedByteCode.__invokevirtual: + x64hack = true; + break; + } + } +#endif + // if there is junk on the stack (other than the return value), we must pop it off + // because in .NET this is invalid (unlike in Java) + int stackHeight = ma.GetStackHeight(i); + if(instr.NormalizedOpCode == NormalizedByteCode.__return) + { + if(stackHeight != 0 || x64hack) + { + ilGenerator.EmitClearStack(); + } + ilGenerator.Emit(OpCodes.Ret); + } + else + { + TypeWrapper retTypeWrapper = mw.ReturnType; + retTypeWrapper.EmitConvStackTypeToSignatureType(ilGenerator, ma.GetStackTypeWrapper(i, 0)); + if(stackHeight != 1) + { + CodeEmitterLocal local = ilGenerator.AllocTempLocal(retTypeWrapper.TypeAsSignatureType); + ilGenerator.Emit(OpCodes.Stloc, local); + ilGenerator.EmitClearStack(); + ilGenerator.Emit(OpCodes.Ldloc, local); + ilGenerator.ReleaseTempLocal(local); + } + else if(x64hack) + { + ilGenerator.EmitTailCallPrevention(); + } + ilGenerator.Emit(OpCodes.Ret); + } + } + break; + } + case NormalizedByteCode.__aload: + { + TypeWrapper type = ma.GetLocalTypeWrapper(i, instr.NormalizedArg1); + if(type == VerifierTypeWrapper.Null) + { + // if the local is known to be null, we just emit a null + ilGenerator.Emit(OpCodes.Ldnull); + } + else if(VerifierTypeWrapper.IsNotPresentOnStack(type)) + { + // since object isn't represented on the stack, we don't need to do anything here + } + else if(VerifierTypeWrapper.IsThis(type)) + { + ilGenerator.Emit(OpCodes.Ldarg_0); + } + else if(type == VerifierTypeWrapper.UninitializedThis) + { + // any unitialized this reference has to be loaded from arg 0 + // NOTE if the method overwrites the this references, it will always end up in + // a different local (due to the way the local variable liveness analysis works), + // so we don't have to worry about that. + ilGenerator.Emit(OpCodes.Ldarg_0); + } + else + { + LocalVar v = LoadLocal(i); + if(!type.IsUnloadable && (v.type.IsUnloadable || !v.type.IsAssignableTo(type))) + { + type.EmitCheckcast(ilGenerator); + } + } + break; + } + case NormalizedByteCode.__astore: + { + TypeWrapper type = ma.GetRawStackTypeWrapper(i, 0); + if(VerifierTypeWrapper.IsNotPresentOnStack(type)) + { + // object isn't really on the stack, so we can't copy it into the local + // (and the local doesn't exist anyway) + } + else if(type == VerifierTypeWrapper.UninitializedThis) + { + // any unitialized reference is always the this reference, we don't store anything + // here (because CLR won't allow unitialized references in locals) and then when + // the unitialized ref is loaded we redirect to the this reference + ilGenerator.Emit(OpCodes.Pop); + } + else + { + StoreLocal(i); + } + break; + } + case NormalizedByteCode.__iload: + case NormalizedByteCode.__lload: + case NormalizedByteCode.__fload: + case NormalizedByteCode.__dload: + LoadLocal(i); + break; + case NormalizedByteCode.__istore: + case NormalizedByteCode.__lstore: + StoreLocal(i); + break; + case NormalizedByteCode.__fstore: + StoreLocal(i); + break; + case NormalizedByteCode.__dstore: + if(ma.IsStackTypeExtendedDouble(i, 0)) + { + ilGenerator.Emit(OpCodes.Conv_R8); + } + StoreLocal(i); + break; + case NormalizedByteCode.__new: + { + TypeWrapper wrapper = classFile.GetConstantPoolClassType(instr.Arg1); + if(wrapper.IsUnloadable) + { + Profiler.Count("EmitDynamicNewCheckOnly"); + // this is here to make sure we throw the exception in the right location (before + // evaluating the constructor arguments) + EmitDynamicClassLiteral(wrapper); + ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicNewCheckOnly); + } + else if(wrapper != clazz && RequiresExplicitClassInit(wrapper, i + 1, flags)) + { + // trigger cctor (as the spec requires) + wrapper.EmitRunClassConstructor(ilGenerator); + } + // we don't actually allocate the object here, the call to will be converted into a newobj instruction + break; + } + case NormalizedByteCode.__multianewarray: + { + CodeEmitterLocal localArray = ilGenerator.UnsafeAllocTempLocal(JVM.Import(typeof(int[]))); + CodeEmitterLocal localInt = ilGenerator.UnsafeAllocTempLocal(Types.Int32); + ilGenerator.EmitLdc_I4(instr.Arg2); + ilGenerator.Emit(OpCodes.Newarr, Types.Int32); + ilGenerator.Emit(OpCodes.Stloc, localArray); + for(int j = 1; j <= instr.Arg2; j++) + { + ilGenerator.Emit(OpCodes.Stloc, localInt); + ilGenerator.Emit(OpCodes.Ldloc, localArray); + ilGenerator.EmitLdc_I4(instr.Arg2 - j); + ilGenerator.Emit(OpCodes.Ldloc, localInt); + ilGenerator.Emit(OpCodes.Stelem_I4); + } + TypeWrapper wrapper = classFile.GetConstantPoolClassType(instr.Arg1); + if(wrapper.IsUnloadable) + { + Profiler.Count("EmitDynamicMultianewarray"); + ilGenerator.Emit(OpCodes.Ldloc, localArray); + EmitDynamicClassLiteral(wrapper); + ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicMultianewarray); + } + else if(wrapper.IsGhost || wrapper.IsGhostArray) + { + TypeWrapper tw = wrapper; + while(tw.IsArray) + { + tw = tw.ElementTypeWrapper; + } + ilGenerator.Emit(OpCodes.Ldtoken, ArrayTypeWrapper.MakeArrayType(tw.TypeAsTBD, wrapper.ArrayRank)); + ilGenerator.Emit(OpCodes.Ldloc, localArray); + ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.multianewarray_ghost); + ilGenerator.Emit(OpCodes.Castclass, wrapper.TypeAsArrayType); + } + else + { + Type type = wrapper.TypeAsArrayType; + ilGenerator.Emit(OpCodes.Ldtoken, type); + ilGenerator.Emit(OpCodes.Ldloc, localArray); + ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.multianewarray); + ilGenerator.Emit(OpCodes.Castclass, type); + } + break; + } + case NormalizedByteCode.__anewarray: + { + TypeWrapper wrapper = classFile.GetConstantPoolClassType(instr.Arg1); + if(wrapper.IsUnloadable) + { + Profiler.Count("EmitDynamicNewarray"); + EmitDynamicClassLiteral(wrapper); + ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicNewarray); + } + else if(wrapper.IsGhost || wrapper.IsGhostArray) + { + // NOTE for ghost types we create object arrays to make sure that Ghost implementers can be + // stored in ghost arrays, but this has the unintended consequence that ghost arrays can + // contain *any* reference type (because they are compiled as Object arrays). We could + // modify aastore to emit code to check for this, but this would have an huge performance + // cost for all object arrays. + // Oddly, while the JVM accepts any reference for any other interface typed references, in the + // case of aastore it does check that the object actually implements the interface. This + // is unfortunate, but I think we can live with this minor incompatibility. + // Note that this does not break type safety, because when the incorrect object is eventually + // used as the ghost interface type it will generate a ClassCastException. + TypeWrapper tw = wrapper; + while(tw.IsArray) + { + tw = tw.ElementTypeWrapper; + } + ilGenerator.Emit(OpCodes.Ldtoken, ArrayTypeWrapper.MakeArrayType(tw.TypeAsTBD, wrapper.ArrayRank + 1)); + ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.anewarray_ghost.MakeGenericMethod(wrapper.TypeAsArrayType)); + } + else + { + ilGenerator.Emit(OpCodes.Newarr, wrapper.TypeAsArrayType); + } + break; + } + case NormalizedByteCode.__newarray: + switch(instr.Arg1) + { + case 4: + ilGenerator.Emit(OpCodes.Newarr, PrimitiveTypeWrapper.BOOLEAN.TypeAsArrayType); + break; + case 5: + ilGenerator.Emit(OpCodes.Newarr, PrimitiveTypeWrapper.CHAR.TypeAsArrayType); + break; + case 6: + ilGenerator.Emit(OpCodes.Newarr, PrimitiveTypeWrapper.FLOAT.TypeAsArrayType); + break; + case 7: + ilGenerator.Emit(OpCodes.Newarr, PrimitiveTypeWrapper.DOUBLE.TypeAsArrayType); + break; + case 8: + ilGenerator.Emit(OpCodes.Newarr, PrimitiveTypeWrapper.BYTE.TypeAsArrayType); + break; + case 9: + ilGenerator.Emit(OpCodes.Newarr, PrimitiveTypeWrapper.SHORT.TypeAsArrayType); + break; + case 10: + ilGenerator.Emit(OpCodes.Newarr, PrimitiveTypeWrapper.INT.TypeAsArrayType); + break; + case 11: + ilGenerator.Emit(OpCodes.Newarr, PrimitiveTypeWrapper.LONG.TypeAsArrayType); + break; + default: + // this can't happen, the verifier would have caught it + throw new InvalidOperationException(); + } + break; + case NormalizedByteCode.__checkcast: + { + TypeWrapper wrapper = classFile.GetConstantPoolClassType(instr.Arg1); + if(wrapper.IsUnloadable) + { + EmitDynamicCast(wrapper); + } + else + { + wrapper.EmitCheckcast(ilGenerator); + } + break; + } + case NormalizedByteCode.__instanceof: + { + TypeWrapper wrapper = classFile.GetConstantPoolClassType(instr.Arg1); + if(wrapper.IsUnloadable) + { + EmitDynamicInstanceOf(wrapper); + } + else + { + wrapper.EmitInstanceOf(ilGenerator); + } + break; + } + case NormalizedByteCode.__aaload: + { + TypeWrapper tw = ma.GetRawStackTypeWrapper(i, 1); + if(tw.IsUnloadable) + { + Profiler.Count("EmitDynamicAaload"); + ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicAaload); + } + else + { + TypeWrapper elem = tw.ElementTypeWrapper; + if(elem.IsNonPrimitiveValueType) + { + Type t = elem.TypeAsTBD; + ilGenerator.Emit(OpCodes.Ldelema, t); + ilGenerator.Emit(OpCodes.Ldobj, t); + elem.EmitBox(ilGenerator); + } + else + { + ilGenerator.Emit(OpCodes.Ldelem_Ref); + } + } + break; + } + case NormalizedByteCode.__baload: + // NOTE both the JVM and the CLR use signed bytes for boolean arrays (how convenient!) + ilGenerator.Emit(OpCodes.Ldelem_I1); + break; + case NormalizedByteCode.__bastore: + ilGenerator.Emit(OpCodes.Stelem_I1); + break; + case NormalizedByteCode.__caload: + ilGenerator.Emit(OpCodes.Ldelem_U2); + break; + case NormalizedByteCode.__castore: + ilGenerator.Emit(OpCodes.Stelem_I2); + break; + case NormalizedByteCode.__saload: + ilGenerator.Emit(OpCodes.Ldelem_I2); + break; + case NormalizedByteCode.__sastore: + ilGenerator.Emit(OpCodes.Stelem_I2); + break; + case NormalizedByteCode.__iaload: + ilGenerator.Emit(OpCodes.Ldelem_I4); + break; + case NormalizedByteCode.__iastore: + ilGenerator.Emit(OpCodes.Stelem_I4); + break; + case NormalizedByteCode.__laload: + ilGenerator.Emit(OpCodes.Ldelem_I8); + break; + case NormalizedByteCode.__lastore: + ilGenerator.Emit(OpCodes.Stelem_I8); + break; + case NormalizedByteCode.__faload: + ilGenerator.Emit(OpCodes.Ldelem_R4); + break; + case NormalizedByteCode.__fastore: + ilGenerator.Emit(OpCodes.Stelem_R4); + break; + case NormalizedByteCode.__daload: + ilGenerator.Emit(OpCodes.Ldelem_R8); + break; + case NormalizedByteCode.__dastore: + if(ma.IsStackTypeExtendedDouble(i, 0)) + { + ilGenerator.Emit(OpCodes.Conv_R8); + } + ilGenerator.Emit(OpCodes.Stelem_R8); + break; + case NormalizedByteCode.__aastore: + { + TypeWrapper tw = ma.GetRawStackTypeWrapper(i, 2); + if(tw.IsUnloadable) + { + Profiler.Count("EmitDynamicAastore"); + ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicAastore); + } + else + { + TypeWrapper elem = tw.ElementTypeWrapper; + if(elem.IsNonPrimitiveValueType) + { + Type t = elem.TypeAsTBD; + CodeEmitterLocal local = ilGenerator.UnsafeAllocTempLocal(Types.Object); + ilGenerator.Emit(OpCodes.Stloc, local); + ilGenerator.Emit(OpCodes.Ldelema, t); + ilGenerator.Emit(OpCodes.Ldloc, local); + elem.EmitUnbox(ilGenerator); + ilGenerator.Emit(OpCodes.Stobj, t); + } + else + { + // NOTE for verifiability it is expressly *not* required that the + // value matches the array type, so we don't need to handle interface + // references here. + ilGenerator.Emit(OpCodes.Stelem_Ref); + } + } + break; + } + case NormalizedByteCode.__arraylength: + if(ma.GetRawStackTypeWrapper(i, 0).IsUnloadable) + { + ilGenerator.Emit(OpCodes.Castclass, Types.Array); + ilGenerator.Emit(OpCodes.Callvirt, Types.Array.GetMethod("get_Length")); + } + else + { + ilGenerator.Emit(OpCodes.Ldlen); + } + break; + case NormalizedByteCode.__lcmp: + ilGenerator.Emit_lcmp(); + break; + case NormalizedByteCode.__fcmpl: + ilGenerator.Emit_fcmpl(); + break; + case NormalizedByteCode.__fcmpg: + ilGenerator.Emit_fcmpg(); + break; + case NormalizedByteCode.__dcmpl: + ilGenerator.Emit_dcmpl(); + break; + case NormalizedByteCode.__dcmpg: + ilGenerator.Emit_dcmpg(); + break; + case NormalizedByteCode.__if_icmpeq: + ilGenerator.EmitBeq(block.GetLabel(instr.TargetIndex)); + break; + case NormalizedByteCode.__if_icmpne: + ilGenerator.EmitBne_Un(block.GetLabel(instr.TargetIndex)); + break; + case NormalizedByteCode.__if_icmple: + ilGenerator.EmitBle(block.GetLabel(instr.TargetIndex)); + break; + case NormalizedByteCode.__if_icmplt: + ilGenerator.EmitBlt(block.GetLabel(instr.TargetIndex)); + break; + case NormalizedByteCode.__if_icmpge: + ilGenerator.EmitBge(block.GetLabel(instr.TargetIndex)); + break; + case NormalizedByteCode.__if_icmpgt: + ilGenerator.EmitBgt(block.GetLabel(instr.TargetIndex)); + break; + case NormalizedByteCode.__ifle: + ilGenerator.Emit_if_le_lt_ge_gt(CodeEmitter.Comparison.LessOrEqual, block.GetLabel(instr.TargetIndex)); + break; + case NormalizedByteCode.__iflt: + ilGenerator.Emit_if_le_lt_ge_gt(CodeEmitter.Comparison.LessThan, block.GetLabel(instr.TargetIndex)); + break; + case NormalizedByteCode.__ifge: + ilGenerator.Emit_if_le_lt_ge_gt(CodeEmitter.Comparison.GreaterOrEqual, block.GetLabel(instr.TargetIndex)); + break; + case NormalizedByteCode.__ifgt: + ilGenerator.Emit_if_le_lt_ge_gt(CodeEmitter.Comparison.GreaterThan, block.GetLabel(instr.TargetIndex)); + break; + case NormalizedByteCode.__ifne: + case NormalizedByteCode.__ifnonnull: + ilGenerator.EmitBrtrue(block.GetLabel(instr.TargetIndex)); + break; + case NormalizedByteCode.__ifeq: + case NormalizedByteCode.__ifnull: + ilGenerator.EmitBrfalse(block.GetLabel(instr.TargetIndex)); + break; + case NormalizedByteCode.__if_acmpeq: + ilGenerator.EmitBeq(block.GetLabel(instr.TargetIndex)); + break; + case NormalizedByteCode.__if_acmpne: + ilGenerator.EmitBne_Un(block.GetLabel(instr.TargetIndex)); + break; + case NormalizedByteCode.__goto: + case NormalizedByteCode.__goto_finally: + ilGenerator.EmitBr(block.GetLabel(instr.TargetIndex)); + break; + case NormalizedByteCode.__ineg: + case NormalizedByteCode.__lneg: + case NormalizedByteCode.__fneg: + case NormalizedByteCode.__dneg: + ilGenerator.Emit(OpCodes.Neg); + break; + case NormalizedByteCode.__iadd: + case NormalizedByteCode.__ladd: + ilGenerator.Emit(OpCodes.Add); + break; + case NormalizedByteCode.__fadd: + ilGenerator.Emit(OpCodes.Add); + ilGenerator.Emit(OpCodes.Conv_R4); + break; + case NormalizedByteCode.__dadd: + ilGenerator.Emit(OpCodes.Add); + if(strictfp) + { + ilGenerator.Emit(OpCodes.Conv_R8); + } + break; + case NormalizedByteCode.__isub: + case NormalizedByteCode.__lsub: + ilGenerator.Emit(OpCodes.Sub); + break; + case NormalizedByteCode.__fsub: + ilGenerator.Emit(OpCodes.Sub); + ilGenerator.Emit(OpCodes.Conv_R4); + break; + case NormalizedByteCode.__dsub: + ilGenerator.Emit(OpCodes.Sub); + if(strictfp) + { + ilGenerator.Emit(OpCodes.Conv_R8); + } + break; + case NormalizedByteCode.__ixor: + case NormalizedByteCode.__lxor: + ilGenerator.Emit(OpCodes.Xor); + break; + case NormalizedByteCode.__ior: + case NormalizedByteCode.__lor: + ilGenerator.Emit(OpCodes.Or); + break; + case NormalizedByteCode.__iand: + case NormalizedByteCode.__land: + ilGenerator.Emit(OpCodes.And); + break; + case NormalizedByteCode.__imul: + case NormalizedByteCode.__lmul: + ilGenerator.Emit(OpCodes.Mul); + break; + case NormalizedByteCode.__fmul: + ilGenerator.Emit(OpCodes.Mul); + ilGenerator.Emit(OpCodes.Conv_R4); + break; + case NormalizedByteCode.__dmul: + ilGenerator.Emit(OpCodes.Mul); + if(strictfp) + { + ilGenerator.Emit(OpCodes.Conv_R8); + } + break; + case NormalizedByteCode.__idiv: + ilGenerator.Emit_idiv(); + break; + case NormalizedByteCode.__ldiv: + ilGenerator.Emit_ldiv(); + break; + case NormalizedByteCode.__fdiv: + ilGenerator.Emit(OpCodes.Div); + ilGenerator.Emit(OpCodes.Conv_R4); + break; + case NormalizedByteCode.__ddiv: + ilGenerator.Emit(OpCodes.Div); + if(strictfp) + { + ilGenerator.Emit(OpCodes.Conv_R8); + } + break; + case NormalizedByteCode.__irem: + case NormalizedByteCode.__lrem: + { + // we need to special case taking the remainder of dividing by -1, + // because the CLR rem instruction throws an OverflowException when + // taking the remainder of dividing Int32.MinValue by -1, and + // Java just silently overflows + ilGenerator.Emit(OpCodes.Dup); + ilGenerator.Emit(OpCodes.Ldc_I4_M1); + if(instr.NormalizedOpCode == NormalizedByteCode.__lrem) + { + ilGenerator.Emit(OpCodes.Conv_I8); + } + CodeEmitterLabel label = ilGenerator.DefineLabel(); + ilGenerator.EmitBne_Un(label); + ilGenerator.Emit(OpCodes.Pop); + ilGenerator.Emit(OpCodes.Pop); + ilGenerator.Emit(OpCodes.Ldc_I4_0); + if(instr.NormalizedOpCode == NormalizedByteCode.__lrem) + { + ilGenerator.Emit(OpCodes.Conv_I8); + } + CodeEmitterLabel label2 = ilGenerator.DefineLabel(); + ilGenerator.EmitBr(label2); + ilGenerator.MarkLabel(label); + ilGenerator.Emit(OpCodes.Rem); + ilGenerator.MarkLabel(label2); + break; + } + case NormalizedByteCode.__frem: + ilGenerator.Emit(OpCodes.Rem); + ilGenerator.Emit(OpCodes.Conv_R4); + break; + case NormalizedByteCode.__drem: + ilGenerator.Emit(OpCodes.Rem); + if(strictfp) + { + ilGenerator.Emit(OpCodes.Conv_R8); + } + break; + case NormalizedByteCode.__ishl: + ilGenerator.Emit_And_I4(31); + ilGenerator.Emit(OpCodes.Shl); + break; + case NormalizedByteCode.__lshl: + ilGenerator.Emit_And_I4(63); + ilGenerator.Emit(OpCodes.Shl); + break; + case NormalizedByteCode.__iushr: + ilGenerator.Emit_And_I4(31); + ilGenerator.Emit(OpCodes.Shr_Un); + break; + case NormalizedByteCode.__lushr: + ilGenerator.Emit_And_I4(63); + ilGenerator.Emit(OpCodes.Shr_Un); + break; + case NormalizedByteCode.__ishr: + ilGenerator.Emit_And_I4(31); + ilGenerator.Emit(OpCodes.Shr); + break; + case NormalizedByteCode.__lshr: + ilGenerator.Emit_And_I4(63); + ilGenerator.Emit(OpCodes.Shr); + break; + case NormalizedByteCode.__swap: + { + DupHelper dh = new DupHelper(this, 2); + dh.SetType(0, ma.GetRawStackTypeWrapper(i, 0)); + dh.SetType(1, ma.GetRawStackTypeWrapper(i, 1)); + dh.Store(0); + dh.Store(1); + dh.Load(0); + dh.Load(1); + dh.Release(); + break; + } + case NormalizedByteCode.__dup: + // if the TOS contains a "new" object or a fault block exception, it isn't really there, so we don't dup it + if(!VerifierTypeWrapper.IsNotPresentOnStack(ma.GetRawStackTypeWrapper(i, 0))) + { + ilGenerator.Emit(OpCodes.Dup); + } + break; + case NormalizedByteCode.__dup2: + { + TypeWrapper type1 = ma.GetRawStackTypeWrapper(i, 0); + if(type1.IsWidePrimitive) + { + ilGenerator.Emit(OpCodes.Dup); + } + else + { + DupHelper dh = new DupHelper(this, 2); + dh.SetType(0, type1); + dh.SetType(1, ma.GetRawStackTypeWrapper(i, 1)); + dh.Store(0); + dh.Store(1); + dh.Load(1); + dh.Load(0); + dh.Load(1); + dh.Load(0); + dh.Release(); + } + break; + } + case NormalizedByteCode.__dup_x1: + { + DupHelper dh = new DupHelper(this, 2); + dh.SetType(0, ma.GetRawStackTypeWrapper(i, 0)); + dh.SetType(1, ma.GetRawStackTypeWrapper(i, 1)); + dh.Store(0); + dh.Store(1); + dh.Load(0); + dh.Load(1); + dh.Load(0); + dh.Release(); + break; + } + case NormalizedByteCode.__dup2_x1: + { + TypeWrapper type1 = ma.GetRawStackTypeWrapper(i, 0); + if(type1.IsWidePrimitive) + { + DupHelper dh = new DupHelper(this, 2); + dh.SetType(0, type1); + dh.SetType(1, ma.GetRawStackTypeWrapper(i, 1)); + dh.Store(0); + dh.Store(1); + dh.Load(0); + dh.Load(1); + dh.Load(0); + dh.Release(); + } + else + { + DupHelper dh = new DupHelper(this, 3); + dh.SetType(0, type1); + dh.SetType(1, ma.GetRawStackTypeWrapper(i, 1)); + dh.SetType(2, ma.GetRawStackTypeWrapper(i, 2)); + dh.Store(0); + dh.Store(1); + dh.Store(2); + dh.Load(1); + dh.Load(0); + dh.Load(2); + dh.Load(1); + dh.Load(0); + dh.Release(); + } + break; + } + case NormalizedByteCode.__dup2_x2: + { + TypeWrapper type1 = ma.GetRawStackTypeWrapper(i, 0); + TypeWrapper type2 = ma.GetRawStackTypeWrapper(i, 1); + if(type1.IsWidePrimitive) + { + if(type2.IsWidePrimitive) + { + // Form 4 + DupHelper dh = new DupHelper(this, 2); + dh.SetType(0, type1); + dh.SetType(1, type2); + dh.Store(0); + dh.Store(1); + dh.Load(0); + dh.Load(1); + dh.Load(0); + dh.Release(); + } + else + { + // Form 2 + DupHelper dh = new DupHelper(this, 3); + dh.SetType(0, type1); + dh.SetType(1, type2); + dh.SetType(2, ma.GetRawStackTypeWrapper(i, 2)); + dh.Store(0); + dh.Store(1); + dh.Store(2); + dh.Load(0); + dh.Load(2); + dh.Load(1); + dh.Load(0); + dh.Release(); + } + } + else + { + TypeWrapper type3 = ma.GetRawStackTypeWrapper(i, 2); + if(type3.IsWidePrimitive) + { + // Form 3 + DupHelper dh = new DupHelper(this, 3); + dh.SetType(0, type1); + dh.SetType(1, type2); + dh.SetType(2, type3); + dh.Store(0); + dh.Store(1); + dh.Store(2); + dh.Load(1); + dh.Load(0); + dh.Load(2); + dh.Load(1); + dh.Load(0); + dh.Release(); + } + else + { + // Form 1 + DupHelper dh = new DupHelper(this, 4); + dh.SetType(0, type1); + dh.SetType(1, type2); + dh.SetType(2, type3); + dh.SetType(3, ma.GetRawStackTypeWrapper(i, 3)); + dh.Store(0); + dh.Store(1); + dh.Store(2); + dh.Store(3); + dh.Load(1); + dh.Load(0); + dh.Load(3); + dh.Load(2); + dh.Load(1); + dh.Load(0); + dh.Release(); + } + } + break; + } + case NormalizedByteCode.__dup_x2: + { + TypeWrapper type2 = ma.GetRawStackTypeWrapper(i, 1); + if(type2.IsWidePrimitive) + { + // Form 2 + DupHelper dh = new DupHelper(this, 2); + dh.SetType(0, ma.GetRawStackTypeWrapper(i, 0)); + dh.SetType(1, type2); + dh.Store(0); + dh.Store(1); + dh.Load(0); + dh.Load(1); + dh.Load(0); + dh.Release(); + } + else + { + // Form 1 + DupHelper dh = new DupHelper(this, 3); + dh.SetType(0, ma.GetRawStackTypeWrapper(i, 0)); + dh.SetType(1, type2); + dh.SetType(2, ma.GetRawStackTypeWrapper(i, 2)); + dh.Store(0); + dh.Store(1); + dh.Store(2); + dh.Load(0); + dh.Load(2); + dh.Load(1); + dh.Load(0); + dh.Release(); + } + break; + } + case NormalizedByteCode.__pop2: + { + TypeWrapper type1 = ma.GetRawStackTypeWrapper(i, 0); + if(type1.IsWidePrimitive) + { + ilGenerator.Emit(OpCodes.Pop); + } + else + { + if (!VerifierTypeWrapper.IsNotPresentOnStack(type1)) + { + ilGenerator.Emit(OpCodes.Pop); + } + if (!VerifierTypeWrapper.IsNotPresentOnStack(ma.GetRawStackTypeWrapper(i, 1))) + { + ilGenerator.Emit(OpCodes.Pop); + } + } + break; + } + case NormalizedByteCode.__pop: + // if the TOS is a new object or a fault block exception, it isn't really there, so we don't need to pop it + if(!VerifierTypeWrapper.IsNotPresentOnStack(ma.GetRawStackTypeWrapper(i, 0))) + { + ilGenerator.Emit(OpCodes.Pop); + } + break; + case NormalizedByteCode.__monitorenter: + ilGenerator.EmitMonitorEnter(); + break; + case NormalizedByteCode.__monitorexit: + ilGenerator.EmitMonitorExit(); + break; + case NormalizedByteCode.__athrow_no_unmap: + if(ma.GetRawStackTypeWrapper(i, 0).IsUnloadable) + { + ilGenerator.Emit(OpCodes.Castclass, Types.Exception); + } + ilGenerator.Emit(OpCodes.Throw); + break; + case NormalizedByteCode.__athrow: + if (VerifierTypeWrapper.IsFaultBlockException(ma.GetRawStackTypeWrapper(i, 0))) + { + ilGenerator.Emit(OpCodes.Endfinally); + } + else + { + if (ma.GetRawStackTypeWrapper(i, 0).IsUnloadable) + { + ilGenerator.Emit(OpCodes.Castclass, Types.Exception); + } + ilGenerator.Emit(OpCodes.Call, unmapExceptionMethod); + ilGenerator.Emit(OpCodes.Throw); + } + break; + case NormalizedByteCode.__tableswitch: + { + // note that a tableswitch always has at least one entry + // (otherwise it would have failed verification) + CodeEmitterLabel[] labels = new CodeEmitterLabel[instr.SwitchEntryCount]; + for(int j = 0; j < labels.Length; j++) + { + labels[j] = block.GetLabel(instr.GetSwitchTargetIndex(j)); + } + if(instr.GetSwitchValue(0) != 0) + { + ilGenerator.EmitLdc_I4(instr.GetSwitchValue(0)); + ilGenerator.Emit(OpCodes.Sub); + } + ilGenerator.EmitSwitch(labels); + ilGenerator.EmitBr(block.GetLabel(instr.DefaultTarget)); + break; + } + case NormalizedByteCode.__lookupswitch: + for(int j = 0; j < instr.SwitchEntryCount; j++) + { + ilGenerator.Emit(OpCodes.Dup); + ilGenerator.EmitLdc_I4(instr.GetSwitchValue(j)); + CodeEmitterLabel label = ilGenerator.DefineLabel(); + ilGenerator.EmitBne_Un(label); + ilGenerator.Emit(OpCodes.Pop); + ilGenerator.EmitBr(block.GetLabel(instr.GetSwitchTargetIndex(j))); + ilGenerator.MarkLabel(label); + } + ilGenerator.Emit(OpCodes.Pop); + ilGenerator.EmitBr(block.GetLabel(instr.DefaultTarget)); + break; + case NormalizedByteCode.__iinc: + LoadLocal(i); + ilGenerator.EmitLdc_I4(instr.Arg2); + ilGenerator.Emit(OpCodes.Add); + StoreLocal(i); + break; + case NormalizedByteCode.__i2b: + ilGenerator.Emit(OpCodes.Conv_I1); + break; + case NormalizedByteCode.__i2c: + ilGenerator.Emit(OpCodes.Conv_U2); + break; + case NormalizedByteCode.__i2s: + ilGenerator.Emit(OpCodes.Conv_I2); + break; + case NormalizedByteCode.__l2i: + ilGenerator.Emit(OpCodes.Conv_I4); + break; + case NormalizedByteCode.__f2i: + ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.f2i); + break; + case NormalizedByteCode.__d2i: + ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.d2i); + break; + case NormalizedByteCode.__f2l: + ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.f2l); + break; + case NormalizedByteCode.__d2l: + ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.d2l); + break; + case NormalizedByteCode.__i2l: + ilGenerator.Emit(OpCodes.Conv_I8); + break; + case NormalizedByteCode.__i2f: + case NormalizedByteCode.__l2f: + case NormalizedByteCode.__d2f: + ilGenerator.Emit(OpCodes.Conv_R4); + break; + case NormalizedByteCode.__i2d: + case NormalizedByteCode.__l2d: + case NormalizedByteCode.__f2d: + ilGenerator.Emit(OpCodes.Conv_R8); + break; + case NormalizedByteCode.__nop: + ilGenerator.Emit(OpCodes.Nop); + break; + case NormalizedByteCode.__intrinsic_gettype: + ilGenerator.Emit(OpCodes.Callvirt, getTypeMethod); + break; + case NormalizedByteCode.__static_error: + { + bool wrapIncompatibleClassChangeError = false; + TypeWrapper exceptionType; + switch(instr.HardError) + { + case HardError.AbstractMethodError: + exceptionType = ClassLoaderWrapper.LoadClassCritical("java.lang.AbstractMethodError"); + break; + case HardError.IllegalAccessError: + exceptionType = ClassLoaderWrapper.LoadClassCritical("java.lang.IllegalAccessError"); + break; + case HardError.IncompatibleClassChangeError: + exceptionType = ClassLoaderWrapper.LoadClassCritical("java.lang.IncompatibleClassChangeError"); + break; + case HardError.InstantiationError: + exceptionType = ClassLoaderWrapper.LoadClassCritical("java.lang.InstantiationError"); + break; + case HardError.LinkageError: + exceptionType = ClassLoaderWrapper.LoadClassCritical("java.lang.LinkageError"); + break; + case HardError.NoClassDefFoundError: + exceptionType = ClassLoaderWrapper.LoadClassCritical("java.lang.NoClassDefFoundError"); + break; + case HardError.NoSuchFieldError: + exceptionType = ClassLoaderWrapper.LoadClassCritical("java.lang.NoSuchFieldError"); + break; + case HardError.NoSuchMethodError: + exceptionType = ClassLoaderWrapper.LoadClassCritical("java.lang.NoSuchMethodError"); + break; + case HardError.IllegalAccessException: + exceptionType = ClassLoaderWrapper.LoadClassCritical("java.lang.IllegalAccessException"); + wrapIncompatibleClassChangeError = true; + break; + default: + throw new InvalidOperationException(); + } + if(wrapIncompatibleClassChangeError) + { + ClassLoaderWrapper.LoadClassCritical("java.lang.IncompatibleClassChangeError").GetMethodWrapper("", "()V", false).EmitNewobj(ilGenerator); + } + string message = harderrors[instr.HardErrorMessageId]; + Tracer.Error(Tracer.Compiler, "{0}: {1}\n\tat {2}.{3}{4}", exceptionType.Name, message, classFile.Name, m.Name, m.Signature); + ilGenerator.Emit(OpCodes.Ldstr, message); + MethodWrapper method = exceptionType.GetMethodWrapper("", "(Ljava.lang.String;)V", false); + method.Link(); + method.EmitNewobj(ilGenerator); + if(wrapIncompatibleClassChangeError) + { + CoreClasses.java.lang.Throwable.Wrapper.GetMethodWrapper("initCause", "(Ljava.lang.Throwable;)Ljava.lang.Throwable;", false).EmitCallvirt(ilGenerator); + } + ilGenerator.Emit(OpCodes.Throw); + break; + } + default: + throw new NotImplementedException(instr.NormalizedOpCode.ToString()); + } + // mark next instruction as inuse + switch(ByteCodeMetaData.GetFlowControl(instr.NormalizedOpCode)) + { + case ByteCodeFlowControl.Switch: + case ByteCodeFlowControl.Branch: + case ByteCodeFlowControl.Return: + case ByteCodeFlowControl.Throw: + instructionIsForwardReachable = false; + break; + case ByteCodeFlowControl.CondBranch: + case ByteCodeFlowControl.Next: + instructionIsForwardReachable = true; + Debug.Assert((flags[i + 1] & InstructionFlags.Reachable) != 0); + // don't fall through end of try block + if(block.EndIndex == i + 1) + { + // TODO instead of emitting a branch to the leave stub, it would be more efficient to put the leave stub here + ilGenerator.EmitBr(block.GetLabel(i + 1)); + } + break; + default: + throw new InvalidOperationException(); + } + } + } + + private void EmitReturnTypeConversion(TypeWrapper returnType) + { + returnType.EmitConvSignatureTypeToStackType(ilGenerator); + if (!strictfp) + { + // no need to convert + } + else if (returnType == PrimitiveTypeWrapper.DOUBLE) + { + ilGenerator.Emit(OpCodes.Conv_R8); + } + else if (returnType == PrimitiveTypeWrapper.FLOAT) + { + ilGenerator.Emit(OpCodes.Conv_R4); + } + } + + private void EmitLoadConstant(CodeEmitter ilgen, int constant) + { + switch (classFile.GetConstantPoolConstantType(constant)) + { + case ClassFile.ConstantType.Double: + ilgen.EmitLdc_R8(classFile.GetConstantPoolConstantDouble(constant)); + break; + case ClassFile.ConstantType.Float: + ilgen.EmitLdc_R4(classFile.GetConstantPoolConstantFloat(constant)); + break; + case ClassFile.ConstantType.Integer: + ilgen.EmitLdc_I4(classFile.GetConstantPoolConstantInteger(constant)); + break; + case ClassFile.ConstantType.Long: + ilgen.EmitLdc_I8(classFile.GetConstantPoolConstantLong(constant)); + break; + case ClassFile.ConstantType.String: + ilgen.Emit(OpCodes.Ldstr, classFile.GetConstantPoolConstantString(constant)); + break; + case ClassFile.ConstantType.Class: + EmitLoadClass(ilgen, classFile.GetConstantPoolClassType(constant)); + break; + case ClassFile.ConstantType.MethodHandle: + context.GetValue(constant).Emit(this, ilgen, constant); + break; + case ClassFile.ConstantType.MethodType: + context.GetValue(constant).Emit(this, ilgen, constant); + break; +#if !STATIC_COMPILER + case ClassFile.ConstantType.LiveObject: + context.EmitLiveObjectLoad(ilgen, classFile.GetConstantPoolConstantLiveObject(constant)); + break; +#endif + default: + throw new InvalidOperationException(); + } + } + + private void EmitDynamicCast(TypeWrapper tw) + { + Debug.Assert(tw.IsUnloadable); + Profiler.Count("EmitDynamicCast"); + // NOTE it's important that we don't try to load the class if obj == null + CodeEmitterLabel ok = ilGenerator.DefineLabel(); + ilGenerator.Emit(OpCodes.Dup); + ilGenerator.EmitBrfalse(ok); + EmitDynamicClassLiteral(tw); + ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicCast); + ilGenerator.MarkLabel(ok); + } + + private void EmitDynamicInstanceOf(TypeWrapper tw) + { + // NOTE it's important that we don't try to load the class if obj == null + CodeEmitterLabel notnull = ilGenerator.DefineLabel(); + CodeEmitterLabel end = ilGenerator.DefineLabel(); + ilGenerator.Emit(OpCodes.Dup); + ilGenerator.EmitBrtrue(notnull); + ilGenerator.Emit(OpCodes.Pop); + ilGenerator.EmitLdc_I4(0); + ilGenerator.EmitBr(end); + ilGenerator.MarkLabel(notnull); + EmitDynamicClassLiteral(tw); + ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicInstanceOf); + ilGenerator.MarkLabel(end); + } + + private void EmitDynamicClassLiteral(TypeWrapper tw) + { + context.EmitDynamicClassLiteral(ilGenerator, tw, m.IsLambdaFormCompiled); + } + + private void EmitLoadClass(CodeEmitter ilgen, TypeWrapper tw) + { + if (tw.IsUnloadable) + { + Profiler.Count("EmitDynamicClassLiteral"); + context.EmitDynamicClassLiteral(ilgen, tw, m.IsLambdaFormCompiled); + } + else + { + tw.EmitClassLiteral(ilgen); + } + } + + internal static bool HasUnloadable(TypeWrapper[] args, TypeWrapper ret) + { + TypeWrapper tw = ret; + for (int i = 0; !tw.IsUnloadable && i < args.Length; i++) + { + tw = args[i]; + } + return tw.IsUnloadable; + } + + private static class InvokeDynamicBuilder + { + private static readonly Type typeofOpenIndyCallSite; + private static readonly Type typeofCallSite; + private static readonly MethodWrapper methodLookup; + + static InvokeDynamicBuilder() + { +#if STATIC_COMPILER + typeofOpenIndyCallSite = StaticCompiler.GetRuntimeType("IKVM.Runtime.IndyCallSite`1"); + typeofCallSite = ClassLoaderWrapper.LoadClassCritical("java.lang.invoke.CallSite").TypeAsSignatureType; +#elif !FIRST_PASS + typeofOpenIndyCallSite = typeof(IKVM.Runtime.IndyCallSite<>); + typeofCallSite = typeof(java.lang.invoke.CallSite); +#endif + methodLookup = ClassLoaderWrapper.LoadClassCritical("java.lang.invoke.MethodHandles") + .GetMethodWrapper("lookup", "()Ljava.lang.invoke.MethodHandles$Lookup;", false); + methodLookup.Link(); + } + + internal static void Emit(Compiler compiler, ClassFile.ConstantPoolItemInvokeDynamic cpi, Type delegateType) + { + Type typeofIndyCallSite = typeofOpenIndyCallSite.MakeGenericType(delegateType); + MethodInfo methodCreateBootStrap; + MethodInfo methodGetTarget; + if (ReflectUtil.ContainsTypeBuilder(typeofIndyCallSite)) + { + methodCreateBootStrap = TypeBuilder.GetMethod(typeofIndyCallSite, typeofOpenIndyCallSite.GetMethod("CreateBootstrap")); + methodGetTarget = TypeBuilder.GetMethod(typeofIndyCallSite, typeofOpenIndyCallSite.GetMethod("GetTarget")); + } + else + { + methodCreateBootStrap = typeofIndyCallSite.GetMethod("CreateBootstrap"); + methodGetTarget = typeofIndyCallSite.GetMethod("GetTarget"); + } + TypeBuilder tb = compiler.context.DefineIndyCallSiteType(); + FieldBuilder fb = tb.DefineField("value", typeofIndyCallSite, FieldAttributes.Static | FieldAttributes.Assembly); + CodeEmitter ilgen = CodeEmitter.Create(ReflectUtil.DefineTypeInitializer(tb, compiler.clazz.GetClassLoader())); + ilgen.Emit(OpCodes.Ldnull); + ilgen.Emit(OpCodes.Ldftn, CreateBootstrapStub(compiler, cpi, delegateType, tb, fb, methodGetTarget)); + ilgen.Emit(OpCodes.Newobj, MethodHandleUtil.GetDelegateConstructor(delegateType)); + ilgen.Emit(OpCodes.Call, methodCreateBootStrap); + ilgen.Emit(OpCodes.Stsfld, fb); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + + compiler.ilGenerator.Emit(OpCodes.Ldsfld, fb); + compiler.ilGenerator.Emit(OpCodes.Call, methodGetTarget); + } + + private static MethodBuilder CreateBootstrapStub(Compiler compiler, ClassFile.ConstantPoolItemInvokeDynamic cpi, Type delegateType, TypeBuilder tb, FieldBuilder fb, MethodInfo methodGetTarget) + { + Type[] args = Type.EmptyTypes; + if (delegateType.IsGenericType) + { + // MONOBUG we don't look at the invoke method directly here, because Mono doesn't support GetParameters() on a builder instantiation + args = delegateType.GetGenericArguments(); + if (cpi.GetRetType() != PrimitiveTypeWrapper.VOID) + { + Array.Resize(ref args, args.Length - 1); + } + } + MethodBuilder mb = tb.DefineMethod("BootstrapStub", MethodAttributes.Static | MethodAttributes.PrivateScope, cpi.GetRetType().TypeAsSignatureType, args); + CodeEmitter ilgen = CodeEmitter.Create(mb); + CodeEmitterLocal cs = ilgen.DeclareLocal(typeofCallSite); + CodeEmitterLocal ex = ilgen.DeclareLocal(Types.Exception); + CodeEmitterLocal ok = ilgen.DeclareLocal(Types.Boolean); + CodeEmitterLabel label = ilgen.DefineLabel(); + ilgen.BeginExceptionBlock(); + if (EmitCallBootstrapMethod(compiler, cpi, ilgen, ok)) + { + ilgen.Emit(OpCodes.Isinst, typeofCallSite); + ilgen.Emit(OpCodes.Stloc, cs); + } + ilgen.EmitLeave(label); + ilgen.BeginCatchBlock(Types.Exception); + ilgen.Emit(OpCodes.Stloc, ex); + ilgen.Emit(OpCodes.Ldloc, ok); + CodeEmitterLabel label2 = ilgen.DefineLabel(); + ilgen.EmitBrtrue(label2); + ilgen.Emit(OpCodes.Rethrow); + ilgen.MarkLabel(label2); + ilgen.EmitLeave(label); + ilgen.EndExceptionBlock(); + ilgen.MarkLabel(label); + ilgen.Emit(OpCodes.Ldsflda, fb); + ilgen.Emit(OpCodes.Ldloc, cs); + ilgen.Emit(OpCodes.Ldloc, ex); + if (HasUnloadable(cpi.GetArgTypes(), cpi.GetRetType())) + { + ilgen.Emit(OpCodes.Ldstr, cpi.Signature); + compiler.context.EmitCallerID(ilgen, compiler.m.IsLambdaFormHidden); + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicLinkIndyCallSite.MakeGenericMethod(delegateType)); + } + else + { + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.LinkIndyCallSite.MakeGenericMethod(delegateType)); + } + ilgen.Emit(OpCodes.Ldsfld, fb); + ilgen.Emit(OpCodes.Call, methodGetTarget); + for (int i = 0; i < args.Length; i++) + { + ilgen.EmitLdarg(i); + } + ilgen.Emit(OpCodes.Callvirt, MethodHandleUtil.GetDelegateInvokeMethod(delegateType)); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + return mb; + } + + private static bool EmitCallBootstrapMethod(Compiler compiler, ClassFile.ConstantPoolItemInvokeDynamic cpi, CodeEmitter ilgen, CodeEmitterLocal ok) + { + ClassFile.BootstrapMethod bsm = compiler.classFile.GetBootstrapMethod(cpi.BootstrapMethod); + if (3 + bsm.ArgumentCount > 255) + { + ilgen.EmitThrow("java.lang.BootstrapMethodError", "too many bootstrap method arguments"); + return false; + } + ClassFile.ConstantPoolItemMethodHandle mh = compiler.classFile.GetConstantPoolConstantMethodHandle(bsm.BootstrapMethodIndex); + MethodWrapper mw = mh.Member as MethodWrapper; + switch (mh.Kind) + { + case ClassFile.RefKind.invokeStatic: + if (mw != null && !mw.IsStatic) + goto default; + break; + case ClassFile.RefKind.newInvokeSpecial: + if (mw != null && !mw.IsConstructor) + goto default; + break; + default: + // to throw the right exception, we have to resolve the MH constant here + compiler.context.GetValue(bsm.BootstrapMethodIndex).Emit(compiler, ilgen, bsm.BootstrapMethodIndex); + ilgen.Emit(OpCodes.Pop); + ilgen.EmitLdc_I4(1); + ilgen.Emit(OpCodes.Stloc, ok); + ilgen.EmitThrow("java.lang.invoke.WrongMethodTypeException"); + return false; + } + if (mw == null) + { + // to throw the right exception (i.e. without wrapping it in a BootstrapMethodError), we have to resolve the MH constant here + compiler.context.GetValue(bsm.BootstrapMethodIndex).Emit(compiler, ilgen, bsm.BootstrapMethodIndex); + ilgen.Emit(OpCodes.Pop); + ClassFile.ConstantPoolItemMI cpiMI; + if ((cpiMI = mh.MemberConstantPoolItem as ClassFile.ConstantPoolItemMI) != null) + { + mw = new DynamicBinder().Get(compiler, mh.Kind, cpiMI, false); + } + else + { + ilgen.EmitLdc_I4(1); + ilgen.Emit(OpCodes.Stloc, ok); + ilgen.EmitThrow("java.lang.invoke.WrongMethodTypeException"); + return false; + } + } + TypeWrapper[] parameters = mw.GetParameters(); + int extraArgs = parameters.Length - 3; + int fixedArgs; + int varArgs; + if (extraArgs == 1 && parameters[3].IsArray && parameters[3].ElementTypeWrapper == CoreClasses.java.lang.Object.Wrapper) + { + fixedArgs = 0; + varArgs = bsm.ArgumentCount - fixedArgs; + } + else if (extraArgs != bsm.ArgumentCount) + { + ilgen.EmitLdc_I4(1); + ilgen.Emit(OpCodes.Stloc, ok); + ilgen.EmitThrow("java.lang.invoke.WrongMethodTypeException"); + return false; + } + else + { + fixedArgs = extraArgs; + varArgs = -1; + } + compiler.context.EmitCallerID(ilgen, compiler.m.IsLambdaFormCompiled); + methodLookup.EmitCall(ilgen); + ilgen.Emit(OpCodes.Ldstr, cpi.Name); + parameters[1].EmitConvStackTypeToSignatureType(ilgen, CoreClasses.java.lang.String.Wrapper); + if (HasUnloadable(cpi.GetArgTypes(), cpi.GetRetType())) + { + // the cache is useless since we only run once, so we use a local + ilgen.Emit(OpCodes.Ldloca, ilgen.DeclareLocal(CoreClasses.java.lang.invoke.MethodType.Wrapper.TypeAsSignatureType)); + ilgen.Emit(OpCodes.Ldstr, cpi.Signature); + compiler.context.EmitCallerID(ilgen, compiler.m.IsLambdaFormCompiled); + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicLoadMethodType); + } + else + { + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.LoadMethodType.MakeGenericMethod(MethodHandleUtil.CreateDelegateTypeForLoadConstant(cpi.GetArgTypes(), cpi.GetRetType()))); + } + parameters[2].EmitConvStackTypeToSignatureType(ilgen, CoreClasses.java.lang.invoke.MethodType.Wrapper); + for (int i = 0; i < fixedArgs; i++) + { + EmitExtraArg(compiler, ilgen, bsm, i, parameters[i + 3], ok); + } + if (varArgs >= 0) + { + ilgen.EmitLdc_I4(varArgs); + TypeWrapper elemType = parameters[parameters.Length - 1].ElementTypeWrapper; + ilgen.Emit(OpCodes.Newarr, elemType.TypeAsArrayType); + for (int i = 0; i < varArgs; i++) + { + ilgen.Emit(OpCodes.Dup); + ilgen.EmitLdc_I4(i); + EmitExtraArg(compiler, ilgen, bsm, i + fixedArgs, elemType, ok); + ilgen.Emit(OpCodes.Stelem_Ref); + } + } + ilgen.EmitLdc_I4(1); + ilgen.Emit(OpCodes.Stloc, ok); + if (mw.IsConstructor) + { + mw.EmitNewobj(ilgen); + } + else + { + mw.EmitCall(ilgen); + } + return true; + } + + private static void EmitExtraArg(Compiler compiler, CodeEmitter ilgen, ClassFile.BootstrapMethod bsm, int index, TypeWrapper targetType, CodeEmitterLocal wrapException) + { + int constant = bsm.GetArgument(index); + compiler.EmitLoadConstant(ilgen, constant); + TypeWrapper constType; + switch (compiler.classFile.GetConstantPoolConstantType(constant)) + { + case ClassFile.ConstantType.Integer: + constType = PrimitiveTypeWrapper.INT; + break; + case ClassFile.ConstantType.Long: + constType = PrimitiveTypeWrapper.LONG; + break; + case ClassFile.ConstantType.Float: + constType = PrimitiveTypeWrapper.FLOAT; + break; + case ClassFile.ConstantType.Double: + constType = PrimitiveTypeWrapper.DOUBLE; + break; + case ClassFile.ConstantType.Class: + constType = CoreClasses.java.lang.Class.Wrapper; + break; + case ClassFile.ConstantType.String: + constType = CoreClasses.java.lang.String.Wrapper; + break; + case ClassFile.ConstantType.MethodHandle: + constType = CoreClasses.java.lang.invoke.MethodHandle.Wrapper; + break; + case ClassFile.ConstantType.MethodType: + constType = CoreClasses.java.lang.invoke.MethodType.Wrapper; + break; + default: + throw new InvalidOperationException(); + } + if (constType != targetType) + { + ilgen.EmitLdc_I4(1); + ilgen.Emit(OpCodes.Stloc, wrapException); + if (constType.IsPrimitive) + { + string dummy; + TypeWrapper wrapper = GetWrapperType(constType, out dummy); + wrapper.GetMethodWrapper("valueOf", "(" + constType.SigName + ")" + wrapper.SigName, false).EmitCall(ilgen); + } + if (targetType.IsUnloadable) + { + // do nothing + } + else if (targetType.IsPrimitive) + { + string unbox; + TypeWrapper wrapper = GetWrapperType(targetType, out unbox); + ilgen.Emit(OpCodes.Castclass, wrapper.TypeAsBaseType); + wrapper.GetMethodWrapper(unbox, "()" + targetType.SigName, false).EmitCallvirt(ilgen); + } + else if (!constType.IsAssignableTo(targetType)) + { + ilgen.Emit(OpCodes.Castclass, targetType.TypeAsBaseType); + } + targetType.EmitConvStackTypeToSignatureType(ilgen, targetType); + ilgen.EmitLdc_I4(0); + ilgen.Emit(OpCodes.Stloc, wrapException); + } + } + + private static TypeWrapper GetWrapperType(TypeWrapper tw, out string unbox) + { + if (tw == PrimitiveTypeWrapper.INT) + { + unbox = "intValue"; + return ClassLoaderWrapper.LoadClassCritical("java.lang.Integer"); + } + else if (tw == PrimitiveTypeWrapper.LONG) + { + unbox = "longValue"; + return ClassLoaderWrapper.LoadClassCritical("java.lang.Long"); + } + else if (tw == PrimitiveTypeWrapper.FLOAT) + { + unbox = "floatValue"; + return ClassLoaderWrapper.LoadClassCritical("java.lang.Float"); + } + else if (tw == PrimitiveTypeWrapper.DOUBLE) + { + unbox = "doubleValue"; + return ClassLoaderWrapper.LoadClassCritical("java.lang.Double"); + } + else + { + throw new InvalidOperationException(); + } + } + } + + private void EmitInvokeDynamic(ClassFile.ConstantPoolItemInvokeDynamic cpi) + { + CodeEmitter ilgen = ilGenerator; + TypeWrapper[] args = cpi.GetArgTypes(); + CodeEmitterLocal[] temps = new CodeEmitterLocal[args.Length]; + for (int i = args.Length - 1; i >= 0; i--) + { + temps[i] = ilgen.DeclareLocal(args[i].TypeAsSignatureType); + ilgen.Emit(OpCodes.Stloc, temps[i]); + } + Type delegateType = MethodHandleUtil.CreateMethodHandleDelegateType(args, cpi.GetRetType()); + InvokeDynamicBuilder.Emit(this, cpi, delegateType); + for (int i = 0; i < args.Length; i++) + { + ilgen.Emit(OpCodes.Ldloc, temps[i]); + } + MethodHandleUtil.EmitCallDelegateInvokeMethod(ilgen, delegateType); + } + + private sealed class MethodHandleConstant + { + private FieldBuilder field; + + internal void Emit(Compiler compiler, CodeEmitter ilgen, int index) + { + if (field == null) + { + field = compiler.context.DefineDynamicMethodHandleCacheField(); + } + ClassFile.ConstantPoolItemMethodHandle mh = compiler.classFile.GetConstantPoolConstantMethodHandle(index); + ilgen.Emit(OpCodes.Ldsflda, field); + ilgen.EmitLdc_I4((int)mh.Kind); + ilgen.Emit(OpCodes.Ldstr, mh.Class); + ilgen.Emit(OpCodes.Ldstr, mh.Name); + ilgen.Emit(OpCodes.Ldstr, mh.Signature); + compiler.context.EmitCallerID(ilgen, compiler.m.IsLambdaFormCompiled); + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicLoadMethodHandle); + } + } + + private sealed class MethodTypeConstant + { + private FieldBuilder field; + private bool dynamic; + + internal void Emit(Compiler compiler, CodeEmitter ilgen, int index) + { + if (field == null) + { + field = CreateField(compiler, index, ref dynamic); + } + if (dynamic) + { + ilgen.Emit(OpCodes.Ldsflda, field); + ilgen.Emit(OpCodes.Ldstr, compiler.classFile.GetConstantPoolConstantMethodType(index).Signature); + compiler.context.EmitCallerID(ilgen, compiler.m.IsLambdaFormCompiled); + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicLoadMethodType); + } + else + { + ilgen.Emit(OpCodes.Ldsfld, field); + } + } + + private static FieldBuilder CreateField(Compiler compiler, int index, ref bool dynamic) + { + ClassFile.ConstantPoolItemMethodType cpi = compiler.classFile.GetConstantPoolConstantMethodType(index); + TypeWrapper[] args = cpi.GetArgTypes(); + TypeWrapper ret = cpi.GetRetType(); + + if (HasUnloadable(args, ret)) + { + dynamic = true; + return compiler.context.DefineDynamicMethodTypeCacheField(); + } + else + { + TypeBuilder tb = compiler.context.DefineMethodTypeConstantType(index); + FieldBuilder field = tb.DefineField("value", CoreClasses.java.lang.invoke.MethodType.Wrapper.TypeAsSignatureType, FieldAttributes.Assembly | FieldAttributes.Static | FieldAttributes.InitOnly); + CodeEmitter ilgen = CodeEmitter.Create(ReflectUtil.DefineTypeInitializer(tb, compiler.clazz.GetClassLoader())); + Type delegateType = MethodHandleUtil.CreateDelegateTypeForLoadConstant(args, ret); + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.LoadMethodType.MakeGenericMethod(delegateType)); + ilgen.Emit(OpCodes.Stsfld, field); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + return field; + } + } + } + + private bool RequiresExplicitClassInit(TypeWrapper tw, int index, InstructionFlags[] flags) + { + ClassFile.Method.Instruction[] code = m.Instructions; + for (; index < code.Length; index++) + { + if (code[index].NormalizedOpCode == NormalizedByteCode.__invokespecial) + { + ClassFile.ConstantPoolItemMI cpi = classFile.GetMethodref(code[index].Arg1); + MethodWrapper mw = cpi.GetMethodForInvokespecial(); + return !mw.IsConstructor || mw.DeclaringType != tw; + } + if ((flags[index] & InstructionFlags.BranchTarget) != 0 + || ByteCodeMetaData.IsBranch(code[index].NormalizedOpCode) + || ByteCodeMetaData.CanThrowException(code[index].NormalizedOpCode)) + { + break; + } + } + return true; + } + + // NOTE despite its name this also handles value type args + private void CastInterfaceArgs(TypeWrapper declaringType, TypeWrapper[] args, int instructionIndex, bool instanceMethod) + { + bool needsCast = false; + int firstCastArg = -1; + + if(!needsCast) + { + for(int i = 0; i < args.Length; i++) + { + if(args[i].IsUnloadable) + { + // nothing to do, callee will (eventually) do the cast + } + else if(args[i].IsGhost) + { + needsCast = true; + firstCastArg = i; + break; + } + else if(args[i].IsInterfaceOrInterfaceArray) + { + TypeWrapper tw = ma.GetStackTypeWrapper(instructionIndex, args.Length - 1 - i); + if(tw.IsUnloadable || NeedsInterfaceDownCast(tw, args[i])) + { + needsCast = true; + firstCastArg = i; + break; + } + } + else if(args[i].IsNonPrimitiveValueType) + { + if(i == 0 && instanceMethod && declaringType != args[i]) + { + // no cast needed because we're calling an inherited method + } + else + { + needsCast = true; + firstCastArg = i; + break; + } + } + // if the stack contains an unloadable, we might need to cast it + // (e.g. if the argument type is a base class that is loadable) + if(ma.GetRawStackTypeWrapper(instructionIndex, args.Length - 1 - i).IsUnloadable) + { + needsCast = true; + firstCastArg = i; + break; + } + } + } + + if(needsCast) + { + DupHelper dh = new DupHelper(this, args.Length); + for(int i = firstCastArg + 1; i < args.Length; i++) + { + TypeWrapper tw = ma.GetRawStackTypeWrapper(instructionIndex, args.Length - 1 - i); + if(tw != VerifierTypeWrapper.UninitializedThis + && !VerifierTypeWrapper.IsThis(tw)) + { + tw = args[i]; + } + dh.SetType(i, tw); + } + for(int i = args.Length - 1; i >= firstCastArg; i--) + { + if(!args[i].IsUnloadable && !args[i].IsGhost) + { + TypeWrapper tw = ma.GetStackTypeWrapper(instructionIndex, args.Length - 1 - i); + if(tw.IsUnloadable || (args[i].IsInterfaceOrInterfaceArray && NeedsInterfaceDownCast(tw, args[i]))) + { + ilGenerator.EmitAssertType(args[i].TypeAsTBD); + Profiler.Count("InterfaceDownCast"); + } + } + if(i != firstCastArg) + { + dh.Store(i); + } + } + if(instanceMethod && args[0].IsUnloadable && !declaringType.IsUnloadable) + { + if(declaringType.IsInterface) + { + ilGenerator.EmitAssertType(declaringType.TypeAsTBD); + } + else if(declaringType.IsNonPrimitiveValueType) + { + ilGenerator.Emit(OpCodes.Unbox, declaringType.TypeAsTBD); + } + else + { + ilGenerator.Emit(OpCodes.Castclass, declaringType.TypeAsSignatureType); + } + } + for(int i = firstCastArg; i < args.Length; i++) + { + if(i != firstCastArg) + { + dh.Load(i); + } + if(!args[i].IsUnloadable && args[i].IsGhost) + { + if(i == 0 && instanceMethod && !declaringType.IsInterface) + { + // we're calling a java.lang.Object method through a ghost interface reference, + // no ghost handling is needed + } + else if(VerifierTypeWrapper.IsThis(ma.GetRawStackTypeWrapper(instructionIndex, args.Length - 1 - i))) + { + // we're an instance method in a ghost interface, so the this pointer is a managed pointer to the + // wrapper value and if we're not calling another instance method on ourself, we need to load + // the wrapper value onto the stack + if(!instanceMethod || i != 0) + { + ilGenerator.Emit(OpCodes.Ldobj, args[i].TypeAsSignatureType); + } + } + else + { + CodeEmitterLocal ghost = ilGenerator.AllocTempLocal(Types.Object); + ilGenerator.Emit(OpCodes.Stloc, ghost); + CodeEmitterLocal local = ilGenerator.AllocTempLocal(args[i].TypeAsSignatureType); + ilGenerator.Emit(OpCodes.Ldloca, local); + ilGenerator.Emit(OpCodes.Ldloc, ghost); + ilGenerator.Emit(OpCodes.Stfld, args[i].GhostRefField); + ilGenerator.Emit(OpCodes.Ldloca, local); + ilGenerator.ReleaseTempLocal(local); + ilGenerator.ReleaseTempLocal(ghost); + // NOTE when the this argument is a value type, we need the address on the stack instead of the value + if(i != 0 || !instanceMethod) + { + ilGenerator.Emit(OpCodes.Ldobj, args[i].TypeAsSignatureType); + } + } + } + else + { + if(!args[i].IsUnloadable) + { + if(args[i].IsNonPrimitiveValueType) + { + if(i == 0 && instanceMethod) + { + // we only need to unbox if the method was actually declared on the value type + if(declaringType == args[i]) + { + ilGenerator.Emit(OpCodes.Unbox, args[i].TypeAsTBD); + } + } + else + { + args[i].EmitUnbox(ilGenerator); + } + } + else if(ma.GetRawStackTypeWrapper(instructionIndex, args.Length - 1 - i).IsUnloadable) + { + ilGenerator.Emit(OpCodes.Castclass, args[i].TypeAsSignatureType); + } + } + } + } + dh.Release(); + } + } + + private bool NeedsInterfaceDownCast(TypeWrapper tw, TypeWrapper arg) + { + if (tw == VerifierTypeWrapper.Null) + { + return false; + } + if (!tw.IsAccessibleFrom(clazz)) + { + tw = tw.GetPublicBaseTypeWrapper(); + } + return !tw.IsAssignableTo(arg); + } + + private void DynamicGetPutField(Instruction instr, int i) + { + ClassFile.RefKind kind; + switch (instr.NormalizedOpCode) + { + case NormalizedByteCode.__dynamic_getfield: + Profiler.Count("EmitDynamicGetfield"); + kind = ClassFile.RefKind.getField; + break; + case NormalizedByteCode.__dynamic_putfield: + Profiler.Count("EmitDynamicPutfield"); + kind = ClassFile.RefKind.putField; + break; + case NormalizedByteCode.__dynamic_getstatic: + Profiler.Count("EmitDynamicGetstatic"); + kind = ClassFile.RefKind.getStatic; + break; + case NormalizedByteCode.__dynamic_putstatic: + Profiler.Count("EmitDynamicPutstatic"); + kind = ClassFile.RefKind.putStatic; + break; + default: + throw new InvalidOperationException(); + } + ClassFile.ConstantPoolItemFieldref cpi = classFile.GetFieldref(instr.Arg1); + TypeWrapper fieldType = cpi.GetFieldType(); + if (kind == ClassFile.RefKind.putField || kind == ClassFile.RefKind.putStatic) + { + fieldType.EmitConvStackTypeToSignatureType(ilGenerator, ma.GetStackTypeWrapper(i, 0)); + if (strictfp) + { + // no need to convert + } + else if (fieldType == PrimitiveTypeWrapper.DOUBLE) + { + ilGenerator.Emit(OpCodes.Conv_R8); + } + } + context.GetValue(instr.Arg1 | ((byte)kind << 24)).Emit(this, cpi, kind); + if (kind == ClassFile.RefKind.getField || kind == ClassFile.RefKind.getStatic) + { + fieldType.EmitConvSignatureTypeToStackType(ilGenerator); + } + } + + private static void EmitReturnTypeConversion(CodeEmitter ilgen, TypeWrapper typeWrapper) + { + if(typeWrapper.IsUnloadable) + { + // nothing to do for unloadables + } + else if(typeWrapper == PrimitiveTypeWrapper.VOID) + { + ilgen.Emit(OpCodes.Pop); + } + else if(typeWrapper.IsPrimitive) + { + // NOTE we don't need to use TypeWrapper.EmitUnbox, because the return value cannot be null + ilgen.Emit(OpCodes.Unbox, typeWrapper.TypeAsTBD); + ilgen.Emit(OpCodes.Ldobj, typeWrapper.TypeAsTBD); + if(typeWrapper == PrimitiveTypeWrapper.BYTE) + { + ilgen.Emit(OpCodes.Conv_I1); + } + } + else + { + typeWrapper.EmitCheckcast(ilgen); + } + } + + internal sealed class MethodHandleMethodWrapper : MethodWrapper + { + private readonly Compiler compiler; + private readonly TypeWrapper wrapper; + private readonly ClassFile.ConstantPoolItemMI cpi; + + internal MethodHandleMethodWrapper(Compiler compiler, TypeWrapper wrapper, ClassFile.ConstantPoolItemMI cpi) + : base(CoreClasses.java.lang.invoke.MethodHandle.Wrapper, cpi.Name, cpi.Signature, null, cpi.GetRetType(), cpi.GetArgTypes(), Modifiers.Public, MemberFlags.None) + { + this.compiler = compiler; + this.wrapper = wrapper; + this.cpi = cpi; + } + + private static void ToBasic(TypeWrapper tw, CodeEmitter ilgen) + { + if (tw.IsNonPrimitiveValueType) + { + tw.EmitBox(ilgen); + } + else if (tw.IsGhost) + { + tw.EmitConvSignatureTypeToStackType(ilgen); + } + } + + private static void FromBasic(TypeWrapper tw, CodeEmitter ilgen) + { + if (tw.IsNonPrimitiveValueType) + { + tw.EmitUnbox(ilgen); + } + else if (tw.IsGhost) + { + tw.EmitConvStackTypeToSignatureType(ilgen, null); + } + else if (!tw.IsPrimitive && tw != CoreClasses.java.lang.Object.Wrapper) + { + tw.EmitCheckcast(ilgen); + } + } + + internal override void EmitCall(CodeEmitter ilgen) + { + Debug.Assert(cpi.Name == "linkToVirtual" || cpi.Name == "linkToStatic" || cpi.Name == "linkToSpecial" || cpi.Name == "linkToInterface"); + EmitLinkToCall(ilgen, cpi.GetArgTypes(), cpi.GetRetType()); + } + + internal static void EmitLinkToCall(CodeEmitter ilgen, TypeWrapper[] args, TypeWrapper retType) + { +#if !FIRST_PASS && !STATIC_COMPILER + CodeEmitterLocal[] temps = new CodeEmitterLocal[args.Length]; + for (int i = args.Length - 1; i > 0; i--) + { + temps[i] = ilgen.DeclareLocal(MethodHandleUtil.AsBasicType(args[i])); + ToBasic(args[i], ilgen); + ilgen.Emit(OpCodes.Stloc, temps[i]); + } + temps[0] = ilgen.DeclareLocal(args[0].TypeAsSignatureType); + ilgen.Emit(OpCodes.Stloc, temps[0]); + Array.Resize(ref args, args.Length - 1); + Type delegateType = MethodHandleUtil.CreateMemberWrapperDelegateType(args, retType); + ilgen.Emit(OpCodes.Ldloc, temps[args.Length]); + ilgen.Emit(OpCodes.Ldfld, typeof(java.lang.invoke.MemberName).GetField("vmtarget", BindingFlags.Instance | BindingFlags.NonPublic)); + ilgen.Emit(OpCodes.Castclass, delegateType); + for (int i = 0; i < args.Length; i++) + { + ilgen.Emit(OpCodes.Ldloc, temps[i]); + } + MethodHandleUtil.EmitCallDelegateInvokeMethod(ilgen, delegateType); + FromBasic(retType, ilgen); +#else + throw new InvalidOperationException(); +#endif + } + + private void EmitInvokeExact(CodeEmitter ilgen) + { + TypeWrapper[] args = cpi.GetArgTypes(); + CodeEmitterLocal[] temps = new CodeEmitterLocal[args.Length]; + for (int i = args.Length - 1; i >= 0; i--) + { + temps[i] = ilgen.DeclareLocal(args[i].TypeAsSignatureType); + ilgen.Emit(OpCodes.Stloc, temps[i]); + } + Type delegateType = MethodHandleUtil.CreateMethodHandleDelegateType(args, cpi.GetRetType()); + if (HasUnloadable(cpi.GetArgTypes(), cpi.GetRetType())) + { + // TODO consider sharing the cache for the same signatures + ilgen.Emit(OpCodes.Ldsflda, compiler.context.DefineDynamicMethodTypeCacheField()); + ilgen.Emit(OpCodes.Ldstr, cpi.Signature); + compiler.context.EmitCallerID(ilgen, compiler.m.IsLambdaFormCompiled); + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicLoadMethodType); + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.LoadMethodType.MakeGenericMethod(delegateType)); + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicEraseInvokeExact); + } + MethodInfo mi = ByteCodeHelperMethods.GetDelegateForInvokeExact.MakeGenericMethod(delegateType); + ilgen.Emit(OpCodes.Call, mi); + for (int i = 0; i < args.Length; i++) + { + ilgen.Emit(OpCodes.Ldloc, temps[i]); + } + MethodHandleUtil.EmitCallDelegateInvokeMethod(ilgen, delegateType); + } + + private void EmitInvokeMaxArity(CodeEmitter ilgen) + { + TypeWrapper[] args = cpi.GetArgTypes(); + CodeEmitterLocal[] temps = new CodeEmitterLocal[args.Length]; + for (int i = args.Length - 1; i >= 0; i--) + { + temps[i] = ilgen.DeclareLocal(args[i].TypeAsSignatureType); + ilgen.Emit(OpCodes.Stloc, temps[i]); + } + Type delegateType = MethodHandleUtil.CreateMethodHandleDelegateType(args, cpi.GetRetType()); + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.LoadMethodType.MakeGenericMethod(delegateType)); + CoreClasses.java.lang.invoke.MethodHandle.Wrapper.GetMethodWrapper("asType", "(Ljava.lang.invoke.MethodType;)Ljava.lang.invoke.MethodHandle;", false).EmitCallvirt(ilgen); + MethodInfo mi = ByteCodeHelperMethods.GetDelegateForInvokeExact.MakeGenericMethod(delegateType); + ilgen.Emit(OpCodes.Call, mi); + for (int i = 0; i < args.Length; i++) + { + ilgen.Emit(OpCodes.Ldloc, temps[i]); + } + MethodHandleUtil.EmitCallDelegateInvokeMethod(ilgen, delegateType); + } + + private void EmitInvoke(CodeEmitter ilgen) + { + if (cpi.GetArgTypes().Length >= 127 && MethodHandleUtil.SlotCount(cpi.GetArgTypes()) >= 254) + { + EmitInvokeMaxArity(ilgen); + return; + } + TypeWrapper[] args = ArrayUtil.Concat(CoreClasses.java.lang.invoke.MethodHandle.Wrapper, cpi.GetArgTypes()); + CodeEmitterLocal[] temps = new CodeEmitterLocal[args.Length]; + for (int i = args.Length - 1; i >= 0; i--) + { + temps[i] = ilgen.DeclareLocal(args[i].TypeAsSignatureType); + ilgen.Emit(OpCodes.Stloc, temps[i]); + } + Type delegateType = MethodHandleUtil.CreateMethodHandleDelegateType(args, cpi.GetRetType()); + MethodInfo mi = ByteCodeHelperMethods.GetDelegateForInvoke.MakeGenericMethod(delegateType); + Type typeofInvokeCache; +#if STATIC_COMPILER + typeofInvokeCache = StaticCompiler.GetRuntimeType("IKVM.Runtime.InvokeCache`1"); +#else + typeofInvokeCache = typeof(IKVM.Runtime.InvokeCache<>); +#endif + FieldBuilder fb = compiler.context.DefineMethodHandleInvokeCacheField(typeofInvokeCache.MakeGenericType(delegateType)); + ilgen.Emit(OpCodes.Ldloc, temps[0]); + if (HasUnloadable(cpi.GetArgTypes(), cpi.GetRetType())) + { + // TODO consider sharing the cache for the same signatures + ilgen.Emit(OpCodes.Ldsflda, compiler.context.DefineDynamicMethodTypeCacheField()); + ilgen.Emit(OpCodes.Ldstr, cpi.Signature); + compiler.context.EmitCallerID(ilgen, compiler.m.IsLambdaFormCompiled); + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicLoadMethodType); + } + else + { + ilgen.Emit(OpCodes.Ldnull); + } + ilgen.Emit(OpCodes.Ldsflda, fb); + ilgen.Emit(OpCodes.Call, mi); + for (int i = 0; i < args.Length; i++) + { + ilgen.Emit(OpCodes.Ldloc, temps[i]); + } + MethodHandleUtil.EmitCallDelegateInvokeMethod(ilgen, delegateType); + } + + private void EmitInvokeBasic(CodeEmitter ilgen) + { + TypeWrapper retType = cpi.GetRetType(); + EmitInvokeBasic(ilgen, cpi.GetArgTypes(), retType, true); + FromBasic(retType, ilgen); + } + + internal static void EmitInvokeBasic(CodeEmitter ilgen, TypeWrapper[] args, TypeWrapper retType, bool toBasic) + { + args = ArrayUtil.Concat(CoreClasses.java.lang.invoke.MethodHandle.Wrapper, args); + CodeEmitterLocal[] temps = new CodeEmitterLocal[args.Length]; + for (int i = args.Length - 1; i > 0; i--) + { + temps[i] = ilgen.DeclareLocal(MethodHandleUtil.AsBasicType(args[i])); + if (toBasic) + { + ToBasic(args[i], ilgen); + } + ilgen.Emit(OpCodes.Stloc, temps[i]); + } + temps[0] = ilgen.DeclareLocal(args[0].TypeAsSignatureType); + ilgen.Emit(OpCodes.Stloc, temps[0]); + Type delegateType = MethodHandleUtil.CreateMemberWrapperDelegateType(args, retType); + MethodInfo mi = ByteCodeHelperMethods.GetDelegateForInvokeBasic.MakeGenericMethod(delegateType); + ilgen.Emit(OpCodes.Ldloc, temps[0]); + ilgen.Emit(OpCodes.Call, mi); + for (int i = 0; i < args.Length; i++) + { + ilgen.Emit(OpCodes.Ldloc, temps[i]); + } + MethodHandleUtil.EmitCallDelegateInvokeMethod(ilgen, delegateType); + } + + internal override void EmitCallvirt(CodeEmitter ilgen) + { + switch (cpi.Name) + { + case "invokeExact": + EmitInvokeExact(ilgen); + break; + case "invoke": + EmitInvoke(ilgen); + break; + case "invokeBasic": + EmitInvokeBasic(ilgen); + break; + default: + throw new InvalidOperationException(); + } + } + + internal override void EmitNewobj(CodeEmitter ilgen) + { + throw new InvalidOperationException(); + } + } + + private sealed class DynamicFieldBinder + { + private MethodInfo method; + + internal void Emit(Compiler compiler, ClassFile.ConstantPoolItemFieldref cpi, ClassFile.RefKind kind) + { + if (method == null) + { + method = CreateMethod(compiler, cpi, kind); + } + compiler.ilGenerator.Emit(OpCodes.Call, method); + } + + private static MethodInfo CreateMethod(Compiler compiler, ClassFile.ConstantPoolItemFieldref cpi, ClassFile.RefKind kind) + { + TypeWrapper ret; + TypeWrapper[] args; + switch (kind) + { + case ClassFile.RefKind.getField: + ret = cpi.GetFieldType(); + args = new TypeWrapper[] { cpi.GetClassType() }; + break; + case ClassFile.RefKind.getStatic: + ret = cpi.GetFieldType(); + args = TypeWrapper.EmptyArray; + break; + case ClassFile.RefKind.putField: + ret = PrimitiveTypeWrapper.VOID; + args = new TypeWrapper[] { cpi.GetClassType(), cpi.GetFieldType() }; + break; + case ClassFile.RefKind.putStatic: + ret = PrimitiveTypeWrapper.VOID; + args = new TypeWrapper[] { cpi.GetFieldType() }; + break; + default: + throw new InvalidOperationException(); + } + return DynamicBinder.Emit(compiler, kind, cpi, ret, args, false); + } + } + + private sealed class DynamicBinder + { + private MethodWrapper mw; + + internal MethodWrapper Get(Compiler compiler, ClassFile.RefKind kind, ClassFile.ConstantPoolItemMI cpi, bool privileged) + { + return mw ?? (mw = new DynamicBinderMethodWrapper(cpi, Emit(compiler, kind, cpi, privileged), kind)); + } + + private static MethodInfo Emit(Compiler compiler, ClassFile.RefKind kind, ClassFile.ConstantPoolItemMI cpi, bool privileged) + { + TypeWrapper ret; + TypeWrapper[] args; + if (kind == ClassFile.RefKind.invokeStatic) + { + ret = cpi.GetRetType(); + args = cpi.GetArgTypes(); + } + else if (kind == ClassFile.RefKind.newInvokeSpecial) + { + ret = cpi.GetClassType(); + args = cpi.GetArgTypes(); + } + else + { + ret = cpi.GetRetType(); + args = ArrayUtil.Concat(cpi.GetClassType(), cpi.GetArgTypes()); + } + return Emit(compiler, kind, cpi, ret, args, privileged); + } + + internal static MethodInfo Emit(Compiler compiler, ClassFile.RefKind kind, ClassFile.ConstantPoolItemFMI cpi, TypeWrapper ret, TypeWrapper[] args, bool privileged) + { + bool ghostTarget = (kind == ClassFile.RefKind.invokeSpecial || kind == ClassFile.RefKind.invokeVirtual || kind == ClassFile.RefKind.invokeInterface) && args[0].IsGhost; + Type delegateType = MethodHandleUtil.CreateMethodHandleDelegateType(args, ret); + FieldBuilder fb = compiler.context.DefineMethodHandleInvokeCacheField(delegateType); + Type[] types = new Type[args.Length]; + for (int i = 0; i < types.Length; i++) + { + types[i] = args[i].TypeAsSignatureType; + } + if (ghostTarget) + { + types[0] = types[0].MakeByRefType(); + } + MethodBuilder mb = compiler.context.DefineMethodHandleDispatchStub(ret.TypeAsSignatureType, types); + CodeEmitter ilgen = CodeEmitter.Create(mb); + ilgen.Emit(OpCodes.Ldsfld, fb); + CodeEmitterLabel label = ilgen.DefineLabel(); + ilgen.EmitBrtrue(label); + ilgen.EmitLdc_I4((int)kind); + ilgen.Emit(OpCodes.Ldstr, cpi.Class); + ilgen.Emit(OpCodes.Ldstr, cpi.Name); + ilgen.Emit(OpCodes.Ldstr, cpi.Signature); + if (privileged) + { + compiler.context.EmitHostCallerID(ilgen); + } + else + { + compiler.context.EmitCallerID(ilgen, compiler.m.IsLambdaFormCompiled); + } + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicBinderMemberLookup.MakeGenericMethod(delegateType)); + ilgen.Emit(OpCodes.Volatile); + ilgen.Emit(OpCodes.Stsfld, fb); + ilgen.MarkLabel(label); + ilgen.Emit(OpCodes.Ldsfld, fb); + for (int i = 0; i < args.Length; i++) + { + ilgen.EmitLdarg(i); + if (i == 0 && ghostTarget) + { + ilgen.Emit(OpCodes.Ldobj, args[0].TypeAsSignatureType); + } + } + MethodHandleUtil.EmitCallDelegateInvokeMethod(ilgen, delegateType); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + return mb; + } + + private sealed class DynamicBinderMethodWrapper : MethodWrapper + { + private readonly MethodInfo method; + + internal DynamicBinderMethodWrapper(ClassFile.ConstantPoolItemMI cpi, MethodInfo method, ClassFile.RefKind kind) + : base(cpi.GetClassType(), cpi.Name, cpi.Signature, null, cpi.GetRetType(), cpi.GetArgTypes(), kind == ClassFile.RefKind.invokeStatic ? Modifiers.Public | Modifiers.Static : Modifiers.Public, MemberFlags.None) + { + this.method = method; + } + + internal override void EmitCall(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Call, method); + } + + internal override void EmitCallvirt(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Call, method); + } + + internal override void EmitNewobj(CodeEmitter ilgen) + { + ilgen.Emit(OpCodes.Call, method); + } + } + } + + private MethodWrapper GetMethodCallEmitter(NormalizedByteCode invoke, int constantPoolIndex) + { + ClassFile.ConstantPoolItemMI cpi = classFile.GetMethodref(constantPoolIndex); +#if STATIC_COMPILER + if(replacedMethodWrappers != null) + { + for(int i = 0; i < replacedMethodWrappers.Length; i++) + { + if(replacedMethodWrappers[i].DeclaringType == cpi.GetClassType() + && replacedMethodWrappers[i].Name == cpi.Name + && replacedMethodWrappers[i].Signature == cpi.Signature) + { + MethodWrapper rmw = replacedMethodWrappers[i]; + rmw.Link(); + return rmw; + } + } + } +#endif + MethodWrapper mw = null; + switch (invoke) + { + case NormalizedByteCode.__invokespecial: + mw = cpi.GetMethodForInvokespecial(); + break; + case NormalizedByteCode.__invokeinterface: + mw = cpi.GetMethod(); + break; + case NormalizedByteCode.__invokestatic: + case NormalizedByteCode.__invokevirtual: + mw = cpi.GetMethod(); + break; + case NormalizedByteCode.__dynamic_invokeinterface: + case NormalizedByteCode.__dynamic_invokestatic: + case NormalizedByteCode.__dynamic_invokevirtual: + case NormalizedByteCode.__dynamic_invokespecial: + case NormalizedByteCode.__privileged_invokestatic: + case NormalizedByteCode.__privileged_invokevirtual: + case NormalizedByteCode.__privileged_invokespecial: + return GetDynamicMethodWrapper(constantPoolIndex, invoke, cpi); + case NormalizedByteCode.__methodhandle_invoke: + case NormalizedByteCode.__methodhandle_link: + return new MethodHandleMethodWrapper(this, clazz, cpi); + default: + throw new InvalidOperationException(); + } + if(mw.IsDynamicOnly) + { + return GetDynamicMethodWrapper(constantPoolIndex, invoke, cpi); + } + return mw; + } + + private MethodWrapper GetDynamicMethodWrapper(int index, NormalizedByteCode invoke, ClassFile.ConstantPoolItemMI cpi) + { + ClassFile.RefKind kind; + switch (invoke) + { + case NormalizedByteCode.__invokeinterface: + case NormalizedByteCode.__dynamic_invokeinterface: + kind = ClassFile.RefKind.invokeInterface; + break; + case NormalizedByteCode.__invokestatic: + case NormalizedByteCode.__dynamic_invokestatic: + case NormalizedByteCode.__privileged_invokestatic: + kind = ClassFile.RefKind.invokeStatic; + break; + case NormalizedByteCode.__invokevirtual: + case NormalizedByteCode.__dynamic_invokevirtual: + case NormalizedByteCode.__privileged_invokevirtual: + kind = ClassFile.RefKind.invokeVirtual; + break; + case NormalizedByteCode.__invokespecial: + case NormalizedByteCode.__dynamic_invokespecial: + kind = ClassFile.RefKind.newInvokeSpecial; + break; + case NormalizedByteCode.__privileged_invokespecial: + // we don't support calling a base class constructor + kind = cpi.GetMethod().IsConstructor + ? ClassFile.RefKind.newInvokeSpecial + : ClassFile.RefKind.invokeSpecial; + break; + default: + throw new InvalidOperationException(); + } + bool privileged; + switch (invoke) + { + case NormalizedByteCode.__privileged_invokestatic: + case NormalizedByteCode.__privileged_invokevirtual: + case NormalizedByteCode.__privileged_invokespecial: + privileged = true; + break; + default: + privileged = false; + break; + } + return context.GetValue(index | ((byte)kind << 24)).Get(this, kind, cpi, privileged); + } + + private TypeWrapper ComputeThisType(TypeWrapper type, MethodWrapper method, NormalizedByteCode invoke) + { + if(type == VerifierTypeWrapper.UninitializedThis + || VerifierTypeWrapper.IsThis(type)) + { + return clazz; + } + else if(VerifierTypeWrapper.IsNew(type)) + { + return ((VerifierTypeWrapper)type).UnderlyingType; + } + else if(type == VerifierTypeWrapper.Null) + { + return method.DeclaringType; + } + else if(invoke == NormalizedByteCode.__invokevirtual && method.IsProtected && type.IsUnloadable) + { + return clazz; + } + else + { + return type; + } + } + + private LocalVar LoadLocal(int instructionIndex) + { + LocalVar v = localVars.GetLocalVar(instructionIndex); + if(v.isArg) + { + ClassFile.Method.Instruction instr = m.Instructions[instructionIndex]; + int i = m.ArgMap[instr.NormalizedArg1]; + ilGenerator.EmitLdarg(i); + if(v.type == PrimitiveTypeWrapper.DOUBLE) + { + ilGenerator.Emit(OpCodes.Conv_R8); + } + if(v.type == PrimitiveTypeWrapper.FLOAT) + { + ilGenerator.Emit(OpCodes.Conv_R4); + } + } + else if(v.type == VerifierTypeWrapper.Null) + { + ilGenerator.Emit(OpCodes.Ldnull); + } + else + { + if(v.builder == null) + { + v.builder = ilGenerator.DeclareLocal(GetLocalBuilderType(v.type)); + if(debug && v.name != null) + { + v.builder.SetLocalSymInfo(v.name); + } + } + ilGenerator.Emit(OpCodes.Ldloc, v.builder); + } + return v; + } + + private LocalVar StoreLocal(int instructionIndex) + { + LocalVar v = localVars.GetLocalVar(instructionIndex); + if(v == null) + { + // dead store + ilGenerator.Emit(OpCodes.Pop); + } + else if(v.isArg) + { + ClassFile.Method.Instruction instr = m.Instructions[instructionIndex]; + int i = m.ArgMap[instr.NormalizedArg1]; + ilGenerator.EmitStarg(i); + } + else if(v.type == VerifierTypeWrapper.Null) + { + ilGenerator.Emit(OpCodes.Pop); + } + else + { + if(v.builder == null) + { + v.builder = ilGenerator.DeclareLocal(GetLocalBuilderType(v.type)); + if(debug && v.name != null) + { + v.builder.SetLocalSymInfo(v.name); + } + } + ilGenerator.Emit(OpCodes.Stloc, v.builder); + } + return v; + } + + private Type GetLocalBuilderType(TypeWrapper tw) + { + if (tw.IsUnloadable) + { + return Types.Object; + } + else if (tw.IsAccessibleFrom(clazz)) + { + return tw.TypeAsLocalOrStackType; + } + else + { + return tw.GetPublicBaseTypeWrapper().TypeAsLocalOrStackType; + } + } + + private ExceptionTableEntry[] GetExceptionTableFor(InstructionFlags[] flags) + { + List list = new List(); + // return only reachable exception handlers (because the code gen depends on that) + for (int i = 0; i < exceptions.Length; i++) + { + // if the first instruction is unreachable, the entire block is unreachable, + // because you can't jump into a block (we've just split the blocks to ensure that) + if ((flags[exceptions[i].startIndex] & InstructionFlags.Reachable) != 0) + { + list.Add(exceptions[i]); + } + } + return list.ToArray(); + } + + private InstructionFlags[] ComputePartialReachability(int initialInstructionIndex, bool skipFaultBlocks) + { + return MethodAnalyzer.ComputePartialReachability(ma, m.Instructions, exceptions, initialInstructionIndex, skipFaultBlocks); + } +} diff --git a/runtime/fdlibm/e_hypot.cs b/runtime/fdlibm/e_hypot.cs new file mode 100644 index 0000000..c765b02 --- /dev/null +++ b/runtime/fdlibm/e_hypot.cs @@ -0,0 +1,126 @@ + + +/* + * Copyright (c) 1998, 2001, 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. + */ + +/* __ieee754_hypot(x,y) + * + * Method : + * If (assume round-to-nearest) z=x*x+y*y + * has error less than sqrt(2)/2 ulp, than + * sqrt(z) has error less than 1 ulp (exercise). + * + * So, compute sqrt(x*x+y*y) with some care as + * follows to get the error below 1 ulp: + * + * Assume x>y>0; + * (if possible, set rounding to round-to-nearest) + * 1. if x > 2y use + * x1*x1+(y*y+(x2*(x+x1))) for x*x+y*y + * where x1 = x with lower 32 bits cleared, x2 = x-x1; else + * 2. if x <= 2y use + * t1*y1+((x-y)*(x-y)+(t1*y2+t2*y)) + * where t1 = 2x with lower 32 bits cleared, t2 = 2x-t1, + * y1= y with lower 32 bits chopped, y2 = y-y1. + * + * NOTE: scaling may be necessary if some argument is too + * large or too tiny + * + * Special cases: + * hypot(x,y) is INF if x or y is +INF or -INF; else + * hypot(x,y) is NAN if x or y is NAN. + * + * Accuracy: + * hypot(x,y) returns sqrt(x^2+y^2) with error less + * than 1 ulps (units in the last place) + */ + +static partial class fdlibm +{ + internal static + double __ieee754_hypot(double x, double y) +{ + double a=x,b=y,t1,t2,y1,y2,w; + int j,k,ha,hb; + + ha = __HI(x)&0x7fffffff; /* high word of x */ + hb = __HI(y)&0x7fffffff; /* high word of y */ + if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;} + a = __HI(a, ha); /* a <- |a| */ + b = __HI(b, hb); /* b <- |b| */ + if((ha-hb)>0x3c00000) {return a+b;} /* x/y > 2**60 */ + k=0; + if(ha > 0x5f300000) { /* a>2**500 */ + if(ha >= 0x7ff00000) { /* Inf or NaN */ + w = a+b; /* for sNaN */ + if(((ha&0xfffff)|__LO(a))==0) w = a; + if(((hb^0x7ff00000)|__LO(b))==0) w = b; + return w; + } + /* scale a and b by 2**-600 */ + ha -= 0x25800000; hb -= 0x25800000; k += 600; + a = __HI(a, ha); + b = __HI(b, hb); + } + if(hb < 0x20b00000) { /* b < 2**-500 */ + if(hb <= 0x000fffff) { /* subnormal b or 0 */ + if((hb|(__LO(b)))==0) return a; + t1=0; + t1 = __HI(t1, 0x7fd00000); /* t1=2^1022 */ + b *= t1; + a *= t1; + k -= 1022; + } else { /* scale a and b by 2^600 */ + ha += 0x25800000; /* a *= 2^600 */ + hb += 0x25800000; /* b *= 2^600 */ + k -= 600; + a = __HI(a, ha); + b = __HI(b, hb); + } + } + /* medium size a and b */ + w = a-b; + if (w>b) { + t1 = 0; + t1 = __HI(t1, ha); + t2 = a-t1; + w = sqrt(t1*t1-(b*(-b)-t2*(a+t1))); + } else { + a = a+a; + y1 = 0; + y1 = __HI(y1, hb); + y2 = b - y1; + t1 = 0; + t1 = __HI(t1, ha+0x00100000); + t2 = a - t1; + w = sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b))); + } + if(k!=0) { + t1 = 1.0; + t1 = __HI(t1, __HI(t1) + (k<<20)); + return t1*w; + } else return w; +} +} diff --git a/runtime/fdlibm/e_pow.cs b/runtime/fdlibm/e_pow.cs new file mode 100644 index 0000000..485490a --- /dev/null +++ b/runtime/fdlibm/e_pow.cs @@ -0,0 +1,314 @@ + + +/* + * Copyright (c) 1998, 2004, 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. + */ + +/* __ieee754_pow(x,y) return x**y + * + * n + * Method: Let x = 2 * (1+f) + * 1. Compute and return log2(x) in two pieces: + * log2(x) = w1 + w2, + * where w1 has 53-24 = 29 bit trailing zeros. + * 2. Perform y*log2(x) = n+y' by simulating muti-precision + * arithmetic, where |y'|<=0.5. + * 3. Return x**y = 2**n*exp(y'*log2) + * + * Special cases: + * 1. (anything) ** 0 is 1 + * 2. (anything) ** 1 is itself + * 3. (anything) ** NAN is NAN + * 4. NAN ** (anything except 0) is NAN + * 5. +-(|x| > 1) ** +INF is +INF + * 6. +-(|x| > 1) ** -INF is +0 + * 7. +-(|x| < 1) ** +INF is +0 + * 8. +-(|x| < 1) ** -INF is +INF + * 9. +-1 ** +-INF is NAN + * 10. +0 ** (+anything except 0, NAN) is +0 + * 11. -0 ** (+anything except 0, NAN, odd integer) is +0 + * 12. +0 ** (-anything except 0, NAN) is +INF + * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF + * 14. -0 ** (odd integer) = -( +0 ** (odd integer) ) + * 15. +INF ** (+anything except 0,NAN) is +INF + * 16. +INF ** (-anything except 0,NAN) is +0 + * 17. -INF ** (anything) = -0 ** (-anything) + * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer) + * 19. (-anything except 0 and inf) ** (non-integer) is NAN + * + * Accuracy: + * pow(x,y) returns x**y nearly rounded. In particular + * pow(integer,integer) + * always returns the correct integer provided it is + * representable. + * + * Constants : + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ +using unsigned = System.UInt32; +#pragma warning disable 168 + +static partial class fdlibm +{ +static readonly double[] bp = {1.0, 1.5,}; +static readonly double[] dp_h = { 0.0, 5.84962487220764160156e-01,}; /* 0x3FE2B803, 0x40000000 */ +static readonly double[] dp_l = { 0.0, 1.35003920212974897128e-08,}; /* 0x3E4CFDEB, 0x43CFD006 */ + + internal static double __ieee754_pow(double x, double y) + { + const double zero = 0.0, +one = 1.0, +two = 2.0, +two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */ +huge = 1.0e300, +tiny = 1.0e-300, + /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ +L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */ +L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */ +L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */ +L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */ +L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */ +L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */ +P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ +P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ +P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ +P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ +P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */ +lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ +lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */ +lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */ +ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */ +cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */ +cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */ +cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/ +ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */ +ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/ +ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/ + + double z,ax,z_h,z_l,p_h,p_l; + double y1,t1,t2,r,s,t,u,v,w; + int i0,i1,i,j,k,yisint,n; + int hx,hy,ix,iy; + unsigned lx,ly; + + hx = __HI(x); lx = (uint)__LO(x); + hy = __HI(y); ly = (uint)__LO(y); + ix = hx&0x7fffffff; iy = hy&0x7fffffff; + + /* y==zero: x**0 = 1 */ + if((iy|(int)ly)==0) return one; + + /* +-NaN return x+y */ + if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) || + iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0))) + return x+y; + + /* determine if y is an odd int when x < 0 + * yisint = 0 ... y is not an integer + * yisint = 1 ... y is an odd int + * yisint = 2 ... y is an even int + */ + yisint = 0; + if(hx<0) { + if(iy>=0x43400000) yisint = 2; /* even integer y */ + else if(iy>=0x3ff00000) { + k = (iy>>20)-0x3ff; /* exponent */ + if(k>20) { + j = (int)(ly>>(52-k)); + if((j<<(52-k))==(int)ly) yisint = 2-(j&1); + } else if(ly==0) { + j = iy>>(20-k); + if((j<<(20-k))==iy) yisint = 2-(j&1); + } + } + } + + /* special value of y */ + if(ly==0) { + if (iy==0x7ff00000) { /* y is +-inf */ + if(((ix-0x3ff00000)|(int)lx)==0) + return y - y; /* inf**+-1 is NaN */ + else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */ + return (hy>=0)? y: zero; + else /* (|x|<1)**-,+inf = inf,0 */ + return (hy<0)?-y: zero; + } + if(iy==0x3ff00000) { /* y is +-1 */ + if(hy<0) return one/x; else return x; + } + if(hy==0x40000000) return x*x; /* y is 2 */ + if(hy==0x3fe00000) { /* y is 0.5 */ + if(hx>=0) /* x >= +0 */ + return sqrt(x); + } + } + + ax = fabs(x); + /* special value of x */ + if(lx==0) { + if(ix==0x7ff00000||ix==0||ix==0x3ff00000){ + z = ax; /*x is +-0,+-inf,+-1*/ + if(hy<0) z = one/z; /* z = (1/|x|) */ + if(hx<0) { + if(((ix-0x3ff00000)|yisint)==0) { + z = (z-z)/(z-z); /* (-1)**non-int is NaN */ + } else if(yisint==1) + z = -1.0*z; /* (x<0)**odd = -(|x|**odd) */ + } + return z; + } + } + + n = (hx>>31)+1; + + /* (x<0)**(non-int) is NaN */ + if((n|yisint)==0) return (x-x)/(x-x); + + s = one; /* s (sign of result -ve**odd) = -1 else = 1 */ + if((n|(yisint-1))==0) s = -one;/* (-ve)**(odd int) */ + + /* |y| is huge */ + if(iy>0x41e00000) { /* if |y| > 2**31 */ + if(iy>0x43f00000){ /* if |y| > 2**64, must o/uflow */ + if(ix<=0x3fefffff) return (hy<0)? huge*huge:tiny*tiny; + if(ix>=0x3ff00000) return (hy>0)? huge*huge:tiny*tiny; + } + /* over/underflow if x is not close to one */ + if(ix<0x3fefffff) return (hy<0)? s*huge*huge:s*tiny*tiny; + if(ix>0x3ff00000) return (hy>0)? s*huge*huge:s*tiny*tiny; + /* now |1-x| is tiny <= 2**-20, suffice to compute + log(x) by x-x^2/2+x^3/3-x^4/4 */ + t = ax-one; /* t has 20 trailing zeros */ + w = (t*t)*(0.5-t*(0.3333333333333333333333-t*0.25)); + u = ivln2_h*t; /* ivln2_h has 21 sig. bits */ + v = t*ivln2_l-w*ivln2; + t1 = u+v; + t1 = __LO(t1, 0); + t2 = v-(t1-u); + } else { + double ss,s2,s_h,s_l,t_h,t_l; + n = 0; + /* take care subnormal number */ + if(ix<0x00100000) + {ax *= two53; n -= 53; ix = __HI(ax); } + n += ((ix)>>20)-0x3ff; + j = ix&0x000fffff; + /* determine interval */ + ix = j|0x3ff00000; /* normalize ix */ + if(j<=0x3988E) k=0; /* |x|> 1) | 0x20000000) + 0x00080000 + (k << 18)); + t_l = ax - (t_h-bp[k]); + s_l = v*((u-s_h*t_h)-s_h*t_l); + /* compute log(ax) */ + s2 = ss*ss; + r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6))))); + r += s_l*(s_h+ss); + s2 = s_h*s_h; + t_h = 3.0+s2+r; + t_h = __LO(t_h, 0); + t_l = r-((t_h-3.0)-s2); + /* u+v = ss*(1+...) */ + u = s_h*t_h; + v = s_l*t_h+t_l*ss; + /* 2/(3log2)*(ss+...) */ + p_h = u+v; + p_h = __LO(p_h, 0); + p_l = v-(p_h-u); + z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */ + z_l = cp_l*p_h+p_l*cp+dp_l[k]; + /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */ + t = (double)n; + t1 = (((z_h+z_l)+dp_h[k])+t); + t1 = __LO(t1, 0); + t2 = z_l-(((t1-t)-dp_h[k])-z_h); + } + + /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ + y1 = y; + y1 = __LO(y1, 0); + p_l = (y-y1)*t1+y*t2; + p_h = y1*t1; + z = p_l+p_h; + j = __HI(z); + i = __LO(z); + if (j>=0x40900000) { /* z >= 1024 */ + if(((j-0x40900000)|i)!=0) /* if z > 1024 */ + return s*huge*huge; /* overflow */ + else { + if(p_l+ovt>z-p_h) return s*huge*huge; /* overflow */ + } + } else if((j&0x7fffffff)>=0x4090cc00 ) { /* z <= -1075 */ + if(((int)(j-0xc090cc00)|i)!=0) /* z < -1075 */ + return s*tiny*tiny; /* underflow */ + else { + if(p_l<=z-p_h) return s*tiny*tiny; /* underflow */ + } + } + /* + * compute 2**(p_h+p_l) + */ + i = j&0x7fffffff; + k = (i>>20)-0x3ff; + n = 0; + if(i>0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */ + n = j+(0x00100000>>(k+1)); + k = ((n&0x7fffffff)>>20)-0x3ff; /* new k for n */ + t = zero; + t = __HI(t, (n&~(0x000fffff>>k))); + n = ((n&0x000fffff)|0x00100000)>>(20-k); + if(j<0) n = -n; + p_h -= t; + } + t = p_l+p_h; + t = __LO(t, 0); + u = t*lg2_h; + v = (p_l-(t-p_h))*lg2+t*lg2_l; + z = u+v; + w = v-(z-u); + t = z*z; + t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); + r = (z*t1)/(t1-two)-(w+z*w); + z = one-(r-z); + j = __HI(z); + j += (n<<20); + if((j>>20)<=0) z = scalbn(z,n); /* subnormal output */ + else z = __HI(z, __HI(z) + (n<<20)); + return s*z; +} +} diff --git a/runtime/fdlibm/e_rem_pio2.cs b/runtime/fdlibm/e_rem_pio2.cs new file mode 100644 index 0000000..645decd --- /dev/null +++ b/runtime/fdlibm/e_rem_pio2.cs @@ -0,0 +1,173 @@ + + +/* + * Copyright (c) 1998, 2001, 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. + */ + +/* __ieee754_rem_pio2(x,y) + * + * return the remainder of x rem pi/2 in y_0_+y_1_ + * use __kernel_rem_pio2() + */ + +static partial class fdlibm +{ +/* + * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi + */ +static readonly int[] two_over_pi = { +0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, +0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, +0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, +0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, +0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, +0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, +0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, +0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, +0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, +0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, +0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B, +}; + +static readonly int[] npio2_hw = { +0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C, +0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C, +0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A, +0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C, +0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB, +0x404858EB, 0x404921FB, +}; + +/* + * invpio2: 53 bits of 2/pi + * pio2_1: first 33 bit of pi/2 + * pio2_1t: pi/2 - pio2_1 + * pio2_2: second 33 bit of pi/2 + * pio2_2t: pi/2 - (pio2_1+pio2_2) + * pio2_3: third 33 bit of pi/2 + * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) + */ + + static int __ieee754_rem_pio2(double x, ref double y_0_, ref double y_1_) + { + const double +zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ +half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ +two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ +invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ +pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ +pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ +pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */ +pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */ +pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ +pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ + + double z,w,t,r,fn; + int e0,i,j,nx,n,ix,hx; + + hx = __HI(x); /* high word of x */ + ix = hx&0x7fffffff; + if(ix<=0x3fe921fb) /* |x| ~<= pi/4 , no need for reduction */ + {y_0_ = x; y_1_ = 0; return 0;} + if(ix<0x4002d97c) { /* |x| < 3pi/4, special case with n=+-1 */ + if(hx>0) { + z = x - pio2_1; + if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */ + y_0_ = z - pio2_1t; + y_1_ = (z-y_0_)-pio2_1t; + } else { /* near pi/2, use 33+33+53 bit pi */ + z -= pio2_2; + y_0_ = z - pio2_2t; + y_1_ = (z-y_0_)-pio2_2t; + } + return 1; + } else { /* negative x */ + z = x + pio2_1; + if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */ + y_0_ = z + pio2_1t; + y_1_ = (z-y_0_)+pio2_1t; + } else { /* near pi/2, use 33+33+53 bit pi */ + z += pio2_2; + y_0_ = z + pio2_2t; + y_1_ = (z-y_0_)+pio2_2t; + } + return -1; + } + } + if(ix<=0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */ + t = fabs(x); + n = (int) (t*invpio2+half); + fn = (double)n; + r = t-fn*pio2_1; + w = fn*pio2_1t; /* 1st round good to 85 bit */ + if(n<32&&ix!=npio2_hw[n-1]) { + y_0_ = r-w; /* quick check no cancellation */ + } else { + j = ix>>20; + y_0_ = r-w; + i = j-(((__HI(y_0_))>>20)&0x7ff); + if(i>16) { /* 2nd iteration needed, good to 118 */ + t = r; + w = fn*pio2_2; + r = t-w; + w = fn*pio2_2t-((t-r)-w); + y_0_ = r-w; + i = j-(((__HI(y_0_))>>20)&0x7ff); + if(i>49) { /* 3rd iteration need, 151 bits acc */ + t = r; /* will cover all possible cases */ + w = fn*pio2_3; + r = t-w; + w = fn*pio2_3t-((t-r)-w); + y_0_ = r-w; + } + } + } + y_1_ = (r-y_0_)-w; + if(hx<0) {y_0_ = -y_0_; y_1_ = -y_1_; return -n;} + else return n; + } + /* + * all other (large) arguments + */ + if(ix>=0x7ff00000) { /* x is inf or NaN */ + y_0_=y_1_=x-x; return 0; + } + /* set z = scalbn(|x|,ilogb(x)-23) */ + z = x; + e0 = (ix>>20)-1046; /* e0 = ilogb(z)-23; */ + z = __HI(z, ix - (e0<<20)); + double[] tx = new double[3]; + for(i=0;i<2;i++) { + tx[i] = (double)((int)(z)); + z = (z-tx[i])*two24; + } + tx[2] = z; + nx = 3; + while(tx[nx-1]==zero) nx--; /* skip zero term */ + double y_2_ = 0.0; + n = __kernel_rem_pio2(tx,ref y_0_, ref y_1_, ref y_2_,e0,nx,2,two_over_pi); + if(hx<0) {y_0_ = -y_0_; y_1_ = -y_1_; return -n;} + return n; + } +} diff --git a/runtime/fdlibm/fdlibm_h.cs b/runtime/fdlibm/fdlibm_h.cs new file mode 100644 index 0000000..62e8ede --- /dev/null +++ b/runtime/fdlibm/fdlibm_h.cs @@ -0,0 +1,70 @@ + + +/* + * Copyright (c) 1998, 2002, 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. + */ + +using System; + +static partial class fdlibm +{ + static int __HI(double x) + { + return (int)(BitConverter.DoubleToInt64Bits(x) >> 32); + } + + static int __LO(double x) + { + return (int)BitConverter.DoubleToInt64Bits(x); + } + + static double __HI(double x, int i) + { + long l = BitConverter.DoubleToInt64Bits(x) & 0xFFFFFFFFL; + long h = (long)i << 32; + return BitConverter.Int64BitsToDouble(l | h); + } + + static double __LO(double x, int i) + { + long h = BitConverter.DoubleToInt64Bits(x) & ~0xFFFFFFFFL; + return BitConverter.Int64BitsToDouble(h | (uint)i); + } + + static double fabs(double d) + { + return Math.Abs(d); + } + + static double sqrt(double d) + { + return Math.Sqrt(d); + } + + static double copysign(double x, double y) + { + x = __HI(x, (__HI(x) & 0x7fffffff) | (__HI(y) & unchecked((int)0x80000000))); + return x; + } +} diff --git a/runtime/fdlibm/k_rem_pio2.cs b/runtime/fdlibm/k_rem_pio2.cs new file mode 100644 index 0000000..0696b2f --- /dev/null +++ b/runtime/fdlibm/k_rem_pio2.cs @@ -0,0 +1,319 @@ + + +/* + * Copyright (c) 1998, 2001, 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. + */ + +/* + * __kernel_rem_pio2(x,y,e0,nx,prec,ipio2) + * double x[],y[]; int e0,nx,prec; int ipio2[]; + * + * __kernel_rem_pio2 return the last three digits of N with + * y = x - N*pi/2 + * so that |y| < pi/2. + * + * The method is to compute the integer (mod 8) and fraction parts of + * (2/pi)*x without doing the full multiplication. In general we + * skip the part of the product that are known to be a huge integer ( + * more accurately, = 0 mod 8 ). Thus the number of operations are + * independent of the exponent of the input. + * + * (2/pi) is represented by an array of 24-bit integers in ipio2[]. + * + * Input parameters: + * x[] The input value (must be positive) is broken into nx + * pieces of 24-bit integers in double precision format. + * x[i] will be the i-th 24 bit of x. The scaled exponent + * of x[0] is given in input parameter e0 (i.e., x[0]*2^e0 + * match x's up to 24 bits. + * + * Example of breaking a double positive z into x[0]+x[1]+x[2]: + * e0 = ilogb(z)-23 + * z = scalbn(z,-e0) + * for i = 0,1,2 + * x[i] = floor(z) + * z = (z-x[i])*2**24 + * + * + * y[] ouput result in an array of double precision numbers. + * The dimension of y[] is: + * 24-bit precision 1 + * 53-bit precision 2 + * 64-bit precision 2 + * 113-bit precision 3 + * The actual value is the sum of them. Thus for 113-bit + * precison, one may have to do something like: + * + * long double t,w,r_head, r_tail; + * t = (long double)y[2] + (long double)y_1_; + * w = (long double)y_0_; + * r_head = t+w; + * r_tail = w - (r_head - t); + * + * e0 The exponent of x[0] + * + * nx dimension of x[] + * + * prec an integer indicating the precision: + * 0 24 bits (single) + * 1 53 bits (double) + * 2 64 bits (extended) + * 3 113 bits (quad) + * + * ipio2[] + * integer array, contains the (24*i)-th to (24*i+23)-th + * bit of 2/pi after binary point. The corresponding + * floating value is + * + * ipio2[i] * 2^(-24(i+1)). + * + * External function: + * double scalbn(), floor(); + * + * + * Here is the description of some local variables: + * + * jk jk+1 is the initial number of terms of ipio2[] needed + * in the computation. The recommended value is 2,3,4, + * 6 for single, double, extended,and quad. + * + * jz local integer variable indicating the number of + * terms of ipio2[] used. + * + * jx nx - 1 + * + * jv index for pointing to the suitable ipio2[] for the + * computation. In general, we want + * ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8 + * is an integer. Thus + * e0-3-24*jv >= 0 or (e0-3)/24 >= jv + * Hence jv = max(0,(e0-3)/24). + * + * jp jp+1 is the number of terms in PIo2[] needed, jp = jk. + * + * q[] double array with integral value, representing the + * 24-bits chunk of the product of x and 2/pi. + * + * q0 the corresponding exponent of q[0]. Note that the + * exponent for q[i] would be q0-24*i. + * + * PIo2[] double precision array, obtained by cutting pi/2 + * into 24 bits chunks. + * + * f[] ipio2[] in floating point + * + * iq[] integer array by breaking up q[] in 24-bits chunk. + * + * fq[] final product of x*(2/pi) in fq[0],..,fq[jk] + * + * ih integer. If >0 it indicates q[] is >= 0.5, hence + * it also indicates the *sign* of the result. + * + */ + + +/* + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +static partial class fdlibm +{ +static readonly int[] init_jk = {2,3,4,6}; /* initial value for jk */ + +static readonly double[] PIo2 = { + 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */ + 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */ + 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */ + 3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */ + 1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */ + 1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */ + 2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */ + 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */ +}; + + static int __kernel_rem_pio2(double[] x, ref double y_0_, ref double y_1_, ref double y_2_, int e0, int nx, int prec, int[] ipio2) + { + const double +zero = 0.0, +one = 1.0, +two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ +twon24 = 5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */ + + int jz,jx,jv,jp,jk,carry,n,i,j,k,m,q0,ih; + int[] iq = new int[20]; + double z,fw; + double[] f = new double[20]; + double[] fq = new double[20]; + double[] q = new double[20]; + + /* initialize jk*/ + jk = init_jk[prec]; + jp = jk; + + /* determine jx,jv,q0, note that 3>q0 */ + jx = nx-1; + jv = (e0-3)/24; if(jv<0) jv=0; + q0 = e0-24*(jv+1); + + /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ + j = jv-jx; m = jx+jk; + for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (double) ipio2[j]; + + /* compute q[0],q[1],...q[jk] */ + for (i=0;i<=jk;i++) { + for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw; + } + + jz = jk; +recompute: + /* distill q[] into iq[] reversingly */ + for(i=0,j=jz,z=q[jz];j>0;i++,j--) { + fw = (double)((int)(twon24* z)); + iq[i] = (int)(z-two24*fw); + z = q[j-1]+fw; + } + + /* compute n */ + z = scalbn(z,q0); /* actual value of z */ + z -= 8.0*floor(z*0.125); /* trim off integer >= 8 */ + n = (int) z; + z -= (double)n; + ih = 0; + if(q0>0) { /* need iq[jz-1] to determine n */ + i = (iq[jz-1]>>(24-q0)); n += i; + iq[jz-1] -= i<<(24-q0); + ih = iq[jz-1]>>(23-q0); + } + else if(q0==0) ih = iq[jz-1]>>23; + else if(z>=0.5) ih=2; + + if(ih>0) { /* q > 0.5 */ + n += 1; carry = 0; + for(i=0;i0) { /* rare case: chance is 1 in 12 */ + switch(q0) { + case 1: + iq[jz-1] &= 0x7fffff; break; + case 2: + iq[jz-1] &= 0x3fffff; break; + } + } + if(ih==2) { + z = one - z; + if(carry!=0) z -= scalbn(one,q0); + } + } + + /* check if recomputation is needed */ + if(z==zero) { + j = 0; + for (i=jz-1;i>=jk;i--) j |= iq[i]; + if(j==0) { /* need recomputation */ + for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */ + + for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */ + f[jx+i] = (double) ipio2[jv+i]; + for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; + q[i] = fw; + } + jz += k; + goto recompute; + } + } + + /* chop off zero terms */ + if(z==0.0) { + jz -= 1; q0 -= 24; + while(iq[jz]==0) { jz--; q0-=24;} + } else { /* break z into 24-bit if necessary */ + z = scalbn(z,-q0); + if(z>=two24) { + fw = (double)((int)(twon24*z)); + iq[jz] = (int)(z-two24*fw); + jz += 1; q0 += 24; + iq[jz] = (int) fw; + } else iq[jz] = (int) z ; + } + + /* convert integer "bit" chunk to floating-point value */ + fw = scalbn(one,q0); + for(i=jz;i>=0;i--) { + q[i] = fw*(double)iq[i]; fw*=twon24; + } + + /* compute PIo2[0,...,jp]*q[jz,...,0] */ + for(i=jz;i>=0;i--) { + for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k]; + fq[jz-i] = fw; + } + + /* compress fq[] into y[] */ + switch(prec) { + case 0: + fw = 0.0; + for (i=jz;i>=0;i--) fw += fq[i]; + y_0_ = (ih==0)? fw: -fw; + break; + case 1: + case 2: + fw = 0.0; + for (i=jz;i>=0;i--) fw += fq[i]; + y_0_ = (ih==0)? fw: -fw; + fw = fq[0]-fw; + for (i=1;i<=jz;i++) fw += fq[i]; + y_1_ = (ih==0)? fw: -fw; + break; + case 3: /* painful */ + for (i=jz;i>0;i--) { + fw = fq[i-1]+fq[i]; + fq[i] += fq[i-1]-fw; + fq[i-1] = fw; + } + for (i=jz;i>1;i--) { + fw = fq[i-1]+fq[i]; + fq[i] += fq[i-1]-fw; + fq[i-1] = fw; + } + for (fw=0.0,i=jz;i>=2;i--) fw += fq[i]; + if(ih==0) { + y_0_ = fq[0]; y_1_ = fq[1]; y_2_ = fw; + } else { + y_0_ = -fq[0]; y_1_ = -fq[1]; y_2_ = -fw; + } + break; + } + return n&7; + } +} diff --git a/runtime/fdlibm/k_tan.cs b/runtime/fdlibm/k_tan.cs new file mode 100644 index 0000000..c484a75 --- /dev/null +++ b/runtime/fdlibm/k_tan.cs @@ -0,0 +1,158 @@ + + +/* + * Copyright (c) 1998, 2004, 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. + */ + +/* __kernel_tan( x, y, k ) + * kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854 + * Input x is assumed to be bounded by ~pi/4 in magnitude. + * Input y is the tail of x. + * Input k indicates whether tan (if k=1) or + * -1/tan (if k= -1) is returned. + * + * Algorithm + * 1. Since tan(-x) = -tan(x), we need only to consider positive x. + * 2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0. + * 3. tan(x) is approximated by a odd polynomial of degree 27 on + * [0,0.67434] + * 3 27 + * tan(x) ~ x + T1*x + ... + T13*x + * where + * + * |tan(x) 2 4 26 | -59.2 + * |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2 + * | x | + * + * Note: tan(x+y) = tan(x) + tan'(x)*y + * ~ tan(x) + (1+x*x)*y + * Therefore, for better accuracy in computing tan(x+y), let + * 3 2 2 2 2 + * r = x *(T2+x *(T3+x *(...+x *(T12+x *T13)))) + * then + * 3 2 + * tan(x+y) = x + (T1*x + (x *(r+y)+y)) + * + * 4. For x in [0.67434,pi/4], let y = pi/4 - x, then + * tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y)) + * = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y))) + */ + +static partial class fdlibm +{ + static double __kernel_tan(double x, double y, int iy) + { + const double +one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ +pio4 = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */ +pio4lo= 3.06161699786838301793e-17, /* 0x3C81A626, 0x33145C07 */ +T_0_ = + 3.33333333333334091986e-01, /* 0x3FD55555, 0x55555563 */ +T_1_ = + 1.33333333333201242699e-01, /* 0x3FC11111, 0x1110FE7A */ +T_2_ = + 5.39682539762260521377e-02, /* 0x3FABA1BA, 0x1BB341FE */ +T_3_ = + 2.18694882948595424599e-02, /* 0x3F9664F4, 0x8406D637 */ +T_4_ = + 8.86323982359930005737e-03, /* 0x3F8226E3, 0xE96E8493 */ +T_5_ = + 3.59207910759131235356e-03, /* 0x3F6D6D22, 0xC9560328 */ +T_6_ = + 1.45620945432529025516e-03, /* 0x3F57DBC8, 0xFEE08315 */ +T_7_ = + 5.88041240820264096874e-04, /* 0x3F4344D8, 0xF2F26501 */ +T_8_ = + 2.46463134818469906812e-04, /* 0x3F3026F7, 0x1A8D1068 */ +T_9_ = + 7.81794442939557092300e-05, /* 0x3F147E88, 0xA03792A6 */ +T_10_ = + 7.14072491382608190305e-05, /* 0x3F12B80F, 0x32F0A7E9 */ +T_11_ = + -1.85586374855275456654e-05, /* 0xBEF375CB, 0xDB605373 */ +T_12_ = + 2.59073051863633712884e-05; /* 0x3EFB2A70, 0x74BF7AD4 */ + + double z,r,v,w,s; + int ix,hx; + hx = __HI(x); /* high word of x */ + ix = hx&0x7fffffff; /* high word of |x| */ + if(ix<0x3e300000) { /* x < 2**-28 */ + if((int)x==0) { /* generate inexact */ + if (((ix | __LO(x)) | (iy + 1)) == 0) + return one / fabs(x); + else { + if (iy == 1) + return x; + else { /* compute -1 / (x+y) carefully */ + double a, t; + + z = w = x + y; + z = __LO(z, 0); + v = y - (z - x); + t = a = -one / w; + t = __LO(t, 0); + s = one + t * z; + return t + a * (s + t * v); + } + } + } + } + if(ix>=0x3FE59428) { /* |x|>=0.6744 */ + if(hx<0) {x = -x; y = -y;} + z = pio4-x; + w = pio4lo-y; + x = z+w; y = 0.0; + } + z = x*x; + w = z*z; + /* Break x^5*(T[1]+x^2*T[2]+...) into + * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) + + * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12])) + */ + r = T_1_+w*(T_3_+w*(T_5_+w*(T_7_+w*(T_9_+w*T_11_)))); + v = z*(T_2_+w*(T_4_+w*(T_6_+w*(T_8_+w*(T_10_+w*T_12_))))); + s = z*x; + r = y + z*(s*(r+v)+y); + r += T_0_*s; + w = x+r; + if(ix>=0x3FE59428) { + v = (double)iy; + return (double)(1-((hx>>30)&2))*(v-2.0*(x-(w*w/(w+v)-r))); + } + if(iy==1) return w; + else { /* if allow error up to 2 ulp, + simply return -1.0/(x+r) here */ + /* compute -1.0/(x+r) accurately */ + double a,t; + z = w; + z = __LO(z, 0); + v = r-(z - x); /* z+v = r+x */ + t = a = -1.0/w; /* a = -1.0/w */ + t = __LO(t, 0); + s = 1.0+t*z; + return t+a*(s+t*v); + } +} +} diff --git a/runtime/fdlibm/s_cbrt.cs b/runtime/fdlibm/s_cbrt.cs new file mode 100644 index 0000000..455818f --- /dev/null +++ b/runtime/fdlibm/s_cbrt.cs @@ -0,0 +1,89 @@ + + +/* + * Copyright (c) 1998, 2001, 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. + */ + +static partial class fdlibm +{ + internal static double cbrt(double x) + { + +/* cbrt(x) + * Return cube root of x + */ +const int + B1 = 715094163, /* B1 = (682-0.03306235651)*2**20 */ + B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */ + +const double +C = 5.42857142857142815906e-01, /* 19/35 = 0x3FE15F15, 0xF15F15F1 */ +D = -7.05306122448979611050e-01, /* -864/1225 = 0xBFE691DE, 0x2532C834 */ +E = 1.41428571428571436819e+00, /* 99/70 = 0x3FF6A0EA, 0x0EA0EA0F */ +F = 1.60714285714285720630e+00, /* 45/28 = 0x3FF9B6DB, 0x6DB6DB6E */ +G = 3.57142857142857150787e-01; /* 5/14 = 0x3FD6DB6D, 0xB6DB6DB7 */ + + int hx; + double r,s,t=0.0,w; + int sign; + + + hx = __HI(x); /* high word of x */ + sign=hx&unchecked((int)0x80000000); /* sign= sign(x) */ + hx ^=sign; + if(hx>=0x7ff00000) return(x+x); /* cbrt(NaN,INF) is itself */ + if((hx|__LO(x))==0) + return(x); /* cbrt(0) is itself */ + + x = __HI(x, hx); /* x <- |x| */ + /* rough cbrt to 5 bits */ + if(hx<0x00100000) /* subnormal number */ + {t = __HI(t, 0x43500000); /* set t= 2**54 */ + t*=x; t = __HI(t, __HI(t)/3+B2); + } + else + t = __HI(t, hx/3+B1); + + + /* new cbrt to 23 bits, may be implemented in single precision */ + r=t*t/x; + s=C+r*t; + t*=G+F/(s+E+D/s); + + /* chopped to 20 bits and make it larger than cbrt(x) */ + t = __LO(t, 0); t = __HI(t, __HI(t) + 0x00000001); + + + /* one step newton iteration to 53 bits with error less than 0.667 ulps */ + s=t*t; /* t*t is exact */ + r=x/s; + w=t+t; + r=(r-t)/(w+r); /* r-s is exact */ + t=t+t*r; + + /* retore the sign bit */ + t = __HI(t, __HI(t) | sign); + return(t); +} +} diff --git a/runtime/fdlibm/s_expm1.cs b/runtime/fdlibm/s_expm1.cs new file mode 100644 index 0000000..e3a6ec4 --- /dev/null +++ b/runtime/fdlibm/s_expm1.cs @@ -0,0 +1,224 @@ + + +/* + * Copyright (c) 1998, 2001, 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. + */ + +/* expm1(x) + * Returns exp(x)-1, the exponential of x minus 1. + * + * Method + * 1. Argument reduction: + * Given x, find r and integer k such that + * + * x = k*ln2 + r, |r| <= 0.5*ln2 ~ 0.34658 + * + * Here a correction term c will be computed to compensate + * the error in r when rounded to a floating-point number. + * + * 2. Approximating expm1(r) by a special rational function on + * the interval [0,0.34658]: + * Since + * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ... + * we define R1(r*r) by + * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r) + * That is, + * R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r) + * = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r)) + * = 1 - r^2/60 + r^4/2520 - r^6/100800 + ... + * We use a special Reme algorithm on [0,0.347] to generate + * a polynomial of degree 5 in r*r to approximate R1. The + * maximum error of this polynomial approximation is bounded + * by 2**-61. In other words, + * R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5 + * where Q1 = -1.6666666666666567384E-2, + * Q2 = 3.9682539681370365873E-4, + * Q3 = -9.9206344733435987357E-6, + * Q4 = 2.5051361420808517002E-7, + * Q5 = -6.2843505682382617102E-9; + * (where z=r*r, and the values of Q1 to Q5 are listed below) + * with error bounded by + * | 5 | -61 + * | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2 + * | | + * + * expm1(r) = exp(r)-1 is then computed by the following + * specific way which minimize the accumulation rounding error: + * 2 3 + * r r [ 3 - (R1 + R1*r/2) ] + * expm1(r) = r + --- + --- * [--------------------] + * 2 2 [ 6 - r*(3 - R1*r/2) ] + * + * To compensate the error in the argument reduction, we use + * expm1(r+c) = expm1(r) + c + expm1(r)*c + * ~ expm1(r) + c + r*c + * Thus c+r*c will be added in as the correction terms for + * expm1(r+c). Now rearrange the term to avoid optimization + * screw up: + * ( 2 2 ) + * ({ ( r [ R1 - (3 - R1*r/2) ] ) } r ) + * expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- ) + * ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 ) + * ( ) + * + * = r - E + * 3. Scale back to obtain expm1(x): + * From step 1, we have + * expm1(x) = either 2^k*[expm1(r)+1] - 1 + * = or 2^k*[expm1(r) + (1-2^-k)] + * 4. Implementation notes: + * (A). To save one multiplication, we scale the coefficient Qi + * to Qi*2^i, and replace z by (x^2)/2. + * (B). To achieve maximum accuracy, we compute expm1(x) by + * (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf) + * (ii) if k=0, return r-E + * (iii) if k=-1, return 0.5*(r-E)-0.5 + * (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E) + * else return 1.0+2.0*(r-E); + * (v) if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1) + * (vi) if k <= 20, return 2^k((1-2^-k)-(E-r)), else + * (vii) return 2^k(1-((E+2^-k)-r)) + * + * Special cases: + * expm1(INF) is INF, expm1(NaN) is NaN; + * expm1(-INF) is -1, and + * for finite argument, only expm1(0)=0 is exact. + * + * Accuracy: + * according to an error analysis, the error is always less than + * 1 ulp (unit in the last place). + * + * Misc. info. + * For IEEE double + * if x > 7.09782712893383973096e+02 then expm1(x) overflow + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ +using unsigned = System.UInt32; + +static partial class fdlibm +{ + internal static double expm1(double x) + { + const double +one = 1.0, +huge = 1.0e+300, +tiny = 1.0e-300, +o_threshold = 7.09782712893383973096e+02,/* 0x40862E42, 0xFEFA39EF */ +ln2_hi = 6.93147180369123816490e-01,/* 0x3fe62e42, 0xfee00000 */ +ln2_lo = 1.90821492927058770002e-10,/* 0x3dea39ef, 0x35793c76 */ +invln2 = 1.44269504088896338700e+00,/* 0x3ff71547, 0x652b82fe */ + /* scaled coefficients related to expm1 */ +Q1 = -3.33333333333331316428e-02, /* BFA11111 111110F4 */ +Q2 = 1.58730158725481460165e-03, /* 3F5A01A0 19FE5585 */ +Q3 = -7.93650757867487942473e-05, /* BF14CE19 9EAADBB7 */ +Q4 = 4.00821782732936239552e-06, /* 3ED0CFCA 86E65239 */ +Q5 = -2.01099218183624371326e-07; /* BE8AFDB7 6E09C32D */ + + double y,hi,lo,c=0,t,e,hxs,hfx,r1; + int k,xsb; + unsigned hx; + + hx = (unsigned)__HI(x); /* high word of x */ + xsb = (int)(hx&0x80000000); /* sign bit of x */ + if(xsb==0) y=x; else y= -x; /* y = |x| */ + hx &= 0x7fffffff; /* high word of |x| */ + + /* filter out huge and non-finite argument */ + if(hx >= 0x4043687A) { /* if |x|>=56*ln2 */ + if(hx >= 0x40862E42) { /* if |x|>=709.78... */ + if(hx>=0x7ff00000) { + if(((int)(hx&0xfffff)|__LO(x))!=0) + return x+x; /* NaN */ + else return (xsb==0)? x:-1.0;/* exp(+-inf)={inf,-1} */ + } + if(x > o_threshold) return huge*huge; /* overflow */ + } + if(xsb!=0) { /* x < -56*ln2, return -1.0 with inexact */ + if(x+tiny<0.0) /* raise inexact */ + return tiny-one; /* return -1 */ + } + } + + /* argument reduction */ + if(hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ + if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */ + if(xsb==0) + {hi = x - ln2_hi; lo = ln2_lo; k = 1;} + else + {hi = x + ln2_hi; lo = -ln2_lo; k = -1;} + } else { + k = (int)(invln2*x+((xsb==0)?0.5:-0.5)); + t = k; + hi = x - t*ln2_hi; /* t*ln2_hi is exact here */ + lo = t*ln2_lo; + } + x = hi - lo; + c = (hi-x)-lo; + } + else if(hx < 0x3c900000) { /* when |x|<2**-54, return x */ + t = huge+x; /* return x with inexact flags when x!=0 */ + return x - (t-(huge+x)); + } + else k = 0; + + /* x is now in primary range */ + hfx = 0.5*x; + hxs = x*hfx; + r1 = one+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5)))); + t = 3.0-r1*hfx; + e = hxs*((r1-t)/(6.0 - x*t)); + if(k==0) return x - (x*e-hxs); /* c is 0 */ + else { + e = (x*(e-c)-c); + e -= hxs; + if(k== -1) return 0.5*(x-e)-0.5; + if(k==1) { + if(x < -0.25) return -2.0*(e-(x+0.5)); + else return one+2.0*(x-e); + } + if (k <= -2 || k>56) { /* suffice to return exp(x)-1 */ + y = one-(e-x); + y = __HI(y, __HI(y) + (k<<20)); /* add k to y's exponent */ + return y-one; + } + t = one; + if(k<20) { + t = __HI(t, 0x3ff00000 - (0x200000>>k)); /* t=1-2^-k */ + y = t-(e-x); + y = __HI(y, __HI(y) + (k<<20)); /* add k to y's exponent */ + } else { + t = __HI(t, ((0x3ff-k)<<20)); /* 2^-k */ + y = x-(e+t); + y += one; + y = __HI(y, __HI(y) + (k<<20)); /* add k to y's exponent */ + } + } + return y; +} +} diff --git a/runtime/fdlibm/s_floor.cs b/runtime/fdlibm/s_floor.cs new file mode 100644 index 0000000..0e6347c --- /dev/null +++ b/runtime/fdlibm/s_floor.cs @@ -0,0 +1,86 @@ + + +/* + * Copyright (c) 1998, 2001, 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. + */ + +/* + * floor(x) + * Return x rounded toward -inf to integral value + * Method: + * Bit twiddling. + * Exception: + * Inexact flag raised if x not equal to floor(x). + */ +using unsigned = System.UInt32; + +static partial class fdlibm +{ + internal static double floor(double x) + { + const double huge = 1.0e300; + + int i0,i1,j0; + unsigned i,j; + i0 = __HI(x); + i1 = __LO(x); + j0 = ((i0>>20)&0x7ff)-0x3ff; + if(j0<20) { + if(j0<0) { /* raise inexact if x != 0 */ + if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */ + if(i0>=0) {i0=i1=0;} + else if(((i0&0x7fffffff)|i1)!=0) + { i0=unchecked((int)0xbff00000);i1=0;} + } + } else { + i = (unsigned)((0x000fffff)>>j0); + if(((i0&(int)i)|i1)==0) return x; /* x is integral */ + if(huge+x>0.0) { /* raise inexact flag */ + if(i0<0) i0 += (0x00100000)>>j0; + i0 &= (~(int)i); i1=0; + } + } + } else if (j0>51) { + if(j0==0x400) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } else { + i = ((unsigned)(0xffffffff))>>(j0-20); + if((i1&i)==0) return x; /* x is integral */ + if(huge+x>0.0) { /* raise inexact flag */ + if(i0<0) { + if(j0==20) i0+=1; + else { + j = (unsigned)(i1+(1<<(52-j0))); + if(j 2**53, one can simply return log(x)) + * + * 2. Approximation of log1p(f). + * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) + * = 2s + 2/3 s**3 + 2/5 s**5 + ....., + * = 2s + s*R + * We use a special Reme algorithm on [0,0.1716] to generate + * a polynomial of degree 14 to approximate R The maximum error + * of this polynomial approximation is bounded by 2**-58.45. In + * other words, + * 2 4 6 8 10 12 14 + * R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s +Lp6*s +Lp7*s + * (the values of Lp1 to Lp7 are listed in the program) + * and + * | 2 14 | -58.45 + * | Lp1*s +...+Lp7*s - R(z) | <= 2 + * | | + * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. + * In order to guarantee error in log below 1ulp, we compute log + * by + * log1p(f) = f - (hfsq - s*(hfsq+R)). + * + * 3. Finally, log1p(x) = k*ln2 + log1p(f). + * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) + * Here ln2 is split into two floating point number: + * ln2_hi + ln2_lo, + * where n*ln2_hi is always exact for |n| < 2000. + * + * Special cases: + * log1p(x) is NaN with signal if x < -1 (including -INF) ; + * log1p(+INF) is +INF; log1p(-1) is -INF with signal; + * log1p(NaN) is that NaN with no signal. + * + * Accuracy: + * according to an error analysis, the error is always less than + * 1 ulp (unit in the last place). + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + * + * Note: Assuming log() return accurate answer, the following + * algorithm can be used to compute log1p(x) to within a few ULP: + * + * u = 1+x; + * if(u==1.0) return x ; else + * return log(u)*(x/(u-1.0)); + * + * See HP-15C Advanced Functions Handbook, p.193. + */ + +static partial class fdlibm +{ + internal static double log1p(double x) + { + const double +ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ +ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ +two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */ +Lp1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ +Lp2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ +Lp3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ +Lp4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ +Lp5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ +Lp6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ +Lp7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ + +const double zero = 0.0; + + double hfsq,f=0,c=0,s,z,R,u; + int k,hx,hu=0,ax; + + hx = __HI(x); /* high word of x */ + ax = hx&0x7fffffff; + + k = 1; + if (hx < 0x3FDA827A) { /* x < 0.41422 */ + if(ax>=0x3ff00000) { /* x <= -1.0 */ + /* + * Added redundant test against hx to work around VC++ + * code generation problem. + */ + if(x==-1.0 && (hx==unchecked((int)0xbff00000))) /* log1p(-1)=-inf */ + return -two54/zero; + else + return (x-x)/(x-x); /* log1p(x<-1)=NaN */ + } + if(ax<0x3e200000) { /* |x| < 2**-29 */ + if(two54+x>zero /* raise inexact */ + &&ax<0x3c900000) /* |x| < 2**-54 */ + return x; + else + return x - x*x*0.5; + } + if(hx>0||hx<=(unchecked((int)0xbfd2bec3))) { + k=0;f=x;hu=1;} /* -0.2929= 0x7ff00000) return x+x; + if(k!=0) { + if(hx<0x43400000) { + u = 1.0+x; + hu = __HI(u); /* high word of u */ + k = (hu>>20)-1023; + c = (k>0)? 1.0-(u-x):x-(u-1.0);/* correction term */ + c /= u; + } else { + u = x; + hu = __HI(u); /* high word of u */ + k = (hu>>20)-1023; + c = 0; + } + hu &= 0x000fffff; + if(hu<0x6a09e) { + u = __HI(u, hu|0x3ff00000); /* normalize u */ + } else { + k += 1; + u = __HI(u, hu|0x3fe00000); /* normalize u/2 */ + hu = (0x00100000-hu)>>2; + } + f = u-1.0; + } + hfsq=0.5*f*f; + if(hu==0) { /* |f| < 2**-20 */ + if(f==zero) { if(k==0) return zero; + else {c += k*ln2_lo; return k*ln2_hi+c;}} + R = hfsq*(1.0-0.66666666666666666*f); + if(k==0) return f-R; else + return k*ln2_hi-((R-(k*ln2_lo+c))-f); + } + s = f/(2.0+f); + z = s*s; + R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7)))))); + if(k==0) return f-(hfsq-s*(hfsq+R)); else + return k*ln2_hi-((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f); +} +} diff --git a/runtime/fdlibm/s_scalbn.cs b/runtime/fdlibm/s_scalbn.cs new file mode 100644 index 0000000..df751ed --- /dev/null +++ b/runtime/fdlibm/s_scalbn.cs @@ -0,0 +1,70 @@ + + +/* + * Copyright (c) 1998, 2001, 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. + */ + +/* + * scalbn (double x, int n) + * scalbn(x,n) returns x* 2**n computed by exponent + * manipulation rather than by actually performing an + * exponentiation or a multiplication. + */ + +static partial class fdlibm +{ + static double scalbn(double x, int n) + { + const double +two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ +twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ +huge = 1.0e+300, +tiny = 1.0e-300; + + int k,hx,lx; + hx = __HI(x); + lx = __LO(x); + k = (hx&0x7ff00000)>>20; /* extract exponent */ + if (k==0) { /* 0 or subnormal x */ + if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */ + x *= two54; + hx = __HI(x); + k = ((hx&0x7ff00000)>>20) - 54; + if (n< -50000) return tiny*x; /*underflow*/ + } + if (k==0x7ff) return x+x; /* NaN or Inf */ + k = k+n; + if (k > 0x7fe) return huge*copysign(huge,x); /* overflow */ + if (k > 0) /* normal result */ + {x = __HI(x, (hx&unchecked((int)0x800fffff))|(k<<20)); return x;} + if (k <= -54) { + if (n > 50000) /* in case integer overflow in n+k */ + return huge*copysign(huge,x); /*overflow*/ + else return tiny*copysign(tiny,x); /*underflow*/ + } + k += 54; /* subnormal result */ + x = __HI(x, (hx&unchecked((int)0x800fffff))|(k<<20)); + return x*twom54; +} +} diff --git a/runtime/fdlibm/s_tan.cs b/runtime/fdlibm/s_tan.cs new file mode 100644 index 0000000..4172ca2 --- /dev/null +++ b/runtime/fdlibm/s_tan.cs @@ -0,0 +1,84 @@ + + +/* + * Copyright (c) 1998, 2001, 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. + */ + +/* tan(x) + * Return tangent function of x. + * + * kernel function: + * __kernel_tan ... tangent function on [-pi/4,pi/4] + * __ieee754_rem_pio2 ... argument reduction routine + * + * Method. + * Let S,C and T denote the sin, cos and tan respectively on + * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 + * in [-pi/4 , +pi/4], and let n = k mod 4. + * We have + * + * n sin(x) cos(x) tan(x) + * ---------------------------------------------------------- + * 0 S C T + * 1 C -S -1/T + * 2 -S -C T + * 3 -C S -1/T + * ---------------------------------------------------------- + * + * Special cases: + * Let trig be any of sin, cos, or tan. + * trig(+-INF) is NaN, with signals; + * trig(NaN) is that NaN; + * + * Accuracy: + * TRIG(x) returns trig(x) nearly rounded + */ + +static partial class fdlibm +{ + internal static + double tan(double x) +{ + double z=0.0; + int n, ix; + + /* High word of x. */ + ix = __HI(x); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffff; + if(ix <= 0x3fe921fb) return __kernel_tan(x,z,1); + + /* tan(Inf or NaN) is NaN */ + else if (ix>=0x7ff00000) return x-x; /* NaN */ + + /* argument reduction needed */ + else { + double y_0_ = 0.0, y_1_ = 0.0; + n = __ieee754_rem_pio2(x, ref y_0_, ref y_1_); + return __kernel_tan(y_0_,y_1_,1-((n&1)<<1)); /* 1 -- n even + -1 -- n odd */ + } + } +} diff --git a/runtime/intrinsics.cs b/runtime/intrinsics.cs new file mode 100644 index 0000000..c8ed370 --- /dev/null +++ b/runtime/intrinsics.cs @@ -0,0 +1,1278 @@ +/* + Copyright (C) 2008-2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +using System; +using System.Collections.Generic; +#if STATIC_COMPILER +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using Type = IKVM.Reflection.Type; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif +using System.Diagnostics; +using Instruction = IKVM.Internal.ClassFile.Method.Instruction; +using InstructionFlags = IKVM.Internal.ClassFile.Method.InstructionFlags; + +namespace IKVM.Internal +{ + sealed class EmitIntrinsicContext + { + internal readonly MethodWrapper Method; + internal readonly DynamicTypeWrapper.FinishContext Context; + internal readonly CodeEmitter Emitter; + private readonly CodeInfo ma; + internal readonly int OpcodeIndex; + internal readonly MethodWrapper Caller; + internal readonly ClassFile ClassFile; + internal readonly Instruction[] Code; + internal readonly InstructionFlags[] Flags; + internal bool NonLeaf = true; + + internal EmitIntrinsicContext(MethodWrapper method, DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, CodeInfo ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) + { + this.Method = method; + this.Context = context; + this.Emitter = ilgen; + this.ma = ma; + this.OpcodeIndex = opcodeIndex; + this.Caller = caller; + this.ClassFile = classFile; + this.Code = code; + this.Flags = flags; + } + + internal bool MatchRange(int offset, int length) + { + if (OpcodeIndex + offset < 0) + { + return false; + } + if (OpcodeIndex + offset + length > Code.Length) + { + return false; + } + // we check for branches *into* the range, the start of the range may be a branch target + for (int i = OpcodeIndex + offset + 1, end = OpcodeIndex + offset + length; i < end; i++) + { + if ((Flags[i] & InstructionFlags.BranchTarget) != 0) + { + return false; + } + } + return true; + } + + internal bool Match(int offset, NormalizedByteCode opcode) + { + return Code[OpcodeIndex + offset].NormalizedOpCode == opcode; + } + + internal bool Match(int offset, NormalizedByteCode opcode, int arg) + { + return Code[OpcodeIndex + offset].NormalizedOpCode == opcode && Code[OpcodeIndex + offset].Arg1 == arg; + } + + internal TypeWrapper GetStackTypeWrapper(int offset, int pos) + { + return ma.GetStackTypeWrapper(OpcodeIndex + offset, pos); + } + + internal ClassFile.ConstantPoolItemMI GetMethodref(int offset) + { + return ClassFile.GetMethodref(Code[OpcodeIndex + offset].Arg1); + } + + internal ClassFile.ConstantPoolItemFieldref GetFieldref(int offset) + { + return ClassFile.GetFieldref(Code[OpcodeIndex + offset].Arg1); + } + + internal TypeWrapper GetClassLiteral(int offset) + { + return ClassFile.GetConstantPoolClassType(Code[OpcodeIndex + offset].Arg1); + } + + internal string GetStringLiteral(int offset) + { + return ClassFile.GetConstantPoolConstantString(Code[OpcodeIndex + offset].Arg1); + } + + internal ClassFile.ConstantType GetConstantType(int offset) + { + return ClassFile.GetConstantPoolConstantType(Code[OpcodeIndex + offset].Arg1); + } + + internal void PatchOpCode(int offset, NormalizedByteCode opc) + { + Code[OpcodeIndex + offset].PatchOpCode(opc); + } + } + + static class Intrinsics + { + private delegate bool Emitter(EmitIntrinsicContext eic); + private struct IntrinsicKey : IEquatable + { + private readonly string className; + private readonly string methodName; + private readonly string methodSignature; + + internal IntrinsicKey(string className, string methodName, string methodSignature) + { + this.className = string.Intern(className); + this.methodName = string.Intern(methodName); + this.methodSignature = string.Intern(methodSignature); + } + + internal IntrinsicKey(MethodWrapper mw) + { + this.className = mw.DeclaringType.Name; + this.methodName = mw.Name; + this.methodSignature = mw.Signature; + } + + public override bool Equals(object obj) + { + return Equals((IntrinsicKey)obj); + } + + public bool Equals(IntrinsicKey other) + { + return ReferenceEquals(className, other.className) && ReferenceEquals(methodName, other.methodName) && ReferenceEquals(methodSignature, other.methodSignature); + } + + public override int GetHashCode() + { + return methodName.GetHashCode(); + } + } + private static readonly Dictionary intrinsics = Register(); +#if STATIC_COMPILER + private static readonly Type typeofFloatConverter = StaticCompiler.GetRuntimeType("IKVM.Runtime.FloatConverter"); + private static readonly Type typeofDoubleConverter = StaticCompiler.GetRuntimeType("IKVM.Runtime.DoubleConverter"); +#else + private static readonly Type typeofFloatConverter = typeof(IKVM.Runtime.FloatConverter); + private static readonly Type typeofDoubleConverter = typeof(IKVM.Runtime.DoubleConverter); +#endif + + private static Dictionary Register() + { + Dictionary intrinsics = new Dictionary(); + intrinsics.Add(new IntrinsicKey("java.lang.Object", "getClass", "()Ljava.lang.Class;"), Object_getClass); + intrinsics.Add(new IntrinsicKey("java.lang.Class", "desiredAssertionStatus", "()Z"), Class_desiredAssertionStatus); + intrinsics.Add(new IntrinsicKey("java.lang.Float", "floatToRawIntBits", "(F)I"), Float_floatToRawIntBits); + intrinsics.Add(new IntrinsicKey("java.lang.Float", "intBitsToFloat", "(I)F"), Float_intBitsToFloat); + intrinsics.Add(new IntrinsicKey("java.lang.Double", "doubleToRawLongBits", "(D)J"), Double_doubleToRawLongBits); + intrinsics.Add(new IntrinsicKey("java.lang.Double", "longBitsToDouble", "(J)D"), Double_longBitsToDouble); + intrinsics.Add(new IntrinsicKey("java.lang.System", "arraycopy", "(Ljava.lang.Object;ILjava.lang.Object;II)V"), System_arraycopy); + intrinsics.Add(new IntrinsicKey("java.util.concurrent.atomic.AtomicReferenceFieldUpdater", "newUpdater", "(Ljava.lang.Class;Ljava.lang.Class;Ljava.lang.String;)Ljava.util.concurrent.atomic.AtomicReferenceFieldUpdater;"), AtomicReferenceFieldUpdater_newUpdater); +#if STATIC_COMPILER + // String_toCharArray relies on globals, which aren't usable in dynamic mode + intrinsics.Add(new IntrinsicKey("java.lang.String", "toCharArray", "()[C"), String_toCharArray); + intrinsics.Add(new IntrinsicKey("sun.reflect.Reflection", "getCallerClass", "()Ljava.lang.Class;"), Reflection_getCallerClass); + intrinsics.Add(new IntrinsicKey("ikvm.internal.CallerID", "getCallerID", "()Likvm.internal.CallerID;"), CallerID_getCallerID); +#endif + intrinsics.Add(new IntrinsicKey("ikvm.runtime.Util", "getInstanceTypeFromClass", "(Ljava.lang.Class;)Lcli.System.Type;"), Util_getInstanceTypeFromClass); +#if STATIC_COMPILER + // this only applies to the core class library, so makes no sense in dynamic mode + intrinsics.Add(new IntrinsicKey("java.lang.Class", "getPrimitiveClass", "(Ljava.lang.String;)Ljava.lang.Class;"), Class_getPrimitiveClass); + intrinsics.Add(new IntrinsicKey("java.lang.Class", "getDeclaredField", "(Ljava.lang.String;)Ljava.lang.reflect.Field;"), Class_getDeclaredField); +#endif + intrinsics.Add(new IntrinsicKey("java.lang.ThreadLocal", "", "()V"), ThreadLocal_new); + intrinsics.Add(new IntrinsicKey("sun.misc.Unsafe", "ensureClassInitialized", "(Ljava.lang.Class;)V"), Unsafe_ensureClassInitialized); + // note that the following intrinsics don't pay off on CLR v2, but they do on CLR v4 + intrinsics.Add(new IntrinsicKey("sun.misc.Unsafe", "putObject", "(Ljava.lang.Object;JLjava.lang.Object;)V"), Unsafe_putObject); + intrinsics.Add(new IntrinsicKey("sun.misc.Unsafe", "putOrderedObject", "(Ljava.lang.Object;JLjava.lang.Object;)V"), Unsafe_putOrderedObject); + intrinsics.Add(new IntrinsicKey("sun.misc.Unsafe", "putObjectVolatile", "(Ljava.lang.Object;JLjava.lang.Object;)V"), Unsafe_putObjectVolatile); + intrinsics.Add(new IntrinsicKey("sun.misc.Unsafe", "getObjectVolatile", "(Ljava.lang.Object;J)Ljava.lang.Object;"), Unsafe_getObjectVolatile); + intrinsics.Add(new IntrinsicKey("sun.misc.Unsafe", "getObject", "(Ljava.lang.Object;J)Ljava.lang.Object;"), Unsafe_getObjectVolatile); + intrinsics.Add(new IntrinsicKey("sun.misc.Unsafe", "compareAndSwapObject", "(Ljava.lang.Object;JLjava.lang.Object;Ljava.lang.Object;)Z"), Unsafe_compareAndSwapObject); + intrinsics.Add(new IntrinsicKey("sun.misc.Unsafe", "getAndSetObject", "(Ljava.lang.Object;JLjava.lang.Object;)Ljava.lang.Object;"), Unsafe_getAndSetObject); + intrinsics.Add(new IntrinsicKey("sun.misc.Unsafe", "compareAndSwapInt", "(Ljava.lang.Object;JII)Z"), Unsafe_compareAndSwapInt); + intrinsics.Add(new IntrinsicKey("sun.misc.Unsafe", "getAndAddInt", "(Ljava.lang.Object;JI)I"), Unsafe_getAndAddInt); + intrinsics.Add(new IntrinsicKey("sun.misc.Unsafe", "compareAndSwapLong", "(Ljava.lang.Object;JJJ)Z"), Unsafe_compareAndSwapLong); + return intrinsics; + } + + internal static bool IsIntrinsic(MethodWrapper mw) + { + return intrinsics.ContainsKey(new IntrinsicKey(mw)) && mw.DeclaringType.GetClassLoader() == CoreClasses.java.lang.Object.Wrapper.GetClassLoader(); + } + + internal static bool Emit(EmitIntrinsicContext context) + { + // note that intrinsics can always refuse to emit code and the code generator will fall back to a normal method call + return intrinsics[new IntrinsicKey(context.Method)](context); + } + + private static bool Object_getClass(EmitIntrinsicContext eic) + { + // this is the null-check idiom that javac uses (both in its own source and in the code it generates) + if (eic.MatchRange(0, 2) + && eic.Match(1, NormalizedByteCode.__pop)) + { + eic.Emitter.Emit(OpCodes.Dup); + eic.Emitter.EmitNullCheck(); + return true; + } + // this optimizes obj1.getClass() ==/!= obj2.getClass() + else if (eic.MatchRange(0, 4) + && eic.Match(1, NormalizedByteCode.__aload) + && eic.Match(2, NormalizedByteCode.__invokevirtual) + && (eic.Match(3, NormalizedByteCode.__if_acmpeq) || eic.Match(3, NormalizedByteCode.__if_acmpne)) + && (IsSafeForGetClassOptimization(eic.GetStackTypeWrapper(0, 0)) || IsSafeForGetClassOptimization(eic.GetStackTypeWrapper(2, 0)))) + { + ClassFile.ConstantPoolItemMI cpi = eic.GetMethodref(2); + if (cpi.Class == "java.lang.Object" && cpi.Name == "getClass" && cpi.Signature == "()Ljava.lang.Class;") + { + // we can't patch the current opcode, so we have to emit the first call to GetTypeHandle here + eic.Emitter.Emit(OpCodes.Callvirt, Compiler.getTypeMethod); + eic.PatchOpCode(2, NormalizedByteCode.__intrinsic_gettype); + return true; + } + } + // this optimizes obj.getClass() == Xxx.class + else if (eic.MatchRange(0, 3) + && eic.Match(1, NormalizedByteCode.__ldc) && eic.GetConstantType(1) == ClassFile.ConstantType.Class + && (eic.Match(2, NormalizedByteCode.__if_acmpeq) || eic.Match(2, NormalizedByteCode.__if_acmpne))) + { + TypeWrapper tw = eic.GetClassLiteral(1); + if (tw.IsGhost || tw.IsGhostArray || tw.IsUnloadable || (tw.IsRemapped && tw.IsFinal && tw is DotNetTypeWrapper)) + { + return false; + } + eic.Emitter.Emit(OpCodes.Callvirt, Compiler.getTypeMethod); + eic.Emitter.Emit(OpCodes.Ldtoken, (tw.IsRemapped && tw.IsFinal) ? tw.TypeAsTBD : tw.TypeAsBaseType); + eic.Emitter.Emit(OpCodes.Call, Compiler.getTypeFromHandleMethod); + eic.PatchOpCode(1, NormalizedByteCode.__nop); + return true; + } + return false; + } + + private static bool Class_desiredAssertionStatus(EmitIntrinsicContext eic) + { + if (eic.MatchRange(-1, 2) + && eic.Match(-1, NormalizedByteCode.__ldc)) + { + TypeWrapper classLiteral = eic.GetClassLiteral(-1); + if (!classLiteral.IsUnloadable && classLiteral.GetClassLoader().RemoveAsserts) + { + eic.Emitter.Emit(OpCodes.Pop); + eic.Emitter.EmitLdc_I4(0); + return true; + } + } + return false; + } + +#if STATIC_COMPILER + // this intrinsifies the following two patterns: + // unsafe.objectFieldOffset(XXX.class.getDeclaredField("xxx")); + // and + // Class k = XXX.class; + // unsafe.objectFieldOffset(k.getDeclaredField("xxx")); + // to avoid initializing the full reflection machinery at this point + private static bool Class_getDeclaredField(EmitIntrinsicContext eic) + { + if (eic.Caller.DeclaringType.GetClassLoader() != CoreClasses.java.lang.Object.Wrapper.GetClassLoader()) + { + // we can only do this optimization when compiling the trusted core classes + return false; + } + TypeWrapper fieldClass; + if (eic.MatchRange(-2, 4) + && eic.Match(-2, NormalizedByteCode.__ldc) + && eic.Match(-1, NormalizedByteCode.__ldc_nothrow) + && eic.Match(1, NormalizedByteCode.__invokevirtual)) + { + // unsafe.objectFieldOffset(XXX.class.getDeclaredField("xxx")); + fieldClass = eic.GetClassLiteral(-2); + } + else if (eic.MatchRange(-5, 7) + && eic.Match(-5, NormalizedByteCode.__ldc) + && eic.Match(-4, NormalizedByteCode.__astore) + && eic.Match(-3, NormalizedByteCode.__getstatic) + && eic.Match(-2, NormalizedByteCode.__aload, eic.Code[eic.OpcodeIndex - 4].NormalizedArg1) + && eic.Match(-1, NormalizedByteCode.__ldc_nothrow) + && eic.Match(1, NormalizedByteCode.__invokevirtual)) + { + // Class k = XXX.class; + // unsafe.objectFieldOffset(k.getDeclaredField("xxx")); + fieldClass = eic.GetClassLiteral(-5); + } + else + { + return false; + } + FieldWrapper field = null; + string fieldName = eic.GetStringLiteral(-1); + foreach (FieldWrapper fw in fieldClass.GetFields()) + { + if (fw.Name == fieldName) + { + if (field != null) + { + return false; + } + field = fw; + } + } + if (field == null || field.IsStatic) + { + return false; + } + ClassFile.ConstantPoolItemMI cpi = eic.GetMethodref(1); + if (cpi.Class == "sun.misc.Unsafe" && cpi.Name == "objectFieldOffset" && cpi.Signature == "(Ljava.lang.reflect.Field;)J") + { + MethodWrapper mw = ClassLoaderWrapper.LoadClassCritical("sun.misc.Unsafe") + .GetMethodWrapper("objectFieldOffset", "(Ljava.lang.Class;Ljava.lang.String;)J", false); + mw.Link(); + mw.EmitCallvirt(eic.Emitter); + eic.PatchOpCode(1, NormalizedByteCode.__nop); + return true; + } + return false; + } +#endif + + private static bool IsSafeForGetClassOptimization(TypeWrapper tw) + { + // because of ghost arrays, we don't optimize if both types are either java.lang.Object or an array + return tw != CoreClasses.java.lang.Object.Wrapper && !tw.IsArray; + } + + private static bool Float_floatToRawIntBits(EmitIntrinsicContext eic) + { + EmitConversion(eic.Emitter, typeofFloatConverter, "ToInt"); + return true; + } + + private static bool Float_intBitsToFloat(EmitIntrinsicContext eic) + { + EmitConversion(eic.Emitter, typeofFloatConverter, "ToFloat"); + return true; + } + + private static bool Double_doubleToRawLongBits(EmitIntrinsicContext eic) + { + EmitConversion(eic.Emitter, typeofDoubleConverter, "ToLong"); + return true; + } + + private static bool Double_longBitsToDouble(EmitIntrinsicContext eic) + { + EmitConversion(eic.Emitter, typeofDoubleConverter, "ToDouble"); + return true; + } + + private static void EmitConversion(CodeEmitter ilgen, Type converterType, string method) + { + CodeEmitterLocal converter = ilgen.UnsafeAllocTempLocal(converterType); + ilgen.Emit(OpCodes.Ldloca, converter); + ilgen.Emit(OpCodes.Call, converterType.GetMethod(method)); + } + + private static bool System_arraycopy(EmitIntrinsicContext eic) + { + // if the array arguments on the stack are of a known array type, we can redirect to an optimized version of arraycopy. + TypeWrapper dst_type = eic.GetStackTypeWrapper(0, 2); + TypeWrapper src_type = eic.GetStackTypeWrapper(0, 4); + if (!dst_type.IsUnloadable && dst_type.IsArray && dst_type == src_type) + { + switch (dst_type.Name[1]) + { + case 'J': + case 'D': + eic.Emitter.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy_primitive_8); + break; + case 'I': + case 'F': + eic.Emitter.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy_primitive_4); + break; + case 'S': + case 'C': + eic.Emitter.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy_primitive_2); + break; + case 'B': + case 'Z': + eic.Emitter.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy_primitive_1); + break; + default: + // TODO once the verifier tracks actual types (i.e. it knows that + // a particular reference is the result of a "new" opcode) we can + // use the fast version if the exact destination type is known + // (in that case the "dst_type == src_type" above should + // be changed to "src_type.IsAssignableTo(dst_type)". + TypeWrapper elemtw = dst_type.ElementTypeWrapper; + // note that IsFinal returns true for array types, so we have to be careful! + if (!elemtw.IsArray && elemtw.IsFinal) + { + eic.Emitter.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy_fast); + } + else + { + eic.Emitter.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy); + } + break; + } + return true; + } + else + { + return false; + } + } + + private static bool AtomicReferenceFieldUpdater_newUpdater(EmitIntrinsicContext eic) + { + return AtomicReferenceFieldUpdaterEmitter.Emit(eic.Context, eic.Caller.DeclaringType, eic.Emitter, eic.ClassFile, eic.OpcodeIndex, eic.Code, eic.Flags); + } + +#if STATIC_COMPILER + private static bool String_toCharArray(EmitIntrinsicContext eic) + { + if (eic.MatchRange(-1, 2) + && eic.Match(-1, NormalizedByteCode.__ldc_nothrow)) + { + string str = eic.GetStringLiteral(-1); + // arbitrary length for "big" strings + if (str.Length > 128) + { + eic.Emitter.Emit(OpCodes.Pop); + EmitLoadCharArrayLiteral(eic.Emitter, str, eic.Caller.DeclaringType); + return true; + } + } + return false; + } + + private static void EmitLoadCharArrayLiteral(CodeEmitter ilgen, string str, TypeWrapper tw) + { + ModuleBuilder mod = tw.GetClassLoader().GetTypeWrapperFactory().ModuleBuilder; + // FXBUG on .NET 1.1 & 2.0 the value type that Ref.Emit automatically generates is public, + // so we pre-create a non-public type with the right name here and it will "magically" use + // that instead. + // If we're running on Mono this isn't necessary, but for simplicitly we'll simply create + // the type as well (it is useless, but all it does is waste a little space). + int length = str.Length * 2; + string typename = "$ArrayType$" + length; + Type type = mod.GetType(typename, false, false); + if (type == null) + { + if (tw.GetClassLoader().GetTypeWrapperFactory().ReserveName(typename)) + { + TypeBuilder tb = mod.DefineType(typename, TypeAttributes.Sealed | TypeAttributes.Class | TypeAttributes.ExplicitLayout | TypeAttributes.NotPublic, Types.ValueType, PackingSize.Size1, length); + AttributeHelper.HideFromJava(tb); + type = tb.CreateType(); + } + } + if (type == null + || !type.IsValueType + || type.StructLayoutAttribute.Pack != 1 || type.StructLayoutAttribute.Size != length) + { + // the type that we found doesn't match (must mean we've compiled a Java type with that name), + // so we fall back to the string approach + ilgen.Emit(OpCodes.Ldstr, str); + ilgen.Emit(OpCodes.Call, Types.String.GetMethod("ToCharArray", Type.EmptyTypes)); + return; + } + ilgen.EmitLdc_I4(str.Length); + ilgen.Emit(OpCodes.Newarr, Types.Char); + ilgen.Emit(OpCodes.Dup); + byte[] data = new byte[length]; + for (int j = 0; j < str.Length; j++) + { + data[j * 2 + 0] = (byte)(str[j] >> 0); + data[j * 2 + 1] = (byte)(str[j] >> 8); + } + // NOTE we define a module field, because type fields on Mono don't use the global $ArrayType$ type. + // NOTE this also means that this will only work during static compilation, because ModuleBuilder.CreateGlobalFunctions() must + // be called before the field can be used. + FieldBuilder fb = mod.DefineInitializedData("__", data, FieldAttributes.Static | FieldAttributes.PrivateScope); + ilgen.Emit(OpCodes.Ldtoken, fb); + ilgen.Emit(OpCodes.Call, JVM.Import(typeof(System.Runtime.CompilerServices.RuntimeHelpers)).GetMethod("InitializeArray", new Type[] { Types.Array, JVM.Import(typeof(RuntimeFieldHandle)) })); + } + + private static bool Reflection_getCallerClass(EmitIntrinsicContext eic) + { + if (eic.Caller.HasCallerID) + { + int arg = eic.Caller.GetParametersForDefineMethod().Length - 1; + if (!eic.Caller.IsStatic) + { + arg++; + } + eic.Emitter.EmitLdarg(arg); + MethodWrapper mw; + if (MatchInvokeStatic(eic, 1, "java.lang.ClassLoader", "getClassLoader", "(Ljava.lang.Class;)Ljava.lang.ClassLoader;")) + { + eic.PatchOpCode(1, NormalizedByteCode.__nop); + mw = CoreClasses.ikvm.@internal.CallerID.Wrapper.GetMethodWrapper("getCallerClassLoader", "()Ljava.lang.ClassLoader;", false); + } + else + { + mw = CoreClasses.ikvm.@internal.CallerID.Wrapper.GetMethodWrapper("getCallerClass", "()Ljava.lang.Class;", false); + } + mw.Link(); + mw.EmitCallvirt(eic.Emitter); + return true; + } + else if (DynamicTypeWrapper.RequiresDynamicReflectionCallerClass(eic.ClassFile.Name, eic.Caller.Name, eic.Caller.Signature)) + { + // since the non-intrinsic version of Reflection.getCallerClass() always throws an exception, we have to redirect to the dynamic version + MethodWrapper getCallerClass = ClassLoaderWrapper.LoadClassCritical("sun.reflect.Reflection").GetMethodWrapper("getCallerClass", "(I)Ljava.lang.Class;", false); + getCallerClass.Link(); + eic.Emitter.EmitLdc_I4(2); + getCallerClass.EmitCall(eic.Emitter); + return true; + } + else + { + StaticCompiler.IssueMessage(Message.ReflectionCallerClassRequiresCallerID, eic.ClassFile.Name, eic.Caller.Name, eic.Caller.Signature); + } + return false; + } + + private static bool CallerID_getCallerID(EmitIntrinsicContext eic) + { + if (eic.Caller.HasCallerID) + { + int arg = eic.Caller.GetParametersForDefineMethod().Length - 1; + if (!eic.Caller.IsStatic) + { + arg++; + } + eic.Emitter.EmitLdarg(arg); + return true; + } + else + { + throw new FatalCompilerErrorException(Message.CallerIDRequiresHasCallerIDAnnotation); + } + } +#endif + + private static bool Util_getInstanceTypeFromClass(EmitIntrinsicContext eic) + { + if (eic.MatchRange(-1, 2) + && eic.Match(-1, NormalizedByteCode.__ldc)) + { + TypeWrapper tw = eic.GetClassLiteral(-1); + if (!tw.IsUnloadable) + { + eic.Emitter.Emit(OpCodes.Pop); + if (tw.IsRemapped && tw.IsFinal) + { + eic.Emitter.Emit(OpCodes.Ldtoken, tw.TypeAsTBD); + } + else + { + eic.Emitter.Emit(OpCodes.Ldtoken, tw.TypeAsBaseType); + } + eic.Emitter.Emit(OpCodes.Call, Compiler.getTypeFromHandleMethod); + return true; + } + } + return false; + } + +#if STATIC_COMPILER + private static bool Class_getPrimitiveClass(EmitIntrinsicContext eic) + { + eic.Emitter.Emit(OpCodes.Pop); + eic.Emitter.Emit(OpCodes.Ldnull); + MethodWrapper mw = CoreClasses.java.lang.Class.Wrapper.GetMethodWrapper("", "(Lcli.System.Type;)V", false); + mw.Link(); + mw.EmitNewobj(eic.Emitter); + return true; + } +#endif + + private static bool ThreadLocal_new(EmitIntrinsicContext eic) + { + // it is only valid to replace a ThreadLocal instantiation by our ThreadStatic based version, if we can prove that the instantiation only happens once + // (which is the case when we're in and there aren't any branches that lead to the current position) + if (!eic.Caller.IsClassInitializer) + { + return false; + } +#if CLASSGC + if (JVM.classUnloading) + { + // RunAndCollect assemblies do not support ThreadStaticAttribute + return false; + } +#endif + for (int i = 0; i <= eic.OpcodeIndex; i++) + { + if ((eic.Flags[i] & InstructionFlags.BranchTarget) != 0) + { + return false; + } + } + eic.Emitter.Emit(OpCodes.Newobj, eic.Context.DefineThreadLocalType()); + return true; + } + + private static bool Unsafe_ensureClassInitialized(EmitIntrinsicContext eic) + { + if (eic.MatchRange(-1, 2) + && eic.Match(-1, NormalizedByteCode.__ldc)) + { + TypeWrapper classLiteral = eic.GetClassLiteral(-1); + if (!classLiteral.IsUnloadable) + { + eic.Emitter.Emit(OpCodes.Pop); + eic.Emitter.EmitNullCheck(); + classLiteral.EmitRunClassConstructor(eic.Emitter); + return true; + } + } + return false; + } + + internal static bool IsSupportedArrayTypeForUnsafeOperation(TypeWrapper tw) + { + return tw.IsArray + && !tw.IsGhostArray + && !tw.ElementTypeWrapper.IsPrimitive + && !tw.ElementTypeWrapper.IsNonPrimitiveValueType; + } + + private static bool Unsafe_putObject(EmitIntrinsicContext eic) + { + return Unsafe_putObjectImpl(eic, false); + } + + private static bool Unsafe_putOrderedObject(EmitIntrinsicContext eic) + { + return Unsafe_putObjectImpl(eic, false); + } + + private static bool Unsafe_putObjectVolatile(EmitIntrinsicContext eic) + { + return Unsafe_putObjectImpl(eic, true); + } + + private static bool Unsafe_putObjectImpl(EmitIntrinsicContext eic, bool membarrier) + { + TypeWrapper tw = eic.GetStackTypeWrapper(0, 2); + if (IsSupportedArrayTypeForUnsafeOperation(tw) + && eic.GetStackTypeWrapper(0, 0).IsAssignableTo(tw.ElementTypeWrapper)) + { + CodeEmitterLocal value = eic.Emitter.AllocTempLocal(tw.ElementTypeWrapper.TypeAsLocalOrStackType); + CodeEmitterLocal index = eic.Emitter.AllocTempLocal(Types.Int32); + CodeEmitterLocal array = eic.Emitter.AllocTempLocal(tw.TypeAsLocalOrStackType); + eic.Emitter.Emit(OpCodes.Stloc, value); + eic.Emitter.Emit(OpCodes.Conv_Ovf_I4); + eic.Emitter.Emit(OpCodes.Stloc, index); + eic.Emitter.Emit(OpCodes.Stloc, array); + EmitConsumeUnsafe(eic); + eic.Emitter.Emit(OpCodes.Ldloc, array); + eic.Emitter.Emit(OpCodes.Ldloc, index); + eic.Emitter.Emit(OpCodes.Ldloc, value); + eic.Emitter.ReleaseTempLocal(array); + eic.Emitter.ReleaseTempLocal(index); + eic.Emitter.ReleaseTempLocal(value); + eic.Emitter.Emit(OpCodes.Stelem_Ref); + if (membarrier) + { + eic.Emitter.EmitMemoryBarrier(); + } + eic.NonLeaf = false; + return true; + } + if ((eic.Flags[eic.OpcodeIndex] & InstructionFlags.BranchTarget) != 0 + || (eic.Flags[eic.OpcodeIndex - 1] & InstructionFlags.BranchTarget) != 0) + { + return false; + } + if ((eic.Match(-1, NormalizedByteCode.__aload) || eic.Match(-1, NormalizedByteCode.__aconst_null)) + && eic.Match(-2, NormalizedByteCode.__getstatic)) + { + FieldWrapper fw = GetUnsafeField(eic, eic.GetFieldref(-2)); + if (fw != null + && (!fw.IsFinal || (!fw.IsStatic && eic.Caller.Name == "") || (fw.IsStatic && eic.Caller.Name == "")) + && fw.IsAccessibleFrom(fw.DeclaringType, eic.Caller.DeclaringType, fw.DeclaringType) + && eic.GetStackTypeWrapper(0, 0).IsAssignableTo(fw.FieldTypeWrapper) + && (fw.IsStatic || fw.DeclaringType == eic.GetStackTypeWrapper(0, 2))) + { + CodeEmitterLocal value = eic.Emitter.AllocTempLocal(fw.FieldTypeWrapper.TypeAsLocalOrStackType); + eic.Emitter.Emit(OpCodes.Stloc, value); + eic.Emitter.Emit(OpCodes.Pop); // discard offset field + if (fw.IsStatic) + { + eic.Emitter.Emit(OpCodes.Pop); // discard object + EmitConsumeUnsafe(eic); + } + else + { + CodeEmitterLocal obj = eic.Emitter.AllocTempLocal(fw.DeclaringType.TypeAsLocalOrStackType); + eic.Emitter.Emit(OpCodes.Stloc, obj); + EmitConsumeUnsafe(eic); + eic.Emitter.Emit(OpCodes.Ldloc, obj); + eic.Emitter.ReleaseTempLocal(obj); + } + eic.Emitter.Emit(OpCodes.Ldloc, value); + eic.Emitter.ReleaseTempLocal(value); + // note that we assume the CLR memory model where all writes are ordered, + // so we don't need a volatile store or a memory barrier and putOrderedObject + // is typically used with a volatile field, so to avoid the memory barrier, + // we don't use FieldWrapper.EmitSet(), but emit the store directly + eic.Emitter.Emit(fw.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, fw.GetField()); + if (membarrier) + { + eic.Emitter.EmitMemoryBarrier(); + } + eic.NonLeaf = false; + return true; + } + } + return false; + } + + private static bool Unsafe_getObjectVolatile(EmitIntrinsicContext eic) + { + // the check here must be kept in sync with the hack in MethodAnalyzer.AnalyzeTypeFlow() + TypeWrapper tw = eic.GetStackTypeWrapper(0, 1); + if (IsSupportedArrayTypeForUnsafeOperation(tw)) + { + CodeEmitterLocal index = eic.Emitter.AllocTempLocal(Types.Int32); + CodeEmitterLocal obj = eic.Emitter.AllocTempLocal(tw.TypeAsLocalOrStackType); + eic.Emitter.Emit(OpCodes.Conv_Ovf_I4); + eic.Emitter.Emit(OpCodes.Stloc, index); + eic.Emitter.Emit(OpCodes.Stloc, obj); + EmitConsumeUnsafe(eic); + eic.Emitter.Emit(OpCodes.Ldloc, obj); + eic.Emitter.Emit(OpCodes.Ldloc, index); + eic.Emitter.ReleaseTempLocal(obj); + eic.Emitter.ReleaseTempLocal(index); + eic.Emitter.Emit(OpCodes.Ldelema, tw.TypeAsLocalOrStackType.GetElementType()); + eic.Emitter.Emit(OpCodes.Volatile); + eic.Emitter.Emit(OpCodes.Ldind_Ref); + // remove the redundant checkcast that usually follows + if (eic.Code[eic.OpcodeIndex + 1].NormalizedOpCode == NormalizedByteCode.__checkcast + && tw.ElementTypeWrapper.IsAssignableTo(eic.ClassFile.GetConstantPoolClassType(eic.Code[eic.OpcodeIndex + 1].Arg1))) + { + eic.PatchOpCode(1, NormalizedByteCode.__nop); + } + eic.NonLeaf = false; + return true; + } + return false; + } + + private static bool Unsafe_compareAndSwapObject(EmitIntrinsicContext eic) + { + TypeWrapper tw = eic.GetStackTypeWrapper(0, 3); + if (IsSupportedArrayTypeForUnsafeOperation(tw) + && eic.GetStackTypeWrapper(0, 0).IsAssignableTo(tw.ElementTypeWrapper) + && eic.GetStackTypeWrapper(0, 1).IsAssignableTo(tw.ElementTypeWrapper)) + { + Type type = tw.TypeAsLocalOrStackType.GetElementType(); + CodeEmitterLocal update = eic.Emitter.AllocTempLocal(type); + CodeEmitterLocal expect = eic.Emitter.AllocTempLocal(type); + CodeEmitterLocal index = eic.Emitter.AllocTempLocal(Types.Int32); + CodeEmitterLocal obj = eic.Emitter.AllocTempLocal(tw.TypeAsLocalOrStackType); + eic.Emitter.Emit(OpCodes.Stloc, update); + eic.Emitter.Emit(OpCodes.Stloc, expect); + eic.Emitter.Emit(OpCodes.Conv_Ovf_I4); + eic.Emitter.Emit(OpCodes.Stloc, index); + eic.Emitter.Emit(OpCodes.Stloc, obj); + EmitConsumeUnsafe(eic); + eic.Emitter.Emit(OpCodes.Ldloc, obj); + eic.Emitter.Emit(OpCodes.Ldloc, index); + eic.Emitter.Emit(OpCodes.Ldelema, type); + eic.Emitter.Emit(OpCodes.Ldloc, update); + eic.Emitter.Emit(OpCodes.Ldloc, expect); + eic.Emitter.Emit(OpCodes.Call, AtomicReferenceFieldUpdaterEmitter.MakeCompareExchange(type)); + eic.Emitter.Emit(OpCodes.Ldloc, expect); + eic.Emitter.Emit(OpCodes.Ceq); + eic.Emitter.ReleaseTempLocal(obj); + eic.Emitter.ReleaseTempLocal(index); + eic.Emitter.ReleaseTempLocal(expect); + eic.Emitter.ReleaseTempLocal(update); + eic.NonLeaf = false; + return true; + } + if ((eic.Flags[eic.OpcodeIndex] & InstructionFlags.BranchTarget) != 0 + || (eic.Flags[eic.OpcodeIndex - 1] & InstructionFlags.BranchTarget) != 0 + || (eic.Flags[eic.OpcodeIndex - 2] & InstructionFlags.BranchTarget) != 0) + { + return false; + } + if ((eic.Match(-1, NormalizedByteCode.__aload) || eic.Match(-1, NormalizedByteCode.__aconst_null)) + && (eic.Match(-2, NormalizedByteCode.__aload) || eic.Match(-2, NormalizedByteCode.__aconst_null)) + && eic.Match(-3, NormalizedByteCode.__getstatic)) + { + FieldWrapper fw = GetUnsafeField(eic, eic.GetFieldref(-3)); + if (fw != null + && fw.IsAccessibleFrom(fw.DeclaringType, eic.Caller.DeclaringType, fw.DeclaringType) + && eic.GetStackTypeWrapper(0, 0).IsAssignableTo(fw.FieldTypeWrapper) + && eic.GetStackTypeWrapper(0, 1).IsAssignableTo(fw.FieldTypeWrapper) + && (fw.IsStatic || fw.DeclaringType == eic.GetStackTypeWrapper(0, 3))) + { + Type type = fw.FieldTypeWrapper.TypeAsLocalOrStackType; + CodeEmitterLocal update = eic.Emitter.AllocTempLocal(type); + CodeEmitterLocal expect = eic.Emitter.AllocTempLocal(type); + eic.Emitter.Emit(OpCodes.Stloc, update); + eic.Emitter.Emit(OpCodes.Stloc, expect); + eic.Emitter.Emit(OpCodes.Pop); // discard index + if (fw.IsStatic) + { + eic.Emitter.Emit(OpCodes.Pop); // discard obj + EmitConsumeUnsafe(eic); + eic.Emitter.Emit(OpCodes.Ldsflda, fw.GetField()); + } + else + { + CodeEmitterLocal obj = eic.Emitter.AllocTempLocal(eic.Caller.DeclaringType.TypeAsLocalOrStackType); + eic.Emitter.Emit(OpCodes.Stloc, obj); + EmitConsumeUnsafe(eic); + eic.Emitter.Emit(OpCodes.Ldloc, obj); + eic.Emitter.ReleaseTempLocal(obj); + eic.Emitter.Emit(OpCodes.Ldflda, fw.GetField()); + } + eic.Emitter.Emit(OpCodes.Ldloc, update); + eic.Emitter.Emit(OpCodes.Ldloc, expect); + eic.Emitter.Emit(OpCodes.Call, AtomicReferenceFieldUpdaterEmitter.MakeCompareExchange(type)); + eic.Emitter.Emit(OpCodes.Ldloc, expect); + eic.Emitter.Emit(OpCodes.Ceq); + eic.Emitter.ReleaseTempLocal(expect); + eic.Emitter.ReleaseTempLocal(update); + eic.NonLeaf = false; + return true; + } + } + // stack layout at call site: + // 4 Unsafe (receiver) + // 3 Object (obj) + // 2 long (offset) + // 1 Object (expect) + // 0 Object (update) + TypeWrapper twUnsafe = eic.GetStackTypeWrapper(0, 4); + if (twUnsafe == VerifierTypeWrapper.Null) + { + return false; + } + for (int i = 0; ; i--) + { + if ((eic.Flags[eic.OpcodeIndex + i] & InstructionFlags.BranchTarget) != 0) + { + return false; + } + if (eic.GetStackTypeWrapper(i, 0) == twUnsafe) + { + // the pattern we recognize is: + // aload + // getstatic + if (eic.Match(i, NormalizedByteCode.__aload) && eic.GetStackTypeWrapper(i + 1, 0) == eic.Caller.DeclaringType + && eic.Match(i + 1, NormalizedByteCode.__getstatic)) + { + FieldWrapper fw = GetUnsafeField(eic, eic.GetFieldref(i + 1)); + if (fw != null && !fw.IsStatic && fw.DeclaringType == eic.Caller.DeclaringType) + { + Type type = fw.FieldTypeWrapper.TypeAsLocalOrStackType; + CodeEmitterLocal update = eic.Emitter.AllocTempLocal(type); + CodeEmitterLocal expect = eic.Emitter.AllocTempLocal(type); + CodeEmitterLocal obj = eic.Emitter.AllocTempLocal(eic.Caller.DeclaringType.TypeAsLocalOrStackType); + eic.Emitter.Emit(OpCodes.Stloc, update); + eic.Emitter.Emit(OpCodes.Stloc, expect); + eic.Emitter.Emit(OpCodes.Pop); // discard offset + eic.Emitter.Emit(OpCodes.Stloc, obj); + EmitConsumeUnsafe(eic); + eic.Emitter.Emit(OpCodes.Ldloc, obj); + eic.Emitter.Emit(OpCodes.Ldflda, fw.GetField()); + eic.Emitter.Emit(OpCodes.Ldloc, update); + eic.Emitter.Emit(OpCodes.Ldloc, expect); + eic.Emitter.Emit(OpCodes.Call, AtomicReferenceFieldUpdaterEmitter.MakeCompareExchange(type)); + eic.Emitter.Emit(OpCodes.Ldloc, expect); + eic.Emitter.Emit(OpCodes.Ceq); + eic.Emitter.ReleaseTempLocal(expect); + eic.Emitter.ReleaseTempLocal(update); + eic.NonLeaf = false; + return true; + } + } + return false; + } + } + } + + private static bool Unsafe_getAndSetObject(EmitIntrinsicContext eic) + { + TypeWrapper tw = eic.GetStackTypeWrapper(0, 2); + if (IsSupportedArrayTypeForUnsafeOperation(tw) + && eic.GetStackTypeWrapper(0, 0).IsAssignableTo(tw.ElementTypeWrapper)) + { + Type type = tw.TypeAsLocalOrStackType.GetElementType(); + CodeEmitterLocal newValue = eic.Emitter.AllocTempLocal(type); + CodeEmitterLocal index = eic.Emitter.AllocTempLocal(Types.Int32); + CodeEmitterLocal obj = eic.Emitter.AllocTempLocal(tw.TypeAsLocalOrStackType); + eic.Emitter.Emit(OpCodes.Stloc, newValue); + eic.Emitter.Emit(OpCodes.Conv_Ovf_I4); + eic.Emitter.Emit(OpCodes.Stloc, index); + eic.Emitter.Emit(OpCodes.Stloc, obj); + EmitConsumeUnsafe(eic); + eic.Emitter.Emit(OpCodes.Ldloc, obj); + eic.Emitter.Emit(OpCodes.Ldloc, index); + eic.Emitter.Emit(OpCodes.Ldelema, type); + eic.Emitter.Emit(OpCodes.Ldloc, newValue); + eic.Emitter.Emit(OpCodes.Call, MakeExchange(type)); + eic.Emitter.ReleaseTempLocal(obj); + eic.Emitter.ReleaseTempLocal(index); + eic.Emitter.ReleaseTempLocal(newValue); + eic.NonLeaf = false; + return true; + } + return false; + } + + private static bool Unsafe_compareAndSwapInt(EmitIntrinsicContext eic) + { + // stack layout at call site: + // 4 Unsafe (receiver) + // 3 Object (obj) + // 2 long (offset) + // 1 int (expect) + // 0 int (update) + TypeWrapper twUnsafe = eic.GetStackTypeWrapper(0, 4); + if (twUnsafe == VerifierTypeWrapper.Null) + { + return false; + } + for (int i = 0; ; i--) + { + if ((eic.Flags[eic.OpcodeIndex + i] & InstructionFlags.BranchTarget) != 0) + { + return false; + } + if (eic.GetStackTypeWrapper(i, 0) == twUnsafe) + { + // the pattern we recognize is: + // aload + // getstatic + if (eic.Match(i, NormalizedByteCode.__aload) && eic.GetStackTypeWrapper(i + 1, 0) == eic.Caller.DeclaringType + && eic.Match(i + 1, NormalizedByteCode.__getstatic)) + { + FieldWrapper fw = GetUnsafeField(eic, eic.GetFieldref(i + 1)); + if (fw != null && !fw.IsStatic && fw.DeclaringType == eic.Caller.DeclaringType) + { + CodeEmitterLocal update = eic.Emitter.AllocTempLocal(Types.Int32); + CodeEmitterLocal expect = eic.Emitter.AllocTempLocal(Types.Int32); + CodeEmitterLocal obj = eic.Emitter.AllocTempLocal(eic.Caller.DeclaringType.TypeAsLocalOrStackType); + eic.Emitter.Emit(OpCodes.Stloc, update); + eic.Emitter.Emit(OpCodes.Stloc, expect); + eic.Emitter.Emit(OpCodes.Pop); // discard offset + eic.Emitter.Emit(OpCodes.Stloc, obj); + EmitConsumeUnsafe(eic); + eic.Emitter.Emit(OpCodes.Ldloc, obj); + eic.Emitter.Emit(OpCodes.Ldflda, fw.GetField()); + eic.Emitter.Emit(OpCodes.Ldloc, update); + eic.Emitter.Emit(OpCodes.Ldloc, expect); + eic.Emitter.Emit(OpCodes.Call, InterlockedMethods.CompareExchangeInt32); + eic.Emitter.Emit(OpCodes.Ldloc, expect); + eic.Emitter.Emit(OpCodes.Ceq); + eic.Emitter.ReleaseTempLocal(expect); + eic.Emitter.ReleaseTempLocal(update); + eic.NonLeaf = false; + return true; + } + } + return false; + } + } + } + + private static bool Unsafe_getAndAddInt(EmitIntrinsicContext eic) + { + // stack layout at call site: + // 3 Unsafe (receiver) + // 2 Object (obj) + // 1 long (offset) + // 0 int (delta) + TypeWrapper twUnsafe = eic.GetStackTypeWrapper(0, 3); + if (twUnsafe == VerifierTypeWrapper.Null) + { + return false; + } + for (int i = 0; ; i--) + { + if ((eic.Flags[eic.OpcodeIndex + i] & InstructionFlags.BranchTarget) != 0) + { + return false; + } + if (eic.GetStackTypeWrapper(i, 0) == twUnsafe) + { + // the pattern we recognize is: + // aload_0 + // getstatic + if (eic.Match(i, NormalizedByteCode.__aload, 0) + && eic.Match(i + 1, NormalizedByteCode.__getstatic)) + { + FieldWrapper fw = GetUnsafeField(eic, eic.GetFieldref(i + 1)); + if (fw != null && !fw.IsStatic && fw.DeclaringType == eic.Caller.DeclaringType) + { + CodeEmitterLocal delta = eic.Emitter.AllocTempLocal(Types.Int32); + eic.Emitter.Emit(OpCodes.Stloc, delta); + eic.Emitter.Emit(OpCodes.Pop); // discard offset + eic.Emitter.Emit(OpCodes.Pop); // discard obj + EmitConsumeUnsafe(eic); + eic.Emitter.Emit(OpCodes.Ldarg_0); + eic.Emitter.Emit(OpCodes.Ldflda, fw.GetField()); + eic.Emitter.Emit(OpCodes.Ldloc, delta); + eic.Emitter.Emit(OpCodes.Call, InterlockedMethods.AddInt32); + eic.Emitter.Emit(OpCodes.Ldloc, delta); + eic.Emitter.Emit(OpCodes.Sub); + eic.Emitter.ReleaseTempLocal(delta); + eic.NonLeaf = false; + return true; + } + } + return false; + } + } + } + + private static bool Unsafe_compareAndSwapLong(EmitIntrinsicContext eic) + { + // stack layout at call site: + // 4 Unsafe (receiver) + // 3 Object (obj) + // 2 long (offset) + // 1 long (expect) + // 0 long (update) + TypeWrapper twUnsafe = eic.GetStackTypeWrapper(0, 4); + if (twUnsafe == VerifierTypeWrapper.Null) + { + return false; + } + for (int i = 0; ; i--) + { + if ((eic.Flags[eic.OpcodeIndex + i] & InstructionFlags.BranchTarget) != 0) + { + return false; + } + if (eic.GetStackTypeWrapper(i, 0) == twUnsafe) + { + // the pattern we recognize is: + // aload + // getstatic + if (eic.Match(i, NormalizedByteCode.__aload) && eic.GetStackTypeWrapper(i + 1, 0) == eic.Caller.DeclaringType + && eic.Match(i + 1, NormalizedByteCode.__getstatic)) + { + FieldWrapper fw = GetUnsafeField(eic, eic.GetFieldref(i + 1)); + if (fw != null && !fw.IsStatic && fw.DeclaringType == eic.Caller.DeclaringType) + { + CodeEmitterLocal update = eic.Emitter.AllocTempLocal(Types.Int64); + CodeEmitterLocal expect = eic.Emitter.AllocTempLocal(Types.Int64); + CodeEmitterLocal obj = eic.Emitter.AllocTempLocal(eic.Caller.DeclaringType.TypeAsLocalOrStackType); + eic.Emitter.Emit(OpCodes.Stloc, update); + eic.Emitter.Emit(OpCodes.Stloc, expect); + eic.Emitter.Emit(OpCodes.Pop); // discard offset + eic.Emitter.Emit(OpCodes.Stloc, obj); + EmitConsumeUnsafe(eic); + eic.Emitter.Emit(OpCodes.Ldloc, obj); + eic.Emitter.Emit(OpCodes.Ldflda, fw.GetField()); + eic.Emitter.Emit(OpCodes.Ldloc, update); + eic.Emitter.Emit(OpCodes.Ldloc, expect); + eic.Emitter.Emit(OpCodes.Call, InterlockedMethods.CompareExchangeInt64); + eic.Emitter.Emit(OpCodes.Ldloc, expect); + eic.Emitter.Emit(OpCodes.Ceq); + eic.Emitter.ReleaseTempLocal(expect); + eic.Emitter.ReleaseTempLocal(update); + eic.NonLeaf = false; + return true; + } + } + return false; + } + } + } + + internal static MethodInfo MakeExchange(Type type) + { + return InterlockedMethods.ExchangeOfT.MakeGenericMethod(type); + } + + private static void EmitConsumeUnsafe(EmitIntrinsicContext eic) + { +#if STATIC_COMPILER + if (eic.Caller.DeclaringType.GetClassLoader() == CoreClasses.java.lang.Object.Wrapper.GetClassLoader()) + { + // we're compiling the core library (which is obviously trusted), so we don't need to check + // if we really have an Unsafe instance + eic.Emitter.Emit(OpCodes.Pop); + } + else +#endif + { + eic.Emitter.EmitNullCheck(); + } + } + + private static FieldWrapper GetUnsafeField(EmitIntrinsicContext eic, ClassFile.ConstantPoolItemFieldref field) + { + if (eic.Caller.DeclaringType.GetClassLoader() != CoreClasses.java.lang.Object.Wrapper.GetClassLoader()) + { + // this code does not solve the general problem and assumes non-hostile, well behaved static initializers + // so we only support the core class library + return null; + } + + // the field offset field must be a static field inside the current class + // (we don't need to check that the field is static, because the caller already ensured that) + if (field.GetField().DeclaringType == eic.Caller.DeclaringType) + { + // now look inside the static initializer to see if we can found out what field it refers to + foreach (ClassFile.Method method in eic.ClassFile.Methods) + { + if (method.IsClassInitializer) + { + // TODO should we first verify the method? + // TODO should we attempt to make sure the field is definitely assigned (and only once)? + + // TODO special case/support the pattern used by: + // - java.util.concurrent.atomic.AtomicMarkableReference + // - java.util.concurrent.atomic.AtomicStampedReference + // - java.util.concurrent.locks.AbstractQueuedLongSynchronizer + + /* + * ldc_w test + * astore_0 + * ... + * getstatic + * aload_0 | ldc + * ldc "next" + * invokevirtual + * invokevirtual + * putstatic + */ + for (int i = 0; i < method.Instructions.Length; i++) + { + if (method.Instructions[i].NormalizedOpCode == NormalizedByteCode.__putstatic + && eic.ClassFile.GetFieldref(method.Instructions[i].Arg1) == field) + { + if (MatchInvokeVirtual(eic, ref method.Instructions[i - 1], "sun.misc.Unsafe", "objectFieldOffset", "(Ljava.lang.reflect.Field;)J") + && MatchInvokeVirtual(eic, ref method.Instructions[i - 2], "java.lang.Class", "getDeclaredField", "(Ljava.lang.String;)Ljava.lang.reflect.Field;") + && MatchLdc(eic, ref method.Instructions[i - 3], ClassFile.ConstantType.String) + && (method.Instructions[i - 4].NormalizedOpCode == NormalizedByteCode.__aload || method.Instructions[i - 4].NormalizedOpCode == NormalizedByteCode.__ldc) + && method.Instructions[i - 5].NormalizedOpCode == NormalizedByteCode.__getstatic && eic.ClassFile.GetFieldref(method.Instructions[i - 5].Arg1).Signature == "Lsun.misc.Unsafe;") + { + if (method.Instructions[i - 4].NormalizedOpCode == NormalizedByteCode.__ldc) + { + if (eic.ClassFile.GetConstantPoolClassType(method.Instructions[i - 4].Arg1) == eic.Caller.DeclaringType) + { + string fieldName = eic.ClassFile.GetConstantPoolConstantString(method.Instructions[i - 3].Arg1); + FieldWrapper fw = null; + foreach (FieldWrapper fw1 in eic.Caller.DeclaringType.GetFields()) + { + if (fw1.Name == fieldName) + { + if (fw == null) + { + fw = fw1; + } + else + { + // duplicate name + return null; + } + } + } + return fw; + } + return null; + } + // search backward for the astore that corresponds to the aload (of the class object) + for (int j = i - 6; j > 0; j--) + { + if (method.Instructions[j].NormalizedOpCode == NormalizedByteCode.__astore + && method.Instructions[j].Arg1 == method.Instructions[i - 4].Arg1 + && MatchLdc(eic, ref method.Instructions[j - 1], ClassFile.ConstantType.Class) + && eic.ClassFile.GetConstantPoolClassType(method.Instructions[j - 1].Arg1) == eic.Caller.DeclaringType) + { + string fieldName = eic.ClassFile.GetConstantPoolConstantString(method.Instructions[i - 3].Arg1); + FieldWrapper fw = null; + foreach (FieldWrapper fw1 in eic.Caller.DeclaringType.GetFields()) + { + if (fw1.Name == fieldName) + { + if (fw == null) + { + fw = fw1; + } + else + { + // duplicate name + return null; + } + } + } + return fw; + } + } + break; + } + } + } + break; + } + } + } + return null; + } + + private static bool MatchInvokeVirtual(EmitIntrinsicContext eic, ref Instruction instr, string clazz, string name, string sig) + { + return MatchInvoke(eic, ref instr, NormalizedByteCode.__invokevirtual, clazz, name, sig); + } + + private static bool MatchInvokeStatic(EmitIntrinsicContext eic, int offset, string clazz, string name, string sig) + { + return MatchInvoke(eic, ref eic.Code[eic.OpcodeIndex + offset], NormalizedByteCode.__invokestatic, clazz, name, sig); + } + + private static bool MatchInvoke(EmitIntrinsicContext eic, ref Instruction instr, NormalizedByteCode opcode, string clazz, string name, string sig) + { + if (instr.NormalizedOpCode == opcode) + { + ClassFile.ConstantPoolItemMI method = eic.ClassFile.GetMethodref(instr.Arg1); + return method.Class == clazz + && method.Name == name + && method.Signature == sig; + } + return false; + } + + private static bool MatchLdc(EmitIntrinsicContext eic, ref Instruction instr, ClassFile.ConstantType constantType) + { + return (instr.NormalizedOpCode == NormalizedByteCode.__ldc || instr.NormalizedOpCode == NormalizedByteCode.__ldc_nothrow) + && eic.ClassFile.GetConstantPoolConstantType(instr.NormalizedArg1) == constantType; + } + } +} diff --git a/runtime/openjdk/NativeInvokerBytecodeGenerator.cs b/runtime/openjdk/NativeInvokerBytecodeGenerator.cs new file mode 100644 index 0000000..c38a010 --- /dev/null +++ b/runtime/openjdk/NativeInvokerBytecodeGenerator.cs @@ -0,0 +1,1029 @@ +/* + * Copyright (c) 2012, 2013, 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. + */ + +// [IKVM] Based on original from OpenJDK, but heavily modified to directly generate a DynamicMethod, +// instead of Java bytecode. +// Copyright (C) 2015 Jeroen Frijters + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using System.Reflection.Emit; +using System.Runtime.CompilerServices; +using IKVM.Attributes; +using IKVM.Internal; +using java.lang.invoke; +#if !FIRST_PASS +using BasicType = java.lang.invoke.LambdaForm.BasicType; +using Class = java.lang.Class; +using Name = java.lang.invoke.LambdaForm.Name; +using Opcodes = jdk.@internal.org.objectweb.asm.Opcodes.__Fields; +using VerifyType = sun.invoke.util.VerifyType; +using Wrapper = sun.invoke.util.Wrapper; +#endif + +sealed class NativeInvokerBytecodeGenerator +{ +#if FIRST_PASS + public static MemberName generateCustomizedCode(LambdaForm form, MethodType invokerType) + { + return null; + } +#else + private readonly LambdaForm lambdaForm; + private readonly MethodType invokerType; + private readonly Type delegateType; + private readonly DynamicMethod dm; + private readonly CodeEmitter ilgen; + private readonly int packedArgPos; + private readonly Type packedArgType; + private readonly CodeEmitterLocal[] locals; + private readonly List constants = new List(); + + private enum Bailout + { + NotBasicType, + UnsupportedIntrinsic, + UnsupportedArrayType, + UnsupportedRefKind, + UnsupportedConstant, + NotStaticallyInvocable, + PreconditionViolated, + } + + private sealed class BailoutException : Exception + { + internal BailoutException(Bailout reason, object data) + : base("BAILOUT " + reason + ": " + data) + { + } + } + + private NativeInvokerBytecodeGenerator(LambdaForm lambdaForm, MethodType invokerType) + { + if (invokerType != invokerType.basicType()) + { + throw new BailoutException(Bailout.NotBasicType, invokerType); + } + this.lambdaForm = lambdaForm; + this.invokerType = invokerType; + this.delegateType = MethodHandleUtil.GetMemberWrapperDelegateType(invokerType); + MethodInfo mi = MethodHandleUtil.GetDelegateInvokeMethod(delegateType); + Type[] paramTypes = MethodHandleUtil.GetParameterTypes(typeof(object[]), mi); + // HACK the code we generate is not verifiable (known issue: locals aren't typed correctly), so we stick the DynamicMethod into mscorlib (a security critical assembly) + this.dm = new DynamicMethod(lambdaForm.debugName, mi.ReturnType, paramTypes, typeof(object).Module, true); + this.ilgen = CodeEmitter.Create(this.dm); + if (invokerType.parameterCount() > MethodHandleUtil.MaxArity) + { + this.packedArgType = paramTypes[paramTypes.Length - 1]; + this.packedArgPos = paramTypes.Length - 1; + } + else + { + this.packedArgPos = Int32.MaxValue; + } + + locals = new CodeEmitterLocal[lambdaForm.names.Length]; + for (int i = lambdaForm._arity(); i < lambdaForm.names.Length; i++) + { + Name name = lambdaForm.names[i]; + if (name.index() != i) + { + throw new BailoutException(Bailout.PreconditionViolated, "name.index() != i"); + } + switch (name.typeChar()) + { + case 'L': + locals[i] = ilgen.DeclareLocal(Types.Object); + break; + case 'I': + locals[i] = ilgen.DeclareLocal(Types.Int32); + break; + case 'J': + locals[i] = ilgen.DeclareLocal(Types.Int64); + break; + case 'F': + locals[i] = ilgen.DeclareLocal(Types.Single); + break; + case 'D': + locals[i] = ilgen.DeclareLocal(Types.Double); + break; + case 'V': + break; + default: + throw new BailoutException(Bailout.PreconditionViolated, "Unsupported typeChar(): " + name.typeChar()); + } + } + } + + /* + * Low-level emit helpers. + */ + private void emitConst(object con) { + if (con == null) { + ilgen.Emit(OpCodes.Ldnull); + } else if (con is string) { + ilgen.Emit(OpCodes.Ldstr, (string)con); + } else if (con is java.lang.Integer) { + ilgen.EmitLdc_I4(((java.lang.Integer)con).intValue()); + } else if (con is java.lang.Long) { + ilgen.EmitLdc_I8(((java.lang.Long)con).longValue()); + } else if (con is java.lang.Float) { + ilgen.EmitLdc_R4(((java.lang.Float)con).floatValue()); + } else if (con is java.lang.Double) { + ilgen.EmitLdc_R8(((java.lang.Double)con).doubleValue()); + } else if (con is java.lang.Boolean) { + ilgen.EmitLdc_I4(((java.lang.Boolean)con).booleanValue() ? 1 : 0); + } else { + throw new BailoutException(Bailout.UnsupportedConstant, con); + } + } + + private void emitIconstInsn(int i) { + ilgen.EmitLdc_I4(i); + } + + /* + * NOTE: These load/store methods use the localsMap to find the correct index! + */ + private void emitLoadInsn(BasicType type, int index) { + // [IKVM] we don't need the localsMap (it is used to correct for long/double taking two slots) + if (locals[index] == null) { + MethodHandleUtil.LoadPackedArg(ilgen, index, 1, packedArgPos, packedArgType); + } else { + ilgen.Emit(OpCodes.Ldloc, locals[index]); + } + } + + private void emitStoreInsn(BasicType type, int index) { + ilgen.Emit(OpCodes.Stloc, locals[index]); + } + + private void emitAstoreInsn(int index) { + emitStoreInsn(BasicType.L_TYPE, index); + } + + private byte arrayTypeCode(Wrapper elementType) { + switch (elementType.name()) { + case "BOOLEAN": return Opcodes.T_BOOLEAN; + case "BYTE": return Opcodes.T_BYTE; + case "CHAR": return Opcodes.T_CHAR; + case "SHORT": return Opcodes.T_SHORT; + case "INT": return Opcodes.T_INT; + case "LONG": return Opcodes.T_LONG; + case "FLOAT": return Opcodes.T_FLOAT; + case "DOUBLE": return Opcodes.T_DOUBLE; + case "OBJECT": return 0; // in place of Opcodes.T_OBJECT + default: throw new BailoutException(Bailout.PreconditionViolated, "elemendType = " + elementType); + } + } + + private OpCode arrayInsnOpcode(byte tcode) + { + switch (tcode) + { + case Opcodes.T_BOOLEAN: + case Opcodes.T_BYTE: + return OpCodes.Stelem_I1; + case Opcodes.T_CHAR: + case Opcodes.T_SHORT: + return OpCodes.Stelem_I2; + case Opcodes.T_INT: + return OpCodes.Stelem_I4; + case Opcodes.T_LONG: + return OpCodes.Stelem_I8; + case Opcodes.T_FLOAT: + return OpCodes.Stelem_R4; + case Opcodes.T_DOUBLE: + return OpCodes.Stelem_R8; + case 0: + return OpCodes.Stelem_Ref; + default: + throw new BailoutException(Bailout.PreconditionViolated, "tcode = " + tcode); + } + } + + /** + * Emit an implicit conversion for an argument which must be of the given pclass. + * This is usually a no-op, except when pclass is a subword type or a reference other than Object or an interface. + * + * @param ptype type of value present on stack + * @param pclass type of value required on stack + * @param arg compile-time representation of value on stack (Node, constant) or null if none + */ + private void emitImplicitConversion(BasicType ptype, Class pclass, object arg) { + //assert(basicType(pclass) == ptype); // boxing/unboxing handled by caller + if (pclass == ptype.basicTypeClass() && ptype != BasicType.L_TYPE) + return; // nothing to do + switch (ptype.name()) { + case "L_TYPE": + if (VerifyType.isNullConversion(CoreClasses.java.lang.Object.Wrapper.ClassObject, pclass, false)) { + //if (PROFILE_LEVEL > 0) + // emitReferenceCast(Object.class, arg); + return; + } + emitReferenceCast(pclass, arg); + return; + case "I_TYPE": + if (!VerifyType.isNullConversion(java.lang.Integer.TYPE, pclass, false)) + emitPrimCast(ptype.basicTypeWrapper(), Wrapper.forPrimitiveType(pclass)); + return; + } + throw new BailoutException(Bailout.PreconditionViolated, "bad implicit conversion: tc=" + ptype + ": " + pclass); + } + + /** Update localClasses type map. Return true if the information is already present. */ + private void assertStaticType(Class cls, Name n) { + // [IKVM] not implemented + } + + private void emitReferenceCast(Class cls, object arg) { + // [IKVM] handle the type system hole that is caused by arrays being both derived from cli.System.Array and directly from java.lang.Object + if (cls != CoreClasses.cli.System.Object.Wrapper.ClassObject) + { + TypeWrapper.FromClass(cls).EmitCheckcast(ilgen); + } + } + + private sealed class AnonymousClass : TypeWrapper + { + internal static readonly Class Instance = new AnonymousClass().ClassObject; + + private AnonymousClass() + : base(TypeFlags.Anonymous, Modifiers.Super | Modifiers.Final, "java.lang.invoke.LambdaForm$MH") + { + } + + internal override ClassLoaderWrapper GetClassLoader() + { + return ClassLoaderWrapper.GetBootstrapClassLoader(); + } + + internal override Type TypeAsTBD + { + get { throw new InvalidOperationException(); } + } + + internal override TypeWrapper BaseTypeWrapper + { + get { return CoreClasses.java.lang.Object.Wrapper; } + } + } + + /** + * Generate customized bytecode for a given LambdaForm. + */ + public static MemberName generateCustomizedCode(LambdaForm form, MethodType invokerType) + { + try + { + MemberName memberName = new MemberName(); + memberName._clazz(AnonymousClass.Instance); + memberName._name(form.debugName); + memberName._type(invokerType); + memberName._flags(MethodHandleNatives.Constants.MN_IS_METHOD | MethodHandleNatives.Constants.ACC_STATIC | (MethodHandleNatives.Constants.REF_invokeStatic << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT)); + memberName.vmtarget = new NativeInvokerBytecodeGenerator(form, invokerType).generateCustomizedCodeBytes(); + return memberName; + } +#if DEBUG + catch (BailoutException x) + { + Console.WriteLine(x.Message); + Console.WriteLine("generateCustomizedCode: " + form + ", " + invokerType); + } +#else + catch (BailoutException) + { + } +#endif + return InvokerBytecodeGenerator.generateCustomizedCode(form, invokerType); + } + + /** + * Generate an invoker method for the passed {@link LambdaForm}. + */ + private Delegate generateCustomizedCodeBytes() { + // iterate over the form's names, generating bytecode instructions for each + // start iterating at the first name following the arguments + Name onStack = null; + for (int i = lambdaForm._arity(); i < lambdaForm.names.Length; i++) { + Name name = lambdaForm.names[i]; + + emitStoreResult(onStack); + onStack = name; // unless otherwise modified below + MethodHandleImpl.Intrinsic intr = name.function.intrinsicName(); + switch (intr.name()) { + case "SELECT_ALTERNATIVE": + //assert isSelectAlternative(i); + onStack = emitSelectAlternative(name, lambdaForm.names[i+1]); + i++; // skip MH.invokeBasic of the selectAlternative result + continue; + case "GUARD_WITH_CATCH": + //assert isGuardWithCatch(i); + onStack = emitGuardWithCatch(i); + i = i+2; // Jump to the end of GWC idiom + continue; + case "NEW_ARRAY": + Class rtype = name.function.methodType().returnType(); + if (InvokerBytecodeGenerator.isStaticallyNameable(rtype)) { + emitNewArray(name); + continue; + } + break; + case "ARRAY_LOAD": + emitArrayLoad(name); + continue; + case "IDENTITY": + //assert(name.arguments.length == 1); + emitPushArguments(name); + continue; + case "NONE": + // no intrinsic associated + break; + // [IKVM] ARRAY_STORE and ZERO appear to be unused + default: + throw new BailoutException(Bailout.UnsupportedIntrinsic, "Unknown intrinsic: "+intr); + } + + MemberName member = name.function._member(); + if (isStaticallyInvocable(member)) { + emitStaticInvoke(member, name); + } else { + emitInvoke(name); + } + } + + // return statement + emitReturn(onStack); + + ilgen.DoEmit(); + return dm.CreateDelegate(delegateType, constants.ToArray()); + } + + void emitArrayLoad(Name name) { + OpCode arrayOpcode = OpCodes.Ldelem_Ref; + Class elementType = name.function.methodType().parameterType(0).getComponentType(); + emitPushArguments(name); + if (elementType.isPrimitive()) { + Wrapper w = Wrapper.forPrimitiveType(elementType); + arrayOpcode = arrayLoadOpcode(arrayTypeCode(w)); + } + ilgen.Emit(arrayOpcode); + } + + /** + * Emit an invoke for the given name. + */ + void emitInvoke(Name name) { + //assert(!isLinkerMethodInvoke(name)); // should use the static path for these + if (true) { + // push receiver + MethodHandle target = name.function._resolvedHandle(); + //assert(target != null) : name.exprString(); + //mv.visitLdcInsn(constantPlaceholder(target)); + EmitConstant(target); + emitReferenceCast(CoreClasses.java.lang.invoke.MethodHandle.Wrapper.ClassObject, target); + } else { + // load receiver + //emitAloadInsn(0); + //emitReferenceCast(MethodHandle.class, null); + //mv.visitFieldInsn(Opcodes.GETFIELD, MH, "form", LF_SIG); + //mv.visitFieldInsn(Opcodes.GETFIELD, LF, "names", LFN_SIG); + // TODO more to come + } + + // push arguments + emitPushArguments(name); + + // invocation + MethodType type = name.function.methodType(); + //mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", type.basicType().toMethodDescriptorString(), false); + EmitInvokeBasic(type.basicType()); + } + + static bool isStaticallyInvocable(MemberName member) { + if (member == null) return false; + if (member.isConstructor()) return false; + Class cls = member.getDeclaringClass(); + if (cls.isArray() || cls.isPrimitive()) + return false; // FIXME + /* + if (cls.isAnonymousClass() || cls.isLocalClass()) + return false; // inner class of some sort + if (cls.getClassLoader() != MethodHandle.class.getClassLoader()) + return false; // not on BCP + if (ReflectUtil.isVMAnonymousClass(cls)) // FIXME: switch to supported API once it is added + return false; + MethodType mtype = member.getMethodOrFieldType(); + if (!isStaticallyNameable(mtype.returnType())) + return false; + for (Class ptype : mtype.parameterArray()) + if (!isStaticallyNameable(ptype)) + return false; + if (!member.isPrivate() && VerifyAccess.isSamePackage(MethodHandle.class, cls)) + return true; // in java.lang.invoke package + if (member.isPublic() && isStaticallyNameable(cls)) + return true; + */ + if (member.isMethod()) { + // [IKVM] If we can't call the method directly, invoke it via the invokeBasic infrastructure. + return IsMethodHandleLinkTo(member) + || IsMethodHandleInvokeBasic(member) + || IsStaticallyInvocable(GetMethodWrapper(member)); + } + if (member.isField()) { + // [IKVM] If we can't access the field directly, use the invokeBasic infrastructure. + return IsStaticallyInvocable(GetFieldWrapper(member)); + } + return false; + } + + /* + static boolean isStaticallyNameable(Class cls) { + if (cls == Object.class) + return true; + while (cls.isArray()) + cls = cls.getComponentType(); + if (cls.isPrimitive()) + return true; // int[].class, for example + if (ReflectUtil.isVMAnonymousClass(cls)) // FIXME: switch to supported API once it is added + return false; + // could use VerifyAccess.isClassAccessible but the following is a safe approximation + if (cls.getClassLoader() != Object.class.getClassLoader()) + return false; + if (VerifyAccess.isSamePackage(MethodHandle.class, cls)) + return true; + if (!Modifier.isPublic(cls.getModifiers())) + return false; + for (Class pkgcls : STATICALLY_INVOCABLE_PACKAGES) { + if (VerifyAccess.isSamePackage(pkgcls, cls)) + return true; + } + return false; + } + */ + + void emitStaticInvoke(Name name) { + emitStaticInvoke(name.function._member(), name); + } + + /** + * Emit an invoke for the given name, using the MemberName directly. + */ + void emitStaticInvoke(MemberName member, Name name) { + // push arguments + emitPushArguments(name); + + // invocation + if (member.isMethod()) { + if (IsMethodHandleLinkTo(member)) { + MethodType mt = member.getMethodType(); + TypeWrapper[] args = new TypeWrapper[mt.parameterCount()]; + for (int j = 0; j < args.Length; j++) { + args[j] = TypeWrapper.FromClass(mt.parameterType(j)); + args[j].Finish(); + } + TypeWrapper ret = TypeWrapper.FromClass(mt.returnType()); + ret.Finish(); + Compiler.MethodHandleMethodWrapper.EmitLinkToCall(ilgen, args, ret); + ret.EmitConvSignatureTypeToStackType(ilgen); + } else if (IsMethodHandleInvokeBasic(member)) { + EmitInvokeBasic(member.getMethodType()); + } else { + switch (member.getReferenceKind()) { + case MethodHandleNatives.Constants.REF_invokeInterface: + case MethodHandleNatives.Constants.REF_invokeSpecial: + case MethodHandleNatives.Constants.REF_invokeStatic: + case MethodHandleNatives.Constants.REF_invokeVirtual: + break; + default: + throw new BailoutException(Bailout.UnsupportedRefKind, member); + } + MethodWrapper mw = GetMethodWrapper(member); + if (!IsStaticallyInvocable(mw)) { + throw new BailoutException(Bailout.NotStaticallyInvocable, member); + } + mw.Link(); + mw.DeclaringType.Finish(); + mw.ResolveMethod(); + if (mw.HasCallerID) { + EmitConstant(DynamicCallerIDProvider.Instance); + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicCallerID); + } + if (mw.IsStatic || member.getReferenceKind() == MethodHandleNatives.Constants.REF_invokeSpecial) { + mw.EmitCall(ilgen); + } else { + mw.EmitCallvirt(ilgen); + } + mw.ReturnType.EmitConvSignatureTypeToStackType(ilgen); + } + } else if (member.isField()) { + FieldWrapper fw = GetFieldWrapper(member); + if (!IsStaticallyInvocable(fw)) { + throw new BailoutException(Bailout.NotStaticallyInvocable, member); + } + fw.Link(); + fw.DeclaringType.Finish(); + fw.ResolveField(); + switch (member.getReferenceKind()) { + case MethodHandleNatives.Constants.REF_getField: + case MethodHandleNatives.Constants.REF_getStatic: + fw.EmitGet(ilgen); + fw.FieldTypeWrapper.EmitConvSignatureTypeToStackType(ilgen); + break; + case MethodHandleNatives.Constants.REF_putField: + case MethodHandleNatives.Constants.REF_putStatic: + fw.EmitSet(ilgen); + break; + default: + throw new BailoutException(Bailout.UnsupportedRefKind, member); + } + } else { + throw new BailoutException(Bailout.NotStaticallyInvocable, member); + } + } + + void emitNewArray(Name name) { + Class rtype = name.function.methodType().returnType(); + if (name.arguments.Length == 0) { + // The array will be a constant. + object emptyArray; + try { + emptyArray = name.function._resolvedHandle().invoke(); + } catch (Exception ex) { + throw new java.lang.InternalError(ex); + } + //assert(java.lang.reflect.Array.getLength(emptyArray) == 0); + //assert(emptyArray.getClass() == rtype); // exact typing + //mv.visitLdcInsn(constantPlaceholder(emptyArray)); + EmitConstant(emptyArray); + emitReferenceCast(rtype, emptyArray); + return; + } + Class arrayElementType = rtype.getComponentType(); + //assert(arrayElementType != null); + emitIconstInsn(name.arguments.Length); + OpCode xas = OpCodes.Stelem_Ref; + if (!arrayElementType.isPrimitive()) { + TypeWrapper tw = TypeWrapper.FromClass(arrayElementType); + if (tw.IsUnloadable || tw.IsGhost || tw.IsGhostArray || tw.IsNonPrimitiveValueType) { + throw new BailoutException(Bailout.UnsupportedArrayType, tw); + } + ilgen.Emit(OpCodes.Newarr, tw.TypeAsArrayType); + } else { + byte tc = arrayTypeCode(Wrapper.forPrimitiveType(arrayElementType)); + xas = arrayInsnOpcode(tc); + //mv.visitIntInsn(Opcodes.NEWARRAY, tc); + ilgen.Emit(OpCodes.Newarr, TypeWrapper.FromClass(arrayElementType).TypeAsArrayType); + } + // store arguments + for (int i = 0; i < name.arguments.Length; i++) { + //mv.visitInsn(Opcodes.DUP); + ilgen.Emit(OpCodes.Dup); + emitIconstInsn(i); + emitPushArgument(name, i); + //mv.visitInsn(xas); + ilgen.Emit(xas); + } + // the array is left on the stack + assertStaticType(rtype, name); + } + + /** + * Emit bytecode for the selectAlternative idiom. + * + * The pattern looks like (Cf. MethodHandleImpl.makeGuardWithTest): + *
{@code
+     *   Lambda(a0:L,a1:I)=>{
+     *     t2:I=foo.test(a1:I);
+     *     t3:L=MethodHandleImpl.selectAlternative(t2:I,(MethodHandle(int)int),(MethodHandle(int)int));
+     *     t4:I=MethodHandle.invokeBasic(t3:L,a1:I);t4:I}
+     * }
+ */ + private Name emitSelectAlternative(Name selectAlternativeName, Name invokeBasicName) { + //assert isStaticallyInvocable(invokeBasicName); + + Name receiver = (Name) invokeBasicName.arguments[0]; + + CodeEmitterLabel L_fallback = ilgen.DefineLabel(); + CodeEmitterLabel L_done = ilgen.DefineLabel(); + + // load test result + emitPushArgument(selectAlternativeName, 0); + + // if_icmpne L_fallback + ilgen.EmitBrfalse(L_fallback); + + // invoke selectAlternativeName.arguments[1] + //Class[] preForkClasses = localClasses.clone(); + emitPushArgument(selectAlternativeName, 1); // get 2nd argument of selectAlternative + emitAstoreInsn(receiver.index()); // store the MH in the receiver slot + emitStaticInvoke(invokeBasicName); + + // goto L_done + ilgen.EmitBr(L_done); + + // L_fallback: + ilgen.MarkLabel(L_fallback); + + // invoke selectAlternativeName.arguments[2] + //System.arraycopy(preForkClasses, 0, localClasses, 0, preForkClasses.length); + emitPushArgument(selectAlternativeName, 2); // get 3rd argument of selectAlternative + emitAstoreInsn(receiver.index()); // store the MH in the receiver slot + emitStaticInvoke(invokeBasicName); + + // L_done: + ilgen.MarkLabel(L_done); + // for now do not bother to merge typestate; just reset to the dominator state + //System.arraycopy(preForkClasses, 0, localClasses, 0, preForkClasses.length); + + return invokeBasicName; // return what's on stack + } + + /** + * Emit bytecode for the guardWithCatch idiom. + * + * The pattern looks like (Cf. MethodHandleImpl.makeGuardWithCatch): + *
{@code
+      *  guardWithCatch=Lambda(a0:L,a1:L,a2:L,a3:L,a4:L,a5:L,a6:L,a7:L)=>{
+      *    t8:L=MethodHandle.invokeBasic(a4:L,a6:L,a7:L);
+      *    t9:L=MethodHandleImpl.guardWithCatch(a1:L,a2:L,a3:L,t8:L);
+      *   t10:I=MethodHandle.invokeBasic(a5:L,t9:L);t10:I}
+      * }
+ * + * It is compiled into bytecode equivalent of the following code: + *
{@code
+      *  try {
+      *      return a1.invokeBasic(a6, a7);
+      *  } catch (Throwable e) {
+      *      if (!a2.isInstance(e)) throw e;
+      *      return a3.invokeBasic(ex, a6, a7);
+      *  }}
+      */
+    private Name emitGuardWithCatch(int pos) {
+        Name args    = lambdaForm.names[pos];
+        Name invoker = lambdaForm.names[pos+1];
+        Name result  = lambdaForm.names[pos+2];
+
+        CodeEmitterLabel L_handler = ilgen.DefineLabel();
+        CodeEmitterLabel L_done = ilgen.DefineLabel();
+
+        Class returnType = result.function._resolvedHandle().type().returnType();
+        MethodType type = args.function._resolvedHandle().type()
+                              .dropParameterTypes(0,1)
+                              .changeReturnType(returnType);
+
+        // Normal case
+        ilgen.BeginExceptionBlock();
+        // load target
+        emitPushArgument(invoker, 0);
+        emitPushArguments(args, 1); // skip 1st argument: method handle
+        EmitInvokeBasic(type.basicType());
+        CodeEmitterLocal returnValue = null;
+        if (returnType != java.lang.Void.TYPE) {
+            returnValue = ilgen.DeclareLocal(TypeWrapper.FromClass(returnType).TypeAsLocalOrStackType);
+            ilgen.Emit(OpCodes.Stloc, returnValue);
+        }
+        ilgen.EmitLeave(L_done);
+
+        // Exceptional case
+        ilgen.BeginCatchBlock(typeof(Exception));
+
+        // [IKVM] map the exception and store it in a local and exit the handler
+        ilgen.EmitLdc_I4(0);
+        ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.mapException.MakeGenericMethod(typeof(Exception)));
+        CodeEmitterLocal exception = ilgen.DeclareLocal(typeof(Exception));
+        ilgen.Emit(OpCodes.Stloc, exception);
+        ilgen.EmitLeave(L_handler);
+        ilgen.EndExceptionBlock();
+
+        // Check exception's type
+        ilgen.MarkLabel(L_handler);
+        // load exception class
+        emitPushArgument(invoker, 1);
+        ilgen.Emit(OpCodes.Ldloc, exception);
+        CoreClasses.java.lang.Class.Wrapper.GetMethodWrapper("isInstance", "(Ljava.lang.Object;)Z", false).EmitCall(ilgen);
+        CodeEmitterLabel L_rethrow = ilgen.DefineLabel();
+        ilgen.EmitBrfalse(L_rethrow);
+
+        // Invoke catcher
+        // load catcher
+        emitPushArgument(invoker, 2);
+        ilgen.Emit(OpCodes.Ldloc, exception);
+        emitPushArguments(args, 1); // skip 1st argument: method handle
+        MethodType catcherType = type.insertParameterTypes(0, CoreClasses.java.lang.Throwable.Wrapper.ClassObject);
+        EmitInvokeBasic(catcherType.basicType());
+        if (returnValue != null) {
+            ilgen.Emit(OpCodes.Stloc, returnValue);
+        }
+        ilgen.EmitBr(L_done);
+
+        ilgen.MarkLabel(L_rethrow);
+        ilgen.Emit(OpCodes.Ldloc, exception);
+        ilgen.Emit(OpCodes.Call, Compiler.unmapExceptionMethod);
+        ilgen.Emit(OpCodes.Throw);
+
+        ilgen.MarkLabel(L_done);
+        if (returnValue != null) {
+            ilgen.Emit(OpCodes.Ldloc, returnValue);
+        }
+
+        return result;
+    }
+
+    private void emitPushArguments(Name args) {
+        emitPushArguments(args, 0);
+    }
+
+    private void emitPushArguments(Name args, int start) {
+        for (int i = start; i < args.arguments.Length; i++) {
+            emitPushArgument(args, i);
+        }
+    }
+
+    private void emitPushArgument(Name name, int paramIndex) {
+        object arg = name.arguments[paramIndex];
+        Class ptype = name.function.methodType().parameterType(paramIndex);
+        emitPushArgument(ptype, arg);
+    }
+
+    private void emitPushArgument(Class ptype, object arg) {
+        BasicType bptype = BasicType.basicType(ptype);
+        if (arg is Name) {
+            Name n = (Name)arg;
+            emitLoadInsn(n._type(), n.index());
+            emitImplicitConversion(n._type(), ptype, n);
+        } else if ((arg == null || arg is string) && bptype == BasicType.L_TYPE) {
+            emitConst(arg);
+        } else {
+            if (Wrapper.isWrapperType(ikvm.extensions.ExtensionMethods.getClass(arg)) && bptype != BasicType.L_TYPE) {
+                emitConst(arg);
+            } else {
+                EmitConstant(arg);
+                emitImplicitConversion(BasicType.L_TYPE, ptype, arg);
+            }
+        }
+    }
+
+    /**
+     * Store the name to its local, if necessary.
+     */
+    private void emitStoreResult(Name name) {
+        if (name != null && name._type() != BasicType.V_TYPE) {
+            // non-void: actually assign
+            emitStoreInsn(name._type(), name.index());
+        }
+    }
+
+    /**
+     * Emits a return statement from a LF invoker. If required, the result type is cast to the correct return type.
+     */
+    private void emitReturn(Name onStack) {
+        // return statement
+        Class rclass = invokerType.returnType();
+        BasicType rtype = lambdaForm.returnType();
+        //assert(rtype == basicType(rclass));  // must agree
+        if (rtype == BasicType.V_TYPE) {
+            // [IKVM] unlike the JVM, the CLR doesn't like left over values on the stack
+            if (onStack != null && onStack._type() != BasicType.V_TYPE) {
+                ilgen.Emit(OpCodes.Pop);
+            }
+        } else {
+            LambdaForm.Name rn = lambdaForm.names[lambdaForm.result];
+
+            // put return value on the stack if it is not already there
+            if (rn != onStack) {
+                emitLoadInsn(rtype, lambdaForm.result);
+            }
+
+            emitImplicitConversion(rtype, rclass, rn);
+        }
+        ilgen.Emit(OpCodes.Ret);
+    }
+
+    /**
+     * Emit a type conversion bytecode casting from "from" to "to".
+     */
+    private void emitPrimCast(Wrapper from, Wrapper to) {
+        // Here's how.
+        // -   indicates forbidden
+        // <-> indicates implicit
+        //      to ----> boolean  byte     short    char     int      long     float    double
+        // from boolean    <->        -        -        -        -        -        -        -
+        //      byte        -       <->       i2s      i2c      <->      i2l      i2f      i2d
+        //      short       -       i2b       <->      i2c      <->      i2l      i2f      i2d
+        //      char        -       i2b       i2s      <->      <->      i2l      i2f      i2d
+        //      int         -       i2b       i2s      i2c      <->      i2l      i2f      i2d
+        //      long        -     l2i,i2b   l2i,i2s  l2i,i2c    l2i      <->      l2f      l2d
+        //      float       -     f2i,i2b   f2i,i2s  f2i,i2c    f2i      f2l      <->      f2d
+        //      double      -     d2i,i2b   d2i,i2s  d2i,i2c    d2i      d2l      d2f      <->
+        if (from == to) {
+            // no cast required, should be dead code anyway
+            return;
+        }
+        if (from.isSubwordOrInt()) {
+            // cast from {byte,short,char,int} to anything
+            emitI2X(to);
+        } else {
+            // cast from {long,float,double} to anything
+            if (to.isSubwordOrInt()) {
+                // cast to {byte,short,char,int}
+                emitX2I(from);
+                if (to.bitWidth() < 32) {
+                    // targets other than int require another conversion
+                    emitI2X(to);
+                }
+            } else {
+                // cast to {long,float,double} - this is verbose
+                bool error = false;
+                switch (from.name()) {
+                case "LONG":
+                    switch (to.name()) {
+                    case "FLOAT":   ilgen.Emit(OpCodes.Conv_R4);  break;
+                    case "DOUBLE":  ilgen.Emit(OpCodes.Conv_R8);  break;
+                    default:        error = true;                 break;
+                    }
+                    break;
+                case "FLOAT":
+                    switch (to.name()) {
+                    case "LONG":    ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.f2l); break;
+                    case "DOUBLE":  ilgen.Emit(OpCodes.Conv_R8);  break;
+                    default:        error = true;                 break;
+                    }
+                    break;
+                case "DOUBLE":
+                    switch (to.name()) {
+                    case "LONG" :   ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.d2l); break;
+                    case "FLOAT":   ilgen.Emit(OpCodes.Conv_R4);  break;
+                    default:        error = true;                 break;
+                    }
+                    break;
+                default:
+                    error = true;
+                    break;
+                }
+                if (error) {
+                    throw new BailoutException(Bailout.PreconditionViolated, "unhandled prim cast: " + from + "2" + to);
+                }
+            }
+        }
+    }
+
+    private void emitI2X(Wrapper type) {
+        switch (type.name()) {
+        case "BYTE":    ilgen.Emit(OpCodes.Conv_I1);  break;
+        case "SHORT":   ilgen.Emit(OpCodes.Conv_I2);  break;
+        case "CHAR":    ilgen.Emit(OpCodes.Conv_U2);  break;
+        case "INT":     /* naught */                  break;
+        case "LONG":    ilgen.Emit(OpCodes.Conv_I8);  break;
+        case "FLOAT":   ilgen.Emit(OpCodes.Conv_R4);  break;
+        case "DOUBLE":  ilgen.Emit(OpCodes.Conv_R8);  break;
+        case "BOOLEAN":
+            // For compatibility with ValueConversions and explicitCastArguments:
+            ilgen.EmitLdc_I4(1);
+            ilgen.Emit(OpCodes.And);
+            break;
+        default:   throw new BailoutException(Bailout.PreconditionViolated, "unknown type: " + type);
+        }
+    }
+
+    private void emitX2I(Wrapper type) {
+        switch (type.name()) {
+        case "LONG":    ilgen.Emit(OpCodes.Conv_I4);  break;
+        case "FLOAT":   ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.f2i);  break;
+        case "DOUBLE":  ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.d2i);  break;
+        default:        throw new BailoutException(Bailout.PreconditionViolated, "unknown type: " + type);
+        }
+    }
+
+    private void EmitConstant(object obj)
+    {
+        if (obj == null)
+        {
+            ilgen.Emit(OpCodes.Ldnull);
+            return;
+        }
+        int index = constants.IndexOf(obj);
+        if (index == -1)
+        {
+            index = constants.Count;
+            constants.Add(obj);
+        }
+        ilgen.EmitLdarg(0);	// we want the bound value, not the real first parameter
+        ilgen.EmitLdc_I4(index);
+        ilgen.Emit(OpCodes.Ldelem_Ref);
+    }
+
+    private void EmitInvokeBasic(MethodType mt)
+    {
+        TypeWrapper[] args = new TypeWrapper[mt.parameterCount()];
+        for (int i = 0; i < args.Length; i++)
+        {
+            args[i] = TypeWrapper.FromClass(mt.parameterType(i));
+            args[i].Finish();
+        }
+        TypeWrapper ret = TypeWrapper.FromClass(mt.returnType());
+        ret.Finish();
+        Compiler.MethodHandleMethodWrapper.EmitInvokeBasic(ilgen, args, ret, false);
+    }
+
+    private OpCode arrayLoadOpcode(byte tcode)
+    {
+        switch (tcode)
+        {
+            case Opcodes.T_BOOLEAN:
+            case Opcodes.T_BYTE:
+                return OpCodes.Ldelem_I1;
+            case Opcodes.T_CHAR:
+                return OpCodes.Ldelem_U2;
+            case Opcodes.T_SHORT:
+                return OpCodes.Ldelem_I2;
+            case Opcodes.T_INT:
+                return OpCodes.Ldelem_I4;
+            case Opcodes.T_LONG:
+                return OpCodes.Ldelem_I8;
+            case Opcodes.T_FLOAT:
+                return OpCodes.Ldelem_R4;
+            case Opcodes.T_DOUBLE:
+                return OpCodes.Ldelem_R8;
+            case 0:
+                return OpCodes.Ldelem_Ref;
+            default:
+                throw new BailoutException(Bailout.PreconditionViolated, "tcode = " + tcode);
+        }
+    }
+
+    private static bool IsMethodHandleLinkTo(MemberName member)
+    {
+        return member.getDeclaringClass() == CoreClasses.java.lang.invoke.MethodHandle.Wrapper.ClassObject
+            && member.getName().StartsWith("linkTo", StringComparison.Ordinal);
+    }
+
+    private static bool IsMethodHandleInvokeBasic(MemberName member)
+    {
+        return member.getDeclaringClass() == CoreClasses.java.lang.invoke.MethodHandle.Wrapper.ClassObject
+            && member.getName() == "invokeBasic";
+    }
+
+    private static MethodWrapper GetMethodWrapper(MemberName member)
+    {
+        return TypeWrapper.FromClass(member.getDeclaringClass()).GetMethodWrapper(member.getName(), member.getSignature().Replace('/', '.'), true);
+    }
+
+    private static bool IsStaticallyInvocable(MethodWrapper mw)
+    {
+        if (mw == null || mw.DeclaringType.IsUnloadable || mw.DeclaringType.IsGhost || mw.DeclaringType.IsNonPrimitiveValueType || mw.IsFinalizeOrClone || mw.IsDynamicOnly)
+        {
+            return false;
+        }
+        if (mw.ReturnType.IsUnloadable || mw.ReturnType.IsGhost || mw.ReturnType.IsNonPrimitiveValueType)
+        {
+            return false;
+        }
+        foreach (TypeWrapper tw in mw.GetParameters())
+        {
+            if (tw.IsUnloadable || tw.IsGhost || tw.IsNonPrimitiveValueType)
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static FieldWrapper GetFieldWrapper(MemberName member)
+    {
+        return TypeWrapper.FromClass(member.getDeclaringClass()).GetFieldWrapper(member.getName(), member.getSignature().Replace('/', '.'));
+    }
+
+    private static bool IsStaticallyInvocable(FieldWrapper fw)
+    {
+        return fw != null
+            && !fw.FieldTypeWrapper.IsUnloadable
+            && !fw.FieldTypeWrapper.IsGhost
+            && !fw.FieldTypeWrapper.IsNonPrimitiveValueType;
+    }
+#endif
+}
diff --git a/runtime/openjdk/java.io.cs b/runtime/openjdk/java.io.cs
new file mode 100644
index 0000000..78b51cb
--- /dev/null
+++ b/runtime/openjdk/java.io.cs
@@ -0,0 +1,1562 @@
+/*
+  Copyright (C) 2007-2014 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Reflection;
+using System.Text;
+#if !NO_REF_EMIT
+using System.Reflection.Emit;
+#endif
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.AccessControl;
+using Microsoft.Win32.SafeHandles;
+using IKVM.Internal;
+
+static class Java_java_io_Console
+{
+	public static string encoding()
+	{
+		int cp = 437;
+		try
+		{
+			cp = Console.InputEncoding.CodePage;
+		}
+		catch
+		{
+		}
+		if (cp >= 874 && cp <= 950)
+		{
+			return "ms" + cp;
+		}
+		return "cp" + cp;
+	}
+
+	private const int STD_INPUT_HANDLE = -10;
+	private const int ENABLE_ECHO_INPUT = 0x0004;
+
+	[DllImport("kernel32")]
+	private static extern IntPtr GetStdHandle(int nStdHandle);
+
+	[DllImport("kernel32")]
+	private static extern int GetConsoleMode(IntPtr hConsoleHandle, out int lpMode);
+
+	[DllImport("kernel32")]
+	private static extern int SetConsoleMode(IntPtr hConsoleHandle, int dwMode);
+
+	public static bool echo(bool on)
+	{
+#if !FIRST_PASS
+		// HACK the only way to get this to work is by p/invoking the Win32 APIs
+		if (Environment.OSVersion.Platform == PlatformID.Win32NT)
+		{
+			IntPtr hStdIn = GetStdHandle(STD_INPUT_HANDLE);
+			if (hStdIn.ToInt64() == 0 || hStdIn.ToInt64() == -1)
+			{
+				throw new java.io.IOException("The handle is invalid");
+			}
+			int fdwMode;
+			if (GetConsoleMode(hStdIn, out fdwMode) == 0)
+			{
+				throw new java.io.IOException("GetConsoleMode failed");
+			}
+			bool old = (fdwMode & ENABLE_ECHO_INPUT) != 0;
+			if (on)
+			{
+				fdwMode |= ENABLE_ECHO_INPUT;
+			}
+			else
+			{
+				fdwMode &= ~ENABLE_ECHO_INPUT;
+			}
+			if (SetConsoleMode(hStdIn, fdwMode) == 0)
+			{
+				throw new java.io.IOException("SetConsoleMode failed");
+			}
+			return old;
+		}
+#endif
+		return true;
+	}
+
+	public static bool istty()
+	{
+		// The JDK returns false here if stdin or stdout (not stderr) is redirected to a file
+		// or if there is no console associated with the current process.
+		// The best we can do is to look at the KeyAvailable property, which
+		// will throw an InvalidOperationException if stdin is redirected or not available
+		try
+		{
+			return Console.KeyAvailable || true;
+		}
+		catch (InvalidOperationException)
+		{
+			return false;
+		}
+	}
+}
+
+static class Java_java_io_FileDescriptor
+{
+	private static Converter fsync;
+
+	public static Stream open(string name, FileMode fileMode, FileAccess fileAccess)
+	{
+		if (VirtualFileSystem.IsVirtualFS(name))
+		{
+			return VirtualFileSystem.Open(name, fileMode, fileAccess);
+		}
+		else if (fileMode == FileMode.Append)
+		{
+			// this is the way to get atomic append behavior for all writes
+			return new FileStream(name, fileMode, FileSystemRights.AppendData, FileShare.ReadWrite, 1, FileOptions.None);
+		}
+		else
+		{
+			return new FileStream(name, fileMode, fileAccess, FileShare.ReadWrite, 1, false);
+		}
+	}
+
+	[SecuritySafeCritical]
+	public static bool flushPosix(FileStream fs)
+	{
+		if (fsync == null)
+		{
+			ResolveFSync();
+		}
+		bool success = false;
+		SafeFileHandle handle = fs.SafeFileHandle;
+		RuntimeHelpers.PrepareConstrainedRegions();
+		try
+		{
+			handle.DangerousAddRef(ref success);
+			return fsync(handle.DangerousGetHandle().ToInt32()) == 0;
+		}
+		finally
+		{
+			if (success)
+			{
+				handle.DangerousRelease();
+			}
+		}
+	}
+
+	[SecurityCritical]
+	private static void ResolveFSync()
+	{
+		// we don't want a build time dependency on this Mono assembly, so we use reflection
+		Type type = Type.GetType("Mono.Unix.Native.Syscall, Mono.Posix, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756");
+		if (type != null)
+		{
+			fsync = (Converter)Delegate.CreateDelegate(typeof(Converter), type, "fsync", false, false);
+		}
+		if (fsync == null)
+		{
+			fsync = DummyFSync;
+		}
+	}
+
+	private static int DummyFSync(int fd)
+	{
+		return 0;
+	}
+}
+
+static class Java_java_io_FileInputStream
+{
+	public static void open0(object _this, string name, [In] java.io.FileDescriptor fd)
+	{
+#if !FIRST_PASS
+		fd.openReadOnly(name);
+#endif
+	}
+
+	public static int read0(object _this, [In] java.io.FileDescriptor fd)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		return fd.read();
+#endif
+	}
+
+	public static int readBytes(object _this, byte[] b, int off, int len, [In] java.io.FileDescriptor fd)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		return fd.readBytes(b, off, len);
+#endif
+	}
+
+	public static long skip(object _this, long n, [In] java.io.FileDescriptor fd)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		return fd.skip(n);
+#endif
+	}
+
+	public static int available(object _this, [In] java.io.FileDescriptor fd)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		return fd.available();
+#endif
+	}
+
+	public static void close0(object _this, [In] java.io.FileDescriptor fd)
+	{
+#if !FIRST_PASS
+		fd.close();
+#endif
+	}
+
+	public static void initIDs()
+	{
+	}
+}
+
+static class Java_java_io_FileOutputStream
+{
+	public static void open0(object _this, string name, bool append, [In] java.io.FileDescriptor fd)
+	{
+#if !FIRST_PASS
+		if (append)
+		{
+			fd.openAppend(name);
+		}
+		else
+		{
+			fd.openWriteOnly(name);
+		}
+#endif
+	}
+
+	public static void write(object _this, int b, bool append, [In] java.io.FileDescriptor fd)
+	{
+#if !FIRST_PASS
+		fd.write(b);
+#endif
+	}
+
+	public static void writeBytes(object _this, byte[] b, int off, int len, bool append, [In] java.io.FileDescriptor fd)
+	{
+#if !FIRST_PASS
+		fd.writeBytes(b, off, len);
+#endif
+	}
+
+	public static void close0(object _this, [In] java.io.FileDescriptor fd)
+	{
+#if !FIRST_PASS
+		fd.close();
+#endif
+	}
+
+	public static void initIDs()
+	{
+	}
+}
+
+static class Java_java_io_ObjectInputStream
+{
+	public static void bytesToFloats(byte[] src, int srcpos, float[] dst, int dstpos, int nfloats)
+	{
+		IKVM.Runtime.FloatConverter converter = new IKVM.Runtime.FloatConverter();
+		for (int i = 0; i < nfloats; i++)
+		{
+			int v = src[srcpos++];
+			v = (v << 8) | src[srcpos++];
+			v = (v << 8) | src[srcpos++];
+			v = (v << 8) | src[srcpos++];
+			dst[dstpos++] = IKVM.Runtime.FloatConverter.ToFloat(v, ref converter);
+		}
+	}
+
+	public static void bytesToDoubles(byte[] src, int srcpos, double[] dst, int dstpos, int ndoubles)
+	{
+		IKVM.Runtime.DoubleConverter converter = new IKVM.Runtime.DoubleConverter();
+		for (int i = 0; i < ndoubles; i++)
+		{
+			long v = src[srcpos++];
+			v = (v << 8) | src[srcpos++];
+			v = (v << 8) | src[srcpos++];
+			v = (v << 8) | src[srcpos++];
+			v = (v << 8) | src[srcpos++];
+			v = (v << 8) | src[srcpos++];
+			v = (v << 8) | src[srcpos++];
+			v = (v << 8) | src[srcpos++];
+			dst[dstpos++] = IKVM.Runtime.DoubleConverter.ToDouble(v, ref converter);
+		}
+	}
+}
+
+static class Java_java_io_ObjectOutputStream
+{
+	public static void floatsToBytes(float[] src, int srcpos, byte[] dst, int dstpos, int nfloats)
+	{
+		IKVM.Runtime.FloatConverter converter = new IKVM.Runtime.FloatConverter();
+		for (int i = 0; i < nfloats; i++)
+		{
+			int v = IKVM.Runtime.FloatConverter.ToInt(src[srcpos++], ref converter);
+			dst[dstpos++] = (byte)(v >> 24);
+			dst[dstpos++] = (byte)(v >> 16);
+			dst[dstpos++] = (byte)(v >> 8);
+			dst[dstpos++] = (byte)(v >> 0);
+		}
+	}
+
+	public static void doublesToBytes(double[] src, int srcpos, byte[] dst, int dstpos, int ndoubles)
+	{
+		IKVM.Runtime.DoubleConverter converter = new IKVM.Runtime.DoubleConverter();
+		for (int i = 0; i < ndoubles; i++)
+		{
+			long v = IKVM.Runtime.DoubleConverter.ToLong(src[srcpos++], ref converter);
+			dst[dstpos++] = (byte)(v >> 56);
+			dst[dstpos++] = (byte)(v >> 48);
+			dst[dstpos++] = (byte)(v >> 40);
+			dst[dstpos++] = (byte)(v >> 32);
+			dst[dstpos++] = (byte)(v >> 24);
+			dst[dstpos++] = (byte)(v >> 16);
+			dst[dstpos++] = (byte)(v >> 8);
+			dst[dstpos++] = (byte)(v >> 0);
+		}
+	}
+}
+
+namespace IKVM.Internal
+{
+	public static class IOHelpers
+	{
+		public static void WriteByte(byte[] buf, int offset, byte value)
+		{
+			buf[offset] = value;
+		}
+
+		public static void WriteBoolean(byte[] buf, int offset, bool value)
+		{
+			buf[offset] = value ? (byte)1 : (byte)0;
+		}
+
+		public static void WriteChar(byte[] buf, int offset, char value)
+		{
+			buf[offset + 0] = (byte)(value >> 8);
+			buf[offset + 1] = (byte)(value >> 0);
+		}
+
+		public static void WriteShort(byte[] buf, int offset, short value)
+		{
+			buf[offset + 0] = (byte)(value >> 8);
+			buf[offset + 1] = (byte)(value >> 0);
+		}
+
+		public static void WriteInt(byte[] buf, int offset, int value)
+		{
+			buf[offset + 0] = (byte)(value >> 24);
+			buf[offset + 1] = (byte)(value >> 16);
+			buf[offset + 2] = (byte)(value >> 8);
+			buf[offset + 3] = (byte)(value >> 0);
+		}
+
+		public static void WriteFloat(byte[] buf, int offset, float value)
+		{
+#if !FIRST_PASS
+			java.io.Bits.putFloat(buf, offset, value);
+#endif
+		}
+
+		public static void WriteLong(byte[] buf, int offset, long value)
+		{
+			WriteInt(buf, offset, (int)(value >> 32));
+			WriteInt(buf, offset + 4, (int)value);
+		}
+
+		public static void WriteDouble(byte[] buf, int offset, double value)
+		{
+#if !FIRST_PASS
+			java.io.Bits.putDouble(buf, offset, value);
+#endif
+		}
+
+		public static byte ReadByte(byte[] buf, int offset)
+		{
+			return buf[offset];
+		}
+
+		public static bool ReadBoolean(byte[] buf, int offset)
+		{
+			return buf[offset] != 0;
+		}
+
+		public static char ReadChar(byte[] buf, int offset)
+		{
+			return (char)((buf[offset] << 8) + buf[offset + 1]);
+		}
+
+		public static short ReadShort(byte[] buf, int offset)
+		{
+			return (short)((buf[offset] << 8) + buf[offset + 1]);
+		}
+
+		public static int ReadInt(byte[] buf, int offset)
+		{
+			return (buf[offset + 0] << 24)
+				 + (buf[offset + 1] << 16)
+				 + (buf[offset + 2] << 8)
+				 + (buf[offset + 3] << 0);
+		}
+
+		public static float ReadFloat(byte[] buf, int offset)
+		{
+#if FIRST_PASS
+			return 0;
+#else
+			return java.lang.Float.intBitsToFloat(ReadInt(buf, offset));
+#endif
+		}
+
+		public static long ReadLong(byte[] buf, int offset)
+		{
+			long hi = (uint)ReadInt(buf, offset);
+			long lo = (uint)ReadInt(buf, offset + 4);
+			return lo + (hi << 32);
+		}
+
+		public static double ReadDouble(byte[] buf, int offset)
+		{
+#if FIRST_PASS
+			return 0;
+#else
+			return java.lang.Double.longBitsToDouble(ReadLong(buf, offset));
+#endif
+		}
+	}
+}
+
+static class Java_java_io_ObjectStreamClass
+{
+	public static void initNative()
+	{
+	}
+
+	public static bool isDynamicTypeWrapper(java.lang.Class cl)
+	{
+		TypeWrapper wrapper = TypeWrapper.FromClass(cl);
+		return !wrapper.IsFastClassLiteralSafe;
+	}
+
+	public static bool hasStaticInitializer(java.lang.Class cl)
+	{
+		TypeWrapper wrapper = TypeWrapper.FromClass(cl);
+		try
+		{
+			wrapper.Finish();
+		}
+		catch (RetargetableJavaException x)
+		{
+			throw x.ToJava();
+		}
+		Type type = wrapper.TypeAsTBD;
+		if (!type.IsArray && type.TypeInitializer != null)
+		{
+			wrapper.RunClassInit();
+			return !AttributeHelper.IsHideFromJava(type.TypeInitializer);
+		}
+		return false;
+	}
+
+#if !FIRST_PASS && !NO_REF_EMIT
+	private sealed class FastFieldReflector : ikvm.@internal.FieldReflectorBase
+	{
+		private static readonly MethodInfo ReadByteMethod = typeof(IOHelpers).GetMethod("ReadByte");
+		private static readonly MethodInfo ReadBooleanMethod = typeof(IOHelpers).GetMethod("ReadBoolean");
+		private static readonly MethodInfo ReadCharMethod = typeof(IOHelpers).GetMethod("ReadChar");
+		private static readonly MethodInfo ReadShortMethod = typeof(IOHelpers).GetMethod("ReadShort");
+		private static readonly MethodInfo ReadIntMethod = typeof(IOHelpers).GetMethod("ReadInt");
+		private static readonly MethodInfo ReadFloatMethod = typeof(IOHelpers).GetMethod("ReadFloat");
+		private static readonly MethodInfo ReadLongMethod = typeof(IOHelpers).GetMethod("ReadLong");
+		private static readonly MethodInfo ReadDoubleMethod = typeof(IOHelpers).GetMethod("ReadDouble");
+		private static readonly MethodInfo WriteByteMethod = typeof(IOHelpers).GetMethod("WriteByte");
+		private static readonly MethodInfo WriteBooleanMethod = typeof(IOHelpers).GetMethod("WriteBoolean");
+		private static readonly MethodInfo WriteCharMethod = typeof(IOHelpers).GetMethod("WriteChar");
+		private static readonly MethodInfo WriteShortMethod = typeof(IOHelpers).GetMethod("WriteShort");
+		private static readonly MethodInfo WriteIntMethod = typeof(IOHelpers).GetMethod("WriteInt");
+		private static readonly MethodInfo WriteFloatMethod = typeof(IOHelpers).GetMethod("WriteFloat");
+		private static readonly MethodInfo WriteLongMethod = typeof(IOHelpers).GetMethod("WriteLong");
+		private static readonly MethodInfo WriteDoubleMethod = typeof(IOHelpers).GetMethod("WriteDouble");
+		private delegate void ObjFieldGetterSetter(object obj, object[] objarr);
+		private delegate void PrimFieldGetterSetter(object obj, byte[] objarr);
+		private static readonly ObjFieldGetterSetter objDummy = new ObjFieldGetterSetter(Dummy);
+		private static readonly PrimFieldGetterSetter primDummy = new PrimFieldGetterSetter(Dummy);
+		private java.io.ObjectStreamField[] fields;
+		private ObjFieldGetterSetter objFieldGetter;
+		private PrimFieldGetterSetter primFieldGetter;
+		private ObjFieldGetterSetter objFieldSetter;
+		private PrimFieldGetterSetter primFieldSetter;
+
+		private static void Dummy(object obj, object[] objarr)
+		{
+		}
+
+		private static void Dummy(object obj, byte[] barr)
+		{
+		}
+
+		internal FastFieldReflector(java.io.ObjectStreamField[] fields)
+		{
+			this.fields = fields;
+			TypeWrapper tw = null;
+			foreach (java.io.ObjectStreamField field in fields)
+			{
+				FieldWrapper fw = GetFieldWrapper(field);
+				if (fw != null)
+				{
+					if (tw == null)
+					{
+						tw = fw.DeclaringType;
+					}
+					else if (tw != fw.DeclaringType)
+					{
+						// pre-condition is that all fields are from the same Type!
+						throw new java.lang.InternalError();
+					}
+				}
+			}
+			if (tw == null)
+			{
+				objFieldGetter = objFieldSetter = objDummy;
+				primFieldGetter = primFieldSetter = primDummy;
+			}
+			else
+			{
+				try
+				{
+					tw.Finish();
+				}
+				catch (RetargetableJavaException x)
+				{
+					throw x.ToJava();
+				}
+				DynamicMethod dmObjGetter = DynamicMethodUtils.Create("__", tw.TypeAsBaseType, true, null, new Type[] { typeof(object), typeof(object[]) });
+				DynamicMethod dmPrimGetter = DynamicMethodUtils.Create("__", tw.TypeAsBaseType, true, null, new Type[] { typeof(object), typeof(byte[]) });
+				DynamicMethod dmObjSetter = DynamicMethodUtils.Create("__", tw.TypeAsBaseType, true, null, new Type[] { typeof(object), typeof(object[]) });
+				DynamicMethod dmPrimSetter = DynamicMethodUtils.Create("__", tw.TypeAsBaseType, true, null, new Type[] { typeof(object), typeof(byte[]) });
+				CodeEmitter ilgenObjGetter = CodeEmitter.Create(dmObjGetter);
+				CodeEmitter ilgenPrimGetter = CodeEmitter.Create(dmPrimGetter);
+				CodeEmitter ilgenObjSetter = CodeEmitter.Create(dmObjSetter);
+				CodeEmitter ilgenPrimSetter = CodeEmitter.Create(dmPrimSetter);
+
+				// we want the getters to be verifiable (because writeObject can be used from partial trust),
+				// so we create a local to hold the properly typed object reference
+				CodeEmitterLocal objGetterThis = ilgenObjGetter.DeclareLocal(tw.TypeAsBaseType);
+				CodeEmitterLocal primGetterThis = ilgenPrimGetter.DeclareLocal(tw.TypeAsBaseType);
+				ilgenObjGetter.Emit(OpCodes.Ldarg_0);
+				ilgenObjGetter.Emit(OpCodes.Castclass, tw.TypeAsBaseType);
+				ilgenObjGetter.Emit(OpCodes.Stloc, objGetterThis);
+				ilgenPrimGetter.Emit(OpCodes.Ldarg_0);
+				ilgenPrimGetter.Emit(OpCodes.Castclass, tw.TypeAsBaseType);
+				ilgenPrimGetter.Emit(OpCodes.Stloc, primGetterThis);
+
+				foreach (java.io.ObjectStreamField field in fields)
+				{
+					FieldWrapper fw = GetFieldWrapper(field);
+					if (fw == null)
+					{
+						continue;
+					}
+					fw.ResolveField();
+					TypeWrapper fieldType = fw.FieldTypeWrapper;
+					try
+					{
+						fieldType = fieldType.EnsureLoadable(tw.GetClassLoader());
+						fieldType.Finish();
+					}
+					catch (RetargetableJavaException x)
+					{
+						throw x.ToJava();
+					}
+					if (fieldType.IsPrimitive)
+					{
+						// Getter
+						ilgenPrimGetter.Emit(OpCodes.Ldarg_1);
+						ilgenPrimGetter.EmitLdc_I4(field.getOffset());
+						ilgenPrimGetter.Emit(OpCodes.Ldloc, primGetterThis);
+						fw.EmitGet(ilgenPrimGetter);
+						if (fieldType == PrimitiveTypeWrapper.BYTE)
+						{
+							ilgenPrimGetter.Emit(OpCodes.Call, WriteByteMethod);
+						}
+						else if (fieldType == PrimitiveTypeWrapper.BOOLEAN)
+						{
+							ilgenPrimGetter.Emit(OpCodes.Call, WriteBooleanMethod);
+						}
+						else if (fieldType == PrimitiveTypeWrapper.CHAR)
+						{
+							ilgenPrimGetter.Emit(OpCodes.Call, WriteCharMethod);
+						}
+						else if (fieldType == PrimitiveTypeWrapper.SHORT)
+						{
+							ilgenPrimGetter.Emit(OpCodes.Call, WriteShortMethod);
+						}
+						else if (fieldType == PrimitiveTypeWrapper.INT)
+						{
+							ilgenPrimGetter.Emit(OpCodes.Call, WriteIntMethod);
+						}
+						else if (fieldType == PrimitiveTypeWrapper.FLOAT)
+						{
+							ilgenPrimGetter.Emit(OpCodes.Call, WriteFloatMethod);
+						}
+						else if (fieldType == PrimitiveTypeWrapper.LONG)
+						{
+							ilgenPrimGetter.Emit(OpCodes.Call, WriteLongMethod);
+						}
+						else if (fieldType == PrimitiveTypeWrapper.DOUBLE)
+						{
+							ilgenPrimGetter.Emit(OpCodes.Call, WriteDoubleMethod);
+						}
+						else
+						{
+							throw new java.lang.InternalError();
+						}
+
+						// Setter
+						ilgenPrimSetter.Emit(OpCodes.Ldarg_0);
+						ilgenPrimSetter.Emit(OpCodes.Castclass, tw.TypeAsBaseType);
+						ilgenPrimSetter.Emit(OpCodes.Ldarg_1);
+						ilgenPrimSetter.EmitLdc_I4(field.getOffset());
+						if (fieldType == PrimitiveTypeWrapper.BYTE)
+						{
+							ilgenPrimSetter.Emit(OpCodes.Call, ReadByteMethod);
+						}
+						else if (fieldType == PrimitiveTypeWrapper.BOOLEAN)
+						{
+							ilgenPrimSetter.Emit(OpCodes.Call, ReadBooleanMethod);
+						}
+						else if (fieldType == PrimitiveTypeWrapper.CHAR)
+						{
+							ilgenPrimSetter.Emit(OpCodes.Call, ReadCharMethod);
+						}
+						else if (fieldType == PrimitiveTypeWrapper.SHORT)
+						{
+							ilgenPrimSetter.Emit(OpCodes.Call, ReadShortMethod);
+						}
+						else if (fieldType == PrimitiveTypeWrapper.INT)
+						{
+							ilgenPrimSetter.Emit(OpCodes.Call, ReadIntMethod);
+						}
+						else if (fieldType == PrimitiveTypeWrapper.FLOAT)
+						{
+							ilgenPrimSetter.Emit(OpCodes.Call, ReadFloatMethod);
+						}
+						else if (fieldType == PrimitiveTypeWrapper.LONG)
+						{
+							ilgenPrimSetter.Emit(OpCodes.Call, ReadLongMethod);
+						}
+						else if (fieldType == PrimitiveTypeWrapper.DOUBLE)
+						{
+							ilgenPrimSetter.Emit(OpCodes.Call, ReadDoubleMethod);
+						}
+						else
+						{
+							throw new java.lang.InternalError();
+						}
+						fw.EmitSet(ilgenPrimSetter);
+					}
+					else
+					{
+						// Getter
+						ilgenObjGetter.Emit(OpCodes.Ldarg_1);
+						ilgenObjGetter.EmitLdc_I4(field.getOffset());
+						ilgenObjGetter.Emit(OpCodes.Ldloc, objGetterThis);
+						fw.EmitGet(ilgenObjGetter);
+						fieldType.EmitConvSignatureTypeToStackType(ilgenObjGetter);
+						ilgenObjGetter.Emit(OpCodes.Stelem_Ref);
+
+						// Setter
+						ilgenObjSetter.Emit(OpCodes.Ldarg_0);
+						ilgenObjSetter.Emit(OpCodes.Ldarg_1);
+						ilgenObjSetter.EmitLdc_I4(field.getOffset());
+						ilgenObjSetter.Emit(OpCodes.Ldelem_Ref);
+						fieldType.EmitCheckcast(ilgenObjSetter);
+						fieldType.EmitConvStackTypeToSignatureType(ilgenObjSetter, null);
+						fw.EmitSet(ilgenObjSetter);
+					}
+				}
+				ilgenObjGetter.Emit(OpCodes.Ret);
+				ilgenPrimGetter.Emit(OpCodes.Ret);
+				ilgenObjSetter.Emit(OpCodes.Ret);
+				ilgenPrimSetter.Emit(OpCodes.Ret);
+				ilgenObjGetter.DoEmit();
+				ilgenPrimGetter.DoEmit();
+				ilgenObjSetter.DoEmit();
+				ilgenPrimSetter.DoEmit();
+				objFieldGetter = (ObjFieldGetterSetter)dmObjGetter.CreateDelegate(typeof(ObjFieldGetterSetter));
+				primFieldGetter = (PrimFieldGetterSetter)dmPrimGetter.CreateDelegate(typeof(PrimFieldGetterSetter));
+				objFieldSetter = (ObjFieldGetterSetter)dmObjSetter.CreateDelegate(typeof(ObjFieldGetterSetter));
+				primFieldSetter = (PrimFieldGetterSetter)dmPrimSetter.CreateDelegate(typeof(PrimFieldGetterSetter));
+			}
+		}
+
+		private static FieldWrapper GetFieldWrapper(java.io.ObjectStreamField field)
+		{
+			java.lang.reflect.Field f = field.getField();
+			return f == null ? null : FieldWrapper.FromField(f);
+		}
+
+		public override java.io.ObjectStreamField[] getFields()
+		{
+			return fields;
+		}
+
+		public override void getObjFieldValues(object obj, object[] objarr)
+		{
+			objFieldGetter(obj, objarr);
+		}
+
+		public override void setObjFieldValues(object obj, object[] objarr)
+		{
+			objFieldSetter(obj, objarr);
+		}
+
+		public override void getPrimFieldValues(object obj, byte[] barr)
+		{
+			primFieldGetter(obj, barr);
+		}
+
+		public override void setPrimFieldValues(object obj, byte[] barr)
+		{
+			primFieldSetter(obj, barr);
+		}
+	}
+#endif // !FIRST_PASS && !NO_REF_EMIT
+
+	public static object getFastFieldReflector(java.io.ObjectStreamField[] fieldsObj)
+	{
+#if FIRST_PASS || NO_REF_EMIT
+		return null;
+#else
+		return new FastFieldReflector(fieldsObj);
+#endif
+	}
+}
+
+static class Java_java_io_RandomAccessFile
+{
+	public static void open0(object _this, string name, int mode, [In] java.io.FileDescriptor fd, [In] int O_RDWR)
+	{
+#if !FIRST_PASS
+		if ((mode & O_RDWR) == O_RDWR)
+		{
+			fd.openReadWrite(name);
+		}
+		else
+		{
+			fd.openReadOnly(name);
+		}
+#endif
+	}
+
+	public static int read0(object _this, [In] java.io.FileDescriptor fd)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		return fd.read();
+#endif
+	}
+
+	public static int readBytes(object _this, byte[] b, int off, int len, [In] java.io.FileDescriptor fd)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		return fd.readBytes(b, off, len);
+#endif
+	}
+
+	public static void write0(object _this, int b, [In] java.io.FileDescriptor fd)
+	{
+#if !FIRST_PASS
+		fd.write(b);
+#endif
+	}
+
+	public static void writeBytes(object _this, byte[] b, int off, int len, [In] java.io.FileDescriptor fd)
+	{
+#if !FIRST_PASS
+		fd.writeBytes(b, off, len);
+#endif
+	}
+
+	public static long getFilePointer(object _this, [In] java.io.FileDescriptor fd)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		return fd.getFilePointer();
+#endif
+	}
+
+	public static void seek0(object _this, long pos, [In] java.io.FileDescriptor fd)
+	{
+#if !FIRST_PASS
+		fd.seek(pos);
+#endif
+	}
+
+	public static long length(object _this, [In] java.io.FileDescriptor fd)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		return fd.length();
+#endif
+	}
+
+	public static void setLength(object _this, long newLength, [In] java.io.FileDescriptor fd)
+	{
+#if !FIRST_PASS
+		fd.setLength(newLength);
+#endif
+	}
+
+	public static void close0(object _this, [In] java.io.FileDescriptor fd)
+	{
+#if !FIRST_PASS
+		fd.close();
+#endif
+	}
+
+	public static void initIDs()
+	{
+	}
+}
+
+static class Java_java_io_WinNTFileSystem
+{
+	internal const int ACCESS_READ = 0x04;
+	const int ACCESS_WRITE = 0x02;
+	const int ACCESS_EXECUTE = 0x01;
+
+	public static string getDriveDirectory(object _this, int drive)
+	{
+		try
+		{
+			string path = ((char)('A' + (drive - 1))) + ":";
+			return Path.GetFullPath(path).Substring(2);
+		}
+		catch (ArgumentException)
+		{
+		}
+		catch (SecurityException)
+		{
+		}
+		catch (PathTooLongException)
+		{
+		}
+		return "\\";
+	}
+
+	private static string CanonicalizePath(string path)
+	{
+		try
+		{
+			FileInfo fi = new FileInfo(path);
+			if (fi.DirectoryName == null)
+			{
+				return path.Length > 1 && path[1] == ':'
+					? (Char.ToUpper(path[0]) + ":" + Path.DirectorySeparatorChar)
+					: path;
+			}
+			string dir = CanonicalizePath(fi.DirectoryName);
+			string name = fi.Name;
+			try
+			{
+				if (!VirtualFileSystem.IsVirtualFS(path))
+				{
+					string[] arr = Directory.GetFileSystemEntries(dir, name);
+					if (arr.Length == 1)
+					{
+						name = arr[0];
+					}
+				}
+			}
+			catch (UnauthorizedAccessException)
+			{
+			}
+			catch (IOException)
+			{
+			}
+			return Path.Combine(dir, name);
+		}
+		catch (UnauthorizedAccessException)
+		{
+		}
+		catch (IOException)
+		{
+		}
+		catch (SecurityException)
+		{
+		}
+		catch (NotSupportedException)
+		{
+		}
+		return path;
+	}
+
+	public static string canonicalize0(object _this, string path)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		try
+		{
+			// TODO there is still a known bug here. A dotted path component right after the root component
+			// are not removed as they should be. E.g. "c:\..." => "C:\..." or "\\server\..." => IOException
+			// Another know issue is that when running under Mono on Windows, the case names aren't converted
+			// to the correct (on file system) casing.
+			//
+			// FXBUG we're appending the directory separator to work around an apparent .NET bug.
+			// If we don't do this, "c:\j\." would be canonicalized to "C:\"
+			int colon = path.IndexOf(':', 2);
+			if (colon != -1)
+			{
+				return CanonicalizePath(path.Substring(0, colon) + Path.DirectorySeparatorChar) + path.Substring(colon);
+			}
+			return CanonicalizePath(path + Path.DirectorySeparatorChar);
+		}
+		catch (ArgumentException x)
+		{
+			throw new java.io.IOException(x.Message);
+		}
+#endif
+	}
+
+	public static string canonicalizeWithPrefix0(object _this, string canonicalPrefix, string pathWithCanonicalPrefix)
+	{
+		return canonicalize0(_this, pathWithCanonicalPrefix);
+	}
+
+	private static string GetPathFromFile(java.io.File file)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		return file.getPath();
+#endif
+	}
+
+	public static int getBooleanAttributes(object _this, java.io.File f)
+	{
+		try
+		{
+			string path = GetPathFromFile(f);
+			if (VirtualFileSystem.IsVirtualFS(path))
+			{
+				return VirtualFileSystem.GetBooleanAttributes(path);
+			}
+			FileAttributes attr = File.GetAttributes(path);
+			const int BA_EXISTS = 0x01;
+			const int BA_REGULAR = 0x02;
+			const int BA_DIRECTORY = 0x04;
+			const int BA_HIDDEN = 0x08;
+			int rv = BA_EXISTS;
+			if ((attr & FileAttributes.Directory) != 0)
+			{
+				rv |= BA_DIRECTORY;
+			}
+			else
+			{
+				rv |= BA_REGULAR;
+			}
+			if ((attr & FileAttributes.Hidden) != 0)
+			{
+				rv |= BA_HIDDEN;
+			}
+			return rv;
+		}
+		catch (ArgumentException)
+		{
+		}
+		catch (UnauthorizedAccessException)
+		{
+		}
+		catch (SecurityException)
+		{
+		}
+		catch (NotSupportedException)
+		{
+		}
+		catch (IOException)
+		{
+		}
+		return 0;
+	}
+
+	public static bool checkAccess(object _this, java.io.File f, int access)
+	{
+		string path = GetPathFromFile(f);
+		if (VirtualFileSystem.IsVirtualFS(path))
+		{
+			return VirtualFileSystem.CheckAccess(path, access);
+		}
+		bool ok = true;
+		if ((access & (ACCESS_READ | ACCESS_EXECUTE)) != 0)
+		{
+			ok = false;
+			try
+			{
+				// HACK if path refers to a directory, we always return true
+				if (!Directory.Exists(path))
+				{
+					new FileInfo(path).Open(
+						FileMode.Open,
+						FileAccess.Read,
+						FileShare.ReadWrite).Close();
+				}
+				ok = true;
+			}
+			catch (SecurityException)
+			{
+			}
+			catch (ArgumentException)
+			{
+			}
+			catch (UnauthorizedAccessException)
+			{
+			}
+			catch (IOException)
+			{
+			}
+			catch (NotSupportedException)
+			{
+			}
+		}
+		if (ok && ((access & ACCESS_WRITE) != 0))
+		{
+			ok = false;
+			try
+			{
+				// HACK if path refers to a directory, we always return true
+				if (Directory.Exists(path))
+				{
+					ok = true;
+				}
+				else
+				{
+					FileInfo fileInfo = new FileInfo(path);
+					// Like the JDK we'll only look at the read-only attribute and not
+					// the security permissions associated with the file or directory.
+					ok = (fileInfo.Attributes & FileAttributes.ReadOnly) == 0;
+				}
+			}
+			catch (SecurityException)
+			{
+			}
+			catch (ArgumentException)
+			{
+			}
+			catch (UnauthorizedAccessException)
+			{
+			}
+			catch (IOException)
+			{
+			}
+			catch (NotSupportedException)
+			{
+			}
+		}
+		return ok;
+	}
+
+	private static long DateTimeToJavaLongTime(DateTime datetime)
+	{
+		return (TimeZone.CurrentTimeZone.ToUniversalTime(datetime) - new DateTime(1970, 1, 1)).Ticks / 10000L;
+	}
+
+	private static DateTime JavaLongTimeToDateTime(long datetime)
+	{
+		return TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(new DateTime(1970, 1, 1).Ticks + datetime * 10000L));
+	}
+
+	public static long getLastModifiedTime(object _this, java.io.File f)
+	{
+		try
+		{
+			DateTime dt = File.GetLastWriteTime(GetPathFromFile(f));
+			if (dt.ToFileTime() == 0)
+			{
+				return 0;
+			}
+			else
+			{
+				return DateTimeToJavaLongTime(dt);
+			}
+		}
+		catch (UnauthorizedAccessException)
+		{
+		}
+		catch (ArgumentException)
+		{
+		}
+		catch (IOException)
+		{
+		}
+		catch (NotSupportedException)
+		{
+		}
+		return 0;
+	}
+
+	public static long getLength(object _this, java.io.File f)
+	{
+		try
+		{
+			string path = GetPathFromFile(f);
+			if (VirtualFileSystem.IsVirtualFS(path))
+			{
+				return VirtualFileSystem.GetLength(path);
+			}
+			return new FileInfo(path).Length;
+		}
+		catch (SecurityException)
+		{
+		}
+		catch (ArgumentException)
+		{
+		}
+		catch (UnauthorizedAccessException)
+		{
+		}
+		catch (IOException)
+		{
+		}
+		catch (NotSupportedException)
+		{
+		}
+		return 0;
+	}
+
+	public static bool setPermission(object _this, java.io.File f, int access, bool enable, bool owneronly)
+	{
+		if ((access & ACCESS_WRITE) != 0)
+		{
+			try
+			{
+				FileInfo file = new FileInfo(GetPathFromFile(f));
+				if (enable)
+				{
+					file.Attributes &= ~FileAttributes.ReadOnly;
+				}
+				else
+				{
+					file.Attributes |= FileAttributes.ReadOnly;
+				}
+				return true;
+			}
+			catch (SecurityException)
+			{
+			}
+			catch (ArgumentException)
+			{
+			}
+			catch (UnauthorizedAccessException)
+			{
+			}
+			catch (IOException)
+			{
+			}
+			catch (NotSupportedException)
+			{
+			}
+			return false;
+		}
+		return enable;
+	}
+
+	public static bool createFileExclusively(object _this, string path)
+	{
+#if !FIRST_PASS
+		try
+		{
+			File.Open(path, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None).Close();
+			return true;
+		}
+		catch (ArgumentException x)
+		{
+			throw new java.io.IOException(x.Message);
+		}
+		catch (IOException x)
+		{
+			if (!File.Exists(path) && !Directory.Exists(path))
+			{
+				throw new java.io.IOException(x.Message);
+			}
+		}
+		catch (UnauthorizedAccessException x)
+		{
+			if (!File.Exists(path) && !Directory.Exists(path))
+			{
+				throw new java.io.IOException(x.Message);
+			}
+		}
+		catch (NotSupportedException x)
+		{
+			throw new java.io.IOException(x.Message);
+		}
+#endif
+		return false;
+	}
+
+	public static bool delete0(object _this, java.io.File f)
+	{
+		FileSystemInfo fileInfo = null;
+		try
+		{
+			string path = GetPathFromFile(f);
+			if (Directory.Exists(path))
+			{
+				fileInfo = new DirectoryInfo(path);
+			}
+			else if (File.Exists(path))
+			{
+				fileInfo = new FileInfo(path);
+			}
+			else
+			{
+				return false;
+			}
+			// We need to be able to delete read-only files/dirs too, so we clear
+			// the read-only attribute, if set.
+			if ((fileInfo.Attributes & FileAttributes.ReadOnly) != 0)
+			{
+				fileInfo.Attributes &= ~FileAttributes.ReadOnly;
+			}
+			fileInfo.Delete();
+			return true;
+		}
+		catch (SecurityException)
+		{
+		}
+		catch (ArgumentException)
+		{
+		}
+		catch (UnauthorizedAccessException)
+		{
+		}
+		catch (IOException)
+		{
+		}
+		catch (NotSupportedException)
+		{
+		}
+		return false;
+	}
+
+	public static string[] list(object _this, java.io.File f)
+	{
+		try
+		{
+			string path = GetPathFromFile(f);
+			if (VirtualFileSystem.IsVirtualFS(path))
+			{
+				return VirtualFileSystem.List(path);
+			}
+			string[] l = Directory.GetFileSystemEntries(path);
+			for (int i = 0; i < l.Length; i++)
+			{
+				int pos = l[i].LastIndexOf(Path.DirectorySeparatorChar);
+				if (pos >= 0)
+				{
+					l[i] = l[i].Substring(pos + 1);
+				}
+			}
+			return l;
+		}
+		catch (ArgumentException)
+		{
+		}
+		catch (IOException)
+		{
+		}
+		catch (UnauthorizedAccessException)
+		{
+		}
+		catch (NotSupportedException)
+		{
+		}
+		return null;
+	}
+
+	public static bool createDirectory(object _this, java.io.File f)
+	{
+		try
+		{
+			string path = GetPathFromFile(f);
+			DirectoryInfo parent = Directory.GetParent(path);
+			if (parent == null ||
+				!Directory.Exists(parent.FullName) ||
+				Directory.Exists(path))
+			{
+				return false;
+			}
+			return Directory.CreateDirectory(path) != null;
+		}
+		catch (SecurityException)
+		{
+		}
+		catch (ArgumentException)
+		{
+		}
+		catch (UnauthorizedAccessException)
+		{
+		}
+		catch (IOException)
+		{
+		}
+		catch (NotSupportedException)
+		{
+		}
+		return false;
+	}
+
+	public static bool rename0(object _this, java.io.File f1, java.io.File f2)
+	{
+		try
+		{
+			new FileInfo(GetPathFromFile(f1)).MoveTo(GetPathFromFile(f2));
+			return true;
+		}
+		catch (SecurityException)
+		{
+		}
+		catch (ArgumentException)
+		{
+		}
+		catch (UnauthorizedAccessException)
+		{
+		}
+		catch (IOException)
+		{
+		}
+		catch (NotSupportedException)
+		{
+		}
+		return false;
+	}
+
+	public static bool setLastModifiedTime(object _this, java.io.File f, long time)
+	{
+		try
+		{
+			new FileInfo(GetPathFromFile(f)).LastWriteTime = JavaLongTimeToDateTime(time);
+			return true;
+		}
+		catch (SecurityException)
+		{
+		}
+		catch (ArgumentException)
+		{
+		}
+		catch (UnauthorizedAccessException)
+		{
+		}
+		catch (IOException)
+		{
+		}
+		catch (NotSupportedException)
+		{
+		}
+		return false;
+	}
+
+	public static bool setReadOnly(object _this, java.io.File f)
+	{
+		try
+		{
+			FileInfo fileInfo = new FileInfo(GetPathFromFile(f));
+			fileInfo.Attributes |= FileAttributes.ReadOnly;
+			return true;
+		}
+		catch (SecurityException)
+		{
+		}
+		catch (ArgumentException)
+		{
+		}
+		catch (UnauthorizedAccessException)
+		{
+		}
+		catch (IOException)
+		{
+		}
+		catch (NotSupportedException)
+		{
+		}
+		return false;
+	}
+
+	public static int listRoots0()
+	{
+		try
+		{
+			int drives = 0;
+			foreach (string drive in Environment.GetLogicalDrives())
+			{
+				char c = Char.ToUpper(drive[0]);
+				drives |= 1 << (c - 'A');
+			}
+			return drives;
+		}
+		catch (IOException)
+		{
+		}
+		catch (UnauthorizedAccessException)
+		{
+		}
+		catch (SecurityException)
+		{
+		}
+		return 0;
+	}
+
+	[SecuritySafeCritical]
+	public static long getSpace0(object _this, java.io.File f, int t)
+	{
+#if !FIRST_PASS
+		long freeAvailable;
+		long total;
+		long totalFree;
+		StringBuilder volname = new StringBuilder(256);
+		if (GetVolumePathName(GetPathFromFile(f), volname, volname.Capacity) != 0
+			&& GetDiskFreeSpaceEx(volname.ToString(), out freeAvailable, out total, out totalFree) != 0)
+		{
+			switch (t)
+			{
+				case java.io.FileSystem.SPACE_TOTAL:
+					return total;
+				case java.io.FileSystem.SPACE_FREE:
+					return totalFree;
+				case java.io.FileSystem.SPACE_USABLE:
+					return freeAvailable;
+			}
+		}
+#endif
+		return 0;
+	}
+
+	[DllImport("kernel32")]
+	private static extern int GetDiskFreeSpaceEx(string directory, out long freeAvailable, out long total, out long totalFree);
+
+	[DllImport("kernel32")]
+	private static extern int GetVolumePathName(string lpszFileName, [In, Out] StringBuilder lpszVolumePathName, int cchBufferLength);
+
+	public static void initIDs()
+	{
+	}
+}
+
+static class Java_java_io_UnixFileSystem
+{
+	public static int getBooleanAttributes0(object _this, java.io.File f)
+	{
+		return Java_java_io_WinNTFileSystem.getBooleanAttributes(_this, f);
+	}
+
+	public static long getSpace(object _this, java.io.File f, int t)
+	{
+		// TODO
+		return 0;
+	}
+
+	public static string canonicalize0(object _this, string path)
+	{
+		return Java_java_io_WinNTFileSystem.canonicalize0(_this, path);
+	}
+
+	public static bool checkAccess(object _this, java.io.File f, int access)
+	{
+		return Java_java_io_WinNTFileSystem.checkAccess(_this, f, access);
+	}
+
+	public static long getLastModifiedTime(object _this, java.io.File f)
+	{
+		return Java_java_io_WinNTFileSystem.getLastModifiedTime(_this, f);
+	}
+
+	public static long getLength(object _this, java.io.File f)
+	{
+		return Java_java_io_WinNTFileSystem.getLength(_this, f);
+	}
+
+	public static bool setPermission(object _this, java.io.File f, int access, bool enable, bool owneronly)
+	{
+		// TODO consider using Mono.Posix
+		return Java_java_io_WinNTFileSystem.setPermission(_this, f, access, enable, owneronly);
+	}
+
+	public static bool createFileExclusively(object _this, string path)
+	{
+		return Java_java_io_WinNTFileSystem.createFileExclusively(_this, path);
+	}
+
+	public static bool delete0(object _this, java.io.File f)
+	{
+		return Java_java_io_WinNTFileSystem.delete0(_this, f);
+	}
+
+	public static string[] list(object _this, java.io.File f)
+	{
+		return Java_java_io_WinNTFileSystem.list(_this, f);
+	}
+
+	public static bool createDirectory(object _this, java.io.File f)
+	{
+		return Java_java_io_WinNTFileSystem.createDirectory(_this, f);
+	}
+
+	public static bool rename0(object _this, java.io.File f1, java.io.File f2)
+	{
+		return Java_java_io_WinNTFileSystem.rename0(_this, f1, f2);
+	}
+
+	public static bool setLastModifiedTime(object _this, java.io.File f, long time)
+	{
+		return Java_java_io_WinNTFileSystem.setLastModifiedTime(_this, f, time);
+	}
+
+	public static bool setReadOnly(object _this, java.io.File f)
+	{
+		return Java_java_io_WinNTFileSystem.setReadOnly(_this, f);
+	}
+
+	public static void initIDs()
+	{
+	}
+}
diff --git a/runtime/openjdk/java.lang.cs b/runtime/openjdk/java.lang.cs
new file mode 100644
index 0000000..1879c1b
--- /dev/null
+++ b/runtime/openjdk/java.lang.cs
@@ -0,0 +1,1448 @@
+/*
+  Copyright (C) 2007-2014 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Threading;
+using IKVM.Internal;
+
+static class Java_java_lang_Class
+{
+	public static java.lang.Class forName0(string name, bool initialize, java.lang.ClassLoader loader, java.lang.Class caller)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		//Console.WriteLine("forName: " + name + ", loader = " + loader);
+		TypeWrapper tw = null;
+		if (name.IndexOf(',') > 0)
+		{
+			// we essentially require full trust before allowing arbitrary types to be loaded,
+			// hence we do the "createClassLoader" permission check
+			java.lang.SecurityManager sm = java.lang.System.getSecurityManager();
+			if (sm != null)
+				sm.checkPermission(new java.lang.RuntimePermission("createClassLoader"));
+			Type type = Type.GetType(name);
+			if (type != null)
+			{
+				tw = ClassLoaderWrapper.GetWrapperFromType(type);
+			}
+			if (tw == null)
+			{
+				java.lang.Throwable.suppressFillInStackTrace = true;
+				throw new java.lang.ClassNotFoundException(name);
+			}
+		}
+		else
+		{
+			try
+			{
+				ClassLoaderWrapper classLoaderWrapper = ClassLoaderWrapper.GetClassLoaderWrapper(loader);
+				tw = classLoaderWrapper.LoadClassByDottedName(name);
+			}
+			catch (ClassNotFoundException x)
+			{
+				java.lang.Throwable.suppressFillInStackTrace = true;
+				throw new java.lang.ClassNotFoundException(x.Message);
+			}
+			catch (ClassLoadingException x)
+			{
+				throw x.InnerException;
+			}
+			catch (RetargetableJavaException x)
+			{
+				throw x.ToJava();
+			}
+		}
+		java.security.ProtectionDomain pd;
+		if (loader != null && caller != null && (pd = getProtectionDomain0(caller)) != null)
+		{
+			loader.checkPackageAccess(tw.ClassObject, pd);
+		}
+		if (initialize && !tw.IsArray)
+		{
+			try
+			{
+				tw.Finish();
+			}
+			catch (RetargetableJavaException x)
+			{
+				throw x.ToJava();
+			}
+			tw.RunClassInit();
+		}
+		return tw.ClassObject;
+#endif
+	}
+
+	public static byte[] getRawTypeAnnotations(java.lang.Class thisClass)
+	{
+		return TypeWrapper.FromClass(thisClass).GetRawTypeAnnotations();
+	}
+
+#if !FIRST_PASS
+	private sealed class ConstantPoolImpl : sun.reflect.ConstantPool
+	{
+		private readonly object[] constantPool;
+
+		internal ConstantPoolImpl(object[] constantPool)
+		{
+			this.constantPool = constantPool;
+		}
+
+		public override string getUTF8At(int index)
+		{
+			return (string)constantPool[index];
+		}
+
+		public override int getIntAt(int index)
+		{
+			return (int)constantPool[index];
+		}
+
+		public override long getLongAt(int index)
+		{
+			return (long)constantPool[index];
+		}
+
+		public override float getFloatAt(int index)
+		{
+			return (float)constantPool[index];
+		}
+
+		public override double getDoubleAt(int index)
+		{
+			return (double)constantPool[index];
+		}
+	}
+#endif
+
+    public static object getConstantPool(java.lang.Class thisClass)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		return new ConstantPoolImpl(TypeWrapper.FromClass(thisClass).GetConstantPool());
+#endif
+	}
+
+	public static bool isInstance(java.lang.Class thisClass, object obj)
+	{
+		return TypeWrapper.FromClass(thisClass).IsInstance(obj);
+	}
+
+	public static bool isAssignableFrom(java.lang.Class thisClass, java.lang.Class otherClass)
+	{
+#if !FIRST_PASS
+		if (otherClass == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+#endif
+		return TypeWrapper.FromClass(otherClass).IsAssignableTo(TypeWrapper.FromClass(thisClass));
+	}
+
+	public static bool isInterface(java.lang.Class thisClass)
+	{
+		return TypeWrapper.FromClass(thisClass).IsInterface;
+	}
+
+	public static bool isArray(java.lang.Class thisClass)
+	{
+		return TypeWrapper.FromClass(thisClass).IsArray;
+	}
+
+	public static bool isPrimitive(java.lang.Class thisClass)
+	{
+		return TypeWrapper.FromClass(thisClass).IsPrimitive;
+	}
+
+	public static string getName0(java.lang.Class thisClass)
+	{
+		TypeWrapper tw = TypeWrapper.FromClass(thisClass);
+		if (tw.IsPrimitive)
+		{
+			if (tw == PrimitiveTypeWrapper.BYTE)
+			{
+				return "byte";
+			}
+			else if (tw == PrimitiveTypeWrapper.CHAR)
+			{
+				return "char";
+			}
+			else if (tw == PrimitiveTypeWrapper.DOUBLE)
+			{
+				return "double";
+			}
+			else if (tw == PrimitiveTypeWrapper.FLOAT)
+			{
+				return "float";
+			}
+			else if (tw == PrimitiveTypeWrapper.INT)
+			{
+				return "int";
+			}
+			else if (tw == PrimitiveTypeWrapper.LONG)
+			{
+				return "long";
+			}
+			else if (tw == PrimitiveTypeWrapper.SHORT)
+			{
+				return "short";
+			}
+			else if (tw == PrimitiveTypeWrapper.BOOLEAN)
+			{
+				return "boolean";
+			}
+			else if (tw == PrimitiveTypeWrapper.VOID)
+			{
+				return "void";
+			}
+		}
+		if (tw.IsUnsafeAnonymous)
+		{
+#if !FIRST_PASS
+			// for OpenJDK compatibility and debugging convenience we modify the class name to
+			// include the identity hashcode of the class object
+			return tw.Name + "/" + java.lang.System.identityHashCode(thisClass);
+#endif
+		}
+		return tw.Name;
+	}
+
+	public static string getSigName(java.lang.Class thisClass)
+	{
+		return TypeWrapper.FromClass(thisClass).SigName;
+	}
+
+	public static java.lang.ClassLoader getClassLoader0(java.lang.Class thisClass)
+	{
+		return TypeWrapper.FromClass(thisClass).GetClassLoader().GetJavaClassLoader();
+	}
+
+	public static java.lang.Class getSuperclass(java.lang.Class thisClass)
+	{
+		TypeWrapper super = TypeWrapper.FromClass(thisClass).BaseTypeWrapper;
+		return super != null ? super.ClassObject : null;
+	}
+
+	public static java.lang.Class[] getInterfaces0(java.lang.Class thisClass)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		TypeWrapper[] ifaces = TypeWrapper.FromClass(thisClass).Interfaces;
+		java.lang.Class[] interfaces = new java.lang.Class[ifaces.Length];
+		for (int i = 0; i < ifaces.Length; i++)
+		{
+			interfaces[i] = ifaces[i].ClassObject;
+		}
+		return interfaces;
+#endif
+	}
+
+	public static java.lang.Class getComponentType(java.lang.Class thisClass)
+	{
+		TypeWrapper tw = TypeWrapper.FromClass(thisClass);
+		return tw.IsArray ? tw.ElementTypeWrapper.ClassObject : null;
+	}
+
+	public static int getModifiers(java.lang.Class thisClass)
+	{
+		// the 0x7FFF mask comes from JVM_ACC_WRITTEN_FLAGS in hotspot\src\share\vm\utilities\accessFlags.hpp
+		// masking out ACC_SUPER comes from instanceKlass::compute_modifier_flags() in hotspot\src\share\vm\oops\instanceKlass.cpp
+		const int mask = 0x7FFF & (int)~IKVM.Attributes.Modifiers.Super;
+		return (int)TypeWrapper.FromClass(thisClass).ReflectiveModifiers & mask;
+	}
+
+	public static object[] getSigners(java.lang.Class thisClass)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		return thisClass.signers;
+#endif
+	}
+
+	public static void setSigners(java.lang.Class thisClass, object[] signers)
+	{
+#if !FIRST_PASS
+		thisClass.signers = signers;
+#endif
+	}
+
+	public static object[] getEnclosingMethod0(java.lang.Class thisClass)
+	{
+		try
+		{
+			TypeWrapper tw = TypeWrapper.FromClass(thisClass);
+			tw.Finish();
+			string[] enc = tw.GetEnclosingMethod();
+			if (enc == null)
+			{
+				return null;
+			}
+			return new object[] { tw.GetClassLoader().LoadClassByDottedName(enc[0]).ClassObject, enc[1], enc[2] == null ? null : enc[2].Replace('.', '/') };
+		}
+		catch (RetargetableJavaException x)
+		{
+			throw x.ToJava();
+		}
+	}
+
+	public static java.lang.Class getDeclaringClass0(java.lang.Class thisClass)
+	{
+		try
+		{
+			TypeWrapper wrapper = TypeWrapper.FromClass(thisClass);
+			wrapper.Finish();
+			TypeWrapper decl = wrapper.DeclaringTypeWrapper;
+			if (decl == null)
+			{
+				return null;
+			}
+			decl = decl.EnsureLoadable(wrapper.GetClassLoader());
+			if (!decl.IsAccessibleFrom(wrapper))
+			{
+				throw new IllegalAccessError(string.Format("tried to access class {0} from class {1}", decl.Name, wrapper.Name));
+			}
+			decl.Finish();
+			TypeWrapper[] declInner = decl.InnerClasses;
+			for (int i = 0; i < declInner.Length; i++)
+			{
+				if (declInner[i].Name == wrapper.Name && declInner[i].EnsureLoadable(decl.GetClassLoader()) == wrapper)
+				{
+					return decl.ClassObject;
+				}
+			}
+			throw new IncompatibleClassChangeError(string.Format("{0} and {1} disagree on InnerClasses attribute", decl.Name, wrapper.Name));
+		}
+		catch (RetargetableJavaException x)
+		{
+			throw x.ToJava();
+		}
+	}
+
+	public static java.security.ProtectionDomain getProtectionDomain0(java.lang.Class thisClass)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		TypeWrapper wrapper = TypeWrapper.FromClass(thisClass);
+		if (wrapper.IsArray)
+		{
+			return null;
+		}
+		java.security.ProtectionDomain pd = wrapper.ClassObject.pd;
+		if (pd == null)
+		{
+			// The protection domain for statically compiled code is created lazily (not at java.lang.Class creation time),
+			// to work around boot strap issues.
+			AssemblyClassLoader acl = wrapper.GetClassLoader() as AssemblyClassLoader;
+			if (acl != null)
+			{
+				pd = acl.GetProtectionDomain();
+			}
+			else if (wrapper is AnonymousTypeWrapper)
+			{
+				// dynamically compiled intrinsified lamdba anonymous types end up here and should get their
+				// protection domain from the host class
+				pd = ClassLoaderWrapper.GetWrapperFromType(wrapper.TypeAsTBD.DeclaringType).ClassObject.pd;
+			}
+		}
+		return pd;
+#endif
+	}
+
+	public static java.lang.Class getPrimitiveClass(string name)
+	{
+		// note that this method isn't used anymore (because it is an intrinsic (during core class library compilation))
+		// it still remains for compat because it might be invoked through reflection by evil code
+		switch (name)
+		{
+			case "byte":
+				return PrimitiveTypeWrapper.BYTE.ClassObject;
+			case "char":
+				return PrimitiveTypeWrapper.CHAR.ClassObject;
+			case "double":
+				return PrimitiveTypeWrapper.DOUBLE.ClassObject;
+			case "float":
+				return PrimitiveTypeWrapper.FLOAT.ClassObject;
+			case "int":
+				return PrimitiveTypeWrapper.INT.ClassObject;
+			case "long":
+				return PrimitiveTypeWrapper.LONG.ClassObject;
+			case "short":
+				return PrimitiveTypeWrapper.SHORT.ClassObject;
+			case "boolean":
+				return PrimitiveTypeWrapper.BOOLEAN.ClassObject;
+			case "void":
+				return PrimitiveTypeWrapper.VOID.ClassObject;
+			default:
+				throw new ArgumentException(name);
+		}
+	}
+
+	public static string getGenericSignature0(java.lang.Class thisClass)
+	{
+		TypeWrapper tw = TypeWrapper.FromClass(thisClass);
+		tw.Finish();
+		return tw.GetGenericSignature();
+	}
+
+	internal static object AnnotationsToMap(ClassLoaderWrapper loader, object[] objAnn)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		java.util.LinkedHashMap map = new java.util.LinkedHashMap();
+		if (objAnn != null)
+		{
+			foreach (object obj in objAnn)
+			{
+				java.lang.annotation.Annotation a = obj as java.lang.annotation.Annotation;
+				if (a != null)
+				{
+					map.put(a.annotationType(), FreezeOrWrapAttribute(a));
+				}
+				else if (obj is IKVM.Attributes.DynamicAnnotationAttribute)
+				{
+					a = (java.lang.annotation.Annotation)JVM.NewAnnotation(loader.GetJavaClassLoader(), ((IKVM.Attributes.DynamicAnnotationAttribute)obj).Definition);
+					if (a != null)
+					{
+						map.put(a.annotationType(), a);
+					}
+				}
+			}
+		}
+		return map;
+#endif
+	}
+
+#if !FIRST_PASS
+	internal static java.lang.annotation.Annotation FreezeOrWrapAttribute(java.lang.annotation.Annotation ann)
+	{
+		ikvm.@internal.AnnotationAttributeBase attr = ann as ikvm.@internal.AnnotationAttributeBase;
+		if (attr != null)
+		{
+#if DONT_WRAP_ANNOTATION_ATTRIBUTES
+			attr.freeze();
+#else
+			// freeze to make sure the defaults are set
+			attr.freeze();
+			ann = sun.reflect.annotation.AnnotationParser.annotationForMap(attr.annotationType(), attr.getValues());
+#endif
+		}
+		return ann;
+	}
+#endif
+
+	public static object getDeclaredAnnotationsImpl(java.lang.Class thisClass)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		TypeWrapper wrapper = TypeWrapper.FromClass(thisClass);
+		try
+		{
+			wrapper.Finish();
+		}
+		catch (RetargetableJavaException x)
+		{
+			throw x.ToJava();
+		}
+		return AnnotationsToMap(wrapper.GetClassLoader(), wrapper.GetDeclaredAnnotations());
+#endif
+	}
+
+	public static object getDeclaredFields0(java.lang.Class thisClass, bool publicOnly)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		Profiler.Enter("Class.getDeclaredFields0");
+		try
+		{
+			TypeWrapper wrapper = TypeWrapper.FromClass(thisClass);
+			// we need to finish the type otherwise all fields will not be in the field map yet
+			wrapper.Finish();
+			FieldWrapper[] fields = wrapper.GetFields();
+			List list = new List();
+			for (int i = 0; i < fields.Length; i++)
+			{
+				if (fields[i].IsHideFromReflection)
+				{
+					// skip
+				}
+				else if (publicOnly && !fields[i].IsPublic)
+				{
+					// caller is only asking for public field, so we don't return this non-public field
+				}
+				else
+				{
+					list.Add((java.lang.reflect.Field)fields[i].ToField(false, i));
+				}
+			}
+			return list.ToArray();
+		}
+		catch (RetargetableJavaException x)
+		{
+			throw x.ToJava();
+		}
+		finally
+		{
+			Profiler.Leave("Class.getDeclaredFields0");
+		}
+#endif
+	}
+
+	public static object getDeclaredMethods0(java.lang.Class thisClass, bool publicOnly)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		Profiler.Enter("Class.getDeclaredMethods0");
+		try
+		{
+			TypeWrapper wrapper = TypeWrapper.FromClass(thisClass);
+			wrapper.Finish();
+			if (wrapper.HasVerifyError)
+			{
+				// TODO we should get the message from somewhere
+				throw new VerifyError();
+			}
+			if (wrapper.HasClassFormatError)
+			{
+				// TODO we should get the message from somewhere
+				throw new ClassFormatError(wrapper.Name);
+			}
+			MethodWrapper[] methods = wrapper.GetMethods();
+			List list = new List(methods.Length);
+			for (int i = 0; i < methods.Length; i++)
+			{
+				// we don't want to expose "hideFromReflection" methods (one reason is that it would
+				// mess up the serialVersionUID computation)
+				if (!methods[i].IsHideFromReflection
+					&& !methods[i].IsConstructor
+					&& !methods[i].IsClassInitializer
+					&& (!publicOnly || methods[i].IsPublic))
+				{
+					list.Add((java.lang.reflect.Method)methods[i].ToMethodOrConstructor(false));
+				}
+			}
+			return list.ToArray();
+		}
+		catch (RetargetableJavaException x)
+		{
+			throw x.ToJava();
+		}
+		finally
+		{
+			Profiler.Leave("Class.getDeclaredMethods0");
+		}
+#endif
+	}
+
+	public static object getDeclaredConstructors0(java.lang.Class thisClass, bool publicOnly)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		Profiler.Enter("Class.getDeclaredConstructors0");
+		try
+		{
+			TypeWrapper wrapper = TypeWrapper.FromClass(thisClass);
+			wrapper.Finish();
+			if (wrapper.HasVerifyError)
+			{
+				// TODO we should get the message from somewhere
+				throw new VerifyError();
+			}
+			if (wrapper.HasClassFormatError)
+			{
+				// TODO we should get the message from somewhere
+				throw new ClassFormatError(wrapper.Name);
+			}
+			MethodWrapper[] methods = wrapper.GetMethods();
+			List list = new List();
+			for (int i = 0; i < methods.Length; i++)
+			{
+				// we don't want to expose "hideFromReflection" methods (one reason is that it would
+				// mess up the serialVersionUID computation)
+				if (!methods[i].IsHideFromReflection
+					&& methods[i].IsConstructor
+					&& (!publicOnly || methods[i].IsPublic))
+				{
+					list.Add((java.lang.reflect.Constructor)methods[i].ToMethodOrConstructor(false));
+				}
+			}
+			return list.ToArray();
+		}
+		catch (RetargetableJavaException x)
+		{
+			throw x.ToJava();
+		}
+		finally
+		{
+			Profiler.Leave("Class.getDeclaredConstructors0");
+		}
+#endif
+	}
+
+	public static java.lang.Class[] getDeclaredClasses0(java.lang.Class thisClass)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		try
+		{
+			TypeWrapper wrapper = TypeWrapper.FromClass(thisClass);
+			// NOTE to get at the InnerClasses we need to finish the type
+			wrapper.Finish();
+			TypeWrapper[] wrappers = wrapper.InnerClasses;
+			java.lang.Class[] innerclasses = new java.lang.Class[wrappers.Length];
+			for (int i = 0; i < innerclasses.Length; i++)
+			{
+				TypeWrapper tw = wrappers[i].EnsureLoadable(wrapper.GetClassLoader());
+				if (!tw.IsAccessibleFrom(wrapper))
+				{
+					throw new IllegalAccessError(string.Format("tried to access class {0} from class {1}", tw.Name, wrapper.Name));
+				}
+				tw.Finish();
+				innerclasses[i] = tw.ClassObject;
+			}
+			return innerclasses;
+		}
+		catch (RetargetableJavaException x)
+		{
+			throw x.ToJava();
+		}
+#endif
+	}
+
+	public static bool desiredAssertionStatus0(java.lang.Class clazz)
+	{
+		return IKVM.Runtime.Assertions.IsEnabled(TypeWrapper.FromClass(clazz));
+	}
+}
+
+static class Java_java_lang_ClassLoader
+{
+	public static java.net.URL getBootstrapResource(string name)
+	{
+		foreach (java.net.URL url in ClassLoaderWrapper.GetBootstrapClassLoader().GetResources(name))
+		{
+			return url;
+		}
+		return null;
+	}
+
+	public static java.util.Enumeration getBootstrapResources(string name)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		return new ikvm.runtime.EnumerationWrapper(ClassLoaderWrapper.GetBootstrapClassLoader().GetResources(name));
+#endif
+	}
+
+	public static java.lang.Class defineClass0(java.lang.ClassLoader thisClassLoader, string name, byte[] b, int off, int len, java.security.ProtectionDomain pd)
+	{
+		return defineClass1(thisClassLoader, name, b, off, len, pd, null);
+	}
+
+	public static java.lang.Class defineClass1(java.lang.ClassLoader thisClassLoader, string name, byte[] b, int off, int len, java.security.ProtectionDomain pd, string source)
+	{
+		// it appears the source argument is only used for trace messages in HotSpot. We'll just ignore it for now.
+		Profiler.Enter("ClassLoader.defineClass");
+		try
+		{
+			try
+			{
+				ClassLoaderWrapper classLoaderWrapper = ClassLoaderWrapper.GetClassLoaderWrapper(thisClassLoader);
+				ClassFile classFile = new ClassFile(b, off, len, name, classLoaderWrapper.ClassFileParseOptions, null);
+				if (name != null && classFile.Name != name)
+				{
+#if !FIRST_PASS
+					throw new java.lang.NoClassDefFoundError(name + " (wrong name: " + classFile.Name + ")");
+#endif
+				}
+				TypeWrapper type = classLoaderWrapper.DefineClass(classFile, pd);
+				return type.ClassObject;
+			}
+			catch (RetargetableJavaException x)
+			{
+				throw x.ToJava();
+			}
+		}
+		finally
+		{
+			Profiler.Leave("ClassLoader.defineClass");
+		}
+	}
+
+	public static java.lang.Class defineClass2(java.lang.ClassLoader thisClassLoader, string name, java.nio.ByteBuffer bb, int off, int len, java.security.ProtectionDomain pd, string source)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		byte[] buf = new byte[bb.remaining()];
+		bb.get(buf);
+		return defineClass1(thisClassLoader, name, buf, 0, buf.Length, pd, source);
+#endif
+	}
+
+	public static void resolveClass0(java.lang.ClassLoader thisClassLoader, java.lang.Class clazz)
+	{
+		// no-op
+	}
+
+	public static java.lang.Class findBootstrapClass(java.lang.ClassLoader thisClassLoader, string name)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		TypeWrapper tw;
+		try
+		{
+			tw = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedNameFast(name);
+		}
+		catch (RetargetableJavaException x)
+		{
+			throw x.ToJava();
+		}
+		return tw != null ? tw.ClassObject : null;
+#endif
+	}
+
+	public static java.lang.Class findLoadedClass0(java.lang.ClassLoader thisClassLoader, string name)
+	{
+		if (name == null)
+		{
+			return null;
+		}
+		ClassLoaderWrapper loader = ClassLoaderWrapper.GetClassLoaderWrapper(thisClassLoader);
+		TypeWrapper tw = loader.FindLoadedClass(name);
+		return tw != null ? tw.ClassObject : null;
+	}
+
+	public static object retrieveDirectives()
+	{
+		return IKVM.Runtime.Assertions.RetrieveDirectives();
+	}
+}
+
+static class Java_java_lang_ClassLoader_00024NativeLibrary
+{
+	public static void load(object thisNativeLibrary, string name, bool isBuiltin)
+	{
+#if !FIRST_PASS
+		if (VirtualFileSystem.IsVirtualFS(name))
+		{
+			// we fake success for native libraries loaded from VFS
+			((java.lang.ClassLoader.NativeLibrary)thisNativeLibrary).loaded = true;
+		}
+		else
+		{
+			doLoad(thisNativeLibrary, name);
+		}
+#endif
+	}
+
+#if !FIRST_PASS
+	// we don't want to inline this method, because that would needlessly cause IKVM.Runtime.JNI.dll to be loaded when loading a fake native library from VFS
+	[MethodImpl(MethodImplOptions.NoInlining)]
+	[SecuritySafeCritical]
+	private static void doLoad(object thisNativeLibrary, string name)
+	{
+		java.lang.ClassLoader.NativeLibrary lib = (java.lang.ClassLoader.NativeLibrary)thisNativeLibrary;
+		lib.handle = IKVM.Runtime.JniHelper.LoadLibrary(name, TypeWrapper.FromClass(java.lang.ClassLoader.NativeLibrary.getFromClass()).GetClassLoader());
+		lib.loaded = true;
+	}
+#endif
+
+	public static long find(object thisNativeLibrary, string name)
+	{
+		// TODO
+		throw new NotImplementedException();
+	}
+
+	[SecuritySafeCritical]
+	public static void unload(object thisNativeLibrary, string name, bool isBuiltin)
+	{
+#if !FIRST_PASS
+		java.lang.ClassLoader.NativeLibrary lib = (java.lang.ClassLoader.NativeLibrary)thisNativeLibrary;
+		long handle = Interlocked.Exchange(ref lib.handle, 0);
+		if (handle != 0)
+		{
+			IKVM.Runtime.JniHelper.UnloadLibrary(handle, TypeWrapper.FromClass(java.lang.ClassLoader.NativeLibrary.getFromClass()).GetClassLoader());
+		}
+#endif
+	}
+
+	public static string findBuiltinLib(string name)
+	{
+		return null;
+	}
+}
+
+static class Java_java_lang_Compiler
+{
+	public static void initialize()
+	{
+	}
+
+	public static void registerNatives()
+	{
+	}
+
+	public static bool compileClass(object clazz)
+	{
+		return false;
+	}
+
+	public static bool compileClasses(string str)
+	{
+		return false;
+	}
+
+	public static object command(object any)
+	{
+		return null;
+	}
+
+	public static void enable()
+	{
+	}
+
+	public static void disable()
+	{
+	}
+}
+
+static class Java_java_lang_Double
+{
+	public static long doubleToRawLongBits(double value)
+	{
+		IKVM.Runtime.DoubleConverter converter = new IKVM.Runtime.DoubleConverter();
+		return IKVM.Runtime.DoubleConverter.ToLong(value, ref converter);
+	}
+
+	public static double longBitsToDouble(long bits)
+	{
+		IKVM.Runtime.DoubleConverter converter = new IKVM.Runtime.DoubleConverter();
+		return IKVM.Runtime.DoubleConverter.ToDouble(bits, ref converter);
+	}
+}
+
+static class Java_java_lang_Float
+{
+	public static int floatToRawIntBits(float value)
+	{
+		IKVM.Runtime.FloatConverter converter = new IKVM.Runtime.FloatConverter();
+		return IKVM.Runtime.FloatConverter.ToInt(value, ref converter);
+	}
+
+	public static float intBitsToFloat(int bits)
+	{
+		IKVM.Runtime.FloatConverter converter = new IKVM.Runtime.FloatConverter();
+		return IKVM.Runtime.FloatConverter.ToFloat(bits, ref converter);
+	}
+}
+
+static class Java_java_lang_Package
+{
+	private static Dictionary systemPackages;
+
+	private static void LazyInitSystemPackages()
+	{
+		if (systemPackages == null)
+		{
+			Dictionary dict = new Dictionary();
+			string path = VirtualFileSystem.GetAssemblyResourcesPath(JVM.CoreAssembly) + "resources.jar";
+			foreach (KeyValuePair pkgs in ClassLoaderWrapper.GetBootstrapClassLoader().GetPackageInfo())
+			{
+				foreach (string pkg in pkgs.Value)
+				{
+					dict[pkg.Replace('.', '/') + "/"] = path;
+				}
+			}
+			Interlocked.CompareExchange(ref systemPackages, dict, null);
+		}
+	}
+
+	public static string getSystemPackage0(string name)
+	{
+		LazyInitSystemPackages();
+		string path;
+		systemPackages.TryGetValue(name, out path);
+		return path;
+	}
+
+	public static string[] getSystemPackages0()
+	{
+		LazyInitSystemPackages();
+		string[] pkgs = new string[systemPackages.Count];
+		systemPackages.Keys.CopyTo(pkgs, 0);
+		return pkgs;
+	}
+}
+
+static class Java_java_lang_ProcessEnvironment
+{
+	public static string environmentBlock()
+	{
+		StringBuilder sb = new StringBuilder();
+		foreach (System.Collections.DictionaryEntry de in Environment.GetEnvironmentVariables())
+		{
+			sb.Append(de.Key).Append('=').Append(de.Value).Append('\u0000');
+		}
+		if (sb.Length == 0)
+		{
+			sb.Append('\u0000');
+		}
+		sb.Append('\u0000');
+		return sb.ToString();
+	}
+}
+
+static class Java_java_lang_Runtime
+{
+	public static int availableProcessors(object thisRuntime)
+	{
+		return Environment.ProcessorCount;
+	}
+
+	public static long freeMemory(object thisRuntime)
+	{
+		// TODO figure out if there is anything meaningful we can return here
+		return 10 * 1024 * 1024;
+	}
+
+	public static long totalMemory(object thisRuntime)
+	{
+		// NOTE this really is a bogus number, but we have to return something
+		return GC.GetTotalMemory(false) + freeMemory(thisRuntime);
+	}
+
+	public static long maxMemory(object thisRuntime)
+	{
+		// spec says: If there is no inherent limit then the value Long.MAX_VALUE will be returned.
+		return Int64.MaxValue;
+	}
+
+	public static void gc(object thisRuntime)
+	{
+		GC.Collect();
+	}
+
+	public static void traceInstructions(object thisRuntime, bool on)
+	{
+	}
+
+	public static void traceMethodCalls(object thisRuntime, bool on)
+	{
+	}
+
+	public static void runFinalization0()
+	{
+		GC.WaitForPendingFinalizers();
+	}
+}
+
+static class Java_java_lang_SecurityManager
+{
+	// this field is set by code in the JNI assembly itself,
+	// to prevent having to load the JNI assembly when it isn't used.
+	internal static volatile Assembly jniAssembly;
+
+	public static java.lang.Class[] getClassContext(object thisSecurityManager)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		List stack = new List();
+		StackTrace trace = new StackTrace();
+		for (int i = 0; i < trace.FrameCount; i++)
+		{
+			StackFrame frame = trace.GetFrame(i);
+			MethodBase method = frame.GetMethod();
+			if (Java_sun_reflect_Reflection.IsHideFromStackWalk(method))
+			{
+				continue;
+			}
+			Type type = method.DeclaringType;
+			if (type == typeof(java.lang.SecurityManager))
+			{
+				continue;
+			}
+			stack.Add(ClassLoaderWrapper.GetWrapperFromType(type).ClassObject);
+		}
+		return stack.ToArray();
+#endif
+	}
+
+	public static object currentClassLoader0(object thisSecurityManager)
+	{
+		java.lang.Class currentClass = currentLoadedClass0(thisSecurityManager);
+		if (currentClass != null)
+		{
+			return TypeWrapper.FromClass(currentClass).GetClassLoader().GetJavaClassLoader();
+		}
+		return null;
+	}
+
+	public static int classDepth(object thisSecurityManager, string name)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static int classLoaderDepth0(object thisSecurityManager)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static java.lang.Class currentLoadedClass0(object thisSecurityManager)
+	{
+		throw new NotImplementedException();
+	}
+}
+
+static class Java_java_lang_StrictMath
+{
+	public static double sin(double d)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		return ikvm.@internal.JMath.sin(d);
+#endif
+	}
+
+	public static double cos(double d)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		return ikvm.@internal.JMath.cos(d);
+#endif
+	}
+
+	public static double tan(double d)
+	{
+		return fdlibm.tan(d);
+	}
+
+	public static double asin(double d)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		return ikvm.@internal.JMath.asin(d);
+#endif
+	}
+
+	public static double acos(double d)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		return ikvm.@internal.JMath.acos(d);
+#endif
+	}
+
+	public static double atan(double d)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		return ikvm.@internal.JMath.atan(d);
+#endif
+	}
+
+	public static double exp(double d)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		return ikvm.@internal.JMath.exp(d);
+#endif
+	}
+
+	public static double log(double d)
+	{
+		// FPU behavior is correct
+		return Math.Log(d);
+	}
+
+	public static double log10(double d)
+	{
+		// FPU behavior is correct
+		return Math.Log10(d);
+	}
+
+	public static double sqrt(double d)
+	{
+		// FPU behavior is correct
+		return Math.Sqrt(d);
+	}
+
+	public static double cbrt(double d)
+	{
+		return fdlibm.cbrt(d);
+	}
+
+	public static double IEEEremainder(double f1, double f2)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		return ikvm.@internal.JMath.IEEEremainder(f1, f2);
+#endif
+	}
+
+	public static double atan2(double y, double x)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		return ikvm.@internal.JMath.atan2(y, x);
+#endif
+	}
+
+	public static double pow(double x, double y)
+	{
+		return fdlibm.__ieee754_pow(x, y);
+	}
+
+	public static double sinh(double d)
+	{
+		return Math.Sinh(d);
+	}
+
+	public static double cosh(double d)
+	{
+		return Math.Cosh(d);
+	}
+
+	public static double tanh(double d)
+	{
+		return Math.Tanh(d);
+	}
+
+	public static double hypot(double a, double b)
+	{
+		return fdlibm.__ieee754_hypot(a, b);
+	}
+
+	public static double expm1(double d)
+	{
+		return fdlibm.expm1(d);
+	}
+
+	public static double log1p(double d)
+	{
+		return fdlibm.log1p(d);
+	}
+}
+
+static class Java_java_lang_System
+{
+	public static void registerNatives()
+	{
+	}
+
+	public static void setIn0(object @in)
+	{
+#if !FIRST_PASS
+		java.lang.StdIO.@in = (java.io.InputStream)@in;
+#endif
+	}
+
+	public static void setOut0(object @out)
+	{
+#if !FIRST_PASS
+		java.lang.StdIO.@out = (java.io.PrintStream)@out;
+#endif
+	}
+
+	public static void setErr0(object err)
+	{
+#if !FIRST_PASS
+		java.lang.StdIO.err = (java.io.PrintStream)err;
+#endif
+	}
+
+	public static object initProperties(object props)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		java.lang.VMSystemProperties.initProperties((java.util.Properties)props);
+		return props;
+#endif
+	}
+
+	public static string mapLibraryName(string libname)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		if (libname == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+		if (ikvm.@internal.Util.WINDOWS)
+		{
+			return libname + ".dll";
+		}
+		else if (ikvm.@internal.Util.MACOSX)
+		{
+			return "lib" + libname + ".jnilib";
+		}
+		else
+		{
+			return "lib" + libname + ".so";
+		}
+#endif
+	}
+
+	public static void arraycopy(object src, int srcPos, object dest, int destPos, int length)
+	{
+		IKVM.Runtime.ByteCodeHelper.arraycopy(src, srcPos, dest, destPos, length);
+	}
+}
+
+static class Java_java_lang_Thread
+{
+	private static readonly object mainThreadGroup;
+
+#if !FIRST_PASS
+	static Java_java_lang_Thread()
+	{
+		mainThreadGroup = new java.lang.ThreadGroup(java.lang.ThreadGroup.createRootGroup(), "main");
+	}
+#endif
+
+	public static object getMainThreadGroup()
+	{
+		return mainThreadGroup;
+	}
+
+	// this is called from JniInterface.cs
+	internal static void WaitUntilLastJniThread()
+	{
+#if !FIRST_PASS
+		int count = java.lang.Thread.currentThread().isDaemon() ? 0 : 1;
+		while (Interlocked.CompareExchange(ref java.lang.Thread.nonDaemonCount[0], 0, 0) > count)
+		{
+			Thread.Sleep(1);
+		}
+#endif
+	}
+
+	// this is called from JniInterface.cs
+	internal static void AttachThreadFromJni(object threadGroup)
+	{
+#if !FIRST_PASS
+		if (threadGroup == null)
+		{
+			threadGroup = mainThreadGroup;
+		}
+		if (java.lang.Thread.current == null)
+		{
+			new java.lang.Thread((java.lang.ThreadGroup)threadGroup);
+		}
+#endif
+	}
+
+	public static java.lang.StackTraceElement[] getStackTrace(StackTrace stack)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		List stackTrace = new List();
+		ExceptionHelper.ExceptionInfoHelper.Append(stackTrace, stack, 0, true);
+		return stackTrace.ToArray();
+#endif
+	}
+
+	public static object getThreads()
+	{
+#if FIRST_PASS
+		return null;
+#else
+		return java.security.AccessController.doPrivileged(ikvm.runtime.Delegates.toPrivilegedAction(delegate
+		{
+			java.lang.ThreadGroup root = (java.lang.ThreadGroup)mainThreadGroup;
+			for (; ; )
+			{
+				java.lang.Thread[] threads = new java.lang.Thread[root.activeCount()];
+				if (root.enumerate(threads) == threads.Length)
+				{
+					return threads;
+				}
+			}
+		}));
+#endif
+	}
+}
+
+static class Java_java_lang_ProcessImpl
+{
+	public static string mapVfsExecutable(string path)
+	{
+		string unquoted = path;
+		if (unquoted.Length > 2 && unquoted[0] == '"' && unquoted[unquoted.Length - 1] == '"')
+		{
+			unquoted = unquoted.Substring(1, unquoted.Length - 2);
+		}
+		if (VirtualFileSystem.IsVirtualFS(unquoted))
+		{
+			return VirtualFileSystem.MapExecutable(unquoted);
+		}
+		return path;
+	}
+
+	public static int parseCommandString(string cmdstr)
+	{
+		int pos = cmdstr.IndexOf(' ');
+		if (pos == -1)
+		{
+			return cmdstr.Length;
+		}
+		if (cmdstr[0] == '"')
+		{
+			int close = cmdstr.IndexOf('"', 1);
+			return close == -1 ? cmdstr.Length : close + 1;
+		}
+		if (Environment.OSVersion.Platform != PlatformID.Win32NT)
+		{
+			return pos;
+		}
+		IList path = null;
+		for (; ; )
+		{
+			string str = cmdstr.Substring(0, pos);
+			if (IsPathRooted(str))
+			{
+				if (Exists(str))
+				{
+					return pos;
+				}
+			}
+			else
+			{
+				if (path == null)
+				{
+					path = GetSearchPath();
+				}
+				foreach (string p in path)
+				{
+					if (Exists(Path.Combine(p, str)))
+					{
+						return pos;
+					}
+				}
+			}
+			if (pos == cmdstr.Length)
+			{
+				return cmdstr.IndexOf(' ');
+			}
+			pos = cmdstr.IndexOf(' ', pos + 1);
+			if (pos == -1)
+			{
+				pos = cmdstr.Length;
+			}
+		}
+	}
+
+	private static List GetSearchPath()
+	{
+		List list = new List();
+		list.Add(Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName));
+		list.Add(Environment.CurrentDirectory);
+		list.Add(Environment.SystemDirectory);
+		string windir = Path.GetDirectoryName(Environment.SystemDirectory);
+		list.Add(Path.Combine(windir, "System"));
+		list.Add(windir);
+		string path = Environment.GetEnvironmentVariable("PATH");
+		if (path != null)
+		{
+			foreach (string p in path.Split(Path.PathSeparator))
+			{
+				list.Add(p);
+			}
+		}
+		return list;
+	}
+
+	private static bool IsPathRooted(string path)
+	{
+		try
+		{
+			return Path.IsPathRooted(path);
+		}
+		catch (ArgumentException)
+		{
+			return false;
+		}
+	}
+
+	private static bool Exists(string file)
+	{
+		try
+		{
+			if (File.Exists(file))
+			{
+				return true;
+			}
+			else if (Directory.Exists(file))
+			{
+				return false;
+			}
+			else if (file.IndexOf('.') == -1 && File.Exists(file + ".exe"))
+			{
+				return true;
+			}
+			else if (mapVfsExecutable(file) != file)
+			{
+				return true;
+			}
+			else
+			{
+				return false;
+			}
+		}
+		catch
+		{
+			return false;
+		}
+	}
+}
diff --git a/runtime/openjdk/java.lang.invoke.cs b/runtime/openjdk/java.lang.invoke.cs
new file mode 100644
index 0000000..2f6a318
--- /dev/null
+++ b/runtime/openjdk/java.lang.invoke.cs
@@ -0,0 +1,1278 @@
+/*
+  Copyright (C) 2011-2015 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.CompilerServices;
+using IKVM.Internal;
+using java.lang.invoke;
+using jlClass = java.lang.Class;
+
+static class Java_java_lang_invoke_DirectMethodHandle
+{
+	// this is called from DirectMethodHandle.makeAllocator() via a map.xml prologue patch
+	public static DirectMethodHandle makeStringAllocator(MemberName member)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		// we cannot construct strings via the standard two-pass approach (allocateObject followed by constructor invocation),
+		// so we special case string construction here (to call our static factory method instead)
+		if (member.getDeclaringClass() == CoreClasses.java.lang.String.Wrapper.ClassObject)
+		{
+			MethodType mt = member.getMethodType().changeReturnType(CoreClasses.java.lang.String.Wrapper.ClassObject);
+			return new DirectMethodHandle(mt, DirectMethodHandle._preparedLambdaForm(mt, MethodTypeForm.LF_INVSTATIC), member, null);
+		}
+		return null;
+#endif
+	}
+}
+
+static class Java_java_lang_invoke_MethodHandle
+{
+	public static object invokeExact(MethodHandle thisObject, object[] args)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		return IKVM.Runtime.ByteCodeHelper.GetDelegateForInvokeExact>(thisObject)(args);
+#endif
+	}
+
+	public static object invoke(MethodHandle thisObject, object[] args)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		return thisObject.invokeWithArguments(args);
+#endif
+	}
+
+	public static object invokeBasic(MethodHandle thisObject, object[] args)
+	{
+		throw new InvalidOperationException();
+	}
+
+	public static object linkToVirtual(object[] args)
+	{
+		throw new InvalidOperationException();
+	}
+
+	public static object linkToStatic(object[] args)
+	{
+		throw new InvalidOperationException();
+	}
+
+	public static object linkToSpecial(object[] args)
+	{
+		throw new InvalidOperationException();
+	}
+
+	public static object linkToInterface(object[] args)
+	{
+		throw new InvalidOperationException();
+	}
+}
+
+static class Java_java_lang_invoke_MethodHandleImpl
+{
+	// hooked up via map.xml (as a replacement for makePairwiseConvertByEditor)
+	public static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType, bool strict, bool monobox)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		object[] convSpecs = MethodHandleImpl.computeValueConversions(srcType, target.type(), strict, monobox);
+		List names = new List();
+		names.Add(new LambdaForm.Name(0, LambdaForm.BasicType.L_TYPE));
+		for (int i = 0; i < srcType.parameterCount(); i++)
+		{
+			names.Add(new LambdaForm.Name(i + 1, LambdaForm.BasicType.basicType(srcType.parameterType(i))));
+		}
+		LambdaForm.Name[] invokeArgs = new LambdaForm.Name[srcType.parameterCount()];
+		for (int i = 0; i < invokeArgs.Length; i++)
+		{
+			object convSpec = convSpecs[i];
+			if (convSpec == null)
+			{
+				invokeArgs[i] = names[i + 1];
+			}
+			else
+			{
+				LambdaForm.Name temp = new LambdaForm.Name(convSpec as MethodHandle ?? MethodHandleImpl.Lazy.MH_castReference.bindTo(convSpec), names[i + 1]);
+				names.Add(temp);
+				invokeArgs[i] = temp;
+			}
+		}
+		names.Add(new LambdaForm.Name(target, invokeArgs));
+		if (convSpecs[convSpecs.Length - 1] != null)
+		{
+			object convSpec = convSpecs[convSpecs.Length - 1];
+			if (convSpec != java.lang.Void.TYPE)
+			{
+				names.Add(new LambdaForm.Name(convSpec as MethodHandle ?? MethodHandleImpl.Lazy.MH_castReference.bindTo(convSpec), names[names.Count - 1]));
+			}
+		}
+		if (target.type().returnType() == java.lang.Void.TYPE && srcType.returnType() != java.lang.Void.TYPE)
+		{
+			names.Add(new LambdaForm.Name(LambdaForm.constantZero(LambdaForm.BasicType.basicType(srcType.returnType()))));
+		}
+		LambdaForm form = new LambdaForm("PairwiseConvert", srcType.parameterCount() + 1, names.ToArray(), srcType.returnType() == java.lang.Void.TYPE ? LambdaForm.VOID_RESULT : LambdaForm.LAST_RESULT, false);
+		return new LightWeightMethodHandle(srcType, form);
+#endif
+	}
+}
+
+static class Java_java_lang_invoke_MethodHandleNatives
+{
+	// called from map.xml as a replacement for Class.isInstance() in java.lang.invoke.MethodHandleImpl.castReference()
+	public static bool Class_isInstance(java.lang.Class clazz, object obj)
+	{
+		TypeWrapper tw = TypeWrapper.FromClass(clazz);
+		// handle the type system hole that is caused by arrays being both derived from cli.System.Array and directly from java.lang.Object
+		return tw.IsInstance(obj) || (tw == CoreClasses.cli.System.Object.Wrapper && obj is Array);
+	}
+
+	public static void init(MemberName self, object refObj)
+	{
+		init(self, refObj, false);
+	}
+
+	// this overload is called via a map.xml patch to the MemberName(Method, boolean) constructor, because we need wantSpecial
+	public static void init(MemberName self, object refObj, bool wantSpecial)
+	{
+#if !FIRST_PASS
+		java.lang.reflect.Method method;
+		java.lang.reflect.Constructor constructor;
+		java.lang.reflect.Field field;
+		if ((method = refObj as java.lang.reflect.Method) != null)
+		{
+			InitMethodImpl(self, MethodWrapper.FromExecutable(method), wantSpecial);
+		}
+		else if ((constructor = refObj as java.lang.reflect.Constructor) != null)
+		{
+			InitMethodImpl(self, MethodWrapper.FromExecutable(constructor), wantSpecial);
+		}
+		else if ((field = refObj as java.lang.reflect.Field) != null)
+		{
+			FieldWrapper fw = FieldWrapper.FromField(field);
+			self._clazz(fw.DeclaringType.ClassObject);
+			int flags = (int)fw.Modifiers | MethodHandleNatives.Constants.MN_IS_FIELD;
+			flags |= (fw.IsStatic ? MethodHandleNatives.Constants.REF_getStatic : MethodHandleNatives.Constants.REF_getField) << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT;
+			self._flags(flags);
+		}
+		else
+		{
+			throw new InvalidOperationException();
+		}
+#endif
+	}
+
+	private static void InitMethodImpl(MemberName self, MethodWrapper mw, bool wantSpecial)
+	{
+#if !FIRST_PASS
+		int flags = (int)mw.Modifiers;
+		flags |= mw.IsConstructor ? MethodHandleNatives.Constants.MN_IS_CONSTRUCTOR : MethodHandleNatives.Constants.MN_IS_METHOD;
+		if (mw.IsStatic)
+		{
+			flags |= MethodHandleNatives.Constants.REF_invokeStatic << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT;
+		}
+		else if (mw.IsConstructor && !wantSpecial)
+		{
+			flags |= MethodHandleNatives.Constants.REF_newInvokeSpecial << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT;
+		}
+		else if (mw.IsPrivate || mw.IsFinal || mw.IsConstructor || wantSpecial)
+		{
+			flags |= MethodHandleNatives.Constants.REF_invokeSpecial << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT;
+		}
+		else if (mw.DeclaringType.IsInterface)
+		{
+			flags |= MethodHandleNatives.Constants.REF_invokeInterface << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT;
+		}
+		else
+		{
+			flags |= MethodHandleNatives.Constants.REF_invokeVirtual << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT;
+		}
+		if (mw.HasCallerID || DynamicTypeWrapper.RequiresDynamicReflectionCallerClass(mw.DeclaringType.Name, mw.Name, mw.Signature))
+		{
+			flags |= MemberName.CALLER_SENSITIVE;
+		}
+		if (mw.IsConstructor && mw.DeclaringType == CoreClasses.java.lang.String.Wrapper)
+		{
+			java.lang.Class[] parameters1 = new java.lang.Class[mw.GetParameters().Length];
+			for (int i = 0; i < mw.GetParameters().Length; i++)
+			{
+				parameters1[i] = mw.GetParameters()[i].ClassObject;
+			}
+			MethodType mt = MethodType.methodType(PrimitiveTypeWrapper.VOID.ClassObject, parameters1);
+			self._type(mt);
+			self._flags(flags);
+			self._clazz(mw.DeclaringType.ClassObject);
+			self.vmtarget = CreateMemberNameDelegate(mw, null, false, self.getMethodType().changeReturnType(CoreClasses.java.lang.String.Wrapper.ClassObject));
+			return;
+		}
+		self._flags(flags);
+		self._clazz(mw.DeclaringType.ClassObject);
+		int firstParam = mw.IsStatic ? 0 : 1;
+		java.lang.Class[] parameters = new java.lang.Class[mw.GetParameters().Length + firstParam];
+		for (int i = 0; i < mw.GetParameters().Length; i++)
+		{
+			parameters[i + firstParam] = mw.GetParameters()[i].ClassObject;
+		}
+		if (!mw.IsStatic)
+		{
+			parameters[0] = mw.DeclaringType.ClassObject;
+		}
+		self.vmtarget = CreateMemberNameDelegate(mw, mw.ReturnType.ClassObject, !wantSpecial, MethodType.methodType(mw.ReturnType.ClassObject, parameters));
+#endif
+	}
+
+#if !FIRST_PASS
+	private static void SetModifiers(MemberName self, MemberWrapper mw)
+	{
+		self._flags(self._flags() | (int)mw.Modifiers);
+	}
+#endif
+
+	public static void expand(MemberName self)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static MemberName resolve(MemberName self, java.lang.Class caller)
+	{
+#if !FIRST_PASS
+		switch (self.getReferenceKind())
+		{
+			case MethodHandleNatives.Constants.REF_invokeStatic:
+				if (self.getDeclaringClass() == CoreClasses.java.lang.invoke.MethodHandle.Wrapper.ClassObject)
+				{
+					switch (self.getName())
+					{
+						case "linkToVirtual":
+						case "linkToStatic":
+						case "linkToSpecial":
+						case "linkToInterface":
+							// this delegate is never used normally, only by the PrivateInvokeTest white-box JSR-292 tests
+							self.vmtarget = MethodHandleUtil.DynamicMethodBuilder.CreateMethodHandleLinkTo(self);
+							self._flags(self._flags() | java.lang.reflect.Modifier.STATIC | java.lang.reflect.Modifier.NATIVE | MethodHandleNatives.Constants.MN_IS_METHOD);
+							return self;
+					}
+				}
+				ResolveMethod(self, caller);
+				break;
+			case MethodHandleNatives.Constants.REF_invokeVirtual:
+				if (self.getDeclaringClass() == CoreClasses.java.lang.invoke.MethodHandle.Wrapper.ClassObject)
+				{
+					switch (self.getName())
+					{
+						case "invoke":
+						case "invokeExact":
+						case "invokeBasic":
+							self.vmtarget = MethodHandleUtil.DynamicMethodBuilder.CreateMethodHandleInvoke(self);
+							self._flags(self._flags() | java.lang.reflect.Modifier.NATIVE | java.lang.reflect.Modifier.FINAL | MethodHandleNatives.Constants.MN_IS_METHOD);
+							return self;
+					}
+				}
+				ResolveMethod(self, caller);
+				break;
+			case MethodHandleNatives.Constants.REF_invokeInterface:
+			case MethodHandleNatives.Constants.REF_invokeSpecial:
+			case MethodHandleNatives.Constants.REF_newInvokeSpecial:
+				ResolveMethod(self, caller);
+				break;
+			case MethodHandleNatives.Constants.REF_getField:
+			case MethodHandleNatives.Constants.REF_putField:
+			case MethodHandleNatives.Constants.REF_getStatic:
+			case MethodHandleNatives.Constants.REF_putStatic:
+				ResolveField(self);
+				break;
+			default:
+				throw new InvalidOperationException();
+		}
+#endif
+		return self;
+	}
+
+#if !FIRST_PASS
+	private static void ResolveMethod(MemberName self, java.lang.Class caller)
+	{
+		bool invokeSpecial = self.getReferenceKind() == MethodHandleNatives.Constants.REF_invokeSpecial;
+		bool newInvokeSpecial = self.getReferenceKind() == MethodHandleNatives.Constants.REF_newInvokeSpecial;
+		bool searchBaseClasses = !newInvokeSpecial;
+		MethodWrapper mw = TypeWrapper.FromClass(self.getDeclaringClass()).GetMethodWrapper(self.getName(), self.getSignature().Replace('/', '.'), searchBaseClasses);
+		if (mw == null)
+		{
+			if (self.getReferenceKind() == MethodHandleNatives.Constants.REF_invokeInterface)
+			{
+				mw = TypeWrapper.FromClass(self.getDeclaringClass()).GetInterfaceMethod(self.getName(), self.getSignature().Replace('/', '.'));
+				if (mw == null)
+				{
+					mw = CoreClasses.java.lang.Object.Wrapper.GetMethodWrapper(self.getName(), self.getSignature().Replace('/', '.'), false);
+				}
+				if (mw != null && mw.IsConstructor)
+				{
+					throw new java.lang.IncompatibleClassChangeError("Found interface " + self.getDeclaringClass().getName() + ", but class was expected");
+				}
+			}
+			if (mw == null)
+			{
+				string msg = String.Format(invokeSpecial ? "{0}: method {1}{2} not found" : "{0}.{1}{2}", self.getDeclaringClass().getName(), self.getName(), self.getSignature());
+				throw new java.lang.NoSuchMethodError(msg);
+			}
+		}
+		if (mw.IsStatic != IsReferenceKindStatic(self.getReferenceKind()))
+		{
+			string msg = String.Format(mw.IsStatic ? "Expecting non-static method {0}.{1}{2}" : "Expected static method {0}.{1}{2}", mw.DeclaringType.Name, self.getName(), self.getSignature());
+			throw new java.lang.IncompatibleClassChangeError(msg);
+		}
+		if (self.getReferenceKind() == MethodHandleNatives.Constants.REF_invokeVirtual && mw.DeclaringType.IsInterface)
+		{
+			throw new java.lang.IncompatibleClassChangeError("Found interface " + mw.DeclaringType.Name + ", but class was expected");
+		}
+		if (!mw.IsPublic && self.getReferenceKind() == MethodHandleNatives.Constants.REF_invokeInterface)
+		{
+			throw new java.lang.IncompatibleClassChangeError("private interface method requires invokespecial, not invokeinterface: method " + self.getDeclaringClass().getName() + "." + self.getName() + self.getSignature());
+		}
+		if (mw.IsConstructor && mw.DeclaringType == CoreClasses.java.lang.String.Wrapper)
+		{
+			self.vmtarget = CreateMemberNameDelegate(mw, caller, false, self.getMethodType().changeReturnType(CoreClasses.java.lang.String.Wrapper.ClassObject));
+		}
+		else if (!mw.IsConstructor || invokeSpecial || newInvokeSpecial)
+		{
+			MethodType methodType = self.getMethodType();
+			if (!mw.IsStatic)
+			{
+				methodType = methodType.insertParameterTypes(0, mw.DeclaringType.ClassObject);
+				if (newInvokeSpecial)
+				{
+					methodType = methodType.changeReturnType(java.lang.Void.TYPE);
+				}
+			}
+			self.vmtarget = CreateMemberNameDelegate(mw, caller, self.hasReceiverTypeDispatch(), methodType);
+		}
+		SetModifiers(self, mw);
+		self._flags(self._flags() | (mw.IsConstructor ? MethodHandleNatives.Constants.MN_IS_CONSTRUCTOR : MethodHandleNatives.Constants.MN_IS_METHOD));
+		if (self.getReferenceKind() == MethodHandleNatives.Constants.REF_invokeVirtual && (mw.IsPrivate || mw.IsFinal || mw.IsConstructor))
+		{
+			int flags = self._flags();
+			flags -= MethodHandleNatives.Constants.REF_invokeVirtual << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT;
+			flags += MethodHandleNatives.Constants.REF_invokeSpecial << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT;
+			self._flags(flags);
+		}
+		if (mw.HasCallerID || DynamicTypeWrapper.RequiresDynamicReflectionCallerClass(mw.DeclaringType.Name, mw.Name, mw.Signature))
+		{
+			self._flags(self._flags() | MemberName.CALLER_SENSITIVE);
+		}
+	}
+
+	private static void ResolveField(MemberName self)
+	{
+		FieldWrapper fw = TypeWrapper.FromClass(self.getDeclaringClass()).GetFieldWrapper(self.getName(), self.getSignature().Replace('/', '.'));
+		if (fw == null)
+		{
+			throw new java.lang.NoSuchFieldError(self.getName());
+		}
+		SetModifiers(self, fw);
+		self._flags(self._flags() | MethodHandleNatives.Constants.MN_IS_FIELD);
+		if (fw.IsStatic != IsReferenceKindStatic(self.getReferenceKind()))
+		{
+			int newReferenceKind;
+			switch (self.getReferenceKind())
+			{
+				case MethodHandleNatives.Constants.REF_getField:
+					newReferenceKind = MethodHandleNatives.Constants.REF_getStatic;
+					break;
+				case MethodHandleNatives.Constants.REF_putField:
+					newReferenceKind = MethodHandleNatives.Constants.REF_putStatic;
+					break;
+				case MethodHandleNatives.Constants.REF_getStatic:
+					newReferenceKind = MethodHandleNatives.Constants.REF_getField;
+					break;
+				case MethodHandleNatives.Constants.REF_putStatic:
+					newReferenceKind = MethodHandleNatives.Constants.REF_putField;
+					break;
+				default:
+					throw new InvalidOperationException();
+			}
+			int flags = self._flags();
+			flags -= self.getReferenceKind() << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT;
+			flags += newReferenceKind << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT;
+			self._flags(flags);
+		}
+	}
+	
+	private static bool IsReferenceKindStatic(int referenceKind)
+	{
+		switch (referenceKind)
+		{
+			case MethodHandleNatives.Constants.REF_getField:
+			case MethodHandleNatives.Constants.REF_putField:
+			case MethodHandleNatives.Constants.REF_invokeVirtual:
+			case MethodHandleNatives.Constants.REF_invokeSpecial:
+			case MethodHandleNatives.Constants.REF_newInvokeSpecial:
+			case MethodHandleNatives.Constants.REF_invokeInterface:
+				return false;
+			case MethodHandleNatives.Constants.REF_getStatic:
+			case MethodHandleNatives.Constants.REF_putStatic:
+			case MethodHandleNatives.Constants.REF_invokeStatic:
+				return true;
+		}
+		throw new InvalidOperationException();
+	}
+#endif
+
+	// TODO consider caching this delegate in MethodWrapper
+	private static Delegate CreateMemberNameDelegate(MethodWrapper mw, java.lang.Class caller, bool doDispatch, MethodType type)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		if (mw.IsDynamicOnly)
+		{
+			return MethodHandleUtil.DynamicMethodBuilder.CreateDynamicOnly(mw, type);
+		}
+		// HACK this code is duplicated in compiler.cs
+		if (mw.IsFinalizeOrClone)
+		{
+			TypeWrapper thisType = TypeWrapper.FromClass(caller);
+			// HACK we may need to redirect finalize or clone from java.lang.Object/Throwable
+			// to a more specific base type.
+			if (thisType.IsAssignableTo(CoreClasses.cli.System.Object.Wrapper))
+			{
+				mw = CoreClasses.cli.System.Object.Wrapper.GetMethodWrapper(mw.Name, mw.Signature, true);
+			}
+			else if (thisType.IsAssignableTo(CoreClasses.cli.System.Exception.Wrapper))
+			{
+				mw = CoreClasses.cli.System.Exception.Wrapper.GetMethodWrapper(mw.Name, mw.Signature, true);
+			}
+			else if (thisType.IsAssignableTo(CoreClasses.java.lang.Throwable.Wrapper))
+			{
+				mw = CoreClasses.java.lang.Throwable.Wrapper.GetMethodWrapper(mw.Name, mw.Signature, true);
+			}
+		}
+		TypeWrapper tw = mw.DeclaringType;
+		tw.Finish();
+		mw.Link();
+		mw.ResolveMethod();
+		MethodInfo mi = mw.GetMethod() as MethodInfo;
+		if (mi != null
+			&& !mw.HasCallerID
+			&& mw.IsStatic
+			&& MethodHandleUtil.HasOnlyBasicTypes(mw.GetParameters(), mw.ReturnType)
+			&& type.parameterCount() <= MethodHandleUtil.MaxArity)
+		{
+			return Delegate.CreateDelegate(MethodHandleUtil.CreateMemberWrapperDelegateType(mw.GetParameters(), mw.ReturnType), mi);
+		}
+		else
+		{
+			// slow path where we emit a DynamicMethod
+			return MethodHandleUtil.DynamicMethodBuilder.CreateMemberName(mw, type, doDispatch);
+		}
+#endif
+	}
+
+	public static int getMembers(java.lang.Class defc, string matchName, string matchSig, int matchFlags, java.lang.Class caller, int skip, MemberName[] results)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		if (matchName != null || matchSig != null || matchFlags != MethodHandleNatives.Constants.MN_IS_METHOD)
+		{
+			throw new NotImplementedException();
+		}
+		MethodWrapper[] methods = TypeWrapper.FromClass(defc).GetMethods();
+		for (int i = skip, len = Math.Min(results.Length, methods.Length - skip); i < len; i++)
+		{
+			if (!methods[i].IsConstructor && !methods[i].IsClassInitializer)
+			{
+				results[i - skip] = new MemberName((java.lang.reflect.Method)methods[i].ToMethodOrConstructor(true), false);
+			}
+		}
+		return methods.Length - skip;
+#endif
+	}
+
+	public static long objectFieldOffset(MemberName self)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		java.lang.reflect.Field field = (java.lang.reflect.Field)TypeWrapper.FromClass(self.getDeclaringClass())
+			.GetFieldWrapper(self.getName(), self.getSignature().Replace('/', '.')).ToField(false);
+		return sun.misc.Unsafe.allocateUnsafeFieldId(field);
+#endif
+	}
+
+	public static long staticFieldOffset(MemberName self)
+	{
+		return objectFieldOffset(self);
+	}
+
+	public static object staticFieldBase(MemberName self)
+	{
+		return null;
+	}
+
+#if !FIRST_PASS
+	internal static void InitializeCallSite(CallSite site)
+	{
+		Type type = typeof(IKVM.Runtime.IndyCallSite<>).MakeGenericType(MethodHandleUtil.GetDelegateTypeForInvokeExact(site.type()));
+		IKVM.Runtime.IIndyCallSite ics = (IKVM.Runtime.IIndyCallSite)Activator.CreateInstance(type, true);
+		System.Threading.Interlocked.CompareExchange(ref site.ics, ics, null);
+	}
+#endif
+
+	public static void setCallSiteTargetNormal(CallSite site, MethodHandle target)
+	{
+#if !FIRST_PASS
+		if (site.ics == null)
+		{
+			InitializeCallSite(site);
+		}
+		lock (site.ics)
+		{
+			site.target = target;
+			site.ics.SetTarget(target);
+		}
+#endif
+	}
+
+	public static void setCallSiteTargetVolatile(CallSite site, MethodHandle target)
+	{
+		setCallSiteTargetNormal(site, target);
+	}
+
+	public static void registerNatives()
+	{
+	}
+
+	public static object getMemberVMInfo(MemberName self)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		if (self.isField())
+		{
+			return new object[] { java.lang.Long.valueOf(0), self.getDeclaringClass() };
+		}
+		if (MethodHandleNatives.refKindDoesDispatch(self.getReferenceKind()))
+		{
+			return new object[] { java.lang.Long.valueOf(0), self };
+		}
+		return new object[] { java.lang.Long.valueOf(-1), self };
+#endif
+	}
+
+	public static int getConstant(int which)
+	{
+		return 0;
+	}
+
+	public static int getNamedCon(int which, object[] name)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		FieldInfo[] fields = typeof(MethodHandleNatives.Constants).GetFields(BindingFlags.Static | BindingFlags.NonPublic);
+		if (which >= fields.Length)
+		{
+			name[0] = null;
+			return -1;
+		}
+		name[0] = fields[which].Name;
+		return ((IConvertible)fields[which].GetRawConstantValue()).ToInt32(null);
+#endif
+	}
+}
+
+static partial class MethodHandleUtil
+{
+	internal static Type GetMemberWrapperDelegateType(MethodType type)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		return GetDelegateTypeForInvokeExact(type.basicType());
+#endif
+	}
+
+#if !FIRST_PASS
+	private static Type CreateMethodHandleDelegateType(MethodType type)
+	{
+		TypeWrapper[] args = new TypeWrapper[type.parameterCount()];
+		for (int i = 0; i < args.Length; i++)
+		{
+			args[i] = TypeWrapper.FromClass(type.parameterType(i));
+			args[i].Finish();
+		}
+		TypeWrapper ret = TypeWrapper.FromClass(type.returnType());
+		ret.Finish();
+		return CreateMethodHandleDelegateType(args, ret);
+	}
+
+	private static Type[] GetParameterTypes(MethodBase mb)
+	{
+		ParameterInfo[] pi = mb.GetParameters();
+		Type[] args = new Type[pi.Length];
+		for (int i = 0; i < args.Length; i++)
+		{
+			args[i] = pi[i].ParameterType;
+		}
+		return args;
+	}
+
+	internal static Type[] GetParameterTypes(Type thisType, MethodBase mb)
+	{
+		ParameterInfo[] pi = mb.GetParameters();
+		Type[] args = new Type[pi.Length + 1];
+		args[0] = thisType;
+		for (int i = 1; i < args.Length; i++)
+		{
+			args[i] = pi[i - 1].ParameterType;
+		}
+		return args;
+	}
+
+	internal static MethodType GetDelegateMethodType(Type type)
+	{
+		java.lang.Class[] types;
+		MethodInfo mi = GetDelegateInvokeMethod(type);
+		ParameterInfo[] pi = mi.GetParameters();
+		if (pi.Length > 0 && IsPackedArgsContainer(pi[pi.Length - 1].ParameterType))
+		{
+			System.Collections.Generic.List list = new System.Collections.Generic.List();
+			for (int i = 0; i < pi.Length - 1; i++)
+			{
+				list.Add(ClassLoaderWrapper.GetWrapperFromType(pi[i].ParameterType).ClassObject);
+			}
+			Type[] args = pi[pi.Length - 1].ParameterType.GetGenericArguments();
+			while (IsPackedArgsContainer(args[args.Length - 1]))
+			{
+				for (int i = 0; i < args.Length - 1; i++)
+				{
+					list.Add(ClassLoaderWrapper.GetWrapperFromType(args[i]).ClassObject);
+				}
+				args = args[args.Length - 1].GetGenericArguments();
+			}
+			for (int i = 0; i < args.Length; i++)
+			{
+				list.Add(ClassLoaderWrapper.GetWrapperFromType(args[i]).ClassObject);
+			}
+			types = list.ToArray();
+		}
+		else
+		{
+			types = new java.lang.Class[pi.Length];
+			for (int i = 0; i < types.Length; i++)
+			{
+				types[i] = ClassLoaderWrapper.GetWrapperFromType(pi[i].ParameterType).ClassObject;
+			}
+		}
+		return MethodType.methodType(ClassLoaderWrapper.GetWrapperFromType(mi.ReturnType).ClassObject, types);
+	}
+
+	internal sealed class DynamicMethodBuilder
+	{
+		private readonly MethodType type;
+		private readonly int firstArg;
+		private readonly Type delegateType;
+		private readonly object firstBoundValue;
+		private readonly object secondBoundValue;
+		private readonly Type container;
+		private readonly DynamicMethod dm;
+		private readonly CodeEmitter ilgen;
+		private readonly Type packedArgType;
+		private readonly int packedArgPos;
+
+		sealed class Container
+		{
+			public T1 target;
+			public T2 value;
+
+			public Container(T1 target, T2 value)
+			{
+				this.target = target;
+				this.value = value;
+			}
+		}
+
+		private DynamicMethodBuilder(string name, MethodType type, Type container, object target, object value, Type owner, bool useBasicTypes)
+		{
+			this.type = type;
+			this.delegateType = useBasicTypes ? GetMemberWrapperDelegateType(type) : GetDelegateTypeForInvokeExact(type);
+			this.firstBoundValue = target;
+			this.secondBoundValue = value;
+			this.container = container;
+			MethodInfo mi = GetDelegateInvokeMethod(delegateType);
+			Type[] paramTypes;
+			if (container != null)
+			{
+				this.firstArg = 1;
+				paramTypes = GetParameterTypes(container, mi);
+			}
+			else if (target != null)
+			{
+				this.firstArg = 1;
+				paramTypes = GetParameterTypes(target.GetType(), mi);
+			}
+			else
+			{
+				paramTypes = GetParameterTypes(mi);
+			}
+			if (!ReflectUtil.CanOwnDynamicMethod(owner))
+			{
+				owner = typeof(DynamicMethodBuilder);
+			}
+			this.dm = new DynamicMethod(name, mi.ReturnType, paramTypes, owner, true);
+			this.ilgen = CodeEmitter.Create(dm);
+
+			if (type.parameterCount() > MaxArity)
+			{
+				ParameterInfo[] pi = mi.GetParameters();
+				this.packedArgType = pi[pi.Length - 1].ParameterType;
+				this.packedArgPos = pi.Length - 1 + firstArg;
+			}
+			else
+			{
+				this.packedArgPos = Int32.MaxValue;
+			}
+		}
+
+		internal static Delegate CreateVoidAdapter(MethodType type)
+		{
+			DynamicMethodBuilder dm = new DynamicMethodBuilder("VoidAdapter", type.changeReturnType(java.lang.Void.TYPE), null, null, null, null, true);
+			Type targetDelegateType = GetMemberWrapperDelegateType(type);
+			dm.Ldarg(0);
+			dm.EmitCheckcast(CoreClasses.java.lang.invoke.MethodHandle.Wrapper);
+			dm.ilgen.Emit(OpCodes.Ldfld, typeof(MethodHandle).GetField("form", BindingFlags.Instance | BindingFlags.NonPublic));
+			dm.ilgen.Emit(OpCodes.Ldfld, typeof(LambdaForm).GetField("vmentry", BindingFlags.Instance | BindingFlags.NonPublic));
+			dm.ilgen.Emit(OpCodes.Ldfld, typeof(MemberName).GetField("vmtarget", BindingFlags.Instance | BindingFlags.NonPublic));
+			dm.ilgen.Emit(OpCodes.Castclass, targetDelegateType);
+			for (int i = 0; i < type.parameterCount(); i++)
+			{
+				dm.Ldarg(i);
+			}
+			dm.CallDelegate(targetDelegateType);
+			dm.ilgen.Emit(OpCodes.Pop);
+			dm.Ret();
+			return dm.CreateDelegate();
+		}
+
+		internal static DynamicMethod CreateInvokeExact(MethodType type)
+		{
+			FinishTypes(type);
+			DynamicMethodBuilder dm = new DynamicMethodBuilder("InvokeExact", type, typeof(MethodHandle), null, null, null, false);
+			Type targetDelegateType = GetMemberWrapperDelegateType(type.insertParameterTypes(0, CoreClasses.java.lang.invoke.MethodHandle.Wrapper.ClassObject));
+			dm.ilgen.Emit(OpCodes.Ldarg_0);
+			dm.ilgen.Emit(OpCodes.Ldfld, typeof(MethodHandle).GetField("form", BindingFlags.Instance | BindingFlags.NonPublic));
+			dm.ilgen.Emit(OpCodes.Ldfld, typeof(LambdaForm).GetField("vmentry", BindingFlags.Instance | BindingFlags.NonPublic));
+			if (type.returnType() == java.lang.Void.TYPE)
+			{
+				dm.ilgen.Emit(OpCodes.Call, typeof(MethodHandleUtil).GetMethod("GetVoidAdapter", BindingFlags.Static | BindingFlags.NonPublic));
+			}
+			else
+			{
+				dm.ilgen.Emit(OpCodes.Ldfld, typeof(MemberName).GetField("vmtarget", BindingFlags.Instance | BindingFlags.NonPublic));
+			}
+			dm.ilgen.Emit(OpCodes.Castclass, targetDelegateType);
+			dm.ilgen.Emit(OpCodes.Ldarg_0);
+			for (int i = 0; i < type.parameterCount(); i++)
+			{
+				dm.Ldarg(i);
+				TypeWrapper tw = TypeWrapper.FromClass(type.parameterType(i));
+				if (tw.IsNonPrimitiveValueType)
+				{
+					tw.EmitBox(dm.ilgen);
+				}
+				else if (tw.IsGhost)
+				{
+					tw.EmitConvSignatureTypeToStackType(dm.ilgen);
+				}
+				else if (tw == PrimitiveTypeWrapper.BYTE)
+				{
+					dm.ilgen.Emit(OpCodes.Conv_I1);
+				}
+			}
+			dm.CallDelegate(targetDelegateType);
+			TypeWrapper retType = TypeWrapper.FromClass(type.returnType());
+			if (retType.IsNonPrimitiveValueType)
+			{
+				retType.EmitUnbox(dm.ilgen);
+			}
+			else if (retType.IsGhost)
+			{
+				retType.EmitConvStackTypeToSignatureType(dm.ilgen, null);
+			}
+			else if (!retType.IsPrimitive && retType != CoreClasses.java.lang.Object.Wrapper)
+			{
+				dm.EmitCheckcast(retType);
+			}
+			dm.Ret();
+			dm.ilgen.DoEmit();
+			return dm.dm;
+		}
+
+		internal static Delegate CreateMethodHandleLinkTo(MemberName mn)
+		{
+			MethodType type = mn.getMethodType();
+			Type delegateType = MethodHandleUtil.GetMemberWrapperDelegateType(type.dropParameterTypes(type.parameterCount() - 1, type.parameterCount()));
+			DynamicMethodBuilder dm = new DynamicMethodBuilder("DirectMethodHandle." + mn.getName() + type, type, null, null, null, null, true);
+			dm.Ldarg(type.parameterCount() - 1);
+			dm.ilgen.EmitCastclass(typeof(java.lang.invoke.MemberName));
+			dm.ilgen.Emit(OpCodes.Ldfld, typeof(java.lang.invoke.MemberName).GetField("vmtarget", BindingFlags.Instance | BindingFlags.NonPublic));
+			dm.ilgen.Emit(OpCodes.Castclass, delegateType);
+			for (int i = 0, count = type.parameterCount() - 1; i < count; i++)
+			{
+				dm.Ldarg(i);
+			}
+			dm.CallDelegate(delegateType);
+			dm.Ret();
+			return dm.CreateDelegate();
+		}
+
+		internal static Delegate CreateMethodHandleInvoke(MemberName mn)
+		{
+			MethodType type = mn.getMethodType().insertParameterTypes(0, mn.getDeclaringClass());
+			Type targetDelegateType = MethodHandleUtil.GetMemberWrapperDelegateType(type);
+			DynamicMethodBuilder dm = new DynamicMethodBuilder("DirectMethodHandle." + mn.getName() + type, type,
+				typeof(Container<,>).MakeGenericType(typeof(object), typeof(IKVM.Runtime.InvokeCache<>).MakeGenericType(targetDelegateType)), null, null, null, true);
+			dm.Ldarg(0);
+			dm.EmitCheckcast(CoreClasses.java.lang.invoke.MethodHandle.Wrapper);
+			switch (mn.getName())
+			{
+				case "invokeExact":
+					dm.Call(ByteCodeHelperMethods.GetDelegateForInvokeExact.MakeGenericMethod(targetDelegateType));
+					break;
+				case "invoke":
+					dm.LoadValueAddress();
+					dm.Call(ByteCodeHelperMethods.GetDelegateForInvoke.MakeGenericMethod(targetDelegateType));
+					break;
+				case "invokeBasic":
+					dm.Call(ByteCodeHelperMethods.GetDelegateForInvokeBasic.MakeGenericMethod(targetDelegateType));
+					break;
+				default:
+					throw new InvalidOperationException();
+			}
+			dm.Ldarg(0);
+			for (int i = 1, count = type.parameterCount(); i < count; i++)
+			{
+				dm.Ldarg(i);
+			}
+			dm.CallDelegate(targetDelegateType);
+			dm.Ret();
+			return dm.CreateDelegate();
+		}
+
+		internal static Delegate CreateDynamicOnly(MethodWrapper mw, MethodType type)
+		{
+			FinishTypes(type);
+			DynamicMethodBuilder dm = new DynamicMethodBuilder("CustomInvoke:" + mw.Name, type, null, mw, null, null, true);
+			dm.ilgen.Emit(OpCodes.Ldarg_0);
+			if (mw.IsStatic)
+			{
+				dm.LoadNull();
+				dm.BoxArgs(0);
+			}
+			else
+			{
+				dm.Ldarg(0);
+				dm.BoxArgs(1);
+			}
+			dm.Callvirt(typeof(MethodWrapper).GetMethod("Invoke", BindingFlags.Instance | BindingFlags.NonPublic));
+			dm.UnboxReturnValue();
+			dm.Ret();
+			return dm.CreateDelegate();
+		}
+
+		internal static Delegate CreateMemberName(MethodWrapper mw, MethodType type, bool doDispatch)
+		{
+			FinishTypes(type);
+			TypeWrapper tw = mw.DeclaringType;
+			Type owner = tw.TypeAsBaseType;
+#if NET_4_0
+			if (!doDispatch && !mw.IsStatic)
+			{
+				// on .NET 4 we can only do a non-virtual invocation of a virtual method if we skip verification,
+				// and to skip verification we need to inject the dynamic method in a critical assembly
+
+				// TODO instead of injecting in mscorlib, we should use DynamicMethodUtils.Create()
+				owner = typeof(object);
+			}
+#endif
+			DynamicMethodBuilder dm = new DynamicMethodBuilder("MemberName:" + mw.DeclaringType.Name + "::" + mw.Name + mw.Signature, type, null,
+				mw.HasCallerID ? DynamicCallerIDProvider.Instance : null, null, owner, true);
+			for (int i = 0, count = type.parameterCount(); i < count; i++)
+			{
+				if (i == 0 && !mw.IsStatic && (tw.IsGhost || tw.IsNonPrimitiveValueType || tw.IsRemapped) && (!mw.IsConstructor || tw != CoreClasses.java.lang.String.Wrapper))
+				{
+					if (tw.IsGhost || tw.IsNonPrimitiveValueType)
+					{
+						dm.LoadFirstArgAddress(tw);
+					}
+					else
+					{
+						Debug.Assert(tw.IsRemapped);
+						// TODO this must be checked
+						dm.Ldarg(0);
+						if (mw.IsConstructor)
+						{
+							dm.EmitCastclass(tw.TypeAsBaseType);
+						}
+						else if (tw != CoreClasses.cli.System.Object.Wrapper)
+						{
+							dm.EmitCheckcast(tw);
+						}
+					}
+				}
+				else
+				{
+					dm.Ldarg(i);
+					TypeWrapper argType = TypeWrapper.FromClass(type.parameterType(i));
+					if (!argType.IsPrimitive)
+					{
+						if (argType.IsUnloadable)
+						{
+						}
+						else if (argType.IsNonPrimitiveValueType)
+						{
+							dm.Unbox(argType);
+						}
+						else if (argType.IsGhost)
+						{
+							dm.UnboxGhost(argType);
+						}
+						else
+						{
+							dm.EmitCheckcast(argType);
+						}
+					}
+				}
+			}
+			if (mw.HasCallerID)
+			{
+				dm.LoadCallerID();
+			}
+			// special case for Object.clone() and Object.finalize()
+			if (mw.IsFinalizeOrClone)
+			{
+				if (doDispatch)
+				{
+					mw.EmitCallvirtReflect(dm.ilgen);
+				}
+				else
+				{
+					// we can re-use the implementations from cli.System.Object (even though the object may not in-fact extend cli.System.Object)
+					CoreClasses.cli.System.Object.Wrapper.GetMethodWrapper(mw.Name, mw.Signature, false).EmitCall(dm.ilgen);
+				}
+			}
+			else if (doDispatch && !mw.IsStatic)
+			{
+				dm.Callvirt(mw);
+			}
+			else
+			{
+				dm.Call(mw);
+			}
+			TypeWrapper retType = TypeWrapper.FromClass(type.returnType());
+			if (retType.IsUnloadable)
+			{
+			}
+			else if (retType.IsNonPrimitiveValueType)
+			{
+				dm.Box(retType);
+			}
+			else if (retType.IsGhost)
+			{
+				dm.BoxGhost(retType);
+			}
+			else if (retType == PrimitiveTypeWrapper.BYTE)
+			{
+				dm.CastByte();
+			}
+			dm.Ret();
+			return dm.CreateDelegate();
+		}
+
+		internal void Call(MethodInfo method)
+		{
+			ilgen.Emit(OpCodes.Call, method);
+		}
+
+		internal void Callvirt(MethodInfo method)
+		{
+			ilgen.Emit(OpCodes.Callvirt, method);
+		}
+
+		internal void Call(MethodWrapper mw)
+		{
+			mw.EmitCall(ilgen);
+		}
+
+		internal void Callvirt(MethodWrapper mw)
+		{
+			mw.EmitCallvirt(ilgen);
+		}
+
+		internal void CallDelegate(Type delegateType)
+		{
+			EmitCallDelegateInvokeMethod(ilgen, delegateType);
+		}
+
+		internal void LoadFirstArgAddress(TypeWrapper tw)
+		{
+			ilgen.EmitLdarg(0);
+			if (tw.IsGhost)
+			{
+				tw.EmitConvStackTypeToSignatureType(ilgen, null);
+				CodeEmitterLocal local = ilgen.DeclareLocal(tw.TypeAsSignatureType);
+				ilgen.Emit(OpCodes.Stloc, local);
+				ilgen.Emit(OpCodes.Ldloca, local);
+			}
+			else if (tw.IsNonPrimitiveValueType)
+			{
+				ilgen.Emit(OpCodes.Unbox, tw.TypeAsSignatureType);
+			}
+			else
+			{
+				throw new InvalidOperationException();
+			}
+		}
+
+		internal void Ldarg(int i)
+		{
+			LoadPackedArg(ilgen, i, firstArg, packedArgPos, packedArgType);
+		}
+
+		internal void LoadCallerID()
+		{
+			ilgen.Emit(OpCodes.Ldarg_0);
+			ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicCallerID);
+		}
+
+		internal void LoadValueAddress()
+		{
+			ilgen.Emit(OpCodes.Ldarg_0);
+			ilgen.Emit(OpCodes.Ldflda, container.GetField("value"));
+		}
+
+		internal void Ret()
+		{
+			ilgen.Emit(OpCodes.Ret);
+		}
+
+		internal Delegate CreateDelegate()
+		{
+			//Console.WriteLine(delegateType);
+			//ilgen.DumpMethod();
+			ilgen.DoEmit();
+			return ValidateDelegate(firstArg == 0
+				? dm.CreateDelegate(delegateType)
+				: dm.CreateDelegate(delegateType, container == null ? firstBoundValue : Activator.CreateInstance(container, firstBoundValue, secondBoundValue)));
+		}
+
+		internal void BoxArgs(int start)
+		{
+			int paramCount = type.parameterCount();
+			ilgen.EmitLdc_I4(paramCount - start);
+			ilgen.Emit(OpCodes.Newarr, Types.Object);
+			for (int i = start; i < paramCount; i++)
+			{
+				ilgen.Emit(OpCodes.Dup);
+				ilgen.EmitLdc_I4(i - start);
+				Ldarg(i);
+				TypeWrapper tw = TypeWrapper.FromClass(type.parameterType(i));
+				if (tw.IsPrimitive)
+				{
+					ilgen.Emit(OpCodes.Box, tw.TypeAsSignatureType);
+				}
+				ilgen.Emit(OpCodes.Stelem_Ref);
+			}
+		}
+
+		internal void UnboxReturnValue()
+		{
+			TypeWrapper tw = TypeWrapper.FromClass(type.returnType());
+			if (tw == PrimitiveTypeWrapper.VOID)
+			{
+				ilgen.Emit(OpCodes.Pop);
+			}
+			else if (tw.IsPrimitive)
+			{
+				ilgen.Emit(OpCodes.Unbox, tw.TypeAsSignatureType);
+				ilgen.Emit(OpCodes.Ldobj, tw.TypeAsSignatureType);
+			}
+		}
+
+		internal void LoadNull()
+		{
+			ilgen.Emit(OpCodes.Ldnull);
+		}
+
+		internal void Unbox(TypeWrapper tw)
+		{
+			tw.EmitUnbox(ilgen);
+		}
+
+		internal void Box(TypeWrapper tw)
+		{
+			tw.EmitBox(ilgen);
+		}
+
+		internal void UnboxGhost(TypeWrapper tw)
+		{
+			tw.EmitConvStackTypeToSignatureType(ilgen, null);
+		}
+
+		internal void BoxGhost(TypeWrapper tw)
+		{
+			tw.EmitConvSignatureTypeToStackType(ilgen);
+		}
+
+		internal void EmitCheckcast(TypeWrapper tw)
+		{
+			tw.EmitCheckcast(ilgen);
+		}
+
+		internal void EmitCastclass(Type type)
+		{
+			ilgen.EmitCastclass(type);
+		}
+
+		internal void EmitWriteLine()
+		{
+			ilgen.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(object) }));
+		}
+
+		internal void CastByte()
+		{
+			ilgen.Emit(OpCodes.Conv_I1);
+		}
+
+		internal void DumpMethod()
+		{
+			Console.WriteLine(dm.Name + ", type = " + delegateType);
+			ilgen.DumpMethod();
+		}
+
+		private static void FinishTypes(MethodType type)
+		{
+			// FXBUG(?) DynamicILGenerator doesn't like SymbolType (e.g. an array of a TypeBuilder)
+			// so we have to finish the signature types
+			TypeWrapper.FromClass(type.returnType()).Finish();
+			for (int i = 0; i < type.parameterCount(); i++)
+			{
+				TypeWrapper.FromClass(type.parameterType(i)).Finish();
+			}
+		}
+	}
+
+#if DEBUG
+	[System.Security.SecuritySafeCritical]
+#endif
+	private static Delegate ValidateDelegate(Delegate d)
+	{
+#if DEBUG
+		try
+		{
+			System.Runtime.CompilerServices.RuntimeHelpers.PrepareDelegate(d);
+		}
+		catch (Exception x)
+		{
+			JVM.CriticalFailure("Delegate failed to JIT", x);
+		}
+#endif
+		return d;
+	}
+
+	internal static Type GetDelegateTypeForInvokeExact(MethodType type)
+	{
+		if (type._invokeExactDelegateType == null)
+		{
+			type._invokeExactDelegateType = CreateMethodHandleDelegateType(type);
+		}
+		return type._invokeExactDelegateType;
+	}
+
+	internal static T GetDelegateForInvokeExact(MethodHandle mh)
+		where T : class
+	{
+		MethodType type = mh.type();
+		if (mh._invokeExactDelegate == null)
+		{
+			if (type._invokeExactDynamicMethod == null)
+			{
+				type._invokeExactDynamicMethod = DynamicMethodBuilder.CreateInvokeExact(type);
+			}
+			mh._invokeExactDelegate = type._invokeExactDynamicMethod.CreateDelegate(GetDelegateTypeForInvokeExact(type), mh);
+			T del = mh._invokeExactDelegate as T;
+			if (del != null)
+			{
+				return del;
+			}
+		}
+		throw Invokers.newWrongMethodTypeException(GetDelegateMethodType(typeof(T)), type);
+	}
+
+	// called from InvokeExact DynamicMethod and ByteCodeHelper.GetDelegateForInvokeBasic()
+	internal static object GetVoidAdapter(MemberName mn)
+	{
+		MethodType type = mn.getMethodType();
+		if (type.voidAdapter == null)
+		{
+			if (type.returnType() == java.lang.Void.TYPE)
+			{
+				return mn.vmtarget;
+			}
+			type.voidAdapter = DynamicMethodBuilder.CreateVoidAdapter(type);
+		}
+		return type.voidAdapter;
+	}
+
+	internal static void LoadPackedArg(CodeEmitter ilgen, int index, int firstArg, int packedArgPos, Type packedArgType)
+	{
+		index += firstArg;
+		if (index >= packedArgPos)
+		{
+			ilgen.EmitLdarga(packedArgPos);
+			int fieldPos = index - packedArgPos;
+			Type type = packedArgType;
+			while (fieldPos >= MaxArity || (fieldPos == MaxArity - 1 && IsPackedArgsContainer(type.GetField("t8").FieldType)))
+			{
+				FieldInfo field = type.GetField("t8");
+				type = field.FieldType;
+				ilgen.Emit(OpCodes.Ldflda, field);
+				fieldPos -= MaxArity - 1;
+			}
+			ilgen.Emit(OpCodes.Ldfld, type.GetField("t" + (1 + fieldPos)));
+		}
+		else
+		{
+			ilgen.EmitLdarg(index);
+		}
+	}
+#endif
+}
diff --git a/runtime/openjdk/java.lang.reflect.cs b/runtime/openjdk/java.lang.reflect.cs
new file mode 100644
index 0000000..d663c53
--- /dev/null
+++ b/runtime/openjdk/java.lang.reflect.cs
@@ -0,0 +1,808 @@
+/*
+  Copyright (C) 2007-2013 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using IKVM.Internal;
+
+static class Java_java_lang_reflect_Array
+{
+#if FIRST_PASS
+	public static int getLength(object arrayObj)
+	{
+		return 0;
+	}
+
+	public static object get(object arrayObj, int index)
+	{
+		return null;
+	}
+
+	public static bool getBoolean(object arrayObj, int index)
+	{
+		return false;
+	}
+
+	public static byte getByte(object arrayObj, int index)
+	{
+		return 0;
+	}
+
+	public static char getChar(object arrayObj, int index)
+	{
+		return '\u0000';
+	}
+
+	public static short getShort(object arrayObj, int index)
+	{
+		return 0;
+	}
+
+	public static int getInt(object arrayObj, int index)
+	{
+		return 0;
+	}
+
+	public static float getFloat(object arrayObj, int index)
+	{
+		return 0;
+	}
+
+	public static long getLong(object arrayObj, int index)
+	{
+		return 0;
+	}
+
+	public static double getDouble(object arrayObj, int index)
+	{
+		return 0;
+	}
+
+	public static void set(object arrayObj, int index, object value)
+	{
+	}
+
+	public static void setBoolean(object arrayObj, int index, bool value)
+	{
+	}
+
+	public static void setByte(object arrayObj, int index, byte value)
+	{
+	}
+
+	public static void setChar(object arrayObj, int index, char value)
+	{
+	}
+
+	public static void setShort(object arrayObj, int index, short value)
+	{
+	}
+
+	public static void setInt(object arrayObj, int index, int value)
+	{
+	}
+
+	public static void setFloat(object arrayObj, int index, float value)
+	{
+	}
+
+	public static void setLong(object arrayObj, int index, long value)
+	{
+	}
+
+	public static void setDouble(object arrayObj, int index, double value)
+	{
+	}
+
+	public static object newArray(java.lang.Class componentType, int length)
+	{
+		return null;
+	}
+
+	public static object multiNewArray(java.lang.Class componentType, int[] dimensions)
+	{
+		return null;
+	}
+#else
+	private static Array CheckArray(object arrayObj)
+	{
+		if (arrayObj == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+		Array arr = arrayObj as Array;
+		if (arr != null)
+		{
+			return arr;
+		}
+		throw new java.lang.IllegalArgumentException("Argument is not an array");
+	}
+
+	public static int getLength(object arrayObj)
+	{
+		return CheckArray(arrayObj).Length;
+	}
+
+	public static object get(object arrayObj, int index)
+	{
+		Array arr = CheckArray(arrayObj);
+		if (index < 0 || index >= arr.Length)
+		{
+			throw new java.lang.ArrayIndexOutOfBoundsException();
+		}
+		// We need to look at the actual type here, because "is" or "as"
+		// will convert enums to their underlying type and unsigned integral types
+		// to their signed counter parts.
+		Type type = arrayObj.GetType();
+		if (type == typeof(bool[]))
+		{
+			return java.lang.Boolean.valueOf(((bool[])arr)[index]);
+		}
+		if (type == typeof(byte[]))
+		{
+			return java.lang.Byte.valueOf(((byte[])arr)[index]);
+		}
+		if (type == typeof(short[]))
+		{
+			return java.lang.Short.valueOf(((short[])arr)[index]);
+		}
+		if (type == typeof(char[]))
+		{
+			return java.lang.Character.valueOf(((char[])arr)[index]);
+		}
+		if (type == typeof(int[]))
+		{
+			return java.lang.Integer.valueOf(((int[])arr)[index]);
+		}
+		if (type == typeof(float[]))
+		{
+			return java.lang.Float.valueOf(((float[])arr)[index]);
+		}
+		if (type == typeof(long[]))
+		{
+			return java.lang.Long.valueOf(((long[])arr)[index]);
+		}
+		if (type == typeof(double[]))
+		{
+			return java.lang.Double.valueOf(((double[])arr)[index]);
+		}
+		return arr.GetValue(index);
+	}
+
+	public static bool getBoolean(object arrayObj, int index)
+	{
+		if (arrayObj == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+		bool[] arr = arrayObj as bool[];
+		if (arr != null)
+		{
+			if (index < 0 || index >= arr.Length)
+			{
+				throw new java.lang.ArrayIndexOutOfBoundsException();
+			}
+			return arr[index];
+		}
+		throw new java.lang.IllegalArgumentException("argument type mismatch");
+	}
+
+	public static byte getByte(object arrayObj, int index)
+	{
+		if (arrayObj == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+		byte[] arr = arrayObj as byte[];
+		if (arr != null)
+		{
+			if (index < 0 || index >= arr.Length)
+			{
+				throw new java.lang.ArrayIndexOutOfBoundsException();
+			}
+			return arr[index];
+		}
+		throw new java.lang.IllegalArgumentException("argument type mismatch");
+	}
+
+	public static char getChar(object arrayObj, int index)
+	{
+		if (arrayObj == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+		char[] arr = arrayObj as char[];
+		if (arr != null)
+		{
+			if (index < 0 || index >= arr.Length)
+			{
+				throw new java.lang.ArrayIndexOutOfBoundsException();
+			}
+			return arr[index];
+		}
+		throw new java.lang.IllegalArgumentException("argument type mismatch");
+	}
+
+	public static short getShort(object arrayObj, int index)
+	{
+		if (arrayObj == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+		short[] arr = arrayObj as short[];
+		if (arr != null)
+		{
+			if (index < 0 || index >= arr.Length)
+			{
+				throw new java.lang.ArrayIndexOutOfBoundsException();
+			}
+			return arr[index];
+		}
+		return (sbyte)getByte(arrayObj, index);
+	}
+
+	public static int getInt(object arrayObj, int index)
+	{
+		if (arrayObj == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+		int[] arr1 = arrayObj as int[];
+		if (arr1 != null)
+		{
+			if (index < 0 || index >= arr1.Length)
+			{
+				throw new java.lang.ArrayIndexOutOfBoundsException();
+			}
+			return arr1[index];
+		}
+		char[] arr2 = arrayObj as char[];
+		if (arr2 != null)
+		{
+			if (index < 0 || index >= arr2.Length)
+			{
+				throw new java.lang.ArrayIndexOutOfBoundsException();
+			}
+			return arr2[index];
+		}
+		return getShort(arrayObj, index);
+	}
+
+	public static float getFloat(object arrayObj, int index)
+	{
+		if (arrayObj == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+		float[] arr = arrayObj as float[];
+		if (arr != null)
+		{
+			if (index < 0 || index >= arr.Length)
+			{
+				throw new java.lang.ArrayIndexOutOfBoundsException();
+			}
+			return arr[index];
+		}
+		return getLong(arrayObj, index);
+	}
+
+	public static long getLong(object arrayObj, int index)
+	{
+		if (arrayObj == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+		long[] arr = arrayObj as long[];
+		if (arr != null)
+		{
+			if (index < 0 || index >= arr.Length)
+			{
+				throw new java.lang.ArrayIndexOutOfBoundsException();
+			}
+			return arr[index];
+		}
+		return getInt(arrayObj, index);
+	}
+
+	public static double getDouble(object arrayObj, int index)
+	{
+		if (arrayObj == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+		double[] arr = arrayObj as double[];
+		if (arr != null)
+		{
+			if (index < 0 || index >= arr.Length)
+			{
+				throw new java.lang.ArrayIndexOutOfBoundsException();
+			}
+			return arr[index];
+		}
+		return getFloat(arrayObj, index);
+	}
+
+	public static void set(object arrayObj, int index, object value)
+	{
+		if (arrayObj == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+		Type type = arrayObj.GetType();
+		if (ReflectUtil.IsVector(type) && ClassLoaderWrapper.GetWrapperFromType(type.GetElementType()).IsPrimitive)
+		{
+			java.lang.Boolean booleanValue = value as java.lang.Boolean;
+			if (booleanValue != null)
+			{
+				setBoolean(arrayObj, index, booleanValue.booleanValue());
+				return;
+			}
+			java.lang.Byte byteValue = value as java.lang.Byte;
+			if (byteValue != null)
+			{
+				setByte(arrayObj, index, byteValue.byteValue());
+				return;
+			}
+			java.lang.Character charValue = value as java.lang.Character;
+			if (charValue != null)
+			{
+				setChar(arrayObj, index, charValue.charValue());
+				return;
+			}
+			java.lang.Short shortValue = value as java.lang.Short;
+			if (shortValue != null)
+			{
+				setShort(arrayObj, index, shortValue.shortValue());
+				return;
+			}
+			java.lang.Integer intValue = value as java.lang.Integer;
+			if (intValue != null)
+			{
+				setInt(arrayObj, index, intValue.intValue());
+				return;
+			}
+			java.lang.Float floatValue = value as java.lang.Float;
+			if (floatValue != null)
+			{
+				setFloat(arrayObj, index, floatValue.floatValue());
+				return;
+			}
+			java.lang.Long longValue = value as java.lang.Long;
+			if (longValue != null)
+			{
+				setLong(arrayObj, index, longValue.longValue());
+				return;
+			}
+			java.lang.Double doubleValue = value as java.lang.Double;
+			if (doubleValue != null)
+			{
+				setDouble(arrayObj, index, doubleValue.doubleValue());
+				return;
+			}
+		}
+		try
+		{
+			CheckArray(arrayObj).SetValue(value, index);
+		}
+		catch (InvalidCastException)
+		{
+			throw new java.lang.IllegalArgumentException("argument type mismatch");
+		}
+		catch (IndexOutOfRangeException)
+		{
+			throw new java.lang.ArrayIndexOutOfBoundsException();
+		}
+	}
+
+	public static void setBoolean(object arrayObj, int index, bool value)
+	{
+		if (arrayObj == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+		bool[] arr = arrayObj as bool[];
+		if (arr != null)
+		{
+			if (index < 0 || index >= arr.Length)
+			{
+				throw new java.lang.ArrayIndexOutOfBoundsException();
+			}
+			arr[index] = value;
+		}
+		else
+		{
+			throw new java.lang.IllegalArgumentException("argument type mismatch");
+		}
+	}
+
+	public static void setByte(object arrayObj, int index, byte value)
+	{
+		if (arrayObj == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+		byte[] arr = arrayObj as byte[];
+		if (arr != null)
+		{
+			if (index < 0 || index >= arr.Length)
+			{
+				throw new java.lang.ArrayIndexOutOfBoundsException();
+			}
+			arr[index] = value;
+		}
+		else
+		{
+			setShort(arrayObj, index, (sbyte)value);
+		}
+	}
+
+	public static void setChar(object arrayObj, int index, char value)
+	{
+		if (arrayObj == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+		char[] arr = arrayObj as char[];
+		if (arr != null)
+		{
+			if (index < 0 || index >= arr.Length)
+			{
+				throw new java.lang.ArrayIndexOutOfBoundsException();
+			}
+			arr[index] = value;
+		}
+		else
+		{
+			setInt(arrayObj, index, value);
+		}
+	}
+
+	public static void setShort(object arrayObj, int index, short value)
+	{
+		if (arrayObj == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+		short[] arr = arrayObj as short[];
+		if (arr != null)
+		{
+			if (index < 0 || index >= arr.Length)
+			{
+				throw new java.lang.ArrayIndexOutOfBoundsException();
+			}
+			arr[index] = value;
+		}
+		else
+		{
+			setInt(arrayObj, index, value);
+		}
+	}
+
+	public static void setInt(object arrayObj, int index, int value)
+	{
+		if (arrayObj == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+		int[] arr = arrayObj as int[];
+		if (arr != null)
+		{
+			if (index < 0 || index >= arr.Length)
+			{
+				throw new java.lang.ArrayIndexOutOfBoundsException();
+			}
+			arr[index] = value;
+		}
+		else
+		{
+			setLong(arrayObj, index, value);
+		}
+	}
+
+	public static void setFloat(object arrayObj, int index, float value)
+	{
+		if (arrayObj == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+		float[] arr = arrayObj as float[];
+		if (arr != null)
+		{
+			if (index < 0 || index >= arr.Length)
+			{
+				throw new java.lang.ArrayIndexOutOfBoundsException();
+			}
+			arr[index] = value;
+		}
+		else
+		{
+			setDouble(arrayObj, index, value);
+		}
+	}
+
+	public static void setLong(object arrayObj, int index, long value)
+	{
+		if (arrayObj == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+		long[] arr = arrayObj as long[];
+		if (arr != null)
+		{
+			if (index < 0 || index >= arr.Length)
+			{
+				throw new java.lang.ArrayIndexOutOfBoundsException();
+			}
+			arr[index] = value;
+		}
+		else
+		{
+			setFloat(arrayObj, index, value);
+		}
+	}
+
+	public static void setDouble(object arrayObj, int index, double value)
+	{
+		if (arrayObj == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+		double[] arr = arrayObj as double[];
+		if (arr != null)
+		{
+			if (index < 0 || index >= arr.Length)
+			{
+				throw new java.lang.ArrayIndexOutOfBoundsException();
+			}
+			arr[index] = value;
+		}
+		else
+		{
+			throw new java.lang.IllegalArgumentException("argument type mismatch");
+		}
+	}
+
+	public static object newArray(java.lang.Class componentType, int length)
+	{
+		if (componentType == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+		if (componentType == java.lang.Void.TYPE)
+		{
+			throw new java.lang.IllegalArgumentException();
+		}
+		if (length < 0)
+		{
+			throw new java.lang.NegativeArraySizeException();
+		}
+		try
+		{
+			TypeWrapper wrapper = TypeWrapper.FromClass(componentType);
+			wrapper.Finish();
+			object obj = Array.CreateInstance(wrapper.TypeAsArrayType, length);
+			if (wrapper.IsGhost || wrapper.IsGhostArray)
+			{
+				IKVM.Runtime.GhostTag.SetTag(obj, wrapper.MakeArrayType(1));
+			}
+			return obj;
+		}
+		catch (RetargetableJavaException x)
+		{
+			throw x.ToJava();
+		}
+		catch (NotSupportedException x)
+		{
+			// This happens when you try to create an array from TypedReference, ArgIterator, ByRef,
+			// RuntimeArgumentHandle or an open generic type.
+			throw new java.lang.IllegalArgumentException(x.Message);
+		}
+	}
+
+	public static object multiNewArray(java.lang.Class componentType, int[] dimensions)
+	{
+		if (componentType == null || dimensions == null)
+		{
+			throw new java.lang.NullPointerException();
+		}
+		if (componentType == java.lang.Void.TYPE)
+		{
+			throw new java.lang.IllegalArgumentException();
+		}
+		if (dimensions.Length == 0 || dimensions.Length > 255)
+		{
+			throw new java.lang.IllegalArgumentException();
+		}
+		try
+		{
+			TypeWrapper wrapper = TypeWrapper.FromClass(componentType).MakeArrayType(dimensions.Length);
+			wrapper.Finish();
+			object obj = IKVM.Runtime.ByteCodeHelper.multianewarray(wrapper.TypeAsArrayType.TypeHandle, dimensions);
+			if (wrapper.IsGhostArray)
+			{
+				IKVM.Runtime.GhostTag.SetTag(obj, wrapper);
+			}
+			return obj;
+		}
+		catch (RetargetableJavaException x)
+		{
+			throw x.ToJava();
+		}
+		catch (NotSupportedException x)
+		{
+			// This happens when you try to create an array from TypedReference, ArgIterator, ByRef,
+			// RuntimeArgumentHandle or an open generic type.
+			throw new java.lang.IllegalArgumentException(x.Message);
+		}
+	}
+#endif // FIRST_PASS
+}
+
+static class Java_java_lang_reflect_Proxy
+{
+	public static object defineClass0(java.lang.ClassLoader classLoader, string name, byte[] b, int off, int len)
+	{
+		return Java_java_lang_ClassLoader.defineClass1(classLoader, name, b, off, len, null, null);
+	}
+
+	public static java.lang.Class getPrecompiledProxy(java.lang.ClassLoader classLoader, string proxyName, java.lang.Class[] interfaces)
+	{
+		AssemblyClassLoader acl = ClassLoaderWrapper.GetClassLoaderWrapper(classLoader) as AssemblyClassLoader;
+		if (acl == null)
+		{
+			return null;
+		}
+		TypeWrapper[] wrappers = new TypeWrapper[interfaces.Length];
+		for (int i = 0; i < wrappers.Length; i++)
+		{
+			wrappers[i] = TypeWrapper.FromClass(interfaces[i]);
+		}
+		// TODO support multi assembly class loaders
+		Type type = acl.MainAssembly.GetType(TypeNameUtil.GetProxyName(wrappers));
+		if (type == null)
+		{
+			return null;
+		}
+		TypeWrapper tw = CompiledTypeWrapper.newInstance(proxyName, type);
+		TypeWrapper tw2 = acl.RegisterInitiatingLoader(tw);
+		if (tw != tw2)
+		{
+			return null;
+		}
+		// we need to explicitly register the type, because the type isn't visible by normal means
+		tw.GetClassLoader().SetWrapperForType(type, tw);
+		TypeWrapper[] wrappers2 = tw.Interfaces;
+		if (wrappers.Length != wrappers.Length)
+		{
+			return null;
+		}
+		for (int i = 0; i < wrappers.Length; i++)
+		{
+			if (wrappers[i] != wrappers2[i])
+			{
+				return null;
+			}
+		}
+		return tw.ClassObject;
+	}
+}
+
+static class Java_java_lang_reflect_Executable
+{
+	public static object[] getParameters0(java.lang.reflect.Executable _this)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		MethodWrapper mw = MethodWrapper.FromExecutable(_this);
+		MethodParametersEntry[] methodParameters = mw.DeclaringType.GetMethodParameters(mw);
+		if (methodParameters == null)
+		{
+			return null;
+		}
+		if (methodParameters == MethodParametersEntry.Malformed)
+		{
+			throw new java.lang.reflect.MalformedParametersException("Invalid constant pool index");
+		}
+		java.lang.reflect.Parameter[] parameters = new java.lang.reflect.Parameter[methodParameters.Length];
+		for (int i = 0; i < parameters.Length; i++)
+		{
+			parameters[i] = new java.lang.reflect.Parameter(methodParameters[i].name ?? "", methodParameters[i].flags, _this, i);
+		}
+		return parameters;
+#endif
+	}
+
+	public static byte[] getTypeAnnotationBytes0(java.lang.reflect.Executable _this)
+	{
+		MethodWrapper mw = MethodWrapper.FromExecutable(_this);
+		return mw.DeclaringType.GetMethodRawTypeAnnotations(mw);
+	}
+
+	public static object declaredAnnotationsImpl(java.lang.reflect.Executable executable)
+	{
+		MethodWrapper mw = MethodWrapper.FromExecutable(executable);
+		return Java_java_lang_Class.AnnotationsToMap(mw.DeclaringType.GetClassLoader(), mw.DeclaringType.GetMethodAnnotations(mw));
+	}
+
+	public static object[][] sharedGetParameterAnnotationsImpl(java.lang.reflect.Executable executable)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		MethodWrapper mw = MethodWrapper.FromExecutable(executable);
+		object[][] objAnn = mw.DeclaringType.GetParameterAnnotations(mw);
+		if (objAnn == null)
+		{
+			return null;
+		}
+		java.lang.annotation.Annotation[][] ann = new java.lang.annotation.Annotation[objAnn.Length][];
+		for (int i = 0; i < ann.Length; i++)
+		{
+			List list = new List();
+			foreach (object obj in objAnn[i])
+			{
+				java.lang.annotation.Annotation a = obj as java.lang.annotation.Annotation;
+				if (a != null)
+				{
+					list.Add(Java_java_lang_Class.FreezeOrWrapAttribute(a));
+				}
+				else if (obj is IKVM.Attributes.DynamicAnnotationAttribute)
+				{
+					a = (java.lang.annotation.Annotation)JVM.NewAnnotation(mw.DeclaringType.GetClassLoader().GetJavaClassLoader(), ((IKVM.Attributes.DynamicAnnotationAttribute)obj).Definition);
+					if (a != null)
+					{
+						list.Add(a);
+					}
+				}
+			}
+			ann[i] = list.ToArray();
+		}
+		return ann;
+#endif
+	}
+}
+
+static class Java_java_lang_reflect_Field
+{
+	public static object getDeclaredAnnotationsImpl(java.lang.reflect.Field thisField)
+	{
+		FieldWrapper fw = FieldWrapper.FromField(thisField);
+		return Java_java_lang_Class.AnnotationsToMap(fw.DeclaringType.GetClassLoader(), fw.DeclaringType.GetFieldAnnotations(fw));
+	}
+
+	public static byte[] getTypeAnnotationBytes0(java.lang.reflect.Field thisField)
+	{
+		FieldWrapper fw = FieldWrapper.FromField(thisField);
+		return fw.DeclaringType.GetFieldRawTypeAnnotations(fw);
+	}
+}
+
+static class Java_java_lang_reflect_Method
+{
+	public static object getDefaultValue(java.lang.reflect.Method thisMethod)
+	{
+		MethodWrapper mw = MethodWrapper.FromExecutable(thisMethod);
+		return mw.DeclaringType.GetAnnotationDefault(mw);
+	}
+}
diff --git a/runtime/openjdk/java.net.SocketInputStream.cs b/runtime/openjdk/java.net.SocketInputStream.cs
new file mode 100644
index 0000000..800eb4f
--- /dev/null
+++ b/runtime/openjdk/java.net.SocketInputStream.cs
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 1995, 2013, 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.
+ */
+#if !FIRST_PASS
+using Winsock = ikvm.@internal.Winsock;
+using java.net;
+#endif
+
+static class Java_java_net_SocketInputStream
+{
+	public static int socketRead0(object _this, java.io.FileDescriptor fd, byte[] b, int off, int len, int timeout)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		// [IKVM] this method is a direct port of the native code in openjdk6-b18\jdk\src\windows\native\java\net\SocketInputStream.c
+		System.Net.Sockets.Socket socket = null;
+		int nread;
+
+		if (fd == null)
+		{
+			throw new SocketException("socket closed");
+		}
+		socket = fd.getSocket();
+		if (socket == null)
+		{
+			throw new SocketException("Socket closed");
+		}
+
+		if (timeout != 0)
+		{
+			if (timeout <= 5000 || !net_util_md.isRcvTimeoutSupported)
+			{
+				int ret = net_util_md.NET_Timeout(socket, timeout);
+
+				if (ret <= 0)
+				{
+					if (ret == 0)
+					{
+						throw new SocketTimeoutException("Read timed out");
+					}
+					else
+					{
+						// [IKVM] the OpenJDK native code is broken and always throws this exception on any failure of NET_Timeout
+						throw new SocketException("socket closed");
+					}
+				}
+
+				/*check if the socket has been closed while we were in timeout*/
+				if (fd.getSocket() == null)
+				{
+					throw new SocketException("Socket Closed");
+				}
+			}
+		}
+
+		nread = Winsock.recv(socket, b, off, len, 0);
+		if (nread > 0)
+		{
+			// ok
+		}
+		else
+		{
+			if (nread < 0)
+			{
+				/*
+				 * Recv failed.
+				 */
+				switch (Winsock.WSAGetLastError())
+				{
+					case Winsock.WSAEINTR:
+						throw new SocketException("socket closed");
+
+					case Winsock.WSAECONNRESET:
+					case Winsock.WSAESHUTDOWN:
+						/*
+						 * Connection has been reset - Windows sometimes reports
+						 * the reset as a shutdown error.
+						 */
+						throw new sun.net.ConnectionResetException();
+
+					case Winsock.WSAETIMEDOUT:
+						throw new SocketTimeoutException("Read timed out");
+
+					default:
+						throw net_util_md.NET_ThrowCurrent("recv failed");
+				}
+			}
+		}
+		return nread;
+#endif
+	}
+
+	public static void init()
+	{
+	}
+}
+
+static class Java_java_net_SocketOutputStream
+{
+	public static void socketWrite0(object _this, java.io.FileDescriptor fd, byte[] data, int off, int len)
+	{
+#if !FIRST_PASS
+		// [IKVM] this method is a direct port of the native code in openjdk6-b18\jdk\src\windows\native\java\net\SocketOutputStream.c
+		const int MAX_BUFFER_LEN = 2048;
+		System.Net.Sockets.Socket socket;
+		int buflen = 65536; // MAX_HEAP_BUFFER_LEN
+		int n;
+
+		if (fd == null)
+		{
+			throw new SocketException("socket closed");
+		}
+		else
+		{
+			socket = fd.getSocket();
+		}
+		if (data == null)
+		{
+			throw new java.lang.NullPointerException("data argument");
+		}
+
+		while (len > 0)
+		{
+			int loff = 0;
+			int chunkLen = java.lang.Math.min(buflen, len);
+			int llen = chunkLen;
+			int retry = 0;
+
+			while (llen > 0)
+			{
+				n = Winsock.send(socket, data, off + loff, llen, 0);
+				if (n > 0)
+				{
+					llen -= n;
+					loff += n;
+					continue;
+				}
+
+				/*
+				 * Due to a bug in Windows Sockets (observed on NT and Windows
+				 * 2000) it may be necessary to retry the send. The issue is that
+				 * on blocking sockets send/WSASend is supposed to block if there
+				 * is insufficient buffer space available. If there are a large
+				 * number of threads blocked on write due to congestion then it's
+				 * possile to hit the NT/2000 bug whereby send returns WSAENOBUFS.
+				 * The workaround we use is to retry the send. If we have a
+				 * large buffer to send (>2k) then we retry with a maximum of
+				 * 2k buffer. If we hit the issue with <=2k buffer then we backoff
+				 * for 1 second and retry again. We repeat this up to a reasonable
+				 * limit before bailing out and throwing an exception. In load
+				 * conditions we've observed that the send will succeed after 2-3
+				 * attempts but this depends on network buffers associated with
+				 * other sockets draining.
+				 */
+				if (Winsock.WSAGetLastError() == Winsock.WSAENOBUFS)
+				{
+					if (llen > MAX_BUFFER_LEN)
+					{
+						buflen = MAX_BUFFER_LEN;
+						chunkLen = MAX_BUFFER_LEN;
+						llen = MAX_BUFFER_LEN;
+						continue;
+					}
+					if (retry >= 30)
+					{
+						throw new SocketException("No buffer space available - exhausted attempts to queue buffer");
+					}
+					System.Threading.Thread.Sleep(1000);
+					retry++;
+					continue;
+				}
+
+				/*
+				 * Send failed - can be caused by close or write error.
+				 */
+				if (Winsock.WSAGetLastError() == Winsock.WSAENOTSOCK)
+				{
+					throw new SocketException("Socket closed");
+				}
+				else
+				{
+					throw net_util_md.NET_ThrowCurrent("socket write error");
+				}
+			}
+			len -= chunkLen;
+			off += chunkLen;
+		}
+#endif
+	}
+
+	public static void init()
+	{
+	}
+}
diff --git a/runtime/openjdk/java.net.cs b/runtime/openjdk/java.net.cs
new file mode 100644
index 0000000..b5626d7
--- /dev/null
+++ b/runtime/openjdk/java.net.cs
@@ -0,0 +1,732 @@
+/*
+  Copyright (C) 2007-2015 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Net.NetworkInformation;
+using System.Net.Sockets;
+using System.Security;
+
+static class Java_java_net_AbstractPlainDatagramSocketImpl
+{
+	public static void init()
+	{
+	}
+
+	public static int dataAvailable(object _this)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		try
+		{
+			java.net.AbstractPlainDatagramSocketImpl obj = (java.net.AbstractPlainDatagramSocketImpl)_this;
+			if (obj.fd != null)
+			{
+				return obj.fd.getSocket().Available;
+			}
+		}
+		catch (ObjectDisposedException)
+		{
+		}
+		catch (SocketException)
+		{
+		}
+		throw new java.net.SocketException("Socket closed");
+#endif
+	}
+}
+
+static class Java_java_net_DatagramPacket
+{
+	public static void init()
+	{
+	}
+}
+
+static class Java_java_net_InetAddress
+{
+	public static void init()
+	{
+	}
+
+#if !FIRST_PASS
+	internal static java.net.InetAddress ConvertIPAddress(IPAddress address, string hostname)
+	{
+		if (address.IsIPv6LinkLocal || address.IsIPv6SiteLocal)
+		{
+			return java.net.Inet6Address.getByAddress(hostname, address.GetAddressBytes(), (int)address.ScopeId);
+		}
+		else
+		{
+			return java.net.InetAddress.getByAddress(hostname, address.GetAddressBytes());
+		}
+	}
+#endif
+}
+
+static class Java_java_net_InetAddressImplFactory
+{
+	private static readonly bool ipv6supported = Init();
+
+	private static bool Init()
+	{
+		string env = IKVM.Internal.JVM.SafeGetEnvironmentVariable("IKVM_IPV6");
+		int val;
+		if (env != null && Int32.TryParse(env, out val))
+		{
+			return (val & 1) != 0;
+		}
+		// On Linux we can't bind both an IPv4 and IPv6 to the same port, so we have to disable IPv6 until we have a dual-stack implementation.
+		// Mono on Windows doesn't appear to support IPv6 either (Mono on Linux does).
+		return Type.GetType("Mono.Runtime") == null
+			&& Environment.OSVersion.Platform == PlatformID.Win32NT
+			&& Socket.OSSupportsIPv6;
+	}
+
+	public static bool isIPv6Supported()
+	{
+		return ipv6supported;
+	}
+}
+
+static class Java_java_net_Inet4Address
+{
+	public static void init()
+	{
+	}
+}
+
+static class Java_java_net_Inet4AddressImpl
+{
+	public static string getLocalHostName(object thisInet4AddressImpl)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		try
+		{
+			return Dns.GetHostName();
+		}
+		catch (SocketException)
+		{
+		}
+		catch (SecurityException)
+		{
+		}
+		return "localhost";
+#endif
+	}
+
+	public static object lookupAllHostAddr(object thisInet4AddressImpl, string hostname)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		try
+		{
+			IPAddress[] addr = Dns.GetHostAddresses(hostname);
+			List addresses = new List();
+			for (int i = 0; i < addr.Length; i++)
+			{
+				byte[] b = addr[i].GetAddressBytes();
+				if (b.Length == 4)
+				{
+					addresses.Add(java.net.InetAddress.getByAddress(hostname, b));
+				}
+			}
+			if (addresses.Count == 0)
+			{
+				throw new java.net.UnknownHostException(hostname);
+			}
+			return addresses.ToArray();
+		}
+		catch (ArgumentException x)
+		{
+			throw new java.net.UnknownHostException(x.Message);
+		}
+		catch (SocketException x)
+		{
+			throw new java.net.UnknownHostException(x.Message);
+		}
+#endif
+	}
+
+	public static string getHostByAddr(object thisInet4AddressImpl, byte[] addr)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		try
+		{
+			return Dns.GetHostEntry(new IPAddress(addr)).HostName;
+		}
+		catch (ArgumentException x)
+		{
+			throw new java.net.UnknownHostException(x.Message);
+		}
+		catch (SocketException x)
+		{
+			throw new java.net.UnknownHostException(x.Message);
+		}
+#endif
+	}
+
+	public static bool isReachable0(object thisInet4AddressImpl, byte[] addr, int timeout, byte[] ifaddr, int ttl)
+	{
+		// like the JDK, we don't use Ping, but we try a TCP connection to the echo port
+		// (.NET 2.0 has a System.Net.NetworkInformation.Ping class, but that doesn't provide the option of binding to a specific interface)
+		try
+		{
+			using (Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
+			{
+				if (ifaddr != null)
+				{
+					sock.Bind(new IPEndPoint(((ifaddr[3] << 24) + (ifaddr[2] << 16) + (ifaddr[1] << 8) + ifaddr[0]) & 0xFFFFFFFFL, 0));
+				}
+				if (ttl > 0)
+				{
+					sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, ttl);
+				}
+				IPEndPoint ep = new IPEndPoint(((addr[3] << 24) + (addr[2] << 16) + (addr[1] << 8) + addr[0]) & 0xFFFFFFFFL, 7);
+				IAsyncResult res = sock.BeginConnect(ep, null, null);
+				if (res.AsyncWaitHandle.WaitOne(timeout, false))
+				{
+					try
+					{
+						sock.EndConnect(res);
+						return true;
+					}
+					catch (SocketException x)
+					{
+						const int WSAECONNREFUSED = 10061;
+						if (x.ErrorCode == WSAECONNREFUSED)
+						{
+							// we got back an explicit "connection refused", that means the host was reachable.
+							return true;
+						}
+					}
+				}
+			}
+		}
+		catch (SocketException)
+		{
+		}
+		return false;
+	}
+}
+
+static class Java_java_net_Inet6Address
+{
+	public static void init()
+	{
+	}
+}
+
+static class Java_java_net_Inet6AddressImpl
+{
+	public static string getLocalHostName(object thisInet6AddressImpl)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		try
+		{
+			return Dns.GetHostName();
+		}
+		catch (SocketException x)
+		{
+			throw new java.net.UnknownHostException(x.Message);
+		}
+#endif
+	}
+
+	public static object lookupAllHostAddr(object thisInet6AddressImpl, string hostname)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		try
+		{
+			IPAddress[] addr = Dns.GetHostAddresses(hostname);
+			java.net.InetAddress[] addresses = new java.net.InetAddress[addr.Length];
+			int pos = 0;
+			for (int i = 0; i < addr.Length; i++)
+			{
+				if (addr[i].AddressFamily == AddressFamily.InterNetworkV6 == java.net.InetAddress.preferIPv6Address)
+				{
+					addresses[pos++] = Java_java_net_InetAddress.ConvertIPAddress(addr[i], hostname);
+				}
+			}
+			for (int i = 0; i < addr.Length; i++)
+			{
+				if (addr[i].AddressFamily == AddressFamily.InterNetworkV6 != java.net.InetAddress.preferIPv6Address)
+				{
+					addresses[pos++] = Java_java_net_InetAddress.ConvertIPAddress(addr[i], hostname);
+				}
+			}
+			if (addresses.Length == 0)
+			{
+				throw new java.net.UnknownHostException(hostname);
+			}
+			return addresses;
+		}
+		catch (ArgumentException x)
+		{
+			throw new java.net.UnknownHostException(x.Message);
+		}
+		catch (SocketException x)
+		{
+			throw new java.net.UnknownHostException(x.Message);
+		}
+#endif
+	}
+
+	public static string getHostByAddr(object thisInet6AddressImpl, byte[] addr)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		try
+		{
+			return Dns.GetHostEntry(new IPAddress(addr)).HostName;
+		}
+		catch (ArgumentException x)
+		{
+			throw new java.net.UnknownHostException(x.Message);
+		}
+		catch (SocketException x)
+		{
+			throw new java.net.UnknownHostException(x.Message);
+		}
+#endif
+	}
+
+	public static bool isReachable0(object thisInet6AddressImpl, byte[] addr, int scope, int timeout, byte[] inf, int ttl, int if_scope)
+	{
+		if (addr.Length == 4)
+		{
+			return Java_java_net_Inet4AddressImpl.isReachable0(null, addr, timeout, inf, ttl);
+		}
+		// like the JDK, we don't use Ping, but we try a TCP connection to the echo port
+		// (.NET 2.0 has a System.Net.NetworkInformation.Ping class, but that doesn't provide the option of binding to a specific interface)
+		try
+		{
+			using (Socket sock = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp))
+			{
+				if (inf != null)
+				{
+					sock.Bind(new IPEndPoint(new IPAddress(inf, (uint)if_scope), 0));
+				}
+				if (ttl > 0)
+				{
+					sock.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.HopLimit, ttl);
+				}
+				IPEndPoint ep = new IPEndPoint(new IPAddress(addr, (uint)scope), 7);
+				IAsyncResult res = sock.BeginConnect(ep, null, null);
+				if (res.AsyncWaitHandle.WaitOne(timeout, false))
+				{
+					try
+					{
+						sock.EndConnect(res);
+						return true;
+					}
+					catch (SocketException x)
+					{
+						const int WSAECONNREFUSED = 10061;
+						if (x.ErrorCode == WSAECONNREFUSED)
+						{
+							// we got back an explicit "connection refused", that means the host was reachable.
+							return true;
+						}
+					}
+				}
+			}
+		}
+		catch (ArgumentException)
+		{
+		}
+		catch (SocketException)
+		{
+		}
+		return false;
+	}
+}
+
+static class Java_java_net_NetworkInterface
+{
+#if !FIRST_PASS
+	private static NetworkInterfaceInfo cache;
+	private static DateTime cachedSince;
+#endif
+
+	public static void init()
+	{
+	}
+
+#if !FIRST_PASS
+	private sealed class NetworkInterfaceInfo
+	{
+		internal NetworkInterface[] dotnetInterfaces;
+		internal java.net.NetworkInterface[] javaInterfaces;
+	}
+
+	private static int Compare(NetworkInterface ni1, NetworkInterface ni2)
+	{
+		int index1 = GetIndex(ni1);
+		int index2 = GetIndex(ni2);
+		return index1.CompareTo(index2);
+	}
+
+	private static IPv4InterfaceProperties GetIPv4Properties(IPInterfaceProperties props)
+	{
+		try
+		{
+			return props.GetIPv4Properties();
+		}
+		catch (NetworkInformationException)
+		{
+			return null;
+		}
+	}
+
+	private static IPv6InterfaceProperties GetIPv6Properties(IPInterfaceProperties props)
+	{
+		try
+		{
+			return props.GetIPv6Properties();
+		}
+		catch (NetworkInformationException)
+		{
+			return null;
+		}
+	}
+
+	private static int GetIndex(NetworkInterface ni)
+	{
+		IPInterfaceProperties ipprops = ni.GetIPProperties();
+		IPv4InterfaceProperties ipv4props = GetIPv4Properties(ipprops);
+		if (ipv4props != null)
+		{
+			return ipv4props.Index;
+		}
+		else if (Java_java_net_InetAddressImplFactory.isIPv6Supported())
+		{
+			IPv6InterfaceProperties ipv6props = GetIPv6Properties(ipprops);
+			if (ipv6props != null)
+			{
+				return ipv6props.Index;
+			}
+		}
+		return -1;
+	}
+
+	private static bool IsValid(NetworkInterface ni)
+	{
+		return GetIndex(ni) != -1;
+	}
+
+	private static NetworkInterfaceInfo GetInterfaces()
+	{
+		// Since many of the methods in java.net.NetworkInterface end up calling this method and the underlying stuff this is
+		// based on isn't very quick either, we cache the array for a couple of seconds.
+		if (cache != null && DateTime.UtcNow - cachedSince < new TimeSpan(0, 0, 5))
+		{
+			return cache;
+		}
+		NetworkInterface[] ifaces = NetworkInterface.GetAllNetworkInterfaces();
+		// on Mono (on Windows) we need to filter out the network interfaces that don't have any IP properties
+		ifaces = Array.FindAll(ifaces, IsValid);
+		Array.Sort(ifaces, Compare);
+		java.net.NetworkInterface[] ret = new java.net.NetworkInterface[ifaces.Length];
+		int eth = 0;
+		int tr = 0;
+		int fddi = 0;
+		int lo = 0;
+		int ppp = 0;
+		int sl = 0;
+		int net = 0;
+		for (int i = 0; i < ifaces.Length; i++)
+		{
+			string name;
+			switch (ifaces[i].NetworkInterfaceType)
+			{
+				case NetworkInterfaceType.Ethernet:
+					name = "eth" + eth++;
+					break;
+				case NetworkInterfaceType.TokenRing:
+					name = "tr" + tr++;
+					break;
+				case NetworkInterfaceType.Fddi:
+					name = "fddi" + fddi++;
+					break;
+				case NetworkInterfaceType.Loopback:
+					if (lo > 0)
+					{
+						continue;
+					}
+					name = "lo";
+					lo++;
+					break;
+				case NetworkInterfaceType.Ppp:
+					name = "ppp" + ppp++;
+					break;
+				case NetworkInterfaceType.Slip:
+					name = "sl" + sl++;
+					break;
+				default:
+					name = "net" + net++;
+					break;
+			}
+			java.net.NetworkInterface netif = new java.net.NetworkInterface();
+			ret[i] = netif;
+			netif._set1(name, ifaces[i].Description, GetIndex(ifaces[i]));
+			UnicastIPAddressInformationCollection uipaic = ifaces[i].GetIPProperties().UnicastAddresses;
+			List addresses = new List();
+			List bindings = new List();
+			for (int j = 0; j < uipaic.Count; j++)
+			{
+				IPAddress addr = uipaic[j].Address;
+				if (addr.AddressFamily == AddressFamily.InterNetwork)
+				{
+					java.net.Inet4Address address = new java.net.Inet4Address(null, addr.GetAddressBytes());
+					java.net.InterfaceAddress binding = new java.net.InterfaceAddress();
+					short mask = 32;
+					java.net.Inet4Address broadcast = null;
+					IPAddress v4mask;
+					try
+					{
+						v4mask = uipaic[j].IPv4Mask;
+					}
+					catch (NotImplementedException)
+					{
+						// Mono (as of 2.6.7) doesn't implement the IPv4Mask property
+						v4mask = null;
+					}
+					if (v4mask != null && !v4mask.Equals(IPAddress.Any))
+					{
+						broadcast = new java.net.Inet4Address(null, -1);
+						mask = 0;
+						foreach (byte b in v4mask.GetAddressBytes())
+						{
+							mask += (short)java.lang.Integer.bitCount(b);
+						}
+					}
+					else if (address.isLoopbackAddress())
+					{
+						mask = 8;
+						broadcast = new java.net.Inet4Address(null, 0xffffff);
+					}
+					binding._set(address, broadcast, mask);
+					addresses.Add(address);
+					bindings.Add(binding);
+				}
+				else if (Java_java_net_InetAddressImplFactory.isIPv6Supported())
+				{
+					int scope = 0;
+					if (addr.IsIPv6LinkLocal || addr.IsIPv6SiteLocal)
+					{
+						scope = (int)addr.ScopeId;
+					}
+					java.net.Inet6Address ia6 = new java.net.Inet6Address();
+					ia6._holder().ipaddress = addr.GetAddressBytes();
+					if (scope != 0)
+					{
+						ia6._holder().scope_id = scope;
+						ia6._holder().scope_id_set = true;
+						ia6._holder().scope_ifname = netif;
+						ia6._holder().scope_ifname_set = true;
+					}
+					java.net.InterfaceAddress binding = new java.net.InterfaceAddress();
+					// TODO where do we get the IPv6 subnet prefix length?
+					short mask = 128;
+					binding._set(ia6, null, mask);
+					addresses.Add(ia6);
+					bindings.Add(binding);
+				}
+			}
+			netif._set2(addresses.ToArray(), bindings.ToArray(), new java.net.NetworkInterface[0]);
+		}
+		NetworkInterfaceInfo nii = new NetworkInterfaceInfo();
+		nii.dotnetInterfaces = ifaces;
+		nii.javaInterfaces = ret;
+		cache = nii;
+		cachedSince = DateTime.UtcNow;
+		return nii;
+	}
+#endif
+
+	private static NetworkInterface GetDotNetNetworkInterfaceByIndex(int index)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		NetworkInterfaceInfo nii = GetInterfaces();
+		for (int i = 0; i < nii.javaInterfaces.Length; i++)
+		{
+			if (nii.javaInterfaces[i].getIndex() == index)
+			{
+				return nii.dotnetInterfaces[i];
+			}
+		}
+		throw new java.net.SocketException("interface index not found");
+#endif
+	}
+
+	public static object getAll()
+	{
+#if FIRST_PASS
+		return null;
+#else
+		return GetInterfaces().javaInterfaces;
+#endif
+	}
+
+	public static object getByName0(string name)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		foreach (java.net.NetworkInterface iface in GetInterfaces().javaInterfaces)
+		{
+			if (iface.getName() == name)
+			{
+				return iface;
+			}
+		}
+		return null;
+#endif
+	}
+
+	public static object getByIndex0(int index)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		foreach (java.net.NetworkInterface iface in GetInterfaces().javaInterfaces)
+		{
+			if (iface.getIndex() == index)
+			{
+				return iface;
+			}
+		}
+		return null;
+#endif
+	}
+
+	public static object getByInetAddress0(object addr)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		foreach (java.net.NetworkInterface iface in GetInterfaces().javaInterfaces)
+		{
+			java.util.Enumeration addresses = iface.getInetAddresses();
+			while (addresses.hasMoreElements())
+			{
+				if (addresses.nextElement().Equals(addr))
+				{
+					return iface;
+				}
+			}
+		}
+		return null;
+#endif
+	}
+
+	public static bool isUp0(string name, int ind)
+	{
+#if FIRST_PASS
+		return false;
+#else
+		return GetDotNetNetworkInterfaceByIndex(ind).OperationalStatus == OperationalStatus.Up;
+#endif
+	}
+
+	public static bool isLoopback0(string name, int ind)
+	{
+#if FIRST_PASS
+		return false;
+#else
+		return GetDotNetNetworkInterfaceByIndex(ind).NetworkInterfaceType == NetworkInterfaceType.Loopback;
+#endif
+	}
+
+	public static bool supportsMulticast0(string name, int ind)
+	{
+#if FIRST_PASS
+		return false;
+#else
+		return GetDotNetNetworkInterfaceByIndex(ind).SupportsMulticast;
+#endif
+	}
+
+	public static bool isP2P0(string name, int ind)
+	{
+#if FIRST_PASS
+		return false;
+#else
+		switch (GetDotNetNetworkInterfaceByIndex(ind).NetworkInterfaceType)
+		{
+			case NetworkInterfaceType.Ppp:
+			case NetworkInterfaceType.Slip:
+				return true;
+			default:
+				return false;
+		}
+#endif
+	}
+
+	public static byte[] getMacAddr0(byte[] inAddr, string name, int ind)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		return GetDotNetNetworkInterfaceByIndex(ind).GetPhysicalAddress().GetAddressBytes();
+#endif
+	}
+
+	public static int getMTU0(string name, int ind)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		IPInterfaceProperties ipprops = GetDotNetNetworkInterfaceByIndex(ind).GetIPProperties();
+		IPv4InterfaceProperties v4props = GetIPv4Properties(ipprops);
+		if (v4props != null)
+		{
+			return v4props.Mtu;
+		}
+		if (Java_java_net_InetAddressImplFactory.isIPv6Supported())
+		{
+			IPv6InterfaceProperties v6props = GetIPv6Properties(ipprops);
+			if (v6props != null)
+			{
+				return v6props.Mtu;
+			}
+		}
+		return -1;
+#endif
+	}
+}
diff --git a/runtime/openjdk/java.nio.cs b/runtime/openjdk/java.nio.cs
new file mode 100644
index 0000000..2d0ce9c
--- /dev/null
+++ b/runtime/openjdk/java.nio.cs
@@ -0,0 +1,277 @@
+/*
+  Copyright (C) 2007-2013 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Permissions;
+using IKVM.Internal;
+
+[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
+[SecurityCritical]
+static class Java_java_nio_Bits
+{
+	public static void copyFromShortArray(object src, long srcPos, long dstAddr, long length)
+	{
+#if !FIRST_PASS
+		short[] shortArray = src as short[];
+		if (shortArray != null)
+		{
+			int index = ((int)srcPos) >> 1;
+			while (length > 0)
+			{
+				short v = java.lang.Short.reverseBytes(shortArray[index++]);
+				Marshal.WriteInt16((IntPtr)dstAddr, v);
+				dstAddr += 2;
+				length -= 2;
+			}
+		}
+		else
+		{
+			char[] charArray = (char[])src;
+			int index = ((int)srcPos) >> 1;
+			while (length > 0)
+			{
+				short v = java.lang.Short.reverseBytes((short)charArray[index++]);
+				Marshal.WriteInt16((IntPtr)dstAddr, v);
+				dstAddr += 2;
+				length -= 2;
+			}
+		}
+#endif
+	}
+
+	public static void copyToShortArray(long srcAddr, object dst, long dstPos, long length)
+	{
+#if !FIRST_PASS
+		short[] shortArray = dst as short[];
+		if (shortArray != null)
+		{
+			int index = ((int)dstPos) >> 1;
+			while (length > 0)
+			{
+				short v = Marshal.ReadInt16((IntPtr)srcAddr);
+				shortArray[index++] = java.lang.Short.reverseBytes(v);
+				srcAddr += 2;
+				length -= 2;
+			}
+		}
+		else
+		{
+			char[] charArray = (char[])dst;
+			int index = ((int)dstPos) >> 1;
+			while (length > 0)
+			{
+				short v = Marshal.ReadInt16((IntPtr)srcAddr);
+				charArray[index++] = (char)java.lang.Short.reverseBytes(v);
+				srcAddr += 2;
+				length -= 2;
+			}
+		}
+#endif
+	}
+
+	public static void copyFromIntArray(object src, long srcPos, long dstAddr, long length)
+	{
+#if !FIRST_PASS
+		int[] intArray = src as int[];
+		if (intArray != null)
+		{
+			int index = ((int)srcPos) >> 2;
+			while (length > 0)
+			{
+				int v = java.lang.Integer.reverseBytes(intArray[index++]);
+				Marshal.WriteInt32((IntPtr)dstAddr, v);
+				dstAddr += 4;
+				length -= 4;
+			}
+		}
+		else
+		{
+			float[] floatArray = (float[])src;
+			int index = ((int)srcPos) >> 2;
+			while (length > 0)
+			{
+				int v = java.lang.Integer.reverseBytes(java.lang.Float.floatToRawIntBits(floatArray[index++]));
+				Marshal.WriteInt32((IntPtr)dstAddr, v);
+				dstAddr += 4;
+				length -= 4;
+			}
+		}
+#endif
+	}
+
+	public static void copyToIntArray(long srcAddr, object dst, long dstPos, long length)
+	{
+#if !FIRST_PASS
+		int[] intArray = dst as int[];
+		if (intArray != null)
+		{
+			int index = ((int)dstPos) >> 2;
+			while (length > 0)
+			{
+				int v = Marshal.ReadInt32((IntPtr)srcAddr);
+				intArray[index++] = java.lang.Integer.reverseBytes(v);
+				srcAddr += 4;
+				length -= 4;
+			}
+		}
+		else
+		{
+			float[] floatArray = (float[])dst;
+			int index = ((int)dstPos) >> 2;
+			while (length > 0)
+			{
+				int v = Marshal.ReadInt32((IntPtr)srcAddr);
+				floatArray[index++] = java.lang.Float.intBitsToFloat(java.lang.Integer.reverseBytes(v));
+				srcAddr += 4;
+				length -= 4;
+			}
+		}
+#endif
+	}
+
+	public static void copyFromLongArray(object src, long srcPos, long dstAddr, long length)
+	{
+#if !FIRST_PASS
+		long[] longArray = src as long[];
+		if (longArray != null)
+		{
+			int index = ((int)srcPos) >> 3;
+			while (length > 0)
+			{
+				long v = java.lang.Long.reverseBytes(longArray[index++]);
+				Marshal.WriteInt64((IntPtr)dstAddr, v);
+				dstAddr += 8;
+				length -= 8;
+			}
+		}
+		else
+		{
+			double[] doubleArray = (double[])src;
+			int index = ((int)srcPos) >> 3;
+			while (length > 0)
+			{
+				long v = java.lang.Long.reverseBytes(BitConverter.DoubleToInt64Bits(doubleArray[index++]));
+				Marshal.WriteInt64((IntPtr)dstAddr, v);
+				dstAddr += 8;
+				length -= 8;
+			}
+		}
+#endif
+	}
+
+	public static void copyToLongArray(long srcAddr, object dst, long dstPos, long length)
+	{
+#if !FIRST_PASS
+		long[] longArray = dst as long[];
+		if (longArray != null)
+		{
+			int index = ((int)dstPos) >> 3;
+			while (length > 0)
+			{
+				long v = Marshal.ReadInt64((IntPtr)srcAddr);
+				longArray[index++] = java.lang.Long.reverseBytes(v);
+				srcAddr += 8;
+				length -= 8;
+			}
+		}
+		else
+		{
+			double[] doubleArray = (double[])dst;
+			int index = ((int)dstPos) >> 3;
+			while (length > 0)
+			{
+				long v = Marshal.ReadInt64((IntPtr)srcAddr);
+				doubleArray[index++] = BitConverter.Int64BitsToDouble(java.lang.Long.reverseBytes(v));
+				srcAddr += 8;
+				length -= 8;
+			}
+		}
+#endif
+	}
+}
+
+static class Java_java_nio_MappedByteBuffer
+{
+	private static volatile int bogusField;
+
+	public static bool isLoaded0(object thisMappedByteBuffer, long address, long length, int pageCount)
+	{
+		// on Windows, JDK simply returns false, so we can get away with that too.
+		return false;
+	}
+
+	[SecuritySafeCritical]
+	public static void load0(object thisMappedByteBuffer, long address, long length)
+	{
+		int bogus = bogusField;
+		while (length > 0)
+		{
+			// touch a byte in every page
+			bogus += Marshal.ReadByte((IntPtr)address);
+			length -= 4096;
+			address += 4096;
+		}
+		// do a volatile store of the sum of the bytes to make sure the reads don't get optimized out
+		bogusField = bogus;
+		GC.KeepAlive(thisMappedByteBuffer);
+	}
+
+	[SecuritySafeCritical]
+	public static void force0(object thisMappedByteBuffer, object fd, long address, long length)
+	{
+		if (JVM.IsUnix)
+		{
+			ikvm_msync((IntPtr)address, (int)length);
+			GC.KeepAlive(thisMappedByteBuffer);
+		}
+		else
+		{
+			// according to the JDK sources, FlushViewOfFile can fail with an ERROR_LOCK_VIOLATION error,
+			// so like the JDK, we retry up to three times if that happens.
+			for (int i = 0; i < 3; i++)
+			{
+				if (FlushViewOfFile((IntPtr)address, (IntPtr)length) != 0)
+				{
+					GC.KeepAlive(thisMappedByteBuffer);
+					return;
+				}
+				const int ERROR_LOCK_VIOLATION = 33;
+				if (Marshal.GetLastWin32Error() != ERROR_LOCK_VIOLATION)
+				{
+					break;
+				}
+			}
+#if !FIRST_PASS
+			throw new java.io.IOException("Flush failed");
+#endif
+		}
+	}
+
+	[DllImport("kernel32", SetLastError = true)]
+	private static extern int FlushViewOfFile(IntPtr lpBaseAddress, IntPtr dwNumberOfBytesToFlush);
+
+	[DllImport("ikvm-native")]
+	private static extern int ikvm_msync(IntPtr address, int size);
+}
diff --git a/runtime/openjdk/java.security.cs b/runtime/openjdk/java.security.cs
new file mode 100644
index 0000000..4e794d8
--- /dev/null
+++ b/runtime/openjdk/java.security.cs
@@ -0,0 +1,154 @@
+/*
+  Copyright (C) 2007-2013 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using IKVM.Internal;
+
+static class Java_java_security_AccessController
+{
+	public static object getStackAccessControlContext(java.security.AccessControlContext context, ikvm.@internal.CallerID callerID)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		List array = new List();
+		bool is_privileged = GetProtectionDomains(array, callerID, new StackTrace(1));
+		if (array.Count == 0)
+		{
+			if (is_privileged && context == null)
+			{
+				return null;
+			}
+		}
+		return CreateAccessControlContext(array, is_privileged, context);
+#endif
+	}
+
+#if !FIRST_PASS
+	private static bool GetProtectionDomains(List array, ikvm.@internal.CallerID callerID, StackTrace stack)
+	{
+		// first we have to skip all AccessController related frames, because we can be called from a doPrivileged implementation (not the privileged action)
+		// in which case we should ignore the doPrivileged frame
+		int skip = 0;
+		for (; skip < stack.FrameCount; skip++)
+		{
+			Type type  = stack.GetFrame(skip).GetMethod().DeclaringType;
+			if (type != typeof(Java_java_security_AccessController) && type != typeof(java.security.AccessController))
+			{
+				break;
+			}
+		}
+		java.security.ProtectionDomain previous_protection_domain = null;
+		for (int i = skip; i < stack.FrameCount; i++)
+		{
+			bool is_privileged = false;
+			java.security.ProtectionDomain protection_domain;
+			MethodBase method = stack.GetFrame(i).GetMethod();
+			if (method.DeclaringType == typeof(java.security.AccessController)
+				&& method.Name == "doPrivileged")
+			{
+				is_privileged = true;
+				java.lang.Class caller = callerID.getCallerClass();
+				protection_domain = caller == null ? null : Java_java_lang_Class.getProtectionDomain0(caller);
+			}
+			else if (Java_sun_reflect_Reflection.IsHideFromStackWalk(method))
+			{
+				continue;
+			}
+			else
+			{
+				protection_domain = GetProtectionDomainFromType(method.DeclaringType);
+			}
+
+			if (previous_protection_domain != protection_domain && protection_domain != null)
+			{
+				previous_protection_domain = protection_domain;
+				array.Add(protection_domain);
+			}
+
+			if (is_privileged)
+			{
+				return true;
+			}
+		}
+		return false;
+	}
+
+	private static object CreateAccessControlContext(List context, bool is_privileged, java.security.AccessControlContext privileged_context)
+	{
+		java.security.AccessControlContext acc = new java.security.AccessControlContext(context == null || context.Count == 0 ? null : context.ToArray(), is_privileged);
+		acc._privilegedContext(privileged_context);
+		return acc;
+	}
+
+	private static java.security.ProtectionDomain GetProtectionDomainFromType(Type type)
+	{
+		if (type == null
+			|| type.Assembly == typeof(object).Assembly
+			|| type.Assembly == typeof(Java_java_security_AccessController).Assembly
+			|| type.Assembly == Java_java_lang_SecurityManager.jniAssembly
+			|| type.Assembly == typeof(java.lang.Thread).Assembly)
+		{
+			return null;
+		}
+		TypeWrapper tw = ClassLoaderWrapper.GetWrapperFromType(type);
+		if (tw != null)
+		{
+			return Java_java_lang_Class.getProtectionDomain0(tw.ClassObject);
+		}
+		return null;
+	}
+#endif
+
+	public static object getInheritedAccessControlContext()
+	{
+#if FIRST_PASS
+		return null;
+#else
+		object inheritedAccessControlContext = java.lang.Thread.currentThread().inheritedAccessControlContext;
+		java.security.AccessControlContext acc = inheritedAccessControlContext as java.security.AccessControlContext;
+		if (acc != null)
+		{
+			return acc;
+		}
+		java.security.AccessController.LazyContext lc = inheritedAccessControlContext as java.security.AccessController.LazyContext;
+		if (lc == null)
+		{
+			return null;
+		}
+		List list = new List();
+		while (lc != null)
+		{
+			if (GetProtectionDomains(list, lc.callerID, lc.stackTrace))
+			{
+				return CreateAccessControlContext(list, true, lc.context);
+			}
+			lc = lc.parent;
+		}
+		return CreateAccessControlContext(list, false, null);
+#endif
+	}
+}
diff --git a/runtime/openjdk/java.util.cs b/runtime/openjdk/java.util.cs
new file mode 100644
index 0000000..c0d3b82
--- /dev/null
+++ b/runtime/openjdk/java.util.cs
@@ -0,0 +1,339 @@
+/*
+  Copyright (C) 2007-2013 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+
+static class Java_java_util_TimeZone
+{
+	private static string GetCurrentTimeZoneID()
+	{
+#if NET_4_0
+		return TimeZoneInfo.Local.Id;
+#else
+		// we don't want a static dependency on System.Core (to be able to run on .NET 2.0)
+		Type typeofTimeZoneInfo = Type.GetType("System.TimeZoneInfo, System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
+		if (typeofTimeZoneInfo != null)
+		{
+			try
+			{
+				return (string)typeofTimeZoneInfo.GetProperty("Id").GetValue(typeofTimeZoneInfo.GetProperty("Local").GetValue(null, null), null);
+			}
+			catch (Exception x)
+			{
+				// older Mono versions did not wrap the exception in a TargetInvocationExcception,
+				// so we check both x and x.InnerException
+				if (typeofTimeZoneInfo.Assembly.GetType("System.TimeZoneNotFoundException").IsInstanceOfType(x)
+					|| typeofTimeZoneInfo.Assembly.GetType("System.TimeZoneNotFoundException").IsInstanceOfType(x.InnerException))
+				{
+					// MONOBUG Mono's TimeZoneInfo.Local property throws a TimeZoneNotFoundException on Windows
+					// (https://bugzilla.novell.com/show_bug.cgi?id=622524)
+					return TimeZone.CurrentTimeZone.StandardName;
+				}
+				else
+				{
+					throw;
+				}
+			}
+		}
+		else
+		{
+			// HACK this is very lame and probably won't work on localized windows versions
+			return TimeZone.CurrentTimeZone.StandardName;
+		}
+#endif
+	}
+
+	public static string getSystemTimeZoneID(string javaHome)
+	{
+		// (the switch was generated from the contents of $JAVA_HOME/lib/tzmappings)
+		switch (GetCurrentTimeZoneID())
+		{
+			case "Romance":
+			case "Romance Standard Time":
+				return "Europe/Paris";
+			case "Warsaw":
+				return "Europe/Warsaw";
+			case "Central Europe":
+			case "Central Europe Standard Time":
+			case "Prague Bratislava":
+				return "Europe/Prague";
+			case "W. Central Africa Standard Time":
+				return "Africa/Luanda";
+			case "FLE":
+			case "FLE Standard Time":
+				return "Europe/Helsinki";
+			case "GFT":
+			case "GFT Standard Time":
+			case "GTB":
+			case "GTB Standard Time":
+				return "Europe/Athens";
+			case "Israel":
+			case "Israel Standard Time":
+				return "Asia/Jerusalem";
+			case "Arab":
+			case "Arab Standard Time":
+				return "Asia/Riyadh";
+			case "Arabic Standard Time":
+				return "Asia/Baghdad";
+			case "E. Africa":
+			case "E. Africa Standard Time":
+				return "Africa/Nairobi";
+			case "Saudi Arabia":
+			case "Saudi Arabia Standard Time":
+				return "Asia/Riyadh";
+			case "Iran":
+			case "Iran Standard Time":
+				return "Asia/Tehran";
+			case "Afghanistan":
+			case "Afghanistan Standard Time":
+				return "Asia/Kabul";
+			case "India":
+			case "India Standard Time":
+				return "Asia/Calcutta";
+			case "Myanmar Standard Time":
+				return "Asia/Rangoon";
+			case "Nepal Standard Time":
+				return "Asia/Katmandu";
+			case "Sri Lanka":
+			case "Sri Lanka Standard Time":
+				return "Asia/Colombo";
+			case "Beijing":
+			case "China":
+			case "China Standard Time":
+				return "Asia/Shanghai";
+			case "AUS Central":
+			case "AUS Central Standard Time":
+				return "Australia/Darwin";
+			case "Cen. Australia":
+			case "Cen. Australia Standard Time":
+				return "Australia/Adelaide";
+			case "Vladivostok":
+			case "Vladivostok Standard Time":
+				return "Asia/Vladivostok";
+			case "West Pacific":
+			case "West Pacific Standard Time":
+				return "Pacific/Guam";
+			case "E. South America":
+			case "E. South America Standard Time":
+				return "America/Sao_Paulo";
+			case "Greenland Standard Time":
+				return "America/Godthab";
+			case "Newfoundland":
+			case "Newfoundland Standard Time":
+				return "America/St_Johns";
+			case "Pacific SA":
+			case "Pacific SA Standard Time":
+				return "America/Santiago";
+			case "SA Western":
+			case "SA Western Standard Time":
+				return "America/Caracas";
+			case "SA Pacific":
+			case "SA Pacific Standard Time":
+				return "America/Bogota";
+			case "US Eastern":
+			case "US Eastern Standard Time":
+				return "America/Indianapolis";
+			case "Central America Standard Time":
+				return "America/Regina";
+			case "Mexico":
+			case "Mexico Standard Time":
+				return "America/Mexico_City";
+			case "Canada Central":
+			case "Canada Central Standard Time":
+				return "America/Regina";
+			case "US Mountain":
+			case "US Mountain Standard Time":
+				return "America/Phoenix";
+			case "GMT":
+			case "GMT Standard Time":
+				return "Europe/London";
+			case "Ekaterinburg":
+			case "Ekaterinburg Standard Time":
+				return "Asia/Yekaterinburg";
+			case "West Asia":
+			case "West Asia Standard Time":
+				return "Asia/Karachi";
+			case "Central Asia":
+			case "Central Asia Standard Time":
+				return "Asia/Dhaka";
+			case "N. Central Asia Standard Time":
+				return "Asia/Novosibirsk";
+			case "Bangkok":
+			case "Bangkok Standard Time":
+				return "Asia/Bangkok";
+			case "North Asia Standard Time":
+				return "Asia/Krasnoyarsk";
+			case "SE Asia":
+			case "SE Asia Standard Time":
+				return "Asia/Bangkok";
+			case "North Asia East Standard Time":
+				return "Asia/Ulaanbaatar";
+			case "Singapore":
+			case "Singapore Standard Time":
+				return "Asia/Singapore";
+			case "Taipei":
+			case "Taipei Standard Time":
+				return "Asia/Taipei";
+			case "W. Australia":
+			case "W. Australia Standard Time":
+				return "Australia/Perth";
+			case "Korea":
+			case "Korea Standard Time":
+				return "Asia/Seoul";
+			case "Tokyo":
+			case "Tokyo Standard Time":
+				return "Asia/Tokyo";
+			case "Yakutsk":
+			case "Yakutsk Standard Time":
+				return "Asia/Yakutsk";
+			case "Central European":
+			case "Central European Standard Time":
+				return "Europe/Belgrade";
+			case "W. Europe":
+			case "W. Europe Standard Time":
+				return "Europe/Berlin";
+			case "Tasmania":
+			case "Tasmania Standard Time":
+				return "Australia/Hobart";
+			case "AUS Eastern":
+			case "AUS Eastern Standard Time":
+				return "Australia/Sydney";
+			case "E. Australia":
+			case "E. Australia Standard Time":
+				return "Australia/Brisbane";
+			case "Sydney Standard Time":
+				return "Australia/Sydney";
+			case "Central Pacific":
+			case "Central Pacific Standard Time":
+				return "Pacific/Guadalcanal";
+			case "Dateline":
+			case "Dateline Standard Time":
+				return "GMT-1200";
+			case "Fiji":
+			case "Fiji Standard Time":
+				return "Pacific/Fiji";
+			case "Samoa":
+			case "Samoa Standard Time":
+				return "Pacific/Apia";
+			case "Hawaiian":
+			case "Hawaiian Standard Time":
+				return "Pacific/Honolulu";
+			case "Alaskan":
+			case "Alaskan Standard Time":
+				return "America/Anchorage";
+			case "Pacific":
+			case "Pacific Standard Time":
+				return "America/Los_Angeles";
+			case "Mexico Standard Time 2":
+				return "America/Chihuahua";
+			case "Mountain":
+			case "Mountain Standard Time":
+				return "America/Denver";
+			case "Central":
+			case "Central Standard Time":
+				return "America/Chicago";
+			case "Eastern":
+			case "Eastern Standard Time":
+				return "America/New_York";
+			case "E. Europe":
+			case "E. Europe Standard Time":
+				return "Europe/Minsk";
+			case "Egypt":
+			case "Egypt Standard Time":
+				return "Africa/Cairo";
+			case "South Africa":
+			case "South Africa Standard Time":
+				return "Africa/Harare";
+			case "Atlantic":
+			case "Atlantic Standard Time":
+				return "America/Halifax";
+			case "SA Eastern":
+			case "SA Eastern Standard Time":
+				return "America/Buenos_Aires";
+			case "Mid-Atlantic":
+			case "Mid-Atlantic Standard Time":
+				return "Atlantic/South_Georgia";
+			case "Azores":
+			case "Azores Standard Time":
+				return "Atlantic/Azores";
+			case "Cape Verde Standard Time":
+				return "Atlantic/Cape_Verde";
+			case "Russian":
+			case "Russian Standard Time":
+				return "Europe/Moscow";
+			case "New Zealand":
+			case "New Zealand Standard Time":
+				return "Pacific/Auckland";
+			case "Tonga Standard Time":
+				return "Pacific/Tongatapu";
+			case "Arabian":
+			case "Arabian Standard Time":
+				return "Asia/Muscat";
+			case "Caucasus":
+			case "Caucasus Standard Time":
+				return "Asia/Yerevan";
+			case "Greenwich":
+			case "Greenwich Standard Time":
+				return "GMT";
+			case "Central Brazilian Standard Time":
+				return "America/Manaus";
+			case "Central Standard Time (Mexico)":
+				return "America/Mexico_City";
+			case "Georgian Standard Time":
+				return "Asia/Tbilisi";
+			case "Mountain Standard Time (Mexico)":
+				return "America/Chihuahua";
+			case "Namibia Standard Time":
+				return "Africa/Windhoek";
+			case "Pacific Standard Time (Mexico)":
+				return "America/Tijuana";
+			case "Western Brazilian Standard Time":
+				return "America/Rio_Branco";
+			case "Azerbaijan Standard Time":
+				return "Asia/Baku";
+			case "Jordan Standard Time":
+				return "Asia/Amman";
+			case "Middle East Standard Time":
+				return "Asia/Beirut";
+			default:
+				// this means fall back to GMT offset
+				return getSystemGMTOffsetID();
+		}
+	}
+
+	public static string getSystemGMTOffsetID()
+	{
+		TimeSpan sp = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now);
+		int hours = sp.Hours;
+		int mins = sp.Minutes;
+		if (hours >= 0 && mins >= 0)
+		{
+			return String.Format("GMT+{0:D2}:{1:D2}", hours, mins);
+		}
+		else
+		{
+			return String.Format("GMT-{0:D2}:{1:D2}", -hours, -mins);
+		}
+	}
+}
+
diff --git a/runtime/openjdk/java.util.prefs.cs b/runtime/openjdk/java.util.prefs.cs
new file mode 100644
index 0000000..0166e37
--- /dev/null
+++ b/runtime/openjdk/java.util.prefs.cs
@@ -0,0 +1,359 @@
+/*
+  Copyright (C) 2007-2013 Jeroen Frijters
+  Copyright (C) 2009 Volker Berlin (i-net software)
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Principal;
+using System.Text;
+
+static class Java_java_util_prefs_FileSystemPreferences
+{
+	public static int chmod(string filename, int permission)
+	{
+		// TODO
+		return 0;
+	}
+
+	public static int[] lockFile0(string filename, int permission, bool shared)
+	{
+		// TODO
+		return new int[] { 1, 0 };
+	}
+
+	public static int unlockFile0(int fd)
+	{
+		// TODO
+		return 0;
+	}
+}
+
+static class Java_java_util_prefs_WindowsPreferences
+{
+	// HACK we currently support only 16 handles at a time
+	private static readonly Microsoft.Win32.RegistryKey[] keys = new Microsoft.Win32.RegistryKey[16];
+
+	private static Microsoft.Win32.RegistryKey MapKey(int hKey)
+	{
+		switch (hKey)
+		{
+			case unchecked((int)0x80000001):
+				return Microsoft.Win32.Registry.CurrentUser;
+			case unchecked((int)0x80000002):
+				return Microsoft.Win32.Registry.LocalMachine;
+			default:
+				return keys[hKey - 1];
+		}
+	}
+
+	private static int AllocHandle(Microsoft.Win32.RegistryKey key)
+	{
+		lock (keys)
+		{
+			if (key != null)
+			{
+				for (int i = 0; i < keys.Length; i++)
+				{
+					if (keys[i] == null)
+					{
+						keys[i] = key;
+						return i + 1;
+					}
+				}
+			}
+			return 0;
+		}
+	}
+
+	private static string BytesToString(byte[] bytes)
+	{
+		int len = bytes.Length;
+		if (bytes[len - 1] == 0)
+		{
+			len--;
+		}
+		return Encoding.ASCII.GetString(bytes, 0, len);
+	}
+
+	private static byte[] StringToBytes(string str)
+	{
+		if (str.Length == 0 || str[str.Length - 1] != 0)
+		{
+			str += '\u0000';
+		}
+		return Encoding.ASCII.GetBytes(str);
+	}
+
+	public static int[] WindowsRegOpenKey(int hKey, byte[] subKey, int securityMask)
+	{
+		// writeable = DELETE == 0x10000 || KEY_SET_VALUE == 2 || KEY_CREATE_SUB_KEY == 4 || KEY_WRITE = 0x20006;
+		// !writeable : KEY_ENUMERATE_SUB_KEYS == 8 || KEY_READ == 0x20019 || KEY_QUERY_VALUE == 1
+		bool writable = (securityMask & 0x10006) != 0;
+		Microsoft.Win32.RegistryKey resultKey = null;
+		int error = 0;
+		try
+		{
+			Microsoft.Win32.RegistryKey parent = MapKey(hKey);
+			// HACK we check if we can write in the system preferences 
+			// we want not user registry virtualization for compatibility
+			if (writable && parent.Name.StartsWith("HKEY_LOCAL_MACHINE", StringComparison.Ordinal) && UACVirtualization.Enabled)
+			{
+				resultKey = parent.OpenSubKey(BytesToString(subKey), false);
+				if (resultKey != null)
+				{
+					// error only if key exists
+					resultKey.Close();
+					error = 5;
+					resultKey = null;
+				}
+			}
+			else
+			{
+				resultKey = parent.OpenSubKey(BytesToString(subKey), writable);
+			}
+		}
+		catch (SecurityException)
+		{
+			error = 5;
+		}
+		catch (UnauthorizedAccessException)
+		{
+			error = 5;
+		}
+		return new int[] { AllocHandle(resultKey), error };
+	}
+
+	public static int WindowsRegCloseKey(int hKey)
+	{
+		keys[hKey - 1].Close();
+		lock (keys)
+		{
+			keys[hKey - 1] = null;
+		}
+		return 0;
+	}
+
+	public static int[] WindowsRegCreateKeyEx(int hKey, byte[] subKey)
+	{
+		Microsoft.Win32.RegistryKey resultKey = null;
+		int error = 0;
+		int disposition = -1;
+		try
+		{
+			Microsoft.Win32.RegistryKey key = MapKey(hKey);
+			string name = BytesToString(subKey);
+			resultKey = key.OpenSubKey(name);
+			disposition = 2;
+			if (resultKey == null)
+			{
+				resultKey = key.CreateSubKey(name);
+				disposition = 1;
+			}
+		}
+		catch (SecurityException)
+		{
+			error = 5;
+		}
+		catch (UnauthorizedAccessException)
+		{
+			error = 5;
+		}
+		return new int[] { AllocHandle(resultKey), error, disposition };
+	}
+
+	public static int WindowsRegDeleteKey(int hKey, byte[] subKey)
+	{
+		try
+		{
+			MapKey(hKey).DeleteSubKey(BytesToString(subKey), false);
+			return 0;
+		}
+		catch (SecurityException)
+		{
+			return 5;
+		}
+	}
+
+	public static int WindowsRegFlushKey(int hKey)
+	{
+		MapKey(hKey).Flush();
+		return 0;
+	}
+
+	public static byte[] WindowsRegQueryValueEx(int hKey, byte[] valueName)
+	{
+		try
+		{
+			string value = MapKey(hKey).GetValue(BytesToString(valueName)) as string;
+			if (value == null)
+			{
+				return null;
+			}
+			return StringToBytes(value);
+		}
+		catch (SecurityException)
+		{
+			return null;
+		}
+		catch (UnauthorizedAccessException)
+		{
+			return null;
+		}
+	}
+
+	public static int WindowsRegSetValueEx(int hKey, byte[] valueName, byte[] data)
+	{
+		if (valueName == null || data == null)
+		{
+			return -1;
+		}
+		try
+		{
+			MapKey(hKey).SetValue(BytesToString(valueName), BytesToString(data));
+			return 0;
+		}
+		catch (SecurityException)
+		{
+			return 5;
+		}
+		catch (UnauthorizedAccessException)
+		{
+			return 5;
+		}
+	}
+
+	public static int WindowsRegDeleteValue(int hKey, byte[] valueName)
+	{
+		try
+		{
+			MapKey(hKey).DeleteValue(BytesToString(valueName));
+			return 0;
+		}
+		catch (System.ArgumentException)
+		{
+			return 2; //ERROR_FILE_NOT_FOUND
+		}
+		catch (SecurityException)
+		{
+			return 5; //ERROR_ACCESS_DENIED
+		}
+		catch (UnauthorizedAccessException)
+		{
+			return 5; //ERROR_ACCESS_DENIED
+		}
+	}
+
+	public static int[] WindowsRegQueryInfoKey(int hKey)
+	{
+		int[] result = new int[5] { -1, -1, -1, -1, -1 };
+		try
+		{
+			Microsoft.Win32.RegistryKey key = MapKey(hKey);
+			result[0] = key.SubKeyCount;
+			result[1] = 0;
+			result[2] = key.ValueCount;
+			foreach (string s in key.GetSubKeyNames())
+			{
+				result[3] = Math.Max(result[3], s.Length);
+			}
+			foreach (string s in key.GetValueNames())
+			{
+				result[4] = Math.Max(result[4], s.Length);
+			}
+		}
+		catch (SecurityException)
+		{
+			result[1] = 5;
+		}
+		catch (UnauthorizedAccessException)
+		{
+			result[1] = 5;
+		}
+		return result;
+	}
+
+	public static byte[] WindowsRegEnumKeyEx(int hKey, int subKeyIndex, int maxKeyLength)
+	{
+		try
+		{
+			return StringToBytes(MapKey(hKey).GetSubKeyNames()[subKeyIndex]);
+		}
+		catch (SecurityException)
+		{
+			return null;
+		}
+		catch (UnauthorizedAccessException)
+		{
+			return null;
+		}
+	}
+
+	public static byte[] WindowsRegEnumValue(int hKey, int valueIndex, int maxValueNameLength)
+	{
+		try
+		{
+			return StringToBytes(MapKey(hKey).GetValueNames()[valueIndex]);
+		}
+		catch (SecurityException)
+		{
+			return null;
+		}
+		catch (UnauthorizedAccessException)
+		{
+			return null;
+		}
+	}
+}
+
+static class UACVirtualization
+{
+	private enum TOKEN_INFORMATION_CLASS
+	{
+		TokenVirtualizationEnabled = 24
+	}
+
+	[DllImport("advapi32.dll")]
+	private static extern int GetTokenInformation(
+		IntPtr TokenHandle,
+		TOKEN_INFORMATION_CLASS TokenInformationClass,
+		out int TokenInformation,
+		int TokenInformationLength,
+		out int ReturnLength);
+
+	internal static bool Enabled
+	{
+		[SecuritySafeCritical]
+		get
+		{
+			OperatingSystem os = Environment.OSVersion;
+			if (os.Platform != PlatformID.Win32NT || os.Version.Major < 6)
+			{
+				return false;
+			}
+			int enabled, length;
+			return GetTokenInformation(WindowsIdentity.GetCurrent().Token, TOKEN_INFORMATION_CLASS.TokenVirtualizationEnabled, out enabled, 4, out length) != 0
+				&& enabled != 0;
+		}
+	}
+}
diff --git a/runtime/openjdk/misc.cs b/runtime/openjdk/misc.cs
new file mode 100644
index 0000000..396f641
--- /dev/null
+++ b/runtime/openjdk/misc.cs
@@ -0,0 +1,635 @@
+/*
+  Copyright (C) 2007-2015 Jeroen Frijters
+  Copyright (C) 2009 Volker Berlin (i-net software)
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Security;
+using System.Security.Cryptography;
+using System.Security.Principal;
+using IKVM.Internal;
+
+static class Java_ikvm_runtime_Startup
+{
+	// this method is called from ikvm.runtime.Startup.exitMainThread() and from JNI's DetachCurrentThread
+	public static void jniDetach()
+	{
+#if !FIRST_PASS
+		java.lang.Thread.currentThread().die();
+#endif
+	}
+
+	public static void addBootClassPathAssembly(Assembly asm)
+	{
+		ClassLoaderWrapper.GetBootstrapClassLoader().AddDelegate(AssemblyClassLoader.FromAssembly(asm));
+	}
+}
+
+static class Java_java_lang_ref_Reference
+{
+	public static bool noclassgc()
+	{
+#if CLASSGC
+		return !JVM.classUnloading;
+#else
+		return true;
+#endif
+	}
+}
+
+static class Java_java_util_logging_FileHandler
+{
+	public static bool isSetUID()
+	{
+		// TODO
+		return false;
+	}
+}
+
+static class Java_java_util_jar_JarFile
+{
+	public static string[] getMetaInfEntryNames(object thisJarFile)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		java.util.zip.ZipFile zf = (java.util.zip.ZipFile)thisJarFile;
+		java.util.Enumeration entries = zf.entries();
+		List list = null;
+		while (entries.hasMoreElements())
+		{
+			java.util.zip.ZipEntry entry = (java.util.zip.ZipEntry)entries.nextElement();
+			if (entry.getName().StartsWith("META-INF/", StringComparison.OrdinalIgnoreCase))
+			{
+				if (list == null)
+				{
+					list = new List();
+				}
+				list.Add(entry.getName());
+			}
+		}
+		return list == null ? null : list.ToArray();
+#endif
+	}
+}
+
+static class Java_java_util_zip_ClassStubZipEntry
+{
+	public static void expandIkvmClasses(object _zipFile, object _entries)
+	{
+#if !FIRST_PASS
+		java.util.zip.ZipFile zipFile = (java.util.zip.ZipFile)_zipFile;
+		java.util.LinkedHashMap entries = (java.util.LinkedHashMap)_entries;
+
+		try
+		{
+			string path = zipFile.getName();
+			java.util.zip.ZipEntry entry = (java.util.zip.ZipEntry)entries.get(JVM.JarClassList);
+			if (entry != null && VirtualFileSystem.IsVirtualFS(path))
+			{
+				using (VirtualFileSystem.ZipEntryStream stream = new VirtualFileSystem.ZipEntryStream(zipFile, entry))
+				{
+					entries.remove(entry.name);
+					BinaryReader br = new BinaryReader(stream);
+					int count = br.ReadInt32();
+					for (int i = 0; i < count; i++)
+					{
+						java.util.zip.ClassStubZipEntry classEntry = new java.util.zip.ClassStubZipEntry(path, br.ReadString());
+						classEntry.setMethod(java.util.zip.ClassStubZipEntry.STORED);
+						classEntry.setTime(entry.getTime());
+						entries.put(classEntry.name, classEntry);
+					}
+				}
+			}
+		}
+		catch (java.io.IOException)
+		{
+		}
+		catch (IOException)
+		{
+		}
+#endif
+	}
+}
+
+static class Java_java_awt_Choice
+{
+	public static void initIDs()
+	{
+	}
+}
+
+static class Java_sun_awt_image_ByteComponentRaster
+{
+	public static void initIDs()
+	{
+	}
+}
+
+static class Java_sun_awt_image_BytePackedRaster
+{
+	public static void initIDs()
+	{
+	}
+}
+
+static class Java_sun_awt_image_IntegerComponentRaster
+{
+	public static void initIDs()
+	{
+	}
+}
+
+static class Java_sun_awt_image_ShortComponentRaster
+{
+	public static void initIDs()
+	{
+	}
+}
+
+static class Java_sun_awt_DefaultMouseInfoPeer
+{
+	public static int fillPointWithCoords(object _this, object point)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static bool isWindowUnderMouse(object _this, object w)
+	{
+		throw new NotImplementedException();
+	}
+}
+
+static class Java_sun_awt_FontDescriptor
+{
+	public static void initIDs()
+	{
+	}
+}
+
+static class Java_sun_invoke_anon_AnonymousClassLoader
+{
+	public static java.lang.Class loadClassInternal(java.lang.Class hostClass, byte[] classFile, object[] patchArray)
+	{
+		throw new NotImplementedException();
+	}
+}
+
+static class Java_sun_invoke_util_VerifyAccess
+{
+	// called from map.xml as a replacement for Class.getClassLoader() in sun.invoke.util.VerifyAccess.isTypeVisible()
+	public static java.lang.ClassLoader Class_getClassLoader(java.lang.Class clazz)
+	{
+		TypeWrapper tw = TypeWrapper.FromClass(clazz);
+		if (ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedNameFast(tw.Name) == tw)
+		{
+			// if a class is visible from the bootstrap class loader, we have to return null to allow the visibility check to succeed
+			return null;
+		}
+		return tw.GetClassLoader().GetJavaClassLoader();
+	}
+}
+
+static class Java_sun_net_PortConfig
+{
+	public static int getLower0()
+	{
+		return 49152;
+	}
+
+	public static int getUpper0()
+	{
+		return 65535;
+	}
+}
+
+static class Java_sun_net_spi_DefaultProxySelector
+{
+	public static bool init()
+	{
+		return true;
+	}
+
+	public static object getSystemProxy(object thisDefaultProxySelector, string protocol, string host)
+	{
+		// TODO on Whidbey we might be able to use System.Net.Configuration.DefaultProxySection.Proxy
+		return null;
+	}
+}
+
+static class Java_sun_nio_fs_NetPath
+{
+	public static string toRealPathImpl(string path)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		path = java.io.DefaultFileSystem.getFileSystem().canonicalize(path);
+		if (VirtualFileSystem.IsVirtualFS(path))
+		{
+			if (VirtualFileSystem.CheckAccess(path, Java_java_io_WinNTFileSystem.ACCESS_READ))
+			{
+				return path;
+			}
+			throw new java.nio.file.NoSuchFileException(path);
+		}
+		try
+		{
+			File.GetAttributes(path);
+			return path;
+		}
+		catch (FileNotFoundException)
+		{
+			throw new java.nio.file.NoSuchFileException(path);
+		}
+		catch (DirectoryNotFoundException)
+		{
+			throw new java.nio.file.NoSuchFileException(path);
+		}
+		catch (UnauthorizedAccessException)
+		{
+			throw new java.nio.file.AccessDeniedException(path);
+		}
+		catch (SecurityException)
+		{
+			throw new java.nio.file.AccessDeniedException(path);
+		}
+		catch (ArgumentException x)
+		{
+			throw new java.nio.file.FileSystemException(path, null, x.Message);
+		}
+		catch (NotSupportedException x)
+		{
+			throw new java.nio.file.FileSystemException(path, null, x.Message);
+		}
+		catch (IOException x)
+		{
+			throw new java.nio.file.FileSystemException(path, null, x.Message);
+		}
+#endif
+	}
+}
+
+static class Java_sun_security_provider_NativeSeedGenerator
+{
+	public static bool nativeGenerateSeed(byte[] result)
+	{
+		try
+		{
+			RNGCryptoServiceProvider csp = new RNGCryptoServiceProvider();
+			csp.GetBytes(result);
+#if NET_4_0
+			csp.Dispose();
+#endif
+			return true;
+		}
+		catch (CryptographicException)
+		{
+			return false;
+		}
+	}
+}
+
+static class Java_com_sun_java_util_jar_pack_NativeUnpack
+{
+	public static void initIDs()
+	{
+	}
+
+	public static long start(object thisNativeUnpack, object buf, long offset)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static bool getNextFile(object thisNativeUnpack, object[] parts)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static object getUnusedInput(object thisNativeUnpack)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static long finish(object thisNativeUnpack)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static bool setOption(object thisNativeUnpack, string opt, string value)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static string getOption(object thisNativeUnpack, string opt)
+	{
+		throw new NotImplementedException();
+	}
+}
+
+static class Java_com_sun_security_auth_module_NTSystem
+{
+	public static void getCurrent(object thisObj, bool debug, ref string userName, ref string domain, ref string domainSID, ref string userSID, ref string[] groupIDs, ref string primaryGroupID)
+	{
+		WindowsIdentity id = WindowsIdentity.GetCurrent();
+		string[] name = id.Name.Split('\\');
+		userName = name[1];
+		domain = name[0];
+		domainSID = id.User.AccountDomainSid.Value;
+		userSID = id.User.Value;
+		string[] groups = new string[id.Groups.Count];
+		for (int i = 0; i < groups.Length; i++)
+		{
+			groups[i] = id.Groups[i].Value;
+		}
+		groupIDs = groups;
+		// HACK it turns out that Groups[0] is the primary group, but AFAIK this is not documented anywhere
+		primaryGroupID = groups[0];
+	}
+
+	public static long getImpersonationToken0(object thisObj)
+	{
+		return WindowsIdentity.GetCurrent().Token.ToInt64();
+	}
+}
+
+static class Java_com_sun_media_sound_JDK13Services
+{
+	public static string getDefaultProviderClassName(object deviceClass)
+	{
+		return null;
+	}
+
+	public static string getDefaultInstanceName(object deviceClass)
+	{
+		return null;
+	}
+
+	public static object getProviders(object providerClass)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		return new java.util.ArrayList();
+#endif
+	}
+}
+
+static class Java_java_awt_AWTEvent
+{
+	public static void initIDs() { }
+	public static void nativeSetSource(object thisObj, object peer) { }
+}
+
+static class Java_java_awt_Button
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_Checkbox
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_CheckboxMenuItem
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_Color
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_Component
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_Container
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_Cursor
+{
+	public static void initIDs() { }
+	public static void finalizeImpl(Int64 pData) { }
+}
+
+static class Java_java_awt_Dialog
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_Dimension
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_Event
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_FileDialog
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_Frame
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_FontMetrics
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_Insets
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_KeyboardFocusManager
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_Label
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_Menu
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_MenuBar
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_MenuComponent
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_MenuItem
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_Rectangle
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_Scrollbar
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_ScrollPane
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_ScrollPaneAdjustable
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_SplashScreen
+{
+	public static void _update(long splashPtr, int[] data, int x, int y, int width, int height, int scanlineStride) { }
+	public static bool _isVisible(long splashPtr) { return false; }
+	public static object _getBounds(long splashPtr) { return null; }
+	public static long _getInstance() { return 0; }
+	public static void _close(long splashPtr) { }
+	public static String _getImageFileName(long splashPtr) { return null; }
+	public static String _getImageJarName(long splashPtr) { return null; }
+	public static bool _setImageData(long splashPtr, byte[] data) { return false; }
+	public static float _getScaleFactor(long SplashPtr) { return 1; }
+}
+
+static class Java_java_awt_TextArea
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_TextField
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_Toolkit
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_TrayIcon
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_Window
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_event_InputEvent
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_event_MouseEvent
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_event_KeyEvent
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_image_ColorModel
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_image_ComponentSampleModel
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_image_Kernel
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_image_Raster
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_image_SinglePixelPackedSampleModel
+{
+	public static void initIDs() { }
+}
+
+static class Java_java_awt_image_SampleModel
+{
+	public static void initIDs() { }
+}
+
+static class Java_sun_net_ExtendedOptionsImpl
+{
+	public static void init()
+	{
+	}
+
+	public static void setFlowOption(java.io.FileDescriptor fd, object f)
+	{
+#if !FIRST_PASS
+		throw new java.lang.UnsupportedOperationException();
+#endif
+	}
+
+	public static void getFlowOption(java.io.FileDescriptor fd, object f)
+	{
+#if !FIRST_PASS
+		throw new java.lang.UnsupportedOperationException();
+#endif
+	}
+
+	public static bool flowSupported()
+	{
+		// We don't support this. Solaris only functionality.
+		return false;
+	}
+}
diff --git a/runtime/openjdk/sun.management.cs b/runtime/openjdk/sun.management.cs
new file mode 100644
index 0000000..1270be4
--- /dev/null
+++ b/runtime/openjdk/sun.management.cs
@@ -0,0 +1,354 @@
+/*
+  Copyright (C) 2011-2014 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Reflection;
+#if !FIRST_PASS
+using java.lang.management;
+#endif
+
+static class Java_sun_management_ClassLoadingImpl
+{
+	public static void setVerboseClass(bool value)
+	{
+	}
+}
+
+static class Java_sun_management_FileSystemImpl
+{
+    public static void init0()
+	{
+	}
+
+	public static bool isSecuritySupported0(string path)
+	{
+		throw new NotSupportedException();
+	}
+
+	public static bool isAccessUserOnly0(string path)
+	{
+		throw new NotSupportedException();
+	}
+}
+
+static class Java_sun_management_GcInfoBuilder
+{
+	public static int getNumGcExtAttributes(object _this, object gc)
+	{
+		throw new NotSupportedException();
+	}
+
+	public static void fillGcAttributeInfo(object _this, object gc, int numAttributes, string[] attributeNames, char[] types, string[] descriptions)
+	{
+		throw new NotSupportedException();
+	}
+
+	public static object getLastGcInfo0(object _this, object gc, int numExtAtts, object[] extAttValues, char[] extAttTypes, object[] before, object[] after)
+	{
+		throw new NotSupportedException();
+	}
+}
+
+static class Java_sun_management_MemoryImpl
+{
+	public static object getMemoryPools0()
+	{
+#if FIRST_PASS
+		return null;
+#else
+		return new MemoryPoolMXBean[0];
+#endif
+	}
+
+	public static object getMemoryManagers0()
+	{
+#if FIRST_PASS
+		return null;
+#else
+		return new MemoryManagerMXBean[0];
+#endif
+	}
+
+	public static object getMemoryUsage0(object impl, bool heap)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		long mem = System.GC.GetTotalMemory(false);
+		return new MemoryUsage(-1, mem, mem, -1);
+#endif
+	}
+
+	public static void setVerboseGC(object impl, bool value)
+	{
+	}
+}
+
+static class Java_sun_management_OperatingSystemImpl
+{
+	private static long getComputerInfo(string property){
+#pragma warning disable 618
+        Assembly asm = Assembly.LoadWithPartialName("Microsoft.VisualBasic");
+#pragma warning restore 618
+        if (asm != null)
+        {
+            Type type = asm.GetType("Microsoft.VisualBasic.Devices.ComputerInfo");
+            if (type != null)
+            {
+                try
+                {
+                    ulong result = (ulong)type.GetProperty(property).GetValue(Activator.CreateInstance(type), null);
+                    return (long)result;
+                }
+                catch (TargetInvocationException)
+                {
+                    // Mono does not implement this property
+                }
+            }
+        }
+		throw new System.NotImplementedException();
+	}
+
+	public static long getCommittedVirtualMemorySize0(object _this)
+	{
+		throw new System.NotImplementedException();
+	}
+
+	public static long getTotalSwapSpaceSize(object _this)
+	{
+		throw new System.NotImplementedException();
+	}
+
+	public static long getFreeSwapSpaceSize(object _this)
+	{
+		throw new System.NotImplementedException();
+	}
+
+	public static long getProcessCpuTime(object _this)
+	{
+		throw new System.NotImplementedException();
+	}
+
+	public static long getFreePhysicalMemorySize(object _this)
+	{
+		return getComputerInfo("AvailablePhysicalMemory");
+	}
+
+	public static long getTotalPhysicalMemorySize(object _this)
+	{
+	    return getComputerInfo("TotalPhysicalMemory");
+	}
+
+	public static double getSystemCpuLoad(object _this)
+	{
+		throw new System.NotImplementedException();
+	}
+
+	public static double getProcessCpuLoad(object _this)
+	{
+		throw new System.NotImplementedException();
+	}
+
+	public static void initialize()
+	{
+	}
+}
+
+static class Java_sun_management_ThreadImpl
+{
+	public static object getThreads()
+	{
+        return Java_java_lang_Thread.getThreads();
+	}
+
+    private const int JVMTI_THREAD_STATE_ALIVE = 0x0001;
+    private const int JVMTI_THREAD_STATE_TERMINATED = 0x0002;
+    private const int JVMTI_THREAD_STATE_RUNNABLE = 0x0004;
+    private const int JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER = 0x0400;
+    private const int JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010;
+    private const int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020;
+    private const int JMM_THREAD_STATE_FLAG_SUSPENDED = 0x00100000;
+    private const int JMM_THREAD_STATE_FLAG_NATIVE = 0x00400000;
+
+	public static void getThreadInfo1(long[] ids, int maxDepth, object result)
+	{
+#if !FIRST_PASS
+
+        System.Reflection.ConstructorInfo[] constructors = typeof(java.lang.management.ThreadInfo).GetConstructors( System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
+        foreach (System.Reflection.ConstructorInfo constructor in constructors)
+        {
+            if (constructor.GetParameters().Length == 9)
+            {
+                java.lang.Thread[] threads = (java.lang.Thread[])getThreads();
+                java.lang.management.ThreadInfo[] threadInfos = (java.lang.management.ThreadInfo[])result;
+                for (int i = 0; i < ids.Length; i++)
+                {
+                    long id = ids[i];
+                    for (int t = 0; t < threads.Length; t++)
+                    {
+                        if (threads[t].getId() == id)
+                        {
+                            java.lang.Thread thread = threads[t];
+
+                            int state;
+                            // invers to sun.misc.VM.toThreadState
+                            switch(thread.getState().ordinal())
+                            {
+                                case (int)java.lang.Thread.State.__Enum.RUNNABLE:
+                                    state = JVMTI_THREAD_STATE_RUNNABLE;
+                                    break;
+                                case (int)java.lang.Thread.State.__Enum.BLOCKED:
+                                    state = JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
+                                    break;
+                                case (int)java.lang.Thread.State.__Enum.WAITING:
+                                    state = JVMTI_THREAD_STATE_WAITING_INDEFINITELY;
+                                    break;
+                                case (int)java.lang.Thread.State.__Enum.TIMED_WAITING:
+                                    state = JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT;
+                                    break;
+                                case (int)java.lang.Thread.State.__Enum.TERMINATED:
+                                    state = JVMTI_THREAD_STATE_TERMINATED;
+                                    break;
+                                case (int)java.lang.Thread.State.__Enum.NEW:
+                                    state = JVMTI_THREAD_STATE_ALIVE;
+                                    break;
+                                default:
+                                    state = 0;
+                                    break;
+                            }
+                            //TODO set in state JMM_THREAD_STATE_FLAG_SUSPENDED if the thread is suspended
+
+                            java.lang.StackTraceElement[] stacktrace = thread.getStackTrace();
+                            if (maxDepth >= 0 && maxDepth < stacktrace.Length)
+                            {
+                                java.lang.StackTraceElement[] temp = new java.lang.StackTraceElement[maxDepth];
+                                System.Array.Copy(stacktrace, temp, temp.Length);
+                                stacktrace = temp;
+                            }
+
+                            object[] parameters = new object[9];
+                            parameters[0] = thread;                     // thread
+                            parameters[1] = state;                      // state
+                                                                        // lockObj
+                                                                        // lockOwner
+                            parameters[4] = 0;                          // blockedCount
+                            parameters[5] = 0;                          // blockedTime
+                            parameters[6] = -1;                         // waitedCount
+                            parameters[7] = 0;                          // waitedTime
+                            parameters[8] = stacktrace;                 // stackTrace
+                            threadInfos[i] = (java.lang.management.ThreadInfo)constructor.Invoke(parameters);
+                            break;
+                        }
+                    }
+                }
+                return;
+            }
+        }
+        throw new java.lang.InternalError("Constructor for java.lang.management.ThreadInfo not find.");
+#endif
+    }
+
+	private static int GetCurrentThreadId()
+	{
+#pragma warning disable 618
+		// On the CLR and Mono on Windows this is the (obsolete) equivalent of kernel32!GetCurrentThreadId
+		return System.AppDomain.GetCurrentThreadId();
+#pragma warning restore 618
+	}
+
+	public static long getThreadTotalCpuTime0(long id)
+	{
+        if (id == 0) {
+            int currentId = GetCurrentThreadId();
+            System.Diagnostics.ProcessThreadCollection threads = System.Diagnostics.Process.GetCurrentProcess().Threads;
+            foreach (System.Diagnostics.ProcessThread t in threads) {
+                if (t.Id == currentId) {
+                    return (long)(t.TotalProcessorTime.Ticks * 100);
+                }
+            }
+            return 0;
+        } else {
+            throw new System.NotImplementedException("Only current Thread is supported.");
+        }
+	}
+
+	public static void getThreadTotalCpuTime1(long[] ids, long[] result)
+	{
+		throw new System.NotImplementedException();
+	}
+
+	public static long getThreadUserCpuTime0(long id)
+	{
+		throw new System.NotImplementedException();
+	}
+
+	public static void getThreadUserCpuTime1(long[] ids, long[] result)
+	{
+		throw new System.NotImplementedException();
+	}
+
+	public static void getThreadAllocatedMemory1(long[] ids, long[] result)
+	{
+		throw new System.NotImplementedException();
+	}
+
+	public static void setThreadCpuTimeEnabled0(bool enable)
+	{
+		//ignoring, we need nothing to enable
+	}
+
+	public static void setThreadAllocatedMemoryEnabled0(bool enable)
+	{
+		throw new System.NotImplementedException();
+	}
+
+	public static void setThreadContentionMonitoringEnabled0(bool enable)
+	{
+		throw new System.NotImplementedException();
+	}
+
+	public static object findMonitorDeadlockedThreads0()
+	{
+		throw new System.NotImplementedException();
+	}
+
+	public static object findDeadlockedThreads0()
+	{
+		throw new System.NotImplementedException();
+	}
+
+	public static void resetPeakThreadCount0()
+	{
+		throw new System.NotImplementedException();
+	}
+
+	public static object dumpThreads0(long[] ids, bool lockedMonitors, bool lockedSynchronizers)
+	{
+		throw new System.NotImplementedException();
+	}
+
+	public static void resetContentionTimes0(long tid)
+	{
+		throw new System.NotImplementedException();
+	}
+}
diff --git a/runtime/openjdk/sun.misc.cs b/runtime/openjdk/sun.misc.cs
new file mode 100644
index 0000000..45939f1
--- /dev/null
+++ b/runtime/openjdk/sun.misc.cs
@@ -0,0 +1,829 @@
+/*
+  Copyright (C) 2007-2015 Jeroen Frijters
+  Copyright (C) 2009 Volker Berlin (i-net software)
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+using System.Security;
+using System.Threading;
+using IKVM.Internal;
+
+static class Java_sun_misc_GC
+{
+	public static long maxObjectInspectionAge()
+	{
+		return 0;
+	}
+}
+
+static class Java_sun_misc_MessageUtils
+{
+	public static void toStderr(string msg)
+	{
+		Console.Error.Write(msg);
+	}
+
+	public static void toStdout(string msg)
+	{
+		Console.Out.Write(msg);
+	}
+}
+
+static class Java_sun_misc_MiscHelper
+{
+	public static object getAssemblyClassLoader(Assembly asm, object extcl)
+	{
+		if (extcl == null || asm.IsDefined(typeof(IKVM.Attributes.CustomAssemblyClassLoaderAttribute), false))
+		{
+			return AssemblyClassLoader.FromAssembly(asm).GetJavaClassLoader();
+		}
+		return null;
+	}
+}
+
+static class Java_sun_misc_Signal
+{
+	/* derived from version 6.0 VC98/include/signal.h */
+	private const int SIGINT = 2;       /* interrupt */
+	private const int SIGILL = 4;       /* illegal instruction - invalid function image */
+	private const int SIGFPE = 8;       /* floating point exception */
+	private const int SIGSEGV = 11;     /* segment violation */
+	private const int SIGTERM = 15;     /* Software termination signal from kill */
+	private const int SIGBREAK = 21;    /* Ctrl-Break sequence */
+	private const int SIGABRT = 22;     /* abnormal termination triggered by abort call */
+
+	private static Dictionary handler = new Dictionary();
+
+	// Delegate type to be used as the Handler Routine for SetConsoleCtrlHandler
+	private delegate Boolean ConsoleCtrlDelegate(CtrlTypes CtrlType);
+
+	// Enumerated type for the control messages sent to the handler routine
+	private enum CtrlTypes : uint
+	{
+		CTRL_C_EVENT = 0,
+		CTRL_BREAK_EVENT,
+		CTRL_CLOSE_EVENT,
+		CTRL_LOGOFF_EVENT = 5,
+		CTRL_SHUTDOWN_EVENT
+	}
+
+	[SecurityCritical]
+	private sealed class CriticalCtrlHandler : CriticalFinalizerObject
+	{
+		private ConsoleCtrlDelegate consoleCtrlDelegate;
+		private bool ok;
+
+		[DllImport("kernel32.dll")]
+		private static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate e, bool add);
+
+		internal CriticalCtrlHandler()
+		{
+			consoleCtrlDelegate = new ConsoleCtrlDelegate(ConsoleCtrlCheck);
+			ok = SetConsoleCtrlHandler(consoleCtrlDelegate, true);
+		}
+
+		[SecuritySafeCritical]
+		~CriticalCtrlHandler()
+		{
+			if (ok)
+			{
+				SetConsoleCtrlHandler(consoleCtrlDelegate, false);
+			}
+		}
+	}
+
+	private static object defaultConsoleCtrlDelegate;
+
+	private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
+	{
+#if !FIRST_PASS
+		switch (ctrlType)
+		{
+			case CtrlTypes.CTRL_BREAK_EVENT:
+				DumpAllJavaThreads();
+				return true;
+
+		}
+#endif
+		return false;
+	}
+
+#if !FIRST_PASS
+	private static void DumpAllJavaThreads()
+	{
+		Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
+		java.util.Map traces = java.lang.Thread.getAllStackTraces();
+		Console.WriteLine("Full thread dump IKVM.NET {0} ({1} bit):", JVM.SafeGetAssemblyVersion(Assembly.GetExecutingAssembly()), IntPtr.Size * 8);
+		java.util.Iterator entries = traces.entrySet().iterator();
+		while (entries.hasNext())
+		{
+			java.util.Map.Entry entry = (java.util.Map.Entry)entries.next();
+			java.lang.Thread thread = (java.lang.Thread)entry.getKey();
+			Console.WriteLine("\n\"{0}\"{1} prio={2} tid=0x{3:X8}", thread.getName(), thread.isDaemon() ? " daemon" : "", thread.getPriority(), thread.getId());
+			Console.WriteLine("   java.lang.Thread.State: " + thread.getState());
+			java.lang.StackTraceElement[] trace = (java.lang.StackTraceElement[])entry.getValue();
+			for (int i = 0; i < trace.Length; i++)
+			{
+				Console.WriteLine("\tat {0}", trace[i]);
+			}
+		}
+		Console.WriteLine();
+	}
+#endif
+
+	public static int findSignal(string sigName)
+	{
+		if (Environment.OSVersion.Platform == PlatformID.Win32NT)
+		{
+			switch (sigName)
+			{
+				case "ABRT": /* abnormal termination triggered by abort cl */
+					return SIGABRT;
+				case "FPE": /* floating point exception */
+					return SIGFPE;
+				case "SEGV": /* segment violation */
+					return SIGSEGV;
+				case "INT": /* interrupt */
+					return SIGINT;
+				case "TERM": /* software term signal from kill */
+					return SIGTERM;
+				case "BREAK": /* Ctrl-Break sequence */
+					return SIGBREAK;
+				case "ILL": /* illegal instruction */
+					return SIGILL;
+			}
+		}
+		return -1;
+	}
+
+	// this is a separate method to be able to catch the SecurityException (for the LinkDemand)
+	[SecuritySafeCritical]
+	private static void RegisterCriticalCtrlHandler()
+	{
+		defaultConsoleCtrlDelegate = new CriticalCtrlHandler();
+	}
+
+	// Register a signal handler
+	public static long handle0(int sig, long nativeH)
+	{
+		long oldHandler;
+		handler.TryGetValue(sig, out oldHandler);
+		switch (nativeH)
+		{
+			case 0: // Default Signal Handler
+				if (defaultConsoleCtrlDelegate == null && Environment.OSVersion.Platform == PlatformID.Win32NT)
+				{
+					try
+					{
+						RegisterCriticalCtrlHandler();
+					}
+					catch (SecurityException)
+					{
+					}
+				}
+				break;
+			case 1: // Ignore Signal
+				break;
+			case 2: // Custom Signal Handler
+				switch (sig)
+				{
+					case SIGBREAK:
+					case SIGFPE:
+						return -1;
+				}
+				break;
+		}
+		handler[sig] = nativeH;
+		return oldHandler;
+	}
+
+	public static void raise0(int sig)
+	{
+#if !FIRST_PASS
+		java.security.AccessController.doPrivileged(ikvm.runtime.Delegates.toPrivilegedAction(delegate
+		{
+			java.lang.Class clazz = typeof(sun.misc.Signal);
+			java.lang.reflect.Method dispatch = clazz.getDeclaredMethod("dispatch", java.lang.Integer.TYPE);
+			dispatch.setAccessible(true);
+			dispatch.invoke(null, java.lang.Integer.valueOf(sig));
+			return null;
+		}));
+#endif
+	}
+}
+
+static class Java_sun_misc_NativeSignalHandler
+{
+	public static void handle0(int number, long handler)
+	{
+		throw new NotImplementedException();
+	}
+}
+
+static class Java_sun_misc_Perf
+{
+	public static object attach(object thisPerf, string user, int lvmid, int mode)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static void detach(object thisPerf, object bb)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static object createLong(object thisPerf, string name, int variability, int units, long value)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		return java.nio.ByteBuffer.allocate(8);
+#endif
+	}
+
+	public static object createByteArray(object thisPerf, string name, int variability, int units, byte[] value, int maxLength)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		return java.nio.ByteBuffer.allocate(maxLength).put(value);
+#endif
+	}
+
+	public static long highResCounter(object thisPerf)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static long highResFrequency(object thisPerf)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static void registerNatives()
+	{
+	}
+}
+
+static class Java_sun_misc_Unsafe
+{
+	public static java.lang.reflect.Field createFieldAndMakeAccessible(java.lang.Class c, string fieldName)
+	{
+#if FIRST_PASS
+		return null;
+#else
+        // we pass in ReflectAccess.class as the field type (which isn't used)
+        // to make Field.toString() return something "meaningful" instead of crash
+        java.lang.reflect.Field field = new java.lang.reflect.Field(c, fieldName, ikvm.@internal.ClassLiteral.Value, 0, -1, null, null);
+        field.@override = true;
+        return field;
+#endif
+	}
+
+	public static java.lang.reflect.Field copyFieldAndMakeAccessible(java.lang.reflect.Field field)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		field = new java.lang.reflect.Field(field.getDeclaringClass(), field.getName(), field.getType(), field.getModifiers() & ~java.lang.reflect.Modifier.FINAL, field._slot(), null, null);
+		field.@override = true;
+		return field;
+#endif
+	}
+
+	private static void CheckArrayBounds(object obj, long offset, int accessLength)
+	{
+		// NOTE we rely on the fact that Buffer.ByteLength() requires a primitive array
+		int arrayLength = Buffer.ByteLength((Array)obj);
+		if (offset < 0 || offset > arrayLength - accessLength || accessLength > arrayLength)
+		{
+			throw new IndexOutOfRangeException();
+		}
+	}
+
+	[SecuritySafeCritical]
+	public static short ReadInt16(object obj, long offset)
+	{
+		Stats.Log("ReadInt16");
+		CheckArrayBounds(obj, offset, 2);
+		GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
+		short value = Marshal.ReadInt16((IntPtr)(handle.AddrOfPinnedObject().ToInt64() + offset));
+		handle.Free();
+		return value;
+	}
+
+	[SecuritySafeCritical]
+	public static int ReadInt32(object obj, long offset)
+	{
+		Stats.Log("ReadInt32");
+		CheckArrayBounds(obj, offset, 4);
+		GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
+		int value = Marshal.ReadInt32((IntPtr)(handle.AddrOfPinnedObject().ToInt64() + offset));
+		handle.Free();
+		return value;
+	}
+
+	[SecuritySafeCritical]
+	public static long ReadInt64(object obj, long offset)
+	{
+		Stats.Log("ReadInt64");
+		CheckArrayBounds(obj, offset, 8);
+		GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
+		long value = Marshal.ReadInt64((IntPtr)(handle.AddrOfPinnedObject().ToInt64() + offset));
+		handle.Free();
+		return value;
+	}
+
+	[SecuritySafeCritical]
+	public static void WriteInt16(object obj, long offset, short value)
+	{
+		Stats.Log("WriteInt16");
+		CheckArrayBounds(obj, offset, 2);
+		GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
+		Marshal.WriteInt16((IntPtr)(handle.AddrOfPinnedObject().ToInt64() + offset), value);
+		handle.Free();
+	}
+
+	[SecuritySafeCritical]
+	public static void WriteInt32(object obj, long offset, int value)
+	{
+		Stats.Log("WriteInt32");
+		CheckArrayBounds(obj, offset, 4);
+		GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
+		Marshal.WriteInt32((IntPtr)(handle.AddrOfPinnedObject().ToInt64() + offset), value);
+		handle.Free();
+	}
+
+	[SecuritySafeCritical]
+	public static void WriteInt64(object obj, long offset, long value)
+	{
+		Stats.Log("WriteInt64");
+		CheckArrayBounds(obj, offset, 8);
+		GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
+		Marshal.WriteInt64((IntPtr)(handle.AddrOfPinnedObject().ToInt64() + offset), value);
+		handle.Free();
+	}
+
+	public static void throwException(object thisUnsafe, Exception x)
+	{
+		throw x;
+	}
+
+	public static bool shouldBeInitialized(object thisUnsafe, java.lang.Class clazz)
+	{
+		return TypeWrapper.FromClass(clazz).HasStaticInitializer;
+	}
+
+	public static void ensureClassInitialized(object thisUnsafe, java.lang.Class clazz)
+	{
+		TypeWrapper tw = TypeWrapper.FromClass(clazz);
+		if (!tw.IsArray)
+		{
+			try
+			{
+				tw.Finish();
+			}
+			catch (RetargetableJavaException x)
+			{
+				throw x.ToJava();
+			}
+			tw.RunClassInit();
+		}
+	}
+
+	[SecurityCritical]
+	public static object allocateInstance(object thisUnsafe, java.lang.Class clazz)
+	{
+		TypeWrapper wrapper = TypeWrapper.FromClass(clazz);
+		try
+		{
+			wrapper.Finish();
+		}
+		catch (RetargetableJavaException x)
+		{
+			throw x.ToJava();
+		}
+		return FormatterServices.GetUninitializedObject(wrapper.TypeAsBaseType);
+	}
+
+	public static java.lang.Class defineClass(object thisUnsafe, string name, byte[] buf, int offset, int length, java.lang.ClassLoader cl, java.security.ProtectionDomain pd)
+	{
+		return Java_java_lang_ClassLoader.defineClass1(cl, name.Replace('/', '.'), buf, offset, length, pd, null);
+	}
+
+	public static java.lang.Class defineClass(object thisUnsafe, string name, byte[] buf, int offset, int length, ikvm.@internal.CallerID callerID)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		return defineClass(thisUnsafe, name, buf, offset, length, callerID.getCallerClassLoader(), callerID.getCallerClass().pd);
+#endif
+	}
+
+	public static java.lang.Class defineAnonymousClass(object thisUnsafe, java.lang.Class host, byte[] data, object[] cpPatches)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		try
+		{
+			ClassLoaderWrapper loader = TypeWrapper.FromClass(host).GetClassLoader();
+			ClassFile classFile = new ClassFile(data, 0, data.Length, "", loader.ClassFileParseOptions, cpPatches);
+			if (classFile.IKVMAssemblyAttribute != null)
+			{
+				// if this happens, the OpenJDK is probably trying to load an OpenJDK class file as a resource,
+				// make sure the build process includes the original class file as a resource in that case
+				throw new java.lang.ClassFormatError("Trying to define anonymous class based on stub class: " + classFile.Name);
+			}
+			return loader.GetTypeWrapperFactory().DefineClassImpl(null, TypeWrapper.FromClass(host), classFile, loader, host.pd).ClassObject;
+		}
+		catch (RetargetableJavaException x)
+		{
+			throw x.ToJava();
+		}
+#endif
+	}
+
+	public static bool compareAndSwapInt(object thisUnsafe, object obj, long offset, int expect, int update)
+	{
+#if FIRST_PASS
+		return false;
+#else
+		int[] array = obj as int[];
+		if (array != null && (offset & 3) == 0)
+		{
+			Stats.Log("compareAndSwapInt.array");
+			return Interlocked.CompareExchange(ref array[offset / 4], update, expect) == expect;
+		}
+		else if (obj is Array)
+		{
+			Stats.Log("compareAndSwapInt.unaligned");
+			// unaligned or not the right array type, so we can't be atomic
+			lock (thisUnsafe)
+			{
+				if (ReadInt32(obj, offset) == expect)
+				{
+					WriteInt32(obj, offset, update);
+					return true;
+				}
+				return false;
+			}
+		}
+		else
+		{
+			if (offset >= cacheCompareExchangeInt32.Length || cacheCompareExchangeInt32[offset] == null)
+			{
+				InterlockedResize(ref cacheCompareExchangeInt32, (int)offset + 1);
+				cacheCompareExchangeInt32[offset] = (CompareExchangeInt32)CreateCompareExchange(offset);
+			}
+			Stats.Log("compareAndSwapInt.", offset);
+			return cacheCompareExchangeInt32[offset](obj, update, expect) == expect;
+		}
+#endif
+	}
+
+    public static bool compareAndSwapLong(object thisUnsafe, object obj, long offset, long expect, long update)
+	{
+#if FIRST_PASS
+		return false;
+#else
+		long[] array = obj as long[];
+		if (array != null && (offset & 7) == 0)
+		{
+			Stats.Log("compareAndSwapLong.array");
+			return Interlocked.CompareExchange(ref array[offset / 8], update, expect) == expect;
+		}
+		else if (obj is Array)
+		{
+			Stats.Log("compareAndSwapLong.unaligned");
+			// unaligned or not the right array type, so we can't be atomic
+			lock (thisUnsafe)
+			{
+				if (ReadInt64(obj, offset) == expect)
+				{
+					WriteInt64(obj, offset, update);
+					return true;
+				}
+				return false;
+			}
+		}
+		else
+		{
+			if (offset >= cacheCompareExchangeInt64.Length || cacheCompareExchangeInt64[offset] == null)
+			{
+				InterlockedResize(ref cacheCompareExchangeInt64, (int)offset + 1);
+				cacheCompareExchangeInt64[offset] = (CompareExchangeInt64)CreateCompareExchange(offset);
+			}
+			Stats.Log("compareAndSwapLong.", offset);
+			return cacheCompareExchangeInt64[offset](obj, update, expect) == expect;
+		}
+#endif
+	}
+
+	private delegate int CompareExchangeInt32(object obj, int value, int comparand);
+	private delegate long CompareExchangeInt64(object obj, long value, long comparand);
+	private delegate object CompareExchangeObject(object obj, object value, object comparand);
+	private static CompareExchangeInt32[] cacheCompareExchangeInt32 = new CompareExchangeInt32[0];
+	private static CompareExchangeInt64[] cacheCompareExchangeInt64 = new CompareExchangeInt64[0];
+	private static CompareExchangeObject[] cacheCompareExchangeObject = new CompareExchangeObject[0];
+
+	private static void InterlockedResize(ref T[] array, int newSize)
+	{
+		for (; ; )
+		{
+			T[] oldArray = array;
+			T[] newArray = oldArray;
+			if (oldArray.Length >= newSize)
+			{
+				return;
+			}
+			Array.Resize(ref newArray, newSize);
+			if (Interlocked.CompareExchange(ref array, newArray, oldArray) == oldArray)
+			{
+				return;
+			}
+		}
+	}
+
+#if !FIRST_PASS
+	private static Delegate CreateCompareExchange(long fieldOffset)
+	{
+		FieldInfo field = GetFieldInfo(fieldOffset);
+		bool primitive = field.FieldType.IsPrimitive;
+		Type signatureType = primitive ? field.FieldType : typeof(object);
+		MethodInfo compareExchange;
+		Type delegateType;
+		if (signatureType == typeof(int))
+		{
+			compareExchange = InterlockedMethods.CompareExchangeInt32;
+			delegateType = typeof(CompareExchangeInt32);
+		}
+		else if (signatureType == typeof(long))
+		{
+			compareExchange = InterlockedMethods.CompareExchangeInt64;
+			delegateType = typeof(CompareExchangeInt64);
+		}
+		else
+		{
+			compareExchange = InterlockedMethods.CompareExchangeOfT.MakeGenericMethod(field.FieldType);
+			delegateType = typeof(CompareExchangeObject);
+		}
+		DynamicMethod dm = new DynamicMethod("CompareExchange", signatureType, new Type[] { typeof(object), signatureType, signatureType }, field.DeclaringType);
+		ILGenerator ilgen = dm.GetILGenerator();
+		// note that we don't bother will special casing static fields, because it is legal to use ldflda on a static field
+		ilgen.Emit(OpCodes.Ldarg_0);
+		ilgen.Emit(OpCodes.Castclass, field.DeclaringType);
+		ilgen.Emit(OpCodes.Ldflda, field);
+		ilgen.Emit(OpCodes.Ldarg_1);
+		if (!primitive)
+		{
+			ilgen.Emit(OpCodes.Castclass, field.FieldType);
+		}
+		ilgen.Emit(OpCodes.Ldarg_2);
+		if (!primitive)
+		{
+			ilgen.Emit(OpCodes.Castclass, field.FieldType);
+		}
+		ilgen.Emit(OpCodes.Call, compareExchange);
+		ilgen.Emit(OpCodes.Ret);
+		return dm.CreateDelegate(delegateType);
+	}
+
+	private static FieldInfo GetFieldInfo(long offset)
+	{
+		FieldWrapper fw = FieldWrapper.FromField(sun.misc.Unsafe.getField(offset));
+		fw.Link();
+		fw.ResolveField();
+		return fw.GetField();
+	}
+#endif
+
+	public static bool compareAndSwapObject(object thisUnsafe, object obj, long offset, object expect, object update)
+	{
+#if FIRST_PASS
+		return false;
+#else
+		object[] array = obj as object[];
+		if (array != null)
+		{
+			Stats.Log("compareAndSwapObject.array");
+			return Atomic.CompareExchange(array, (int)offset, update, expect) == expect;
+		}
+		else
+		{
+			if (offset >= cacheCompareExchangeObject.Length || cacheCompareExchangeObject[offset] == null)
+			{
+				InterlockedResize(ref cacheCompareExchangeObject, (int)offset + 1);
+				cacheCompareExchangeObject[offset] = (CompareExchangeObject)CreateCompareExchange(offset);
+			}
+			Stats.Log("compareAndSwapObject.", offset);
+			return cacheCompareExchangeObject[offset](obj, update, expect) == expect;
+		}
+#endif
+	}
+
+	abstract class Atomic
+	{
+		// NOTE we don't care that we keep the Type alive, because Unsafe should only be used inside the core class libraries
+		private static Dictionary impls = new Dictionary();
+
+		internal static object CompareExchange(object[] array, int index, object value, object comparand)
+		{
+			return GetImpl(array.GetType().GetElementType()).CompareExchangeImpl(array, index, value, comparand);
+		}
+
+		private static Atomic GetImpl(Type type)
+		{
+			Atomic impl;
+			if (!impls.TryGetValue(type, out impl))
+			{
+				impl = (Atomic)Activator.CreateInstance(typeof(Impl<>).MakeGenericType(type));
+				Dictionary curr = impls;
+				Dictionary copy = new Dictionary(curr);
+				copy[type] = impl;
+				Interlocked.CompareExchange(ref impls, copy, curr);
+			}
+			return impl;
+		}
+
+		protected abstract object CompareExchangeImpl(object[] array, int index, object value, object comparand);
+
+		sealed class Impl : Atomic
+			where T : class
+		{
+			protected override object CompareExchangeImpl(object[] array, int index, object value, object comparand)
+			{
+				return Interlocked.CompareExchange(ref ((T[])array)[index], (T)value, (T)comparand);
+			}
+		}
+	}
+
+	static class Stats
+	{
+#if !FIRST_PASS && UNSAFE_STATISTICS
+		private static readonly Dictionary dict = new Dictionary();
+
+		static Stats()
+		{
+			java.lang.Runtime.getRuntime().addShutdownHook(new DumpStats());
+		}
+
+		sealed class DumpStats : java.lang.Thread
+		{
+			public override void run()
+			{
+				List> list = new List>(dict);
+				list.Sort(delegate(KeyValuePair kv1, KeyValuePair kv2) { return kv1.Value.CompareTo(kv2.Value); });
+				foreach (KeyValuePair kv in list)
+				{
+					Console.WriteLine("{0,10}: {1}", kv.Value, kv.Key);
+				}
+			}
+		}
+#endif
+
+		[Conditional("UNSAFE_STATISTICS")]
+		internal static void Log(string key)
+		{
+#if !FIRST_PASS && UNSAFE_STATISTICS
+			lock (dict)
+			{
+				int count;
+				dict.TryGetValue(key, out count);
+				dict[key] = count + 1;
+			}
+#endif
+		}
+
+		[Conditional("UNSAFE_STATISTICS")]
+		internal static void Log(string key, long offset)
+		{
+#if !FIRST_PASS && UNSAFE_STATISTICS
+			FieldWrapper field = FieldWrapper.FromField(sun.misc.Unsafe.getField(offset));
+			key += field.DeclaringType.Name + "::" + field.Name;
+			Log(key);
+#endif
+		}
+	}
+}
+
+static class Java_sun_misc_URLClassPath
+{
+	public static java.net.URL[] getLookupCacheURLs(java.lang.ClassLoader loader)
+	{
+		return null;
+	}
+
+	public static int[] getLookupCacheForClassLoader(java.lang.ClassLoader loader, string name)
+	{
+		return null;
+	}
+
+	public static bool knownToNotExist0(java.lang.ClassLoader loader, string className)
+	{
+		return false;
+	}
+}
+
+static class Java_sun_misc_Version
+{
+	public static string getJvmSpecialVersion()
+	{
+		throw new NotImplementedException();
+	}
+
+	public static string getJdkSpecialVersion()
+	{
+		throw new NotImplementedException();
+	}
+
+	public static bool getJvmVersionInfo()
+	{
+		throw new NotImplementedException();
+	}
+
+	public static void getJdkVersionInfo()
+	{
+		throw new NotImplementedException();
+	}
+}
+
+static class Java_sun_misc_VM
+{
+	public static void initialize()
+	{
+	}
+
+	public static java.lang.ClassLoader latestUserDefinedLoader()
+	{
+		// testing shows that it is cheaper the get the full stack trace and then look at a few frames than getting the frames individually
+		StackTrace trace = new StackTrace(2, false);
+		for (int i = 0; i < trace.FrameCount; i++)
+		{
+			StackFrame frame = trace.GetFrame(i);
+			MethodBase method = frame.GetMethod();
+			if (method == null)
+			{
+				continue;
+			}
+			Type type = method.DeclaringType;
+			if (type != null)
+			{
+				TypeWrapper tw = ClassLoaderWrapper.GetWrapperFromType(type);
+				if (tw != null)
+				{
+					ClassLoaderWrapper classLoader = tw.GetClassLoader();
+					AssemblyClassLoader acl = classLoader as AssemblyClassLoader;
+					if (acl == null || acl.GetAssembly(tw) != typeof(object).Assembly)
+					{
+						java.lang.ClassLoader javaClassLoader = classLoader.GetJavaClassLoader();
+						if (javaClassLoader != null)
+						{
+							return javaClassLoader;
+						}
+					}
+				}
+			}
+		}
+		return null;
+	}
+}
+
+static class Java_sun_misc_VMSupport
+{
+	public static object initAgentProperties(object props)
+	{
+		return props;
+	}
+
+	public static string getVMTemporaryDirectory()
+	{
+		return System.IO.Path.GetTempPath();
+	}
+}
diff --git a/runtime/openjdk/sun.nio.ch.cs b/runtime/openjdk/sun.nio.ch.cs
new file mode 100644
index 0000000..06a63da
--- /dev/null
+++ b/runtime/openjdk/sun.nio.ch.cs
@@ -0,0 +1,1222 @@
+/*
+  Copyright (C) 2011 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+
+using System;
+using System.Collections.Generic;
+using FileDescriptor = java.io.FileDescriptor;
+using InetAddress = java.net.InetAddress;
+using ByteBuffer = java.nio.ByteBuffer;
+
+static class Java_sun_nio_ch_DatagramChannelImpl
+{
+	public static void initIDs()
+	{
+	}
+
+	public static void disconnect0(FileDescriptor fd, bool isIPv6)
+	{
+#if !FIRST_PASS
+		try
+		{
+			fd.getSocket().Connect(new System.Net.IPEndPoint(System.Net.IPAddress.Any, 0));
+			IKVM.NativeCode.sun.nio.ch.Net.setConnectionReset(fd.getSocket(), false);
+		}
+		catch (System.Net.Sockets.SocketException x)
+		{
+			throw java.net.SocketUtil.convertSocketExceptionToIOException(x);
+		}
+		catch (ObjectDisposedException)
+		{
+			throw new java.net.SocketException("Socket is closed");
+		}
+#endif
+	}
+
+	public static int receive0(object obj, FileDescriptor fd, byte[] buf, int pos, int len, bool connected)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		sun.nio.ch.DatagramChannelImpl impl = (sun.nio.ch.DatagramChannelImpl)obj;
+		java.net.SocketAddress remoteAddress = impl.remoteAddress();
+		System.Net.EndPoint remoteEP;
+		if (fd.getSocket().AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
+		{
+			remoteEP = new System.Net.IPEndPoint(System.Net.IPAddress.IPv6Any, 0);
+		}
+		else
+		{
+			remoteEP = new System.Net.IPEndPoint(0, 0);
+		}
+		java.net.InetSocketAddress addr;
+		int length;
+		do
+		{
+			for (; ; )
+			{
+				try
+				{
+					length = fd.getSocket().ReceiveFrom(buf, pos, len, System.Net.Sockets.SocketFlags.None, ref remoteEP);
+					break;
+				}
+				catch (System.Net.Sockets.SocketException x)
+				{
+					if (x.ErrorCode == java.net.SocketUtil.WSAECONNRESET)
+					{
+						// A previous send failed (i.e. the remote host responded with a ICMP that the port is closed) and
+						// the winsock stack helpfully lets us know this, but we only care about this when we're connected,
+						// otherwise we'll simply retry the receive (note that we use SIO_UDP_CONNRESET to prevent these
+						// WSAECONNRESET exceptions, but when switching from connected to disconnected, some can slip through).
+						if (connected)
+						{
+							throw new java.net.PortUnreachableException();
+						}
+						continue;
+					}
+					if (x.ErrorCode == java.net.SocketUtil.WSAEMSGSIZE)
+					{
+						// The buffer size was too small for the packet, ReceiveFrom receives the part of the packet
+						// that fits in the buffer and then throws an exception, so we have to ignore the exception in this case.
+						length = len;
+						break;
+					}
+					if (x.ErrorCode == java.net.SocketUtil.WSAEWOULDBLOCK)
+					{
+						return sun.nio.ch.IOStatus.UNAVAILABLE;
+					}
+					throw java.net.SocketUtil.convertSocketExceptionToIOException(x);
+				}
+				catch (ObjectDisposedException)
+				{
+					throw new java.net.SocketException("Socket is closed");
+				}
+			}
+			System.Net.IPEndPoint ep = (System.Net.IPEndPoint)remoteEP;
+			addr = new java.net.InetSocketAddress(java.net.SocketUtil.getInetAddressFromIPEndPoint(ep), ep.Port);
+		} while (remoteAddress != null && !addr.equals(remoteAddress));
+		impl.sender = addr;
+		return length;
+#endif
+	}
+
+	public static int send0(object obj, bool preferIPv6, FileDescriptor fd, byte[] buf, int pos, int len, InetAddress addr, int port)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		try
+		{
+			return fd.getSocket().SendTo(buf, pos, len, System.Net.Sockets.SocketFlags.None, new System.Net.IPEndPoint(java.net.SocketUtil.getAddressFromInetAddress(addr, preferIPv6), port));
+		}
+		catch (System.Net.Sockets.SocketException x)
+		{
+			if (x.ErrorCode == java.net.SocketUtil.WSAEWOULDBLOCK)
+			{
+				return sun.nio.ch.IOStatus.UNAVAILABLE;
+			}
+			throw java.net.SocketUtil.convertSocketExceptionToIOException(x);
+		}
+		catch (ObjectDisposedException)
+		{
+			throw new java.net.SocketException("Socket is closed");
+		}
+#endif
+	}
+}
+
+#if !FIRST_PASS
+namespace IKVM.Internal.AsyncSocket
+{
+	using System.Net;
+	using System.Net.Sockets;
+
+	abstract class OperationBase
+	{
+		private static readonly AsyncCallback callback = CallbackProc;
+		private Socket socket;
+		private sun.nio.ch.Iocp.ResultHandler handler;
+		private int result;
+		private Exception exception;
+
+		internal int Do(Socket socket, TInput input, object handler)
+		{
+			try
+			{
+				this.socket = socket;
+				this.handler = (sun.nio.ch.Iocp.ResultHandler)handler;
+				IAsyncResult ar = Begin(socket, input, callback, this);
+				if (ar.CompletedSynchronously)
+				{
+					if (exception != null)
+					{
+						throw exception;
+					}
+					return result;
+				}
+				else
+				{
+					return sun.nio.ch.IOStatus.UNAVAILABLE;
+				}
+			}
+			catch (SocketException x)
+			{
+				throw java.net.SocketUtil.convertSocketExceptionToIOException(x);
+			}
+			catch (ObjectDisposedException)
+			{
+				throw new java.nio.channels.ClosedChannelException();
+			}
+		}
+
+		private static void CallbackProc(IAsyncResult ar)
+		{
+			OperationBase obj = (OperationBase)ar.AsyncState;
+			try
+			{
+				int result = obj.End(obj.socket, ar);
+				if (ar.CompletedSynchronously)
+				{
+					obj.result = result;
+				}
+				else
+				{
+					obj.handler.completed(result, false);
+				}
+			}
+			catch (SocketException x)
+			{
+				if (ar.CompletedSynchronously)
+				{
+					obj.exception = x;
+				}
+				else
+				{
+					obj.handler.failed(x.ErrorCode, java.net.SocketUtil.convertSocketExceptionToIOException(x));
+				}
+			}
+			catch (ObjectDisposedException x)
+			{
+				if (ar.CompletedSynchronously)
+				{
+					obj.exception = x;
+				}
+				else
+				{
+					obj.handler.failed(0, new java.nio.channels.ClosedChannelException());
+				}
+			}
+		}
+
+		protected abstract IAsyncResult Begin(Socket socket, TInput input, AsyncCallback callback, object state);
+		protected abstract int End(Socket socket, IAsyncResult ar);
+	}
+}
+#endif
+
+static class Java_sun_nio_ch_WindowsAsynchronousServerSocketChannelImpl
+{
+#if !FIRST_PASS
+	sealed class Accept : IKVM.Internal.AsyncSocket.OperationBase
+	{
+		protected override IAsyncResult Begin(System.Net.Sockets.Socket listenSocket, System.Net.Sockets.Socket acceptSocket, AsyncCallback callback, object state)
+		{
+			return listenSocket.BeginAccept(acceptSocket, 0, callback, state);
+		}
+
+		protected override int End(System.Net.Sockets.Socket socket, IAsyncResult ar)
+		{
+			socket.EndAccept(ar);
+			return 0;
+		}
+	}
+#endif
+
+	public static void initIDs()
+	{
+	}
+
+	public static int accept0(FileDescriptor listenSocket, FileDescriptor acceptSocket, object handler)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		return new Accept().Do(listenSocket.getSocket(), acceptSocket.getSocket(), handler);
+#endif
+	}
+
+	public static void updateAcceptContext(FileDescriptor listenSocket, FileDescriptor acceptSocket)
+	{
+		// already handled by .NET Framework
+	}
+
+	public static void closesocket0(long socket)
+	{
+		// unused
+	}
+}
+
+static class Java_sun_nio_ch_WindowsAsynchronousSocketChannelImpl
+{
+#if !FIRST_PASS
+	sealed class Connect : IKVM.Internal.AsyncSocket.OperationBase
+	{
+		protected override IAsyncResult Begin(System.Net.Sockets.Socket socket, System.Net.IPEndPoint remoteEP, AsyncCallback callback, object state)
+		{
+			return socket.BeginConnect(remoteEP, callback, state);
+		}
+
+		protected override int End(System.Net.Sockets.Socket socket, IAsyncResult ar)
+		{
+			socket.EndConnect(ar);
+			return 0;
+		}
+	}
+
+	private static List> ByteBuffersToList(ByteBuffer[] bufs)
+	{
+		List> list = new List>(bufs.Length);
+		foreach (ByteBuffer bb in bufs)
+		{
+			list.Add(new ArraySegment(bb.array(), bb.arrayOffset() + bb.position(), bb.remaining()));
+		}
+		return list;
+	}
+
+	sealed class Receive : IKVM.Internal.AsyncSocket.OperationBase
+	{
+		protected override IAsyncResult Begin(System.Net.Sockets.Socket socket, ByteBuffer[] bufs, AsyncCallback callback, object state)
+		{
+			return socket.BeginReceive(ByteBuffersToList(bufs), System.Net.Sockets.SocketFlags.None, callback, state);
+		}
+
+		protected override int End(System.Net.Sockets.Socket socket, IAsyncResult ar)
+		{
+			return socket.EndReceive(ar);
+		}
+	}
+
+	sealed class Send : IKVM.Internal.AsyncSocket.OperationBase
+	{
+		protected override IAsyncResult Begin(System.Net.Sockets.Socket socket, ByteBuffer[] bufs, AsyncCallback callback, object state)
+		{
+			return socket.BeginSend(ByteBuffersToList(bufs), System.Net.Sockets.SocketFlags.None, callback, state);
+		}
+
+		protected override int End(System.Net.Sockets.Socket socket, IAsyncResult ar)
+		{
+			return socket.EndSend(ar);
+		}
+	}
+#endif
+
+	public static void initIDs()
+	{
+	}
+
+	public static int connect0(FileDescriptor fd, bool preferIPv6, InetAddress remote, int remotePort, object handler)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		return new Connect().Do(fd.getSocket(), new System.Net.IPEndPoint(java.net.SocketUtil.getAddressFromInetAddress(remote, preferIPv6), remotePort), handler);
+#endif
+	}
+
+	public static void updateConnectContext(FileDescriptor fd)
+	{
+		// already handled by .NET Framework
+	}
+
+	public static int read0(FileDescriptor fd, ByteBuffer[] bufs, object handler)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		return new Receive().Do(fd.getSocket(), bufs, handler);
+#endif
+	}
+
+	public static int write0(FileDescriptor fd, ByteBuffer[] bufs, object handler)
+	{
+#if FIRST_PASS
+		return 0;
+#else
+		return new Send().Do(fd.getSocket(), bufs, handler);
+#endif
+	}
+
+	public static void shutdown0(long socket, int how)
+	{
+		// unused
+	}
+
+	public static void closesocket0(long socket)
+	{
+		// unused
+	}
+}
+
+namespace IKVM.NativeCode.sun.nio.ch
+{
+	static class SocketDispatcher
+	{
+		public static long read(object nd, FileDescriptor fd, ByteBuffer[] bufs, int offset, int length)
+		{
+#if FIRST_PASS
+			return 0;
+#else
+			ByteBuffer[] altBufs = null;
+			List> list = new List>(length);
+			for (int i = 0; i < length; i++)
+			{
+				ByteBuffer bb = bufs[i + offset];
+				if (!bb.hasArray())
+				{
+					if (altBufs == null)
+					{
+						altBufs = new ByteBuffer[bufs.Length];
+					}
+					bb = altBufs[i + offset] = ByteBuffer.allocate(bb.remaining());
+				}
+				list.Add(new ArraySegment(bb.array(), bb.arrayOffset() + bb.position(), bb.remaining()));
+			}
+			int count;
+			try
+			{
+				count = fd.getSocket().Receive(list);
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				if (x.ErrorCode == global::java.net.SocketUtil.WSAEWOULDBLOCK)
+				{
+					count = 0;
+				}
+				else
+				{
+					throw global::java.net.SocketUtil.convertSocketExceptionToIOException(x);
+				}
+			}
+			catch (ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+			int total = count;
+			for (int i = 0; total > 0 && i < length; i++)
+			{
+				ByteBuffer bb = bufs[i + offset];
+				ByteBuffer abb;
+				int consumed = Math.Min(total, bb.remaining());
+				if (altBufs != null && (abb = altBufs[i + offset]) != null)
+				{
+					abb.position(consumed);
+					abb.flip();
+					bb.put(abb);
+				}
+				else
+				{
+					bb.position(bb.position() + consumed);
+				}
+				total -= consumed;
+			}
+			return count;
+#endif
+		}
+
+		public static long write(object nd, FileDescriptor fd, ByteBuffer[] bufs, int offset, int length)
+		{
+#if FIRST_PASS
+			return 0;
+#else
+			ByteBuffer[] altBufs = null;
+			List> list = new List>(length);
+			for (int i = 0; i < length; i++)
+			{
+				ByteBuffer bb = bufs[i + offset];
+				if (!bb.hasArray())
+				{
+					if (altBufs == null)
+					{
+						altBufs = new ByteBuffer[bufs.Length];
+					}
+					ByteBuffer abb = ByteBuffer.allocate(bb.remaining());
+					int pos = bb.position();
+					abb.put(bb);
+					bb.position(pos);
+					abb.flip();
+					bb = altBufs[i + offset] = abb;
+				}
+				list.Add(new ArraySegment(bb.array(), bb.arrayOffset() + bb.position(), bb.remaining()));
+			}
+			int count;
+			try
+			{
+				count = fd.getSocket().Send(list);
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				if (x.ErrorCode == global::java.net.SocketUtil.WSAEWOULDBLOCK)
+				{
+					count = 0;
+				}
+				else
+				{
+					throw global::java.net.SocketUtil.convertSocketExceptionToIOException(x);
+				}
+			}
+			catch (ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+			int total = count;
+			for (int i = 0; total > 0 && i < length; i++)
+			{
+				ByteBuffer bb = bufs[i + offset];
+				int consumed = Math.Min(total, bb.remaining());
+				bb.position(bb.position() + consumed);
+				total -= consumed;
+			}
+			return count;
+#endif
+		}
+	}
+
+	static class Net
+	{
+		public static bool isIPv6Available0()
+		{
+			string env = IKVM.Internal.JVM.SafeGetEnvironmentVariable("IKVM_IPV6");
+			int val;
+			if (env != null && Int32.TryParse(env, out val))
+			{
+				return (val & 2) != 0;
+			}
+			// we only support IPv6 on Vista and up (because there is no TwoStacks nio implementation)
+			// (non-Windows OSses are currently not supported)
+			// Mono on Windows doesn't appear to support IPv6 either (Mono on Linux does).
+			return Type.GetType("Mono.Runtime") == null
+				&& System.Net.Sockets.Socket.OSSupportsIPv6
+				&& Environment.OSVersion.Platform == PlatformID.Win32NT
+				&& Environment.OSVersion.Version.Major >= 6;
+		}
+
+		public static int isExclusiveBindAvailable()
+		{
+			return Environment.OSVersion.Platform == PlatformID.Win32NT
+				? Environment.OSVersion.Version.Major >= 6 ? 1 : 0
+				: -1;
+		}
+
+		public static bool canIPv6SocketJoinIPv4Group0()
+		{
+			return false;
+		}
+
+		public static bool canJoin6WithIPv4Group0()
+		{
+			return false;
+		}
+
+		public static void shutdown(FileDescriptor fd, int how)
+		{
+#if !FIRST_PASS
+			try
+			{
+				fd.getSocket().Shutdown(how == global::sun.nio.ch.Net.SHUT_RD
+					? System.Net.Sockets.SocketShutdown.Receive
+					: System.Net.Sockets.SocketShutdown.Send);
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				throw global::java.net.SocketUtil.convertSocketExceptionToIOException(x);
+			}
+			catch (ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+#endif
+		}
+
+		public static int localPort(FileDescriptor fd)
+		{
+#if FIRST_PASS
+			return 0;
+#else
+			try
+			{
+				System.Net.IPEndPoint ep = (System.Net.IPEndPoint)fd.getSocket().LocalEndPoint;
+				return ep.Port;
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				throw global::java.net.SocketUtil.convertSocketExceptionToIOException(x);
+			}
+			catch (System.ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+#endif
+		}
+
+		public static InetAddress localInetAddress(FileDescriptor fd)
+		{
+#if FIRST_PASS
+			return null;
+#else
+			try
+			{
+				System.Net.IPEndPoint ep = (System.Net.IPEndPoint)fd.getSocket().LocalEndPoint;
+				return global::java.net.SocketUtil.getInetAddressFromIPEndPoint(ep);
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				throw global::java.net.SocketUtil.convertSocketExceptionToIOException(x);
+			}
+			catch (System.ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+#endif
+		}
+
+		public static int remotePort(FileDescriptor fd)
+		{
+#if FIRST_PASS
+			return 0;
+#else
+			try
+			{
+				System.Net.IPEndPoint ep = (System.Net.IPEndPoint)fd.getSocket().RemoteEndPoint;
+				return ep.Port;
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				throw global::java.net.SocketUtil.convertSocketExceptionToIOException(x);
+			}
+			catch (System.ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+#endif
+		}
+
+		public static InetAddress remoteInetAddress(FileDescriptor fd)
+		{
+#if FIRST_PASS
+			return null;
+#else
+			try
+			{
+				System.Net.IPEndPoint ep = (System.Net.IPEndPoint)fd.getSocket().RemoteEndPoint;
+				return global::java.net.SocketUtil.getInetAddressFromIPEndPoint(ep);
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				throw global::java.net.SocketUtil.convertSocketExceptionToIOException(x);
+			}
+			catch (System.ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+#endif
+		}
+
+		public static int getIntOption0(FileDescriptor fd, bool mayNeedConversion, int level, int opt)
+		{
+#if FIRST_PASS
+			return 0;
+#else
+			if (level == global::ikvm.@internal.Winsock.IPPROTO_IPV6 && opt == global::ikvm.@internal.Winsock.IPV6_TCLASS)
+			{
+				return 0;
+			}
+			System.Net.Sockets.SocketOptionLevel sol = (System.Net.Sockets.SocketOptionLevel)level;
+			System.Net.Sockets.SocketOptionName son = (System.Net.Sockets.SocketOptionName)opt;
+			try
+			{
+				object obj = fd.getSocket().GetSocketOption(sol, son);
+				System.Net.Sockets.LingerOption linger = obj as System.Net.Sockets.LingerOption;
+				if (linger != null)
+				{
+					return linger.Enabled ? linger.LingerTime : -1;
+				}
+				return (int)obj;
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				if (mayNeedConversion)
+				{
+					if (x.ErrorCode == global::java.net.SocketUtil.WSAENOPROTOOPT
+						&& sol == System.Net.Sockets.SocketOptionLevel.IP
+						&& son == System.Net.Sockets.SocketOptionName.TypeOfService)
+					{
+						return 0;
+					}
+				}
+				throw global::java.net.SocketUtil.convertSocketExceptionToIOException(x);
+			}
+			catch (System.ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+#endif
+		}
+
+		public static void setIntOption0(FileDescriptor fd, bool mayNeedConversion, int level, int opt, int arg, bool isIPv6)
+		{
+#if !FIRST_PASS
+			if (level == global::ikvm.@internal.Winsock.IPPROTO_IPV6 && opt == global::ikvm.@internal.Winsock.IPV6_TCLASS)
+			{
+				return;
+			}
+			System.Net.Sockets.SocketOptionLevel sol = (System.Net.Sockets.SocketOptionLevel)level;
+			System.Net.Sockets.SocketOptionName son = (System.Net.Sockets.SocketOptionName)opt;
+			if (mayNeedConversion)
+			{
+				const int IPTOS_TOS_MASK = 0x1e;
+				const int IPTOS_PREC_MASK = 0xe0;
+				if (sol == System.Net.Sockets.SocketOptionLevel.IP
+					&& son == System.Net.Sockets.SocketOptionName.TypeOfService)
+				{
+					arg &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);
+				}
+			}
+			try
+			{
+				fd.getSocket().SetSocketOption(sol, son, arg);
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				if (mayNeedConversion)
+				{
+					if (x.ErrorCode == global::java.net.SocketUtil.WSAENOPROTOOPT
+						&& sol == System.Net.Sockets.SocketOptionLevel.IP
+						&& (son == System.Net.Sockets.SocketOptionName.TypeOfService || son == System.Net.Sockets.SocketOptionName.MulticastLoopback))
+					{
+						return;
+					}
+					if (x.ErrorCode == global::java.net.SocketUtil.WSAEINVAL
+						&& sol == System.Net.Sockets.SocketOptionLevel.IP
+						&& son == System.Net.Sockets.SocketOptionName.TypeOfService)
+					{
+						return;
+					}
+				}
+				throw global::java.net.SocketUtil.convertSocketExceptionToIOException(x);
+			}
+			catch (System.ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+#endif
+		}
+
+		private static void PutInt(byte[] buf, int pos, int value)
+		{
+			buf[pos + 0] = (byte)(value >> 24);
+			buf[pos + 1] = (byte)(value >> 16);
+			buf[pos + 2] = (byte)(value >> 8);
+			buf[pos + 3] = (byte)(value >> 0);
+		}
+
+		public static int joinOrDrop4(bool join, FileDescriptor fd, int group, int interf, int source)
+		{
+#if FIRST_PASS
+			return 0;
+#else
+			try
+			{
+				if (source == 0)
+				{
+					fd.getSocket().SetSocketOption(System.Net.Sockets.SocketOptionLevel.IP,
+						join ? System.Net.Sockets.SocketOptionName.AddMembership : System.Net.Sockets.SocketOptionName.DropMembership,
+						new System.Net.Sockets.MulticastOption(new System.Net.IPAddress(System.Net.IPAddress.HostToNetworkOrder(group) & 0xFFFFFFFFL), new System.Net.IPAddress(System.Net.IPAddress.HostToNetworkOrder(interf) & 0xFFFFFFFFL)));
+				}
+				else
+				{
+					// ip_mreq_source
+					byte[] optionValue = new byte[12];
+					PutInt(optionValue, 0, group);
+					PutInt(optionValue, 4, source);
+					PutInt(optionValue, 8, interf);
+					fd.getSocket().SetSocketOption(System.Net.Sockets.SocketOptionLevel.IP,
+						join ? System.Net.Sockets.SocketOptionName.AddSourceMembership : System.Net.Sockets.SocketOptionName.DropSourceMembership,
+						optionValue);
+				}
+				return 0;
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				throw global::java.net.SocketUtil.convertSocketExceptionToIOException(x);
+			}
+			catch (System.ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+#endif
+		}
+
+		public static int blockOrUnblock4(bool block, FileDescriptor fd, int group, int interf, int source)
+		{
+#if FIRST_PASS
+			return 0;
+#else
+			try
+			{
+				// ip_mreq_source
+				byte[] optionValue = new byte[12];
+				PutInt(optionValue, 0, group);
+				PutInt(optionValue, 4, source);
+				PutInt(optionValue, 8, interf);
+				fd.getSocket().SetSocketOption(System.Net.Sockets.SocketOptionLevel.IP,
+					block ? System.Net.Sockets.SocketOptionName.BlockSource : System.Net.Sockets.SocketOptionName.UnblockSource,
+					optionValue);
+				return 0;
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				throw global::java.net.SocketUtil.convertSocketExceptionToIOException(x);
+			}
+			catch (System.ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+#endif
+		}
+
+		// write a sockaddr_in6 into optionValue at offset pos
+		private static void PutSockAddrIn6(byte[] optionValue, int pos, byte[] addr)
+		{
+			// sin6_family
+			optionValue[pos] = 23; // AF_INET6
+
+			// sin6_addr
+			Buffer.BlockCopy(addr, 0, optionValue, pos + 8, addr.Length);
+		}
+
+		public static int joinOrDrop6(bool join, FileDescriptor fd, byte[] group, int index, byte[] source)
+		{
+#if FIRST_PASS
+			return 0;
+#else
+			try
+			{
+				if (source == null)
+				{
+					fd.getSocket().SetSocketOption(System.Net.Sockets.SocketOptionLevel.IPv6,
+						join ? System.Net.Sockets.SocketOptionName.AddMembership : System.Net.Sockets.SocketOptionName.DropMembership,
+						new System.Net.Sockets.IPv6MulticastOption(new System.Net.IPAddress(group), index));
+				}
+				else
+				{
+					const System.Net.Sockets.SocketOptionName MCAST_JOIN_SOURCE_GROUP = (System.Net.Sockets.SocketOptionName)45;
+					const System.Net.Sockets.SocketOptionName MCAST_LEAVE_SOURCE_GROUP = (System.Net.Sockets.SocketOptionName)46;
+					// group_source_req
+					byte[] optionValue = new byte[264];
+					optionValue[0] = (byte)index;
+					optionValue[1] = (byte)(index >> 8);
+					optionValue[2] = (byte)(index >> 16);
+					optionValue[3] = (byte)(index >> 24);
+					PutSockAddrIn6(optionValue, 8, group);
+					PutSockAddrIn6(optionValue, 136, source);
+					fd.getSocket().SetSocketOption(System.Net.Sockets.SocketOptionLevel.IPv6, join ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP, optionValue);
+				}
+				return 0;
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				throw global::java.net.SocketUtil.convertSocketExceptionToIOException(x);
+			}
+			catch (System.ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+#endif
+		}
+
+		public static int blockOrUnblock6(bool block, FileDescriptor fd, byte[] group, int index, byte[] source)
+		{
+#if FIRST_PASS
+			return 0;
+#else
+			try
+			{
+				const System.Net.Sockets.SocketOptionName MCAST_BLOCK_SOURCE = (System.Net.Sockets.SocketOptionName)43;
+				const System.Net.Sockets.SocketOptionName MCAST_UNBLOCK_SOURCE = (System.Net.Sockets.SocketOptionName)44;
+				// group_source_req
+				byte[] optionValue = new byte[264];
+				optionValue[0] = (byte)index;
+				optionValue[1] = (byte)(index >> 8);
+				optionValue[2] = (byte)(index >> 16);
+				optionValue[3] = (byte)(index >> 24);
+				PutSockAddrIn6(optionValue, 8, group);
+				PutSockAddrIn6(optionValue, 136, source);
+				fd.getSocket().SetSocketOption(System.Net.Sockets.SocketOptionLevel.IPv6, block ? MCAST_BLOCK_SOURCE : MCAST_UNBLOCK_SOURCE, optionValue);
+				return 0;
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				throw global::java.net.SocketUtil.convertSocketExceptionToIOException(x);
+			}
+			catch (System.ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+#endif
+		}
+
+		public static void setInterface4(FileDescriptor fd, int interf)
+		{
+#if !FIRST_PASS
+			try
+			{
+				fd.getSocket().SetSocketOption(System.Net.Sockets.SocketOptionLevel.IP, System.Net.Sockets.SocketOptionName.MulticastInterface, System.Net.IPAddress.HostToNetworkOrder(interf));
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				throw global::java.net.SocketUtil.convertSocketExceptionToIOException(x);
+			}
+			catch (System.ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+#endif
+		}
+
+		public static int getInterface4(FileDescriptor fd)
+		{
+#if FIRST_PASS
+			return 0;
+#else
+			try
+			{
+				return System.Net.IPAddress.NetworkToHostOrder((int)fd.getSocket().GetSocketOption(System.Net.Sockets.SocketOptionLevel.IP, System.Net.Sockets.SocketOptionName.MulticastInterface));
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				throw global::java.net.SocketUtil.convertSocketExceptionToIOException(x);
+			}
+			catch (System.ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+#endif
+		}
+
+		public static void setInterface6(FileDescriptor fd, int index)
+		{
+#if !FIRST_PASS
+			try
+			{
+				fd.getSocket().SetSocketOption(System.Net.Sockets.SocketOptionLevel.IPv6, System.Net.Sockets.SocketOptionName.MulticastInterface, index);
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				throw global::java.net.SocketUtil.convertSocketExceptionToIOException(x);
+			}
+			catch (System.ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+#endif
+		}
+
+		public static int getInterface6(FileDescriptor fd)
+		{
+#if FIRST_PASS
+			return 0;
+#else
+			try
+			{
+				return (int)fd.getSocket().GetSocketOption(System.Net.Sockets.SocketOptionLevel.IPv6, System.Net.Sockets.SocketOptionName.MulticastInterface);
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				throw global::java.net.SocketUtil.convertSocketExceptionToIOException(x);
+			}
+			catch (System.ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+#endif
+		}
+
+		public static FileDescriptor socket0(bool preferIPv6, bool stream, bool reuse)
+		{
+#if FIRST_PASS
+			return null;
+#else
+			try
+			{
+				System.Net.Sockets.AddressFamily addressFamily = preferIPv6
+					? System.Net.Sockets.AddressFamily.InterNetworkV6
+					: System.Net.Sockets.AddressFamily.InterNetwork;
+				System.Net.Sockets.SocketType socketType = stream
+					? System.Net.Sockets.SocketType.Stream
+					: System.Net.Sockets.SocketType.Dgram;
+				System.Net.Sockets.ProtocolType protocolType = stream
+					? System.Net.Sockets.ProtocolType.Tcp
+					: System.Net.Sockets.ProtocolType.Udp;
+				System.Net.Sockets.Socket socket = new System.Net.Sockets.Socket(addressFamily, socketType, protocolType);
+				if (preferIPv6)
+				{
+					// enable IPv4 over IPv6 sockets (note that we don't have to check for >= Vista here, because nio sockets only support IPv6 on >= Vista)
+					const System.Net.Sockets.SocketOptionName IPV6_V6ONLY = (System.Net.Sockets.SocketOptionName)27;
+					socket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.IPv6, IPV6_V6ONLY, 0);
+				}
+				if (!stream)
+				{
+					setConnectionReset(socket, false);
+				}
+				FileDescriptor fd = new FileDescriptor();
+				fd.setSocket(socket);
+				return fd;
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				throw global::java.net.SocketUtil.convertSocketExceptionToIOException(x);
+			}
+#endif
+		}
+
+		public static void bind0(FileDescriptor fd, bool preferIPv6, bool useExclBind, InetAddress addr, int port)
+		{
+#if !FIRST_PASS
+			try
+			{
+				if (useExclBind)
+				{
+					global::java.net.net_util_md.setExclusiveBind(fd.getSocket());
+				}
+				fd.getSocket().Bind(new System.Net.IPEndPoint(global::java.net.SocketUtil.getAddressFromInetAddress(addr, preferIPv6), port));
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				throw global::java.net.SocketUtil.convertSocketExceptionToIOException(x);
+			}
+			catch (System.ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+#endif
+		}
+
+		public static void listen(FileDescriptor fd, int backlog)
+		{
+#if !FIRST_PASS
+			try
+			{
+				fd.getSocket().Listen(backlog);
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				throw global::java.net.SocketUtil.convertSocketExceptionToIOException(x);
+			}
+			catch (System.ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+#endif
+		}
+
+		internal static void setConnectionReset(System.Net.Sockets.Socket socket, bool enable)
+		{
+			// Windows 2000 introduced a "feature" that causes it to return WSAECONNRESET from receive,
+			// if a previous send resulted in an ICMP port unreachable. For unconnected datagram sockets,
+			// we disable this feature by using this ioctl.
+			const int IOC_IN = unchecked((int)0x80000000);
+			const int IOC_VENDOR = 0x18000000;
+			const int SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
+
+			socket.IOControl(SIO_UDP_CONNRESET, new byte[] { enable ? (byte)1 : (byte)0 }, null);
+		}
+
+		public static int connect0(bool preferIPv6, FileDescriptor fd, InetAddress remote, int remotePort)
+		{
+#if FIRST_PASS
+			return 0;
+#else
+			try
+			{
+				System.Net.IPEndPoint ep = new System.Net.IPEndPoint(global::java.net.SocketUtil.getAddressFromInetAddress(remote, preferIPv6), remotePort);
+				bool datagram = fd.getSocket().SocketType == System.Net.Sockets.SocketType.Dgram;
+				if (datagram || fd.isSocketBlocking())
+				{
+					fd.getSocket().Connect(ep);
+					if (datagram)
+					{
+						setConnectionReset(fd.getSocket(), true);
+					}
+					return 1;
+				}
+				else
+				{
+					fd.setAsyncResult(fd.getSocket().BeginConnect(ep, null, null));
+					return global::sun.nio.ch.IOStatus.UNAVAILABLE;
+				}
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				throw new global::java.net.ConnectException(x.Message);
+			}
+			catch (System.ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+#endif
+		}
+
+		public static int poll(FileDescriptor fd, int events, long timeout)
+		{
+#if FIRST_PASS
+			return 0;
+#else
+			System.Net.Sockets.SelectMode selectMode;
+			switch (events)
+			{
+				case global::sun.nio.ch.Net.POLLCONN:
+				case global::sun.nio.ch.Net.POLLOUT:
+					selectMode = System.Net.Sockets.SelectMode.SelectWrite;
+					break;
+				case global::sun.nio.ch.Net.POLLIN:
+					selectMode = System.Net.Sockets.SelectMode.SelectRead;
+					break;
+				default:
+					throw new NotSupportedException();
+			}
+			int microSeconds = timeout >= Int32.MaxValue / 1000 ? Int32.MaxValue : (int)(timeout * 1000);
+			try
+			{
+				if (fd.getSocket().Poll(microSeconds, selectMode))
+				{
+					return events;
+				}
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				throw new global::java.net.SocketException(x.Message);
+			}
+			catch (System.ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+			return 0;
+#endif
+		}
+	}
+
+	static class ServerSocketChannelImpl
+	{
+		public static int accept0(object _this, FileDescriptor ssfd, FileDescriptor newfd, object isaa)
+		{
+#if FIRST_PASS
+			return 0;
+#else
+			try
+			{
+				System.Net.Sockets.Socket netSocket = ssfd.getSocket();
+				if (netSocket.Blocking || netSocket.Poll(0, System.Net.Sockets.SelectMode.SelectRead))
+				{
+					System.Net.Sockets.Socket accsock = netSocket.Accept();
+					newfd.setSocket(accsock);
+					System.Net.IPEndPoint ep = (System.Net.IPEndPoint)accsock.RemoteEndPoint;
+					((global::java.net.InetSocketAddress[])isaa)[0] = new global::java.net.InetSocketAddress(global::java.net.SocketUtil.getInetAddressFromIPEndPoint(ep), ep.Port);
+					return 1;
+				}
+				else
+				{
+					return global::sun.nio.ch.IOStatus.UNAVAILABLE;
+				}
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				throw global::java.net.SocketUtil.convertSocketExceptionToIOException(x);
+			}
+			catch (System.ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+#endif
+		}
+
+		public static void initIDs()
+		{
+		}
+	}
+
+	static class SocketChannelImpl
+	{
+		public static int checkConnect(FileDescriptor fd, bool block, bool ready)
+		{
+#if FIRST_PASS
+			return 0;
+#else
+			try
+			{
+				IAsyncResult asyncConnect = fd.getAsyncResult();
+				if (block || ready || asyncConnect.IsCompleted)
+				{
+					fd.setAsyncResult(null);
+					fd.getSocket().EndConnect(asyncConnect);
+					// work around for blocking issue
+					fd.getSocket().Blocking = fd.isSocketBlocking();
+					return 1;
+				}
+				else
+				{
+					return global::sun.nio.ch.IOStatus.UNAVAILABLE;
+				}
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				throw new global::java.net.ConnectException(x.Message);
+			}
+			catch (System.ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+#endif
+		}
+
+		public static int sendOutOfBandData(FileDescriptor fd, byte data)
+		{
+#if FIRST_PASS
+			return 0;
+#else
+			try
+			{
+				fd.getSocket().Send(new byte[] { data }, 1, System.Net.Sockets.SocketFlags.OutOfBand);
+				return 1;
+			}
+			catch (System.Net.Sockets.SocketException x)
+			{
+				throw new global::java.net.ConnectException(x.Message);
+			}
+			catch (System.ObjectDisposedException)
+			{
+				throw new global::java.net.SocketException("Socket is closed");
+			}
+#endif
+		}
+	}
+}
diff --git a/runtime/openjdk/sun.reflect.cs b/runtime/openjdk/sun.reflect.cs
new file mode 100644
index 0000000..b6a1fff
--- /dev/null
+++ b/runtime/openjdk/sun.reflect.cs
@@ -0,0 +1,2310 @@
+/*
+  Copyright (C) 2007-2014 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Diagnostics;
+using System.Collections.Generic;
+using System.Reflection;
+#if !NO_REF_EMIT
+using System.Reflection.Emit;
+#endif
+using System.Runtime.CompilerServices;
+using System.Runtime.Serialization;
+using System.Security;
+using IKVM.Internal;
+using IKVM.Attributes;
+
+namespace IKVM.Internal
+{
+#if !FIRST_PASS
+	public interface IReflectionException
+	{
+		java.lang.IllegalArgumentException GetIllegalArgumentException(object obj);
+		java.lang.IllegalArgumentException SetIllegalArgumentException(object obj);
+	}
+#endif
+}
+
+static class Java_sun_reflect_Reflection
+{
+#if CLASSGC
+	sealed class State
+	{
+		internal HideFromJavaFlags Value;
+		internal volatile bool HasValue;
+	}
+
+	private static readonly ConditionalWeakTable isHideFromJavaCache = new ConditionalWeakTable();
+
+	internal static HideFromJavaFlags GetHideFromJavaFlags(MethodBase mb)
+	{
+		if (mb.Name.StartsWith("__<", StringComparison.Ordinal))
+		{
+			return HideFromJavaFlags.All;
+		}
+		State state = isHideFromJavaCache.GetValue(mb, delegate { return new State(); });
+		if (!state.HasValue)
+		{
+			state.Value = AttributeHelper.GetHideFromJavaFlags(mb);
+			state.HasValue = true;
+		}
+		return state.Value;
+	}
+#else
+	private static readonly Dictionary isHideFromJavaCache = new Dictionary();
+
+	internal static HideFromJavaFlags GetHideFromJavaFlags(MethodBase mb)
+	{
+		if (mb.Name.StartsWith("__<", StringComparison.Ordinal))
+		{
+			return HideFromJavaFlags.All;
+		}
+		RuntimeMethodHandle handle;
+		try
+		{
+			handle = mb.MethodHandle;
+		}
+		catch (InvalidOperationException)
+		{
+			// DynamicMethods don't have a RuntimeMethodHandle and we always want to hide them anyway
+			return HideFromJavaFlags.All;
+		}
+		catch (NotSupportedException)
+		{
+			// DynamicMethods don't have a RuntimeMethodHandle and we always want to hide them anyway
+			return HideFromJavaFlags.All;
+		}
+		lock (isHideFromJavaCache)
+		{
+			HideFromJavaFlags cached;
+			if (isHideFromJavaCache.TryGetValue(handle, out cached))
+			{
+				return cached;
+			}
+		}
+		HideFromJavaFlags flags = AttributeHelper.GetHideFromJavaFlags(mb);
+		lock (isHideFromJavaCache)
+		{
+			isHideFromJavaCache[handle] = flags;
+		}
+		return flags;
+	}
+#endif
+
+	internal static bool IsHideFromStackWalk(MethodBase mb)
+	{
+		Type type = mb.DeclaringType;
+		return type == null
+			|| type.Assembly == typeof(object).Assembly
+			|| type.Assembly == typeof(Java_sun_reflect_Reflection).Assembly
+			|| type.Assembly == Java_java_lang_SecurityManager.jniAssembly
+			|| type == typeof(java.lang.reflect.Method)
+			|| type == typeof(java.lang.reflect.Constructor)
+			|| (GetHideFromJavaFlags(mb) & HideFromJavaFlags.StackWalk) != 0
+			;
+	}
+
+	public static java.lang.Class getCallerClass()
+	{
+#if FIRST_PASS
+		return null;
+#else
+		throw new java.lang.InternalError("CallerSensitive annotation expected at frame 1");
+#endif
+	}
+
+	// NOTE this method is hooked up explicitly through map.xml to prevent inlining of the native stub
+	// and tail-call optimization in the native stub.
+	public static java.lang.Class getCallerClass(int realFramesToSkip)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		if (realFramesToSkip <= 0)
+		{
+			return ikvm.@internal.ClassLiteral.Value;
+		}
+		for (int i = 2; ; )
+		{
+			MethodBase method = new StackFrame(i++, false).GetMethod();
+			if (method == null)
+			{
+				return null;
+			}
+			if (IsHideFromStackWalk(method))
+			{
+				continue;
+			}
+			// HACK we skip HideFromJavaFlags.StackTrace too because we want to skip the LambdaForm methods
+			// that are used by late binding
+			if ((GetHideFromJavaFlags(method) & HideFromJavaFlags.StackTrace) != 0)
+			{
+				continue;
+			}
+			if (--realFramesToSkip == 0)
+			{
+				return ClassLoaderWrapper.GetWrapperFromType(method.DeclaringType).ClassObject;
+			}
+		}
+#endif
+	}
+
+	public static int getClassAccessFlags(java.lang.Class clazz)
+	{
+		// the mask comes from JVM_RECOGNIZED_CLASS_MODIFIERS in src/hotspot/share/vm/prims/jvm.h
+		int mods = (int)TypeWrapper.FromClass(clazz).Modifiers & 0x7631;
+		// interface implies abstract
+		mods |= (mods & 0x0200) << 1;
+		return mods;
+	}
+
+	public static bool checkInternalAccess(java.lang.Class currentClass, java.lang.Class memberClass)
+	{
+		TypeWrapper current = TypeWrapper.FromClass(currentClass);
+		TypeWrapper member = TypeWrapper.FromClass(memberClass);
+		return member.IsInternal && member.InternalsVisibleTo(current);
+	}
+}
+
+static class Java_sun_reflect_ReflectionFactory
+{
+#if !FIRST_PASS
+	private static object ConvertPrimitive(TypeWrapper tw, object value)
+	{
+		if (tw == PrimitiveTypeWrapper.BOOLEAN)
+		{
+			if (value is java.lang.Boolean)
+			{
+				return ((java.lang.Boolean)value).booleanValue();
+			}
+		}
+		else if (tw == PrimitiveTypeWrapper.BYTE)
+		{
+			if (value is java.lang.Byte)
+			{
+				return ((java.lang.Byte)value).byteValue();
+			}
+		}
+		else if (tw == PrimitiveTypeWrapper.CHAR)
+		{
+			if (value is java.lang.Character)
+			{
+				return ((java.lang.Character)value).charValue();
+			}
+		}
+		else if (tw == PrimitiveTypeWrapper.SHORT)
+		{
+			if (value is java.lang.Short || value is java.lang.Byte)
+			{
+				return ((java.lang.Number)value).shortValue();
+			}
+		}
+		else if (tw == PrimitiveTypeWrapper.INT)
+		{
+			if (value is java.lang.Integer || value is java.lang.Short || value is java.lang.Byte)
+			{
+				return ((java.lang.Number)value).intValue();
+			}
+			else if (value is java.lang.Character)
+			{
+				return (int)((java.lang.Character)value).charValue();
+			}
+		}
+		else if (tw == PrimitiveTypeWrapper.LONG)
+		{
+			if (value is java.lang.Long || value is java.lang.Integer || value is java.lang.Short || value is java.lang.Byte)
+			{
+				return ((java.lang.Number)value).longValue();
+			}
+			else if (value is java.lang.Character)
+			{
+				return (long)((java.lang.Character)value).charValue();
+			}
+		}
+		else if (tw == PrimitiveTypeWrapper.FLOAT)
+		{
+			if (value is java.lang.Float || value is java.lang.Long || value is java.lang.Integer || value is java.lang.Short || value is java.lang.Byte)
+			{
+				return ((java.lang.Number)value).floatValue();
+			}
+			else if (value is java.lang.Character)
+			{
+				return (float)((java.lang.Character)value).charValue();
+			}
+		}
+		else if (tw == PrimitiveTypeWrapper.DOUBLE)
+		{
+			if (value is java.lang.Double || value is java.lang.Float || value is java.lang.Long || value is java.lang.Integer || value is java.lang.Short || value is java.lang.Byte)
+			{
+				return ((java.lang.Number)value).doubleValue();
+			}
+			else if (value is java.lang.Character)
+			{
+				return (double)((java.lang.Character)value).charValue();
+			}
+		}
+		throw new java.lang.IllegalArgumentException();
+	}
+
+	private static object[] ConvertArgs(ClassLoaderWrapper loader, TypeWrapper[] argumentTypes, object[] args)
+	{
+		object[] nargs = new object[args == null ? 0 : args.Length];
+		if (nargs.Length != argumentTypes.Length)
+		{
+			throw new java.lang.IllegalArgumentException("wrong number of arguments");
+		}
+		for (int i = 0; i < nargs.Length; i++)
+		{
+			if (argumentTypes[i].IsPrimitive)
+			{
+				nargs[i] = ConvertPrimitive(argumentTypes[i], args[i]);
+			}
+			else
+			{
+				if (args[i] != null && !argumentTypes[i].EnsureLoadable(loader).IsInstance(args[i]))
+				{
+					throw new java.lang.IllegalArgumentException();
+				}
+				nargs[i] = argumentTypes[i].GhostWrap(args[i]);
+			}
+		}
+		return nargs;
+	}
+
+	private sealed class MethodAccessorImpl : sun.reflect.MethodAccessor
+	{
+		private readonly MethodWrapper mw;
+
+		internal MethodAccessorImpl(MethodWrapper mw)
+		{
+			this.mw = mw;
+			mw.Link();
+			mw.ResolveMethod();
+		}
+
+		[IKVM.Attributes.HideFromJava]
+		public object invoke(object obj, object[] args, ikvm.@internal.CallerID callerID)
+		{
+			if (!mw.IsStatic && !mw.DeclaringType.IsInstance(obj))
+			{
+				if (obj == null)
+				{
+					throw new java.lang.NullPointerException();
+				}
+				throw new java.lang.IllegalArgumentException("object is not an instance of declaring class");
+			}
+			args = ConvertArgs(mw.DeclaringType.GetClassLoader(), mw.GetParameters(), args);
+			// if the method is an interface method, we must explicitly run ,
+			// because .NET reflection doesn't
+			if (mw.DeclaringType.IsInterface)
+			{
+				mw.DeclaringType.RunClassInit();
+			}
+			if (mw.HasCallerID)
+			{
+				args = ArrayUtil.Concat(args, callerID);
+			}
+			object retval;
+			try
+			{
+				retval = mw.Invoke(obj, args);
+			}
+			catch (Exception x)
+			{
+				throw new java.lang.reflect.InvocationTargetException(ikvm.runtime.Util.mapException(x));
+			}
+			if (mw.ReturnType.IsPrimitive && mw.ReturnType != PrimitiveTypeWrapper.VOID)
+			{
+				retval = JVM.Box(retval);
+			}
+			else
+			{
+				retval = mw.ReturnType.GhostUnwrap(retval);
+			}
+			return retval;
+		}
+	}
+
+	private sealed class ConstructorAccessorImpl : sun.reflect.ConstructorAccessor
+	{
+		private readonly MethodWrapper mw;
+
+		internal ConstructorAccessorImpl(MethodWrapper mw)
+		{
+			this.mw = mw;
+			mw.Link();
+			mw.ResolveMethod();
+		}
+
+		[IKVM.Attributes.HideFromJava]
+		public object newInstance(object[] args)
+		{
+			args = ConvertArgs(mw.DeclaringType.GetClassLoader(), mw.GetParameters(), args);
+			try
+			{
+				return mw.CreateInstance(args);
+			}
+			catch (Exception x)
+			{
+				throw new java.lang.reflect.InvocationTargetException(ikvm.runtime.Util.mapException(x));
+			}
+		}
+	}
+
+	private sealed class SerializationConstructorAccessorImpl : sun.reflect.ConstructorAccessor
+	{
+		private readonly MethodWrapper mw;
+		private readonly Type type;
+
+		internal SerializationConstructorAccessorImpl(java.lang.reflect.Constructor constructorToCall, java.lang.Class classToInstantiate)
+		{
+			this.type = TypeWrapper.FromClass(classToInstantiate).TypeAsBaseType;
+			MethodWrapper mw = MethodWrapper.FromExecutable(constructorToCall);
+			if (mw.DeclaringType != CoreClasses.java.lang.Object.Wrapper)
+			{
+				this.mw = mw;
+				mw.Link();
+				mw.ResolveMethod();
+			}
+		}
+
+		[IKVM.Attributes.HideFromJava]
+		[SecuritySafeCritical]
+		public object newInstance(object[] args)
+		{
+			object obj = FormatterServices.GetUninitializedObject(type);
+			if (mw != null)
+			{
+				mw.Invoke(obj, ConvertArgs(mw.DeclaringType.GetClassLoader(), mw.GetParameters(), args));
+			}
+			return obj;
+		}
+	}
+
+#if !NO_REF_EMIT
+	private sealed class BoxUtil
+	{
+		private static readonly MethodInfo valueOfByte = typeof(java.lang.Byte).GetMethod("valueOf", new Type[] { typeof(byte) });
+		private static readonly MethodInfo valueOfBoolean = typeof(java.lang.Boolean).GetMethod("valueOf", new Type[] { typeof(bool) });
+		private static readonly MethodInfo valueOfChar = typeof(java.lang.Character).GetMethod("valueOf", new Type[] { typeof(char) });
+		private static readonly MethodInfo valueOfShort = typeof(java.lang.Short).GetMethod("valueOf", new Type[] { typeof(short) });
+		private static readonly MethodInfo valueOfInt = typeof(java.lang.Integer).GetMethod("valueOf", new Type[] { typeof(int) });
+		private static readonly MethodInfo valueOfFloat = typeof(java.lang.Float).GetMethod("valueOf", new Type[] { typeof(float) });
+		private static readonly MethodInfo valueOfLong = typeof(java.lang.Long).GetMethod("valueOf", new Type[] { typeof(long) });
+		private static readonly MethodInfo valueOfDouble = typeof(java.lang.Double).GetMethod("valueOf", new Type[] { typeof(double) });
+		private static readonly MethodInfo byteValue = typeof(java.lang.Byte).GetMethod("byteValue", Type.EmptyTypes);
+		private static readonly MethodInfo booleanValue = typeof(java.lang.Boolean).GetMethod("booleanValue", Type.EmptyTypes);
+		private static readonly MethodInfo charValue = typeof(java.lang.Character).GetMethod("charValue", Type.EmptyTypes);
+		private static readonly MethodInfo shortValue = typeof(java.lang.Short).GetMethod("shortValue", Type.EmptyTypes);
+		private static readonly MethodInfo intValue = typeof(java.lang.Integer).GetMethod("intValue", Type.EmptyTypes);
+		private static readonly MethodInfo floatValue = typeof(java.lang.Float).GetMethod("floatValue", Type.EmptyTypes);
+		private static readonly MethodInfo longValue = typeof(java.lang.Long).GetMethod("longValue", Type.EmptyTypes);
+		private static readonly MethodInfo doubleValue = typeof(java.lang.Double).GetMethod("doubleValue", Type.EmptyTypes);
+
+		internal static void EmitUnboxArg(CodeEmitter ilgen, TypeWrapper type)
+		{
+			if (type == PrimitiveTypeWrapper.BYTE)
+			{
+				ilgen.Emit(OpCodes.Castclass, typeof(java.lang.Byte));
+				ilgen.Emit(OpCodes.Call, byteValue);
+			}
+			else if (type == PrimitiveTypeWrapper.BOOLEAN)
+			{
+				ilgen.Emit(OpCodes.Castclass, typeof(java.lang.Boolean));
+				ilgen.Emit(OpCodes.Call, booleanValue);
+			}
+			else if (type == PrimitiveTypeWrapper.CHAR)
+			{
+				ilgen.Emit(OpCodes.Castclass, typeof(java.lang.Character));
+				ilgen.Emit(OpCodes.Call, charValue);
+			}
+			else if (type == PrimitiveTypeWrapper.SHORT
+				|| type == PrimitiveTypeWrapper.INT
+				|| type == PrimitiveTypeWrapper.FLOAT
+				|| type == PrimitiveTypeWrapper.LONG
+				|| type == PrimitiveTypeWrapper.DOUBLE)
+			{
+				ilgen.Emit(OpCodes.Dup);
+				ilgen.Emit(OpCodes.Isinst, typeof(java.lang.Byte));
+				CodeEmitterLabel next = ilgen.DefineLabel();
+				ilgen.EmitBrfalse(next);
+				ilgen.Emit(OpCodes.Castclass, typeof(java.lang.Byte));
+				ilgen.Emit(OpCodes.Call, byteValue);
+				ilgen.Emit(OpCodes.Conv_I1);
+				Expand(ilgen, type);
+				CodeEmitterLabel done = ilgen.DefineLabel();
+				ilgen.EmitBr(done);
+				ilgen.MarkLabel(next);
+				if (type == PrimitiveTypeWrapper.SHORT)
+				{
+					ilgen.Emit(OpCodes.Castclass, typeof(java.lang.Short));
+					ilgen.Emit(OpCodes.Call, shortValue);
+				}
+				else
+				{
+					ilgen.Emit(OpCodes.Dup);
+					ilgen.Emit(OpCodes.Isinst, typeof(java.lang.Short));
+					next = ilgen.DefineLabel();
+					ilgen.EmitBrfalse(next);
+					ilgen.Emit(OpCodes.Castclass, typeof(java.lang.Short));
+					ilgen.Emit(OpCodes.Call, shortValue);
+					Expand(ilgen, type);
+					ilgen.EmitBr(done);
+					ilgen.MarkLabel(next);
+					ilgen.Emit(OpCodes.Dup);
+					ilgen.Emit(OpCodes.Isinst, typeof(java.lang.Character));
+					next = ilgen.DefineLabel();
+					ilgen.EmitBrfalse(next);
+					ilgen.Emit(OpCodes.Castclass, typeof(java.lang.Character));
+					ilgen.Emit(OpCodes.Call, charValue);
+					Expand(ilgen, type);
+					ilgen.EmitBr(done);
+					ilgen.MarkLabel(next);
+					if (type == PrimitiveTypeWrapper.INT)
+					{
+						ilgen.Emit(OpCodes.Castclass, typeof(java.lang.Integer));
+						ilgen.Emit(OpCodes.Call, intValue);
+					}
+					else
+					{
+						ilgen.Emit(OpCodes.Dup);
+						ilgen.Emit(OpCodes.Isinst, typeof(java.lang.Integer));
+						next = ilgen.DefineLabel();
+						ilgen.EmitBrfalse(next);
+						ilgen.Emit(OpCodes.Castclass, typeof(java.lang.Integer));
+						ilgen.Emit(OpCodes.Call, intValue);
+						Expand(ilgen, type);
+						ilgen.EmitBr(done);
+						ilgen.MarkLabel(next);
+						if (type == PrimitiveTypeWrapper.LONG)
+						{
+							ilgen.Emit(OpCodes.Castclass, typeof(java.lang.Long));
+							ilgen.Emit(OpCodes.Call, longValue);
+						}
+						else
+						{
+							ilgen.Emit(OpCodes.Dup);
+							ilgen.Emit(OpCodes.Isinst, typeof(java.lang.Long));
+							next = ilgen.DefineLabel();
+							ilgen.EmitBrfalse(next);
+							ilgen.Emit(OpCodes.Castclass, typeof(java.lang.Long));
+							ilgen.Emit(OpCodes.Call, longValue);
+							Expand(ilgen, type);
+							ilgen.EmitBr(done);
+							ilgen.MarkLabel(next);
+							if (type == PrimitiveTypeWrapper.FLOAT)
+							{
+								ilgen.Emit(OpCodes.Castclass, typeof(java.lang.Float));
+								ilgen.Emit(OpCodes.Call, floatValue);
+							}
+							else if (type == PrimitiveTypeWrapper.DOUBLE)
+							{
+								ilgen.Emit(OpCodes.Dup);
+								ilgen.Emit(OpCodes.Isinst, typeof(java.lang.Float));
+								next = ilgen.DefineLabel();
+								ilgen.EmitBrfalse(next);
+								ilgen.Emit(OpCodes.Castclass, typeof(java.lang.Float));
+								ilgen.Emit(OpCodes.Call, floatValue);
+								ilgen.EmitBr(done);
+								ilgen.MarkLabel(next);
+								ilgen.Emit(OpCodes.Castclass, typeof(java.lang.Double));
+								ilgen.Emit(OpCodes.Call, doubleValue);
+							}
+							else
+							{
+								throw new InvalidOperationException();
+							}
+						}
+					}
+				}
+				ilgen.MarkLabel(done);
+			}
+			else
+			{
+				type.EmitCheckcast(ilgen);
+			}
+		}
+
+		internal static void BoxReturnValue(CodeEmitter ilgen, TypeWrapper type)
+		{
+			if (type == PrimitiveTypeWrapper.VOID)
+			{
+				ilgen.Emit(OpCodes.Ldnull);
+			}
+			else if (type == PrimitiveTypeWrapper.BYTE)
+			{
+				ilgen.Emit(OpCodes.Call, valueOfByte);
+			}
+			else if (type == PrimitiveTypeWrapper.BOOLEAN)
+			{
+				ilgen.Emit(OpCodes.Call, valueOfBoolean);
+			}
+			else if (type == PrimitiveTypeWrapper.CHAR)
+			{
+				ilgen.Emit(OpCodes.Call, valueOfChar);
+			}
+			else if (type == PrimitiveTypeWrapper.SHORT)
+			{
+				ilgen.Emit(OpCodes.Call, valueOfShort);
+			}
+			else if (type == PrimitiveTypeWrapper.INT)
+			{
+				ilgen.Emit(OpCodes.Call, valueOfInt);
+			}
+			else if (type == PrimitiveTypeWrapper.FLOAT)
+			{
+				ilgen.Emit(OpCodes.Call, valueOfFloat);
+			}
+			else if (type == PrimitiveTypeWrapper.LONG)
+			{
+				ilgen.Emit(OpCodes.Call, valueOfLong);
+			}
+			else if (type == PrimitiveTypeWrapper.DOUBLE)
+			{
+				ilgen.Emit(OpCodes.Call, valueOfDouble);
+			}
+		}
+
+		private static void Expand(CodeEmitter ilgen, TypeWrapper type)
+		{
+			if (type == PrimitiveTypeWrapper.FLOAT)
+			{
+				ilgen.Emit(OpCodes.Conv_R4);
+			}
+			else if (type == PrimitiveTypeWrapper.LONG)
+			{
+				ilgen.Emit(OpCodes.Conv_I8);
+			}
+			else if (type == PrimitiveTypeWrapper.DOUBLE)
+			{
+				ilgen.Emit(OpCodes.Conv_R8);
+			}
+		}
+	}
+
+	private sealed class FastMethodAccessorImpl : sun.reflect.MethodAccessor
+	{
+		internal static readonly ConstructorInfo invocationTargetExceptionCtor;
+		internal static readonly ConstructorInfo illegalArgumentExceptionCtor;
+		internal static readonly MethodInfo get_TargetSite;
+		internal static readonly MethodInfo GetCurrentMethod;
+
+		private delegate object Invoker(object obj, object[] args, ikvm.@internal.CallerID callerID);
+		private Invoker invoker;
+
+		static FastMethodAccessorImpl()
+		{
+			invocationTargetExceptionCtor = typeof(java.lang.reflect.InvocationTargetException).GetConstructor(new Type[] { typeof(Exception) });
+			illegalArgumentExceptionCtor = typeof(java.lang.IllegalArgumentException).GetConstructor(Type.EmptyTypes);
+			get_TargetSite = typeof(Exception).GetMethod("get_TargetSite");
+			GetCurrentMethod = typeof(MethodBase).GetMethod("GetCurrentMethod");
+		}
+
+		private sealed class RunClassInit
+		{
+			private FastMethodAccessorImpl outer;
+			private TypeWrapper tw;
+			private Invoker invoker;
+
+			internal RunClassInit(FastMethodAccessorImpl outer, TypeWrapper tw, Invoker invoker)
+			{
+				this.outer = outer;
+				this.tw = tw;
+				this.invoker = invoker;
+			}
+
+			[IKVM.Attributes.HideFromJava]
+			internal object invoke(object obj, object[] args, ikvm.@internal.CallerID callerID)
+			{
+				// FXBUG pre-SP1 a DynamicMethod that calls a static method doesn't trigger the cctor, so we do that explicitly.
+				// even on .NET 2.0 SP2, interface method invocations don't run the interface cctor
+				// NOTE when testing, please test both the x86 and x64 CLR JIT, because they have different bugs (even on .NET 2.0 SP2)
+				tw.RunClassInit();
+				outer.invoker = invoker;
+				return invoker(obj, args, callerID);
+			}
+		}
+
+		internal FastMethodAccessorImpl(MethodWrapper mw)
+		{
+			TypeWrapper[] parameters;
+			try
+			{
+				mw.DeclaringType.Finish();
+				parameters = mw.GetParameters();
+				for (int i = 0; i < parameters.Length; i++)
+				{
+					// the EnsureLoadable shouldn't fail, because we don't allow a java.lang.reflect.Method
+					// to "escape" if it has an unloadable type in the signature
+					parameters[i] = parameters[i].EnsureLoadable(mw.DeclaringType.GetClassLoader());
+					parameters[i].Finish();
+				}
+			}
+			catch (RetargetableJavaException x)
+			{
+				throw x.ToJava();
+			}
+			mw.ResolveMethod();
+			DynamicMethod dm = DynamicMethodUtils.Create("__", mw.DeclaringType.TypeAsBaseType, !mw.IsPublic || !mw.DeclaringType.IsPublic, typeof(object), new Type[] { typeof(object), typeof(object[]), typeof(ikvm.@internal.CallerID) });
+			CodeEmitter ilgen = CodeEmitter.Create(dm);
+			CodeEmitterLocal ret = ilgen.DeclareLocal(typeof(object));
+			if (!mw.IsStatic)
+			{
+				// check target for null
+				ilgen.Emit(OpCodes.Ldarg_0);
+				ilgen.EmitNullCheck();
+			}
+
+			// check args length
+			CodeEmitterLabel argsLengthOK = ilgen.DefineLabel();
+			if (parameters.Length == 0)
+			{
+				// zero length array may be null
+				ilgen.Emit(OpCodes.Ldarg_1);
+				ilgen.EmitBrfalse(argsLengthOK);
+			}
+			ilgen.Emit(OpCodes.Ldarg_1);
+			ilgen.Emit(OpCodes.Ldlen);
+			ilgen.EmitLdc_I4(parameters.Length);
+			ilgen.EmitBeq(argsLengthOK);
+			ilgen.Emit(OpCodes.Newobj, illegalArgumentExceptionCtor);
+			ilgen.Emit(OpCodes.Throw);
+			ilgen.MarkLabel(argsLengthOK);
+
+			int thisCount = mw.IsStatic ? 0 : 1;
+			CodeEmitterLocal[] args = new CodeEmitterLocal[parameters.Length + thisCount];
+			if (!mw.IsStatic)
+			{
+				args[0] = ilgen.DeclareLocal(mw.DeclaringType.TypeAsSignatureType);
+			}
+			for (int i = thisCount; i < args.Length; i++)
+			{
+				args[i] = ilgen.DeclareLocal(parameters[i - thisCount].TypeAsSignatureType);
+			}
+			ilgen.BeginExceptionBlock();
+			if (!mw.IsStatic)
+			{
+				ilgen.Emit(OpCodes.Ldarg_0);
+				mw.DeclaringType.EmitCheckcast(ilgen);
+				mw.DeclaringType.EmitConvStackTypeToSignatureType(ilgen, null);
+				ilgen.Emit(OpCodes.Stloc, args[0]);
+			}
+			for (int i = thisCount; i < args.Length; i++)
+			{
+				ilgen.Emit(OpCodes.Ldarg_1);
+				ilgen.EmitLdc_I4(i - thisCount);
+				ilgen.Emit(OpCodes.Ldelem_Ref);
+				TypeWrapper tw = parameters[i - thisCount];
+				BoxUtil.EmitUnboxArg(ilgen, tw);
+				tw.EmitConvStackTypeToSignatureType(ilgen, null);
+				ilgen.Emit(OpCodes.Stloc, args[i]);
+			}
+			CodeEmitterLabel label1 = ilgen.DefineLabel();
+			ilgen.EmitLeave(label1);
+			ilgen.BeginCatchBlock(typeof(InvalidCastException));
+			ilgen.Emit(OpCodes.Newobj, illegalArgumentExceptionCtor);
+			ilgen.Emit(OpCodes.Throw);
+			ilgen.BeginCatchBlock(typeof(NullReferenceException));
+			ilgen.Emit(OpCodes.Newobj, illegalArgumentExceptionCtor);
+			ilgen.Emit(OpCodes.Throw);
+			ilgen.EndExceptionBlock();
+
+			// this is the actual call
+			ilgen.MarkLabel(label1);
+			ilgen.BeginExceptionBlock();
+			for (int i = 0; i < args.Length; i++)
+			{
+				if (i == 0 && !mw.IsStatic && (mw.DeclaringType.IsNonPrimitiveValueType || mw.DeclaringType.IsGhost))
+				{
+					ilgen.Emit(OpCodes.Ldloca, args[i]);
+				}
+				else
+				{
+					ilgen.Emit(OpCodes.Ldloc, args[i]);
+				}
+			}
+			if (mw.HasCallerID)
+			{
+				ilgen.Emit(OpCodes.Ldarg_2);
+			}
+			if (mw.IsStatic)
+			{
+				mw.EmitCall(ilgen);
+			}
+			else
+			{
+				mw.EmitCallvirtReflect(ilgen);
+			}
+			mw.ReturnType.EmitConvSignatureTypeToStackType(ilgen);
+			BoxUtil.BoxReturnValue(ilgen, mw.ReturnType);
+			ilgen.Emit(OpCodes.Stloc, ret);
+			CodeEmitterLabel label2 = ilgen.DefineLabel();
+			ilgen.EmitLeave(label2);
+			ilgen.BeginCatchBlock(typeof(Exception));
+			CodeEmitterLabel label = ilgen.DefineLabel();
+			CodeEmitterLabel labelWrap = ilgen.DefineLabel();
+			// If the exception we caught is a java.lang.reflect.InvocationTargetException, we know it must be
+			// wrapped, because .NET won't throw that exception and we also cannot check the target site,
+			// because it may be the same as us if a method is recursively invoking itself.
+			ilgen.Emit(OpCodes.Dup);
+			ilgen.Emit(OpCodes.Isinst, typeof(java.lang.reflect.InvocationTargetException));
+			ilgen.EmitBrtrue(labelWrap);
+			ilgen.Emit(OpCodes.Dup);
+			ilgen.Emit(OpCodes.Callvirt, get_TargetSite);
+			ilgen.Emit(OpCodes.Call, GetCurrentMethod);
+			ilgen.Emit(OpCodes.Ceq);
+			ilgen.EmitBrtrue(label);
+			ilgen.MarkLabel(labelWrap);
+			ilgen.Emit(OpCodes.Ldc_I4_0);
+			ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.mapException.MakeGenericMethod(Types.Exception));
+			ilgen.Emit(OpCodes.Newobj, invocationTargetExceptionCtor);
+			ilgen.MarkLabel(label);
+			ilgen.Emit(OpCodes.Throw);
+			ilgen.EndExceptionBlock();
+
+			ilgen.MarkLabel(label2);
+			ilgen.Emit(OpCodes.Ldloc, ret);
+			ilgen.Emit(OpCodes.Ret);
+			ilgen.DoEmit();
+			invoker = (Invoker)dm.CreateDelegate(typeof(Invoker));
+			if ((mw.IsStatic || mw.DeclaringType.IsInterface) && mw.DeclaringType.HasStaticInitializer)
+			{
+				invoker = new Invoker(new RunClassInit(this, mw.DeclaringType, invoker).invoke);
+			}
+		}
+
+		[IKVM.Attributes.HideFromJava]
+		public object invoke(object obj, object[] args, ikvm.@internal.CallerID callerID)
+		{
+			try
+			{
+				return invoker(obj, args, callerID);
+			}
+			catch (MethodAccessException x)
+			{
+				// this can happen if we're calling a non-public method and the call stack doesn't have ReflectionPermission.MemberAccess
+				throw new java.lang.IllegalAccessException().initCause(x);
+			}
+		}
+	}
+
+	private sealed class FastConstructorAccessorImpl : sun.reflect.ConstructorAccessor
+	{
+		private delegate object Invoker(object[] args);
+		private Invoker invoker;
+
+		internal FastConstructorAccessorImpl(java.lang.reflect.Constructor constructor)
+		{
+			MethodWrapper mw = MethodWrapper.FromExecutable(constructor);
+			TypeWrapper[] parameters;
+			try
+			{
+				mw.DeclaringType.Finish();
+				parameters = mw.GetParameters();
+				for (int i = 0; i < parameters.Length; i++)
+				{
+					// the EnsureLoadable shouldn't fail, because we don't allow a java.lang.reflect.Method
+					// to "escape" if it has an unloadable type in the signature
+					parameters[i] = parameters[i].EnsureLoadable(mw.DeclaringType.GetClassLoader());
+					parameters[i].Finish();
+				}
+			}
+			catch (RetargetableJavaException x)
+			{
+				throw x.ToJava();
+			}
+			mw.ResolveMethod();
+			DynamicMethod dm = DynamicMethodUtils.Create("__", mw.DeclaringType.TypeAsTBD, !mw.IsPublic || !mw.DeclaringType.IsPublic, typeof(object), new Type[] { typeof(object[]) });
+			CodeEmitter ilgen = CodeEmitter.Create(dm);
+			CodeEmitterLocal ret = ilgen.DeclareLocal(typeof(object));
+
+			// check args length
+			CodeEmitterLabel argsLengthOK = ilgen.DefineLabel();
+			if (parameters.Length == 0)
+			{
+				// zero length array may be null
+				ilgen.Emit(OpCodes.Ldarg_0);
+				ilgen.EmitBrfalse(argsLengthOK);
+			}
+			ilgen.Emit(OpCodes.Ldarg_0);
+			ilgen.Emit(OpCodes.Ldlen);
+			ilgen.EmitLdc_I4(parameters.Length);
+			ilgen.EmitBeq(argsLengthOK);
+			ilgen.Emit(OpCodes.Newobj, FastMethodAccessorImpl.illegalArgumentExceptionCtor);
+			ilgen.Emit(OpCodes.Throw);
+			ilgen.MarkLabel(argsLengthOK);
+
+			CodeEmitterLocal[] args = new CodeEmitterLocal[parameters.Length];
+			for (int i = 0; i < args.Length; i++)
+			{
+				args[i] = ilgen.DeclareLocal(parameters[i].TypeAsSignatureType);
+			}
+			ilgen.BeginExceptionBlock();
+			for (int i = 0; i < args.Length; i++)
+			{
+				ilgen.Emit(OpCodes.Ldarg_0);
+				ilgen.EmitLdc_I4(i);
+				ilgen.Emit(OpCodes.Ldelem_Ref);
+				TypeWrapper tw = parameters[i];
+				BoxUtil.EmitUnboxArg(ilgen, tw);
+				tw.EmitConvStackTypeToSignatureType(ilgen, null);
+				ilgen.Emit(OpCodes.Stloc, args[i]);
+			}
+			CodeEmitterLabel label1 = ilgen.DefineLabel();
+			ilgen.EmitLeave(label1);
+			ilgen.BeginCatchBlock(typeof(InvalidCastException));
+			ilgen.Emit(OpCodes.Newobj, FastMethodAccessorImpl.illegalArgumentExceptionCtor);
+			ilgen.Emit(OpCodes.Throw);
+			ilgen.BeginCatchBlock(typeof(NullReferenceException));
+			ilgen.Emit(OpCodes.Newobj, FastMethodAccessorImpl.illegalArgumentExceptionCtor);
+			ilgen.Emit(OpCodes.Throw);
+			ilgen.EndExceptionBlock();
+
+			// this is the actual call
+			ilgen.MarkLabel(label1);
+			ilgen.BeginExceptionBlock();
+			for (int i = 0; i < args.Length; i++)
+			{
+				ilgen.Emit(OpCodes.Ldloc, args[i]);
+			}
+			mw.EmitNewobj(ilgen);
+			ilgen.Emit(OpCodes.Stloc, ret);
+			CodeEmitterLabel label2 = ilgen.DefineLabel();
+			ilgen.EmitLeave(label2);
+			ilgen.BeginCatchBlock(typeof(Exception));
+			ilgen.Emit(OpCodes.Dup);
+			ilgen.Emit(OpCodes.Callvirt, FastMethodAccessorImpl.get_TargetSite);
+			ilgen.Emit(OpCodes.Call, FastMethodAccessorImpl.GetCurrentMethod);
+			ilgen.Emit(OpCodes.Ceq);
+			CodeEmitterLabel label = ilgen.DefineLabel();
+			ilgen.EmitBrtrue(label);
+			ilgen.Emit(OpCodes.Ldc_I4_0);
+			ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.mapException.MakeGenericMethod(Types.Exception));
+			ilgen.Emit(OpCodes.Newobj, FastMethodAccessorImpl.invocationTargetExceptionCtor);
+			ilgen.MarkLabel(label);
+			ilgen.Emit(OpCodes.Throw);
+			ilgen.EndExceptionBlock();
+
+			ilgen.MarkLabel(label2);
+			ilgen.Emit(OpCodes.Ldloc, ret);
+			ilgen.Emit(OpCodes.Ret);
+			ilgen.DoEmit();
+			invoker = (Invoker)dm.CreateDelegate(typeof(Invoker));
+		}
+
+		[IKVM.Attributes.HideFromJava]
+		public object newInstance(object[] args)
+		{
+			try
+			{
+				return invoker(args);
+			}
+			catch (MethodAccessException x)
+			{
+				// this can happen if we're calling a non-public method and the call stack doesn't have ReflectionPermission.MemberAccess
+				throw new java.lang.IllegalAccessException().initCause(x);
+			}
+		}
+	}
+
+	private sealed class FastSerializationConstructorAccessorImpl : sun.reflect.ConstructorAccessor
+	{
+		private static readonly MethodInfo GetTypeFromHandleMethod = typeof(Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(RuntimeTypeHandle) });
+		private static readonly MethodInfo GetUninitializedObjectMethod = typeof(FormatterServices).GetMethod("GetUninitializedObject", new Type[] { typeof(Type) });
+		private delegate object InvokeCtor();
+		private InvokeCtor invoker;
+
+		internal FastSerializationConstructorAccessorImpl(java.lang.reflect.Constructor constructorToCall, java.lang.Class classToInstantiate)
+		{
+			MethodWrapper constructor = MethodWrapper.FromExecutable(constructorToCall);
+			if (constructor.GetParameters().Length != 0)
+			{
+				throw new NotImplementedException("Serialization constructor cannot have parameters");
+			}
+			constructor.Link();
+			constructor.ResolveMethod();
+			Type type;
+			try
+			{
+				TypeWrapper wrapper = TypeWrapper.FromClass(classToInstantiate);
+				wrapper.Finish();
+				type = wrapper.TypeAsBaseType;
+			}
+			catch (RetargetableJavaException x)
+			{
+				throw x.ToJava();
+			}
+			DynamicMethod dm = DynamicMethodUtils.Create("__", constructor.DeclaringType.TypeAsBaseType, true, typeof(object), null);
+			CodeEmitter ilgen = CodeEmitter.Create(dm);
+			ilgen.Emit(OpCodes.Ldtoken, type);
+			ilgen.Emit(OpCodes.Call, GetTypeFromHandleMethod);
+			ilgen.Emit(OpCodes.Call, GetUninitializedObjectMethod);
+			ilgen.Emit(OpCodes.Dup);
+			constructor.EmitCall(ilgen);
+			ilgen.Emit(OpCodes.Ret);
+			ilgen.DoEmit();
+			invoker = (InvokeCtor)dm.CreateDelegate(typeof(InvokeCtor));
+		}
+
+		[IKVM.Attributes.HideFromJava]
+		public object newInstance(object[] args)
+		{
+			try
+			{
+				return invoker();
+			}
+			catch (MethodAccessException x)
+			{
+				// this can happen if we're calling a non-public method and the call stack doesn't have ReflectionPermission.MemberAccess
+				throw new java.lang.IllegalAccessException().initCause(x);
+			}
+		}
+	}
+#endif // !NO_REF_EMIT
+
+	sealed class ActivatorConstructorAccessor : sun.reflect.ConstructorAccessor
+	{
+		private readonly Type type;
+
+		internal ActivatorConstructorAccessor(MethodWrapper mw)
+		{
+			this.type = mw.DeclaringType.TypeAsBaseType;
+		}
+
+		public object newInstance(object[] objarr)
+		{
+			if (objarr != null && objarr.Length != 0)
+			{
+				throw new java.lang.IllegalArgumentException();
+			}
+			try
+			{
+				return Activator.CreateInstance(type);
+			}
+			catch (TargetInvocationException x)
+			{
+				throw new java.lang.reflect.InvocationTargetException(ikvm.runtime.Util.mapException(x.InnerException));
+			}
+		}
+
+		internal static bool IsSuitable(MethodWrapper mw)
+		{
+			MethodBase mb = mw.GetMethod();
+			return mb != null
+				&& mb.IsConstructor
+				&& mb.IsPublic
+				&& mb.DeclaringType.IsPublic
+				&& mb.DeclaringType == mw.DeclaringType.TypeAsBaseType
+				&& mb.GetParameters().Length == 0;
+		}
+	}
+
+	private abstract class FieldAccessorImplBase : sun.reflect.FieldAccessor, IReflectionException
+	{
+		protected static readonly ushort inflationThreshold = 15;
+		protected readonly FieldWrapper fw;
+		protected readonly bool isFinal;
+		protected ushort numInvocations;
+
+		static FieldAccessorImplBase()
+		{
+			string str = java.lang.Props.props.getProperty("ikvm.reflect.field.inflationThreshold");
+			int value;
+			if (str != null && int.TryParse(str, out value))
+			{
+				if (value >= ushort.MinValue && value <= ushort.MaxValue)
+				{
+					inflationThreshold = (ushort)value;
+				}
+			}
+		}
+
+		private FieldAccessorImplBase(FieldWrapper fw, bool isFinal)
+		{
+			this.fw = fw;
+			this.isFinal = isFinal;
+		}
+
+		private string GetQualifiedFieldName()
+		{
+			return fw.DeclaringType.Name + "." + fw.Name;
+		}
+
+		private string GetFieldTypeName()
+		{
+			return fw.FieldTypeWrapper.IsPrimitive
+				? fw.FieldTypeWrapper.ClassObject.getName()
+				: fw.FieldTypeWrapper.Name;
+		}
+
+		public java.lang.IllegalArgumentException GetIllegalArgumentException(object obj)
+		{
+			// LAME like JDK 6 we return the wrong exception message (talking about setting the field, instead of getting)
+			return SetIllegalArgumentException(obj);
+		}
+
+		public java.lang.IllegalArgumentException SetIllegalArgumentException(object obj)
+		{
+			// LAME like JDK 6 we return the wrong exception message (when obj is the object, instead of the value)
+			return SetIllegalArgumentException(obj != null ? ikvm.runtime.Util.getClassFromObject(obj).getName() : "", "");
+		}
+
+		private java.lang.IllegalArgumentException SetIllegalArgumentException(string attemptedType, string attemptedValue)
+		{
+			return new java.lang.IllegalArgumentException(GetSetMessage(attemptedType, attemptedValue));
+		}
+
+		protected java.lang.IllegalAccessException FinalFieldIllegalAccessException(object obj)
+		{
+			return FinalFieldIllegalAccessException(obj != null ? ikvm.runtime.Util.getClassFromObject(obj).getName() : "", "");
+		}
+
+		private java.lang.IllegalAccessException FinalFieldIllegalAccessException(string attemptedType, string attemptedValue)
+		{
+			return new java.lang.IllegalAccessException(GetSetMessage(attemptedType, attemptedValue));
+		}
+
+		private java.lang.IllegalArgumentException GetIllegalArgumentException(string type)
+		{
+			return new java.lang.IllegalArgumentException("Attempt to get " + GetFieldTypeName() + " field \"" + GetQualifiedFieldName() + "\" with illegal data type conversion to " + type);
+		}
+
+		// this message comes from sun.reflect.UnsafeFieldAccessorImpl
+		private string GetSetMessage(String attemptedType, String attemptedValue)
+		{
+			String err = "Can not set";
+			if (fw.IsStatic)
+				err += " static";
+			if (isFinal)
+				err += " final";
+			err += " " + GetFieldTypeName() + " field " + GetQualifiedFieldName() + " to ";
+			if (attemptedValue.Length > 0)
+			{
+				err += "(" + attemptedType + ")" + attemptedValue;
+			}
+			else
+			{
+				if (attemptedType.Length > 0)
+					err += attemptedType;
+				else
+					err += "null value";
+			}
+			return err;
+		}
+
+		public virtual bool getBoolean(object obj)
+		{
+			throw GetIllegalArgumentException("boolean");
+		}
+
+		public virtual byte getByte(object obj)
+		{
+			throw GetIllegalArgumentException("byte");
+		}
+
+		public virtual char getChar(object obj)
+		{
+			throw GetIllegalArgumentException("char");
+		}
+
+		public virtual short getShort(object obj)
+		{
+			throw GetIllegalArgumentException("short");
+		}
+
+		public virtual int getInt(object obj)
+		{
+			throw GetIllegalArgumentException("int");
+		}
+
+		public virtual long getLong(object obj)
+		{
+			throw GetIllegalArgumentException("long");
+		}
+
+		public virtual float getFloat(object obj)
+		{
+			throw GetIllegalArgumentException("float");
+		}
+
+		public virtual double getDouble(object obj)
+		{
+			throw GetIllegalArgumentException("double");
+		}
+
+		public virtual void setBoolean(object obj, bool z)
+		{
+			throw SetIllegalArgumentException("boolean", java.lang.Boolean.toString(z));
+		}
+
+		public virtual void setByte(object obj, byte b)
+		{
+			throw SetIllegalArgumentException("byte", java.lang.Byte.toString(b));
+		}
+
+		public virtual void setChar(object obj, char c)
+		{
+			throw SetIllegalArgumentException("char", java.lang.Character.toString(c));
+		}
+
+		public virtual void setShort(object obj, short s)
+		{
+			throw SetIllegalArgumentException("short", java.lang.Short.toString(s));
+		}
+
+		public virtual void setInt(object obj, int i)
+		{
+			throw SetIllegalArgumentException("int", java.lang.Integer.toString(i));
+		}
+
+		public virtual void setLong(object obj, long l)
+		{
+			throw SetIllegalArgumentException("long", java.lang.Long.toString(l));
+		}
+
+		public virtual void setFloat(object obj, float f)
+		{
+			throw SetIllegalArgumentException("float", java.lang.Float.toString(f));
+		}
+
+		public virtual void setDouble(object obj, double d)
+		{
+			throw SetIllegalArgumentException("double", java.lang.Double.toString(d));
+		}
+
+		public abstract object get(object obj);
+		public abstract void set(object obj, object value);
+
+		private abstract class FieldAccessor : FieldAccessorImplBase
+		{
+			protected delegate void Setter(object obj, T value, FieldAccessor acc);
+			protected delegate T Getter(object obj, FieldAccessor acc);
+			private static readonly Setter initialSetter = lazySet;
+			private static readonly Getter initialGetter = lazyGet;
+			protected Setter setter = initialSetter;
+			protected Getter getter = initialGetter;
+
+			internal FieldAccessor(FieldWrapper fw, bool isFinal)
+				: base(fw, isFinal)
+			{
+				if (!IsSlowPathCompatible(fw))
+				{
+					// prevent slow path
+					numInvocations = inflationThreshold;
+				}
+			}
+
+			private bool IsSlowPathCompatible(FieldWrapper fw)
+			{
+#if !NO_REF_EMIT
+				if (fw.IsVolatile && (fw.FieldTypeWrapper == PrimitiveTypeWrapper.LONG || fw.FieldTypeWrapper == PrimitiveTypeWrapper.DOUBLE))
+				{
+					return false;
+				}
+#endif
+				fw.Link();
+				return true;
+			}
+
+			private static T lazyGet(object obj, FieldAccessor acc)
+			{
+				return acc.lazyGet(obj);
+			}
+
+			private static void lazySet(object obj, T value, FieldAccessor acc)
+			{
+				acc.lazySet(obj, value);
+			}
+
+			private T lazyGet(object obj)
+			{
+#if !NO_REF_EMIT
+				if (numInvocations >= inflationThreshold)
+				{
+					// FXBUG it appears that a ldsfld/stsfld in a DynamicMethod doesn't trigger the class constructor
+					// and if we didn't use the slow path, we haven't yet initialized the class
+					fw.DeclaringType.RunClassInit();
+					getter = (Getter)GenerateFastGetter(typeof(Getter), typeof(T), fw);
+					return getter(obj, this);
+				}
+#endif // !NO_REF_EMIT
+				if (fw.IsStatic)
+				{
+					obj = null;
+				}
+				else if (obj == null)
+				{
+					throw new java.lang.NullPointerException();
+				}
+				else if (!fw.DeclaringType.IsInstance(obj))
+				{
+					throw GetIllegalArgumentException(obj);
+				}
+				else if (fw.DeclaringType.IsRemapped && !fw.DeclaringType.TypeAsBaseType.IsInstanceOfType(obj))
+				{
+					throw GetUnsupportedRemappedFieldException(obj);
+				}
+				if (numInvocations == 0)
+				{
+					fw.DeclaringType.RunClassInit();
+					fw.DeclaringType.Finish();
+					fw.ResolveField();
+				}
+				numInvocations++;
+				return (T)fw.FieldTypeWrapper.GhostUnwrap(fw.GetValue(obj));
+			}
+
+			private void lazySet(object obj, T value)
+			{
+				if (isFinal)
+				{
+					// for some reason Java runs class initialization before checking if the field is final
+					fw.DeclaringType.RunClassInit();
+					throw FinalFieldIllegalAccessException(JavaBox(value));
+				}
+#if !NO_REF_EMIT
+				if (numInvocations >= inflationThreshold)
+				{
+					// FXBUG it appears that a ldsfld/stsfld in a DynamicMethod doesn't trigger the class constructor
+					// and if we didn't use the slow path, we haven't yet initialized the class
+					fw.DeclaringType.RunClassInit();
+					setter = (Setter)GenerateFastSetter(typeof(Setter), typeof(T), fw);
+					setter(obj, value, this);
+					return;
+				}
+#endif // !NO_REF_EMIT
+				if (fw.IsStatic)
+				{
+					obj = null;
+				}
+				else if (obj == null)
+				{
+					throw new java.lang.NullPointerException();
+				}
+				else if (!fw.DeclaringType.IsInstance(obj))
+				{
+					throw SetIllegalArgumentException(obj);
+				}
+				else if (fw.DeclaringType.IsRemapped && !fw.DeclaringType.TypeAsBaseType.IsInstanceOfType(obj))
+				{
+					throw GetUnsupportedRemappedFieldException(obj);
+				}
+				CheckValue(value);
+				if (numInvocations == 0)
+				{
+					fw.DeclaringType.RunClassInit();
+					fw.DeclaringType.Finish();
+					fw.ResolveField();
+				}
+				numInvocations++;
+				fw.SetValue(obj, fw.FieldTypeWrapper.GhostWrap(value));
+			}
+
+			private Exception GetUnsupportedRemappedFieldException(object obj)
+			{
+				return new java.lang.IllegalAccessException("Accessing field " + fw.DeclaringType.Name + "." + fw.Name + " in an object of type " + ikvm.runtime.Util.getClassFromObject(obj).getName() + " is not supported");
+			}
+
+			protected virtual void CheckValue(T value)
+			{
+			}
+
+			protected abstract object JavaBox(T value);
+		}
+
+		private sealed class ByteField : FieldAccessor
+		{
+			internal ByteField(FieldWrapper field, bool isFinal)
+				: base(field, isFinal)
+			{
+			}
+
+			public sealed override short getShort(object obj)
+			{
+				return (sbyte)getByte(obj);
+			}
+
+			public sealed override int getInt(object obj)
+			{
+				return (sbyte)getByte(obj);
+			}
+
+			public sealed override long getLong(object obj)
+			{
+				return (sbyte)getByte(obj);
+			}
+
+			public sealed override float getFloat(object obj)
+			{
+				return (sbyte)getByte(obj);
+			}
+
+			public sealed override double getDouble(object obj)
+			{
+				return (sbyte)getByte(obj);
+			}
+
+			public sealed override object get(object obj)
+			{
+				return java.lang.Byte.valueOf(getByte(obj));
+			}
+
+			public sealed override void set(object obj, object val)
+			{
+				if (!(val is java.lang.Byte))
+				{
+					throw SetIllegalArgumentException(val);
+				}
+				setByte(obj, ((java.lang.Byte)val).byteValue());
+			}
+
+			public sealed override byte getByte(object obj)
+			{
+				try
+				{
+					return getter(obj, this);
+				}
+				catch (FieldAccessException x)
+				{
+					throw new java.lang.IllegalAccessException().initCause(x);
+				}
+			}
+
+			public sealed override void setByte(object obj, byte value)
+			{
+				try
+				{
+					setter(obj, value, this);
+				}
+				catch (FieldAccessException x)
+				{
+					throw new java.lang.IllegalAccessException().initCause(x);
+				}
+			}
+
+			protected sealed override object JavaBox(byte value)
+			{
+				return java.lang.Byte.valueOf(value);
+			}
+		}
+
+		private sealed class BooleanField : FieldAccessor
+		{
+			internal BooleanField(FieldWrapper field, bool isFinal)
+				: base(field, isFinal)
+			{
+			}
+
+			public sealed override object get(object obj)
+			{
+				return java.lang.Boolean.valueOf(getBoolean(obj));
+			}
+
+			public sealed override void set(object obj, object val)
+			{
+				if (!(val is java.lang.Boolean))
+				{
+					throw SetIllegalArgumentException(val);
+				}
+				setBoolean(obj, ((java.lang.Boolean)val).booleanValue());
+			}
+
+			public sealed override bool getBoolean(object obj)
+			{
+				try
+				{
+					return getter(obj, this);
+				}
+				catch (FieldAccessException x)
+				{
+					throw new java.lang.IllegalAccessException().initCause(x);
+				}
+			}
+
+			public sealed override void setBoolean(object obj, bool value)
+			{
+				try
+				{
+					setter(obj, value, this);
+				}
+				catch (FieldAccessException x)
+				{
+					throw new java.lang.IllegalAccessException().initCause(x);
+				}
+			}
+
+			protected sealed override object JavaBox(bool value)
+			{
+				return java.lang.Boolean.valueOf(value);
+			}
+		}
+
+		private sealed class CharField : FieldAccessor
+		{
+			internal CharField(FieldWrapper field, bool isFinal)
+				: base(field, isFinal)
+			{
+			}
+
+			public sealed override int getInt(object obj)
+			{
+				return getChar(obj);
+			}
+
+			public sealed override long getLong(object obj)
+			{
+				return getChar(obj);
+			}
+
+			public sealed override float getFloat(object obj)
+			{
+				return getChar(obj);
+			}
+
+			public sealed override double getDouble(object obj)
+			{
+				return getChar(obj);
+			}
+
+			public sealed override object get(object obj)
+			{
+				return java.lang.Character.valueOf(getChar(obj));
+			}
+
+			public sealed override void set(object obj, object val)
+			{
+				if (val is java.lang.Character)
+					setChar(obj, ((java.lang.Character)val).charValue());
+				else
+					throw SetIllegalArgumentException(val);
+			}
+
+			public sealed override char getChar(object obj)
+			{
+				try
+				{
+					return getter(obj, this);
+				}
+				catch (FieldAccessException x)
+				{
+					throw new java.lang.IllegalAccessException().initCause(x);
+				}
+			}
+
+			public sealed override void setChar(object obj, char value)
+			{
+				try
+				{
+					setter(obj, value, this);
+				}
+				catch (FieldAccessException x)
+				{
+					throw new java.lang.IllegalAccessException().initCause(x);
+				}
+			}
+
+			protected sealed override object JavaBox(char value)
+			{
+				return java.lang.Character.valueOf(value);
+			}
+		}
+
+		private sealed class ShortField : FieldAccessor
+		{
+			internal ShortField(FieldWrapper field, bool isFinal)
+				: base(field, isFinal)
+			{
+			}
+
+			public sealed override int getInt(object obj)
+			{
+				return getShort(obj);
+			}
+
+			public sealed override long getLong(object obj)
+			{
+				return getShort(obj);
+			}
+
+			public sealed override float getFloat(object obj)
+			{
+				return getShort(obj);
+			}
+
+			public sealed override double getDouble(object obj)
+			{
+				return getShort(obj);
+			}
+
+			public sealed override object get(object obj)
+			{
+				return java.lang.Short.valueOf(getShort(obj));
+			}
+
+			public sealed override void set(object obj, object val)
+			{
+				if (val is java.lang.Byte
+					|| val is java.lang.Short)
+					setShort(obj, ((java.lang.Number)val).shortValue());
+				else
+					throw SetIllegalArgumentException(val);
+			}
+
+			public sealed override void setByte(object obj, byte b)
+			{
+				setShort(obj, (sbyte)b);
+			}
+
+			public sealed override short getShort(object obj)
+			{
+				try
+				{
+					return getter(obj, this);
+				}
+				catch (FieldAccessException x)
+				{
+					throw new java.lang.IllegalAccessException().initCause(x);
+				}
+			}
+
+			public sealed override void setShort(object obj, short value)
+			{
+				try
+				{
+					setter(obj, value, this);
+				}
+				catch (FieldAccessException x)
+				{
+					throw new java.lang.IllegalAccessException().initCause(x);
+				}
+			}
+
+			protected sealed override object JavaBox(short value)
+			{
+				return java.lang.Short.valueOf(value);
+			}
+		}
+
+		private sealed class IntField : FieldAccessor
+		{
+			internal IntField(FieldWrapper field, bool isFinal)
+				: base(field, isFinal)
+			{
+			}
+
+			public sealed override long getLong(object obj)
+			{
+				return getInt(obj);
+			}
+
+			public sealed override float getFloat(object obj)
+			{
+				return getInt(obj);
+			}
+
+			public sealed override double getDouble(object obj)
+			{
+				return getInt(obj);
+			}
+
+			public sealed override object get(object obj)
+			{
+				return java.lang.Integer.valueOf(getInt(obj));
+			}
+
+			public sealed override void set(object obj, object val)
+			{
+				if (val is java.lang.Byte
+					|| val is java.lang.Short
+					|| val is java.lang.Integer)
+					setInt(obj, ((java.lang.Number)val).intValue());
+				else if (val is java.lang.Character)
+					setInt(obj, ((java.lang.Character)val).charValue());
+				else
+					throw SetIllegalArgumentException(val);
+			}
+
+			public sealed override void setByte(object obj, byte b)
+			{
+				setInt(obj, (sbyte)b);
+			}
+
+			public sealed override void setChar(object obj, char c)
+			{
+				setInt(obj, c);
+			}
+
+			public sealed override void setShort(object obj, short s)
+			{
+				setInt(obj, s);
+			}
+
+			public sealed override int getInt(object obj)
+			{
+				try
+				{
+					return getter(obj, this);
+				}
+				catch (FieldAccessException x)
+				{
+					throw new java.lang.IllegalAccessException().initCause(x);
+				}
+			}
+
+			public sealed override void setInt(object obj, int value)
+			{
+				try
+				{
+					setter(obj, value, this);
+				}
+				catch (FieldAccessException x)
+				{
+					throw new java.lang.IllegalAccessException().initCause(x);
+				}
+			}
+
+			protected sealed override object JavaBox(int value)
+			{
+				return java.lang.Integer.valueOf(value);
+			}
+		}
+
+		private sealed class FloatField : FieldAccessor
+		{
+			internal FloatField(FieldWrapper field, bool isFinal)
+				: base(field, isFinal)
+			{
+			}
+
+			public sealed override double getDouble(object obj)
+			{
+				return getFloat(obj);
+			}
+
+			public sealed override object get(object obj)
+			{
+				return java.lang.Float.valueOf(getFloat(obj));
+			}
+
+			public sealed override void set(object obj, object val)
+			{
+				if (val is java.lang.Float
+					|| val is java.lang.Byte
+					|| val is java.lang.Short
+					|| val is java.lang.Integer
+					|| val is java.lang.Long)
+					setFloat(obj, ((java.lang.Number)val).floatValue());
+				else if (val is java.lang.Character)
+					setFloat(obj, ((java.lang.Character)val).charValue());
+				else
+					throw SetIllegalArgumentException(val);
+			}
+
+			public sealed override void setByte(object obj, byte b)
+			{
+				setFloat(obj, (sbyte)b);
+			}
+
+			public sealed override void setChar(object obj, char c)
+			{
+				setFloat(obj, c);
+			}
+
+			public sealed override void setShort(object obj, short s)
+			{
+				setFloat(obj, s);
+			}
+
+			public sealed override void setInt(object obj, int i)
+			{
+				setFloat(obj, i);
+			}
+
+			public sealed override void setLong(object obj, long l)
+			{
+				setFloat(obj, l);
+			}
+
+			public sealed override float getFloat(object obj)
+			{
+				try
+				{
+					return getter(obj, this);
+				}
+				catch (FieldAccessException x)
+				{
+					throw new java.lang.IllegalAccessException().initCause(x);
+				}
+			}
+
+			public sealed override void setFloat(object obj, float value)
+			{
+				try
+				{
+					setter(obj, value, this);
+				}
+				catch (FieldAccessException x)
+				{
+					throw new java.lang.IllegalAccessException().initCause(x);
+				}
+			}
+
+			protected sealed override object JavaBox(float value)
+			{
+				return java.lang.Float.valueOf(value);
+			}
+		}
+
+		private sealed class LongField : FieldAccessor
+		{
+			internal LongField(FieldWrapper field, bool isFinal)
+				: base(field, isFinal)
+			{
+			}
+
+			public sealed override float getFloat(object obj)
+			{
+				return getLong(obj);
+			}
+
+			public sealed override double getDouble(object obj)
+			{
+				return getLong(obj);
+			}
+
+			public sealed override object get(object obj)
+			{
+				return java.lang.Long.valueOf(getLong(obj));
+			}
+
+			public sealed override void set(object obj, object val)
+			{
+				if (val is java.lang.Long
+					|| val is java.lang.Byte
+					|| val is java.lang.Short
+					|| val is java.lang.Integer)
+					setLong(obj, ((java.lang.Number)val).longValue());
+				else if (val is java.lang.Character)
+					setLong(obj, ((java.lang.Character)val).charValue());
+				else
+					throw SetIllegalArgumentException(val);
+			}
+
+			public sealed override void setByte(object obj, byte b)
+			{
+				setLong(obj, (sbyte)b);
+			}
+
+			public sealed override void setChar(object obj, char c)
+			{
+				setLong(obj, c);
+			}
+
+			public sealed override void setShort(object obj, short s)
+			{
+				setLong(obj, s);
+			}
+
+			public sealed override void setInt(object obj, int i)
+			{
+				setLong(obj, i);
+			}
+
+			public sealed override long getLong(object obj)
+			{
+				try
+				{
+					return getter(obj, this);
+				}
+				catch (FieldAccessException x)
+				{
+					throw new java.lang.IllegalAccessException().initCause(x);
+				}
+			}
+
+			public sealed override void setLong(object obj, long value)
+			{
+				try
+				{
+					setter(obj, value, this);
+				}
+				catch (FieldAccessException x)
+				{
+					throw new java.lang.IllegalAccessException().initCause(x);
+				}
+			}
+
+			protected sealed override object JavaBox(long value)
+			{
+				return java.lang.Long.valueOf(value);
+			}
+		}
+
+		private sealed class DoubleField : FieldAccessor
+		{
+			internal DoubleField(FieldWrapper field, bool isFinal)
+				: base(field, isFinal)
+			{
+			}
+
+			public sealed override object get(object obj)
+			{
+				return java.lang.Double.valueOf(getDouble(obj));
+			}
+
+			public sealed override void set(object obj, object val)
+			{
+				if (val is java.lang.Double
+					|| val is java.lang.Float
+					|| val is java.lang.Byte
+					|| val is java.lang.Short
+					|| val is java.lang.Integer
+					|| val is java.lang.Long)
+					setDouble(obj, ((java.lang.Number)val).doubleValue());
+				else if (val is java.lang.Character)
+					setDouble(obj, ((java.lang.Character)val).charValue());
+				else
+					throw SetIllegalArgumentException(val);
+			}
+
+			public sealed override void setByte(object obj, byte b)
+			{
+				setDouble(obj, (sbyte)b);
+			}
+
+			public sealed override void setChar(object obj, char c)
+			{
+				setDouble(obj, c);
+			}
+
+			public sealed override void setShort(object obj, short s)
+			{
+				setDouble(obj, s);
+			}
+
+			public sealed override void setInt(object obj, int i)
+			{
+				setDouble(obj, i);
+			}
+
+			public sealed override void setLong(object obj, long l)
+			{
+				setDouble(obj, l);
+			}
+
+			public sealed override void setFloat(object obj, float f)
+			{
+				setDouble(obj, f);
+			}
+
+			public sealed override double getDouble(object obj)
+			{
+				try
+				{
+					return getter(obj, this);
+				}
+				catch (FieldAccessException x)
+				{
+					throw new java.lang.IllegalAccessException().initCause(x);
+				}
+			}
+
+			public sealed override void setDouble(object obj, double value)
+			{
+				try
+				{
+					setter(obj, value, this);
+				}
+				catch (FieldAccessException x)
+				{
+					throw new java.lang.IllegalAccessException().initCause(x);
+				}
+			}
+
+			protected sealed override object JavaBox(double value)
+			{
+				return java.lang.Double.valueOf(value);
+			}
+		}
+
+		private sealed class ObjectField : FieldAccessor
+		{
+			internal ObjectField(FieldWrapper field, bool isFinal)
+				: base(field, isFinal)
+			{
+			}
+
+			protected sealed override void CheckValue(object value)
+			{
+				if (value != null && !fw.FieldTypeWrapper.EnsureLoadable(fw.DeclaringType.GetClassLoader()).IsInstance(value))
+				{
+					throw SetIllegalArgumentException(value);
+				}
+			}
+
+			public sealed override object get(object obj)
+			{
+				try
+				{
+					return getter(obj, this);
+				}
+				catch (FieldAccessException x)
+				{
+					throw new java.lang.IllegalAccessException().initCause(x);
+				}
+			}
+
+			public sealed override void set(object obj, object value)
+			{
+				try
+				{
+					setter(obj, value, this);
+				}
+				catch (FieldAccessException x)
+				{
+					throw new java.lang.IllegalAccessException().initCause(x);
+				}
+			}
+
+			protected sealed override object JavaBox(object value)
+			{
+				return value;
+			}
+		}
+
+#if !NO_REF_EMIT
+		private Delegate GenerateFastGetter(Type delegateType, Type fieldType, FieldWrapper fw)
+		{
+			TypeWrapper fieldTypeWrapper;
+			try
+			{
+				fieldTypeWrapper = fw.FieldTypeWrapper.EnsureLoadable(fw.DeclaringType.GetClassLoader());
+				fieldTypeWrapper.Finish();
+				fw.DeclaringType.Finish();
+			}
+			catch (RetargetableJavaException x)
+			{
+				throw x.ToJava();
+			}
+			fw.ResolveField();
+			DynamicMethod dm = DynamicMethodUtils.Create("__", fw.DeclaringType.TypeAsBaseType, !fw.IsPublic || !fw.DeclaringType.IsPublic, fieldType, new Type[] { typeof(IReflectionException), typeof(object), typeof(object) });
+			CodeEmitter ilgen = CodeEmitter.Create(dm);
+			if (fw.IsStatic)
+			{
+				fw.EmitGet(ilgen);
+				fieldTypeWrapper.EmitConvSignatureTypeToStackType(ilgen);
+			}
+			else
+			{
+				ilgen.BeginExceptionBlock();
+				ilgen.Emit(OpCodes.Ldarg_1);
+				ilgen.Emit(OpCodes.Castclass, fw.DeclaringType.TypeAsBaseType);
+				fw.EmitGet(ilgen);
+				fieldTypeWrapper.EmitConvSignatureTypeToStackType(ilgen);
+				CodeEmitterLocal local = ilgen.DeclareLocal(fieldType);
+				ilgen.Emit(OpCodes.Stloc, local);
+				CodeEmitterLabel label = ilgen.DefineLabel();
+				ilgen.EmitLeave(label);
+				ilgen.BeginCatchBlock(typeof(InvalidCastException));
+				ilgen.Emit(OpCodes.Ldarg_0);
+				ilgen.Emit(OpCodes.Ldarg_1);
+				ilgen.Emit(OpCodes.Callvirt, typeof(IReflectionException).GetMethod("GetIllegalArgumentException"));
+				ilgen.Emit(OpCodes.Throw);
+				ilgen.EndExceptionBlock();
+				ilgen.MarkLabel(label);
+				ilgen.Emit(OpCodes.Ldloc, local);
+			}
+			ilgen.Emit(OpCodes.Ret);
+			ilgen.DoEmit();
+			return dm.CreateDelegate(delegateType, this);
+		}
+
+		private Delegate GenerateFastSetter(Type delegateType, Type fieldType, FieldWrapper fw)
+		{
+			TypeWrapper fieldTypeWrapper;
+			try
+			{
+				fieldTypeWrapper = fw.FieldTypeWrapper.EnsureLoadable(fw.DeclaringType.GetClassLoader());
+				fieldTypeWrapper.Finish();
+				fw.DeclaringType.Finish();
+			}
+			catch (RetargetableJavaException x)
+			{
+				throw x.ToJava();
+			}
+			fw.ResolveField();
+			DynamicMethod dm = DynamicMethodUtils.Create("__", fw.DeclaringType.TypeAsBaseType, !fw.IsPublic || !fw.DeclaringType.IsPublic, null, new Type[] { typeof(IReflectionException), typeof(object), fieldType, typeof(object) });
+			CodeEmitter ilgen = CodeEmitter.Create(dm);
+			if (fw.IsStatic)
+			{
+				if (fieldType == typeof(object))
+				{
+					ilgen.BeginExceptionBlock();
+					ilgen.Emit(OpCodes.Ldarg_2);
+					fieldTypeWrapper.EmitCheckcast(ilgen);
+					fieldTypeWrapper.EmitConvStackTypeToSignatureType(ilgen, null);
+					fw.EmitSet(ilgen);
+					CodeEmitterLabel label = ilgen.DefineLabel();
+					ilgen.EmitLeave(label);
+					ilgen.BeginCatchBlock(typeof(InvalidCastException));
+					ilgen.Emit(OpCodes.Ldarg_0);
+					ilgen.Emit(OpCodes.Ldarg_1);
+					ilgen.Emit(OpCodes.Callvirt, typeof(IReflectionException).GetMethod("SetIllegalArgumentException"));
+					ilgen.Emit(OpCodes.Throw);
+					ilgen.EndExceptionBlock();
+					ilgen.MarkLabel(label);
+				}
+				else
+				{
+					ilgen.Emit(OpCodes.Ldarg_2);
+					fw.EmitSet(ilgen);
+				}
+			}
+			else
+			{
+				ilgen.BeginExceptionBlock();
+				ilgen.Emit(OpCodes.Ldarg_1);
+				ilgen.Emit(OpCodes.Castclass, fw.DeclaringType.TypeAsBaseType);
+				ilgen.Emit(OpCodes.Ldarg_2);
+				if (fieldType == typeof(object))
+				{
+					fieldTypeWrapper.EmitCheckcast(ilgen);
+				}
+				fieldTypeWrapper.EmitConvStackTypeToSignatureType(ilgen, null);
+				fw.EmitSet(ilgen);
+				CodeEmitterLabel label = ilgen.DefineLabel();
+				ilgen.EmitLeave(label);
+				ilgen.BeginCatchBlock(typeof(InvalidCastException));
+				ilgen.Emit(OpCodes.Ldarg_0);
+				ilgen.Emit(OpCodes.Ldarg_1);
+				ilgen.Emit(OpCodes.Callvirt, typeof(IReflectionException).GetMethod("SetIllegalArgumentException"));
+				ilgen.Emit(OpCodes.Throw);
+				ilgen.EndExceptionBlock();
+				ilgen.MarkLabel(label);
+			}
+			ilgen.Emit(OpCodes.Ret);
+			ilgen.DoEmit();
+			return dm.CreateDelegate(delegateType, this);
+		}
+#endif // !NO_REF_EMIT
+
+		internal static FieldAccessorImplBase Create(FieldWrapper field, bool isFinal)
+		{
+			TypeWrapper type = field.FieldTypeWrapper;
+			if (type.IsPrimitive)
+			{
+				if (type == PrimitiveTypeWrapper.BYTE)
+				{
+					return new ByteField(field, isFinal);
+				}
+				if (type == PrimitiveTypeWrapper.BOOLEAN)
+				{
+					return new BooleanField(field, isFinal);
+				}
+				if (type == PrimitiveTypeWrapper.CHAR)
+				{
+					return new CharField(field, isFinal);
+				}
+				if (type == PrimitiveTypeWrapper.SHORT)
+				{
+					return new ShortField(field, isFinal);
+				}
+				if (type == PrimitiveTypeWrapper.INT)
+				{
+					return new IntField(field, isFinal);
+				}
+				if (type == PrimitiveTypeWrapper.FLOAT)
+				{
+					return new FloatField(field, isFinal);
+				}
+				if (type == PrimitiveTypeWrapper.LONG)
+				{
+					return new LongField(field, isFinal);
+				}
+				if (type == PrimitiveTypeWrapper.DOUBLE)
+				{
+					return new DoubleField(field, isFinal);
+				}
+				throw new InvalidOperationException("field type: " + type);
+			}
+			else
+			{
+				return new ObjectField(field, isFinal);
+			}
+		}
+	}
+#endif
+
+	public static sun.reflect.FieldAccessor newFieldAccessor(object thisFactory, java.lang.reflect.Field field, bool overrideAccessCheck)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		// we look at the modifiers of the Field object to allow Unsafe to give us a fake Field take doesn't have the final flag set
+		int modifiers = field.getModifiers();
+		bool isStatic = java.lang.reflect.Modifier.isStatic(modifiers);
+		bool isFinal = java.lang.reflect.Modifier.isFinal(modifiers);
+		return FieldAccessorImplBase.Create(FieldWrapper.FromField(field), isFinal && (!overrideAccessCheck || isStatic));
+#endif
+	}
+
+#if !FIRST_PASS
+	internal static sun.reflect.FieldAccessor NewFieldAccessorJNI(FieldWrapper field)
+	{
+		return FieldAccessorImplBase.Create(field, false);
+	}
+#endif
+
+	public static sun.reflect.MethodAccessor newMethodAccessor(object thisFactory, java.lang.reflect.Method method)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		MethodWrapper mw = MethodWrapper.FromExecutable(method);
+#if !NO_REF_EMIT
+		if (!mw.IsDynamicOnly)
+		{
+			return new FastMethodAccessorImpl(mw);
+		}
+#endif
+		return new MethodAccessorImpl(mw);
+#endif
+	}
+
+	public static sun.reflect.ConstructorAccessor newConstructorAccessor0(object thisFactory, java.lang.reflect.Constructor constructor)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		MethodWrapper mw = MethodWrapper.FromExecutable(constructor);
+		if (ActivatorConstructorAccessor.IsSuitable(mw))
+		{
+			// we special case public default constructors, because in that case using Activator.CreateInstance()
+			// is almost as fast as FastConstructorAccessorImpl, but it saves us significantly in working set and
+			// startup time (because often during startup a sun.nio.cs.* encoder is instantiated using reflection)
+			return new ActivatorConstructorAccessor(mw);
+		}
+		else
+		{
+#if NO_REF_EMIT
+			return new ConstructorAccessorImpl(mw);
+#else
+			return new FastConstructorAccessorImpl(constructor);
+#endif
+		}
+#endif
+	}
+
+	public static sun.reflect.ConstructorAccessor newConstructorAccessorForSerialization(java.lang.Class classToInstantiate, java.lang.reflect.Constructor constructorToCall)
+	{
+#if FIRST_PASS
+		return null;
+#else
+		try
+		{
+#if NO_REF_EMIT
+			return new SerializationConstructorAccessorImpl(constructorToCall, classToInstantiate);
+#else
+			return new FastSerializationConstructorAccessorImpl(constructorToCall, classToInstantiate);
+#endif
+		}
+		catch (SecurityException x)
+		{
+			throw new java.lang.SecurityException(x.Message, ikvm.runtime.Util.mapException(x));
+		}
+#endif
+	}
+}
+
+static class Java_sun_reflect_ConstantPool
+{
+	public static int getSize0(object thisConstantPool, object constantPoolOop)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static object getClassAt0(object thisConstantPool, object constantPoolOop, int index)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static object getClassAtIfLoaded0(object thisConstantPool, object constantPoolOop, int index)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static object getMethodAt0(object thisConstantPool, object constantPoolOop, int index)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static object getMethodAtIfLoaded0(object thisConstantPool, object constantPoolOop, int index)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static object getFieldAt0(object thisConstantPool, object constantPoolOop, int index)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static object getFieldAtIfLoaded0(object thisConstantPool, object constantPoolOop, int index)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static string[] getMemberRefInfoAt0(object thisConstantPool, object constantPoolOop, int index)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static int getIntAt0(object thisConstantPool, object constantPoolOop, int index)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static long getLongAt0(object thisConstantPool, object constantPoolOop, int index)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static float getFloatAt0(object thisConstantPool, object constantPoolOop, int index)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static double getDoubleAt0(object thisConstantPool, object constantPoolOop, int index)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static string getStringAt0(object thisConstantPool, object constantPoolOop, int index)
+	{
+		throw new NotImplementedException();
+	}
+
+	public static string getUTF8At0(object thisConstantPool, object constantPoolOop, int index)
+	{
+		throw new NotImplementedException();
+	}
+}
diff --git a/runtime/openjdk/sun.security.krb5.cs b/runtime/openjdk/sun.security.krb5.cs
new file mode 100644
index 0000000..5189e75
--- /dev/null
+++ b/runtime/openjdk/sun.security.krb5.cs
@@ -0,0 +1,354 @@
+/*
+  Copyright (C) 2007-2011 Jeroen Frijters
+  Copyright (C) 2011 Trevor Bell (Siemens Energy, Inc.)
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.ComponentModel;
+using System.Runtime.InteropServices;
+using System.Security;
+
+static class Java_sun_security_krb5_Config
+{
+	public static string getWindowsDirectory(bool isSystem)
+	{
+		if (isSystem)
+		{
+			return Environment.SystemDirectory;
+		}
+		return Environment.GetEnvironmentVariable("SystemRoot");
+	}
+}
+
+static class Java_sun_security_krb5_Credentials
+{
+#if !FIRST_PASS
+	private static java.util.Date ToJavaDate(long time)
+	{
+		// convert 100-nanosecond intervals to milliseconds offset milliseconds from Jan 1, 1601 to Jan 1, 1970
+		const long DIFF_IN_MILLIS = 11644473600000L;
+		return new java.util.Date((time / 10000) - DIFF_IN_MILLIS);
+	}
+#endif
+
+	public static object acquireDefaultNativeCreds(int[] eTypes)
+	{
+#if FIRST_PASS
+        return null;
+#else
+		Ticket ticket;
+        try
+        {
+            ticket = Win32KerberosSupport.GetTicket();
+        }
+        catch (Win32Exception)
+        {
+            // there's no way to return more specific error information
+            return null;
+        }
+        // we use reflection to instantiate the Credentials object,
+		// because we don't want a static dependency on IKVM.OpenJDK.Security.dll
+        return java.lang.Class.forName("sun.security.krb5.Credentials")
+            .getConstructor(typeof(byte[]),
+                            typeof(string),
+                            typeof(string),
+                            typeof(byte[]),
+                            typeof(int),
+                            typeof(bool[]),
+                            typeof(java.util.Date),
+                            typeof(java.util.Date),
+                            typeof(java.util.Date),
+                            typeof(java.util.Date),
+                            typeof(java.net.InetAddress[]))
+            .newInstance(ticket.EncodedTicket,
+                            ticket.ClientNames[0],
+                            ticket.TargetNames[0],
+                            ticket.SessionKey,
+                            java.lang.Integer.valueOf(ticket.SessionKeyType),
+                            null,
+                            ToJavaDate(ticket.StartTime),
+                            ToJavaDate(ticket.StartTime),
+                            ToJavaDate(ticket.EndTime),
+                            ToJavaDate(ticket.RenewUntil),
+                            null);
+#endif
+	}
+
+    sealed class Ticket
+    {
+        public byte[] EncodedTicket;
+        public string[] ClientNames;
+        public string[] TargetNames;
+        public byte[] SessionKey;
+        public int SessionKeyType;
+        public long StartTime;
+        public long EndTime;
+        public long RenewUntil;
+    }
+
+	static class Win32KerberosSupport
+	{
+        const int STATUS_SUCCESS = 0;
+
+        [SecurityCritical]
+        sealed class LsaSafeHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid
+        {
+            internal LsaSafeHandle()
+                : base(true)
+            {
+            }
+
+            [SecurityCritical]
+            override protected bool ReleaseHandle()
+            {
+                return LsaDeregisterLogonProcess(handle) == STATUS_SUCCESS;
+            }
+        }
+
+        enum KERB_PROTOCOL_MESSAGE_TYPE
+        {
+            KerbRetrieveTicketMessage = 4
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        struct LsaString
+        {
+            public ushort Length;
+            public ushort MaximumLength;
+            [MarshalAs(UnmanagedType.LPStr)]
+            public string Buffer;
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        struct LUID
+        {
+            public uint LowPart;
+            public int HighPart;
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        struct KERB_QUERY_TKT_CACHE_REQUEST
+        {
+            public KERB_PROTOCOL_MESSAGE_TYPE MessageType;
+            public LUID LoginId;
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        struct UNICODE_STRING
+        {
+            public ushort Length;
+            public ushort MaximumLength;
+            public IntPtr Buffer;
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        struct KERB_CRYPTO_KEY
+        {
+            public int KeyType;
+            public int Length;
+            public IntPtr Value;
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        sealed class KERB_RETRIEVE_TKT_RESPONSE
+        {
+            public KERB_EXTERNAL_TICKET Ticket;
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        struct KERB_EXTERNAL_TICKET
+        {
+            public IntPtr ServiceName;
+            public IntPtr TargetName;
+            public IntPtr ClientName;
+            public UNICODE_STRING DomainName;
+            public UNICODE_STRING TargetDomainName;
+            public UNICODE_STRING AltTargetDomainName;
+            public KERB_CRYPTO_KEY SessionKey;
+            public uint TicketFlags;
+            public uint Flags;
+            public long KeyExpirationTime;
+            public long StartTime;
+            public long EndTime;
+            public long RenewUntil;
+            public long TimeSkew;
+            public int EncodedTicketSize;
+            public IntPtr EncodedTicket;
+        }
+
+        [DllImport("secur32.dll")]
+        static extern int LsaDeregisterLogonProcess(IntPtr handle);
+
+        [DllImport("secur32.dll")]
+        static extern int LsaConnectUntrusted(out LsaSafeHandle LsaHandle);
+
+		[DllImport("secur32.dll")]
+		static extern int LsaCallAuthenticationPackage(
+                LsaSafeHandle LsaHandle,
+				uint AuthenticationPackage,
+				ref KERB_QUERY_TKT_CACHE_REQUEST ProtocolSubmitBuffer,
+				int SubmitBufferLength,
+				out IntPtr ProtocolReturnBuffer,
+				out int ReturnBufferLength,
+				out int ProtocolStatus);
+
+		[DllImport("secur32.dll")]
+		static extern int LsaLookupAuthenticationPackage(
+                LsaSafeHandle LsaHandle,
+				ref LsaString PackageName,
+				out uint AuthenticationPackage);
+
+		[DllImport("advapi32.dll")]
+		static extern int LsaNtStatusToWinError(int status);
+
+        [DllImport("secur32.dll")]
+        static extern int LsaFreeReturnBuffer(IntPtr buffer);
+
+        static void Check(int ntstatus)
+        {
+            if (ntstatus != STATUS_SUCCESS)
+            {
+                throw new Win32Exception(LsaNtStatusToWinError(ntstatus));
+            }
+        }
+
+		[SecuritySafeCritical]
+		internal static Ticket GetTicket()
+		{
+            LsaSafeHandle lsaHandle = null;
+            try
+            {
+                // connect to the LSA outside the TCB
+                Check(LsaConnectUntrusted(out lsaHandle));
+
+                string kerberos = "Kerberos";
+                LsaString lsaString = new LsaString();
+                lsaString.Length = (ushort)kerberos.Length;
+                lsaString.MaximumLength = (ushort)kerberos.Length;
+                lsaString.Buffer = kerberos;
+
+                uint authenticationPackage = 0;
+
+                // lookup the index for the Kerberos authentication package
+                Check(LsaLookupAuthenticationPackage(lsaHandle, ref lsaString, out authenticationPackage));
+
+                KERB_QUERY_TKT_CACHE_REQUEST request = new KERB_QUERY_TKT_CACHE_REQUEST();
+                request.MessageType = KERB_PROTOCOL_MESSAGE_TYPE.KerbRetrieveTicketMessage;
+                request.LoginId.LowPart = 0;
+                request.LoginId.HighPart = 0;
+
+                int submitBufferLength = Marshal.SizeOf(typeof(KERB_QUERY_TKT_CACHE_REQUEST));
+                IntPtr responsePointer = IntPtr.Zero;
+                int returnBufferLength = 0;
+                int protocolStatus = 0;
+
+                try
+                {
+                    // send the request to Kerberos and get a response
+                    Check(LsaCallAuthenticationPackage(lsaHandle,
+                            authenticationPackage,
+                            ref request,
+                            submitBufferLength,
+                            out responsePointer,
+                            out returnBufferLength,
+                            out protocolStatus));
+
+                    Check(protocolStatus);
+
+                    if (responsePointer == IntPtr.Zero || returnBufferLength < Marshal.SizeOf(typeof(KERB_RETRIEVE_TKT_RESPONSE)))
+                    {
+                        throw new InvalidOperationException();
+                    }
+
+                    KERB_RETRIEVE_TKT_RESPONSE response = new KERB_RETRIEVE_TKT_RESPONSE();
+                    Marshal.PtrToStructure(responsePointer, response);
+
+                    Ticket ticket = new Ticket();
+                    ticket.EncodedTicket = ReadBytes(response.Ticket.EncodedTicket, response.Ticket.EncodedTicketSize);
+                    ticket.ClientNames = ReadExternalName(response.Ticket.ClientName);
+                    ticket.TargetNames = ReadExternalName(response.Ticket.TargetName);
+                    ticket.SessionKey = ReadBytes(response.Ticket.SessionKey.Value, response.Ticket.SessionKey.Length);
+                    ticket.SessionKeyType = response.Ticket.SessionKey.KeyType;
+                    ticket.StartTime = response.Ticket.StartTime;
+                    ticket.EndTime = response.Ticket.EndTime;
+                    ticket.RenewUntil = response.Ticket.RenewUntil;
+                    return ticket;
+                }
+                finally
+                {
+                    if (responsePointer != IntPtr.Zero)
+                    {
+                        Check(LsaFreeReturnBuffer(responsePointer));
+                    }
+                }
+            }
+            finally
+            {
+                if (lsaHandle != null)
+                {
+                    lsaHandle.Close();
+                }
+            }
+		}
+
+        [SecurityCritical]
+        private static string[] ReadExternalName(IntPtr ptr)
+        {
+            int nameCount = (ushort)Marshal.ReadInt16(ptr, 2);
+            ptr = (IntPtr)((long)ptr + 4 + IntPtr.Size - 4);
+            string[] names = new string[nameCount];
+            for (int i = 0; i < nameCount; i++)
+            {
+                names[i] = ReadUnicodeString(ref ptr);
+            }
+            return names;
+        }
+
+        [SecurityCritical]
+        private static string ReadUnicodeString(ref IntPtr ptr)
+        {
+            UNICODE_STRING str = (UNICODE_STRING)Marshal.PtrToStructure(ptr, typeof(UNICODE_STRING));
+            ptr = (IntPtr)((long)ptr + Marshal.SizeOf(typeof(UNICODE_STRING)));
+            return Marshal.PtrToStringUni(str.Buffer, str.Length / 2);
+        }
+
+        [SecurityCritical]
+        private static byte[] ReadBytes(IntPtr ptr, int length)
+        {
+            byte[] buf = new byte[length];
+            Marshal.Copy(ptr, buf, 0, length);
+            return buf;
+        }
+    }
+}
+
+static class Java_sun_security_krb5_SCDynamicStoreConfig
+{
+	public static void installNotificationCallback()
+	{
+	}
+
+	public static object getKerberosConfig()
+	{
+		return null;
+	}
+}
diff --git a/runtime/openjdk/sun.util.locale.provider.cs b/runtime/openjdk/sun.util.locale.provider.cs
new file mode 100644
index 0000000..6c8763b
--- /dev/null
+++ b/runtime/openjdk/sun.util.locale.provider.cs
@@ -0,0 +1,554 @@
+/*
+  Copyright (C) 2014 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Globalization;
+
+static class Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl
+{
+	private static string[][] positivePatterns = new string[][] {
+        // NF_NUMBER
+        new string[] { "{0}" },
+        // NF_CURRENCY
+        new string[] { "\xA4{0}", "{0}\xA4", "\xA4 {0}", "{0} \xA4" },
+        // NF_PERCENT
+        new string[] { "{0} %", "{0}%", "%{0}", "% {0}" },
+    };
+
+	private static string[][] negativePatterns = new string[][] {
+        // NF_NUMBER
+        new string[] { "({0})", "-{0}", "- {0}", "{0}-", "{0} -" },
+        // NF_CURRENCY
+        new string[] { "(\xA4{0})", "-\xA4{0}", "\xA4-{0}", "\xA4{0}-", "({0}\xA4)", "-{0}\xA4", "{0}-\xA4", "{0}\xA4-", "-{0} \xA4", "-\xA4 {0}", "{0} \xA4-", "\xA4 {0}-", "\xA4 -{0}", "{0}- \xA4", "(\xA4 {0})", "({0} \xA4)" },
+        // NF_PERCENT
+        new string[] { "-{0} %", "-{0}%", "-%{0}", "%-{0}", "%{0}-", "{0}-%", "{0}%-", "-% {0}", "{0} %-", "% {0}-", "% -{0}", "{0}- %" },
+    };
+
+	public static bool initialize()
+	{
+		return true;
+	}
+
+	public static string getDefaultLocale(int cat)
+	{
+		const int CAT_DISPLAY = 0;
+		const int CAT_FORMAT = 1;
+		switch (cat)
+		{
+			case CAT_DISPLAY:
+				return CultureInfo.CurrentUICulture.IetfLanguageTag;
+			case CAT_FORMAT:
+				return CultureInfo.CurrentCulture.IetfLanguageTag;
+			default:
+				throw new NotSupportedException();
+		}
+	}
+
+	public static string getDateTimePattern(int dateStyle, int timeStyle, string langTag)
+	{
+		CultureInfo ci;
+		if (TryGetCultureInfoFromLangTag(langTag, out ci))
+		{
+			switch (timeStyle)
+			{
+				case 0:
+				case 1:
+					return ci.DateTimeFormat.LongTimePattern;
+				case 2:
+				case 3:
+					// NOTE prior to .NET 4.0 this does not return the user's customized time pattern
+					return ci.DateTimeFormat.ShortTimePattern;
+			}
+
+			switch (dateStyle)
+			{
+				case 0:
+				case 1:
+					return ci.DateTimeFormat.LongDatePattern;
+				case 2:
+				case 3:
+					return ci.DateTimeFormat.ShortDatePattern;
+			}
+		}
+		return "";
+	}
+
+	public static int getCalendarID(string langTag)
+	{
+		CultureInfo ci;
+		if (!TryGetCultureInfoFromLangTag(langTag, out ci))
+		{
+			return 0;
+		}
+		// this mapping is based on the CAL_* constants defined in
+		// http://referencesource.microsoft.com/#mscorlib/system/globalization/calendar.cs#70
+		Calendar cal = ci.Calendar;
+		if (cal is GregorianCalendar)
+		{
+			switch (((GregorianCalendar)cal).CalendarType)
+			{
+				case GregorianCalendarTypes.Localized:
+					return 1;
+				case GregorianCalendarTypes.USEnglish:
+					return 2;
+				case GregorianCalendarTypes.MiddleEastFrench:
+					return 9;
+				case GregorianCalendarTypes.Arabic:
+					return 10;
+				case GregorianCalendarTypes.TransliteratedEnglish:
+					return 11;
+				case GregorianCalendarTypes.TransliteratedFrench:
+					return 12;
+				default:
+					return 0;
+			}
+		}
+		else if (cal is JapaneseCalendar)
+		{
+			return 3;
+		}
+		else if (cal is TaiwanCalendar)
+		{
+			return 4;
+		}
+		else if (cal is KoreanCalendar)
+		{
+			return 5;
+		}
+		else if (cal is HijriCalendar)
+		{
+			return 6;
+		}
+		else if (cal is ThaiBuddhistCalendar)
+		{
+			return 7;
+		}
+		else if (cal is HebrewCalendar)
+		{
+			return 8;
+		}
+		else if (cal is JulianCalendar)
+		{
+			return 13;
+		}
+		else if (cal is JapaneseLunisolarCalendar)
+		{
+			return 14;
+		}
+		else if (cal is ChineseLunisolarCalendar)
+		{
+			return 15;
+		}
+		else if (cal is KoreanLunisolarCalendar)
+		{
+			return 20;
+		}
+		else if (cal is TaiwanLunisolarCalendar)
+		{
+			return 21;
+		}
+		else if (cal is PersianCalendar)
+		{
+			return 22;
+		}
+		else if (cal is UmAlQuraCalendar)
+		{
+			return 23;
+		}
+		else
+		{
+			return 0;
+		}
+	}
+
+	public static string[] getAmPmStrings(string langTag, string[] ampm)
+	{
+		CultureInfo ci;
+		if (TryGetCultureInfoFromLangTag(langTag, out ci))
+		{
+			DateTimeFormatInfo info = ci.DateTimeFormat;
+			ampm[0] = info.AMDesignator;
+			ampm[1] = info.PMDesignator;
+		}
+		return ampm;
+	}
+
+	public static string[] getEras(string langTag, string[] eras)
+	{
+		CultureInfo ci;
+		if (TryGetCultureInfoFromLangTag(langTag, out ci))
+		{
+			eras[1] = ci.DateTimeFormat.GetAbbreviatedEraName(ci.Calendar.GetEra(DateTime.Now));
+		}
+		return eras;
+	}
+
+	public static string[] getMonths(string langTag, string[] months)
+	{
+		CultureInfo ci;
+		if (TryGetCultureInfoFromLangTag(langTag, out ci))
+		{
+			DateTimeFormatInfo dtfi = ci.DateTimeFormat;
+			for (int i = 1; i <= 13; i++)
+			{
+				months[i - 1] = dtfi.GetMonthName(i);
+			}
+		}
+		return months;
+	}
+
+	public static string[] getShortMonths(string langTag, string[] smonths)
+	{
+		CultureInfo ci;
+		if (TryGetCultureInfoFromLangTag(langTag, out ci))
+		{
+			DateTimeFormatInfo dtfi = ci.DateTimeFormat;
+			for (int i = 1; i <= 13; i++)
+			{
+				smonths[i - 1] = dtfi.GetAbbreviatedMonthName(i);
+			}
+		}
+		return smonths;
+	}
+
+	public static string[] getWeekdays(string langTag, string[] wdays)
+	{
+		CultureInfo ci;
+		if (TryGetCultureInfoFromLangTag(langTag, out ci))
+		{
+			DateTimeFormatInfo dtfi = ci.DateTimeFormat;
+			for (int i = 0; i < 7; i++)
+			{
+				wdays[i + 1] = dtfi.GetDayName((DayOfWeek)i);
+			}
+		}
+		return wdays;
+	}
+
+	public static string[] getShortWeekdays(string langTag, string[] swdays)
+	{
+		CultureInfo ci;
+		if (TryGetCultureInfoFromLangTag(langTag, out ci))
+		{
+			DateTimeFormatInfo dtfi = ci.DateTimeFormat;
+			for (int i = 0; i < 7; i++)
+			{
+				swdays[i + 1] = dtfi.GetAbbreviatedDayName((DayOfWeek)i);
+			}
+		}
+		return swdays;
+	}
+
+	public static string getNumberPattern(int numberStyle, string langTag)
+	{
+		CultureInfo ci;
+		if (!TryGetCultureInfoFromLangTag(langTag, out ci))
+		{
+			ci = CultureInfo.InvariantCulture;
+		}
+		NumberFormatInfo nfi= ci.NumberFormat;
+		const int NF_NUMBER = 0;
+		const int NF_CURRENCY = 1;
+		const int NF_PERCENT = 2;
+		const int NF_INTEGER = 3;
+		int digits;
+		int[] groupSizes;
+		int positivePattern;
+		int negativePattern;
+		switch (numberStyle)
+		{
+			case NF_NUMBER:
+				digits = nfi.NumberDecimalDigits;
+				groupSizes = nfi.NumberGroupSizes;
+				positivePattern = 0;
+				negativePattern = nfi.NumberNegativePattern;
+				break;
+			case NF_CURRENCY:
+				digits = nfi.CurrencyDecimalDigits;
+				groupSizes = nfi.CurrencyGroupSizes;
+				positivePattern = nfi.CurrencyPositivePattern;
+				negativePattern = nfi.CurrencyNegativePattern;
+				break;
+			case NF_PERCENT:
+				digits = nfi.PercentDecimalDigits;
+				groupSizes = nfi.PercentGroupSizes;
+				positivePattern = nfi.PercentPositivePattern;
+				negativePattern = nfi.PercentNegativePattern;
+				break;
+			case NF_INTEGER:
+				digits = 0;
+				groupSizes = nfi.NumberGroupSizes;
+				positivePattern = 0;
+				negativePattern = nfi.NumberNegativePattern;
+				break;
+			default:
+				throw new NotSupportedException();
+		}
+		string number = "";
+		foreach (int group in groupSizes)
+		{
+			if (group > 0)
+			{
+				number += "#," + new String('#', group - 1);
+			}
+		}
+		number += "0";
+		if (digits > 0)
+		{
+			number += "." + new String('0', digits);
+		}
+		return String.Format(positivePatterns[numberStyle % 3][positivePattern] + ";" + negativePatterns[numberStyle % 3][negativePattern], number);
+	}
+
+	public static bool isNativeDigit(string langTag)
+	{
+		CultureInfo ci;
+		if (!TryGetCultureInfoFromLangTag(langTag, out ci))
+		{
+			return false;
+		}
+		return ci.NumberFormat.DigitSubstitution == DigitShapes.NativeNational;
+	}
+
+	public static string getCurrencySymbol(string langTag, string currencySymbol)
+	{
+		RegionInfo ri;
+		if (!TryGetRegionInfoFromLangTag(langTag, out ri))
+		{
+			return currencySymbol;
+		}
+		return ri.CurrencySymbol;
+	}
+
+	public static char getDecimalSeparator(string langTag, char decimalSeparator)
+	{
+		CultureInfo ci;
+		if (!TryGetCultureInfoFromLangTag(langTag, out ci))
+		{
+			return decimalSeparator;
+		}
+		return ci.NumberFormat.NumberDecimalSeparator[0];
+	}
+
+	public static char getGroupingSeparator(string langTag, char groupingSeparator)
+	{
+		CultureInfo ci;
+		if (!TryGetCultureInfoFromLangTag(langTag, out ci))
+		{
+			return groupingSeparator;
+		}
+		return ci.NumberFormat.NumberGroupSeparator[0];
+	}
+
+	public static string getInfinity(string langTag, string infinity)
+	{
+		CultureInfo ci;
+		if (!TryGetCultureInfoFromLangTag(langTag, out ci))
+		{
+			return infinity;
+		}
+		return ci.NumberFormat.PositiveInfinitySymbol;
+	}
+
+	public static string getInternationalCurrencySymbol(string langTag, string internationalCurrencySymbol)
+	{
+		RegionInfo ri;
+		if (!TryGetRegionInfoFromLangTag(langTag, out ri))
+		{
+			return internationalCurrencySymbol;
+		}
+		return ri.ISOCurrencySymbol;
+	}
+
+	public static char getMinusSign(string langTag, char minusSign)
+	{
+		CultureInfo ci;
+		if (!TryGetCultureInfoFromLangTag(langTag, out ci))
+		{
+			return minusSign;
+		}
+		return ci.NumberFormat.NegativeSign[0];
+	}
+
+	public static char getMonetaryDecimalSeparator(string langTag, char monetaryDecimalSeparator)
+	{
+		CultureInfo ci;
+		if (!TryGetCultureInfoFromLangTag(langTag, out ci))
+		{
+			return monetaryDecimalSeparator;
+		}
+		return ci.NumberFormat.CurrencyDecimalSeparator[0];
+	}
+
+	public static string getNaN(string langTag, string nan)
+	{
+		CultureInfo ci;
+		if (!TryGetCultureInfoFromLangTag(langTag, out ci))
+		{
+			return nan;
+		}
+		return ci.NumberFormat.NaNSymbol;
+	}
+
+	public static char getPercent(string langTag, char percent)
+	{
+		CultureInfo ci;
+		if (!TryGetCultureInfoFromLangTag(langTag, out ci))
+		{
+			return percent;
+		}
+		return ci.NumberFormat.PercentSymbol[0];
+	}
+
+	public static char getPerMill(string langTag, char perMill)
+	{
+		CultureInfo ci;
+		if (!TryGetCultureInfoFromLangTag(langTag, out ci))
+		{
+			return perMill;
+		}
+		return ci.NumberFormat.PerMilleSymbol[0];
+	}
+
+	public static char getZeroDigit(string langTag, char zeroDigit)
+	{
+		CultureInfo ci;
+		if (!TryGetCultureInfoFromLangTag(langTag, out ci))
+		{
+			return zeroDigit;
+		}
+		return ci.NumberFormat.NativeDigits[0][0];
+	}
+
+	public static int getCalendarDataValue(string langTag, int type)
+	{
+		CultureInfo ci;
+		if (!TryGetCultureInfoFromLangTag(langTag, out ci))
+		{
+			return -1;
+		}
+		const int CD_FIRSTDAYOFWEEK = 0;
+		switch (type)
+		{
+			case CD_FIRSTDAYOFWEEK:
+				return (((int)ci.DateTimeFormat.FirstDayOfWeek) + 6) % 7;
+			default:
+				throw new NotSupportedException();
+		}
+	}
+
+	public static string getDisplayString(string langTag, int key, string value)
+	{
+		const int DN_CURRENCY_NAME = 0;
+		const int DN_CURRENCY_SYMBOL = 1;
+		const int DN_LOCALE_LANGUAGE = 2;
+		const int DN_LOCALE_REGION = 4;
+
+		if (key == DN_LOCALE_LANGUAGE)
+		{
+			CultureInfo ci;
+			if (!TryGetCultureInfoFromLangTag(value, out ci))
+			{
+				return null;
+			}
+			while (ci.Parent != CultureInfo.InvariantCulture)
+			{
+				ci = ci.Parent;
+			}
+			return ci.DisplayName;
+		}
+		else if (key == DN_LOCALE_REGION)
+		{
+			RegionInfo ri;
+			if (!TryGetRegionInfoFromLangTag(value, out ri))
+			{
+				return null;
+			}
+			return ri.DisplayName;
+		}
+		else
+		{
+			RegionInfo ri;
+			if (!TryGetRegionInfoFromLangTag(langTag, out ri))
+			{
+				return null;
+			}
+			switch (key)
+			{
+				case DN_CURRENCY_NAME:
+					return ri.CurrencyNativeName;
+				case DN_CURRENCY_SYMBOL:
+					return ri.CurrencySymbol;
+				default:
+					throw new NotSupportedException();
+			}
+		}
+	}
+
+	private static bool TryGetCultureInfoFromLangTag(string langTag, out CultureInfo ci)
+	{
+		try
+		{
+			// we can't use CultureInfo.GetCultureInfo() here, because we want the UseUserOverride = true behavior
+			ci = new CultureInfo(NormalizeLangTag(langTag));
+			return true;
+		}
+		catch (ArgumentException) // .NET 2.0 throws an ArgumentException and .NET 4.0 throws CultureNotFoundException (a subclass of ArgumentException)
+		{
+			ci = null;
+			return false;
+		}
+	}
+
+	private static bool TryGetRegionInfoFromLangTag(string langTag, out RegionInfo ri)
+	{
+		try
+		{
+			ri = new RegionInfo(NormalizeLangTag(langTag));
+			return true;
+		}
+		catch (ArgumentException) // .NET 2.0 throws an ArgumentException and .NET 4.0 throws CultureNotFoundException (a subclass of ArgumentException)
+		{
+			ri = null;
+			return false;
+		}
+	}
+
+	private static string NormalizeLangTag(string langTag)
+	{
+		if (langTag == "und")
+		{
+			langTag = "en-US";
+		}
+		return langTag;
+	}
+}
+
+static class JRELocaleProviderAdapter
+{
+	// the Java implementation is redirected via map.xml
+	internal static bool isNonENLangSupported()
+	{
+		return IKVM.Internal.ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedNameFast("sun.text.resources.nl.FormatData_nl") != null;
+	}
+}
diff --git a/runtime/profiler.cs b/runtime/profiler.cs
new file mode 100644
index 0000000..45cdfd0
--- /dev/null
+++ b/runtime/profiler.cs
@@ -0,0 +1,121 @@
+/*
+  Copyright (C) 2002 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+sealed class Profiler
+{
+	private static Profiler instance = new Profiler();
+	private static Dictionary counters = new Dictionary();
+	[ThreadStatic]
+	private static Stack stack;
+
+	private sealed class Entry
+	{
+		internal long Time;
+		internal long Count;
+	}
+
+	~Profiler()
+	{
+		// get rid off the warning that "instance" is unused
+		instance.Equals(null);
+		Console.Error.WriteLine("{0,-40}{1,10}{2,12}", "Event", "Count", "Time (ms)");
+		Console.Error.WriteLine("{0,-40}{1,10}{2,12}", "-----", "-----", "---------");
+		long totalTime = 0;
+		foreach(KeyValuePair e in counters)
+		{
+			Entry entry = e.Value;
+			if(entry.Time == 0)
+			{
+				Console.Error.WriteLine("{0,-40}{1,10}", e.Key, entry.Count);
+			}
+			else
+			{
+				totalTime += entry.Time / 10000;
+				Console.Error.WriteLine("{0,-40}{1,10}{2,12}", e.Key, entry.Count, entry.Time / 10000);
+			}
+		}
+		Console.Error.WriteLine("{0,-40}{1,10}{2,12}", "", "", "---------");
+		Console.Error.WriteLine("{0,-40}{1,10}{2,12}", "", "", totalTime);
+	}
+
+	[Conditional("PROFILE")]
+	internal static void Enter(string name)
+	{
+		long ticks = DateTime.Now.Ticks;
+		lock(counters)
+		{
+			if(stack == null)
+			{
+				stack = new Stack();
+			}
+			if(stack.Count > 0)
+			{
+				stack.Peek().Time += ticks;
+			}
+			Entry e;
+			if(!counters.TryGetValue(name, out e))
+			{
+				e = new Entry();
+				counters[name] = e;
+			}
+			e.Count++;
+			e.Time -= ticks;
+			stack.Push(e);
+		}
+	}
+
+	[Conditional("PROFILE")]
+	internal static void Leave(string name)
+	{
+		long ticks = DateTime.Now.Ticks;
+		stack.Pop();
+		lock(counters)
+		{
+			Entry e = counters[name];
+			e.Time += ticks;
+			if(stack.Count > 0)
+			{
+				((Entry)stack.Peek()).Time -= ticks;
+			}
+		}
+	}
+
+	[Conditional("PROFILE")]
+	internal static void Count(string name)
+	{
+		lock(counters)
+		{
+			Entry e;
+			if(!counters.TryGetValue(name, out e))
+			{
+				e = new Entry();
+				counters[name] = e;
+			}
+			e.Count++;
+		}
+	}
+}
diff --git a/runtime/runtime.build b/runtime/runtime.build
new file mode 100644
index 0000000..19efa74
--- /dev/null
+++ b/runtime/runtime.build
@@ -0,0 +1,227 @@
+
+
+
+    
+
+    
+        
+        
+        
+    
+
+    
+        
+        
+        
+        
+            
+        
+    
+
+    
+        
+        
+        
+    
+
+    
+        
+        
+    
+
+    
+        
+        
+            
+        
+        
+            
+                
+                
+            
+        
+    
+
+    
+        
+        
+            
+                
+                    
+                
+            
+        
+    
+
+    
+        
+        
+            
+                
+                    
+                
+            
+        
+    
+
+    
+        
+        
+            
+        
+        
+            
+        
+        
+            
+        
+        
+            
+        
+    
+
+    
+        
+            
+            
+                
+                
+                
+            
+            
+                
+                
+                
+                
+            
+        
+                
+    
+
+    
+        
+            
+            
+                
+            
+        
+        
+            
+            
+                
+                
+            
+            
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+            
+            
+                
+            
+            
+                
+                
+                
+                
+                
+                
+                
+                
+                
+            
+        
+        
+    
+
diff --git a/runtime/stubgen/ClassFileWriter.cs b/runtime/stubgen/ClassFileWriter.cs
new file mode 100644
index 0000000..9438a5f
--- /dev/null
+++ b/runtime/stubgen/ClassFileWriter.cs
@@ -0,0 +1,1104 @@
+/*
+  Copyright (C) 2002-2013 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.IO;
+using System.Collections.Generic;
+using IKVM.Attributes;
+
+namespace IKVM.StubGen
+{
+	sealed class BigEndianStream
+	{
+		private Stream stream;
+
+		public BigEndianStream(Stream stream)
+		{
+			this.stream = stream;
+		}
+
+		public void WriteUInt16(ushort s)
+		{
+			stream.WriteByte((byte)(s >> 8));
+			stream.WriteByte((byte)s);
+		}
+
+		public void WriteUInt32(uint u)
+		{
+			stream.WriteByte((byte)(u >> 24));
+			stream.WriteByte((byte)(u >> 16));
+			stream.WriteByte((byte)(u >> 8));
+			stream.WriteByte((byte)u);
+		}
+
+		public void WriteInt64(long l)
+		{
+			WriteUInt32((uint)(l >> 32));
+			WriteUInt32((uint)l);
+		}
+
+		public void WriteFloat(float f)
+		{
+			WriteUInt32(BitConverter.ToUInt32(BitConverter.GetBytes(f), 0));
+		}
+
+		public void WriteDouble(double d)
+		{
+			WriteInt64(BitConverter.ToInt64(BitConverter.GetBytes(d), 0));
+		}
+
+		public void WriteByte(byte b)
+		{
+			stream.WriteByte(b);
+		}
+
+		public void WriteBytes(byte[] data)
+		{
+			stream.Write(data, 0, data.Length);
+		}
+
+		public void WriteUtf8(string str)
+		{
+			byte[] buf = new byte[str.Length * 3 + 1];
+			int j = 0;
+			for (int i = 0, e = str.Length; i < e; i++)
+			{
+				char ch = str[i];
+				if ((ch != 0) && (ch <= 0x7f))
+				{
+					buf[j++] = (byte)ch;
+				}
+				else if (ch <= 0x7FF)
+				{
+					/* 11 bits or less. */
+					byte high_five = (byte)(ch >> 6);
+					byte low_six = (byte)(ch & 0x3F);
+					buf[j++] = (byte)(high_five | 0xC0); /* 110xxxxx */
+					buf[j++] = (byte)(low_six | 0x80);   /* 10xxxxxx */
+				}
+				else
+				{
+					/* possibly full 16 bits. */
+					byte high_four = (byte)(ch >> 12);
+					byte mid_six = (byte)((ch >> 6) & 0x3F);
+					byte low_six = (byte)(ch & 0x3f);
+					buf[j++] = (byte)(high_four | 0xE0); /* 1110xxxx */
+					buf[j++] = (byte)(mid_six | 0x80);   /* 10xxxxxx */
+					buf[j++] = (byte)(low_six | 0x80);   /* 10xxxxxx*/
+				}
+			}
+			WriteUInt16((ushort)j);
+			stream.Write(buf, 0, j);
+		}
+	}
+
+	enum Constant
+	{
+		Utf8 = 1,
+		Integer = 3,
+		Float = 4,
+		Long = 5,
+		Double = 6,
+		Class = 7,
+		String = 8,
+		Fieldref = 9,
+		Methodref = 10,
+		InterfaceMethodref = 11,
+		NameAndType = 12
+	}
+
+	abstract class ConstantPoolItem
+	{
+		public abstract void Write(BigEndianStream bes);
+	}
+
+	sealed class ConstantPoolItemClass : ConstantPoolItem
+	{
+		private ushort name_index;
+
+		public ConstantPoolItemClass(ushort name_index)
+		{
+			this.name_index = name_index;
+		}
+
+		public override int GetHashCode()
+		{
+			return name_index;
+		}
+
+		public override bool Equals(object o)
+		{
+			if (o != null && o.GetType() == typeof(ConstantPoolItemClass))
+			{
+				return ((ConstantPoolItemClass)o).name_index == name_index;
+			}
+			return false;
+		}
+
+		public override void Write(BigEndianStream bes)
+		{
+			bes.WriteByte((byte)Constant.Class);
+			bes.WriteUInt16(name_index);
+		}
+	}
+
+	sealed class ConstantPoolItemMethodref : ConstantPoolItem
+	{
+		private ushort class_index;
+		private ushort name_and_type_index;
+
+		public ConstantPoolItemMethodref(ushort class_index, ushort name_and_type_index)
+		{
+			this.class_index = class_index;
+			this.name_and_type_index = name_and_type_index;
+		}
+
+		public override int GetHashCode()
+		{
+			return class_index | (name_and_type_index << 16);
+		}
+
+		public override bool Equals(object o)
+		{
+			if (o != null && o.GetType() == typeof(ConstantPoolItemMethodref))
+			{
+				ConstantPoolItemMethodref m = (ConstantPoolItemMethodref)o;
+				return m.class_index == class_index && m.name_and_type_index == name_and_type_index;
+			}
+			return false;
+		}
+
+		public override void Write(BigEndianStream bes)
+		{
+			bes.WriteByte((byte)Constant.Methodref);
+			bes.WriteUInt16(class_index);
+			bes.WriteUInt16(name_and_type_index);
+		}
+	}
+
+	sealed class ConstantPoolItemNameAndType : ConstantPoolItem
+	{
+		private ushort name_index;
+		private ushort descriptor_index;
+
+		public ConstantPoolItemNameAndType(ushort name_index, ushort descriptor_index)
+		{
+			this.name_index = name_index;
+			this.descriptor_index = descriptor_index;
+		}
+
+		public override int GetHashCode()
+		{
+			return name_index | (descriptor_index << 16);
+		}
+
+		public override bool Equals(object o)
+		{
+			if (o != null && o.GetType() == typeof(ConstantPoolItemNameAndType))
+			{
+				ConstantPoolItemNameAndType n = (ConstantPoolItemNameAndType)o;
+				return n.name_index == name_index && n.descriptor_index == descriptor_index;
+			}
+			return false;
+		}
+
+		public override void Write(BigEndianStream bes)
+		{
+			bes.WriteByte((byte)Constant.NameAndType);
+			bes.WriteUInt16(name_index);
+			bes.WriteUInt16(descriptor_index);
+		}
+	}
+
+	sealed class ConstantPoolItemUtf8 : ConstantPoolItem
+	{
+		private string str;
+
+		public ConstantPoolItemUtf8(string str)
+		{
+			this.str = str;
+		}
+
+		public override int GetHashCode()
+		{
+			return str.GetHashCode();
+		}
+
+		public override bool Equals(object o)
+		{
+			if (o != null && o.GetType() == typeof(ConstantPoolItemUtf8))
+			{
+				return ((ConstantPoolItemUtf8)o).str == str;
+			}
+			return false;
+		}
+
+		public override void Write(BigEndianStream bes)
+		{
+			bes.WriteByte((byte)Constant.Utf8);
+			bes.WriteUtf8(str);
+		}
+	}
+
+	sealed class ConstantPoolItemInt : ConstantPoolItem
+	{
+		private int v;
+
+		public ConstantPoolItemInt(int v)
+		{
+			this.v = v;
+		}
+
+		public override int GetHashCode()
+		{
+			return v;
+		}
+
+		public override bool Equals(object o)
+		{
+			if (o != null && o.GetType() == typeof(ConstantPoolItemInt))
+			{
+				return ((ConstantPoolItemInt)o).v == v;
+			}
+			return false;
+		}
+
+		public override void Write(BigEndianStream bes)
+		{
+			bes.WriteByte((byte)Constant.Integer);
+			bes.WriteUInt32((uint)v);
+		}
+	}
+
+	sealed class ConstantPoolItemLong : ConstantPoolItem
+	{
+		private long v;
+
+		public ConstantPoolItemLong(long v)
+		{
+			this.v = v;
+		}
+
+		public override int GetHashCode()
+		{
+			return (int)v;
+		}
+
+		public override bool Equals(object o)
+		{
+			if (o != null && o.GetType() == typeof(ConstantPoolItemLong))
+			{
+				return ((ConstantPoolItemLong)o).v == v;
+			}
+			return false;
+		}
+
+		public override void Write(BigEndianStream bes)
+		{
+			bes.WriteByte((byte)Constant.Long);
+			bes.WriteInt64(v);
+		}
+	}
+
+	sealed class ConstantPoolItemFloat : ConstantPoolItem
+	{
+		private float v;
+
+		public ConstantPoolItemFloat(float v)
+		{
+			this.v = v;
+		}
+
+		public override int GetHashCode()
+		{
+			return BitConverter.ToInt32(BitConverter.GetBytes(v), 0);
+		}
+
+		public override bool Equals(object o)
+		{
+			if (o != null && o.GetType() == typeof(ConstantPoolItemFloat))
+			{
+				return ((ConstantPoolItemFloat)o).v == v;
+			}
+			return false;
+		}
+
+		public override void Write(BigEndianStream bes)
+		{
+			bes.WriteByte((byte)Constant.Float);
+			bes.WriteFloat(v);
+		}
+	}
+
+	sealed class ConstantPoolItemDouble : ConstantPoolItem
+	{
+		private double v;
+
+		public ConstantPoolItemDouble(double v)
+		{
+			this.v = v;
+		}
+
+		public override int GetHashCode()
+		{
+			long l = BitConverter.DoubleToInt64Bits(v);
+			return ((int)l) ^ ((int)(l >> 32));
+		}
+
+		public override bool Equals(object o)
+		{
+			if (o != null && o.GetType() == typeof(ConstantPoolItemDouble))
+			{
+				return ((ConstantPoolItemDouble)o).v == v;
+			}
+			return false;
+		}
+
+		public override void Write(BigEndianStream bes)
+		{
+			bes.WriteByte((byte)Constant.Double);
+			bes.WriteDouble(v);
+		}
+	}
+
+	sealed class ConstantPoolItemString : ConstantPoolItem
+	{
+		private ushort string_index;
+
+		public ConstantPoolItemString(ushort string_index)
+		{
+			this.string_index = string_index;
+		}
+
+		public override int GetHashCode()
+		{
+			return string_index;
+		}
+
+		public override bool Equals(object o)
+		{
+			if (o != null && o.GetType() == typeof(ConstantPoolItemString))
+			{
+				return ((ConstantPoolItemString)o).string_index == string_index;
+			}
+			return false;
+		}
+
+		public override void Write(BigEndianStream bes)
+		{
+			bes.WriteByte((byte)Constant.String);
+			bes.WriteUInt16(string_index);
+		}
+	}
+
+	abstract class ClassFileAttribute
+	{
+		private ushort name_index;
+
+		public ClassFileAttribute(ushort name_index)
+		{
+			this.name_index = name_index;
+		}
+
+		public virtual void Write(BigEndianStream bes)
+		{
+			bes.WriteUInt16(name_index);
+		}
+	}
+
+	sealed class DeprecatedAttribute : ClassFileAttribute
+	{
+		internal DeprecatedAttribute(ClassFileWriter classFile)
+			: base(classFile.AddUtf8("Deprecated"))
+		{
+		}
+
+		public override void Write(BigEndianStream bes)
+		{
+			base.Write(bes);
+			bes.WriteUInt32(0);
+		}
+	}
+
+	sealed class ConstantValueAttribute : ClassFileAttribute
+	{
+		private ushort constant_index;
+
+		public ConstantValueAttribute(ushort name_index, ushort constant_index)
+			: base(name_index)
+		{
+			this.constant_index = constant_index;
+		}
+
+		public override void Write(BigEndianStream bes)
+		{
+			base.Write(bes);
+			bes.WriteUInt32(2);
+			bes.WriteUInt16(constant_index);
+		}
+	}
+
+	sealed class StringAttribute : ClassFileAttribute
+	{
+		private ushort string_index;
+
+		public StringAttribute(ushort name_index, ushort string_index)
+			: base(name_index)
+		{
+			this.string_index = string_index;
+		}
+
+		public override void Write(BigEndianStream bes)
+		{
+			base.Write(bes);
+			bes.WriteUInt32(2);
+			bes.WriteUInt16(string_index);
+		}
+	}
+
+	sealed class InnerClassesAttribute : ClassFileAttribute
+	{
+		private ClassFileWriter classFile;
+		private List classes = new List();
+
+		public InnerClassesAttribute(ClassFileWriter classFile)
+			: base(classFile.AddUtf8("InnerClasses"))
+		{
+			this.classFile = classFile;
+		}
+
+		public override void Write(BigEndianStream bes)
+		{
+			base.Write(bes);
+			bes.WriteUInt32((uint)(2 + 8 * classes.Count));
+			bes.WriteUInt16((ushort)classes.Count);
+			foreach (Item i in classes)
+			{
+				bes.WriteUInt16(i.inner_class_info_index);
+				bes.WriteUInt16(i.outer_class_info_index);
+				bes.WriteUInt16(i.inner_name_index);
+				bes.WriteUInt16(i.inner_class_access_flags);
+			}
+		}
+
+		private class Item
+		{
+			internal ushort inner_class_info_index;
+			internal ushort outer_class_info_index;
+			internal ushort inner_name_index;
+			internal ushort inner_class_access_flags;
+		}
+
+		public void Add(string inner, string outer, string name, ushort access)
+		{
+			Item i = new Item();
+			i.inner_class_info_index = classFile.AddClass(inner);
+			i.outer_class_info_index = classFile.AddClass(outer);
+			if (name != null)
+			{
+				i.inner_name_index = classFile.AddUtf8(name);
+			}
+			i.inner_class_access_flags = access;
+			classes.Add(i);
+		}
+	}
+
+	sealed class ExceptionsAttribute : ClassFileAttribute
+	{
+		private ClassFileWriter classFile;
+		private List classes = new List();
+
+		internal ExceptionsAttribute(ClassFileWriter classFile)
+			: base(classFile.AddUtf8("Exceptions"))
+		{
+			this.classFile = classFile;
+		}
+
+		internal void Add(string exceptionClass)
+		{
+			classes.Add(classFile.AddClass(exceptionClass));
+		}
+
+		public override void Write(BigEndianStream bes)
+		{
+			base.Write(bes);
+			bes.WriteUInt32((uint)(2 + 2 * classes.Count));
+			bes.WriteUInt16((ushort)classes.Count);
+			foreach (ushort idx in classes)
+			{
+				bes.WriteUInt16(idx);
+			}
+		}
+	}
+
+	sealed class RuntimeVisibleAnnotationsAttribute : ClassFileAttribute
+	{
+		private ClassFileWriter classFile;
+		private MemoryStream mem;
+		private BigEndianStream bes;
+		private ushort count;
+
+		internal RuntimeVisibleAnnotationsAttribute(ClassFileWriter classFile)
+			: base(classFile.AddUtf8("RuntimeVisibleAnnotations"))
+		{
+			this.classFile = classFile;
+			mem = new MemoryStream();
+			bes = new BigEndianStream(mem);
+		}
+
+		internal void Add(object[] annot)
+		{
+			count++;
+			bes.WriteUInt16(classFile.AddUtf8((string)annot[1]));
+			bes.WriteUInt16((ushort)((annot.Length - 2) / 2));
+			for (int i = 2; i < annot.Length; i += 2)
+			{
+				bes.WriteUInt16(classFile.AddUtf8((string)annot[i]));
+				WriteElementValue(bes, annot[i + 1]);
+			}
+		}
+
+		private static string DecodeTypeName(string typeName)
+		{
+#if !FIRST_PASS && !STUB_GENERATOR
+			int index = typeName.IndexOf(',');
+			if (index > 0)
+			{
+				// HACK if we have an assembly qualified type name we have to resolve it to a Java class name
+				// (at the very least we should use the right class loader here)
+				try
+				{
+					typeName = "L" + java.lang.Class.forName(typeName.Substring(1, typeName.Length - 2).Replace('/', '.')).getName().Replace('.', '/') + ";";
+				}
+				catch { }
+			}
+#endif
+			return typeName;
+		}
+
+		private void WriteElementValue(BigEndianStream bes, object val)
+		{
+			if (val is object[])
+			{
+				object[] arr = (object[])val;
+				if (AnnotationDefaultAttribute.TAG_ENUM.Equals(arr[0]))
+				{
+					bes.WriteByte(AnnotationDefaultAttribute.TAG_ENUM);
+					bes.WriteUInt16(classFile.AddUtf8(DecodeTypeName((string)arr[1])));
+					bes.WriteUInt16(classFile.AddUtf8((string)arr[2]));
+				}
+				else if (AnnotationDefaultAttribute.TAG_ARRAY.Equals(arr[0]))
+				{
+					bes.WriteByte(AnnotationDefaultAttribute.TAG_ARRAY);
+					bes.WriteUInt16((ushort)(arr.Length - 1));
+					for (int i = 1; i < arr.Length; i++)
+					{
+						WriteElementValue(bes, arr[i]);
+					}
+				}
+				else if (AnnotationDefaultAttribute.TAG_CLASS.Equals(arr[0]))
+				{
+					bes.WriteByte(AnnotationDefaultAttribute.TAG_CLASS);
+					bes.WriteUInt16(classFile.AddUtf8(DecodeTypeName((string)arr[1])));
+				}
+				else if (AnnotationDefaultAttribute.TAG_ANNOTATION.Equals(arr[0]))
+				{
+					bes.WriteByte(AnnotationDefaultAttribute.TAG_ANNOTATION);
+					bes.WriteUInt16(classFile.AddUtf8(DecodeTypeName((string)arr[1])));
+					bes.WriteUInt16((ushort)((arr.Length - 2) / 2));
+					for (int i = 2; i < arr.Length; i += 2)
+					{
+						bes.WriteUInt16(classFile.AddUtf8((string)arr[i]));
+						WriteElementValue(bes, arr[i + 1]);
+					}
+				}
+			}
+			else if (val is bool)
+			{
+				bes.WriteByte((byte)'Z');
+				bes.WriteUInt16(classFile.AddInt((bool)val ? 1 : 0));
+			}
+			else if (val is byte)
+			{
+				bes.WriteByte((byte)'B');
+				bes.WriteUInt16(classFile.AddInt((byte)val));
+			}
+			else if (val is char)
+			{
+				bes.WriteByte((byte)'C');
+				bes.WriteUInt16(classFile.AddInt((char)val));
+			}
+			else if (val is short)
+			{
+				bes.WriteByte((byte)'S');
+				bes.WriteUInt16(classFile.AddInt((short)val));
+			}
+			else if (val is int)
+			{
+				bes.WriteByte((byte)'I');
+				bes.WriteUInt16(classFile.AddInt((int)val));
+			}
+			else if (val is long)
+			{
+				bes.WriteByte((byte)'J');
+				bes.WriteUInt16(classFile.AddLong((long)val));
+			}
+			else if (val is float)
+			{
+				bes.WriteByte((byte)'F');
+				bes.WriteUInt16(classFile.AddFloat((float)val));
+			}
+			else if (val is double)
+			{
+				bes.WriteByte((byte)'D');
+				bes.WriteUInt16(classFile.AddDouble((double)val));
+			}
+			else if (val is string)
+			{
+				bes.WriteByte((byte)'s');
+				bes.WriteUInt16(classFile.AddUtf8((string)val));
+			}
+		}
+
+		public override void Write(BigEndianStream bes)
+		{
+			base.Write(bes);
+			bes.WriteUInt32(Length);
+			WriteImpl(bes);
+		}
+
+		internal void WriteImpl(BigEndianStream bes)
+		{
+			bes.WriteUInt16(count);
+			foreach (byte b in mem.ToArray())
+			{
+				bes.WriteByte(b);
+			}
+		}
+
+		internal uint Length
+		{
+			get { return (uint)mem.Length + 2; }
+		}
+	}
+
+	sealed class RuntimeVisibleParameterAnnotationsAttribute : ClassFileAttribute
+	{
+		private readonly List parameters = new List();
+
+		internal RuntimeVisibleParameterAnnotationsAttribute(ClassFileWriter classFile)
+			: base(classFile.AddUtf8("RuntimeVisibleParameterAnnotations"))
+		{
+		}
+
+		internal void Add(RuntimeVisibleAnnotationsAttribute parameter)
+		{
+			parameters.Add(parameter);
+		}
+
+		public override void Write(BigEndianStream bes)
+		{
+			base.Write(bes);
+			uint length = 1;
+			foreach (RuntimeVisibleAnnotationsAttribute attr in parameters)
+			{
+				length += attr.Length;
+			}
+			bes.WriteUInt32(length);
+			bes.WriteByte((byte)parameters.Count);
+			foreach (RuntimeVisibleAnnotationsAttribute attr in parameters)
+			{
+				attr.WriteImpl(bes);
+			}
+		}
+	}
+
+	sealed class RuntimeVisibleTypeAnnotationsAttribute : ClassFileAttribute
+	{
+		private readonly byte[] data;
+
+		internal RuntimeVisibleTypeAnnotationsAttribute(ClassFileWriter classFile, byte[] data)
+			: base(classFile.AddUtf8("RuntimeVisibleTypeAnnotations"))
+		{
+			this.data = data;
+		}
+
+		public override void Write(BigEndianStream bes)
+		{
+			base.Write(bes);
+			bes.WriteUInt32((uint)data.Length);
+			bes.WriteBytes(data);
+		}
+	}
+
+	sealed class AnnotationDefaultClassFileAttribute : ClassFileAttribute
+	{
+		private ClassFileWriter classFile;
+		private byte[] buf;
+
+		internal AnnotationDefaultClassFileAttribute(ClassFileWriter classFile, byte[] buf)
+			: base(classFile.AddUtf8("AnnotationDefault"))
+		{
+			this.classFile = classFile;
+			this.buf = buf;
+		}
+
+		public override void Write(BigEndianStream bes)
+		{
+			base.Write(bes);
+			bes.WriteUInt32((uint)(buf.Length));
+			foreach (byte b in buf)
+			{
+				bes.WriteByte(b);
+			}
+		}
+	}
+
+	sealed class FieldOrMethod : IAttributeOwner
+	{
+		private Modifiers access_flags;
+		private ushort name_index;
+		private ushort descriptor_index;
+		private List attribs = new List();
+
+		public FieldOrMethod(Modifiers access_flags, ushort name_index, ushort descriptor_index)
+		{
+			this.access_flags = access_flags;
+			this.name_index = name_index;
+			this.descriptor_index = descriptor_index;
+		}
+
+		public void AddAttribute(ClassFileAttribute attrib)
+		{
+			attribs.Add(attrib);
+		}
+
+		public void Write(BigEndianStream bes)
+		{
+			bes.WriteUInt16((ushort)access_flags);
+			bes.WriteUInt16(name_index);
+			bes.WriteUInt16(descriptor_index);
+			bes.WriteUInt16((ushort)attribs.Count);
+			for (int i = 0; i < attribs.Count; i++)
+			{
+				attribs[i].Write(bes);
+			}
+		}
+	}
+
+	sealed class CodeAttribute : ClassFileAttribute
+	{
+		private ClassFileWriter classFile;
+		private ushort max_stack;
+		private ushort max_locals;
+		private byte[] code;
+
+		public CodeAttribute(ClassFileWriter classFile)
+			: base(classFile.AddUtf8("Code"))
+		{
+			this.classFile = classFile;
+		}
+
+		public ushort MaxStack
+		{
+			get { return max_stack; }
+			set { max_stack = value; }
+		}
+
+		public ushort MaxLocals
+		{
+			get { return max_locals; }
+			set { max_locals = value; }
+		}
+
+		public byte[] ByteCode
+		{
+			get { return code; }
+			set { code = value; }
+		}
+
+		public override void Write(BigEndianStream bes)
+		{
+			base.Write(bes);
+			bes.WriteUInt32((uint)(2 + 2 + 4 + code.Length + 2 + 2));
+			bes.WriteUInt16(max_stack);
+			bes.WriteUInt16(max_locals);
+			bes.WriteUInt32((uint)code.Length);
+			for (int i = 0; i < code.Length; i++)
+			{
+				bes.WriteByte(code[i]);
+			}
+			bes.WriteUInt16(0);	// no exceptions
+			bes.WriteUInt16(0); // no attributes
+		}
+	}
+
+	sealed class MethodParametersAttribute : ClassFileAttribute
+	{
+		private readonly ClassFileWriter classFile;
+		private readonly ushort[] names;
+		private readonly ushort[] flags;
+
+		internal MethodParametersAttribute(ClassFileWriter classFile, ushort[] names, ushort[] flags)
+			: base(classFile.AddUtf8("MethodParameters"))
+		{
+			this.classFile = classFile;
+			this.names = names;
+			this.flags = flags;
+		}
+
+		public override void Write(BigEndianStream bes)
+		{
+			base.Write(bes);
+			if (flags == null || names == null || flags.Length != names.Length)
+			{
+				// write a malformed MethodParameters attribute
+				bes.WriteUInt32(0);
+				return;
+			}
+			bes.WriteUInt32((uint)(1 + names.Length * 4));
+			bes.WriteByte((byte)names.Length);
+			for (int i = 0; i < names.Length; i++)
+			{
+				bes.WriteUInt16(names[i]);
+				bes.WriteUInt16(flags[i]);
+			}
+		}
+	}
+
+	interface IAttributeOwner
+	{
+		void AddAttribute(ClassFileAttribute attrib);
+	}
+
+	sealed class ClassFileWriter : IAttributeOwner
+	{
+		private List cplist = new List();
+		private Dictionary cphashtable = new Dictionary();
+		private List fields = new List();
+		private List methods = new List();
+		private List attribs = new List();
+		private List interfaces = new List();
+		private Modifiers access_flags;
+		private ushort this_class;
+		private ushort super_class;
+		private ushort minorVersion;
+		private ushort majorVersion;
+
+		public ClassFileWriter(Modifiers mods, string name, string super, ushort minorVersion, ushort majorVersion)
+		{
+			cplist.Add(null);
+			access_flags = mods;
+			this_class = AddClass(name);
+			if (super != null)
+			{
+				super_class = AddClass(super);
+			}
+			this.minorVersion = minorVersion;
+			this.majorVersion = majorVersion;
+		}
+
+		private ushort Add(ConstantPoolItem cpi)
+		{
+			ushort index;
+			if (!cphashtable.TryGetValue(cpi, out index))
+			{
+				index = (ushort)cplist.Count;
+				cplist.Add(cpi);
+				if (cpi is ConstantPoolItemDouble || cpi is ConstantPoolItemLong)
+				{
+					cplist.Add(null);
+				}
+				cphashtable.Add(cpi, index);
+			}
+			return index;
+		}
+
+		public ushort AddUtf8(string str)
+		{
+			return Add(new ConstantPoolItemUtf8(str));
+		}
+
+		public ushort AddClass(string classname)
+		{
+			return Add(new ConstantPoolItemClass(AddUtf8(classname)));
+		}
+
+		public ushort AddMethodRef(string classname, string methodname, string signature)
+		{
+			return Add(new ConstantPoolItemMethodref(AddClass(classname), AddNameAndType(methodname, signature)));
+		}
+
+		public ushort AddNameAndType(string name, string type)
+		{
+			return Add(new ConstantPoolItemNameAndType(AddUtf8(name), AddUtf8(type)));
+		}
+
+		public ushort AddInt(int i)
+		{
+			return Add(new ConstantPoolItemInt(i));
+		}
+
+		public ushort AddLong(long l)
+		{
+			return Add(new ConstantPoolItemLong(l));
+		}
+
+		public ushort AddFloat(float f)
+		{
+			return Add(new ConstantPoolItemFloat(f));
+		}
+
+		public ushort AddDouble(double d)
+		{
+			return Add(new ConstantPoolItemDouble(d));
+		}
+
+		public ushort AddString(string s)
+		{
+			return Add(new ConstantPoolItemString(AddUtf8(s)));
+		}
+
+		public void AddInterface(string name)
+		{
+			interfaces.Add(AddClass(name));
+		}
+
+		public FieldOrMethod AddMethod(Modifiers access, string name, string signature)
+		{
+			FieldOrMethod method = new FieldOrMethod(access, AddUtf8(name), AddUtf8(signature));
+			methods.Add(method);
+			return method;
+		}
+
+		public FieldOrMethod AddField(Modifiers access, string name, string signature, object constantValue)
+		{
+			FieldOrMethod field = new FieldOrMethod(access, AddUtf8(name), AddUtf8(signature));
+			if (constantValue != null)
+			{
+				ushort constantValueIndex;
+				if (constantValue is byte)
+				{
+					constantValueIndex = AddInt((sbyte)(byte)constantValue);
+				}
+				else if (constantValue is bool)
+				{
+					constantValueIndex = AddInt((bool)constantValue ? 1 : 0);
+				}
+				else if (constantValue is short)
+				{
+					constantValueIndex = AddInt((short)constantValue);
+				}
+				else if (constantValue is char)
+				{
+					constantValueIndex = AddInt((char)constantValue);
+				}
+				else if (constantValue is int)
+				{
+					constantValueIndex = AddInt((int)constantValue);
+				}
+				else if (constantValue is long)
+				{
+					constantValueIndex = AddLong((long)constantValue);
+				}
+				else if (constantValue is float)
+				{
+					constantValueIndex = AddFloat((float)constantValue);
+				}
+				else if (constantValue is double)
+				{
+					constantValueIndex = AddDouble((double)constantValue);
+				}
+				else if (constantValue is string)
+				{
+					constantValueIndex = AddString((string)constantValue);
+				}
+				else
+				{
+					throw new InvalidOperationException(constantValue.GetType().FullName);
+				}
+				field.AddAttribute(new ConstantValueAttribute(AddUtf8("ConstantValue"), constantValueIndex));
+			}
+			fields.Add(field);
+			return field;
+		}
+
+		public ClassFileAttribute MakeStringAttribute(string name, string value)
+		{
+			return new StringAttribute(AddUtf8(name), AddUtf8(value));
+		}
+
+		public void AddStringAttribute(string name, string value)
+		{
+			attribs.Add(MakeStringAttribute(name, value));
+		}
+
+		public void AddAttribute(ClassFileAttribute attrib)
+		{
+			attribs.Add(attrib);
+		}
+
+		public void Write(Stream stream)
+		{
+			BigEndianStream bes = new BigEndianStream(stream);
+			bes.WriteUInt32(0xCAFEBABE);
+			bes.WriteUInt16(minorVersion);
+			bes.WriteUInt16(majorVersion);
+			bes.WriteUInt16((ushort)cplist.Count);
+			foreach (ConstantPoolItem cpi in cplist)
+			{
+				if (cpi != null)
+				{
+					cpi.Write(bes);
+				}
+			}
+			bes.WriteUInt16((ushort)access_flags);
+			bes.WriteUInt16(this_class);
+			bes.WriteUInt16(super_class);
+			// interfaces count
+			bes.WriteUInt16((ushort)interfaces.Count);
+			for (int i = 0; i < interfaces.Count; i++)
+			{
+				bes.WriteUInt16(interfaces[i]);
+			}
+			// fields count
+			bes.WriteUInt16((ushort)fields.Count);
+			for (int i = 0; i < fields.Count; i++)
+			{
+				fields[i].Write(bes);
+			}
+			// methods count
+			bes.WriteUInt16((ushort)methods.Count);
+			for (int i = 0; i < methods.Count; i++)
+			{
+				methods[i].Write(bes);
+			}
+			// attributes count
+			bes.WriteUInt16((ushort)attribs.Count);
+			for (int i = 0; i < attribs.Count; i++)
+			{
+				attribs[i].Write(bes);
+			}
+		}
+	}
+}
diff --git a/runtime/stubgen/SerialVersionUID.cs b/runtime/stubgen/SerialVersionUID.cs
new file mode 100644
index 0000000..e155505
--- /dev/null
+++ b/runtime/stubgen/SerialVersionUID.cs
@@ -0,0 +1,183 @@
+/*
+  Copyright (C) 2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using IKVM.Attributes;
+using IKVM.Internal;
+#if STUB_GENERATOR
+using Type = IKVM.Reflection.Type;
+#endif
+
+namespace IKVM.StubGen
+{
+	static class SerialVersionUID
+	{
+		private readonly static System.Security.Cryptography.SHA1Managed sha1 = new System.Security.Cryptography.SHA1Managed();
+
+		internal static long Compute(TypeWrapper tw)
+		{
+			MemoryStream mem = new MemoryStream();
+			BigEndianStream bes = new BigEndianStream(mem);
+			WriteClassName(bes, tw);
+			WriteModifiers(bes, tw);
+			WriteInterfaces(bes, tw);
+			WriteFields(bes, tw);
+			WriteStaticInitializer(bes, tw);
+			WriteConstructors(bes, tw);
+			WriteMethods(bes, tw);
+			byte[] buf = sha1.ComputeHash(mem.ToArray());
+			long hash = 0;
+			for (int i = 7; i >= 0; i--)
+			{
+				hash <<= 8;
+				hash |= buf[i];
+			}
+			return hash;
+		}
+
+		private static void WriteClassName(BigEndianStream bes, TypeWrapper tw)
+		{
+			bes.WriteUtf8(tw.Name);
+		}
+
+		private static void WriteModifiers(BigEndianStream bes, TypeWrapper tw)
+		{
+			Modifiers mods = tw.ReflectiveModifiers & (Modifiers.Public | Modifiers.Final | Modifiers.Interface | Modifiers.Abstract);
+			if ((mods & Modifiers.Interface) != 0)
+			{
+				mods &= ~Modifiers.Abstract;
+				if (HasJavaMethods(tw))
+				{
+					mods |= Modifiers.Abstract;
+				}
+			}
+			bes.WriteUInt32((uint)mods);
+		}
+
+		private static bool HasJavaMethods(TypeWrapper tw)
+		{
+			foreach (MethodWrapper mw in tw.GetMethods())
+			{
+				if (!mw.IsHideFromReflection && !mw.IsClassInitializer)
+				{
+					return true;
+				}
+			}
+			return false;
+		}
+
+		private static void WriteInterfaces(BigEndianStream bes, TypeWrapper tw)
+		{
+			TypeWrapper[] interfaces = (TypeWrapper[])tw.Interfaces.Clone();
+			Array.Sort(interfaces, delegate(TypeWrapper tw1, TypeWrapper tw2) { return String.CompareOrdinal(tw1.Name, tw2.Name); });
+			foreach (TypeWrapper iface in interfaces)
+			{
+				bes.WriteUtf8(iface.Name);
+			}
+		}
+
+		private static void WriteFields(BigEndianStream bes, TypeWrapper tw)
+		{
+			List list = new List();
+			foreach (FieldWrapper fw in tw.GetFields())
+			{
+				if (!fw.IsHideFromReflection)
+				{
+					list.Add(fw);
+				}
+			}
+			list.Sort(delegate(FieldWrapper fw1, FieldWrapper fw2) { return String.CompareOrdinal(fw1.Name, fw2.Name); });
+			foreach (FieldWrapper fw in list)
+			{
+				Modifiers mods = fw.Modifiers & (Modifiers.Public | Modifiers.Private | Modifiers.Protected | Modifiers.Static | Modifiers.Final | Modifiers.Volatile | Modifiers.Transient);
+				if (((mods & Modifiers.Private) == 0) || ((mods & (Modifiers.Static | Modifiers.Transient)) == 0))
+				{
+					bes.WriteUtf8(fw.Name);
+					bes.WriteUInt32((uint)mods);
+					bes.WriteUtf8(fw.Signature.Replace('.', '/'));
+				}
+			}
+		}
+
+		private static void WriteStaticInitializer(BigEndianStream bes, TypeWrapper tw)
+		{
+			Type type = tw.TypeAsTBD;
+			if (!type.IsArray && type.TypeInitializer != null)
+			{
+				if (!AttributeHelper.IsHideFromJava(type.TypeInitializer))
+				{
+					bes.WriteUtf8("");
+					bes.WriteUInt32((uint)Modifiers.Static);
+					bes.WriteUtf8("()V");
+				}
+			}
+		}
+
+		private static void WriteConstructors(BigEndianStream bes, TypeWrapper tw)
+		{
+			List list = new List();
+			foreach (MethodWrapper mw in tw.GetMethods())
+			{
+				if (mw.IsConstructor && !mw.IsHideFromReflection && !mw.IsPrivate)
+				{
+					list.Add(mw);
+				}
+			}
+			list.Sort(delegate(MethodWrapper mw1, MethodWrapper mw2) { return String.CompareOrdinal(mw1.Signature, mw2.Signature); });
+			foreach (MethodWrapper mw in list)
+			{
+				Modifiers mods = mw.Modifiers & (Modifiers.Public | Modifiers.Private | Modifiers.Protected | Modifiers.Static | Modifiers.Final | Modifiers.Synchronized | Modifiers.Native | Modifiers.Abstract | Modifiers.Strictfp);
+				bes.WriteUtf8(mw.Name);
+				bes.WriteUInt32((uint)mods);
+				bes.WriteUtf8(mw.Signature);
+			}
+		}
+
+		private static void WriteMethods(BigEndianStream bes, TypeWrapper tw)
+		{
+			List list = new List();
+			foreach (MethodWrapper mw in tw.GetMethods())
+			{
+				if (!mw.IsConstructor && !mw.IsHideFromReflection && !mw.IsPrivate)
+				{
+					list.Add(mw);
+				}
+			}
+			list.Sort(delegate(MethodWrapper mw1, MethodWrapper mw2) {
+				if (mw1.Name == mw2.Name)
+					return String.CompareOrdinal(mw1.Signature, mw2.Signature);
+				return String.CompareOrdinal(mw1.Name, mw2.Name); 
+			});
+			foreach (MethodWrapper mw in list)
+			{
+				Modifiers mods = mw.Modifiers & (Modifiers.Public | Modifiers.Private | Modifiers.Protected | Modifiers.Static | Modifiers.Final | Modifiers.Synchronized | Modifiers.Native | Modifiers.Abstract | Modifiers.Strictfp);
+				bes.WriteUtf8(mw.Name);
+				bes.WriteUInt32((uint)mods);
+				bes.WriteUtf8(mw.Signature);
+			}
+		}
+	}
+}
diff --git a/runtime/stubgen/StubGenerator.cs b/runtime/stubgen/StubGenerator.cs
new file mode 100644
index 0000000..54ba8c9
--- /dev/null
+++ b/runtime/stubgen/StubGenerator.cs
@@ -0,0 +1,894 @@
+/*
+  Copyright (C) 2002-2013 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.IO;
+using System.Collections.Generic;
+#if STUB_GENERATOR
+using IKVM.Reflection;
+using Type = IKVM.Reflection.Type;
+#else
+using System.Reflection;
+#endif
+using IKVM.Attributes;
+using IKVM.Internal;
+
+namespace IKVM.StubGen
+{
+	static class StubGenerator
+	{
+		internal static void WriteClass(Stream stream, TypeWrapper tw, bool includeNonPublicInterfaces, bool includeNonPublicMembers, bool includeSerialVersionUID, bool includeParameterNames)
+		{
+			string name = tw.Name.Replace('.', '/');
+			string super = null;
+			if (tw.IsInterface)
+			{
+				super = "java/lang/Object";
+			}
+			else if (tw.BaseTypeWrapper != null)
+			{
+				super = tw.BaseTypeWrapper.Name.Replace('.', '/');
+			}
+			ClassFileWriter writer = new ClassFileWriter(tw.Modifiers, name, super, 0, includeParameterNames ? (ushort)52 : (ushort)49);
+			foreach (TypeWrapper iface in tw.Interfaces)
+			{
+				if (iface.IsPublic || includeNonPublicInterfaces)
+				{
+					writer.AddInterface(iface.Name.Replace('.', '/'));
+				}
+			}
+			InnerClassesAttribute innerClassesAttribute = null;
+			if (tw.DeclaringTypeWrapper != null)
+			{
+				TypeWrapper outer = tw.DeclaringTypeWrapper;
+				string innername = name;
+				int idx = name.LastIndexOf('$');
+				if (idx >= 0)
+				{
+					innername = innername.Substring(idx + 1);
+				}
+				innerClassesAttribute = new InnerClassesAttribute(writer);
+				innerClassesAttribute.Add(name, outer.Name.Replace('.', '/'), innername, (ushort)tw.ReflectiveModifiers);
+			}
+			foreach (TypeWrapper inner in tw.InnerClasses)
+			{
+				if (inner.IsPublic)
+				{
+					if (innerClassesAttribute == null)
+					{
+						innerClassesAttribute = new InnerClassesAttribute(writer);
+					}
+					string namePart = inner.Name;
+					namePart = namePart.Substring(namePart.LastIndexOf('$') + 1);
+					innerClassesAttribute.Add(inner.Name.Replace('.', '/'), name, namePart, (ushort)inner.ReflectiveModifiers);
+				}
+			}
+			if (innerClassesAttribute != null)
+			{
+				writer.AddAttribute(innerClassesAttribute);
+			}
+			string genericTypeSignature = tw.GetGenericSignature();
+			if (genericTypeSignature != null)
+			{
+				writer.AddStringAttribute("Signature", genericTypeSignature);
+			}
+			AddAnnotations(writer, writer, tw.TypeAsBaseType);
+			AddTypeAnnotations(writer, writer, tw, tw.GetRawTypeAnnotations());
+			writer.AddStringAttribute("IKVM.NET.Assembly", GetAssemblyName(tw));
+			if (tw.TypeAsBaseType.IsDefined(JVM.Import(typeof(ObsoleteAttribute)), false))
+			{
+				writer.AddAttribute(new DeprecatedAttribute(writer));
+			}
+			foreach (MethodWrapper mw in tw.GetMethods())
+			{
+				if (!mw.IsHideFromReflection && (mw.IsPublic || mw.IsProtected || includeNonPublicMembers))
+				{
+					FieldOrMethod m;
+					// HACK javac has a bug in com.sun.tools.javac.code.Types.isSignaturePolymorphic() where it assumes that
+					// MethodHandle doesn't have any native methods with an empty argument list
+					// (or at least it throws a NPE when it examines the signature of a method without any parameters when it
+					// accesses argtypes.tail.tail)
+					if (mw.Name == "" || (tw == CoreClasses.java.lang.invoke.MethodHandle.Wrapper && (mw.Modifiers & Modifiers.Native) == 0))
+					{
+						m = writer.AddMethod(mw.Modifiers, mw.Name, mw.Signature.Replace('.', '/'));
+						CodeAttribute code = new CodeAttribute(writer);
+						code.MaxLocals = (ushort)(mw.GetParameters().Length * 2 + 1);
+						code.MaxStack = 3;
+						ushort index1 = writer.AddClass("java/lang/UnsatisfiedLinkError");
+						ushort index2 = writer.AddString("ikvmstub generated stubs can only be used on IKVM.NET");
+						ushort index3 = writer.AddMethodRef("java/lang/UnsatisfiedLinkError", "", "(Ljava/lang/String;)V");
+						code.ByteCode = new byte[] {
+						187, (byte)(index1 >> 8), (byte)index1,	// new java/lang/UnsatisfiedLinkError
+						89,										// dup
+						19,	 (byte)(index2 >> 8), (byte)index2,	// ldc_w "..."
+						183, (byte)(index3 >> 8), (byte)index3, // invokespecial java/lang/UnsatisfiedLinkError/init()V
+						191										// athrow
+					};
+						m.AddAttribute(code);
+					}
+					else
+					{
+						Modifiers mods = mw.Modifiers;
+						if ((mods & Modifiers.Abstract) == 0)
+						{
+							mods |= Modifiers.Native;
+						}
+						m = writer.AddMethod(mods, mw.Name, mw.Signature.Replace('.', '/'));
+						if (mw.IsOptionalAttributeAnnotationValue)
+						{
+							m.AddAttribute(new AnnotationDefaultClassFileAttribute(writer, GetAnnotationDefault(writer, mw.ReturnType)));
+						}
+					}
+					MethodBase mb = mw.GetMethod();
+					if (mb != null)
+					{
+						ThrowsAttribute throws = AttributeHelper.GetThrows(mb);
+						if (throws == null)
+						{
+							string[] throwsArray = mw.GetDeclaredExceptions();
+							if (throwsArray != null && throwsArray.Length > 0)
+							{
+								ExceptionsAttribute attrib = new ExceptionsAttribute(writer);
+								foreach (string ex in throwsArray)
+								{
+									attrib.Add(ex.Replace('.', '/'));
+								}
+								m.AddAttribute(attrib);
+							}
+						}
+						else
+						{
+							ExceptionsAttribute attrib = new ExceptionsAttribute(writer);
+							if (throws.classes != null)
+							{
+								foreach (string ex in throws.classes)
+								{
+									attrib.Add(ex.Replace('.', '/'));
+								}
+							}
+							if (throws.types != null)
+							{
+								foreach (Type ex in throws.types)
+								{
+									attrib.Add(ClassLoaderWrapper.GetWrapperFromType(ex).Name.Replace('.', '/'));
+								}
+							}
+							m.AddAttribute(attrib);
+						}
+						if (mb.IsDefined(JVM.Import(typeof(ObsoleteAttribute)), false)
+							// HACK the instancehelper methods are marked as Obsolete (to direct people toward the ikvm.extensions methods instead)
+							// but in the Java world most of them are not deprecated (and to keep the Japi results clean we need to reflect this)
+							&& (!mb.Name.StartsWith("instancehelper_")
+								|| mb.DeclaringType.FullName != "java.lang.String"
+							// the Java deprecated methods actually have two Obsolete attributes
+								|| GetObsoleteCount(mb) == 2))
+						{
+							m.AddAttribute(new DeprecatedAttribute(writer));
+						}
+						CustomAttributeData attr = GetAnnotationDefault(mb);
+						if (attr != null)
+						{
+							m.AddAttribute(new AnnotationDefaultClassFileAttribute(writer, GetAnnotationDefault(writer, attr.ConstructorArguments[0])));
+						}
+						if (includeParameterNames)
+						{
+							MethodParametersEntry[] mp = tw.GetMethodParameters(mw);
+							if (mp == MethodParametersEntry.Malformed)
+							{
+								m.AddAttribute(new MethodParametersAttribute(writer, null, null));
+							}
+							else if (mp != null)
+							{
+								ushort[] names = new ushort[mp.Length];
+								ushort[] flags = new ushort[mp.Length];
+								for (int i = 0; i < names.Length; i++)
+								{
+									if (mp[i].name != null)
+									{
+										names[i] = writer.AddUtf8(mp[i].name);
+									}
+									flags[i] = mp[i].flags;
+								}
+								m.AddAttribute(new MethodParametersAttribute(writer, names, flags));
+							}
+						}
+					}
+					string sig = tw.GetGenericMethodSignature(mw);
+					if (sig != null)
+					{
+						m.AddAttribute(writer.MakeStringAttribute("Signature", sig));
+					}
+					AddAnnotations(writer, m, mw.GetMethod());
+					AddParameterAnnotations(writer, m, mw.GetMethod());
+					AddTypeAnnotations(writer, m, tw, tw.GetMethodRawTypeAnnotations(mw));
+				}
+			}
+			bool hasSerialVersionUID = false;
+			foreach (FieldWrapper fw in tw.GetFields())
+			{
+				if (!fw.IsHideFromReflection)
+				{
+					bool isSerialVersionUID = includeSerialVersionUID && fw.IsSerialVersionUID;
+					hasSerialVersionUID |= isSerialVersionUID;
+					if (fw.IsPublic || fw.IsProtected || isSerialVersionUID || includeNonPublicMembers)
+					{
+						object constant = null;
+						if (fw.GetField() != null && fw.GetField().IsLiteral && (fw.FieldTypeWrapper.IsPrimitive || fw.FieldTypeWrapper == CoreClasses.java.lang.String.Wrapper))
+						{
+							constant = fw.GetField().GetRawConstantValue();
+							if (fw.GetField().FieldType.IsEnum)
+							{
+								constant = EnumHelper.GetPrimitiveValue(EnumHelper.GetUnderlyingType(fw.GetField().FieldType), constant);
+							}
+						}
+						FieldOrMethod f = writer.AddField(fw.Modifiers, fw.Name, fw.Signature.Replace('.', '/'), constant);
+						string sig = tw.GetGenericFieldSignature(fw);
+						if (sig != null)
+						{
+							f.AddAttribute(writer.MakeStringAttribute("Signature", sig));
+						}
+						if (fw.GetField() != null && fw.GetField().IsDefined(JVM.Import(typeof(ObsoleteAttribute)), false))
+						{
+							f.AddAttribute(new DeprecatedAttribute(writer));
+						}
+						AddAnnotations(writer, f, fw.GetField());
+						AddTypeAnnotations(writer, f, tw, tw.GetFieldRawTypeAnnotations(fw));
+					}
+				}
+			}
+			if (includeSerialVersionUID && !hasSerialVersionUID && IsSerializable(tw))
+			{
+				// class is serializable but doesn't have an explicit serialVersionUID, so we add the field to record
+				// the serialVersionUID as we see it (mainly to make the Japi reports more realistic)
+				writer.AddField(Modifiers.Private | Modifiers.Static | Modifiers.Final, "serialVersionUID", "J", SerialVersionUID.Compute(tw));
+			}
+			AddMetaAnnotations(writer, tw);
+			writer.Write(stream);
+		}
+
+		private static void AddAnnotations(ClassFileWriter writer, IAttributeOwner target, MemberInfo source)
+		{
+#if !FIRST_PASS && !STUB_GENERATOR
+			if (source != null)
+			{
+				RuntimeVisibleAnnotationsAttribute attr = null;
+				foreach (CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(source))
+				{
+					object[] ann = GetAnnotation(cad);
+					if (ann != null)
+					{
+						if (attr == null)
+						{
+							attr = new RuntimeVisibleAnnotationsAttribute(writer);
+						}
+						attr.Add(ann);
+					}
+				}
+				if (attr != null)
+				{
+					target.AddAttribute(attr);
+				}
+			}
+#endif
+		}
+
+		private static void AddParameterAnnotations(ClassFileWriter writer, FieldOrMethod target, MethodBase source)
+		{
+#if !FIRST_PASS && !STUB_GENERATOR
+			if (source != null)
+			{
+				RuntimeVisibleParameterAnnotationsAttribute attr = null;
+				ParameterInfo[] parameters = source.GetParameters();
+				for (int i = 0; i < parameters.Length; i++)
+				{
+					RuntimeVisibleAnnotationsAttribute param = null;
+					foreach (CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(parameters[i]))
+					{
+						object[] ann = GetAnnotation(cad);
+						if (ann != null)
+						{
+							if (param == null)
+							{
+								if (attr == null)
+								{
+									attr = new RuntimeVisibleParameterAnnotationsAttribute(writer);
+									for (int j = 0; j < i; j++)
+									{
+										attr.Add(new RuntimeVisibleAnnotationsAttribute(writer));
+									}
+								}
+								param = new RuntimeVisibleAnnotationsAttribute(writer);
+							}
+							param.Add(ann);
+						}
+					}
+					if (attr != null)
+					{
+						attr.Add(param ?? new RuntimeVisibleAnnotationsAttribute(writer));
+					}
+				}
+				if (attr != null)
+				{
+					target.AddAttribute(attr);
+				}
+			}
+#endif
+		}
+
+		private static void AddTypeAnnotations(ClassFileWriter writer, IAttributeOwner target, TypeWrapper tw, byte[] typeAnnotations)
+		{
+#if !FIRST_PASS && !STUB_GENERATOR
+			if (typeAnnotations != null)
+			{
+				typeAnnotations = (byte[])typeAnnotations.Clone();
+				object[] constantPool = tw.GetConstantPool();
+				try
+				{
+					int pos = 0;
+					ushort num_annotations = ReadUInt16BE(typeAnnotations, ref pos);
+					for (int i = 0; i < num_annotations; i++)
+					{
+						FixupTypeAnnotationConstantPoolIndexes(writer, typeAnnotations, constantPool, ref pos);
+					}
+				}
+				catch (IndexOutOfRangeException)
+				{
+					// if the attribute is malformed, we add it anyway and hope the Java parser will agree and throw the right error
+				}
+				target.AddAttribute(new RuntimeVisibleTypeAnnotationsAttribute(writer, typeAnnotations));
+			}
+#endif
+		}
+
+		private static void FixupTypeAnnotationConstantPoolIndexes(ClassFileWriter writer, byte[] typeAnnotations, object[] constantPool, ref int pos)
+		{
+			switch (typeAnnotations[pos++])		// target_type
+			{
+				case 0x00:
+				case 0x01:
+				case 0x16:
+					pos++;
+					break;
+				case 0x10:
+				case 0x11:
+				case 0x12:
+				case 0x17:
+					pos += 2;
+					break;
+				case 0x13:
+				case 0x14:
+				case 0x15:
+					break;
+				default:
+					throw new IndexOutOfRangeException();
+			}
+			byte path_length = typeAnnotations[pos++];
+			pos += path_length * 2;
+			FixupAnnotationConstantPoolIndexes(writer, typeAnnotations, constantPool, ref pos);
+		}
+
+		private static void FixupAnnotationConstantPoolIndexes(ClassFileWriter writer, byte[] typeAnnotations, object[] constantPool, ref int pos)
+		{
+			FixupConstantPoolIndex(writer, typeAnnotations, constantPool, ref pos);
+			ushort num_components = ReadUInt16BE(typeAnnotations, ref pos);
+			for (int i = 0; i < num_components; i++)
+			{
+				FixupConstantPoolIndex(writer, typeAnnotations, constantPool, ref pos);
+				FixupAnnotationComponentValueConstantPoolIndexes(writer, typeAnnotations, constantPool, ref pos);
+			}
+		}
+
+		private static void FixupConstantPoolIndex(ClassFileWriter writer, byte[] typeAnnotations, object[] constantPool, ref int pos)
+		{
+			ushort index = ReadUInt16BE(typeAnnotations, ref pos);
+			object item = constantPool[index];
+			if (item is int)
+			{
+				index = writer.AddInt((int)item);
+			}
+			else if (item is long)
+			{
+				index = writer.AddLong((long)item);
+			}
+			else if (item is float)
+			{
+				index = writer.AddFloat((float)item);
+			}
+			else if (item is double)
+			{
+				index = writer.AddDouble((double)item);
+			}
+			else if (item is string)
+			{
+				index = writer.AddUtf8((string)item);
+			}
+			else
+			{
+				throw new IndexOutOfRangeException();
+			}
+			typeAnnotations[pos - 2] = (byte)(index >> 8);
+			typeAnnotations[pos - 1] = (byte)(index >> 0);
+		}
+
+		private static void FixupAnnotationComponentValueConstantPoolIndexes(ClassFileWriter writer, byte[] typeAnnotations, object[] constantPool, ref int pos)
+		{
+			switch ((char)typeAnnotations[pos++])	// tag
+			{
+				case 'B':
+				case 'C':
+				case 'D':
+				case 'F':
+				case 'I':
+				case 'J':
+				case 'S':
+				case 'Z':
+				case 's':
+				case 'c':
+					FixupConstantPoolIndex(writer, typeAnnotations, constantPool, ref pos);
+					break;
+				case 'e':
+					FixupConstantPoolIndex(writer, typeAnnotations, constantPool, ref pos);
+					FixupConstantPoolIndex(writer, typeAnnotations, constantPool, ref pos);
+					break;
+				case '@':
+					FixupAnnotationConstantPoolIndexes(writer, typeAnnotations, constantPool, ref pos);
+					break;
+				case '[':
+					ushort num_values = ReadUInt16BE(typeAnnotations, ref pos);
+					for (int i = 0; i < num_values; i++)
+					{
+						FixupAnnotationComponentValueConstantPoolIndexes(writer, typeAnnotations, constantPool, ref pos);
+					}
+					break;
+				default:
+					throw new IndexOutOfRangeException();
+			}
+		}
+
+		private static ushort ReadUInt16BE(byte[] buf, ref int pos)
+		{
+			ushort s = (ushort)((buf[pos] << 8) + buf[pos + 1]);
+			pos += 2;
+			return s;
+		}
+
+#if !FIRST_PASS && !STUB_GENERATOR
+		private static object[] GetAnnotation(CustomAttributeData cad)
+		{
+			if (cad.ConstructorArguments.Count == 1 && cad.ConstructorArguments[0].ArgumentType == typeof(object[]) &&
+				(cad.Constructor.DeclaringType.BaseType == typeof(ikvm.@internal.AnnotationAttributeBase)
+				|| cad.Constructor.DeclaringType == typeof(DynamicAnnotationAttribute)))
+			{
+				return UnpackArray((IList)cad.ConstructorArguments[0].Value);
+			}
+			else if (cad.Constructor.DeclaringType.BaseType == typeof(ikvm.@internal.AnnotationAttributeBase))
+			{
+				string annotationType = GetAnnotationInterface(cad);
+				if (annotationType != null)
+				{
+					// this is a custom attribute annotation applied in a non-Java module
+					List list = new List();
+					list.Add(AnnotationDefaultAttribute.TAG_ANNOTATION);
+					list.Add("L" + annotationType.Replace('.', '/') + ";");
+					ParameterInfo[] parameters = cad.Constructor.GetParameters();
+					for (int i = 0; i < parameters.Length; i++)
+					{
+						list.Add(parameters[i].Name);
+						list.Add(EncodeAnnotationValue(cad.ConstructorArguments[i]));
+					}
+					foreach (CustomAttributeNamedArgument arg in cad.NamedArguments)
+					{
+						list.Add(arg.MemberInfo.Name);
+						list.Add(EncodeAnnotationValue(arg.TypedValue));
+					}
+					return list.ToArray();
+				}
+			}
+			return null;
+		}
+
+		private static string GetAnnotationInterface(CustomAttributeData cad)
+		{
+			object[] attr = cad.Constructor.DeclaringType.GetCustomAttributes(typeof(IKVM.Attributes.ImplementsAttribute), false);
+			if (attr.Length == 1)
+			{
+				string[] interfaces = ((IKVM.Attributes.ImplementsAttribute)attr[0]).Interfaces;
+				if (interfaces.Length == 1)
+				{
+					return interfaces[0];
+				}
+			}
+			return null;
+		}
+
+		private static object EncodeAnnotationValue(CustomAttributeTypedArgument arg)
+		{
+			if (arg.ArgumentType.IsEnum)
+			{
+				// if GetWrapperFromType returns null, we've got an ikvmc synthesized .NET enum nested inside a Java enum
+				TypeWrapper tw = ClassLoaderWrapper.GetWrapperFromType(arg.ArgumentType) ?? ClassLoaderWrapper.GetWrapperFromType(arg.ArgumentType.DeclaringType);
+				return new object[] { AnnotationDefaultAttribute.TAG_ENUM, EncodeTypeName(tw), Enum.GetName(arg.ArgumentType, arg.Value) };
+			}
+			else if (arg.Value is Type)
+			{
+				return new object[] { AnnotationDefaultAttribute.TAG_CLASS, EncodeTypeName(ClassLoaderWrapper.GetWrapperFromType((Type)arg.Value)) };
+			}
+			else if (arg.ArgumentType.IsArray)
+			{
+				IList array = (IList)arg.Value;
+				object[] arr = new object[array.Count + 1];
+				arr[0] = AnnotationDefaultAttribute.TAG_ARRAY;
+				for (int i = 0; i < array.Count; i++)
+				{
+					arr[i + 1] = EncodeAnnotationValue(array[i]);
+				}
+				return arr;
+			}
+			else
+			{
+				return arg.Value;
+			}
+		}
+
+		private static string EncodeTypeName(TypeWrapper tw)
+		{
+			return tw.SigName.Replace('.', '/');
+		}
+#endif
+
+		private static object[] UnpackArray(IList list)
+		{
+			object[] arr = new object[list.Count];
+			for (int i = 0; i < arr.Length; i++)
+			{
+				if (list[i].Value is IList)
+				{
+					arr[i] = UnpackArray((IList)list[i].Value);
+				}
+				else
+				{
+					arr[i] = list[i].Value;
+				}
+			}
+			return arr;
+		}
+
+		private static int GetObsoleteCount(MethodBase mb)
+		{
+#if STUB_GENERATOR
+			return mb.__GetCustomAttributes(JVM.Import(typeof(ObsoleteAttribute)), false).Count;
+#else
+			return mb.GetCustomAttributes(typeof(ObsoleteAttribute), false).Length;
+#endif
+		}
+
+		private static CustomAttributeData GetAnnotationDefault(MethodBase mb)
+		{
+#if STUB_GENERATOR
+			IList attr = CustomAttributeData.__GetCustomAttributes(mb, JVM.LoadType(typeof(AnnotationDefaultAttribute)), false);
+			return attr.Count == 1 ? attr[0] : null;
+#else
+			foreach (CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(mb))
+			{
+				if (cad.Constructor.DeclaringType == typeof(AnnotationDefaultAttribute))
+				{
+					return cad;
+				}
+			}
+			return null;
+#endif
+		}
+
+		private static string GetAssemblyName(TypeWrapper tw)
+		{
+			ClassLoaderWrapper loader = tw.GetClassLoader();
+			AssemblyClassLoader acl = loader as AssemblyClassLoader;
+			if (acl != null)
+			{
+				return acl.GetAssembly(tw).FullName;
+			}
+			else
+			{
+				return ((GenericClassLoaderWrapper)loader).GetName();
+			}
+		}
+
+		private static bool IsSerializable(TypeWrapper tw)
+		{
+			if (tw.Name == "java.io.Serializable")
+			{
+				return true;
+			}
+			while (tw != null)
+			{
+				foreach (TypeWrapper iface in tw.Interfaces)
+				{
+					if (IsSerializable(iface))
+					{
+						return true;
+					}
+				}
+				tw = tw.BaseTypeWrapper;
+			}
+			return false;
+		}
+
+		private static void AddMetaAnnotations(ClassFileWriter writer, TypeWrapper tw)
+		{
+			DotNetTypeWrapper.AttributeAnnotationTypeWrapperBase attributeAnnotation = tw as DotNetTypeWrapper.AttributeAnnotationTypeWrapperBase;
+			if (attributeAnnotation != null)
+			{
+				// TODO write the annotation directly, instead of going thru the object[] encoding
+				RuntimeVisibleAnnotationsAttribute annot = new RuntimeVisibleAnnotationsAttribute(writer);
+				annot.Add(new object[] {
+					AnnotationDefaultAttribute.TAG_ANNOTATION,
+					"Ljava/lang/annotation/Retention;",
+					"value",
+					new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/RetentionPolicy;", "RUNTIME" }
+				});
+				AttributeTargets validOn = attributeAnnotation.AttributeTargets;
+				List targets = new List();
+				targets.Add(AnnotationDefaultAttribute.TAG_ARRAY);
+				if ((validOn & (AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Delegate | AttributeTargets.Assembly)) != 0)
+				{
+					targets.Add(new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/ElementType;", "TYPE" });
+				}
+				if ((validOn & AttributeTargets.Constructor) != 0)
+				{
+					targets.Add(new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/ElementType;", "CONSTRUCTOR" });
+				}
+				if ((validOn & AttributeTargets.Field) != 0)
+				{
+					targets.Add(new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/ElementType;", "FIELD" });
+				}
+				if ((validOn & (AttributeTargets.Method | AttributeTargets.ReturnValue)) != 0)
+				{
+					targets.Add(new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/ElementType;", "METHOD" });
+				}
+				if ((validOn & AttributeTargets.Parameter) != 0)
+				{
+					targets.Add(new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/ElementType;", "PARAMETER" });
+				}
+				annot.Add(new object[] {
+					AnnotationDefaultAttribute.TAG_ANNOTATION,
+					"Ljava/lang/annotation/Target;",
+					"value",
+					targets.ToArray()
+				});
+				if (IsRepeatableAnnotation(tw))
+				{
+					annot.Add(new object[] {
+						AnnotationDefaultAttribute.TAG_ANNOTATION,
+						"Ljava/lang/annotation/Repeatable;",
+						"value",
+						new object[] { AnnotationDefaultAttribute.TAG_CLASS, "L" + (tw.Name + DotNetTypeWrapper.AttributeAnnotationMultipleSuffix).Replace('.', '/') + ";" }
+					});
+				}
+				writer.AddAttribute(annot);
+			}
+		}
+
+		private static bool IsRepeatableAnnotation(TypeWrapper tw)
+		{
+			foreach (TypeWrapper nested in tw.InnerClasses)
+			{
+				if (nested.Name == tw.Name + DotNetTypeWrapper.AttributeAnnotationMultipleSuffix)
+				{
+					return true;
+				}
+			}
+			return false;
+		}
+
+		private static byte[] GetAnnotationDefault(ClassFileWriter classFile, TypeWrapper type)
+		{
+			MemoryStream mem = new MemoryStream();
+			BigEndianStream bes = new BigEndianStream(mem);
+			if (type == PrimitiveTypeWrapper.BOOLEAN)
+			{
+				bes.WriteByte((byte)'Z');
+				bes.WriteUInt16(classFile.AddInt(0));
+			}
+			else if (type == PrimitiveTypeWrapper.BYTE)
+			{
+				bes.WriteByte((byte)'B');
+				bes.WriteUInt16(classFile.AddInt(0));
+			}
+			else if (type == PrimitiveTypeWrapper.CHAR)
+			{
+				bes.WriteByte((byte)'C');
+				bes.WriteUInt16(classFile.AddInt(0));
+			}
+			else if (type == PrimitiveTypeWrapper.SHORT)
+			{
+				bes.WriteByte((byte)'S');
+				bes.WriteUInt16(classFile.AddInt(0));
+			}
+			else if (type == PrimitiveTypeWrapper.INT)
+			{
+				bes.WriteByte((byte)'I');
+				bes.WriteUInt16(classFile.AddInt(0));
+			}
+			else if (type == PrimitiveTypeWrapper.FLOAT)
+			{
+				bes.WriteByte((byte)'F');
+				bes.WriteUInt16(classFile.AddFloat(0));
+			}
+			else if (type == PrimitiveTypeWrapper.LONG)
+			{
+				bes.WriteByte((byte)'J');
+				bes.WriteUInt16(classFile.AddLong(0));
+			}
+			else if (type == PrimitiveTypeWrapper.DOUBLE)
+			{
+				bes.WriteByte((byte)'D');
+				bes.WriteUInt16(classFile.AddDouble(0));
+			}
+			else if (type == CoreClasses.java.lang.String.Wrapper)
+			{
+				bes.WriteByte((byte)'s');
+				bes.WriteUInt16(classFile.AddUtf8(""));
+			}
+			else if ((type.Modifiers & Modifiers.Enum) != 0)
+			{
+				bes.WriteByte((byte)'e');
+				bes.WriteUInt16(classFile.AddUtf8("L" + type.Name.Replace('.', '/') + ";"));
+				bes.WriteUInt16(classFile.AddUtf8("__unspecified"));
+			}
+			else if (type == CoreClasses.java.lang.Class.Wrapper)
+			{
+				bes.WriteByte((byte)'c');
+				bes.WriteUInt16(classFile.AddUtf8("Likvm/internal/__unspecified;"));
+			}
+			else if (type.IsArray)
+			{
+				bes.WriteByte((byte)'[');
+				bes.WriteUInt16(0);
+			}
+			else
+			{
+				throw new InvalidOperationException();
+			}
+			return mem.ToArray();
+		}
+
+		private static byte[] GetAnnotationDefault(ClassFileWriter classFile, CustomAttributeTypedArgument value)
+		{
+			MemoryStream mem = new MemoryStream();
+			BigEndianStream bes = new BigEndianStream(mem);
+			try
+			{
+				WriteAnnotationElementValue(classFile, bes, value);
+			}
+			catch (InvalidCastException)
+			{
+				Warning("Warning: incorrect annotation default value");
+			}
+			catch (IndexOutOfRangeException)
+			{
+				Warning("Warning: incorrect annotation default value");
+			}
+			return mem.ToArray();
+		}
+
+		private static void WriteAnnotationElementValue(ClassFileWriter classFile, BigEndianStream bes, CustomAttributeTypedArgument value)
+		{
+			if (value.ArgumentType == Types.Boolean)
+			{
+				bes.WriteByte((byte)'Z');
+				bes.WriteUInt16(classFile.AddInt((bool)value.Value ? 1 : 0));
+			}
+			else if (value.ArgumentType == Types.Byte)
+			{
+				bes.WriteByte((byte)'B');
+				bes.WriteUInt16(classFile.AddInt((byte)value.Value));
+			}
+			else if (value.ArgumentType == Types.Char)
+			{
+				bes.WriteByte((byte)'C');
+				bes.WriteUInt16(classFile.AddInt((char)value.Value));
+			}
+			else if (value.ArgumentType == Types.Int16)
+			{
+				bes.WriteByte((byte)'S');
+				bes.WriteUInt16(classFile.AddInt((short)value.Value));
+			}
+			else if (value.ArgumentType == Types.Int32)
+			{
+				bes.WriteByte((byte)'I');
+				bes.WriteUInt16(classFile.AddInt((int)value.Value));
+			}
+			else if (value.ArgumentType == Types.Single)
+			{
+				bes.WriteByte((byte)'F');
+				bes.WriteUInt16(classFile.AddFloat((float)value.Value));
+			}
+			else if (value.ArgumentType == Types.Int64)
+			{
+				bes.WriteByte((byte)'J');
+				bes.WriteUInt16(classFile.AddLong((long)value.Value));
+			}
+			else if (value.ArgumentType == Types.Double)
+			{
+				bes.WriteByte((byte)'D');
+				bes.WriteUInt16(classFile.AddDouble((double)value.Value));
+			}
+			else if (value.ArgumentType == Types.String)
+			{
+				bes.WriteByte((byte)'s');
+				bes.WriteUInt16(classFile.AddUtf8((string)value.Value));
+			}
+			else if (value.ArgumentType == Types.Object.MakeArrayType())
+			{
+				CustomAttributeTypedArgument[] array = (CustomAttributeTypedArgument[])value.Value;
+				byte type = (byte)array[0].Value;
+				if (type == AnnotationDefaultAttribute.TAG_ARRAY)
+				{
+					bes.WriteByte((byte)'[');
+					bes.WriteUInt16((ushort)(array.Length - 1));
+					for (int i = 1; i < array.Length; i++)
+					{
+						WriteAnnotationElementValue(classFile, bes, array[i]);
+					}
+				}
+				else if (type == AnnotationDefaultAttribute.TAG_CLASS)
+				{
+					bes.WriteByte((byte)'c');
+					bes.WriteUInt16(classFile.AddUtf8((string)array[1].Value));
+				}
+				else if (type == AnnotationDefaultAttribute.TAG_ENUM)
+				{
+					bes.WriteByte((byte)'e');
+					bes.WriteUInt16(classFile.AddUtf8((string)array[1].Value));
+					bes.WriteUInt16(classFile.AddUtf8((string)array[2].Value));
+				}
+				else if (type == AnnotationDefaultAttribute.TAG_ANNOTATION)
+				{
+					bes.WriteByte((byte)'@');
+					bes.WriteUInt16(classFile.AddUtf8((string)array[1].Value));
+					bes.WriteUInt16((ushort)((array.Length - 2) / 2));
+					for (int i = 2; i < array.Length; i += 2)
+					{
+						bes.WriteUInt16(classFile.AddUtf8((string)array[i].Value));
+						WriteAnnotationElementValue(classFile, bes, array[i + 1]);
+					}
+				}
+				else
+				{
+					Warning("Warning: incorrect annotation default element tag: " + type);
+				}
+			}
+			else
+			{
+				Warning("Warning: incorrect annotation default element type: " + value.ArgumentType);
+			}
+		}
+
+		private static void Warning(string message)
+		{
+#if STUB_GENERATOR
+			Console.Error.WriteLine(message);
+#endif
+		}
+	}
+}
diff --git a/runtime/tracer.cs b/runtime/tracer.cs
new file mode 100644
index 0000000..107cb49
--- /dev/null
+++ b/runtime/tracer.cs
@@ -0,0 +1,222 @@
+/*
+  Copyright (C) 2004, 2005, 2006 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Threading;
+using System.Diagnostics;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+using System.Configuration;
+
+namespace IKVM.Internal
+{
+	public static class Tracer
+	{
+		public readonly static TraceSwitch Compiler = new TraceSwitch("compiler", "Static Compiler");
+		public readonly static TraceSwitch FxBug = new TraceSwitch("fxbug", ".NET Framework bug related events");
+		public readonly static TraceSwitch ClassLoading = new TraceSwitch("classloading", "Class loading");
+		public readonly static TraceSwitch Verifier = new TraceSwitch("verifier", "Bytecode Verifier");
+		public readonly static TraceSwitch Runtime = new TraceSwitch("runtime", "Miscellaneous runtime events");
+		public readonly static TraceSwitch Jni = new TraceSwitch("jni", "JNI");
+		//	public readonly static TraceSwitch Methods = new TraceSwitch("methods", "Method Trace");
+		private readonly static Dictionary allTraceSwitches = new Dictionary();
+
+		private readonly static List methodtraces = new List();
+
+		private sealed class MyTextWriterTraceListener : TextWriterTraceListener
+		{
+			internal MyTextWriterTraceListener(System.IO.TextWriter tw)
+				: base(tw)
+			{
+			}
+
+			public override void Fail(string message)
+			{
+				this.WriteLine("Assert.Fail: " + message);
+				this.WriteLine(new StackTrace(true).ToString());
+				base.Fail(message);
+			}
+
+			public override void Fail(string message, string detailMessage)
+			{
+				this.WriteLine("Assert.Fail: " + message + ".\n" + detailMessage);
+				this.WriteLine(new StackTrace(true).ToString());
+				base.Fail(message, detailMessage);
+			}
+		}
+
+		static Tracer()
+		{
+			try
+			{
+				Init();
+			}
+			catch(System.Security.SecurityException)
+			{
+			}
+		}
+
+		private static void Init()
+		{
+			allTraceSwitches[Compiler.DisplayName] = Compiler;
+			allTraceSwitches[FxBug.DisplayName] = FxBug;
+			allTraceSwitches[ClassLoading.DisplayName] = ClassLoading;
+			allTraceSwitches[Verifier.DisplayName] = Verifier;
+			allTraceSwitches[Runtime.DisplayName] = Runtime;
+			allTraceSwitches[Jni.DisplayName] = Jni;
+
+			try
+			{
+				Trace.AutoFlush = true;
+#if !STUB_GENERATOR
+				/* If the app config file gives some method trace - add it */
+				string trace = ConfigurationManager.AppSettings["Traced Methods"];
+				if(trace != null)
+				{
+					methodtraces.Add(trace);
+				}
+#endif
+			}
+			catch(ConfigurationException)
+			{
+				// app.config is malformed, ignore
+			}
+		}
+
+		[Conditional("DEBUG")]
+		public static void EnableTraceForDebug()
+		{
+			SetTraceLevel("*", TraceLevel.Verbose);
+		}
+
+		public static void EnableTraceConsoleListener()
+		{
+			Trace.Listeners.Add(new MyTextWriterTraceListener(Console.Error));
+		}
+
+		public static void HandleMethodTrace(string name)
+		{
+			methodtraces.Add(name);
+		}
+
+		public static bool IsTracedMethod(string name)
+		{
+			if(methodtraces.Count == 0)
+			{
+				return false;
+			}
+			IEnumerator e = methodtraces.GetEnumerator();
+			while(e.MoveNext())
+			{
+				try 
+				{
+					if(Regex.IsMatch(name, e.Current))
+					{
+						return true;
+					}
+				}
+				catch(Exception x) 
+				{
+					Tracer.Warning(Tracer.Compiler,"Regular Expression match failure: " + e.Current + ":" + x);
+				}
+			}
+			return false;
+		}
+
+		public static void SetTraceLevel(string name)
+		{
+			string[] trace = name.Split('=');
+			System.Diagnostics.TraceLevel level = System.Diagnostics.TraceLevel.Verbose;
+			if(trace.Length == 2)
+			{
+				level = (System.Diagnostics.TraceLevel)Enum.Parse(typeof(System.Diagnostics.TraceLevel), trace[1], true);
+			}
+			SetTraceLevel(trace[0], level);
+		}
+
+		public static void SetTraceLevel(string name, TraceLevel level)
+		{
+			if(name == "*")
+			{
+				foreach(TraceSwitch ts in allTraceSwitches.Values)
+				{
+					ts.Level = level;
+				}
+			}
+			else
+			{
+				TraceSwitch ts;
+				if(allTraceSwitches.TryGetValue(name, out ts))
+				{
+					ts.Level = level;
+				}
+				else
+				{
+					Console.Error.WriteLine("Warning: Invalid traceswitch name: {0}", name);
+				}
+			}
+		}
+
+		private static void WriteLine(string message, object[] p)
+		{
+			if(p.Length > 0)
+			{
+				message = string.Format(message, p);
+			}
+			Trace.WriteLine(string.Format("[{0:HH':'mm':'ss'.'fffff} {1}] {2}", DateTime.Now, Thread.CurrentThread.Name, message));
+		}
+
+		[Conditional("TRACE")]
+		public static void Info(TraceSwitch traceSwitch, string message, params object[] p)
+		{
+			if(traceSwitch.TraceInfo)
+			{
+				WriteLine(message, p);
+			}
+		}
+
+		[Conditional("TRACE")]
+		public static void MethodInfo(string message)
+		{
+			Trace.WriteLine(string.Format("[{0:HH':'mm':'ss'.'fffff} {1}] {2}", DateTime.Now, Thread.CurrentThread.Name, message));
+		}
+
+		[Conditional("TRACE")]
+		public static void Warning(TraceSwitch traceSwitch, string message, params object[] p)
+		{
+			if(traceSwitch.TraceWarning)
+			{
+				WriteLine(message, p);
+			}
+		}
+
+		[Conditional("TRACE")]
+		public static void Error(TraceSwitch traceSwitch, string message, params object[] p)
+		{
+			if(traceSwitch.TraceError)
+			{
+				WriteLine(message, p);
+			}
+		}
+	}
+}
diff --git a/runtime/verifier.cs b/runtime/verifier.cs
new file mode 100644
index 0000000..fdeb809
--- /dev/null
+++ b/runtime/verifier.cs
@@ -0,0 +1,4121 @@
+/*
+  Copyright (C) 2002-2014 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Diagnostics;
+using IKVM.Internal;
+using InstructionFlags = IKVM.Internal.ClassFile.Method.InstructionFlags;
+using ExceptionTableEntry = IKVM.Internal.ClassFile.Method.ExceptionTableEntry;
+
+sealed class InstructionState
+{
+	private struct LocalStoreSites
+	{
+		private int[] data;
+		private int count;
+		private bool shared;
+
+		internal LocalStoreSites Copy()
+		{
+			LocalStoreSites n = new LocalStoreSites();
+			n.data = data;
+			n.count = count;
+			n.shared = true;
+			return n;
+		}
+
+		internal static LocalStoreSites Alloc()
+		{
+			LocalStoreSites n = new LocalStoreSites();
+			n.data = new int[4];
+			return n;
+		}
+
+		internal void Add(int store)
+		{
+			for(int i = 0; i < count; i++)
+			{
+				if(data[i] == store)
+				{
+					return;
+				}
+			}
+			if(count == data.Length)
+			{
+				int[] newarray = new int[data.Length * 2];
+				Buffer.BlockCopy(data, 0, newarray, 0, data.Length * 4);
+				data = newarray;
+				shared = false;
+			}
+			if(shared)
+			{
+				shared = false;
+				data = (int[])data.Clone();
+			}
+			data[count++] = store;
+		}
+
+		internal int this[int index]
+		{
+			get
+			{
+				return data[index];
+			}
+		}
+
+		internal int Count
+		{
+			get
+			{
+				return count;
+			}
+		}
+
+		internal static void MarkShared(LocalStoreSites[] localStoreSites)
+		{
+			for(int i = 0; i < localStoreSites.Length; i++)
+			{
+				localStoreSites[i].shared = true;
+			}
+		}
+	}
+	private TypeWrapper[] stack;
+	private int stackSize;
+	private int stackEnd;
+	private TypeWrapper[] locals;
+	private bool unitializedThis;
+	internal bool changed = true;
+	private enum ShareFlags : byte
+	{
+		None = 0,
+		Stack = 1,
+		Locals = 2,
+		All = Stack | Locals
+	}
+	private ShareFlags flags;
+
+	private InstructionState(TypeWrapper[] stack, int stackSize, int stackEnd, TypeWrapper[] locals, bool unitializedThis)
+	{
+		this.flags = ShareFlags.All;
+		this.stack = stack;
+		this.stackSize = stackSize;
+		this.stackEnd = stackEnd;
+		this.locals = locals;
+		this.unitializedThis = unitializedThis;
+	}
+
+	internal InstructionState(int maxLocals, int maxStack)
+	{
+		this.flags = ShareFlags.None;
+		this.stack = new TypeWrapper[maxStack];
+		this.stackEnd = maxStack;
+		this.locals = new TypeWrapper[maxLocals];
+	}
+
+	internal InstructionState Copy()
+	{
+		return new InstructionState(stack, stackSize, stackEnd, locals, unitializedThis);
+	}
+
+	internal void CopyTo(InstructionState target)
+	{
+		target.flags = ShareFlags.All;
+		target.stack = stack;
+		target.stackSize = stackSize;
+		target.stackEnd = stackEnd;
+		target.locals = locals;
+		target.unitializedThis = unitializedThis;
+		target.changed = true;
+	}
+
+	internal InstructionState CopyLocals()
+	{
+		InstructionState copy = new InstructionState(new TypeWrapper[stack.Length], 0, stack.Length, locals, unitializedThis);
+		copy.flags &= ~ShareFlags.Stack;
+		return copy;
+	}
+
+	public static InstructionState operator+(InstructionState s1, InstructionState s2)
+	{
+		if(s1 == null)
+		{
+			return s2.Copy();
+		}
+		if(s1.stackSize != s2.stackSize || s1.stackEnd != s2.stackEnd)
+		{
+			throw new VerifyError(string.Format("Inconsistent stack height: {0} != {1}",
+				s1.stackSize + s1.stack.Length - s1.stackEnd,
+				s2.stackSize + s2.stack.Length - s2.stackEnd));
+		}
+		InstructionState s = s1.Copy();
+		s.changed = s1.changed;
+		for(int i = 0; i < s.stackSize; i++)
+		{
+			TypeWrapper type = s.stack[i];
+			TypeWrapper type2 = s2.stack[i];
+			if(type == type2)
+			{
+				// perfect match, nothing to do
+			}
+			else if((type == VerifierTypeWrapper.ExtendedDouble && type2 == PrimitiveTypeWrapper.DOUBLE)
+				|| (type2 == VerifierTypeWrapper.ExtendedDouble && type == PrimitiveTypeWrapper.DOUBLE))
+			{
+				if(type != VerifierTypeWrapper.ExtendedDouble)
+				{
+					s.StackCopyOnWrite();
+					s.stack[i] = VerifierTypeWrapper.ExtendedDouble;
+					s.changed = true;
+				}
+			}
+			else if((type == VerifierTypeWrapper.ExtendedFloat && type2 == PrimitiveTypeWrapper.FLOAT)
+				|| (type2 == VerifierTypeWrapper.ExtendedFloat && type == PrimitiveTypeWrapper.FLOAT))
+			{
+				if(type != VerifierTypeWrapper.ExtendedFloat)
+				{
+					s.StackCopyOnWrite();
+					s.stack[i] = VerifierTypeWrapper.ExtendedFloat;
+					s.changed = true;
+				}
+			}
+			else if(!type.IsPrimitive)
+			{
+				TypeWrapper baseType = InstructionState.FindCommonBaseType(type, type2);
+				if(baseType == VerifierTypeWrapper.Invalid)
+				{
+					throw new VerifyError(string.Format("cannot merge {0} and {1}", type.Name, type2.Name));
+				}
+				if(type != baseType)
+				{
+					s.StackCopyOnWrite();
+					s.stack[i] = baseType;
+					s.changed = true;
+				}
+			}
+			else
+			{
+				throw new VerifyError(string.Format("cannot merge {0} and {1}", type.Name, type2.Name));
+			}
+		}
+		for(int i = 0; i < s.locals.Length; i++)
+		{
+			TypeWrapper type = s.locals[i];
+			TypeWrapper type2 = s2.locals[i];
+			TypeWrapper baseType = InstructionState.FindCommonBaseType(type, type2);
+			if(type != baseType)
+			{
+				s.LocalsCopyOnWrite();
+				s.locals[i] = baseType;
+				s.changed = true;
+			}
+		}
+		if(!s.unitializedThis && s2.unitializedThis)
+		{
+			s.unitializedThis = true;
+			s.changed = true;
+		}
+		return s;
+	}
+
+	private static LocalStoreSites MergeStoreSites(LocalStoreSites h1, LocalStoreSites h2)
+	{
+		if(h1.Count == 0)
+		{
+			return h2.Copy();
+		}
+		if(h2.Count == 0)
+		{
+			return h1.Copy();
+		}
+		LocalStoreSites h = h1.Copy();
+		for(int i = 0; i < h2.Count; i++)
+		{
+			h.Add(h2[i]);
+		}
+		return h;
+	}
+
+	internal void SetUnitializedThis(bool state)
+	{
+		unitializedThis = state;
+	}
+
+	internal void CheckUninitializedThis()
+	{
+		if(unitializedThis)
+		{
+			throw new VerifyError("Base class constructor wasn't called");
+		}
+	}
+
+	internal static TypeWrapper FindCommonBaseType(TypeWrapper type1, TypeWrapper type2)
+	{
+		if(type1 == type2)
+		{
+			return type1;
+		}
+		if(type1 == VerifierTypeWrapper.Null)
+		{
+			return type2;
+		}
+		if(type2 == VerifierTypeWrapper.Null)
+		{
+			return type1;
+		}
+		if(type1 == VerifierTypeWrapper.Invalid || type2 == VerifierTypeWrapper.Invalid)
+		{
+			return VerifierTypeWrapper.Invalid;
+		}
+		if(VerifierTypeWrapper.IsFaultBlockException(type1))
+		{
+			VerifierTypeWrapper.ClearFaultBlockException(type1);
+			return FindCommonBaseType(CoreClasses.java.lang.Throwable.Wrapper, type2);
+		}
+		if(VerifierTypeWrapper.IsFaultBlockException(type2))
+		{
+			VerifierTypeWrapper.ClearFaultBlockException(type2);
+			return FindCommonBaseType(type1, CoreClasses.java.lang.Throwable.Wrapper);
+		}
+		if(type1.IsPrimitive || type2.IsPrimitive)
+		{
+			return VerifierTypeWrapper.Invalid;
+		}
+		if(type1 == VerifierTypeWrapper.UninitializedThis || type2 == VerifierTypeWrapper.UninitializedThis)
+		{
+			return VerifierTypeWrapper.Invalid;
+		}
+		if(VerifierTypeWrapper.IsNew(type1) || VerifierTypeWrapper.IsNew(type2))
+		{
+			return VerifierTypeWrapper.Invalid;
+		}
+		if(VerifierTypeWrapper.IsThis(type1))
+		{
+			type1 = ((VerifierTypeWrapper)type1).UnderlyingType;
+		}
+		if(VerifierTypeWrapper.IsThis(type2))
+		{
+			type2 = ((VerifierTypeWrapper)type2).UnderlyingType;
+		}
+		if(type1.IsUnloadable || type2.IsUnloadable)
+		{
+			return VerifierTypeWrapper.Unloadable;
+		}
+		if(type1.ArrayRank > 0 && type2.ArrayRank > 0)
+		{
+			int rank = 1;
+			int rank1 = type1.ArrayRank - 1;
+			int rank2 = type2.ArrayRank - 1;
+			TypeWrapper elem1 = type1.ElementTypeWrapper;
+			TypeWrapper elem2 = type2.ElementTypeWrapper;
+			while(rank1 != 0 && rank2 != 0)
+			{
+				elem1 = elem1.ElementTypeWrapper;
+				elem2 = elem2.ElementTypeWrapper;
+				rank++;
+				rank1--;
+				rank2--;
+			}
+			// NOTE arrays of value types have special merging semantics!
+			// NOTE we don't have to test for the case where the element types are the same, because that
+			// is only relevant if the ranks are the same, but if that is the case the types are completely
+			// identical, in which case the identity test at the top of this method already returned.
+			TypeWrapper baseType;
+			if(elem1.IsPrimitive || elem2.IsPrimitive || elem1.IsNonPrimitiveValueType || elem2.IsNonPrimitiveValueType)
+			{
+				baseType = CoreClasses.java.lang.Object.Wrapper;
+				rank--;
+				if(rank == 0)
+				{
+					return baseType;
+				}
+			}
+			else
+			{
+				baseType = FindCommonBaseTypeHelper(elem1, elem2);
+			}
+			return baseType.MakeArrayType(rank);
+		}
+		return FindCommonBaseTypeHelper(type1, type2);
+	}
+
+	private static TypeWrapper FindCommonBaseTypeHelper(TypeWrapper t1, TypeWrapper t2)
+	{
+		if(t1 == t2)
+		{
+			return t1;
+		}
+		if(t1.IsInterface || t2.IsInterface)
+		{
+			// NOTE according to a paper by Alessandro Coglio & Allen Goldberg titled
+			// "Type Safety in the JVM: Some Problems in Java 2 SDK 1.2 and Proposed Solutions"
+			// the common base of two interfaces is java.lang.Object, and there is special
+			// treatment for java.lang.Object types that allow it to be assigned to any interface
+			// type, the JVM's typesafety then depends on the invokeinterface instruction to make
+			// sure that the reference actually implements the interface.
+			// NOTE the ECMA CLI spec also specifies this interface merging algorithm, so we can't
+			// really do anything more clever than this.
+			return CoreClasses.java.lang.Object.Wrapper;
+		}
+		Stack st1 = new Stack();
+		Stack st2 = new Stack();
+		while(t1 != null)
+		{
+			st1.Push(t1);
+			t1 = t1.BaseTypeWrapper;
+		}
+		while(t2 != null)
+		{
+			st2.Push(t2);
+			t2 = t2.BaseTypeWrapper;
+		}
+		if(HasMissingBaseType(st1) || HasMissingBaseType(st2))
+		{
+			return VerifierTypeWrapper.Unloadable;
+		}
+		TypeWrapper type = CoreClasses.java.lang.Object.Wrapper;
+		for(;;)
+		{
+			t1 = st1.Count > 0 ? st1.Pop() : null;
+			t2 = st2.Count > 0 ? st2.Pop() : null;
+			if(t1 != t2)
+			{
+				return type;
+			}
+			type = t1;
+		}
+	}
+
+	private static bool HasMissingBaseType(Stack st)
+	{
+#if STATIC_COMPILER
+		if (st.Pop().IsUnloadable)
+		{
+			// we have a missing type in base class hierarchy
+			StaticCompiler.IssueMissingTypeMessage(st.Pop().TypeAsBaseType.BaseType);
+			return true;
+		}
+#endif
+		return false;
+	}
+
+	private void SetLocal1(int index, TypeWrapper type)
+	{
+		try
+		{
+			LocalsCopyOnWrite();
+			if(index > 0 && locals[index - 1] != VerifierTypeWrapper.Invalid && locals[index - 1].IsWidePrimitive)
+			{
+				locals[index - 1] = VerifierTypeWrapper.Invalid;
+			}
+			locals[index] = type;
+		}
+		catch(IndexOutOfRangeException)
+		{
+			throw new VerifyError("Illegal local variable number");
+		}
+	}
+
+	private void SetLocal2(int index, TypeWrapper type)
+	{
+		try
+		{
+			LocalsCopyOnWrite();
+			if(index > 0 && locals[index - 1] != VerifierTypeWrapper.Invalid && locals[index - 1].IsWidePrimitive)
+			{
+				locals[index - 1] = VerifierTypeWrapper.Invalid;
+			}
+			locals[index] = type;
+			locals[index + 1] = VerifierTypeWrapper.Invalid;
+		}
+		catch(IndexOutOfRangeException)
+		{
+			throw new VerifyError("Illegal local variable number");
+		}
+	}
+
+	internal void GetLocalInt(int index)
+	{
+		if(GetLocalType(index) != PrimitiveTypeWrapper.INT)
+		{
+			throw new VerifyError("Invalid local type");
+		}
+	}
+
+	internal void SetLocalInt(int index, int instructionIndex)
+	{
+		SetLocal1(index, PrimitiveTypeWrapper.INT);
+	}
+
+	internal void GetLocalLong(int index)
+	{
+		if(GetLocalType(index) != PrimitiveTypeWrapper.LONG)
+		{
+			throw new VerifyError("incorrect local type, not long");
+		}
+	}
+
+	internal void SetLocalLong(int index, int instructionIndex)
+	{
+		SetLocal2(index, PrimitiveTypeWrapper.LONG);
+	}
+
+	internal void GetLocalFloat(int index)
+	{
+		if(GetLocalType(index) != PrimitiveTypeWrapper.FLOAT)
+		{
+			throw new VerifyError("incorrect local type, not float");
+		}
+	}
+
+	internal void SetLocalFloat(int index, int instructionIndex)
+	{
+		SetLocal1(index, PrimitiveTypeWrapper.FLOAT);
+	}
+
+	internal void GetLocalDouble(int index)
+	{
+		if(GetLocalType(index) != PrimitiveTypeWrapper.DOUBLE)
+		{
+			throw new VerifyError("incorrect local type, not double");
+		}
+	}
+
+	internal void SetLocalDouble(int index, int instructionIndex)
+	{
+		SetLocal2(index, PrimitiveTypeWrapper.DOUBLE);
+	}
+
+	internal TypeWrapper GetLocalType(int index)
+	{
+		try
+		{
+			return locals[index];
+		}
+		catch(IndexOutOfRangeException)
+		{
+			throw new VerifyError("Illegal local variable number");
+		}
+	}
+
+	// this is used by the compiler (indirectly, through MethodAnalyzer.GetLocalTypeWrapper),
+	// we've already verified the code so we know we won't run outside the array boundary,
+	// and we don't need to record the fact that we're reading the local.
+	internal TypeWrapper GetLocalTypeEx(int index)
+	{
+		return locals[index];
+	}
+
+	internal void SetLocalType(int index, TypeWrapper type, int instructionIndex)
+	{
+		if(type.IsWidePrimitive)
+		{
+			SetLocal2(index, type);
+		}
+		else
+		{
+			SetLocal1(index, type);
+		}
+	}
+
+	internal void PushType(TypeWrapper type)
+	{
+		if(type.IsIntOnStackPrimitive)
+		{
+			type = PrimitiveTypeWrapper.INT;
+		}
+		PushHelper(type);
+	}
+
+	internal void PushInt()
+	{
+		PushHelper(PrimitiveTypeWrapper.INT);
+	}
+
+	internal void PushLong()
+	{
+		PushHelper(PrimitiveTypeWrapper.LONG);
+	}
+
+	internal void PushFloat()
+	{
+		PushHelper(PrimitiveTypeWrapper.FLOAT);
+	}
+
+	internal void PushExtendedFloat()
+	{
+		PushHelper(VerifierTypeWrapper.ExtendedFloat);
+	}
+
+	internal void PushDouble()
+	{
+		PushHelper(PrimitiveTypeWrapper.DOUBLE);
+	}
+
+	internal void PushExtendedDouble()
+	{
+		PushHelper(VerifierTypeWrapper.ExtendedDouble);
+	}
+
+	internal void PopInt()
+	{
+		PopIntImpl(PopAnyType());
+	}
+
+	internal static void PopIntImpl(TypeWrapper type)
+	{
+		if (type != PrimitiveTypeWrapper.INT)
+		{
+			throw new VerifyError("Int expected on stack");
+		}
+	}
+
+	internal bool PopFloat()
+	{
+		TypeWrapper tw = PopAnyType();
+		PopFloatImpl(tw);
+		return tw == VerifierTypeWrapper.ExtendedFloat;
+	}
+
+	internal static void PopFloatImpl(TypeWrapper tw)
+	{
+		if(tw != PrimitiveTypeWrapper.FLOAT && tw != VerifierTypeWrapper.ExtendedFloat)
+		{
+			throw new VerifyError("Float expected on stack");
+		}
+	}
+
+	internal bool PopDouble()
+	{
+		TypeWrapper tw = PopAnyType();
+		PopDoubleImpl(tw);
+		return tw == VerifierTypeWrapper.ExtendedDouble;
+	}
+
+	internal static void PopDoubleImpl(TypeWrapper tw)
+	{
+		if(tw != PrimitiveTypeWrapper.DOUBLE && tw != VerifierTypeWrapper.ExtendedDouble)
+		{
+			throw new VerifyError("Double expected on stack");
+		}
+	}
+
+	internal void PopLong()
+	{
+		PopLongImpl(PopAnyType());
+	}
+
+	internal static void PopLongImpl(TypeWrapper tw)
+	{
+		if(tw != PrimitiveTypeWrapper.LONG)
+		{
+			throw new VerifyError("Long expected on stack");
+		}
+	}
+
+	internal TypeWrapper PopArrayType()
+	{
+		return PopArrayTypeImpl(PopAnyType());
+	}
+
+	internal static TypeWrapper PopArrayTypeImpl(TypeWrapper type)
+	{
+		if(!VerifierTypeWrapper.IsNullOrUnloadable(type) && type.ArrayRank == 0)
+		{
+			throw new VerifyError("Array reference expected on stack");
+		}
+		return type;
+	}
+
+	// null or an initialized object reference
+	internal TypeWrapper PopObjectType()
+	{
+		return PopObjectTypeImpl(PopType());
+	}
+
+	internal static TypeWrapper PopObjectTypeImpl(TypeWrapper type)
+	{
+		if(type.IsPrimitive || VerifierTypeWrapper.IsNew(type) || type == VerifierTypeWrapper.UninitializedThis)
+		{
+			throw new VerifyError("Expected object reference on stack");
+		}
+		return type;
+	}
+
+	// null or an initialized object reference derived from baseType (or baseType)
+	internal TypeWrapper PopObjectType(TypeWrapper baseType)
+	{
+		return PopObjectTypeImpl(baseType, PopObjectType());
+	}
+
+	internal static TypeWrapper PopObjectTypeImpl(TypeWrapper baseType, TypeWrapper type)
+	{
+		// HACK because of the way interfaces references works, if baseType
+		// is an interface or array of interfaces, any reference will be accepted
+		if(!baseType.IsUnloadable && !baseType.IsInterfaceOrInterfaceArray && !(type.IsUnloadable || type.IsAssignableTo(baseType)))
+		{
+			throw new VerifyError("Unexpected type " + type.Name + " where " + baseType.Name + " was expected");
+		}
+		return type;
+	}
+
+	internal TypeWrapper PeekType()
+	{
+		if(stackSize == 0)
+		{
+			throw new VerifyError("Unable to pop operand off an empty stack");
+		}
+		return stack[stackSize - 1];
+	}
+
+	internal void MultiPopAnyType(int count)
+	{
+		while(count-- != 0)
+		{
+			PopAnyType();
+		}
+	}
+
+	internal TypeWrapper PopFaultBlockException()
+	{
+		return stack[--stackSize];
+	}
+
+	internal TypeWrapper PopAnyType()
+	{
+		if(stackSize == 0)
+		{
+			throw new VerifyError("Unable to pop operand off an empty stack");
+		}
+		TypeWrapper type = stack[--stackSize];
+		if(type.IsWidePrimitive || type == VerifierTypeWrapper.ExtendedDouble)
+		{
+			stackEnd++;
+		}
+		if(VerifierTypeWrapper.IsThis(type))
+		{
+			type = ((VerifierTypeWrapper)type).UnderlyingType;
+		}
+		if(VerifierTypeWrapper.IsFaultBlockException(type))
+		{
+			VerifierTypeWrapper.ClearFaultBlockException(type);
+			type = CoreClasses.java.lang.Throwable.Wrapper;
+		}
+		return type;
+	}
+
+	// NOTE this can *not* be used to pop double or long
+	internal TypeWrapper PopType()
+	{
+		return PopTypeImpl(PopAnyType());
+	}
+
+	internal static TypeWrapper PopTypeImpl(TypeWrapper type)
+	{
+		if(type.IsWidePrimitive || type == VerifierTypeWrapper.ExtendedDouble)
+		{
+			throw new VerifyError("Attempt to split long or double on the stack");
+		}
+		return type;
+	}
+
+	// this will accept null, a primitive type of the specified type or an initialized reference of the
+	// specified type or derived from it
+	// NOTE this can also be used to pop double or long
+	internal TypeWrapper PopType(TypeWrapper baseType)
+	{
+		return PopTypeImpl(baseType, PopAnyType());
+	}
+
+	internal static TypeWrapper PopTypeImpl(TypeWrapper baseType, TypeWrapper type)
+	{
+		if(baseType.IsIntOnStackPrimitive)
+		{
+			baseType = PrimitiveTypeWrapper.INT;
+		}
+		if(VerifierTypeWrapper.IsNew(type) || type == VerifierTypeWrapper.UninitializedThis)
+		{
+			throw new VerifyError("Expecting to find object/array on stack");
+		}
+		if(type == baseType)
+		{
+			return type;
+		}
+		else if(type == VerifierTypeWrapper.ExtendedDouble && baseType == PrimitiveTypeWrapper.DOUBLE)
+		{
+			return type;
+		}
+		else if(type == VerifierTypeWrapper.ExtendedFloat && baseType == PrimitiveTypeWrapper.FLOAT)
+		{
+			return type;
+		}
+		else if(type.IsPrimitive || baseType.IsPrimitive)
+		{
+			// throw at the end of the method
+		}
+		else if(baseType == CoreClasses.java.lang.Object.Wrapper)
+		{
+			return type;
+		}
+		else if(type.IsUnloadable || baseType.IsUnloadable)
+		{
+			return type;
+		}
+		else if (baseType.IsInterfaceOrInterfaceArray)
+		{
+			// because of the way interfaces references works, if baseType
+			// is an interface or array of interfaces, any reference will be accepted
+			return type;
+		}
+		else if (type.IsAssignableTo(baseType))
+		{
+			return type;
+		}
+		else if (HasMissingBaseType(type) || HasMissingBaseType(baseType))
+		{
+			return type;
+		}
+		throw new VerifyError("Unexpected type " + type.Name + " where " + baseType.Name + " was expected");
+	}
+
+	private static bool HasMissingBaseType(TypeWrapper tw)
+	{
+#if STATIC_COMPILER
+		for (TypeWrapper baseTypeWrapper; (baseTypeWrapper = tw.BaseTypeWrapper) != null; tw = baseTypeWrapper)
+		{
+			if (baseTypeWrapper.IsUnloadable)
+			{
+				StaticCompiler.IssueMissingTypeMessage(tw.TypeAsBaseType.BaseType);
+				return true;
+			}
+		}
+#endif
+		return false;
+	}
+
+	internal int GetStackHeight()
+	{
+		return stackSize;
+	}
+
+	internal TypeWrapper GetStackSlot(int pos)
+	{
+		TypeWrapper tw = stack[stackSize - 1 - pos];
+		if(tw == VerifierTypeWrapper.ExtendedDouble)
+		{
+			tw = PrimitiveTypeWrapper.DOUBLE;
+		}
+		else if(tw == VerifierTypeWrapper.ExtendedFloat)
+		{
+			tw = PrimitiveTypeWrapper.FLOAT;
+		}
+		return tw;
+	}
+
+	internal TypeWrapper GetStackSlotEx(int pos)
+	{
+		return stack[stackSize - 1 - pos];
+	}
+
+	internal TypeWrapper GetStackByIndex(int index)
+	{
+		return stack[index];
+	}
+
+	private void PushHelper(TypeWrapper type)
+	{
+		if(type.IsWidePrimitive || type == VerifierTypeWrapper.ExtendedDouble)
+		{
+			stackEnd--;
+		}
+		if(stackSize >= stackEnd)
+		{
+			throw new VerifyError("Stack overflow");
+		}
+		StackCopyOnWrite();
+		stack[stackSize++] = type;
+	}
+
+	internal void MarkInitialized(TypeWrapper type, TypeWrapper initType, int instructionIndex)
+	{
+		System.Diagnostics.Debug.Assert(type != null && initType != null);
+
+		for(int i = 0; i < locals.Length; i++)
+		{
+			if(locals[i] == type)
+			{
+				LocalsCopyOnWrite();
+				locals[i] = initType;
+			}
+		}
+		for(int i = 0; i < stackSize; i++)
+		{
+			if(stack[i] == type)
+			{
+				StackCopyOnWrite();
+				stack[i] = initType;
+			}
+		}
+	}
+
+	private void StackCopyOnWrite()
+	{
+		if((flags & ShareFlags.Stack) != 0)
+		{
+			flags &= ~ShareFlags.Stack;
+			stack = (TypeWrapper[])stack.Clone();
+		}
+	}
+
+	private void LocalsCopyOnWrite()
+	{
+		if((flags & ShareFlags.Locals) != 0)
+		{
+			flags &= ~ShareFlags.Locals;
+			locals = (TypeWrapper[])locals.Clone();
+		}
+	}
+
+	internal void DumpLocals()
+	{
+		Console.Write("// ");
+		string sep = "";
+		for(int i = 0; i < locals.Length; i++)
+		{
+			Console.Write(sep);
+			Console.Write(locals[i]);
+			sep = ", ";
+		}
+		Console.WriteLine();
+	}
+
+	internal void DumpStack()
+	{
+		Console.Write("// ");
+		string sep = "";
+		for(int i = 0; i < stackSize; i++)
+		{
+			Console.Write(sep);
+			Console.Write(stack[i]);
+			sep = ", ";
+		}
+		Console.WriteLine();
+	}
+
+	internal void ClearFaultBlockException()
+	{
+		if(VerifierTypeWrapper.IsFaultBlockException(stack[0]))
+		{
+			StackCopyOnWrite();
+			changed = true;
+			stack[0] = CoreClasses.java.lang.Throwable.Wrapper;
+		}
+	}
+}
+
+struct StackState
+{
+	private InstructionState state;
+	private int sp;
+
+	internal StackState(InstructionState state)
+	{
+		this.state = state;
+		sp = state.GetStackHeight();
+	}
+
+	internal TypeWrapper PeekType()
+	{
+		if(sp == 0)
+		{
+			throw new VerifyError("Unable to pop operand off an empty stack");
+		}
+		TypeWrapper type = state.GetStackByIndex(sp - 1);
+		if(VerifierTypeWrapper.IsThis(type))
+		{
+			type = ((VerifierTypeWrapper)type).UnderlyingType;
+		}
+		return type;
+	}
+
+	internal TypeWrapper PopAnyType()
+	{
+		if(sp == 0)
+		{
+			throw new VerifyError("Unable to pop operand off an empty stack");
+		}
+		TypeWrapper type = state.GetStackByIndex(--sp);
+		if(VerifierTypeWrapper.IsThis(type))
+		{
+			type = ((VerifierTypeWrapper)type).UnderlyingType;
+		}
+		if(VerifierTypeWrapper.IsFaultBlockException(type))
+		{
+			VerifierTypeWrapper.ClearFaultBlockException(type);
+			type = CoreClasses.java.lang.Throwable.Wrapper;
+		}
+		return type;
+	}
+
+	internal TypeWrapper PopType(TypeWrapper baseType)
+	{
+		return InstructionState.PopTypeImpl(baseType, PopAnyType());
+	}
+
+	// NOTE this can *not* be used to pop double or long
+	internal TypeWrapper PopType()
+	{
+		return InstructionState.PopTypeImpl(PopAnyType());
+	}
+
+	internal void PopInt()
+	{
+		InstructionState.PopIntImpl(PopAnyType());
+	}
+
+	internal void PopFloat()
+	{
+		InstructionState.PopFloatImpl(PopAnyType());
+	}
+
+	internal void PopDouble()
+	{
+		InstructionState.PopDoubleImpl(PopAnyType());
+	}
+
+	internal void PopLong()
+	{
+		InstructionState.PopLongImpl(PopAnyType());
+	}
+
+	internal TypeWrapper PopArrayType()
+	{
+		return InstructionState.PopArrayTypeImpl(PopAnyType());
+	}
+
+	// either null or an initialized object reference
+	internal TypeWrapper PopObjectType()
+	{
+		return InstructionState.PopObjectTypeImpl(PopAnyType());
+	}
+
+	// null or an initialized object reference derived from baseType (or baseType)
+	internal TypeWrapper PopObjectType(TypeWrapper baseType)
+	{
+		return InstructionState.PopObjectTypeImpl(baseType, PopObjectType());
+	}
+}
+
+sealed class ExceptionSorter : IComparer
+{
+	public int Compare(ExceptionTableEntry e1, ExceptionTableEntry e2)
+	{
+		if (e1.startIndex < e2.startIndex)
+		{
+			return -1;
+		}
+		if (e1.startIndex == e2.startIndex)
+		{
+			if (e1.endIndex == e2.endIndex)
+			{
+				if (e1.ordinal > e2.ordinal)
+				{
+					return -1;
+				}
+				if (e1.ordinal == e2.ordinal)
+				{
+					return 0;
+				}
+				return 1;
+			}
+			if (e1.endIndex > e2.endIndex)
+			{
+				return -1;
+			}
+		}
+		return 1;
+	}
+}
+
+struct UntangledExceptionTable
+{
+	private readonly ExceptionTableEntry[] exceptions;
+
+	internal UntangledExceptionTable(ExceptionTableEntry[] exceptions)
+	{
+#if DEBUG
+		for (int i = 0; i < exceptions.Length; i++)
+		{
+			for (int j = i + 1; j < exceptions.Length; j++)
+			{
+				// check for partially overlapping try blocks (which is legal for the JVM, but not the CLR)
+				if (exceptions[i].startIndex < exceptions[j].startIndex &&
+					exceptions[j].startIndex < exceptions[i].endIndex &&
+					exceptions[i].endIndex < exceptions[j].endIndex)
+				{
+					throw new InvalidOperationException("Partially overlapping try blocks is broken");
+				}
+				// check that we didn't destroy the ordering, when sorting
+				if (exceptions[i].startIndex <= exceptions[j].startIndex &&
+					exceptions[i].endIndex >= exceptions[j].endIndex &&
+					exceptions[i].ordinal < exceptions[j].ordinal)
+				{
+					throw new InvalidOperationException("Non recursive try blocks is broken");
+				}
+			}
+		}
+#endif
+		this.exceptions = exceptions;
+	}
+
+	internal ExceptionTableEntry this[int index]
+	{
+		get { return exceptions[index]; }
+	}
+
+	internal int Length
+	{
+		get { return exceptions.Length; }
+	}
+
+	internal void SetFinally(int index)
+	{
+		exceptions[index] = new ExceptionTableEntry(exceptions[index].startIndex, exceptions[index].endIndex, exceptions[index].handlerIndex, exceptions[index].catch_type, exceptions[index].ordinal, true);
+	}
+}
+
+struct CodeInfo
+{
+	private readonly InstructionState[] state;
+
+	internal CodeInfo(InstructionState[] state)
+	{
+		this.state = state;
+	}
+
+	internal bool HasState(int index)
+	{
+		return state[index] != null;
+	}
+
+	internal int GetStackHeight(int index)
+	{
+		return state[index].GetStackHeight();
+	}
+
+	internal TypeWrapper GetStackTypeWrapper(int index, int pos)
+	{
+		TypeWrapper type = state[index].GetStackSlot(pos);
+		if (VerifierTypeWrapper.IsThis(type))
+		{
+			type = ((VerifierTypeWrapper)type).UnderlyingType;
+		}
+		return type;
+	}
+
+	internal TypeWrapper GetRawStackTypeWrapper(int index, int pos)
+	{
+		return state[index].GetStackSlot(pos);
+	}
+
+	internal bool IsStackTypeExtendedDouble(int index, int pos)
+	{
+		return state[index].GetStackSlotEx(pos) == VerifierTypeWrapper.ExtendedDouble;
+	}
+
+	internal TypeWrapper GetLocalTypeWrapper(int index, int local)
+	{
+		return state[index].GetLocalTypeEx(local);
+	}
+}
+
+sealed class MethodAnalyzer
+{
+	private readonly static TypeWrapper ByteArrayType;
+	private readonly static TypeWrapper BooleanArrayType;
+	private readonly static TypeWrapper ShortArrayType;
+	private readonly static TypeWrapper CharArrayType;
+	private readonly static TypeWrapper IntArrayType;
+	private readonly static TypeWrapper FloatArrayType;
+	private readonly static TypeWrapper DoubleArrayType;
+	private readonly static TypeWrapper LongArrayType;
+	private readonly static TypeWrapper java_lang_ThreadDeath;
+	private readonly TypeWrapper host;	// used to by Unsafe.defineAnonymousClass() to provide access to private members of the host
+	private readonly TypeWrapper wrapper;
+	private readonly MethodWrapper mw;
+	private readonly ClassFile classFile;
+	private readonly ClassFile.Method method;
+	private readonly ClassLoaderWrapper classLoader;
+	private readonly TypeWrapper thisType;
+	private readonly InstructionState[] state;
+	private List errorMessages;
+	private readonly Dictionary newTypes = new Dictionary();
+	private readonly Dictionary faultTypes = new Dictionary();
+
+	static MethodAnalyzer()
+	{
+		ByteArrayType = PrimitiveTypeWrapper.BYTE.MakeArrayType(1);
+		BooleanArrayType = PrimitiveTypeWrapper.BOOLEAN.MakeArrayType(1);
+		ShortArrayType = PrimitiveTypeWrapper.SHORT.MakeArrayType(1);
+		CharArrayType = PrimitiveTypeWrapper.CHAR.MakeArrayType(1);
+		IntArrayType = PrimitiveTypeWrapper.INT.MakeArrayType(1);
+		FloatArrayType = PrimitiveTypeWrapper.FLOAT.MakeArrayType(1);
+		DoubleArrayType = PrimitiveTypeWrapper.DOUBLE.MakeArrayType(1);
+		LongArrayType = PrimitiveTypeWrapper.LONG.MakeArrayType(1);
+		java_lang_ThreadDeath = ClassLoaderWrapper.LoadClassCritical("java.lang.ThreadDeath");
+	}
+
+	internal MethodAnalyzer(TypeWrapper host, TypeWrapper wrapper, MethodWrapper mw, ClassFile classFile, ClassFile.Method method, ClassLoaderWrapper classLoader)
+	{
+		if(method.VerifyError != null)
+		{
+			throw new VerifyError(method.VerifyError);
+		}
+
+		this.host = host;
+		this.wrapper = wrapper;
+		this.mw = mw;
+		this.classFile = classFile;
+		this.method = method;
+		this.classLoader = classLoader;
+		state = new InstructionState[method.Instructions.Length];
+
+		try
+		{
+			// ensure that exception blocks and handlers start and end at instruction boundaries
+			for(int i = 0; i < method.ExceptionTable.Length; i++)
+			{
+				int start = method.ExceptionTable[i].startIndex;
+				int end = method.ExceptionTable[i].endIndex;
+				int handler = method.ExceptionTable[i].handlerIndex;
+				if(start >= end || start == -1 || end == -1 || handler <= 0)
+				{
+					throw new IndexOutOfRangeException();
+				}
+			}
+		}
+		catch(IndexOutOfRangeException)
+		{
+			// TODO figure out if we should throw this during class loading
+			throw new ClassFormatError(string.Format("Illegal exception table (class: {0}, method: {1}, signature: {2}", classFile.Name, method.Name, method.Signature));
+		}
+
+		// start by computing the initial state, the stack is empty and the locals contain the arguments
+		state[0] = new InstructionState(method.MaxLocals, method.MaxStack);
+		int firstNonArgLocalIndex = 0;
+		if(!method.IsStatic)
+		{
+			thisType = VerifierTypeWrapper.MakeThis(wrapper);
+			// this reference. If we're a constructor, the this reference is uninitialized.
+			if(method.IsConstructor)
+			{
+				state[0].SetLocalType(firstNonArgLocalIndex++, VerifierTypeWrapper.UninitializedThis, -1);
+				state[0].SetUnitializedThis(true);
+			}
+			else
+			{
+				state[0].SetLocalType(firstNonArgLocalIndex++, thisType, -1);
+			}
+		}
+		else
+		{
+			thisType = null;
+		}
+		// mw can be null when we're invoked from IsSideEffectFreeStaticInitializer
+		TypeWrapper[] argTypeWrappers = mw == null ? TypeWrapper.EmptyArray : mw.GetParameters();
+		for(int i = 0; i < argTypeWrappers.Length; i++)
+		{
+			TypeWrapper type = argTypeWrappers[i];
+			if(type.IsIntOnStackPrimitive)
+			{
+				type = PrimitiveTypeWrapper.INT;
+			}
+			state[0].SetLocalType(firstNonArgLocalIndex++, type, -1);
+			if(type.IsWidePrimitive)
+			{
+				firstNonArgLocalIndex++;
+			}
+		}
+		AnalyzeTypeFlow();
+		VerifyPassTwo();
+		PatchLoadConstants();
+	}
+
+	private void PatchLoadConstants()
+	{
+		ClassFile.Method.Instruction[] code = method.Instructions;
+		for (int i = 0; i < code.Length; i++)
+		{
+			if (state[i] != null)
+			{
+				switch (code[i].NormalizedOpCode)
+				{
+					case NormalizedByteCode.__ldc:
+						switch (GetConstantPoolConstantType(code[i].Arg1))
+						{
+							case ClassFile.ConstantType.Double:
+							case ClassFile.ConstantType.Float:
+							case ClassFile.ConstantType.Integer:
+							case ClassFile.ConstantType.Long:
+							case ClassFile.ConstantType.String:
+							case ClassFile.ConstantType.LiveObject:
+								code[i].PatchOpCode(NormalizedByteCode.__ldc_nothrow);
+								break;
+						}
+						break;
+				}
+			}
+		}
+	}
+
+	internal CodeInfo GetCodeInfoAndErrors(UntangledExceptionTable exceptions, out List errors)
+	{
+		CodeInfo codeInfo = new CodeInfo(state);
+		OptimizationPass(codeInfo, classFile, method, exceptions, wrapper, classLoader);
+		PatchHardErrorsAndDynamicMemberAccess(wrapper, mw);
+		errors = errorMessages;
+		if (AnalyzePotentialFaultBlocks(codeInfo, method, exceptions))
+		{
+			AnalyzeTypeFlow();
+		}
+		ConvertFinallyBlocks(codeInfo, method, exceptions);
+		return codeInfo;
+	}
+
+	private void AnalyzeTypeFlow()
+	{
+		InstructionState s = new InstructionState(method.MaxLocals, method.MaxStack);
+		bool done = false;
+		ClassFile.Method.Instruction[] instructions = method.Instructions;
+		while(!done)
+		{
+			done = true;
+			for(int i = 0; i < instructions.Length; i++)
+			{
+				if(state[i] != null && state[i].changed)
+				{
+					try
+					{
+						//Console.WriteLine(method.Instructions[i].PC + ": " + method.Instructions[i].OpCode.ToString());
+						done = false;
+						state[i].changed = false;
+						// mark the exception handlers reachable from this instruction
+						for(int j = 0; j < method.ExceptionTable.Length; j++)
+						{
+							if(method.ExceptionTable[j].startIndex <= i && i < method.ExceptionTable[j].endIndex)
+							{
+								MergeExceptionHandler(j, state[i]);
+							}
+						}
+						state[i].CopyTo(s);
+						ClassFile.Method.Instruction instr = instructions[i];
+						switch(instr.NormalizedOpCode)
+						{
+							case NormalizedByteCode.__aload:
+							{
+								TypeWrapper type = s.GetLocalType(instr.NormalizedArg1);
+								if(type == VerifierTypeWrapper.Invalid || type.IsPrimitive)
+								{
+									throw new VerifyError("Object reference expected");
+								}
+								s.PushType(type);
+								break;
+							}
+							case NormalizedByteCode.__astore:
+							{
+								if(VerifierTypeWrapper.IsFaultBlockException(s.PeekType()))
+								{
+									s.SetLocalType(instr.NormalizedArg1, s.PopFaultBlockException(), i);
+									break;
+								}
+								// NOTE since the reference can be uninitialized, we cannot use PopObjectType
+								TypeWrapper type = s.PopType();
+								if(type.IsPrimitive)
+								{
+									throw new VerifyError("Object reference expected");
+								}
+								s.SetLocalType(instr.NormalizedArg1, type, i);
+								break;
+							}
+							case NormalizedByteCode.__aconst_null:
+								s.PushType(VerifierTypeWrapper.Null);
+								break;
+							case NormalizedByteCode.__aaload:
+							{
+								s.PopInt();
+								TypeWrapper type = s.PopArrayType();
+								if(type == VerifierTypeWrapper.Null)
+								{
+									// if the array is null, we have use null as the element type, because
+									// otherwise the rest of the code will not verify correctly
+									s.PushType(VerifierTypeWrapper.Null);
+								}
+								else if(type.IsUnloadable)
+								{
+									s.PushType(VerifierTypeWrapper.Unloadable);
+								}
+								else
+								{
+									type = type.ElementTypeWrapper;
+									if(type.IsPrimitive)
+									{
+										throw new VerifyError("Object array expected");
+									}
+									s.PushType(type);
+								}
+								break;
+							}
+							case NormalizedByteCode.__aastore:
+								s.PopObjectType();
+								s.PopInt();
+								s.PopArrayType();
+								// TODO check that elem is assignable to the array
+								break;
+							case NormalizedByteCode.__baload:
+							{
+								s.PopInt();
+								TypeWrapper type = s.PopArrayType();
+								if(!VerifierTypeWrapper.IsNullOrUnloadable(type) &&
+									type != ByteArrayType &&
+									type != BooleanArrayType)
+								{
+									throw new VerifyError();
+								}
+								s.PushInt();
+								break;
+							}
+							case NormalizedByteCode.__bastore:
+							{
+								s.PopInt();
+								s.PopInt();
+								TypeWrapper type = s.PopArrayType();
+								if(!VerifierTypeWrapper.IsNullOrUnloadable(type) &&
+									type != ByteArrayType &&
+									type != BooleanArrayType)
+								{
+									throw new VerifyError();
+								}
+								break;
+							}
+							case NormalizedByteCode.__caload:
+								s.PopInt();
+								s.PopObjectType(CharArrayType);
+								s.PushInt();
+								break;
+							case NormalizedByteCode.__castore:
+								s.PopInt();
+								s.PopInt();
+								s.PopObjectType(CharArrayType);
+								break;
+							case NormalizedByteCode.__saload:
+								s.PopInt();
+								s.PopObjectType(ShortArrayType);
+								s.PushInt();
+								break;
+							case NormalizedByteCode.__sastore:
+								s.PopInt();
+								s.PopInt();
+								s.PopObjectType(ShortArrayType);
+								break;
+							case NormalizedByteCode.__iaload:
+								s.PopInt();
+								s.PopObjectType(IntArrayType);
+								s.PushInt();
+								break;
+							case NormalizedByteCode.__iastore:
+								s.PopInt();
+								s.PopInt();
+								s.PopObjectType(IntArrayType);
+								break;
+							case NormalizedByteCode.__laload:
+								s.PopInt();
+								s.PopObjectType(LongArrayType);
+								s.PushLong();
+								break;
+							case NormalizedByteCode.__lastore:
+								s.PopLong();
+								s.PopInt();
+								s.PopObjectType(LongArrayType);
+								break;
+							case NormalizedByteCode.__daload:
+								s.PopInt();
+								s.PopObjectType(DoubleArrayType);
+								s.PushDouble();
+								break;
+							case NormalizedByteCode.__dastore:
+								s.PopDouble();
+								s.PopInt();
+								s.PopObjectType(DoubleArrayType);
+								break;
+							case NormalizedByteCode.__faload:
+								s.PopInt();
+								s.PopObjectType(FloatArrayType);
+								s.PushFloat();
+								break;
+							case NormalizedByteCode.__fastore:
+								s.PopFloat();
+								s.PopInt();
+								s.PopObjectType(FloatArrayType);
+								break;
+							case NormalizedByteCode.__arraylength:
+								s.PopArrayType();
+								s.PushInt();
+								break;
+							case NormalizedByteCode.__iconst:
+								s.PushInt();
+								break;
+							case NormalizedByteCode.__if_icmpeq:
+							case NormalizedByteCode.__if_icmpne:
+							case NormalizedByteCode.__if_icmplt:
+							case NormalizedByteCode.__if_icmpge:
+							case NormalizedByteCode.__if_icmpgt:
+							case NormalizedByteCode.__if_icmple:
+								s.PopInt();
+								s.PopInt();
+								break;
+							case NormalizedByteCode.__ifeq:
+							case NormalizedByteCode.__ifge:
+							case NormalizedByteCode.__ifgt:
+							case NormalizedByteCode.__ifle:
+							case NormalizedByteCode.__iflt:
+							case NormalizedByteCode.__ifne:
+								s.PopInt();
+								break;
+							case NormalizedByteCode.__ifnonnull:
+							case NormalizedByteCode.__ifnull:
+								// TODO it might be legal to use an unitialized ref here
+								s.PopObjectType();
+								break;
+							case NormalizedByteCode.__if_acmpeq:
+							case NormalizedByteCode.__if_acmpne:
+								// TODO it might be legal to use an unitialized ref here
+								s.PopObjectType();
+								s.PopObjectType();
+								break;
+							case NormalizedByteCode.__getstatic:
+							case NormalizedByteCode.__dynamic_getstatic:
+								// special support for when we're being called from IsSideEffectFreeStaticInitializer
+								if(mw == null)
+								{
+									switch(GetFieldref(instr.Arg1).Signature[0])
+									{
+										case 'B':
+										case 'Z':
+										case 'C':
+										case 'S':
+										case 'I':
+											s.PushInt();
+											break;
+										case 'F':
+											s.PushFloat();
+											break;
+										case 'D':
+											s.PushDouble();
+											break;
+										case 'J':
+											s.PushLong();
+											break;
+										case 'L':
+										case '[':
+											throw new VerifyError();
+										default:
+											throw new InvalidOperationException();
+									}
+								}
+								else
+								{
+									ClassFile.ConstantPoolItemFieldref cpi = GetFieldref(instr.Arg1);
+									if(cpi.GetField() != null && cpi.GetField().FieldTypeWrapper.IsUnloadable)
+									{
+										s.PushType(cpi.GetField().FieldTypeWrapper);
+									}
+									else
+									{
+										s.PushType(cpi.GetFieldType());
+									}
+								}
+								break;
+							case NormalizedByteCode.__putstatic:
+							case NormalizedByteCode.__dynamic_putstatic:
+								// special support for when we're being called from IsSideEffectFreeStaticInitializer
+								if(mw == null)
+								{
+									switch(GetFieldref(instr.Arg1).Signature[0])
+									{
+										case 'B':
+										case 'Z':
+										case 'C':
+										case 'S':
+										case 'I':
+											s.PopInt();
+											break;
+										case 'F':
+											s.PopFloat();
+											break;
+										case 'D':
+											s.PopDouble();
+											break;
+										case 'J':
+											s.PopLong();
+											break;
+										case 'L':
+										case '[':
+											if(s.PopAnyType() != VerifierTypeWrapper.Null)
+											{
+												throw new VerifyError();
+											}
+											break;
+										default:
+											throw new InvalidOperationException();
+									}
+								}
+								else
+								{
+									s.PopType(GetFieldref(instr.Arg1).GetFieldType());
+								}
+								break;
+							case NormalizedByteCode.__getfield:
+							case NormalizedByteCode.__dynamic_getfield:
+							{
+								s.PopObjectType(GetFieldref(instr.Arg1).GetClassType());
+								ClassFile.ConstantPoolItemFieldref cpi = GetFieldref(instr.Arg1);
+								if(cpi.GetField() != null && cpi.GetField().FieldTypeWrapper.IsUnloadable)
+								{
+									s.PushType(cpi.GetField().FieldTypeWrapper);
+								}
+								else
+								{
+									s.PushType(cpi.GetFieldType());
+								}
+								break;
+							}
+							case NormalizedByteCode.__putfield:
+							case NormalizedByteCode.__dynamic_putfield:
+								s.PopType(GetFieldref(instr.Arg1).GetFieldType());
+								// putfield is allowed to access the uninitialized this
+								if(s.PeekType() == VerifierTypeWrapper.UninitializedThis
+									&& wrapper.IsAssignableTo(GetFieldref(instr.Arg1).GetClassType()))
+								{
+									s.PopType();
+								}
+								else
+								{
+									s.PopObjectType(GetFieldref(instr.Arg1).GetClassType());
+								}
+								break;
+							case NormalizedByteCode.__ldc_nothrow:
+							case NormalizedByteCode.__ldc:
+							{
+								switch(GetConstantPoolConstantType(instr.Arg1))
+								{
+									case ClassFile.ConstantType.Double:
+										s.PushDouble();
+										break;
+									case ClassFile.ConstantType.Float:
+										s.PushFloat();
+										break;
+									case ClassFile.ConstantType.Integer:
+										s.PushInt();
+										break;
+									case ClassFile.ConstantType.Long:
+										s.PushLong();
+										break;
+									case ClassFile.ConstantType.String:
+										s.PushType(CoreClasses.java.lang.String.Wrapper);
+										break;
+									case ClassFile.ConstantType.LiveObject:
+										s.PushType(CoreClasses.java.lang.Object.Wrapper);
+										break;
+									case ClassFile.ConstantType.Class:
+										if(classFile.MajorVersion < 49)
+										{
+											throw new VerifyError("Illegal type in constant pool");
+										}
+										s.PushType(CoreClasses.java.lang.Class.Wrapper);
+										break;
+									case ClassFile.ConstantType.MethodHandle:
+										s.PushType(CoreClasses.java.lang.invoke.MethodHandle.Wrapper);
+										break;
+									case ClassFile.ConstantType.MethodType:
+										s.PushType(CoreClasses.java.lang.invoke.MethodType.Wrapper);
+										break;
+									default:
+										// NOTE this is not a VerifyError, because it cannot happen (unless we have
+										// a bug in ClassFile.GetConstantPoolConstantType)
+										throw new InvalidOperationException();
+								}
+								break;
+							}
+							case NormalizedByteCode.__clone_array:
+							case NormalizedByteCode.__invokevirtual:
+							case NormalizedByteCode.__invokespecial:
+							case NormalizedByteCode.__invokeinterface:
+							case NormalizedByteCode.__invokestatic:
+							case NormalizedByteCode.__dynamic_invokevirtual:
+							case NormalizedByteCode.__dynamic_invokespecial:
+							case NormalizedByteCode.__dynamic_invokeinterface:
+							case NormalizedByteCode.__dynamic_invokestatic:
+							case NormalizedByteCode.__privileged_invokevirtual:
+							case NormalizedByteCode.__privileged_invokespecial:
+							case NormalizedByteCode.__privileged_invokestatic:
+							case NormalizedByteCode.__methodhandle_invoke:
+							case NormalizedByteCode.__methodhandle_link:
+							{
+								ClassFile.ConstantPoolItemMI cpi = GetMethodref(instr.Arg1);
+								TypeWrapper retType = cpi.GetRetType();
+								// HACK to allow the result of Unsafe.getObjectVolatile() (on an array)
+								// to be used with Unsafe.putObject() we need to propagate the
+								// element type here as the return type (instead of object)
+								if(cpi.GetMethod() != null
+									&& cpi.GetMethod().IsIntrinsic
+									&& cpi.Class == "sun.misc.Unsafe"
+									&& cpi.Name == "getObjectVolatile"
+									&& Intrinsics.IsSupportedArrayTypeForUnsafeOperation(s.GetStackSlot(1)))
+								{
+									retType = s.GetStackSlot(1).ElementTypeWrapper;
+								}
+								s.MultiPopAnyType(cpi.GetArgTypes().Length);
+								if(instr.NormalizedOpCode != NormalizedByteCode.__invokestatic
+									&& instr.NormalizedOpCode != NormalizedByteCode.__dynamic_invokestatic)
+								{
+									TypeWrapper type = s.PopType();
+									if(ReferenceEquals(cpi.Name, StringConstants.INIT))
+									{
+										// after we've invoked the constructor, the uninitialized references
+										// are now initialized
+										if(type == VerifierTypeWrapper.UninitializedThis)
+										{
+											if(s.GetLocalTypeEx(0) == type)
+											{
+												s.SetLocalType(0, thisType, i);
+											}
+											s.MarkInitialized(type, wrapper, i);
+											s.SetUnitializedThis(false);
+										}
+										else if(VerifierTypeWrapper.IsNew(type))
+										{
+											s.MarkInitialized(type, ((VerifierTypeWrapper)type).UnderlyingType, i);
+										}
+										else
+										{
+											// This is a VerifyError, but it will be caught by our second pass
+										}
+									}
+								}
+								if(retType != PrimitiveTypeWrapper.VOID)
+								{
+									if(cpi.GetMethod() != null && cpi.GetMethod().ReturnType.IsUnloadable)
+									{
+										s.PushType(cpi.GetMethod().ReturnType);
+									}
+									else if(retType == PrimitiveTypeWrapper.DOUBLE)
+									{
+										s.PushExtendedDouble();
+									}
+									else if(retType == PrimitiveTypeWrapper.FLOAT)
+									{
+										s.PushExtendedFloat();
+									}
+									else
+									{
+										s.PushType(retType);
+									}
+								}
+								break;
+							}
+							case NormalizedByteCode.__invokedynamic:
+							{
+								ClassFile.ConstantPoolItemInvokeDynamic cpi = GetInvokeDynamic(instr.Arg1);
+								s.MultiPopAnyType(cpi.GetArgTypes().Length);
+								TypeWrapper retType = cpi.GetRetType();
+								if (retType != PrimitiveTypeWrapper.VOID)
+								{
+									if (retType == PrimitiveTypeWrapper.DOUBLE)
+									{
+										s.PushExtendedDouble();
+									}
+									else if (retType == PrimitiveTypeWrapper.FLOAT)
+									{
+										s.PushExtendedFloat();
+									}
+									else
+									{
+										s.PushType(retType);
+									}
+								}
+								break;
+							}
+							case NormalizedByteCode.__goto:
+								break;
+							case NormalizedByteCode.__istore:
+								s.PopInt();
+								s.SetLocalInt(instr.NormalizedArg1, i);
+								break;
+							case NormalizedByteCode.__iload:
+								s.GetLocalInt(instr.NormalizedArg1);
+								s.PushInt();
+								break;
+							case NormalizedByteCode.__ineg:
+								s.PopInt();
+								s.PushInt();
+								break;
+							case NormalizedByteCode.__iadd:
+							case NormalizedByteCode.__isub:
+							case NormalizedByteCode.__imul:
+							case NormalizedByteCode.__idiv:
+							case NormalizedByteCode.__irem:
+							case NormalizedByteCode.__iand:
+							case NormalizedByteCode.__ior:
+							case NormalizedByteCode.__ixor:
+							case NormalizedByteCode.__ishl:
+							case NormalizedByteCode.__ishr:
+							case NormalizedByteCode.__iushr:
+								s.PopInt();
+								s.PopInt();
+								s.PushInt();
+								break;
+							case NormalizedByteCode.__lneg:
+								s.PopLong();
+								s.PushLong();
+								break;
+							case NormalizedByteCode.__ladd:
+							case NormalizedByteCode.__lsub:
+							case NormalizedByteCode.__lmul:
+							case NormalizedByteCode.__ldiv:
+							case NormalizedByteCode.__lrem:
+							case NormalizedByteCode.__land:
+							case NormalizedByteCode.__lor:
+							case NormalizedByteCode.__lxor:
+								s.PopLong();
+								s.PopLong();
+								s.PushLong();
+								break;
+							case NormalizedByteCode.__lshl:
+							case NormalizedByteCode.__lshr:
+							case NormalizedByteCode.__lushr:
+								s.PopInt();
+								s.PopLong();
+								s.PushLong();
+								break;
+							case NormalizedByteCode.__fneg:
+								if(s.PopFloat())
+								{
+									s.PushExtendedFloat();
+								}
+								else
+								{
+									s.PushFloat();
+								}
+								break;
+							case NormalizedByteCode.__fadd:
+							case NormalizedByteCode.__fsub:
+							case NormalizedByteCode.__fmul:
+							case NormalizedByteCode.__fdiv:
+							case NormalizedByteCode.__frem:
+								s.PopFloat();
+								s.PopFloat();
+								s.PushExtendedFloat();
+								break;
+							case NormalizedByteCode.__dneg:
+								if(s.PopDouble())
+								{
+									s.PushExtendedDouble();
+								}
+								else
+								{
+									s.PushDouble();
+								}
+								break;
+							case NormalizedByteCode.__dadd:
+							case NormalizedByteCode.__dsub:
+							case NormalizedByteCode.__dmul:
+							case NormalizedByteCode.__ddiv:
+							case NormalizedByteCode.__drem:
+								s.PopDouble();
+								s.PopDouble();
+								s.PushExtendedDouble();
+								break;
+							case NormalizedByteCode.__new:
+							{
+								// mark the type, so that we can ascertain that it is a "new object"
+								TypeWrapper type;
+								if(!newTypes.TryGetValue(i, out type))
+								{
+									type = GetConstantPoolClassType(instr.Arg1);
+									if(type.IsArray)
+									{
+										throw new VerifyError("Illegal use of array type");
+									}
+									type = VerifierTypeWrapper.MakeNew(type, i);
+									newTypes[i] = type;
+								}
+								s.PushType(type);
+								break;
+							}
+							case NormalizedByteCode.__multianewarray:
+							{
+								if(instr.Arg2 < 1)
+								{
+									throw new VerifyError("Illegal dimension argument");
+								}
+								for(int j = 0; j < instr.Arg2; j++)
+								{
+									s.PopInt();
+								}
+								TypeWrapper type = GetConstantPoolClassType(instr.Arg1);
+								if(type.ArrayRank < instr.Arg2)
+								{
+									throw new VerifyError("Illegal dimension argument");
+								}
+								s.PushType(type);
+								break;
+							}
+							case NormalizedByteCode.__anewarray:
+							{
+								s.PopInt();
+								TypeWrapper type = GetConstantPoolClassType(instr.Arg1);
+								if(type.IsUnloadable)
+								{
+									s.PushType(new UnloadableTypeWrapper("[" + type.SigName));
+								}
+								else
+								{
+									s.PushType(type.MakeArrayType(1));
+								}
+								break;
+							}
+							case NormalizedByteCode.__newarray:
+								s.PopInt();
+							switch(instr.Arg1)
+							{
+								case 4:
+									s.PushType(BooleanArrayType);
+									break;
+								case 5:
+									s.PushType(CharArrayType);
+									break;
+								case 6:
+									s.PushType(FloatArrayType);
+									break;
+								case 7:
+									s.PushType(DoubleArrayType);
+									break;
+								case 8:
+									s.PushType(ByteArrayType);
+									break;
+								case 9:
+									s.PushType(ShortArrayType);
+									break;
+								case 10:
+									s.PushType(IntArrayType);
+									break;
+								case 11:
+									s.PushType(LongArrayType);
+									break;
+								default:
+									throw new VerifyError("Bad type");
+							}
+								break;
+							case NormalizedByteCode.__swap:
+							{
+								TypeWrapper t1 = s.PopType();
+								TypeWrapper t2 = s.PopType();
+								s.PushType(t1);
+								s.PushType(t2);
+								break;
+							}
+							case NormalizedByteCode.__dup:
+							{
+								TypeWrapper t = s.PopType();
+								s.PushType(t);
+								s.PushType(t);
+								break;
+							}
+							case NormalizedByteCode.__dup2:
+							{
+								TypeWrapper t = s.PopAnyType();
+								if(t.IsWidePrimitive || t == VerifierTypeWrapper.ExtendedDouble)
+								{
+									s.PushType(t);
+									s.PushType(t);
+								}
+								else
+								{
+									TypeWrapper t2 = s.PopType();
+									s.PushType(t2);
+									s.PushType(t);
+									s.PushType(t2);
+									s.PushType(t);
+								}
+								break;
+							}
+							case NormalizedByteCode.__dup_x1:
+							{
+								TypeWrapper value1 = s.PopType();
+								TypeWrapper value2 = s.PopType();
+								s.PushType(value1);
+								s.PushType(value2);
+								s.PushType(value1);
+								break;
+							}
+							case NormalizedByteCode.__dup2_x1:
+							{
+								TypeWrapper value1 = s.PopAnyType();
+								if(value1.IsWidePrimitive || value1 == VerifierTypeWrapper.ExtendedDouble)
+								{
+									TypeWrapper value2 = s.PopType();
+									s.PushType(value1);
+									s.PushType(value2);
+									s.PushType(value1);
+								}
+								else
+								{
+									TypeWrapper value2 = s.PopType();
+									TypeWrapper value3 = s.PopType();
+									s.PushType(value2);
+									s.PushType(value1);
+									s.PushType(value3);
+									s.PushType(value2);
+									s.PushType(value1);
+								}
+								break;
+							}
+							case NormalizedByteCode.__dup_x2:
+							{
+								TypeWrapper value1 = s.PopType();
+								TypeWrapper value2 = s.PopAnyType();
+								if(value2.IsWidePrimitive || value2 == VerifierTypeWrapper.ExtendedDouble)
+								{
+									s.PushType(value1);
+									s.PushType(value2);
+									s.PushType(value1);
+								}
+								else
+								{
+									TypeWrapper value3 = s.PopType();
+									s.PushType(value1);
+									s.PushType(value3);
+									s.PushType(value2);
+									s.PushType(value1);
+								}
+								break;
+							}
+							case NormalizedByteCode.__dup2_x2:
+							{
+								TypeWrapper value1 = s.PopAnyType();
+								if(value1.IsWidePrimitive || value1 == VerifierTypeWrapper.ExtendedDouble)
+								{
+									TypeWrapper value2 = s.PopAnyType();
+									if(value2.IsWidePrimitive || value2 == VerifierTypeWrapper.ExtendedDouble)
+									{
+										// Form 4
+										s.PushType(value1);
+										s.PushType(value2);
+										s.PushType(value1);
+									}
+									else
+									{
+										// Form 2
+										TypeWrapper value3 = s.PopType();
+										s.PushType(value1);
+										s.PushType(value3);
+										s.PushType(value2);
+										s.PushType(value1);
+									}
+								}
+								else
+								{
+									TypeWrapper value2 = s.PopType();
+									TypeWrapper value3 = s.PopAnyType();
+									if(value3.IsWidePrimitive || value3 == VerifierTypeWrapper.ExtendedDouble)
+									{
+										// Form 3
+										s.PushType(value2);
+										s.PushType(value1);
+										s.PushType(value3);
+										s.PushType(value2);
+										s.PushType(value1);
+									}
+									else
+									{
+										// Form 4
+										TypeWrapper value4 = s.PopType();
+										s.PushType(value2);
+										s.PushType(value1);
+										s.PushType(value4);
+										s.PushType(value3);
+										s.PushType(value2);
+										s.PushType(value1);
+									}
+								}
+								break;
+							}
+							case NormalizedByteCode.__pop:
+								s.PopType();
+								break;
+							case NormalizedByteCode.__pop2:
+							{
+								TypeWrapper type = s.PopAnyType();
+								if(!type.IsWidePrimitive && type != VerifierTypeWrapper.ExtendedDouble)
+								{
+									s.PopType();
+								}
+								break;
+							}
+							case NormalizedByteCode.__monitorenter:
+							case NormalizedByteCode.__monitorexit:
+								// TODO these bytecodes are allowed on an uninitialized object, but
+								// we don't support that at the moment...
+								s.PopObjectType();
+								break;
+							case NormalizedByteCode.__return:
+								// mw is null if we're called from IsSideEffectFreeStaticInitializer
+								if(mw != null)
+								{
+									if(mw.ReturnType != PrimitiveTypeWrapper.VOID)
+									{
+										throw new VerifyError("Wrong return type in function");
+									}
+									// if we're a constructor, make sure we called the base class constructor
+									s.CheckUninitializedThis();
+								}
+								break;
+							case NormalizedByteCode.__areturn:
+								s.PopObjectType(mw.ReturnType);
+								break;
+							case NormalizedByteCode.__ireturn:
+							{
+								s.PopInt();
+								if(!mw.ReturnType.IsIntOnStackPrimitive)
+								{
+									throw new VerifyError("Wrong return type in function");
+								}
+								break;
+							}
+							case NormalizedByteCode.__lreturn:
+								s.PopLong();
+								if(mw.ReturnType != PrimitiveTypeWrapper.LONG)
+								{
+									throw new VerifyError("Wrong return type in function");
+								}
+								break;
+							case NormalizedByteCode.__freturn:
+								s.PopFloat();
+								if(mw.ReturnType != PrimitiveTypeWrapper.FLOAT)
+								{
+									throw new VerifyError("Wrong return type in function");
+								}
+								break;
+							case NormalizedByteCode.__dreturn:
+								s.PopDouble();
+								if(mw.ReturnType != PrimitiveTypeWrapper.DOUBLE)
+								{
+									throw new VerifyError("Wrong return type in function");
+								}
+								break;
+							case NormalizedByteCode.__fload:
+								s.GetLocalFloat(instr.NormalizedArg1);
+								s.PushFloat();
+								break;
+							case NormalizedByteCode.__fstore:
+								s.PopFloat();
+								s.SetLocalFloat(instr.NormalizedArg1, i);
+								break;
+							case NormalizedByteCode.__dload:
+								s.GetLocalDouble(instr.NormalizedArg1);
+								s.PushDouble();
+								break;
+							case NormalizedByteCode.__dstore:
+								s.PopDouble();
+								s.SetLocalDouble(instr.NormalizedArg1, i);
+								break;
+							case NormalizedByteCode.__lload:
+								s.GetLocalLong(instr.NormalizedArg1);
+								s.PushLong();
+								break;
+							case NormalizedByteCode.__lstore:
+								s.PopLong();
+								s.SetLocalLong(instr.NormalizedArg1, i);
+								break;
+							case NormalizedByteCode.__lconst_0:
+							case NormalizedByteCode.__lconst_1:
+								s.PushLong();
+								break;
+							case NormalizedByteCode.__fconst_0:
+							case NormalizedByteCode.__fconst_1:
+							case NormalizedByteCode.__fconst_2:
+								s.PushFloat();
+								break;
+							case NormalizedByteCode.__dconst_0:
+							case NormalizedByteCode.__dconst_1:
+								s.PushDouble();
+								break;
+							case NormalizedByteCode.__lcmp:
+								s.PopLong();
+								s.PopLong();
+								s.PushInt();
+								break;
+							case NormalizedByteCode.__fcmpl:
+							case NormalizedByteCode.__fcmpg:
+								s.PopFloat();
+								s.PopFloat();
+								s.PushInt();
+								break;
+							case NormalizedByteCode.__dcmpl:
+							case NormalizedByteCode.__dcmpg:
+								s.PopDouble();
+								s.PopDouble();
+								s.PushInt();
+								break;
+							case NormalizedByteCode.__checkcast:
+								s.PopObjectType();
+								s.PushType(GetConstantPoolClassType(instr.Arg1));
+								break;
+							case NormalizedByteCode.__instanceof:
+								s.PopObjectType();
+								s.PushInt();
+								break;
+							case NormalizedByteCode.__iinc:
+								s.GetLocalInt(instr.Arg1);
+								break;
+							case NormalizedByteCode.__athrow:
+								if (VerifierTypeWrapper.IsFaultBlockException(s.PeekType()))
+								{
+									s.PopFaultBlockException();
+								}
+								else
+								{
+									s.PopObjectType(CoreClasses.java.lang.Throwable.Wrapper);
+								}
+								break;
+							case NormalizedByteCode.__tableswitch:
+							case NormalizedByteCode.__lookupswitch:
+								s.PopInt();
+								break;
+							case NormalizedByteCode.__i2b:
+								s.PopInt();
+								s.PushInt();
+								break;
+							case NormalizedByteCode.__i2c:
+								s.PopInt();
+								s.PushInt();
+								break;
+							case NormalizedByteCode.__i2s:
+								s.PopInt();
+								s.PushInt();
+								break;
+							case NormalizedByteCode.__i2l:
+								s.PopInt();
+								s.PushLong();
+								break;
+							case NormalizedByteCode.__i2f:
+								s.PopInt();
+								s.PushFloat();
+								break;
+							case NormalizedByteCode.__i2d:
+								s.PopInt();
+								s.PushDouble();
+								break;
+							case NormalizedByteCode.__l2i:
+								s.PopLong();
+								s.PushInt();
+								break;
+							case NormalizedByteCode.__l2f:
+								s.PopLong();
+								s.PushFloat();
+								break;
+							case NormalizedByteCode.__l2d:
+								s.PopLong();
+								s.PushDouble();
+								break;
+							case NormalizedByteCode.__f2i:
+								s.PopFloat();
+								s.PushInt();
+								break;
+							case NormalizedByteCode.__f2l:
+								s.PopFloat();
+								s.PushLong();
+								break;
+							case NormalizedByteCode.__f2d:
+								s.PopFloat();
+								s.PushDouble();
+								break;
+							case NormalizedByteCode.__d2i:
+								s.PopDouble();
+								s.PushInt();
+								break;
+							case NormalizedByteCode.__d2f:
+								s.PopDouble();
+								s.PushFloat();
+								break;
+							case NormalizedByteCode.__d2l:
+								s.PopDouble();
+								s.PushLong();
+								break;
+							case NormalizedByteCode.__nop:
+								if(i + 1 == instructions.Length)
+								{
+									throw new VerifyError("Falling off the end of the code");
+								}
+								break;
+							case NormalizedByteCode.__static_error:
+								break;
+							case NormalizedByteCode.__jsr:
+							case NormalizedByteCode.__ret:
+								throw new VerifyError("Bad instruction");
+							default:
+								throw new NotImplementedException(instr.NormalizedOpCode.ToString());
+						}
+						if(s.GetStackHeight() > method.MaxStack)
+						{
+							throw new VerifyError("Stack size too large");
+						}
+						for(int j = 0; j < method.ExceptionTable.Length; j++)
+						{
+							if(method.ExceptionTable[j].endIndex == i + 1)
+							{
+								MergeExceptionHandler(j, s);
+							}
+						}
+						try
+						{
+							switch(ByteCodeMetaData.GetFlowControl(instr.NormalizedOpCode))
+							{
+								case ByteCodeFlowControl.Switch:
+									for(int j = 0; j < instr.SwitchEntryCount; j++)
+									{
+										state[instr.GetSwitchTargetIndex(j)] += s;
+									}
+									state[instr.DefaultTarget] += s;
+									break;
+								case ByteCodeFlowControl.CondBranch:
+									state[i + 1] += s;
+									state[instr.TargetIndex] += s;
+									break;
+								case ByteCodeFlowControl.Branch:
+									state[instr.TargetIndex] += s;
+									break;
+								case ByteCodeFlowControl.Return:
+								case ByteCodeFlowControl.Throw:
+									break;
+								case ByteCodeFlowControl.Next:
+									state[i + 1] += s;
+									break;
+								default:
+									throw new InvalidOperationException();
+							}
+						}
+						catch(IndexOutOfRangeException)
+						{
+							// we're going to assume that this always means that we have an invalid branch target
+							// NOTE because PcIndexMap returns -1 for illegal PCs (in the middle of an instruction) and
+							// we always use that value as an index into the state array, any invalid PC will result
+							// in an IndexOutOfRangeException
+							throw new VerifyError("Illegal target of jump or branch");
+						}
+					}
+					catch(VerifyError x)
+					{
+						string opcode = instructions[i].NormalizedOpCode.ToString();
+						if(opcode.StartsWith("__"))
+						{
+							opcode = opcode.Substring(2);
+						}
+						throw new VerifyError(string.Format("{5} (class: {0}, method: {1}, signature: {2}, offset: {3}, instruction: {4})",
+							classFile.Name, method.Name, method.Signature, instructions[i].PC, opcode, x.Message), x);
+					}
+				}
+			}
+		}
+	}
+
+	private void MergeExceptionHandler(int exceptionIndex, InstructionState curr)
+	{
+		int idx = method.ExceptionTable[exceptionIndex].handlerIndex;
+		InstructionState ex = curr.CopyLocals();
+		int catch_type = method.ExceptionTable[exceptionIndex].catch_type;
+		if (catch_type == 0)
+		{
+			TypeWrapper tw;
+			if (!faultTypes.TryGetValue(idx, out tw))
+			{
+				tw = VerifierTypeWrapper.MakeFaultBlockException(this, idx);
+				faultTypes.Add(idx, tw);
+			}
+			ex.PushType(tw);
+		}
+		else
+		{
+			// TODO if the exception type is unloadable we should consider pushing
+			// Throwable as the type and recording a loader constraint
+			ex.PushType(GetConstantPoolClassType(catch_type));
+		}
+		state[idx] += ex;
+	}
+
+	// this verification pass must run on the unmodified bytecode stream
+	private void VerifyPassTwo()
+	{
+		ClassFile.Method.Instruction[] instructions = method.Instructions;
+		for (int i = 0; i < instructions.Length; i++)
+		{
+			if (state[i] != null)
+			{
+				try
+				{
+					switch (instructions[i].NormalizedOpCode)
+					{
+						case NormalizedByteCode.__invokeinterface:
+						case NormalizedByteCode.__invokespecial:
+						case NormalizedByteCode.__invokestatic:
+						case NormalizedByteCode.__invokevirtual:
+							VerifyInvokePassTwo(i);
+							break;
+						case NormalizedByteCode.__invokedynamic:
+							VerifyInvokeDynamic(i);
+							break;
+					}
+				}
+				catch (VerifyError x)
+				{
+					string opcode = instructions[i].NormalizedOpCode.ToString();
+					if (opcode.StartsWith("__"))
+					{
+						opcode = opcode.Substring(2);
+					}
+					throw new VerifyError(string.Format("{5} (class: {0}, method: {1}, signature: {2}, offset: {3}, instruction: {4})",
+						classFile.Name, method.Name, method.Signature, instructions[i].PC, opcode, x.Message), x);
+				}
+			}
+		}
+	}
+
+	private void VerifyInvokePassTwo(int index)
+	{
+		StackState stack = new StackState(state[index]);
+		NormalizedByteCode invoke = method.Instructions[index].NormalizedOpCode;
+		ClassFile.ConstantPoolItemMI cpi = GetMethodref(method.Instructions[index].Arg1);
+		if ((invoke == NormalizedByteCode.__invokestatic || invoke == NormalizedByteCode.__invokespecial) && classFile.MajorVersion >= 52)
+		{
+			// invokestatic and invokespecial may be used to invoke interface methods in Java 8
+			// but invokespecial can only invoke methods in the current interface or a directly implemented interface
+			if (invoke == NormalizedByteCode.__invokespecial && cpi is ClassFile.ConstantPoolItemInterfaceMethodref)
+			{
+				if (cpi.GetClassType() == host)
+				{
+					// ok
+				}
+				else if (cpi.GetClassType() != wrapper && Array.IndexOf(wrapper.Interfaces, cpi.GetClassType()) == -1)
+				{
+					throw new VerifyError("Bad invokespecial instruction: interface method reference is in an indirect superinterface.");
+				}
+			}
+		}
+		else if ((cpi is ClassFile.ConstantPoolItemInterfaceMethodref) != (invoke == NormalizedByteCode.__invokeinterface))
+		{
+			throw new VerifyError("Illegal constant pool index");
+		}
+		if (invoke != NormalizedByteCode.__invokespecial && ReferenceEquals(cpi.Name, StringConstants.INIT))
+		{
+			throw new VerifyError("Must call initializers using invokespecial");
+		}
+		if (ReferenceEquals(cpi.Name, StringConstants.CLINIT))
+		{
+			throw new VerifyError("Illegal call to internal method");
+		}
+		TypeWrapper[] args = cpi.GetArgTypes();
+		for (int j = args.Length - 1; j >= 0; j--)
+		{
+			stack.PopType(args[j]);
+		}
+		if (invoke == NormalizedByteCode.__invokeinterface)
+		{
+			int argcount = args.Length + 1;
+			for (int j = 0; j < args.Length; j++)
+			{
+				if (args[j].IsWidePrimitive)
+				{
+					argcount++;
+				}
+			}
+			if (method.Instructions[index].Arg2 != argcount)
+			{
+				throw new VerifyError("Inconsistent args size");
+			}
+		}
+		bool isnew = false;
+		TypeWrapper thisType;
+		if (invoke == NormalizedByteCode.__invokestatic)
+		{
+			thisType = null;
+		}
+		else
+		{
+			thisType = SigTypeToClassName(stack.PeekType(), cpi.GetClassType(), wrapper);
+			if (ReferenceEquals(cpi.Name, StringConstants.INIT))
+			{
+				TypeWrapper type = stack.PopType();
+				isnew = VerifierTypeWrapper.IsNew(type);
+				if ((isnew && ((VerifierTypeWrapper)type).UnderlyingType != cpi.GetClassType()) ||
+					(type == VerifierTypeWrapper.UninitializedThis && cpi.GetClassType() != wrapper.BaseTypeWrapper && cpi.GetClassType() != wrapper) ||
+					(!isnew && type != VerifierTypeWrapper.UninitializedThis))
+				{
+					// TODO oddly enough, Java fails verification for the class without
+					// even running the constructor, so maybe constructors are always
+					// verified...
+					// NOTE when a constructor isn't verifiable, the static initializer
+					// doesn't run either
+					throw new VerifyError("Call to wrong initialization method");
+				}
+			}
+			else
+			{
+				if (invoke != NormalizedByteCode.__invokeinterface)
+				{
+					TypeWrapper refType = stack.PopObjectType();
+					TypeWrapper targetType = cpi.GetClassType();
+					if (!VerifierTypeWrapper.IsNullOrUnloadable(refType) &&
+						!targetType.IsUnloadable &&
+						!refType.IsAssignableTo(targetType))
+					{
+						throw new VerifyError("Incompatible object argument for function call");
+					}
+					// for invokespecial we also need to make sure we're calling ourself or a base class
+					if (invoke == NormalizedByteCode.__invokespecial)
+					{
+						if (VerifierTypeWrapper.IsNullOrUnloadable(refType))
+						{
+							// ok
+						}
+						else if (refType.IsSubTypeOf(wrapper))
+						{
+							// ok
+						}
+						else if (host != null && refType.IsSubTypeOf(host))
+						{
+							// ok
+						}
+						else
+						{
+							throw new VerifyError("Incompatible target object for invokespecial");
+						}
+						if (targetType.IsUnloadable)
+						{
+							// ok
+						}
+						else if (wrapper.IsSubTypeOf(targetType))
+						{
+							// ok
+						}
+						else if (host != null && host.IsSubTypeOf(targetType))
+						{
+							// ok
+						}
+						else
+						{
+							throw new VerifyError("Invokespecial cannot call subclass methods");
+						}
+					}
+				}
+				else /* __invokeinterface */
+				{
+					// NOTE unlike in the above case, we also allow *any* interface target type
+					// regardless of whether it is compatible or not, because if it is not compatible
+					// we want an IncompatibleClassChangeError at runtime
+					TypeWrapper refType = stack.PopObjectType();
+					TypeWrapper targetType = cpi.GetClassType();
+					if (!VerifierTypeWrapper.IsNullOrUnloadable(refType)
+						&& !targetType.IsUnloadable
+						&& !refType.IsAssignableTo(targetType)
+						&& !targetType.IsInterface)
+					{
+						throw new VerifyError("Incompatible object argument for function call");
+					}
+				}
+			}
+		}
+	}
+
+	private void VerifyInvokeDynamic(int index)
+	{
+		StackState stack = new StackState(state[index]);
+		ClassFile.ConstantPoolItemInvokeDynamic cpi = GetInvokeDynamic(method.Instructions[index].Arg1);
+		TypeWrapper[] args = cpi.GetArgTypes();
+		for (int j = args.Length - 1; j >= 0; j--)
+		{
+			stack.PopType(args[j]);
+		}
+	}
+
+	private static void OptimizationPass(CodeInfo codeInfo, ClassFile classFile, ClassFile.Method method, UntangledExceptionTable exceptions, TypeWrapper wrapper, ClassLoaderWrapper classLoader)
+	{
+		// Optimization pass
+		if (classLoader.RemoveAsserts)
+		{
+			// While the optimization is general, in practice it never happens that a getstatic is used on a final field,
+			// so we only look for this if assert initialization has been optimized out.
+			if (classFile.HasAssertions)
+			{
+				// compute branch targets
+				InstructionFlags[] flags = MethodAnalyzer.ComputePartialReachability(codeInfo, method.Instructions, exceptions, 0, false);
+				ClassFile.Method.Instruction[] instructions = method.Instructions;
+				for (int i = 0; i < instructions.Length; i++)
+				{
+					if (instructions[i].NormalizedOpCode == NormalizedByteCode.__getstatic
+						&& instructions[i + 1].NormalizedOpCode == NormalizedByteCode.__ifne
+						&& instructions[i + 1].TargetIndex > i
+						&& (flags[i + 1] & InstructionFlags.BranchTarget) == 0)
+					{
+						ConstantFieldWrapper field = classFile.GetFieldref(instructions[i].Arg1).GetField() as ConstantFieldWrapper;
+						if (field != null && field.FieldTypeWrapper == PrimitiveTypeWrapper.BOOLEAN && (bool)field.GetConstantValue())
+						{
+							// We know the branch will always be taken, so we replace the getstatic/ifne by a goto.
+							instructions[i].PatchOpCode(NormalizedByteCode.__goto, instructions[i + 1].TargetIndex);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	private void PatchHardErrorsAndDynamicMemberAccess(TypeWrapper wrapper, MethodWrapper mw)
+	{
+		// Now we do another pass to find "hard error" instructions
+		if(true)
+		{
+			ClassFile.Method.Instruction[] instructions = method.Instructions;
+			for(int i = 0; i < instructions.Length; i++)
+			{
+				if(state[i] != null)
+				{
+					StackState stack = new StackState(state[i]);
+					switch(instructions[i].NormalizedOpCode)
+					{
+						case NormalizedByteCode.__invokeinterface:
+						case NormalizedByteCode.__invokespecial:
+						case NormalizedByteCode.__invokestatic:
+						case NormalizedByteCode.__invokevirtual:
+							PatchInvoke(wrapper, ref instructions[i], stack);
+							break;
+						case NormalizedByteCode.__getfield:
+						case NormalizedByteCode.__putfield:
+						case NormalizedByteCode.__getstatic:
+						case NormalizedByteCode.__putstatic:
+							PatchFieldAccess(wrapper, mw, ref instructions[i], stack);
+							break;
+						case NormalizedByteCode.__ldc:
+							switch(classFile.GetConstantPoolConstantType(instructions[i].Arg1))
+							{
+								case ClassFile.ConstantType.Class:
+								{
+									TypeWrapper tw = classFile.GetConstantPoolClassType(instructions[i].Arg1);
+									if(tw.IsUnloadable)
+									{
+										ConditionalPatchNoClassDefFoundError(ref instructions[i], tw);
+									}
+									break;
+								}
+								case ClassFile.ConstantType.MethodType:
+								{
+									ClassFile.ConstantPoolItemMethodType cpi = classFile.GetConstantPoolConstantMethodType(instructions[i].Arg1);
+									TypeWrapper[] args = cpi.GetArgTypes();
+									TypeWrapper tw = cpi.GetRetType();
+									for(int j = 0; !tw.IsUnloadable && j < args.Length; j++)
+									{
+										tw = args[j];
+									}
+									if(tw.IsUnloadable)
+									{
+										ConditionalPatchNoClassDefFoundError(ref instructions[i], tw);
+									}
+									break;
+								}
+								case ClassFile.ConstantType.MethodHandle:
+									PatchLdcMethodHandle(ref instructions[i]);
+									break;
+							}
+							break;
+						case NormalizedByteCode.__new:
+						{
+							TypeWrapper tw = classFile.GetConstantPoolClassType(instructions[i].Arg1);
+							if(tw.IsUnloadable)
+							{
+								ConditionalPatchNoClassDefFoundError(ref instructions[i], tw);
+							}
+							else if(!tw.IsAccessibleFrom(wrapper))
+							{
+								SetHardError(wrapper.GetClassLoader(), ref instructions[i], HardError.IllegalAccessError, "Try to access class {0} from class {1}", tw.Name, wrapper.Name);
+							}
+							else if(tw.IsAbstract)
+							{
+								SetHardError(wrapper.GetClassLoader(), ref instructions[i], HardError.InstantiationError, "{0}", tw.Name);
+							}
+							break;
+						}
+						case NormalizedByteCode.__multianewarray:
+						case NormalizedByteCode.__anewarray:
+						{
+							TypeWrapper tw = classFile.GetConstantPoolClassType(instructions[i].Arg1);
+							if(tw.IsUnloadable)
+							{
+								ConditionalPatchNoClassDefFoundError(ref instructions[i], tw);
+							}
+							else if(!tw.IsAccessibleFrom(wrapper))
+							{
+								SetHardError(wrapper.GetClassLoader(), ref instructions[i], HardError.IllegalAccessError, "Try to access class {0} from class {1}", tw.Name, wrapper.Name);
+							}
+							break;
+						}
+						case NormalizedByteCode.__checkcast:
+						case NormalizedByteCode.__instanceof:
+						{
+							TypeWrapper tw = classFile.GetConstantPoolClassType(instructions[i].Arg1);
+							if(tw.IsUnloadable)
+							{
+								// If the type is unloadable, we always generate the dynamic code
+								// (regardless of ClassLoaderWrapper.DisableDynamicBinding), because at runtime,
+								// null references should always pass thru without attempting
+								// to load the type (for Sun compatibility).
+							}
+							else if(!tw.IsAccessibleFrom(wrapper))
+							{
+								SetHardError(wrapper.GetClassLoader(), ref instructions[i], HardError.IllegalAccessError, "Try to access class {0} from class {1}", tw.Name, wrapper.Name);
+							}
+							break;
+						}
+						case NormalizedByteCode.__aaload:
+						{
+							stack.PopInt();
+							TypeWrapper tw = stack.PopArrayType();
+							if(tw.IsUnloadable)
+							{
+								ConditionalPatchNoClassDefFoundError(ref instructions[i], tw);
+							}
+							break;
+						}
+						case NormalizedByteCode.__aastore:
+						{
+							stack.PopObjectType();
+							stack.PopInt();
+							TypeWrapper tw = stack.PopArrayType();
+							if(tw.IsUnloadable)
+							{
+								ConditionalPatchNoClassDefFoundError(ref instructions[i], tw);
+							}
+							break;
+						}
+						default:
+							break;
+					}
+				}
+			}
+		}
+	}
+
+	private void PatchLdcMethodHandle(ref ClassFile.Method.Instruction instr)
+	{
+		ClassFile.ConstantPoolItemMethodHandle cpi = classFile.GetConstantPoolConstantMethodHandle(instr.Arg1);
+		if (cpi.GetClassType().IsUnloadable)
+		{
+			ConditionalPatchNoClassDefFoundError(ref instr, cpi.GetClassType());
+		}
+		else if (!cpi.GetClassType().IsAccessibleFrom(wrapper))
+		{
+			SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IllegalAccessError, "tried to access class {0} from class {1}", cpi.Class, wrapper.Name);
+		}
+		else if (cpi.Kind == ClassFile.RefKind.invokeVirtual
+			&& cpi.GetClassType() == CoreClasses.java.lang.invoke.MethodHandle.Wrapper
+			&& (cpi.Name == "invoke" || cpi.Name == "invokeExact"))
+		{
+			// it's allowed to use ldc to create a MethodHandle invoker
+		}
+		else if (cpi.Member == null
+			|| cpi.Member.IsStatic != (cpi.Kind == ClassFile.RefKind.getStatic || cpi.Kind == ClassFile.RefKind.putStatic || cpi.Kind == ClassFile.RefKind.invokeStatic))
+		{
+			HardError err;
+			string msg;
+			switch (cpi.Kind)
+			{
+				case ClassFile.RefKind.getField:
+				case ClassFile.RefKind.getStatic:
+				case ClassFile.RefKind.putField:
+				case ClassFile.RefKind.putStatic:
+					err = HardError.NoSuchFieldError;
+					msg = cpi.Name;
+					break;
+				default:
+					err = HardError.NoSuchMethodError;
+					msg = cpi.Class + "." + cpi.Name + cpi.Signature;
+					break;
+			}
+			SetHardError(wrapper.GetClassLoader(), ref instr, err, msg, cpi.Class, cpi.Name, SigToString(cpi.Signature));
+		}
+		else if (!cpi.Member.IsAccessibleFrom(cpi.GetClassType(), wrapper, cpi.GetClassType()))
+		{
+			if (cpi.Member.IsProtected && wrapper.IsSubTypeOf(cpi.Member.DeclaringType))
+			{
+				// this is allowed, the receiver will be narrowed to current type
+			}
+			else
+			{
+				SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IllegalAccessException, "member is private: {0}.{1}/{2}/{3}, from {4}", cpi.Class, cpi.Name, SigToString(cpi.Signature), cpi.Kind, wrapper.Name);
+			}
+		}
+	}
+
+	private static string SigToString(string sig)
+	{
+		System.Text.StringBuilder sb = new System.Text.StringBuilder();
+		string sep = "";
+		int dims = 0;
+		for (int i = 0; i < sig.Length; i++)
+		{
+			if (sig[i] == '(' || sig[i] == ')')
+			{
+				sb.Append(sig[i]);
+				sep = "";
+				continue;
+			}
+			else if (sig[i] == '[')
+			{
+				dims++;
+				continue;
+			}
+			sb.Append(sep);
+			sep = ",";
+			switch (sig[i])
+			{
+				case 'V':
+					sb.Append("void");
+					break;
+				case 'B':
+					sb.Append("byte");
+					break;
+				case 'Z':
+					sb.Append("boolean");
+					break;
+				case 'S':
+					sb.Append("short");
+					break;
+				case 'C':
+					sb.Append("char");
+					break;
+				case 'I':
+					sb.Append("int");
+					break;
+				case 'J':
+					sb.Append("long");
+					break;
+				case 'F':
+					sb.Append("float");
+					break;
+				case 'D':
+					sb.Append("double");
+					break;
+				case 'L':
+					sb.Append(sig, i + 1, sig.IndexOf(';', i + 1) - (i + 1));
+					i = sig.IndexOf(';', i + 1);
+					break;
+			}
+			for (; dims != 0; dims--)
+			{
+				sb.Append("[]");
+			}
+		}
+		return sb.ToString();
+	}
+
+	internal static InstructionFlags[] ComputePartialReachability(CodeInfo codeInfo, ClassFile.Method.Instruction[] instructions, UntangledExceptionTable exceptions, int initialInstructionIndex, bool skipFaultBlocks)
+	{
+		InstructionFlags[] flags = new InstructionFlags[instructions.Length];
+		flags[initialInstructionIndex] |= InstructionFlags.Reachable;
+		UpdatePartialReachability(flags, codeInfo, instructions, exceptions, skipFaultBlocks);
+		return flags;
+	}
+
+	private static void UpdatePartialReachability(InstructionFlags[] flags, CodeInfo codeInfo, ClassFile.Method.Instruction[] instructions, UntangledExceptionTable exceptions, bool skipFaultBlocks)
+	{
+		bool done = false;
+		while (!done)
+		{
+			done = true;
+			for (int i = 0; i < instructions.Length; i++)
+			{
+				if ((flags[i] & (InstructionFlags.Reachable | InstructionFlags.Processed)) == InstructionFlags.Reachable)
+				{
+					done = false;
+					flags[i] |= InstructionFlags.Processed;
+					// mark the exception handlers reachable from this instruction
+					for (int j = 0; j < exceptions.Length; j++)
+					{
+						if (exceptions[j].startIndex <= i && i < exceptions[j].endIndex)
+						{
+							int idx = exceptions[j].handlerIndex;
+							if (!skipFaultBlocks || !VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(idx, 0)))
+							{
+								flags[idx] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget;
+							}
+						}
+					}
+					MarkSuccessors(instructions, flags, i);
+				}
+			}
+		}
+	}
+
+	private static void MarkSuccessors(ClassFile.Method.Instruction[] code, InstructionFlags[] flags, int index)
+	{
+		switch (ByteCodeMetaData.GetFlowControl(code[index].NormalizedOpCode))
+		{
+			case ByteCodeFlowControl.Switch:
+				{
+					for (int i = 0; i < code[index].SwitchEntryCount; i++)
+					{
+						flags[code[index].GetSwitchTargetIndex(i)] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget;
+					}
+					flags[code[index].DefaultTarget] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget;
+					break;
+				}
+			case ByteCodeFlowControl.Branch:
+				flags[code[index].TargetIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget;
+				break;
+			case ByteCodeFlowControl.CondBranch:
+				flags[code[index].TargetIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget;
+				flags[index + 1] |= InstructionFlags.Reachable;
+				break;
+			case ByteCodeFlowControl.Return:
+			case ByteCodeFlowControl.Throw:
+				break;
+			case ByteCodeFlowControl.Next:
+				flags[index + 1] |= InstructionFlags.Reachable;
+				break;
+			default:
+				throw new InvalidOperationException();
+		}
+	}
+
+	internal static UntangledExceptionTable UntangleExceptionBlocks(ClassFile classFile, ClassFile.Method method)
+	{
+		ClassFile.Method.Instruction[] instructions = method.Instructions;
+		ExceptionTableEntry[] exceptionTable = method.ExceptionTable;
+		List ar = new List(exceptionTable);
+
+		// This optimization removes the recursive exception handlers that Java compiler place around
+		// the exit of a synchronization block to be "safe" in the face of asynchronous exceptions.
+		// (see http://weblog.ikvm.net/PermaLink.aspx?guid=3af9548e-4905-4557-8809-65a205ce2cd6)
+		// We can safely remove them since the code we generate for this construct isn't async safe anyway,
+		// but there is another reason why this optimization may be slightly controversial. In some
+		// pathological cases it can cause observable differences, where the Sun JVM would spin in an
+		// infinite loop, but we will throw an exception. However, the perf benefit is large enough to
+		// warrant this "incompatibility".
+		// Note that there is also code in the exception handler handling code that detects these bytecode
+		// sequences to try to compile them into a fault block, instead of an exception handler.
+		for (int i = 0; i < ar.Count; i++)
+		{
+			ExceptionTableEntry ei = ar[i];
+			if (ei.startIndex == ei.handlerIndex && ei.catch_type == 0)
+			{
+				int index = ei.startIndex;
+				if (index + 2 < instructions.Length
+					&& ei.endIndex == index + 2
+					&& instructions[index].NormalizedOpCode == NormalizedByteCode.__aload
+					&& instructions[index + 1].NormalizedOpCode == NormalizedByteCode.__monitorexit
+					&& instructions[index + 2].NormalizedOpCode == NormalizedByteCode.__athrow)
+				{
+					// this is the async exception guard that Jikes and the Eclipse Java Compiler produce
+					ar.RemoveAt(i);
+					i--;
+				}
+				else if (index + 4 < instructions.Length
+					&& ei.endIndex == index + 3
+					&& instructions[index].NormalizedOpCode == NormalizedByteCode.__astore
+					&& instructions[index + 1].NormalizedOpCode == NormalizedByteCode.__aload
+					&& instructions[index + 2].NormalizedOpCode == NormalizedByteCode.__monitorexit
+					&& instructions[index + 3].NormalizedOpCode == NormalizedByteCode.__aload
+					&& instructions[index + 4].NormalizedOpCode == NormalizedByteCode.__athrow
+					&& instructions[index].NormalizedArg1 == instructions[index + 3].NormalizedArg1)
+				{
+					// this is the async exception guard that javac produces
+					ar.RemoveAt(i);
+					i--;
+				}
+				else if (index + 1 < instructions.Length
+					&& ei.endIndex == index + 1
+					&& instructions[index].NormalizedOpCode == NormalizedByteCode.__astore)
+				{
+					// this is the finally guard that javac produces
+					ar.RemoveAt(i);
+					i--;
+				}
+			}
+		}
+
+		// Modern versions of javac split try blocks when the try block contains a return statement.
+		// Here we merge these exception blocks again, because it allows us to generate more efficient code.
+		for (int i = 0; i < ar.Count - 1; i++)
+		{
+			if (ar[i].endIndex + 1 == ar[i + 1].startIndex
+				&& ar[i].handlerIndex == ar[i + 1].handlerIndex
+				&& ar[i].catch_type == ar[i + 1].catch_type
+				&& IsReturn(instructions[ar[i].endIndex].NormalizedOpCode))
+			{
+				ar[i] = new ExceptionTableEntry(ar[i].startIndex, ar[i + 1].endIndex, ar[i].handlerIndex, ar[i].catch_type, ar[i].ordinal);
+				ar.RemoveAt(i + 1);
+				i--;
+			}
+		}
+
+	restart:
+		for (int i = 0; i < ar.Count; i++)
+		{
+			ExceptionTableEntry ei = ar[i];
+			for (int j = 0; j < ar.Count; j++)
+			{
+				ExceptionTableEntry ej = ar[j];
+				if (ei.startIndex <= ej.startIndex && ej.startIndex < ei.endIndex)
+				{
+					// 0006/test.j
+					if (ej.endIndex > ei.endIndex)
+					{
+						ExceptionTableEntry emi = new ExceptionTableEntry(ej.startIndex, ei.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal);
+						ExceptionTableEntry emj = new ExceptionTableEntry(ej.startIndex, ei.endIndex, ej.handlerIndex, ej.catch_type, ej.ordinal);
+						ei = new ExceptionTableEntry(ei.startIndex, emi.startIndex, ei.handlerIndex, ei.catch_type, ei.ordinal);
+						ej = new ExceptionTableEntry(emj.endIndex, ej.endIndex, ej.handlerIndex, ej.catch_type, ej.ordinal);
+						ar[i] = ei;
+						ar[j] = ej;
+						ar.Insert(j, emj);
+						ar.Insert(i + 1, emi);
+						goto restart;
+					}
+					// 0007/test.j
+					else if (j > i && ej.endIndex < ei.endIndex)
+					{
+						ExceptionTableEntry emi = new ExceptionTableEntry(ej.startIndex, ej.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal);
+						ExceptionTableEntry eei = new ExceptionTableEntry(ej.endIndex, ei.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal);
+						ei = new ExceptionTableEntry(ei.startIndex, emi.startIndex, ei.handlerIndex, ei.catch_type, ei.ordinal);
+						ar[i] = ei;
+						ar.Insert(i + 1, eei);
+						ar.Insert(i + 1, emi);
+						goto restart;
+					}
+				}
+			}
+		}
+	// Split try blocks at branch targets (branches from outside the try block)
+	restart_split:
+		for (int i = 0; i < ar.Count; i++)
+		{
+			ExceptionTableEntry ei = ar[i];
+			int start = ei.startIndex;
+			int end = ei.endIndex;
+			for (int j = 0; j < instructions.Length; j++)
+			{
+				if (j < start || j >= end)
+				{
+					switch (instructions[j].NormalizedOpCode)
+					{
+						case NormalizedByteCode.__tableswitch:
+						case NormalizedByteCode.__lookupswitch:
+							// start at -1 to have an opportunity to handle the default offset
+							for (int k = -1; k < instructions[j].SwitchEntryCount; k++)
+							{
+								int targetIndex = (k == -1 ? instructions[j].DefaultTarget : instructions[j].GetSwitchTargetIndex(k));
+								if (ei.startIndex < targetIndex && targetIndex < ei.endIndex)
+								{
+									ExceptionTableEntry en = new ExceptionTableEntry(targetIndex, ei.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal);
+									ei = new ExceptionTableEntry(ei.startIndex, targetIndex, ei.handlerIndex, ei.catch_type, ei.ordinal);
+									ar[i] = ei;
+									ar.Insert(i + 1, en);
+									goto restart_split;
+								}
+							}
+							break;
+						case NormalizedByteCode.__ifeq:
+						case NormalizedByteCode.__ifne:
+						case NormalizedByteCode.__iflt:
+						case NormalizedByteCode.__ifge:
+						case NormalizedByteCode.__ifgt:
+						case NormalizedByteCode.__ifle:
+						case NormalizedByteCode.__if_icmpeq:
+						case NormalizedByteCode.__if_icmpne:
+						case NormalizedByteCode.__if_icmplt:
+						case NormalizedByteCode.__if_icmpge:
+						case NormalizedByteCode.__if_icmpgt:
+						case NormalizedByteCode.__if_icmple:
+						case NormalizedByteCode.__if_acmpeq:
+						case NormalizedByteCode.__if_acmpne:
+						case NormalizedByteCode.__ifnull:
+						case NormalizedByteCode.__ifnonnull:
+						case NormalizedByteCode.__goto:
+							{
+								int targetIndex = instructions[j].Arg1;
+								if (ei.startIndex < targetIndex && targetIndex < ei.endIndex)
+								{
+									ExceptionTableEntry en = new ExceptionTableEntry(targetIndex, ei.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal);
+									ei = new ExceptionTableEntry(ei.startIndex, targetIndex, ei.handlerIndex, ei.catch_type, ei.ordinal);
+									ar[i] = ei;
+									ar.Insert(i + 1, en);
+									goto restart_split;
+								}
+								break;
+							}
+					}
+				}
+			}
+		}
+		// exception handlers are also a kind of jump, so we need to split try blocks around handlers as well
+		for (int i = 0; i < ar.Count; i++)
+		{
+			ExceptionTableEntry ei = ar[i];
+			for (int j = 0; j < ar.Count; j++)
+			{
+				ExceptionTableEntry ej = ar[j];
+				if (ei.startIndex < ej.handlerIndex && ej.handlerIndex < ei.endIndex)
+				{
+					ExceptionTableEntry en = new ExceptionTableEntry(ej.handlerIndex, ei.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal);
+					ei = new ExceptionTableEntry(ei.startIndex, ej.handlerIndex, ei.handlerIndex, ei.catch_type, ei.ordinal);
+					ar[i] = ei;
+					ar.Insert(i + 1, en);
+					goto restart_split;
+				}
+			}
+		}
+		// filter out zero length try blocks
+		for (int i = 0; i < ar.Count; i++)
+		{
+			ExceptionTableEntry ei = ar[i];
+			if (ei.startIndex == ei.endIndex)
+			{
+				ar.RemoveAt(i);
+				i--;
+			}
+			else
+			{
+				// exception blocks that only contain harmless instructions (i.e. instructions that will *never* throw an exception)
+				// are also filtered out (to improve the quality of the generated code)
+				TypeWrapper exceptionType = ei.catch_type == 0 ? CoreClasses.java.lang.Throwable.Wrapper : classFile.GetConstantPoolClassType(ei.catch_type);
+				if (exceptionType.IsUnloadable)
+				{
+					// we can't remove handlers for unloadable types
+				}
+				else if (java_lang_ThreadDeath.IsAssignableTo(exceptionType))
+				{
+					// We only remove exception handlers that could catch ThreadDeath in limited cases, because it can be thrown
+					// asynchronously (and thus appear on any instruction). This is particularly important to ensure that
+					// we run finally blocks when a thread is killed.
+					// Note that even so, we aren't remotely async exception safe.
+					int start = ei.startIndex;
+					int end = ei.endIndex;
+					for (int j = start; j < end; j++)
+					{
+						switch (instructions[j].NormalizedOpCode)
+						{
+							case NormalizedByteCode.__aload:
+							case NormalizedByteCode.__iload:
+							case NormalizedByteCode.__lload:
+							case NormalizedByteCode.__fload:
+							case NormalizedByteCode.__dload:
+							case NormalizedByteCode.__astore:
+							case NormalizedByteCode.__istore:
+							case NormalizedByteCode.__lstore:
+							case NormalizedByteCode.__fstore:
+							case NormalizedByteCode.__dstore:
+								break;
+							case NormalizedByteCode.__dup:
+							case NormalizedByteCode.__dup_x1:
+							case NormalizedByteCode.__dup_x2:
+							case NormalizedByteCode.__dup2:
+							case NormalizedByteCode.__dup2_x1:
+							case NormalizedByteCode.__dup2_x2:
+							case NormalizedByteCode.__pop:
+							case NormalizedByteCode.__pop2:
+								break;
+							case NormalizedByteCode.__return:
+							case NormalizedByteCode.__areturn:
+							case NormalizedByteCode.__ireturn:
+							case NormalizedByteCode.__lreturn:
+							case NormalizedByteCode.__freturn:
+							case NormalizedByteCode.__dreturn:
+								break;
+							case NormalizedByteCode.__goto:
+								// if there is a branch that stays inside the block, we should keep the block
+								if (start <= instructions[j].TargetIndex && instructions[j].TargetIndex < end)
+									goto next;
+								break;
+							default:
+								goto next;
+						}
+					}
+					ar.RemoveAt(i);
+					i--;
+				}
+				else
+				{
+					int start = ei.startIndex;
+					int end = ei.endIndex;
+					for (int j = start; j < end; j++)
+					{
+						if (ByteCodeMetaData.CanThrowException(instructions[j].NormalizedOpCode))
+						{
+							goto next;
+						}
+					}
+					ar.RemoveAt(i);
+					i--;
+				}
+			}
+		next: ;
+		}
+
+		ExceptionTableEntry[] exceptions = ar.ToArray();
+		Array.Sort(exceptions, new ExceptionSorter());
+
+		return new UntangledExceptionTable(exceptions);
+	}
+
+	private static bool IsReturn(NormalizedByteCode bc)
+	{
+		return bc == NormalizedByteCode.__return
+			|| bc == NormalizedByteCode.__areturn
+			|| bc == NormalizedByteCode.__dreturn
+			|| bc == NormalizedByteCode.__ireturn
+			|| bc == NormalizedByteCode.__freturn
+			|| bc == NormalizedByteCode.__lreturn;
+	}
+
+	private static bool AnalyzePotentialFaultBlocks(CodeInfo codeInfo, ClassFile.Method method, UntangledExceptionTable exceptions)
+	{
+		ClassFile.Method.Instruction[] code = method.Instructions;
+		bool changed = false;
+		bool done = false;
+		while (!done)
+		{
+			done = true;
+			Stack stack = new Stack();
+			ExceptionTableEntry current = new ExceptionTableEntry(0, code.Length, -1, ushort.MaxValue, -1);
+			stack.Push(current);
+			for (int i = 0; i < exceptions.Length; i++)
+			{
+				while (exceptions[i].startIndex >= current.endIndex)
+				{
+					current = stack.Pop();
+				}
+				Debug.Assert(exceptions[i].startIndex >= current.startIndex && exceptions[i].endIndex <= current.endIndex);
+				if (exceptions[i].catch_type == 0
+					&& codeInfo.HasState(exceptions[i].handlerIndex)
+					&& VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(exceptions[i].handlerIndex, 0)))
+				{
+					InstructionFlags[] flags = MethodAnalyzer.ComputePartialReachability(codeInfo, method.Instructions, exceptions, exceptions[i].handlerIndex, true);
+					for (int j = 0; j < code.Length; j++)
+					{
+						if ((flags[j] & InstructionFlags.Reachable) != 0)
+						{
+							switch (code[j].NormalizedOpCode)
+							{
+								case NormalizedByteCode.__return:
+								case NormalizedByteCode.__areturn:
+								case NormalizedByteCode.__ireturn:
+								case NormalizedByteCode.__lreturn:
+								case NormalizedByteCode.__freturn:
+								case NormalizedByteCode.__dreturn:
+									goto not_fault_block;
+								case NormalizedByteCode.__athrow:
+									for (int k = i + 1; k < exceptions.Length; k++)
+									{
+										if (exceptions[k].startIndex <= j && j < exceptions[k].endIndex)
+										{
+											goto not_fault_block;
+										}
+									}
+									if (VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(j, 0))
+										&& codeInfo.GetRawStackTypeWrapper(j, 0) != codeInfo.GetRawStackTypeWrapper(exceptions[i].handlerIndex, 0))
+									{
+										goto not_fault_block;
+									}
+									break;
+							}
+							if (j < current.startIndex || j >= current.endIndex)
+							{
+								goto not_fault_block;
+							}
+							else if (exceptions[i].startIndex <= j && j < exceptions[i].endIndex)
+							{
+								goto not_fault_block;
+							}
+							else
+							{
+								continue;
+							}
+						not_fault_block:
+							VerifierTypeWrapper.ClearFaultBlockException(codeInfo.GetRawStackTypeWrapper(exceptions[i].handlerIndex, 0));
+							done = false;
+							changed = true;
+							break;
+						}
+					}
+				}
+				stack.Push(current);
+				current = exceptions[i];
+			}
+		}
+		return changed;
+	}
+
+	private static void ConvertFinallyBlocks(CodeInfo codeInfo, ClassFile.Method method, UntangledExceptionTable exceptions)
+	{
+		ClassFile.Method.Instruction[] code = method.Instructions;
+		InstructionFlags[] flags = ComputePartialReachability(codeInfo, code, exceptions, 0, false);
+		for (int i = 0; i < exceptions.Length; i++)
+		{
+			if (exceptions[i].catch_type == 0
+				&& codeInfo.HasState(exceptions[i].handlerIndex)
+				&& VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(exceptions[i].handlerIndex, 0)))
+			{
+				int exit;
+				if (IsSynchronizedBlockHandler(code, exceptions[i].handlerIndex)
+					&& exceptions[i].endIndex - 2 >= exceptions[i].startIndex
+					&& TryFindSingleTryBlockExit(code, flags, exceptions, new ExceptionTableEntry(exceptions[i].startIndex, exceptions[i].endIndex - 2, exceptions[i].handlerIndex, 0, exceptions[i].ordinal), i, out exit)
+					&& exit == exceptions[i].endIndex - 2
+					&& (flags[exit + 1] & InstructionFlags.BranchTarget) == 0
+					&& MatchInstructions(code, exit, exceptions[i].handlerIndex + 1)
+					&& MatchInstructions(code, exit + 1, exceptions[i].handlerIndex + 2)
+					&& MatchExceptionCoverage(exceptions, i, exceptions[i].handlerIndex + 1, exceptions[i].handlerIndex + 3, exit, exit + 2)
+					&& exceptions[i].handlerIndex <= ushort.MaxValue)
+				{
+					code[exit].PatchOpCode(NormalizedByteCode.__goto_finally, exceptions[i].endIndex, (short)exceptions[i].handlerIndex);
+					exceptions.SetFinally(i);
+				}
+				else if (TryFindSingleTryBlockExit(code, flags, exceptions, exceptions[i], i, out exit)
+					// the stack must be empty
+					&& codeInfo.GetStackHeight(exit) == 0
+					// the exit code must not be reachable (except from within the try-block),
+					// because we're going to patch it to jump around the exit code
+					&& !IsReachableFromOutsideTryBlock(codeInfo, code, exceptions, exceptions[i], exit))
+				{
+					int exitHandlerEnd;
+					int faultHandlerEnd;
+					if (MatchFinallyBlock(codeInfo, code, exceptions, exceptions[i].handlerIndex, exit, out exitHandlerEnd, out faultHandlerEnd))
+					{
+						if (exit != exitHandlerEnd
+							&& codeInfo.GetStackHeight(exitHandlerEnd) == 0
+							&& MatchExceptionCoverage(exceptions, -1, exceptions[i].handlerIndex, faultHandlerEnd, exit, exitHandlerEnd))
+						{
+							// We use Arg2 (which is a short) to store the handler in the __goto_finally pseudo-opcode,
+							// so we can only do that if handlerIndex fits in a short (note that we can use the sign bit too).
+							if (exceptions[i].handlerIndex <= ushort.MaxValue)
+							{
+								code[exit].PatchOpCode(NormalizedByteCode.__goto_finally, exitHandlerEnd, (short)exceptions[i].handlerIndex);
+								exceptions.SetFinally(i);
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	private static bool IsSynchronizedBlockHandler(ClassFile.Method.Instruction[] code, int index)
+	{
+		return code[index].NormalizedOpCode == NormalizedByteCode.__astore
+			&& code[index + 1].NormalizedOpCode == NormalizedByteCode.__aload
+			&& code[index + 2].NormalizedOpCode == NormalizedByteCode.__monitorexit
+			&& code[index + 3].NormalizedOpCode == NormalizedByteCode.__aload && code[index + 3].Arg1 == code[index].Arg1
+			&& code[index + 4].NormalizedOpCode == NormalizedByteCode.__athrow;
+	}
+
+	private static bool MatchExceptionCoverage(UntangledExceptionTable exceptions, int skipException, int startFault, int endFault, int startExit, int endExit)
+	{
+		for (int j = 0; j < exceptions.Length; j++)
+		{
+			if (j != skipException && ExceptionCovers(exceptions[j], startFault, endFault) != ExceptionCovers(exceptions[j], startExit, endExit))
+			{
+				return false;
+			}
+		}
+		return true;
+	}
+
+	private static bool ExceptionCovers(ExceptionTableEntry exception, int start, int end)
+	{
+		return exception.startIndex < end && exception.endIndex > start;
+	}
+
+	private static bool MatchFinallyBlock(CodeInfo codeInfo, ClassFile.Method.Instruction[] code, UntangledExceptionTable exceptions, int faultHandler, int exitHandler, out int exitHandlerEnd, out int faultHandlerEnd)
+	{
+		exitHandlerEnd = -1;
+		faultHandlerEnd = -1;
+		if (code[faultHandler].NormalizedOpCode != NormalizedByteCode.__astore)
+		{
+			return false;
+		}
+		int startFault = faultHandler;
+		int faultLocal = code[faultHandler++].NormalizedArg1;
+		for (; ; )
+		{
+			if (code[faultHandler].NormalizedOpCode == NormalizedByteCode.__aload
+				&& code[faultHandler].NormalizedArg1 == faultLocal
+				&& code[faultHandler + 1].NormalizedOpCode == NormalizedByteCode.__athrow)
+			{
+				// make sure that instructions that we haven't covered aren't reachable
+				InstructionFlags[] flags = ComputePartialReachability(codeInfo, code, exceptions, startFault, false);
+				for (int i = 0; i < flags.Length; i++)
+				{
+					if ((i < startFault || i > faultHandler + 1) && (flags[i] & InstructionFlags.Reachable) != 0)
+					{
+						return false;
+					}
+				}
+				exitHandlerEnd = exitHandler;
+				faultHandlerEnd = faultHandler;
+				return true;
+			}
+			if (!MatchInstructions(code, faultHandler, exitHandler))
+			{
+				return false;
+			}
+			faultHandler++;
+			exitHandler++;
+		}
+	}
+
+	private static bool MatchInstructions(ClassFile.Method.Instruction[] code, int i, int j)
+	{
+		if (code[i].NormalizedOpCode != code[j].NormalizedOpCode)
+		{
+			return false;
+		}
+		switch (ByteCodeMetaData.GetFlowControl(code[i].NormalizedOpCode))
+		{
+			case ByteCodeFlowControl.Branch:
+			case ByteCodeFlowControl.CondBranch:
+				if (code[i].Arg1 - i != code[j].Arg1 - j)
+				{
+					return false;
+				}
+				break;
+			case ByteCodeFlowControl.Switch:
+				if (code[i].SwitchEntryCount != code[j].SwitchEntryCount)
+				{
+					return false;
+				}
+				for (int k = 0; k < code[i].SwitchEntryCount; k++)
+				{
+					if (code[i].GetSwitchTargetIndex(k) != code[j].GetSwitchTargetIndex(k))
+					{
+						return false;
+					}
+				}
+				if (code[i].DefaultTarget != code[j].DefaultTarget)
+				{
+					return false;
+				}
+				break;
+			default:
+				if (code[i].Arg1 != code[j].Arg1)
+				{
+					return false;
+				}
+				if (code[i].Arg2 != code[j].Arg2)
+				{
+					return false;
+				}
+				break;
+		}
+		return true;
+	}
+
+	private static bool IsReachableFromOutsideTryBlock(CodeInfo codeInfo, ClassFile.Method.Instruction[] code, UntangledExceptionTable exceptions, ExceptionTableEntry tryBlock, int instructionIndex)
+	{
+		InstructionFlags[] flags = new InstructionFlags[code.Length];
+		flags[0] |= InstructionFlags.Reachable;
+		// We mark the first instruction of the try-block as already processed, so that UpdatePartialReachability will skip the try-block.
+		// Note that we can do this, because it is not possible to jump into the middle of a try-block (after the exceptions have been untangled).
+		flags[tryBlock.startIndex] = InstructionFlags.Processed;
+		// We mark the successor instructions of the instruction we're examinining as reachable,
+		// to figure out if the code following the handler somehow branches back to it.
+		MarkSuccessors(code, flags, instructionIndex);
+		UpdatePartialReachability(flags, codeInfo, code, exceptions, false);
+		return (flags[instructionIndex] & InstructionFlags.Reachable) != 0;
+	}
+
+	private static bool TryFindSingleTryBlockExit(ClassFile.Method.Instruction[] code, InstructionFlags[] flags, UntangledExceptionTable exceptions, ExceptionTableEntry exception, int exceptionIndex, out int exit)
+	{
+		exit = -1;
+		bool fail = false;
+		bool nextIsReachable = false;
+		for (int i = exception.startIndex; !fail && i < exception.endIndex; i++)
+		{
+			if ((flags[i] & InstructionFlags.Reachable) != 0)
+			{
+				nextIsReachable = false;
+				for (int j = 0; j < exceptions.Length; j++)
+				{
+					if (j != exceptionIndex && exceptions[j].startIndex >= exception.startIndex && exception.endIndex <= exceptions[j].endIndex)
+					{
+						UpdateTryBlockExit(exception, exceptions[j].handlerIndex, ref exit, ref fail);
+					}
+				}
+				switch (ByteCodeMetaData.GetFlowControl(code[i].NormalizedOpCode))
+				{
+					case ByteCodeFlowControl.Switch:
+						{
+							for (int j = 0; j < code[i].SwitchEntryCount; j++)
+							{
+								UpdateTryBlockExit(exception, code[i].GetSwitchTargetIndex(j), ref exit, ref fail);
+							}
+							UpdateTryBlockExit(exception, code[i].DefaultTarget, ref exit, ref fail);
+							break;
+						}
+					case ByteCodeFlowControl.Branch:
+						UpdateTryBlockExit(exception, code[i].TargetIndex, ref exit, ref fail);
+						break;
+					case ByteCodeFlowControl.CondBranch:
+						UpdateTryBlockExit(exception, code[i].TargetIndex, ref exit, ref fail);
+						nextIsReachable = true;
+						break;
+					case ByteCodeFlowControl.Return:
+						fail = true;
+						break;
+					case ByteCodeFlowControl.Throw:
+						break;
+					case ByteCodeFlowControl.Next:
+						nextIsReachable = true;
+						break;
+					default:
+						throw new InvalidOperationException();
+				}
+			}
+		}
+		if (nextIsReachable)
+		{
+			UpdateTryBlockExit(exception, exception.endIndex, ref exit, ref fail);
+		}
+		return !fail && exit != -1;
+	}
+
+	private static void UpdateTryBlockExit(ExceptionTableEntry exception, int targetIndex, ref int exitIndex, ref bool fail)
+	{
+		if (exception.startIndex <= targetIndex && targetIndex < exception.endIndex)
+		{
+			// branch stays inside try block
+		}
+		else if (exitIndex == -1)
+		{
+			exitIndex = targetIndex;
+		}
+		else if (exitIndex != targetIndex)
+		{
+			fail = true;
+		}
+	}
+
+	private void ConditionalPatchNoClassDefFoundError(ref ClassFile.Method.Instruction instruction, TypeWrapper tw)
+	{
+		ClassLoaderWrapper loader = wrapper.GetClassLoader();
+		if (loader.DisableDynamicBinding)
+		{
+			SetHardError(loader, ref instruction, HardError.NoClassDefFoundError, "{0}", tw.Name);
+		}
+	}
+
+	private void SetHardError(ClassLoaderWrapper classLoader, ref ClassFile.Method.Instruction instruction, HardError hardError, string message, params object[] args)
+	{
+		string text = string.Format(message, args);
+#if STATIC_COMPILER
+		Message msg;
+		switch (hardError)
+		{
+			case HardError.NoClassDefFoundError:
+				msg = Message.EmittedNoClassDefFoundError;
+				break;
+			case HardError.IllegalAccessError:
+				msg = Message.EmittedIllegalAccessError;
+				break;
+			case HardError.InstantiationError:
+				msg = Message.EmittedIllegalAccessError;
+				break;
+			case HardError.IncompatibleClassChangeError:
+			case HardError.IllegalAccessException:
+				msg = Message.EmittedIncompatibleClassChangeError;
+				break;
+			case HardError.NoSuchFieldError:
+				msg = Message.EmittedNoSuchFieldError;
+				break;
+			case HardError.AbstractMethodError:
+				msg = Message.EmittedAbstractMethodError;
+				break;
+			case HardError.NoSuchMethodError:
+				msg = Message.EmittedNoSuchMethodError;
+				break;
+			case HardError.LinkageError:
+				msg = Message.EmittedLinkageError;
+				break;
+			default:
+				throw new InvalidOperationException();
+		}
+		classLoader.IssueMessage(msg, classFile.Name + "." + method.Name + method.Signature, text);
+#endif
+		instruction.SetHardError(hardError, AllocErrorMessage(text));
+	}
+
+	private void PatchInvoke(TypeWrapper wrapper, ref ClassFile.Method.Instruction instr, StackState stack)
+	{
+		ClassFile.ConstantPoolItemMI cpi = GetMethodref(instr.Arg1);
+		NormalizedByteCode invoke = instr.NormalizedOpCode;
+		bool isnew = false;
+		TypeWrapper thisType;
+		if (invoke == NormalizedByteCode.__invokevirtual
+			&& cpi.Class == "java.lang.invoke.MethodHandle"
+			&& (cpi.Name == "invoke" || cpi.Name == "invokeExact" || cpi.Name == "invokeBasic"))
+		{
+			if (cpi.GetArgTypes().Length > 127 && MethodHandleUtil.SlotCount(cpi.GetArgTypes()) > 254)
+			{
+				instr.SetHardError(HardError.LinkageError, AllocErrorMessage("bad parameter count"));
+				return;
+			}
+			instr.PatchOpCode(NormalizedByteCode.__methodhandle_invoke);
+			return;
+		}
+		else if (invoke == NormalizedByteCode.__invokestatic
+			&& cpi.Class == "java.lang.invoke.MethodHandle"
+			&& (cpi.Name == "linkToVirtual" || cpi.Name == "linkToStatic" || cpi.Name == "linkToSpecial" || cpi.Name == "linkToInterface")
+			&& CoreClasses.java.lang.invoke.MethodHandle.Wrapper.IsPackageAccessibleFrom(wrapper))
+		{
+			instr.PatchOpCode(NormalizedByteCode.__methodhandle_link);
+			return;
+		}
+		else if (invoke == NormalizedByteCode.__invokestatic)
+		{
+			thisType = null;
+		}
+		else
+		{
+			TypeWrapper[] args = cpi.GetArgTypes();
+			for (int j = args.Length - 1; j >= 0; j--)
+			{
+				stack.PopType(args[j]);
+			}
+			thisType = SigTypeToClassName(stack.PeekType(), cpi.GetClassType(), wrapper);
+			if(ReferenceEquals(cpi.Name, StringConstants.INIT))
+			{
+				TypeWrapper type = stack.PopType();
+				isnew = VerifierTypeWrapper.IsNew(type);
+			}
+		}
+
+		if(cpi.GetClassType().IsUnloadable)
+		{
+			if(wrapper.GetClassLoader().DisableDynamicBinding)
+			{
+				SetHardError(wrapper.GetClassLoader(), ref instr, HardError.NoClassDefFoundError, "{0}", cpi.GetClassType().Name);
+			}
+			else
+			{
+				switch(invoke)
+				{
+					case NormalizedByteCode.__invokeinterface:
+						instr.PatchOpCode(NormalizedByteCode.__dynamic_invokeinterface);
+						break;
+					case NormalizedByteCode.__invokestatic:
+						instr.PatchOpCode(NormalizedByteCode.__dynamic_invokestatic);
+						break;
+					case NormalizedByteCode.__invokevirtual:
+						instr.PatchOpCode(NormalizedByteCode.__dynamic_invokevirtual);
+						break;
+					case NormalizedByteCode.__invokespecial:
+						if(isnew)
+						{
+							instr.PatchOpCode(NormalizedByteCode.__dynamic_invokespecial);
+						}
+						else
+						{
+							throw new VerifyError("Invokespecial cannot call subclass methods");
+						}
+						break;
+					default:
+						throw new InvalidOperationException();
+				}
+			}
+		}
+		else if(invoke == NormalizedByteCode.__invokeinterface && !cpi.GetClassType().IsInterface)
+		{
+			SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IncompatibleClassChangeError, "invokeinterface on non-interface");
+		}
+		else if(cpi.GetClassType().IsInterface && invoke != NormalizedByteCode.__invokeinterface && ((invoke != NormalizedByteCode.__invokestatic && invoke != NormalizedByteCode.__invokespecial) || classFile.MajorVersion < 52))
+		{
+			SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IncompatibleClassChangeError,
+				classFile.MajorVersion < 52
+					? "interface method must be invoked using invokeinterface"
+					: "interface method must be invoked using invokeinterface, invokespecial or invokestatic");
+		}
+		else
+		{
+			MethodWrapper targetMethod = invoke == NormalizedByteCode.__invokespecial ? cpi.GetMethodForInvokespecial() : cpi.GetMethod();
+			if(targetMethod != null)
+			{
+				string errmsg = CheckLoaderConstraints(cpi, targetMethod);
+				if(errmsg != null)
+				{
+					SetHardError(wrapper.GetClassLoader(), ref instr, HardError.LinkageError, "{0}", errmsg);
+				}
+				else if(targetMethod.IsStatic == (invoke == NormalizedByteCode.__invokestatic))
+				{
+					if(targetMethod.IsAbstract && invoke == NormalizedByteCode.__invokespecial && (targetMethod.GetMethod() == null || targetMethod.GetMethod().IsAbstract))
+					{
+						SetHardError(wrapper.GetClassLoader(), ref instr, HardError.AbstractMethodError, "{0}.{1}{2}", cpi.Class, cpi.Name, cpi.Signature);
+					}
+					else if(invoke == NormalizedByteCode.__invokeinterface && targetMethod.IsPrivate)
+					{
+						SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IncompatibleClassChangeError, "private interface method requires invokespecial, not invokeinterface: method {0}.{1}{2}", cpi.Class, cpi.Name, cpi.Signature);
+					}
+					else if(targetMethod.IsAccessibleFrom(cpi.GetClassType(), wrapper, thisType))
+					{
+						return;
+					}
+					else if(host != null && targetMethod.IsAccessibleFrom(cpi.GetClassType(), host, thisType))
+					{
+						switch (invoke)
+						{
+							case NormalizedByteCode.__invokespecial:
+								instr.PatchOpCode(NormalizedByteCode.__privileged_invokespecial);
+								break;
+							case NormalizedByteCode.__invokestatic:
+								instr.PatchOpCode(NormalizedByteCode.__privileged_invokestatic);
+								break;
+							case NormalizedByteCode.__invokevirtual:
+								instr.PatchOpCode(NormalizedByteCode.__privileged_invokevirtual);
+								break;
+							default:
+								throw new InvalidOperationException();
+						}
+						return;
+					}
+					else
+					{
+						// NOTE special case for incorrect invocation of Object.clone(), because this could mean
+						// we're calling clone() on an array
+						// (bug in javac, see http://developer.java.sun.com/developer/bugParade/bugs/4329886.html)
+						if(cpi.GetClassType() == CoreClasses.java.lang.Object.Wrapper
+							&& thisType.IsArray
+							&& ReferenceEquals(cpi.Name, StringConstants.CLONE))
+						{
+							// Patch the instruction, so that the compiler doesn't need to do this test again.
+							instr.PatchOpCode(NormalizedByteCode.__clone_array);
+							return;
+						}
+						SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IllegalAccessError, "tried to access method {0}.{1}{2} from class {3}", ToSlash(targetMethod.DeclaringType.Name), cpi.Name, ToSlash(cpi.Signature), ToSlash(wrapper.Name));
+					}
+				}
+				else
+				{
+					SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IncompatibleClassChangeError, "static call to non-static method (or v.v.)");
+				}
+			}
+			else
+			{
+				SetHardError(wrapper.GetClassLoader(), ref instr, HardError.NoSuchMethodError, "{0}.{1}{2}", cpi.Class, cpi.Name, cpi.Signature);
+			}
+		}
+	}
+
+	private static string ToSlash(string str)
+	{
+		return str.Replace('.', '/');
+	}
+
+	private void PatchFieldAccess(TypeWrapper wrapper, MethodWrapper mw, ref ClassFile.Method.Instruction instr, StackState stack)
+	{
+		ClassFile.ConstantPoolItemFieldref cpi = classFile.GetFieldref(instr.Arg1);
+		bool isStatic;
+		bool write;
+		TypeWrapper thisType;
+		switch(instr.NormalizedOpCode)
+		{
+			case NormalizedByteCode.__getfield:
+				isStatic = false;
+				write = false;
+				thisType = SigTypeToClassName(stack.PopObjectType(GetFieldref(instr.Arg1).GetClassType()), cpi.GetClassType(), wrapper);
+				break;
+			case NormalizedByteCode.__putfield:
+				stack.PopType(GetFieldref(instr.Arg1).GetFieldType());
+				isStatic = false;
+				write = true;
+				// putfield is allowed to access the unintialized this
+				if(stack.PeekType() == VerifierTypeWrapper.UninitializedThis
+					&& wrapper.IsAssignableTo(GetFieldref(instr.Arg1).GetClassType()))
+				{
+					thisType = wrapper;
+				}
+				else
+				{
+					thisType = SigTypeToClassName(stack.PopObjectType(GetFieldref(instr.Arg1).GetClassType()), cpi.GetClassType(), wrapper);
+				}
+				break;
+			case NormalizedByteCode.__getstatic:
+				isStatic = true;
+				write = false;
+				thisType = null;
+				break;
+			case NormalizedByteCode.__putstatic:
+				// special support for when we're being called from IsSideEffectFreeStaticInitializer
+				if(mw == null)
+				{
+					switch(GetFieldref(instr.Arg1).Signature[0])
+					{
+						case 'B':
+						case 'Z':
+						case 'C':
+						case 'S':
+						case 'I':
+							stack.PopInt();
+							break;
+						case 'F':
+							stack.PopFloat();
+							break;
+						case 'D':
+							stack.PopDouble();
+							break;
+						case 'J':
+							stack.PopLong();
+							break;
+						case 'L':
+						case '[':
+							if(stack.PopAnyType() != VerifierTypeWrapper.Null)
+							{
+								throw new VerifyError();
+							}
+							break;
+						default:
+							throw new InvalidOperationException();
+					}
+				}
+				else
+				{
+					stack.PopType(GetFieldref(instr.Arg1).GetFieldType());
+				}
+				isStatic = true;
+				write = true;
+				thisType = null;
+				break;
+			default:
+				throw new InvalidOperationException();
+		}
+		if(mw == null)
+		{
+			// We're being called from IsSideEffectFreeStaticInitializer,
+			// no further checks are possible (nor needed).
+		}
+		else if(cpi.GetClassType().IsUnloadable)
+		{
+			if(wrapper.GetClassLoader().DisableDynamicBinding)
+			{
+				SetHardError(wrapper.GetClassLoader(), ref instr, HardError.NoClassDefFoundError, "{0}", cpi.GetClassType().Name);
+			}
+			else
+			{
+				switch(instr.NormalizedOpCode)
+				{
+					case NormalizedByteCode.__getstatic:
+						instr.PatchOpCode(NormalizedByteCode.__dynamic_getstatic);
+						break;
+					case NormalizedByteCode.__putstatic:
+						instr.PatchOpCode(NormalizedByteCode.__dynamic_putstatic);
+						break;
+					case NormalizedByteCode.__getfield:
+						instr.PatchOpCode(NormalizedByteCode.__dynamic_getfield);
+						break;
+					case NormalizedByteCode.__putfield:
+						instr.PatchOpCode(NormalizedByteCode.__dynamic_putfield);
+						break;
+					default:
+						throw new InvalidOperationException();
+				}
+			}
+			return;
+		}
+		else
+		{
+			FieldWrapper field = cpi.GetField();
+			if(field == null)
+			{
+				SetHardError(wrapper.GetClassLoader(), ref instr, HardError.NoSuchFieldError, "{0}.{1}", cpi.Class, cpi.Name);
+				return;
+			}
+			if(cpi.GetFieldType() != field.FieldTypeWrapper && !cpi.GetFieldType().IsUnloadable & !field.FieldTypeWrapper.IsUnloadable)
+			{
+#if STATIC_COMPILER
+				StaticCompiler.LinkageError("Field \"{2}.{3}\" is of type \"{0}\" instead of type \"{1}\" as expected by \"{4}\"", field.FieldTypeWrapper, cpi.GetFieldType(), cpi.GetClassType().Name, cpi.Name, wrapper.Name);
+#endif
+				SetHardError(wrapper.GetClassLoader(), ref instr, HardError.LinkageError, "Loader constraints violated: {0}.{1}", field.DeclaringType.Name, field.Name);
+				return;
+			}
+			if(field.IsStatic != isStatic)
+			{
+				SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IncompatibleClassChangeError, "Static field access to non-static field (or v.v.)");
+				return;
+			}
+			if(!field.IsAccessibleFrom(cpi.GetClassType(), wrapper, thisType))
+			{
+				SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IllegalAccessError, "Try to access field {0}.{1} from class {2}", field.DeclaringType.Name, field.Name, wrapper.Name);
+				return;
+			}
+			// are we trying to mutate a final field? (they are read-only from outside of the defining class)
+			if(write && field.IsFinal
+				&& ((isStatic ? wrapper != cpi.GetClassType() : wrapper != thisType) || (wrapper.GetClassLoader().StrictFinalFieldSemantics && (isStatic ? (mw != null && mw.Name != "") : (mw == null || mw.Name != "")))))
+			{
+				SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IllegalAccessError, "Field {0}.{1} is final", field.DeclaringType.Name, field.Name);
+				return;
+			}
+		}
+	}
+
+	// TODO this method should have a better name
+	private TypeWrapper SigTypeToClassName(TypeWrapper type, TypeWrapper nullType, TypeWrapper wrapper)
+	{
+		if(type == VerifierTypeWrapper.UninitializedThis)
+		{
+			return wrapper;
+		}
+		else if(VerifierTypeWrapper.IsNew(type))
+		{
+			return ((VerifierTypeWrapper)type).UnderlyingType;
+		}
+		else if(type == VerifierTypeWrapper.Null)
+		{
+			return nullType;
+		}
+		else
+		{
+			return type;
+		}
+	}
+
+	private int AllocErrorMessage(string message)
+	{
+		if(errorMessages == null)
+		{
+			errorMessages = new List();
+		}
+		int index = errorMessages.Count;
+		errorMessages.Add(message);
+		return index;
+	}
+
+	private string CheckLoaderConstraints(ClassFile.ConstantPoolItemMI cpi, MethodWrapper mw)
+	{
+		if(cpi.GetRetType() != mw.ReturnType && !cpi.GetRetType().IsUnloadable && !mw.ReturnType.IsUnloadable)
+		{
+#if STATIC_COMPILER
+			StaticCompiler.LinkageError("Method \"{2}.{3}{4}\" has a return type \"{0}\" instead of type \"{1}\" as expected by \"{5}\"", mw.ReturnType, cpi.GetRetType(), cpi.GetClassType().Name, cpi.Name, cpi.Signature, classFile.Name);
+#endif
+			return "Loader constraints violated (return type): " + mw.DeclaringType.Name + "." + mw.Name + mw.Signature;
+		}
+		TypeWrapper[] here = cpi.GetArgTypes();
+		TypeWrapper[] there = mw.GetParameters();
+		for(int i = 0; i < here.Length; i++)
+		{
+			if(here[i] != there[i] && !here[i].IsUnloadable && !there[i].IsUnloadable)
+			{
+#if STATIC_COMPILER
+				StaticCompiler.LinkageError("Method \"{2}.{3}{4}\" has a argument type \"{0}\" instead of type \"{1}\" as expected by \"{5}\"", there[i], here[i], cpi.GetClassType().Name, cpi.Name, cpi.Signature, classFile.Name);
+#endif
+				return "Loader constraints violated (arg " + i + "): " + mw.DeclaringType.Name + "." + mw.Name + mw.Signature;
+			}
+		}
+		return null;
+	}
+
+	private ClassFile.ConstantPoolItemInvokeDynamic GetInvokeDynamic(int index)
+	{
+		try
+		{
+			ClassFile.ConstantPoolItemInvokeDynamic item = classFile.GetInvokeDynamic(index);
+			if(item != null)
+			{
+				return item;
+			}
+		}
+		catch(InvalidCastException)
+		{
+		}
+		catch(IndexOutOfRangeException)
+		{
+		}
+		throw new VerifyError("Illegal constant pool index");
+	}
+
+	private ClassFile.ConstantPoolItemMI GetMethodref(int index)
+	{
+		try
+		{
+			ClassFile.ConstantPoolItemMI item = classFile.GetMethodref(index);
+			if(item != null)
+			{
+				return item;
+			}
+		}
+		catch(InvalidCastException)
+		{
+		}
+		catch(IndexOutOfRangeException)
+		{
+		}
+		throw new VerifyError("Illegal constant pool index");
+	}
+
+	private ClassFile.ConstantPoolItemFieldref GetFieldref(int index)
+	{
+		try
+		{
+			ClassFile.ConstantPoolItemFieldref item = classFile.GetFieldref(index);
+			if(item != null)
+			{
+				return item;
+			}
+		}
+		catch(InvalidCastException)
+		{
+		}
+		catch(IndexOutOfRangeException)
+		{
+		}
+		throw new VerifyError("Illegal constant pool index");
+	}
+
+	private ClassFile.ConstantType GetConstantPoolConstantType(int index)
+	{
+		try
+		{
+			return classFile.GetConstantPoolConstantType(index);
+		}
+		catch(IndexOutOfRangeException)
+		{
+			// constant pool index out of range
+		}
+		catch(InvalidOperationException)
+		{
+			// specified constant pool entry doesn't contain a constant
+		}
+		catch(NullReferenceException)
+		{
+			// specified constant pool entry is empty (entry 0 or the filler following a wide entry)
+		}
+		throw new VerifyError("Illegal constant pool index");
+	}
+
+	private TypeWrapper GetConstantPoolClassType(int index)
+	{
+		try
+		{
+			return classFile.GetConstantPoolClassType(index);
+		}
+		catch(InvalidCastException)
+		{
+		}
+		catch(IndexOutOfRangeException)
+		{
+		}
+		catch(NullReferenceException)
+		{
+		}
+		throw new VerifyError("Illegal constant pool index");
+	}
+
+	internal void ClearFaultBlockException(int instructionIndex)
+	{
+		Debug.Assert(state[instructionIndex].GetStackHeight() == 1);
+		state[instructionIndex].ClearFaultBlockException();
+	}
+
+	private static void DumpMethod(CodeInfo codeInfo, ClassFile.Method method, UntangledExceptionTable exceptions)
+	{
+		ClassFile.Method.Instruction[] code = method.Instructions;
+		InstructionFlags[] flags = ComputePartialReachability(codeInfo, code, exceptions, 0, false);
+		for (int i = 0; i < code.Length; i++)
+		{
+			bool label = (flags[i] & InstructionFlags.BranchTarget) != 0;
+			if (!label)
+			{
+				for (int j = 0; j < exceptions.Length; j++)
+				{
+					if (exceptions[j].startIndex == i
+						|| exceptions[j].endIndex == i
+						|| exceptions[j].handlerIndex == i)
+					{
+						label = true;
+						break;
+					}
+				}
+			}
+			if (label)
+			{
+				Console.WriteLine("label{0}:", i);
+			}
+			if ((flags[i] & InstructionFlags.Reachable) != 0)
+			{
+				Console.Write("  {1}", i, code[i].NormalizedOpCode.ToString().Substring(2));
+				switch (ByteCodeMetaData.GetFlowControl(code[i].NormalizedOpCode))
+				{
+					case ByteCodeFlowControl.Branch:
+					case ByteCodeFlowControl.CondBranch:
+						Console.Write(" label{0}", code[i].Arg1);
+						break;
+				}
+				switch (code[i].NormalizedOpCode)
+				{
+					case NormalizedByteCode.__iload:
+					case NormalizedByteCode.__lload:
+					case NormalizedByteCode.__fload:
+					case NormalizedByteCode.__dload:
+					case NormalizedByteCode.__aload:
+					case NormalizedByteCode.__istore:
+					case NormalizedByteCode.__lstore:
+					case NormalizedByteCode.__fstore:
+					case NormalizedByteCode.__dstore:
+					case NormalizedByteCode.__astore:
+					case NormalizedByteCode.__iconst:
+						Console.Write(" {0}", code[i].Arg1);
+						break;
+					case NormalizedByteCode.__ldc:
+					case NormalizedByteCode.__ldc_nothrow:
+					case NormalizedByteCode.__getfield:
+					case NormalizedByteCode.__getstatic:
+					case NormalizedByteCode.__putfield:
+					case NormalizedByteCode.__putstatic:
+					case NormalizedByteCode.__invokeinterface:
+					case NormalizedByteCode.__invokespecial:
+					case NormalizedByteCode.__invokestatic:
+					case NormalizedByteCode.__invokevirtual:
+					case NormalizedByteCode.__new:
+						Console.Write(" #{0}", code[i].Arg1);
+						break;
+				}
+				Console.WriteLine();
+			}
+		}
+		for (int i = 0; i < exceptions.Length; i++)
+		{
+			Console.WriteLine(".catch #{0} from label{1} to label{2} using label{3}", exceptions[i].catch_type, exceptions[i].startIndex, exceptions[i].endIndex, exceptions[i].handlerIndex);
+		}
+	}
+}
diff --git a/runtime/vfs.cs b/runtime/vfs.cs
new file mode 100644
index 0000000..26bf993
--- /dev/null
+++ b/runtime/vfs.cs
@@ -0,0 +1,1033 @@
+/*
+  Copyright (C) 2007-2011 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Reflection;
+using System.Security.Cryptography.X509Certificates;
+
+namespace IKVM.Internal
+{
+	static class VirtualFileSystem
+	{
+		internal static readonly string RootPath = JVM.IsUnix ? "/.virtual-ikvm-home/" : @"C:\.virtual-ikvm-home\";
+
+		internal static bool IsVirtualFS(string path)
+		{
+			return (path.Length == RootPath.Length - 1 && String.CompareOrdinal(path, 0, RootPath, 0, RootPath.Length - 1) == 0)
+				|| String.CompareOrdinal(path, 0, RootPath, 0, RootPath.Length) == 0;
+		}
+
+		internal static string GetAssemblyClassesPath(Assembly asm)
+		{
+#if FIRST_PASS
+			return null;
+#else
+			// we can't use java.io.File.separatorChar here, because we're invoked by the system property setup code
+			return RootPath + "assembly" + System.IO.Path.DirectorySeparatorChar + VfsAssembliesDirectory.GetName(asm) + System.IO.Path.DirectorySeparatorChar + "classes" + System.IO.Path.DirectorySeparatorChar;
+#endif
+		}
+
+		internal static string GetAssemblyResourcesPath(Assembly asm)
+		{
+#if FIRST_PASS
+			return null;
+#else
+			return RootPath + "assembly" + System.IO.Path.DirectorySeparatorChar + VfsAssembliesDirectory.GetName(asm) + System.IO.Path.DirectorySeparatorChar + "resources" + System.IO.Path.DirectorySeparatorChar;
+#endif
+		}
+
+#if !FIRST_PASS
+		private static VfsDirectory root;
+
+		private abstract class VfsEntry
+		{
+		}
+
+		private abstract class VfsFile : VfsEntry
+		{
+			internal abstract long Size { get; }
+			internal abstract System.IO.Stream Open();
+		}
+
+		private class VfsDirectory : VfsEntry
+		{
+			protected readonly Dictionary entries = new Dictionary();
+
+			internal VfsDirectory AddDirectory(string name)
+			{
+				VfsDirectory dir = new VfsDirectory();
+				Add(name, dir);
+				return dir;
+			}
+
+			internal void Add(string name, VfsEntry entry)
+			{
+				lock (entries)
+				{
+					entries.Add(name, entry);
+				}
+			}
+
+			internal virtual VfsEntry GetEntry(int index, string[] path)
+			{
+				VfsEntry entry = GetEntry(path[index++]);
+				if (index == path.Length)
+				{
+					return entry;
+				}
+				else
+				{
+					VfsDirectory dir = entry as VfsDirectory;
+					if (dir == null)
+					{
+						return null;
+					}
+					return dir.GetEntry(index, path);
+				}
+			}
+
+			internal virtual VfsEntry GetEntry(string name)
+			{
+				VfsEntry entry;
+				lock (entries)
+				{
+					entries.TryGetValue(name, out entry);
+				}
+				return entry;
+			}
+
+			internal virtual string[] List()
+			{
+				lock (entries)
+				{
+					string[] list = new string[entries.Keys.Count];
+					entries.Keys.CopyTo(list, 0);
+					return list;
+				}
+			}
+		}
+
+		private sealed class VfsAssembliesDirectory : VfsDirectory
+		{
+			internal override VfsEntry GetEntry(string name)
+			{
+				VfsEntry entry = base.GetEntry(name);
+				if (entry == null)
+				{
+					Guid guid;
+					if (TryParseGuid(name, out guid))
+					{
+						foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
+						{
+							if (asm.ManifestModule.ModuleVersionId == guid
+								&& !ReflectUtil.IsDynamicAssembly(asm))
+							{
+								return GetOrAddEntry(name, asm);
+							}
+						}
+					}
+					string assemblyName = ParseName(name);
+					if (assemblyName != null)
+					{
+						Assembly asm = null;
+						try
+						{
+							asm = Assembly.Load(assemblyName);
+						}
+						catch
+						{
+						}
+						if (asm != null
+							&& !ReflectUtil.IsDynamicAssembly(asm)
+							&& name == GetName(asm))
+						{
+							return GetOrAddEntry(name, asm);
+						}
+					}
+				}
+				return entry;
+			}
+
+			private VfsEntry GetOrAddEntry(string name, Assembly asm)
+			{
+				lock (entries)
+				{
+					VfsEntry entry;
+					if (!entries.TryGetValue(name, out entry))
+					{
+						VfsDirectory dir = new VfsDirectory();
+						dir.Add("resources", new VfsAssemblyResourcesDirectory(asm));
+						dir.Add("classes", new VfsAssemblyClassesDirectory(asm));
+						Add(name, dir);
+						entry = dir;
+					}
+					return entry;
+				}
+			}
+
+			// HACK we try to figure out if an assembly is loaded in the Load context
+			// http://blogs.msdn.com/b/suzcook/archive/2003/05/29/57143.aspx
+			private static bool IsLoadContext(Assembly asm)
+			{
+				if (asm.ReflectionOnly)
+				{
+					return false;
+				}
+
+				if (asm.GlobalAssemblyCache)
+				{
+					return true;
+				}
+
+				if (ReflectUtil.IsDynamicAssembly(asm) || asm.Location == "")
+				{
+					return false;
+				}
+
+				if (System.IO.Path.GetDirectoryName(asm.Location) == System.IO.Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory))
+				{
+					// this is an optimization for the common case were the assembly was loaded from the app directory
+					return true;
+				}
+
+				try
+				{
+					if (Assembly.Load(asm.FullName) == asm)
+					{
+						return true;
+					}
+				}
+				catch
+				{
+				}
+
+				return false;
+			}
+
+			internal static string GetName(Assembly asm)
+			{
+				if (!IsLoadContext(asm))
+				{
+					return asm.ManifestModule.ModuleVersionId.ToString("N");
+				}
+				AssemblyName name = asm.GetName();
+				System.Text.StringBuilder sb = new System.Text.StringBuilder();
+				string simpleName = name.Name;
+				for (int i = 0; i < simpleName.Length; i++)
+				{
+					if (simpleName[i] == '_')
+					{
+						sb.Append("_!");
+					}
+					else
+					{
+						sb.Append(simpleName[i]);
+					}
+				}
+				byte[] publicKeyToken = name.GetPublicKeyToken();
+				if (publicKeyToken != null && publicKeyToken.Length != 0)
+				{
+					sb.Append("__").Append(name.Version).Append("__");
+					for (int i = 0; i < publicKeyToken.Length; i++)
+					{
+						sb.AppendFormat("{0:x2}", publicKeyToken[i]);
+					}
+				}
+				if (name.CultureInfo != null && !string.IsNullOrEmpty(name.CultureInfo.Name))
+				{
+					sb.Append("__").Append(name.CultureInfo.Name);
+				}
+				return sb.ToString();
+			}
+
+			private static bool TryParseGuid(string name, out Guid guid)
+			{
+				if (name.Length != 32)
+				{
+					guid = Guid.Empty;
+					return false;
+				}
+				for (int i = 0; i < 32; i++)
+				{
+					if ("0123456789abcdefABCDEF".IndexOf(name[i]) == -1)
+					{
+						guid = Guid.Empty;
+						return false;
+					}
+				}
+				guid = new Guid(name);
+				return true;
+			}
+
+			private static string ParseName(string directoryName)
+			{
+				try
+				{
+					string simpleName = null;
+					string version = "0.0.0.0";
+					string publicKeyToken = "null";
+					string culture = "neutral";
+					System.Text.StringBuilder sb = new System.Text.StringBuilder();
+					int part = 0;
+					for (int i = 0; i <= directoryName.Length; i++)
+					{
+						if (i == directoryName.Length || directoryName[i] == '_')
+						{
+							if (i < directoryName.Length - 1 && directoryName[i + 1] == '!')
+							{
+								sb.Append('_');
+								i++;
+							}
+							else if (i == directoryName.Length || directoryName[i + 1] == '_')
+							{
+								switch (part++)
+								{
+									case 0:
+										simpleName = sb.ToString();
+										break;
+									case 1:
+										version = sb.ToString();
+										break;
+									case 2:
+										publicKeyToken = sb.ToString();
+										break;
+									case 3:
+										culture = sb.ToString();
+										break;
+									case 4:
+										return null;
+								}
+								sb.Length = 0;
+								i++;
+							}
+							else
+							{
+								int start = i + 1;
+								int end = start;
+								while ('0' <= directoryName[end] && directoryName[end] <= '9')
+								{
+									end++;
+								}
+								int repeatCount;
+								if (directoryName[end] != '_' || !Int32.TryParse(directoryName.Substring(start, end - start), out repeatCount))
+								{
+									return null;
+								}
+								sb.Append('_', repeatCount);
+								i = end;
+							}
+						}
+						else
+						{
+							sb.Append(directoryName[i]);
+						}
+					}
+					sb.Length = 0;
+					sb.Append(simpleName).Append(", Version=").Append(version).Append(", Culture=").Append(culture).Append(", PublicKeyToken=").Append(publicKeyToken);
+					return sb.ToString();
+				}
+				catch
+				{
+					return null;
+				}
+			}
+		}
+
+		private sealed class VfsAssemblyResourcesDirectory : VfsDirectory
+		{
+			private readonly Assembly asm;
+
+			internal VfsAssemblyResourcesDirectory(Assembly asm)
+			{
+				this.asm = asm;
+			}
+
+			internal override VfsEntry GetEntry(string name)
+			{
+				VfsEntry entry = base.GetEntry(name);
+				if (entry == null)
+				{
+					ManifestResourceInfo resource = asm.GetManifestResourceInfo(name);
+					if (resource != null)
+					{
+						lock (entries)
+						{
+							if (!entries.TryGetValue(name, out entry))
+							{
+								entry = new VfsAssemblyResource(asm, name);
+								entries.Add(name, entry);
+							}
+						}
+					}
+				}
+				return entry;
+			}
+
+			internal override string[] List()
+			{
+				return asm.GetManifestResourceNames();
+			}
+		}
+
+		private sealed class VfsAssemblyResource : VfsFile
+		{
+			private readonly Assembly asm;
+			private readonly string name;
+
+			internal VfsAssemblyResource(Assembly asm, string name)
+			{
+				this.asm = asm;
+				this.name = name;
+			}
+
+			internal override System.IO.Stream Open()
+			{
+				return asm.GetManifestResourceStream(name);
+			}
+
+			internal override long Size
+			{
+				get
+				{
+					using (System.IO.Stream stream = Open())
+					{
+						return stream.Length;
+					}
+				}
+			}
+		}
+
+		private sealed class VfsAssemblyClassesDirectory : VfsDirectory
+		{
+			private readonly Assembly asm;
+			private readonly Dictionary classes = new Dictionary();
+
+			internal VfsAssemblyClassesDirectory(Assembly asm)
+			{
+				this.asm = asm;
+			}
+
+			internal override VfsEntry GetEntry(int index, string[] path)
+			{
+				if (path[path.Length - 1].EndsWith(".class", StringComparison.Ordinal))
+				{
+					System.Text.StringBuilder sb = new System.Text.StringBuilder();
+					for (int i = index; i < path.Length - 1; i++)
+					{
+						sb.Append(path[i]).Append('.');
+					}
+					sb.Append(path[path.Length - 1], 0, path[path.Length - 1].Length - 6);
+					string className = sb.ToString();
+					VfsEntry entry;
+					lock (classes)
+					{
+						if (classes.TryGetValue(className, out entry))
+						{
+							return entry;
+						}
+					}
+					AssemblyClassLoader acl = AssemblyClassLoader.FromAssembly(asm);
+					TypeWrapper tw = null;
+					try
+					{
+						tw = acl.LoadClassByDottedNameFast(className);
+					}
+					catch
+					{
+					}
+					if (tw != null && !tw.IsArray)
+					{
+						lock (classes)
+						{
+							if (!classes.TryGetValue(className, out entry))
+							{
+								entry = new VfsAssemblyClass(tw);
+								classes.Add(className, entry);
+							}
+						}
+						return entry;
+					}
+					return null;
+				}
+				else
+				{
+					Populate();
+					return base.GetEntry(index, path);
+				}
+			}
+
+			internal override string[] List()
+			{
+				Populate();
+				return base.List();
+			}
+
+			private void Populate()
+			{
+				bool populate;
+				lock (entries)
+				{
+					populate = entries.Count == 0;
+				}
+				if (populate)
+				{
+					Dictionary names = new Dictionary();
+					AssemblyClassLoader acl = AssemblyClassLoader.FromAssembly(this.asm);
+					foreach (Assembly asm in acl.GetAllAvailableAssemblies())
+					{
+						Type[] types;
+						try
+						{
+							types = asm.GetTypes();
+						}
+						catch (ReflectionTypeLoadException x)
+						{
+							types = x.Types;
+						}
+						catch
+						{
+							types = Type.EmptyTypes;
+						}
+						foreach (Type type in types)
+						{
+							if (type != null)
+							{
+								string name = null;
+								try
+								{
+									bool isJavaType;
+									name = acl.GetTypeNameAndType(type, out isJavaType);
+#if !FIRST_PASS
+									// annotation custom attributes are pseudo proxies and are not loadable by name (and should not exist in the file systems,
+									// because proxies are, ostensibly, created on the fly)
+									if (isJavaType && type.BaseType == typeof(global::ikvm.@internal.AnnotationAttributeBase) && name.Contains(".$Proxy"))
+									{
+										name = null;
+									}
+#endif
+								}
+								catch
+								{
+								}
+								if (name != null)
+								{
+									names[name] = name;
+								}
+							}
+						}
+					}
+					lock (entries)
+					{
+						if (entries.Count == 0)
+						{
+							foreach (string name in names.Keys)
+							{
+								string[] parts = name.Split('.');
+								VfsDirectory dir = this;
+								for (int i = 0; i < parts.Length - 1; i++)
+								{
+									dir = dir.GetEntry(parts[i]) as VfsDirectory ?? dir.AddDirectory(parts[i]);
+								}
+								// we're adding a dummy file, to make the file appear in the directory listing, it will not actually
+								// be accessed, because the code above handles that
+								dir.Add(parts[parts.Length - 1] + ".class", VfsDummyFile.Instance);
+							}
+						}
+					}
+				}
+			}
+		}
+
+		private sealed class VfsAssemblyClass : VfsFile
+		{
+			private readonly TypeWrapper tw;
+			private volatile byte[] buf;
+
+			internal VfsAssemblyClass(TypeWrapper tw)
+			{
+				this.tw = tw;
+			}
+
+			private void Populate()
+			{
+#if !FIRST_PASS
+				if (buf == null)
+				{
+					System.IO.MemoryStream mem = new System.IO.MemoryStream();
+					bool includeNonPublicInterfaces = !"true".Equals(java.lang.Props.props.getProperty("ikvm.stubgen.skipNonPublicInterfaces"), StringComparison.OrdinalIgnoreCase);
+					IKVM.StubGen.StubGenerator.WriteClass(mem, tw, includeNonPublicInterfaces, false, false, true);
+					buf = mem.ToArray();
+				}
+#endif
+			}
+
+			internal override System.IO.Stream Open()
+			{
+				Populate();
+				return new System.IO.MemoryStream(buf);
+			}
+
+			internal override long Size
+			{
+				get
+				{
+					Populate();
+					return buf.Length;
+				}
+			}
+		}
+
+		private sealed class VfsDummyFile : VfsFile
+		{
+			internal static readonly VfsDummyFile Instance = new VfsDummyFile();
+
+			private VfsDummyFile()
+			{
+			}
+
+			internal override long Size
+			{
+				get { return 0; }
+			}
+
+			internal override System.IO.Stream Open()
+			{
+				return System.IO.Stream.Null;
+			}
+		}
+
+		private sealed class VfsZipEntry : VfsFile
+		{
+			private readonly java.util.zip.ZipFile zipFile;
+			private readonly java.util.zip.ZipEntry entry;
+
+			internal VfsZipEntry(java.util.zip.ZipFile zipFile, java.util.zip.ZipEntry entry)
+			{
+				this.zipFile = zipFile;
+				this.entry = entry;
+			}
+
+			internal override long Size
+			{
+				get { return entry.getSize(); }
+			}
+
+			internal override System.IO.Stream Open()
+			{
+				return new ZipEntryStream(zipFile, entry);
+			}
+		}
+
+		private sealed class VfsCacertsEntry : VfsFile
+		{
+			private volatile byte[] buf;
+
+			internal override long Size
+			{
+				get
+				{
+					Populate();
+					return buf.Length;
+				}
+			}
+
+			internal override System.IO.Stream Open()
+			{
+				Populate();
+				return new System.IO.MemoryStream(buf, false);
+			}
+
+			private void Populate()
+			{
+				if (buf == null)
+				{
+					global::java.security.KeyStore jstore = global::java.security.KeyStore.getInstance("jks");
+					jstore.load(null);
+					global::java.security.cert.CertificateFactory cf = global::java.security.cert.CertificateFactory.getInstance("X509");
+
+					X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
+					store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
+					Dictionary aliases = new Dictionary();
+					foreach (X509Certificate2 cert in store.Certificates)
+					{
+						if (!cert.HasPrivateKey)
+						{
+							// the alias must be unique, otherwise we overwrite the previous certificate with that alias
+							string alias = cert.Subject;
+							int unique = 0;
+							while (aliases.ContainsKey(alias))
+							{
+								alias = cert.Subject + " #" + (++unique);
+							}
+							aliases.Add(alias, null);
+							jstore.setCertificateEntry(alias, cf.generateCertificate(new global::java.io.ByteArrayInputStream(cert.RawData)));
+						}
+					}
+					store.Close();
+					global::java.io.ByteArrayOutputStream baos = new global::java.io.ByteArrayOutputStream();
+					jstore.store(baos, new char[0]);
+					buf = baos.toByteArray();
+				}
+			}
+		}
+
+		private sealed class VfsVfsZipEntry : VfsFile
+		{
+			internal override long Size
+			{
+				get
+				{
+					using (System.IO.Stream stream = Open())
+					{
+						return stream.Length;
+					}
+				}
+			}
+
+			internal override System.IO.Stream Open()
+			{
+				//return new System.IO.FileStream("c:\\ikvm\\openjdk\\vfs.zip", System.IO.FileMode.Open);
+				return Assembly.GetExecutingAssembly().GetManifestResourceStream("vfs.zip");
+			}
+		}
+
+		private abstract class VfsExecutable : VfsFile
+		{
+			internal override long Size { get { return 0; } }
+
+			internal override System.IO.Stream Open()
+			{
+				return System.IO.Stream.Null;
+			}
+
+			internal abstract string GetPath();
+		}
+
+		private sealed class VfsJavaExe : VfsExecutable
+		{
+			private string path;
+
+			internal override string GetPath()
+			{
+				if (path == null)
+				{
+					path = new System.Uri(Assembly.GetEntryAssembly().CodeBase + "/../ikvm.exe").LocalPath;
+				}
+				return path;
+			}
+		}
+
+		private static void Initialize()
+		{
+			VfsDirectory root = new VfsDirectory();
+			root.AddDirectory("lib").AddDirectory("security").Add("cacerts", new VfsCacertsEntry());
+			VfsDirectory bin = new VfsDirectory();
+			root.Add("bin", bin);
+			root.Add("assembly", new VfsAssembliesDirectory());
+			AddDummyLibrary(bin, "zip");
+			AddDummyLibrary(bin, "awt");
+			AddDummyLibrary(bin, "rmi");
+			AddDummyLibrary(bin, "w2k_lsa_auth");
+			AddDummyLibrary(bin, "jaas_nt");
+			AddDummyLibrary(bin, "jaas_unix");
+			AddDummyLibrary(bin, "net");
+			AddDummyLibrary(bin, "splashscreen");
+			AddDummyLibrary(bin, "osx");
+			AddDummyLibrary(bin, "management");
+			bin.Add("java", new VfsJavaExe());
+			bin.Add("javaw", new VfsJavaExe());
+			bin.Add("java.exe", new VfsJavaExe());
+			bin.Add("javaw.exe", new VfsJavaExe());
+
+			// this is a weird loop back, the vfs.zip resource is loaded from vfs,
+			// because that's the easiest way to construct a ZipFile from a Stream.
+			java.util.zip.ZipFile zf = new java.util.zip.ZipFile(RootPath + "vfs.zip");
+			java.util.Enumeration e = zf.entries();
+			while (e.hasMoreElements())
+			{
+				AddZipEntry(zf, root, (java.util.zip.ZipEntry)e.nextElement());
+			}
+
+			// make "lib/security/local_policy.jar" point to "lib/security/US_export_policy.jar"
+			// to get the unrestricted crypto policy
+			VfsDirectory security = (VfsDirectory)((VfsDirectory)root.GetEntry("lib")).GetEntry("security");
+			security.Add("local_policy.jar", security.GetEntry("US_export_policy.jar"));
+
+			Interlocked.CompareExchange(ref VirtualFileSystem.root, root, null);
+		}
+
+		private static void AddDummyLibrary(VfsDirectory dir, string name)
+		{
+			dir.Add(java.lang.System.mapLibraryName(name), VfsDummyFile.Instance);
+		}
+
+		private static void AddZipEntry(java.util.zip.ZipFile zf, VfsDirectory root, java.util.zip.ZipEntry entry)
+		{
+			if (entry.isDirectory())
+			{
+				return;
+			}
+			string[] path = entry.getName().Split('/');
+			VfsDirectory dir = root;
+			for (int i = 0; i < path.Length - 1; i++)
+			{
+				VfsDirectory existing = dir.GetEntry(path[i]) as VfsDirectory;
+				if (existing == null)
+				{
+					existing = dir.AddDirectory(path[i]);
+				}
+				dir = existing;
+			}
+			dir.Add(path[path.Length - 1], new VfsZipEntry(zf, entry));
+		}
+
+		private static VfsEntry GetVfsEntry(string name)
+		{
+			if (root == null)
+			{
+				if (name == RootPath + "vfs.zip")
+				{
+					return new VfsVfsZipEntry();
+				}
+				Initialize();
+			}
+			if (name.Length <= RootPath.Length)
+			{
+				return root;
+			}
+			string[] path = name.Substring(RootPath.Length).Split(java.io.File.separatorChar);
+			return root.GetEntry(0, path);
+		}
+
+		internal sealed class ZipEntryStream : System.IO.Stream
+		{
+			private readonly java.util.zip.ZipFile zipFile;
+			private readonly java.util.zip.ZipEntry entry;
+			private java.io.InputStream inp;
+			private long position;
+
+			internal ZipEntryStream(java.util.zip.ZipFile zipFile, java.util.zip.ZipEntry entry)
+			{
+				this.zipFile = zipFile;
+				this.entry = entry;
+				inp = zipFile.getInputStream(entry);
+			}
+
+			public override bool CanRead
+			{
+				get { return true; }
+			}
+
+			public override bool CanWrite
+			{
+				get { return false; }
+			}
+
+			public override bool CanSeek
+			{
+				get { return true; }
+			}
+
+			public override long Length
+			{
+				get { return entry.getSize(); }
+			}
+
+			public override int Read(byte[] buffer, int offset, int count)
+			{
+				// For compatibility with real file i/o, we try to read the requested number
+				// of bytes, instead of returning earlier if the underlying InputStream does so.
+				int totalRead = 0;
+				while (count > 0)
+				{
+					int read = inp.read(buffer, offset, count);
+					if (read <= 0)
+					{
+						break;
+					}
+					offset += read;
+					count -= read;
+					totalRead += read;
+					position += read;
+				}
+				return totalRead;
+			}
+
+			public override long Position
+			{
+				get
+				{
+					return position;
+				}
+				set
+				{
+					if (value < position)
+					{
+						if (value < 0)
+						{
+							throw new System.IO.IOException("Negative seek offset");
+						}
+						position = 0;
+						inp.close();
+						inp = zipFile.getInputStream(entry);
+					}
+					long skip = value - position;
+					while (skip > 0)
+					{
+						long skipped = inp.skip(skip);
+						if (skipped == 0)
+						{
+							if (position != entry.getSize())
+							{
+								throw new System.IO.IOException("skip failed");
+							}
+							// we're actually at EOF in the InputStream, but we set the virtual position beyond EOF
+							position += skip;
+							break;
+						}
+						position += skipped;
+						skip -= skipped;
+					}
+				}
+			}
+
+			public override void Flush()
+			{
+			}
+
+			public override long Seek(long offset, System.IO.SeekOrigin origin)
+			{
+				switch (origin)
+				{
+					case System.IO.SeekOrigin.Begin:
+						Position = offset;
+						break;
+					case System.IO.SeekOrigin.Current:
+						Position += offset;
+						break;
+					case System.IO.SeekOrigin.End:
+						Position = entry.getSize() + offset;
+						break;
+				}
+				return position;
+			}
+
+			public override void Write(byte[] buffer, int offset, int count)
+			{
+				throw new NotSupportedException();
+			}
+
+			public override void SetLength(long value)
+			{
+				throw new NotSupportedException();
+			}
+
+			public override void Close()
+			{
+				base.Close();
+				inp.close();
+			}
+		}
+#endif
+
+		internal static System.IO.Stream Open(string name, System.IO.FileMode fileMode, System.IO.FileAccess fileAccess)
+		{
+#if FIRST_PASS
+			return null;
+#else
+			if (fileMode != System.IO.FileMode.Open || fileAccess != System.IO.FileAccess.Read)
+			{
+				throw new System.IO.IOException("vfs is read-only");
+			}
+			VfsFile entry = GetVfsEntry(name) as VfsFile;
+			if (entry == null)
+			{
+				throw new System.IO.FileNotFoundException("File not found");
+			}
+			return entry.Open();
+#endif
+		}
+
+		internal static long GetLength(string path)
+		{
+#if FIRST_PASS
+			return 0;
+#else
+			VfsFile entry = GetVfsEntry(path) as VfsFile;
+			return entry == null ? 0 : entry.Size;
+#endif
+		}
+
+		internal static bool CheckAccess(string path, int access)
+		{
+#if FIRST_PASS
+			return false;
+#else
+			return access == Java_java_io_WinNTFileSystem.ACCESS_READ && GetVfsEntry(path) != null;
+#endif
+		}
+
+		internal static int GetBooleanAttributes(string path)
+		{
+#if FIRST_PASS
+			return 0;
+#else
+			VfsEntry entry = GetVfsEntry(path);
+			if (entry == null)
+			{
+				return 0;
+			}
+			const int BA_EXISTS = 0x01;
+			const int BA_REGULAR = 0x02;
+			const int BA_DIRECTORY = 0x04;
+			return entry is VfsDirectory ? BA_EXISTS | BA_DIRECTORY : BA_EXISTS | BA_REGULAR;
+#endif
+		}
+
+		internal static string MapExecutable(string path)
+		{
+#if FIRST_PASS
+			return null;
+#else
+			VfsExecutable entry = GetVfsEntry(path) as VfsExecutable;
+			if (entry == null)
+			{
+				return path;
+			}
+			return entry.GetPath();
+#endif
+		}
+
+		internal static string[] List(string path)
+		{
+#if FIRST_PASS
+			return null;
+#else
+			VfsDirectory dir = GetVfsEntry(path) as VfsDirectory;
+			return dir == null ? null : dir.List();
+#endif
+		}
+	}
+}
diff --git a/runtime/vm.cs b/runtime/vm.cs
new file mode 100644
index 0000000..07b0d71
--- /dev/null
+++ b/runtime/vm.cs
@@ -0,0 +1,499 @@
+/*
+  Copyright (C) 2002-2013 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Threading;
+#if STATIC_COMPILER || STUB_GENERATOR
+using IKVM.Reflection;
+using Type = IKVM.Reflection.Type;
+#else
+using System.Reflection;
+#endif
+using System.IO;
+using System.Diagnostics;
+using System.Text;
+using System.Security;
+using System.Security.Permissions;
+using IKVM.Internal;
+
+#if !STATIC_COMPILER && !STUB_GENERATOR
+namespace IKVM.Internal
+{
+	public static class Starter
+	{
+		public static void PrepareForSaveDebugImage()
+		{
+			JVM.IsSaveDebugImage  = true;
+		}
+	
+		public static void SaveDebugImage()
+		{
+			DynamicClassLoader.SaveDebugImages();
+		}
+
+		public static bool ClassUnloading
+		{
+#if CLASSGC
+			get { return JVM.classUnloading; }
+			set { JVM.classUnloading = value; }
+#else
+			get { return false; }
+			set { }
+#endif
+		}
+
+		public static bool RelaxedVerification
+		{
+			get { return JVM.relaxedVerification; }
+			set { JVM.relaxedVerification = value; }
+		}
+
+		public static bool AllowNonVirtualCalls
+		{
+			get { return JVM.AllowNonVirtualCalls; }
+			set { JVM.AllowNonVirtualCalls = value; }
+		}
+	}
+}
+#endif // !STATIC_COMPILER && !STUB_GENERATOR
+
+namespace IKVM.Internal
+{
+	static class JVM
+	{
+		internal const string JarClassList = "--ikvm-classes--/";
+#if STATIC_COMPILER
+		internal const bool FinishingForDebugSave = false;
+		internal const bool IsSaveDebugImage = false;
+#elif !STUB_GENERATOR
+		private static bool finishingForDebugSave;
+		private static int emitSymbols;
+		internal static bool IsSaveDebugImage;
+#if CLASSGC
+		internal static bool classUnloading = true;
+#endif
+#endif // STATIC_COMPILER
+		private static Assembly coreAssembly;
+#if !STUB_GENERATOR
+		internal static bool relaxedVerification = true;
+		internal static bool AllowNonVirtualCalls;
+		internal static readonly bool DisableEagerClassLoading = SafeGetEnvironmentVariable("IKVM_DISABLE_EAGER_CLASS_LOADING") != null;
+#endif
+
+#if !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS
+		static JVM()
+		{
+			if (SafeGetEnvironmentVariable("IKVM_SAVE_DYNAMIC_ASSEMBLIES") != null)
+			{
+				IsSaveDebugImage = true;
+				java.lang.Runtime.getRuntime().addShutdownHook(new java.lang.Thread(ikvm.runtime.Delegates.toRunnable(DynamicClassLoader.SaveDebugImages)));
+			}
+		}
+#endif
+
+		internal static Version SafeGetAssemblyVersion(System.Reflection.Assembly asm)
+		{
+			// Assembly.GetName().Version requires FileIOPermission,
+			// so we parse the FullName manually :-(
+			string name = asm.FullName;
+			int start = name.IndexOf(", Version=");
+			if(start >= 0)
+			{
+				start += 10;
+				int end = name.IndexOf(',', start);
+				if(end >= 0)
+				{
+					return new Version(name.Substring(start, end - start));
+				}
+			}
+			return new Version();
+		}
+
+		internal static string SafeGetEnvironmentVariable(string name)
+		{
+			try
+			{
+				return Environment.GetEnvironmentVariable(name);
+			}
+			catch(SecurityException)
+			{
+				return null;
+			}
+		}
+
+		internal static Assembly CoreAssembly
+		{
+			get
+			{
+#if !STATIC_COMPILER && !STUB_GENERATOR
+				if(coreAssembly == null)
+				{
+#if FIRST_PASS
+					throw new InvalidOperationException("This version of IKVM.Runtime.dll was compiled with FIRST_PASS defined.");
+#else
+					coreAssembly = typeof(java.lang.Object).Assembly;
+#endif
+				}
+#endif // !STATIC_COMPILER
+				return coreAssembly;
+			}
+			set
+			{
+				coreAssembly = value;
+			}
+		}
+
+#if !STATIC_COMPILER && !STUB_GENERATOR
+		internal static bool FinishingForDebugSave
+		{
+			get
+			{
+				return finishingForDebugSave;
+			}
+			set
+			{
+				finishingForDebugSave = value;
+			}
+		}
+
+		internal static bool EmitSymbols
+		{
+			get
+			{
+				if (emitSymbols == 0)
+				{
+					int state;
+					string debug = System.Configuration.ConfigurationManager.AppSettings["ikvm-emit-symbols"];
+					if (debug == null)
+					{
+						state = Debugger.IsAttached ? 1 : 2;
+					}
+					else
+					{
+						state = debug.Equals("True", StringComparison.OrdinalIgnoreCase) ? 1 : 2;
+					}
+					// make sure we only set the value once, because it isn't allowed to changed as that could cause
+					// the compiler to try emitting symbols into a ModuleBuilder that doesn't accept them (and would
+					// throw an InvalidOperationException)
+					Interlocked.CompareExchange(ref emitSymbols, state, 0);
+				}
+				return emitSymbols == 1;
+			}
+		}
+#endif // !STATIC_COMPILER && !STUB_GENERATOR
+
+		internal static bool IsUnix
+		{
+			get
+			{
+				return Environment.OSVersion.Platform == PlatformID.Unix;
+			}
+		}
+	
+		internal static string MangleResourceName(string name)
+		{
+			// FXBUG there really shouldn't be any need to mangle the resource names,
+			// but in order for ILDASM/ILASM round tripping to work reliably, we have
+			// to make sure that we don't produce resource names that'll cause ILDASM
+			// to generate invalid filenames.
+			StringBuilder sb = new StringBuilder("ikvm__", name.Length + 6);
+			foreach(char c in name)
+			{
+				if("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-+.()$#@~=&{}[]0123456789`".IndexOf(c) != -1)
+				{
+					sb.Append(c);
+				}
+				else if(c == '/')
+				{
+					sb.Append('!');
+				}
+				else
+				{
+					sb.Append('%');
+					sb.Append(string.Format("{0:X4}", (int)c));
+				}
+			}
+			return sb.ToString();
+		}
+
+		// based on Bret Mulvey's C# port of Jenkins32
+		// note that this algorithm cannot be changed, because we persist these hashcodes in the metadata of shared class loader assemblies
+		internal static int PersistableHash(string str)
+		{
+			uint key = 1;
+			foreach (char c in str)
+			{
+				key += c;
+				key += (key << 12);
+				key ^= (key >> 22);
+				key += (key << 4);
+				key ^= (key >> 9);
+				key += (key << 10);
+				key ^= (key >> 2);
+				key += (key << 7);
+				key ^= (key >> 12);
+			}
+			return (int)key;
+		}
+
+#if !STATIC_COMPILER
+		internal static void CriticalFailure(string message, Exception x)
+		{
+			try
+			{
+				Tracer.Error(Tracer.Runtime, "CRITICAL FAILURE: {0}", message);
+				System.Type messageBox = null;
+#if !STUB_GENERATOR
+				// NOTE we use reflection to invoke MessageBox.Show, to make sure we run in environments where WinForms isn't available
+				Assembly winForms = IsUnix ? null : Assembly.Load("System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
+				if(winForms != null)
+				{
+					messageBox = winForms.GetType("System.Windows.Forms.MessageBox");
+				}
+#endif
+				message = String.Format("****** Critical Failure: {1} ******{0}{0}" +
+					"PLEASE FILE A BUG REPORT FOR IKVM.NET WHEN YOU SEE THIS MESSAGE{0}{0}" +
+					(messageBox != null ? "(on Windows you can use Ctrl+C to copy the contents of this message to the clipboard){0}{0}" : "") +
+					"{2}{0}" +
+					"{3}{0}" +
+					"{4} {5}-bit{0}{0}" +
+					"{6}{0}" + 
+					"{7}{0}" +
+					"{8}",
+					Environment.NewLine,
+					message,
+					System.Reflection.Assembly.GetExecutingAssembly().FullName,
+					System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(),
+					Environment.Version,
+					IntPtr.Size * 8,
+					x,
+					x != null ? new StackTrace(x, true).ToString() : "",
+					new StackTrace(true));
+				if(messageBox != null)
+				{
+					try
+					{
+						Version ver = SafeGetAssemblyVersion(typeof(JVM).Assembly);
+						messageBox.InvokeMember("Show", System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public, null, null, new object[] { message, "IKVM.NET " + ver + " Critical Failure" });
+					}
+					catch
+					{
+						Console.Error.WriteLine(message);
+					}
+				}
+				else
+				{
+					Console.Error.WriteLine(message);
+				}
+			}
+			catch(Exception ex)
+			{
+				Console.Error.WriteLine(ex);
+			}
+			finally
+			{
+				Environment.Exit(666);
+			}
+		}
+#endif // !STATIC_COMPILER
+
+#if STATIC_COMPILER || STUB_GENERATOR
+		internal static Type LoadType(System.Type type)
+		{
+			return StaticCompiler.GetRuntimeType(type.FullName);
+		}
+#endif
+
+		// this method resolves types in IKVM.Runtime.dll
+		// (the version of IKVM.Runtime.dll that we're running
+		// with can be different from the one we're compiling against.)
+		internal static Type LoadType(Type type)
+		{
+#if STATIC_COMPILER || STUB_GENERATOR
+			return StaticCompiler.GetRuntimeType(type.FullName);
+#else
+			return type;
+#endif
+		}
+
+		internal static object Box(object val)
+		{
+#if STATIC_COMPILER || FIRST_PASS || STUB_GENERATOR
+			return null;
+#else
+			if(val is byte)
+			{
+				return java.lang.Byte.valueOf((byte)val);
+			}
+			else if(val is bool)
+			{
+				return java.lang.Boolean.valueOf((bool)val);
+			}
+			else if(val is short)
+			{
+				return java.lang.Short.valueOf((short)val);
+			}
+			else if(val is char)
+			{
+				return java.lang.Character.valueOf((char)val);
+			}
+			else if(val is int)
+			{
+				return java.lang.Integer.valueOf((int)val);
+			}
+			else if(val is float)
+			{
+				return java.lang.Float.valueOf((float)val);
+			}
+			else if(val is long)
+			{
+				return java.lang.Long.valueOf((long)val);
+			}
+			else if(val is double)
+			{
+				return java.lang.Double.valueOf((double)val);
+			}
+			else
+			{
+				throw new java.lang.IllegalArgumentException();
+			}
+#endif
+		}
+
+		internal static object Unbox(object val)
+		{
+#if STATIC_COMPILER || FIRST_PASS || STUB_GENERATOR
+			return null;
+#else
+			java.lang.Byte b = val as java.lang.Byte;
+			if(b != null)
+			{
+				return b.byteValue();
+			}
+			java.lang.Boolean b1 = val as java.lang.Boolean;
+			if(b1 != null)
+			{
+				return b1.booleanValue();
+			}
+			java.lang.Short s = val as java.lang.Short;
+			if(s != null)
+			{
+				return s.shortValue();
+			}
+			java.lang.Character c = val as java.lang.Character;
+			if(c != null)
+			{
+				return c.charValue();
+			}
+			java.lang.Integer i = val as java.lang.Integer;
+			if(i != null)
+			{
+				return i.intValue();
+			}
+			java.lang.Float f = val as java.lang.Float;
+			if(f != null)
+			{
+				return f.floatValue();
+			}
+			java.lang.Long l = val as java.lang.Long;
+			if(l != null)
+			{
+				return l.longValue();
+			}
+			java.lang.Double d = val as java.lang.Double;
+			if(d != null)
+			{
+				return d.doubleValue();
+			}
+			else
+			{
+				throw new java.lang.IllegalArgumentException();
+			}
+#endif
+		}
+
+#if !STATIC_COMPILER && !STUB_GENERATOR
+		internal static object NewAnnotation(java.lang.ClassLoader classLoader, object definition)
+		{
+#if !FIRST_PASS
+			java.lang.annotation.Annotation ann = null;
+			try
+			{
+				ann = (java.lang.annotation.Annotation)ikvm.@internal.AnnotationAttributeBase.newAnnotation(classLoader, definition);
+			}
+			catch (java.lang.TypeNotPresentException) { }
+			if (ann != null && sun.reflect.annotation.AnnotationType.getInstance(ann.annotationType()).retention() == java.lang.annotation.RetentionPolicy.RUNTIME)
+			{
+				return ann;
+			}
+#endif
+			return null;
+		}
+#endif
+
+#if !STATIC_COMPILER && !STUB_GENERATOR
+		internal static object NewAnnotationElementValue(java.lang.ClassLoader classLoader, java.lang.Class expectedClass, object definition)
+		{
+#if FIRST_PASS
+			return null;
+#else
+			try
+			{
+				return ikvm.@internal.AnnotationAttributeBase.decodeElementValue(definition, expectedClass, classLoader);
+			}
+			catch(java.lang.IllegalAccessException)
+			{
+				// TODO this shouldn't be here
+				return null;
+			}
+#endif
+		}
+#endif
+
+#if !STATIC_COMPILER && !STUB_GENERATOR
+		// helper for JNI (which doesn't have access to core library internals)
+		internal static object NewDirectByteBuffer(long address, int capacity)
+		{
+#if FIRST_PASS
+			return null;
+#else
+			return java.nio.DirectByteBuffer.__new(address, capacity);
+#endif
+		}
+#endif
+
+		internal static Type Import(System.Type type)
+		{
+#if STATIC_COMPILER || STUB_GENERATOR
+			return StaticCompiler.Universe.Import(type);
+#else
+			return type;
+#endif
+		}
+	}
+
+	static class Experimental
+	{
+		internal static readonly bool JDK_9 = JVM.SafeGetEnvironmentVariable("IKVM_EXPERIMENTAL_JDK_9") != null;
+	}
+}
diff --git a/tools/SourceLicenseAnalyzer.cs b/tools/SourceLicenseAnalyzer.cs
new file mode 100644
index 0000000..ea3f984
--- /dev/null
+++ b/tools/SourceLicenseAnalyzer.cs
@@ -0,0 +1,217 @@
+/*
+  Copyright (C) 2013-2014 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace SourceLicenseAnalyzer
+{
+	class Years
+	{
+		internal static Years Dummy = new Years();
+		internal int min = Int32.MaxValue;
+		internal int max = Int32.MinValue;
+		internal string name;
+	}
+
+	class Program
+	{
+		static Dictionary aliases = new Dictionary();
+		static Dictionary copyrights = new Dictionary();
+		static int errorCount;
+
+		static void Def(string name, params string[] aliasesList)
+		{
+			Years y = new Years();
+			y.name = name;
+			copyrights.Add(name, y);
+			aliases.Add(name, name);
+			foreach (string s in aliasesList)
+			{
+				aliases.Add(s, name);
+			}
+		}
+
+		static int Main(string[] args)
+		{
+			Def("Free Software Foundation", "Free Software   Foundation", "Free Software    Foundation", "Free Software Fonudation, Inc.");
+			Def("Sun Microsystems, Inc.", "Sun Microsystems Inc");
+			Def("Jeroen Frijters");
+			Def("Thai Open Source Software Center Ltd");
+			Def("World Wide Web Consortium");
+			Def("International Business Machines, Inc.", "IBM Corp.", "IBM Corporation", "International Business Machines", "International Business Machines Corporation");
+			Def("Wily Technology, Inc.");
+			Def("Unicode, Inc.");
+			Def("Colin Plumb");
+			Def("Taligent, Inc.");
+			Def("Red Hat, Inc.");
+			Def("The Open Group Research Institute");
+			Def("FundsXpress, INC.");
+			Def("AT&T");
+			Def("The Apache Software Foundation");
+			Def("freebxml.org");
+			Def("The Cryptix Foundation Limited");
+			Def("Visual Numerics Inc.");
+			Def("INRIA, France Telecom");
+			Def("Oracle and/or its affiliates", "Oracle Corporation");
+			Def("i-net software");
+			Def("Google Inc.");
+			Def("Stephen Colebourne & Michael Nascimento Santos");
+			Def("Attila Szegedi");
+
+
+			// these are false positives
+			copyrights.Add("dummy", Years.Dummy);
+			aliases.Add("icSigCopyrightTag", "dummy");
+			aliases.Add("Copyright notice to stick into built-in-profile files.", "dummy");
+			aliases.Add("AssemblyCopyrightAttribute", "dummy");
+			aliases.Add("getVersionAndCopyrightInfo()", "dummy");
+			aliases.Add("Copyright by IBM and others and distributed under the * distributed under MIT/X", "dummy");
+			aliases.Add("*  Copyright Office. *", "dummy");
+			aliases.Add("* Copyright office. *", "dummy");
+			aliases.Add("Your Corporation", "dummy");
+			aliases.Add("but I wrote that code so I co-own the copyright", "dummy");
+			aliases.Add("identifying information: \"Portions Copyrighted [year] * [name of copyright owner]\"", "dummy");
+			aliases.Add("* \"Portions Copyright [year] [name of copyright owner]\" *", "dummy");
+
+			using (StreamReader rdr = new StreamReader("allsources.gen.lst"))
+			{
+				string file;
+				while ((file = rdr.ReadLine()) != null)
+				{
+					if (file != "AssemblyInfo.java")
+					{
+						ProcessFile(file);
+					}
+				}
+			}
+
+			Years[] years = new Years[copyrights.Count];
+			copyrights.Values.CopyTo(years, 0);
+
+			Array.Sort(years, delegate(Years x, Years y) { return x.name == null ? 0 : x.name.CompareTo(y.name); });
+
+			bool first = true;
+			foreach (Years y in years)
+			{
+				if (y != Years.Dummy)
+				{
+					if (!first)
+					{
+						Console.WriteLine("\\r\\n\" +");
+					}
+					first = false;
+					Console.Write("    \"");
+					if (y.min != y.max)
+					{
+						Console.Write("{0}-{1}  {2}", y.min, y.max, y.name);
+					}
+					else
+					{
+						Console.Write("{0}       {1}", y.min, y.name);
+					}
+				}
+			}
+			Console.WriteLine("\"");
+
+			return errorCount;
+		}
+
+		static void ProcessFile(string filePath)
+		{
+			bool gpl = false;
+			bool classpathException = false;
+			if (!File.Exists(filePath) && File.Exists(filePath + ".in"))
+			{
+				filePath += ".in";
+			}
+			using (StreamReader rdr = new StreamReader(filePath))
+			{
+				string line;
+				string nextline = null;
+				while ((line = rdr.ReadLine()) != null)
+				{
+					gpl |= line.Contains("GNU General Public License");
+					classpathException |= line.Contains("subject to the \"Classpath\" exception") || line.Contains("permission to link this library with independent modules");
+					while (line != null && line.IndexOf("Copyright") != -1)
+					{
+						Years y = null;
+						foreach (KeyValuePair kv in aliases)
+						{
+							if (line.IndexOf(kv.Key) != -1)
+							{
+								y = copyrights[kv.Value];
+								break;
+							}
+						}
+						if (y == null)
+						{
+							if (nextline == null)
+							{
+								nextline = rdr.ReadLine();
+								if (nextline.IndexOf("Copyright") == -1)
+								{
+									line += nextline;
+									continue;
+								}
+							}
+							if (filePath.Contains("/jaxws/src/share/jaxws_classes/com/sun/xml/internal/rngom/")
+								&& (line.Contains("* Copyright (C) 2004-2011 *") || line.Contains("* Copyright (C) 2004-2012 *")))
+							{
+								// HACK ignore bogus copyright line
+							}
+							else
+							{
+								Error(filePath + ":" + Environment.NewLine + line);
+							}
+						}
+						else
+						{
+							foreach (Match m in Regex.Matches(line, "[0-9][0-9][0-9][0-9]"))
+							{
+								int v = Int32.Parse(m.Value);
+								y.min = Math.Min(y.min, v);
+								y.max = Math.Max(y.max, v);
+							}
+						}
+						line = nextline;
+						nextline = null;
+					}
+				}
+			}
+			if (gpl && !classpathException)
+			{
+				Error("GPL without Classpath exception: {0}", filePath);
+			}
+		}
+
+		static void Error(string message, params object[] args)
+		{
+			errorCount++;
+			Console.Error.WriteLine(message, args);
+		}
+	}
+}
diff --git a/tools/depcheck.cs b/tools/depcheck.cs
new file mode 100644
index 0000000..ee86e43
--- /dev/null
+++ b/tools/depcheck.cs
@@ -0,0 +1,90 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Reflection;
+
+class DependencyChecker
+{
+	static int Main(string[] args)
+	{
+		Dictionary> deps = new Dictionary>();
+		string dep = null;
+		foreach (string line in File.ReadAllLines(args[1]))
+		{
+			if (line.Trim().Length == 0 || line.StartsWith("#"))
+			{
+				// comment
+			}
+			else if (line.StartsWith("->"))
+			{
+				deps[dep].Add(line.Substring(2));
+			}
+			else
+			{
+				dep = line;
+				deps.Add(dep, new List());
+			}
+		}
+		List whitelist = new List(new string[] { "mscorlib", "System", "IKVM.Runtime", "IKVM.OpenJDK.Core" });
+		bool fail = false;
+		foreach (string line in File.ReadAllLines(args[0]))
+		{
+			if (line.Contains("-out:"))
+			{
+				string file = line.Trim().Substring(5);
+				Assembly asm = Assembly.ReflectionOnlyLoadFrom(Path.Combine(Path.GetDirectoryName(args[0]), file));
+				if (!deps.ContainsKey(asm.GetName().Name))
+				{
+					fail = true;
+					Console.WriteLine(asm.GetName().Name);
+					foreach (AssemblyName asmdep in asm.GetReferencedAssemblies())
+					{
+						if (!whitelist.Contains(asmdep.Name))
+						{
+							Console.WriteLine("->{0}", asmdep.Name);
+						}
+					}
+				}
+				else
+				{
+					foreach (AssemblyName asmdep in asm.GetReferencedAssemblies())
+					{
+						if (!whitelist.Contains(asmdep.Name))
+						{
+							if (!deps[asm.GetName().Name].Contains(asmdep.Name))
+							{
+								fail = true;
+								Console.WriteLine("Error: Assembly {0} has an undeclared dependency on {1}", asm.GetName().Name, asmdep.Name);
+							}
+						}
+					}
+				}
+			}
+		}
+		return fail ? 1 : 0;
+	}
+}
diff --git a/tools/implib.cs b/tools/implib.cs
new file mode 100644
index 0000000..7784cd5
--- /dev/null
+++ b/tools/implib.cs
@@ -0,0 +1,230 @@
+/*
+  Copyright (C) 2013 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text.RegularExpressions;
+using IKVM.Reflection;
+using IKVM.Reflection.Emit;
+using Type = IKVM.Reflection.Type;
+
+static class ImpLib
+{
+    static readonly Regex definition = new Regex(@"^\s*(.+)=\[([^\]]+)\](.+)::([^\s]+)\s+@(\d+)$");
+    static readonly Universe universe = new Universe();
+
+    static int Main(string[] args)
+    {
+        Options options = new Options();
+        List exports = new List();
+        if (!ParseArgs(args, options) || !ParseDefFile(options.deffile, exports))
+        {
+            return 1;
+        }
+        AssemblyName name = new AssemblyName(Path.GetFileNameWithoutExtension(options.outputFile));
+        name.Version = options.version;
+        name.KeyPair = options.key;
+        AssemblyBuilder ab = universe.DefineDynamicAssembly(name, AssemblyBuilderAccess.Save);
+        ModuleBuilder modb = ab.DefineDynamicModule(name.Name, options.outputFile);
+        foreach (Export exp in exports)
+        {
+            ExportMethod(modb, exp);
+        }
+        modb.CreateGlobalFunctions();
+        if (options.win32res != null)
+        {
+            ab.DefineUnmanagedResource(options.win32res);
+        }
+        else
+        {
+            if (options.description != null)
+            {
+                ab.SetCustomAttribute(new CustomAttributeBuilder(universe.Import(typeof(System.Reflection.AssemblyTitleAttribute)).GetConstructor(new Type[] { universe.Import(typeof(string)) }), new object[] { options.description }));
+            }
+            ab.DefineVersionInfoResource(options.product, options.version.ToString(), options.company, options.copyright, null);
+        }
+        ab.Save(options.outputFile, options.peKind, options.machine);
+        return 0;
+    }
+
+    static bool ParseArgs(string[] args, Options options)
+    {
+        options.peKind = PortableExecutableKinds.Required32Bit;
+        options.machine = ImageFileMachine.I386;
+        foreach (string arg in args)
+        {
+            if (arg.StartsWith("-r:", StringComparison.Ordinal) || arg.StartsWith("-reference:", StringComparison.Ordinal))
+            {
+                universe.LoadFile(arg.Substring(arg.IndexOf(':') + 1));
+            }
+            else if (arg.StartsWith("-out:", StringComparison.Ordinal))
+            {
+                options.outputFile = arg.Substring(5);
+            }
+            else if (arg == "-platform:x86")
+            {
+                options.peKind = PortableExecutableKinds.Required32Bit;
+                options.machine = ImageFileMachine.I386;
+            }
+            else if (arg == "-platform:x64")
+            {
+                options.peKind = PortableExecutableKinds.PE32Plus;
+                options.machine = ImageFileMachine.AMD64;
+            }
+            else if (arg == "-platform:arm")
+            {
+                options.peKind = PortableExecutableKinds.Unmanaged32Bit;
+                options.machine = ImageFileMachine.ARM;
+            }
+            else if (arg.StartsWith("-win32res:", StringComparison.Ordinal))
+            {
+                options.win32res = arg.Substring(10);
+            }
+            else if (arg.StartsWith("-key:", StringComparison.Ordinal))
+            {
+                options.key = new StrongNameKeyPair(arg.Substring(5));
+            }
+            else if (arg.StartsWith("-version:", StringComparison.Ordinal))
+            {
+                options.version = new Version(arg.Substring(9));
+            }
+            else if (arg.StartsWith("-product:", StringComparison.Ordinal))
+            {
+                options.product = arg.Substring(9);
+            }
+            else if (arg.StartsWith("-company:", StringComparison.Ordinal))
+            {
+                options.company = arg.Substring(9);
+            }
+            else if (arg.StartsWith("-copyright:", StringComparison.Ordinal))
+            {
+                options.copyright = arg.Substring(11);
+            }
+            else if (arg.StartsWith("-description:", StringComparison.Ordinal))
+            {
+                options.description = arg.Substring(13);
+            }
+            else if (options.deffile == null)
+            {
+                options.deffile = arg;
+            }
+            else
+            {
+                Console.WriteLine("Unknown option: {0}", arg);
+                return false;
+            }
+        }
+
+        if (options.deffile == null || options.outputFile == null)
+        {
+            Console.WriteLine("Usage: implib  -out: -r: [-platform:] [-win32res:] [-key:] [-version:]");
+            return false;
+        }
+
+        return true;
+    }
+
+    static bool ParseDefFile(string fileName, List exports)
+    {
+        using (StreamReader sr = new StreamReader(fileName))
+        {
+            string line;
+            while ((line = sr.ReadLine()) != null)
+            {
+                Match m = definition.Match(line);
+                if (m.Groups.Count == 6)
+                {
+                    Export exp;
+                    exp.name = m.Groups[1].Value;
+                    exp.ordinal = Int32.Parse(m.Groups[5].Value);
+                    exp.method = GetMethod(m.Groups[2].Value, m.Groups[3].Value, m.Groups[4].Value);
+                    if (exp.method == null)
+                    {
+                        Console.WriteLine("Unable to find {0}", exp.name);
+                        return false;
+                    }
+                    exports.Add(exp);
+                }
+            }
+        }
+        return true;
+    }
+
+    static MethodInfo GetMethod(string assembly, string typeName, string method)
+    {
+        foreach (Assembly asm in universe.GetAssemblies())
+        {
+            if (asm.GetName().Name.Equals(assembly, StringComparison.OrdinalIgnoreCase))
+            {
+                Type type = asm.GetType(typeName);
+                if (type != null)
+                {
+                    return type.GetMethod(method, BindingFlags.Public | BindingFlags.Static);
+                }
+            }
+        }
+        return null;
+    }
+
+    static void ExportMethod(ModuleBuilder modb, Export exp)
+    {
+        ParameterInfo[] parameters = exp.method.GetParameters();
+        Type[] types = new Type[parameters.Length];
+        for (int i = 0; i < types.Length; i++)
+        {
+            types[i] = parameters[i].ParameterType;
+        }
+        MethodBuilder mb = modb.DefineGlobalMethod(exp.name, MethodAttributes.Public | MethodAttributes.Static, exp.method.ReturnType, types);
+        ILGenerator ilgen = mb.GetILGenerator();
+        for (int i = 0; i < types.Length; i++)
+        {
+            ilgen.Emit(OpCodes.Ldarg_S, (byte)i);
+        }
+        ilgen.Emit(OpCodes.Call, exp.method);
+        ilgen.Emit(OpCodes.Ret);
+        mb.__AddUnmanagedExport(mb.Name, exp.ordinal);
+    }
+
+    sealed class Options
+    {
+        internal PortableExecutableKinds peKind;
+        internal ImageFileMachine machine;
+        internal string deffile;
+        internal string outputFile;
+        internal string win32res;
+        internal StrongNameKeyPair key;
+        internal Version version;
+        internal string product;
+        internal string company;
+        internal string copyright;
+        internal string description;
+    }
+
+    struct Export
+    {
+        internal string name;
+        internal int ordinal;
+        internal MethodInfo method;
+    }
+}
diff --git a/tools/pubkey.cs b/tools/pubkey.cs
new file mode 100644
index 0000000..2129d8b
--- /dev/null
+++ b/tools/pubkey.cs
@@ -0,0 +1,44 @@
+/*
+  Copyright (C) 2008 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+
+using System;
+using System.IO;
+using System.Text;
+using System.Reflection;
+
+class PublicKey
+{
+    static void Main(string[] args)
+    {
+	StringBuilder sb = new StringBuilder();
+	foreach (byte b in Assembly.GetExecutingAssembly().GetName().GetPublicKey())
+	{
+	    sb.AppendFormat("{0:X2}", b);
+	}
+	using (StreamWriter sw = new StreamWriter("pubkey.txt"))
+	{
+	    sw.Write(sb);
+	}
+    }
+}
diff --git a/tools/pubkey.txt b/tools/pubkey.txt
new file mode 100644
index 0000000..4c8b32a
--- /dev/null
+++ b/tools/pubkey.txt
@@ -0,0 +1 @@
+0024000004800000940000000602000000240000525341310004000001000100DD6B140E5209CAE3D1C710030021EF589D0F00D05ACA8771101A7E99E10EE063E66040DF96E6F842F717BFC5B62D2EC2B62CEB0282E4649790DACB424DB29B68ADC7EAEAB0356FCE04702379F84400B8427EDBB33DAB8720B9F16A42E2CDB87F885EF413DBC4229F2BD157C9B8DC2CD14866DEC5F31C764BFB9394CC3C60E6C0
\ No newline at end of file
diff --git a/tools/tools.build b/tools/tools.build
new file mode 100644
index 0000000..619322e
--- /dev/null
+++ b/tools/tools.build
@@ -0,0 +1,64 @@
+
+
+
+    
+        
+            
+                
+            
+        
+
+        
+            
+                
+            
+        
+
+        
+            
+        
+        
+        
+            
+                
+                
+            
+        
+        
+
+        
+            
+                
+            
+        
+        
+
+        
+            
+                
+            
+        
+    
+
diff --git a/tools/updbaseaddresses.cs b/tools/updbaseaddresses.cs
new file mode 100644
index 0000000..d94c5f1
--- /dev/null
+++ b/tools/updbaseaddresses.cs
@@ -0,0 +1,69 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+/*
+ * This tool updates the -baseaddress options in response.txt based on the current file sizes.
+ *
+ * Usage: updbaseaddresses \ikvm\openjdk\response.txt
+ */
+
+class UpdateBaseAddresses
+{
+	static void Main(string[] args)
+	{
+		string[] input = File.ReadAllLines(args[0]);
+		List output = new List();
+		int baseAddress = 0x56000000;
+		string dir = Path.GetDirectoryName(args[0]);
+		bool dirty = false;
+		for (int i = 0; i < input.Length; i++)
+		{
+			string line = input[i];
+			if (!line.Contains("-baseaddress:"))
+			{
+				output.Add(line);
+			}
+			if (line.Trim().StartsWith("-out:"))
+			{
+				string str = String.Format("    -baseaddress:0x{0:X}", baseAddress);
+				output.Add(str);
+				if (str != input[i + 1])
+				{
+					dirty = true;
+				}
+				string file = line.Trim().Substring(5);
+				FileInfo fileInfo = new FileInfo(Path.Combine(dir, file));
+				baseAddress += 3 * (((int)fileInfo.Length + 65535) / 65536) * 65536;
+			}
+		}
+		if (dirty)
+		{
+			File.WriteAllLines(args[0], output.ToArray());
+		}
+	}
+}
diff --git a/tools/writeappconfig.cs b/tools/writeappconfig.cs
new file mode 100644
index 0000000..29378d3
--- /dev/null
+++ b/tools/writeappconfig.cs
@@ -0,0 +1,48 @@
+/*
+  Copyright (C) 2012 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+
+using System;
+using System.IO;
+
+class WriteAppConfig
+{
+	const string AppConfig =
+@"
+
+    
+        
+        
+    
+";
+
+	static void Main()
+	{
+		if (Environment.Version.Major == 2)
+		{
+			File.WriteAllText("../bin/ikvm.exe.config", AppConfig);
+			File.WriteAllText("../bin/ikvmc.exe.config", AppConfig);
+			File.WriteAllText("../bin/ikvmstub.exe.config", AppConfig);
+		}
+	}
+}